The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netncp/ncp_conn.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1999, Boris Popov
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *    This product includes software developed by Boris Popov.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * Connection tables
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/6.0/sys/netncp/ncp_conn.c 139823 2005-01-07 01:45:51Z imp $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/malloc.h>
   42 #include <sys/proc.h>
   43 #include <sys/lock.h>
   44 #include <sys/sysctl.h>
   45 
   46 #include <netncp/ncp.h>
   47 #include <netncp/nwerror.h>
   48 #include <netncp/ncp_subr.h>
   49 #include <netncp/ncp_conn.h>
   50 #include <netncp/ncp_sock.h>
   51 #include <netncp/ncp_ncp.h>
   52 
   53 SLIST_HEAD(ncp_handle_head,ncp_handle);
   54 
   55 int ncp_burst_enabled = 1;
   56 
   57 struct ncp_conn_head conn_list={NULL};
   58 static int ncp_conn_cnt = 0;
   59 static int ncp_next_ref = 1;
   60 static struct lock listlock;
   61 
   62 struct ncp_handle_head lhlist={NULL};
   63 static int ncp_next_handle = 1;
   64 static struct lock lhlock;
   65 
   66 static int ncp_sysctl_connstat(SYSCTL_HANDLER_ARGS);
   67 static int ncp_conn_lock_any(struct ncp_conn *conn, struct thread *td,
   68     struct ucred *cred);
   69 
   70 SYSCTL_DECL(_net_ncp);
   71 SYSCTL_INT (_net_ncp, OID_AUTO, burst_enabled, CTLFLAG_RD, &ncp_burst_enabled, 0, "");
   72 SYSCTL_INT (_net_ncp, OID_AUTO, conn_cnt, CTLFLAG_RD, &ncp_conn_cnt, 0, "");
   73 SYSCTL_PROC(_net_ncp, OID_AUTO, conn_stat, CTLFLAG_RD|CTLTYPE_OPAQUE,
   74             NULL, 0, ncp_sysctl_connstat, "S,connstat", "Connections list");
   75 
   76 MALLOC_DEFINE(M_NCPDATA, "NCP data", "NCP private data");
   77 
   78 int
   79 ncp_conn_init(void)
   80 {
   81         lockinit(&listlock, PSOCK, "ncpll", 0, 0);
   82         lockinit(&lhlock, PSOCK, "ncplh", 0, 0);
   83         return 0;
   84 }
   85 
   86 int
   87 ncp_conn_destroy(void)
   88 {
   89         if (ncp_conn_cnt) {
   90                 NCPERROR("There are %d connections active\n", ncp_conn_cnt);
   91                 return EBUSY;
   92         }
   93         lockdestroy(&listlock);
   94         lockdestroy(&lhlock);
   95         return 0;
   96 }
   97 
   98 int
   99 ncp_conn_locklist(int flags, struct thread *td)
  100 {
  101         return lockmgr(&listlock, flags | LK_CANRECURSE, 0, td);
  102 }
  103 
  104 void
  105 ncp_conn_unlocklist(struct thread *td)
  106 {
  107         lockmgr(&listlock, LK_RELEASE, 0, td);
  108 }
  109 
  110 int
  111 ncp_conn_access(struct ncp_conn *conn, struct ucred *cred, mode_t mode)
  112 {
  113         int error;
  114 
  115         if (cred == NOCRED || ncp_suser(cred) == 0 ||
  116             cred->cr_uid == conn->nc_owner->cr_uid)
  117                 return 0;
  118         mode >>= 3;
  119         if (!groupmember(conn->nc_group, cred))
  120                 mode >>= 3;
  121         error = (conn->li.access_mode & mode) == mode ? 0 : EACCES;
  122         return error;
  123 }
  124 
  125 int
  126 ncp_conn_lock_any(struct ncp_conn *conn, struct thread *td, struct ucred *cred)
  127 {
  128         int error;
  129 
  130         if (conn->nc_id == 0) return EACCES;
  131         error = lockmgr(&conn->nc_lock, LK_EXCLUSIVE | LK_CANRECURSE, 0, td);
  132         if (error == ERESTART)
  133                 return EINTR;
  134         error = ncp_chkintr(conn, td);
  135         if (error) {
  136                 lockmgr(&conn->nc_lock, LK_RELEASE, 0, td);
  137                 return error;
  138         }
  139 
  140         if (conn->nc_id == 0) {
  141                 lockmgr(&conn->nc_lock, LK_RELEASE, 0, td);
  142                 return EACCES;
  143         }
  144         conn->td = td;          /* who currently operates */
  145         conn->ucred = cred;
  146         return 0;
  147 }
  148 
  149 int
  150 ncp_conn_lock(struct ncp_conn *conn, struct thread *td, struct ucred *cred, int mode)
  151 {
  152         int error;
  153 
  154         error = ncp_conn_access(conn, cred, mode);
  155         if (error) return error;
  156         return ncp_conn_lock_any(conn, td, cred);
  157 }
  158 
  159 /*
  160  * Lock conn but unlock connlist
  161  */
  162 static int
  163 ncp_conn_lock2(struct ncp_conn *conn, struct thread *td, struct ucred *cred, int mode)
  164 {
  165         int error;
  166 
  167         error = ncp_conn_access(conn, cred, mode);
  168         if (error) {
  169                 ncp_conn_unlocklist(td);
  170                 return error;
  171         }
  172         conn->nc_lwant++;
  173         ncp_conn_unlocklist(td);
  174         error = ncp_conn_lock_any(conn, td, cred);
  175         conn->nc_lwant--;
  176         if (conn->nc_lwant == 0) {
  177                 wakeup(&conn->nc_lwant);
  178         }
  179         return error;
  180 }
  181 
  182 void
  183 ncp_conn_unlock(struct ncp_conn *conn, struct thread *td)
  184 {
  185         /*
  186          * note, that LK_RELASE will do wakeup() instead of wakeup_one().
  187          * this will do a little overhead
  188          */
  189         lockmgr(&conn->nc_lock, LK_RELEASE, 0, td);
  190 }
  191 
  192 int
  193 ncp_conn_assert_locked(struct ncp_conn *conn, const char *checker, struct thread *td)
  194 {
  195         if (conn->nc_lock.lk_flags & LK_HAVE_EXCL) return 0;
  196         printf("%s: connection isn't locked!\n", checker);
  197         return EIO;
  198 }
  199 
  200 void
  201 ncp_conn_invalidate(struct ncp_conn *ncp)
  202 {
  203         ncp->flags &= ~(NCPFL_ATTACHED | NCPFL_LOGGED | NCPFL_INVALID);
  204 }
  205 
  206 int
  207 ncp_conn_invalid(struct ncp_conn *ncp)
  208 {
  209         return ncp->flags & NCPFL_INVALID;
  210 }
  211 
  212 /*
  213  * create, fill with defaults and return in locked state
  214  */
  215 int
  216 ncp_conn_alloc(struct ncp_conn_args *cap, struct thread *td, struct ucred *cred,
  217         struct ncp_conn **conn)
  218 {
  219         struct ncp_conn *ncp;
  220         struct ucred *owner;
  221         int error, isroot;
  222 
  223         if (cap->saddr.sa_family != AF_INET && cap->saddr.sa_family != AF_IPX)
  224                 return EPROTONOSUPPORT;
  225         isroot = ncp_suser(cred) == 0;
  226         /*
  227          * Only root can change ownership
  228          */
  229         if (cap->owner != NCP_DEFAULT_OWNER && !isroot)
  230                 return EPERM;
  231         if (cap->group != NCP_DEFAULT_GROUP &&
  232             !groupmember(cap->group, cred) && !isroot)
  233                 return EPERM;
  234         if (cap->owner != NCP_DEFAULT_OWNER) {
  235                 owner = crget();
  236                 owner->cr_uid = cap->owner;
  237         } else
  238                 owner = crhold(cred);
  239         MALLOC(ncp, struct ncp_conn *, sizeof(struct ncp_conn), 
  240             M_NCPDATA, M_WAITOK | M_ZERO);
  241         error = 0;
  242         lockinit(&ncp->nc_lock, PZERO, "ncplck", 0, 0);
  243         ncp_conn_cnt++;
  244         ncp->nc_id = ncp_next_ref++;
  245         ncp->nc_owner = cred;
  246         ncp->seq = 0;
  247         ncp->connid = 0xFFFF;
  248         ncp->li = *cap;
  249         ncp->nc_group = (cap->group != NCP_DEFAULT_GROUP) ?
  250                 cap->group : cred->cr_groups[0];
  251 
  252         if (cap->retry_count == 0)
  253                 ncp->li.retry_count = NCP_RETRY_COUNT;
  254         if (cap->timeout == 0)
  255                 ncp->li.timeout = NCP_RETRY_TIMEOUT;
  256         ncp_conn_lock_any(ncp, td, ncp->nc_owner);
  257         *conn = ncp;
  258         ncp_conn_locklist(LK_EXCLUSIVE, td);
  259         SLIST_INSERT_HEAD(&conn_list,ncp,nc_next);
  260         ncp_conn_unlocklist(td);
  261         return (error);
  262 }
  263 
  264 /*
  265  * Remove the connection, on entry it must be locked
  266  */
  267 int
  268 ncp_conn_free(struct ncp_conn *ncp)
  269 {
  270         struct thread *td;
  271         int error;
  272 
  273         if (ncp == NULL) {
  274                 NCPFATAL("ncp == NULL\n");
  275                 return 0;
  276         }
  277         if (ncp->nc_id == 0) {
  278                 NCPERROR("nc_id == 0\n");
  279                 return EACCES;
  280         }
  281         td = ncp->td;
  282         error = ncp_conn_assert_locked(ncp, __func__, td);
  283         if (error)
  284                 return error;
  285         if (ncp->ref_cnt != 0 || (ncp->flags & NCPFL_PERMANENT))
  286                 return EBUSY;
  287         if (ncp_conn_access(ncp, ncp->ucred, NCPM_WRITE))
  288                 return EACCES;
  289 
  290         if (ncp->flags & NCPFL_ATTACHED)
  291                 ncp_ncp_disconnect(ncp);
  292         ncp_sock_disconnect(ncp);
  293 
  294         /*
  295          * Mark conn as dead and wait for other process
  296          */
  297         ncp->nc_id = 0;
  298         ncp_conn_unlock(ncp, td);
  299         /*
  300          * if signal is raised - how I do react ?
  301          */
  302         lockmgr(&ncp->nc_lock, LK_DRAIN, 0, td);
  303         lockdestroy(&ncp->nc_lock);
  304         while (ncp->nc_lwant) {
  305                 printf("lwant = %d\n", ncp->nc_lwant);
  306                 tsleep(&ncp->nc_lwant, PZERO,"ncpdr",2*hz);
  307         }
  308         ncp_conn_locklist(LK_EXCLUSIVE, td);
  309         SLIST_REMOVE(&conn_list, ncp, ncp_conn, nc_next);
  310         ncp_conn_cnt--;
  311         ncp_conn_unlocklist(td);
  312         if (ncp->li.user)
  313                 free(ncp->li.user, M_NCPDATA);
  314         if (ncp->li.password)
  315                 free(ncp->li.password, M_NCPDATA);
  316         crfree(ncp->nc_owner);
  317         FREE(ncp, M_NCPDATA);
  318         return (0);
  319 }
  320 
  321 int
  322 ncp_conn_reconnect(struct ncp_conn *ncp)
  323 {
  324         int error;
  325 
  326         /*
  327          * Close opened sockets if any
  328          */
  329         ncp_sock_disconnect(ncp);
  330         error = ncp_sock_connect(ncp);
  331         if (error)
  332                 return error;
  333         error = ncp_ncp_connect(ncp);
  334         if (error)
  335                 return error;
  336         error = ncp_renegotiate_connparam(ncp, NCP_DEFAULT_BUFSIZE, 0);
  337         if (error == NWE_SIGNATURE_LEVEL_CONFLICT) {
  338                 printf("Unable to negotiate requested security level\n");
  339                 error = EOPNOTSUPP;
  340         }
  341         if (error) {
  342                 ncp_ncp_disconnect(ncp);
  343                 return error;
  344         }
  345 #ifdef NCPBURST
  346         error = ncp_burst_connect(ncp);
  347         if (error) {
  348                 ncp_ncp_disconnect(ncp);
  349                 return error;
  350         }
  351 #endif
  352         return 0;
  353 }
  354 
  355 int
  356 ncp_conn_login(struct ncp_conn *conn, struct thread *td, struct ucred *cred)
  357 {
  358         struct ncp_bindery_object user;
  359         u_char ncp_key[8];
  360         int error;
  361 
  362         error = ncp_get_encryption_key(conn, ncp_key);
  363         if (error) {
  364                 printf("%s: Warning: use unencrypted login\n", __func__);
  365                 error = ncp_login_unencrypted(conn, conn->li.objtype,
  366                     conn->li.user, conn->li.password, td, cred);
  367         } else {
  368                 error = ncp_get_bindery_object_id(conn, conn->li.objtype,
  369                     conn->li.user, &user, td, cred);
  370                 if (error)
  371                         return error;
  372                 error = ncp_login_encrypted(conn, &user, ncp_key,
  373                     conn->li.password, td, cred);
  374         }
  375         if (!error)
  376                 conn->flags |= NCPFL_LOGGED | NCPFL_WASLOGGED;
  377         return error;
  378 }
  379 
  380 /*
  381  * Lookup connection by handle, return a locked conn descriptor
  382  */
  383 int
  384 ncp_conn_getbyref(int ref, struct thread *td, struct ucred *cred, int mode,
  385                   struct ncp_conn **connpp)
  386 {
  387         struct ncp_conn *ncp;
  388         int error = 0;
  389 
  390         ncp_conn_locklist(LK_SHARED, td);
  391         SLIST_FOREACH(ncp, &conn_list, nc_next)
  392                 if (ncp->nc_id == ref) break;
  393         if (ncp == NULL) {
  394                 ncp_conn_unlocklist(td);
  395                 return(EBADF);
  396         }
  397         error = ncp_conn_lock2(ncp, td, cred, mode);
  398         if (!error)
  399                 *connpp = ncp;
  400         return (error);
  401 }
  402 /*
  403  * find attached, but not logged in connection to specified server
  404  */
  405 int
  406 ncp_conn_getattached(struct ncp_conn_args *li, struct thread *td,
  407                      struct ucred *cred, int mode, struct ncp_conn **connpp)
  408 {
  409         struct ncp_conn *ncp, *ncp2 = NULL;
  410         int error = 0;
  411 
  412         ncp_conn_locklist(LK_SHARED, td);
  413         SLIST_FOREACH(ncp, &conn_list, nc_next) {
  414                 if ((ncp->flags & NCPFL_LOGGED) != 0 ||
  415                     strcmp(ncp->li.server,li->server) != 0 ||
  416                     ncp->li.saddr.sa_len != li->saddr.sa_len ||
  417                     bcmp(&ncp->li.saddr,&ncp->li.saddr,li->saddr.sa_len) != 0)
  418                         continue;
  419                 if (ncp_suser(cred) == 0 ||
  420                     cred->cr_uid == ncp->nc_owner->cr_uid)
  421                         break;
  422                 error = ncp_conn_access(ncp,cred,mode);
  423                 if (!error && ncp2 == NULL)
  424                         ncp2 = ncp;
  425         }
  426         if (ncp == NULL) ncp = ncp2;
  427         if (ncp == NULL) {
  428                 ncp_conn_unlocklist(td);
  429                 return(EBADF);
  430         }
  431         error = ncp_conn_lock2(ncp, td, cred, mode);
  432         if (!error)
  433                 *connpp=ncp;
  434         return (error);
  435 }
  436 
  437 /*
  438  * Lookup connection by server/user pair, return a locked conn descriptor.
  439  * if li is NULL or server/user pair incomplete, try to select best connection
  440  * based on owner.
  441  * Connection selected in next order:
  442  * 1. Try to search conn with ucred owner, if li is NULL also find a primary
  443  * 2. If 1. fails try to get first suitable shared connection
  444  * 3. If 2. fails then nothing can help to poor ucred owner
  445  */
  446 
  447 int
  448 ncp_conn_getbyli(struct ncp_conn_args *li, struct thread *td,
  449                  struct ucred *cred, int mode, struct ncp_conn **connpp)
  450 {
  451         struct ncp_conn *ncp, *ncp2 = NULL;
  452         int error = 0, partial, haveserv;
  453 
  454         partial = (li == NULL || li->server[0] == 0 || li->user == NULL);
  455         haveserv = (li && li->server[0]);
  456         ncp_conn_locklist(LK_SHARED, td);
  457         SLIST_FOREACH(ncp, &conn_list, nc_next) {
  458                 if (partial) {
  459                         if (cred->cr_uid == ncp->nc_owner->cr_uid) {
  460                                 if (haveserv) {
  461                                         if (strcmp(ncp->li.server,li->server) == 0)
  462                                                 break;
  463                                 } else {
  464                                         if (ncp->flags & NCPFL_PRIMARY)
  465                                                 break;
  466                                         ncp2 = ncp;
  467                                 }
  468                                 continue;
  469                         }
  470                 } else {
  471                         if (strcmp(ncp->li.server,li->server) != 0 || 
  472                             ncp->li.user == NULL ||
  473                             strcmp(ncp->li.user,li->user) != 0)
  474                                 continue;
  475                         if (cred->cr_uid == ncp->nc_owner->cr_uid)
  476                                 break;
  477                         if (ncp_suser(cred) == 0)
  478                                 ncp2 = ncp;
  479                 }
  480                 error = ncp_conn_access(ncp,cred,mode);
  481                 if (!error && ncp2 == NULL)
  482                         ncp2 = ncp;
  483         }
  484         if (ncp == NULL) ncp = ncp2;
  485         if (ncp == NULL) {
  486                 ncp_conn_unlocklist(td);
  487                 return(EBADF);
  488         }
  489         error = ncp_conn_lock2(ncp, td, cred,mode);
  490         if (!error)
  491                 *connpp=ncp;
  492         return (error);
  493 }
  494 
  495 /*
  496  * Set primary connection flag, since it have sence only for an owner,
  497  * only owner can modify this flag.
  498  * connection expected to be locked.
  499  */
  500 int
  501 ncp_conn_setprimary(struct ncp_conn *conn, int on)
  502 {
  503         struct ncp_conn *ncp=NULL;
  504 
  505         if (conn->ucred->cr_uid != conn->nc_owner->cr_uid)
  506                 return EACCES;
  507         ncp_conn_locklist(LK_SHARED, conn->td);
  508         SLIST_FOREACH(ncp, &conn_list, nc_next) {
  509                 if (conn->ucred->cr_uid == ncp->nc_owner->cr_uid)
  510                         ncp->flags &= ~NCPFL_PRIMARY;
  511         }
  512         ncp_conn_unlocklist(conn->td);
  513         if (on)
  514                 conn->flags |= NCPFL_PRIMARY;
  515         return 0;
  516 }
  517 /*
  518  * Lease conn to given proc, returning unique handle
  519  * problem: how locks should be applied ?
  520  */
  521 int
  522 ncp_conn_gethandle(struct ncp_conn *conn, struct thread *td, struct ncp_handle **handle)
  523 {
  524         struct ncp_handle *refp;
  525 
  526         lockmgr(&lhlock, LK_EXCLUSIVE, 0, td);
  527         SLIST_FOREACH(refp, &lhlist, nh_next)
  528                 if (refp->nh_conn == conn && td == refp->nh_td) break;
  529         if (refp) {
  530                 conn->ref_cnt++;
  531                 refp->nh_ref++;
  532                 *handle = refp;
  533                 lockmgr(&lhlock, LK_RELEASE, 0, td);
  534                 return 0;
  535         }
  536         MALLOC(refp,struct ncp_handle *,sizeof(struct ncp_handle),M_NCPDATA,
  537             M_WAITOK | M_ZERO);
  538         SLIST_INSERT_HEAD(&lhlist,refp,nh_next);
  539         refp->nh_ref++;
  540         refp->nh_td = td;
  541         refp->nh_conn = conn;
  542         refp->nh_id = ncp_next_handle++;
  543         *handle = refp;
  544         conn->ref_cnt++;
  545         lockmgr(&lhlock, LK_RELEASE, 0, td);
  546         return 0;
  547 }
  548 /*
  549  * release reference, if force - ignore refcount
  550  */
  551 int
  552 ncp_conn_puthandle(struct ncp_handle *handle, struct thread *td, int force)
  553 {
  554         struct ncp_handle *refp = handle;
  555 
  556         lockmgr(&lhlock, LK_EXCLUSIVE, 0, td);
  557         refp->nh_ref--;
  558         refp->nh_conn->ref_cnt--;
  559         if (force) {
  560                 refp->nh_conn->ref_cnt -= refp->nh_ref;
  561                 refp->nh_ref = 0;
  562         }
  563         if (refp->nh_ref == 0) {
  564                 SLIST_REMOVE(&lhlist, refp, ncp_handle, nh_next);
  565                 FREE(refp, M_NCPDATA);
  566         }
  567         lockmgr(&lhlock, LK_RELEASE, 0, td);
  568         return 0;
  569 }
  570 /*
  571  * find a connHandle
  572  */
  573 int
  574 ncp_conn_findhandle(int connHandle, struct thread *td, struct ncp_handle **handle) {
  575         struct ncp_handle *refp;
  576 
  577         lockmgr(&lhlock, LK_SHARED, 0, td);
  578         SLIST_FOREACH(refp, &lhlist, nh_next)
  579                 if (refp->nh_td == td && refp->nh_id == connHandle) break;
  580         lockmgr(&lhlock, LK_RELEASE, 0, td);
  581         if (refp == NULL) {
  582                 return EBADF;
  583         }
  584         *handle = refp;
  585         return 0;
  586 }
  587 /*
  588  * Clear handles associated with specified process
  589  */
  590 int
  591 ncp_conn_putprochandles(struct thread *td)
  592 {
  593         struct ncp_handle *hp, *nhp;
  594         int haveone = 0;
  595 
  596         lockmgr(&lhlock, LK_EXCLUSIVE, 0, td);
  597         for (hp = SLIST_FIRST(&lhlist); hp; hp = nhp) {
  598                 nhp = SLIST_NEXT(hp, nh_next);
  599                 if (hp->nh_td != td) continue;
  600                 haveone = 1;
  601                 hp->nh_conn->ref_cnt -= hp->nh_ref;
  602                 SLIST_REMOVE(&lhlist, hp, ncp_handle, nh_next);
  603                 FREE(hp, M_NCPDATA);
  604         }
  605         lockmgr(&lhlock, LK_RELEASE, 0, td);
  606         return haveone;
  607 }
  608 /*
  609  * remove references in all possible connections,
  610  * XXX - possible problem is a locked list.
  611  */
  612 /*void
  613 ncp_conn_list_rm_ref(pid_t pid) {
  614         struct ncp_conn *ncp;
  615 
  616         ncp_conn_locklist(LK_SHARED, NULL);
  617         SLIST_FOREACH(ncp, &conn_list, nc_next) {
  618                 ncp_conn_rm_ref(ncp,pid,1);
  619         }
  620         ncp_conn_unlocklist(NULL);
  621         return;
  622 }
  623 */
  624 int
  625 ncp_conn_getinfo(struct ncp_conn *ncp, struct ncp_conn_stat *ncs) {
  626         bzero(ncs,sizeof(*ncs));
  627         ncs->li = ncp->li;
  628         ncs->li.user = ncs->user;
  629         if (ncp->li.user)
  630                 strcpy(ncs->user, ncp->li.user);
  631         ncs->li.password = NULL;
  632         ncs->connRef = ncp->nc_id;
  633         ncs->ref_cnt = ncp->ref_cnt;
  634         ncs->connid = ncp->connid;
  635         ncs->owner = ncp->nc_owner->cr_uid;
  636         ncs->group = ncp->nc_group;
  637         ncs->flags = ncp->flags;
  638         ncs->buffer_size = ncp->buffer_size;
  639         return 0;
  640 }
  641 
  642 static int
  643 ncp_sysctl_connstat(SYSCTL_HANDLER_ARGS)
  644 {
  645         int error;
  646         struct ncp_conn_stat ncs;
  647         struct ncp_conn *ncp;
  648 /*      struct ucred *cred = req->td->td_ucred;*/
  649 
  650         error = sysctl_wire_old_buffer(req, 0);
  651         if (error != 0)
  652                 return (error);
  653         ncp_conn_locklist(LK_SHARED, req->td);
  654         error = SYSCTL_OUT(req, &ncp_conn_cnt, sizeof(ncp_conn_cnt));
  655         SLIST_FOREACH(ncp, &conn_list, nc_next) {
  656                 if (error) break;
  657                 /* I can't do conn_lock while list is locked */
  658                 ncp->nc_lwant++;
  659                 if (!error) {
  660                         ncp_conn_getinfo(ncp, &ncs);
  661                 } else {
  662                         bzero(&ncs,sizeof(ncs));
  663                         ncs.connRef = ncp->nc_id;
  664                         strcpy(ncs.li.server,"***");
  665                 }
  666                 ncp->nc_lwant--;
  667                 error = SYSCTL_OUT(req, &ncs, sizeof(ncs));
  668         }
  669         ncp_conn_unlocklist(req->td);
  670         return(error);
  671 }

Cache object: 4acb78644f20b1a084f9c30e786b06c8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.