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

Cache object: 7697bef4df169739339f6c259242e7e1


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