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

Cache object: 52e92a2cc10e3f52c19c34fe925c3a53


[ 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.