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

Cache object: 0ee7fb218f744ebb80750a8bd6a815cf


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