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_ncp.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  * $FreeBSD$
   33  *
   34  * Core of NCP protocol
   35  */
   36 #include "opt_inet.h"
   37 #include "opt_ipx.h"
   38 
   39 #include <sys/param.h>
   40 #include <sys/errno.h>
   41 #include <sys/systm.h>
   42 #include <sys/proc.h>
   43 #include <sys/poll.h>
   44 #include <sys/signalvar.h>
   45 #include <sys/mbuf.h>
   46 
   47 #ifdef IPX
   48 #include <netipx/ipx.h>
   49 #include <netipx/ipx_var.h>
   50 #endif
   51 
   52 #include <netncp/ncp.h>
   53 #include <netncp/ncp_conn.h>
   54 #include <netncp/ncp_sock.h>
   55 #include <netncp/ncp_subr.h>
   56 #include <netncp/ncp_ncp.h>
   57 #include <netncp/ncp_rq.h>
   58 #include <netncp/nwerror.h>
   59 
   60 static int ncp_do_request(struct ncp_conn *,struct ncp_rq *rqp);
   61 static int ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target);
   62 static int ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, int in_options);
   63 static void ncp_sign_packet(struct ncp_conn *conn, struct ncp_rq *rqp, int *size);
   64 
   65 
   66 #ifdef NCP_DATA_DEBUG
   67 static
   68 void m_dumpm(struct mbuf *m) {
   69         char *p;
   70         int len;
   71         printf("d=");
   72         while(m) {
   73                 p=mtod(m,char *);
   74                 len=m->m_len;
   75                 printf("(%d)",len);
   76                 while(len--){
   77                         printf("%02x ",((int)*(p++)) & 0xff);
   78                 }
   79                 m=m->m_next;
   80         };
   81         printf("\n");
   82 }
   83 #endif /* NCP_DATA_DEBUG */
   84 
   85 int
   86 ncp_chkintr(struct ncp_conn *conn, struct proc *p)
   87 {
   88         sigset_t tmpset;
   89 
   90         if (p == NULL)
   91                 return 0;
   92         tmpset = p->p_siglist;
   93         SIGSETNAND(tmpset, p->p_sigmask);
   94         SIGSETNAND(tmpset, p->p_sigignore);
   95         if (SIGNOTEMPTY(p->p_siglist) && NCP_SIGMASK(tmpset))
   96                 return EINTR;
   97         return 0;
   98 }
   99 
  100 /*
  101  * Process initial NCP handshake (attach)
  102  * NOTE: Since all functions below may change conn attributes, they
  103  * should be called with LOCKED connection, also they use procp & ucred
  104  */
  105 int
  106 ncp_ncp_connect(struct ncp_conn *conn) {
  107         int error;
  108         struct ncp_rphdr *rp;
  109         DECLARE_RQ;
  110         
  111         conn->flags &= ~(NCPFL_INVALID | NCPFL_SIGNACTIVE | NCPFL_SIGNWANTED);
  112         conn->seq = 0;
  113         checkbad(ncp_rq_head(rqp,NCP_ALLOC_SLOT,0,conn->procp,conn->ucred));
  114         error=ncp_do_request(conn,rqp);
  115         if (!error) {
  116                 rp = mtod(rqp->rp, struct ncp_rphdr*);
  117                 conn->connid = rp->conn_low + (rp->conn_high << 8);
  118         }
  119         ncp_rq_done(rqp);
  120         if (error) return error;
  121         conn->flags |= NCPFL_ATTACHED;
  122 
  123         error = ncp_renegotiate_connparam(conn, NCP_DEFAULT_BUFSIZE, 0);
  124         if (error == NWE_SIGNATURE_LEVEL_CONFLICT) {
  125                 printf("Unable to negotiate requested security level\n");
  126                 error = EOPNOTSUPP;
  127         }
  128         if (error) {
  129                 ncp_ncp_disconnect(conn);
  130                 return error;
  131         }
  132 #ifdef NCPBURST
  133         ncp_burst_connect(conn);
  134 #endif
  135 bad:
  136         return error;
  137 }
  138 
  139 int
  140 ncp_ncp_disconnect(struct ncp_conn *conn) {
  141         int error;
  142         struct ncp_rqhdr *ncprq;
  143         DECLARE_RQ;
  144 
  145         NCPSDEBUG("for connid=%d\n",conn->nc_id);
  146 #ifdef NCPBURST
  147         ncp_burst_disconnect(conn);
  148 #endif
  149         error=ncp_rq_head(rqp,NCP_FREE_SLOT,0,conn->procp,conn->ucred);
  150         ncprq = mtod(rqp->rq,struct ncp_rqhdr*);
  151         error=ncp_do_request(conn,rqp);
  152         ncp_rq_done(rqp);
  153         ncp_conn_invalidate(conn);
  154         ncp_sock_disconnect(conn);
  155         return 0;
  156 }
  157 /* 
  158  * Make a signature for the current packet and add it at the end of the
  159  * packet.
  160  */
  161 static void
  162 ncp_sign_packet(struct ncp_conn *conn, struct ncp_rq *rqp, int *size) {
  163         u_char data[64];
  164 
  165         bzero(data, sizeof(data));
  166         bcopy(conn->sign_root, data, 8);
  167         setdle(data, 8, *size);
  168         m_copydata(rqp->rq, sizeof(struct ncp_rqhdr)-1,
  169                 min((*size) - sizeof(struct ncp_rqhdr)+1, 52),data+12);
  170         ncp_sign(conn->sign_state, data, conn->sign_state);
  171         ncp_rq_mem(rqp, (void*)conn->sign_state, 8);
  172         (*size) += 8;
  173 }
  174 
  175 /*
  176  * Low level send rpc, here we do not attempt to restore any connection,
  177  * Connection expected to be locked
  178  */
  179 static int 
  180 ncp_do_request(struct ncp_conn *conn, struct ncp_rq *rqp) {
  181         int error=EIO,len, dosend, plen = 0, gotpacket, s;
  182         struct socket *so;
  183         struct proc *p = conn->procp;
  184         struct ncp_rqhdr *rq;
  185         struct ncp_rphdr *rp=NULL;
  186         struct timeval tv;
  187         struct mbuf *m, *mreply = NULL;
  188         
  189         conn->nc_rq = rqp;
  190         rqp->conn = conn;
  191         if (p == NULL)
  192                 p = curproc;    /* XXX maybe procpage ? */
  193         if (!ncp_conn_valid(conn)) {
  194                 printf("%s: conn not valid\n",__FUNCTION__);
  195                 return (error);
  196         }
  197         so = conn->ncp_so;
  198         if (!so) {
  199                 printf("%s: ncp_so is NULL !\n",__FUNCTION__);
  200                 ncp_conn_invalidate(conn);      /* wow ! how we do that ? */
  201                 return EBADF;
  202         }
  203         /*
  204          * Flush out replies on previous reqs
  205          */
  206         s = splnet();
  207         while (1/*so->so_rcv.sb_cc*/) {
  208                 if (ncp_poll(so,POLLIN) == 0) break;
  209                 if (ncp_sock_recv(so,&m,&len) != 0) break;
  210                 m_freem(m);
  211         }
  212         rq = mtod(rqp->rq,struct ncp_rqhdr *);
  213         rq->seq = conn->seq;
  214         m = rqp->rq;
  215         len = 0;
  216         while (m) {
  217                 len += m->m_len;
  218                 m = m->m_next;
  219         }
  220         rqp->rq->m_pkthdr.len = len;
  221         switch(rq->fn) {
  222             case 0x15: case 0x16: case 0x17: case 0x23:
  223                 m = rqp->rq;
  224                 *((u_int16_t*)(mtod(m,u_int8_t*)+sizeof(*rq))) = htons(len-2-sizeof(*rq));
  225                 break;
  226         }
  227         if (conn->flags & NCPFL_SIGNACTIVE) {
  228                 ncp_sign_packet(conn, rqp, &len);
  229                 rqp->rq->m_pkthdr.len = len;
  230         }
  231         rq->conn_low = conn->connid & 0xff;
  232         /* rq->task = p->p_pgrp->pg_id & 0xff; */ /*p->p_pid*/
  233         /* XXX: this is temporary fix till I find a better solution */
  234         rq->task = rq->conn_low;
  235         rq->conn_high = conn->connid >> 8;
  236         rqp->rexmit = conn->li.retry_count;
  237         for(dosend = 1;;) {
  238                 if (rqp->rexmit-- == 0) {
  239                         error = ETIMEDOUT;
  240                         break;
  241                 }
  242                 error = 0;
  243                 if (dosend) {
  244                         NCPSDEBUG("send:%04x f=%02x c=%d l=%d s=%d t=%d\n",rq->type, rq->fn, (rq->conn_high << 8) + rq->conn_low,
  245                                 rqp->rq->m_pkthdr.len, rq->seq, rq->task
  246                         );
  247                         error = ncp_sock_send(so, rqp->rq, rqp);
  248                         if (error) break;
  249                 }
  250                 tv.tv_sec = conn->li.timeout;
  251                 tv.tv_usec = 0;
  252                 error = ncp_sock_rselect(so, p, &tv, POLLIN);
  253                 if (error == EWOULDBLOCK )      /* timeout expired */
  254                         continue;
  255                 error = ncp_chkintr(conn, p);
  256                 if (error == EINTR)             /* we dont restart */
  257                         break;
  258                 if (error) break;
  259                 /*
  260                  * At this point it is possible to get more than one
  261                  * reply from server. In general, last reply should be for
  262                  * current request, but not always. So, we loop through
  263                  * all replies to find the right answer and flush others.
  264                  */
  265                 gotpacket = 0;  /* nothing good found */
  266                 dosend = 1;     /* resend rq if error */
  267                 for (;;) {
  268                         error = 0;
  269                         if (ncp_poll(so,POLLIN) == 0) break;
  270 /*                      if (so->so_rcv.sb_cc == 0) {
  271                                 break;
  272                         }*/
  273                         error = ncp_sock_recv(so,&m,&len);
  274                         if (error) break;               /* must be more checks !!! */
  275                         if (m->m_len < sizeof(*rp)) {
  276                                 m = m_pullup(m, sizeof(*rp));
  277                                 if (m == NULL) {
  278                                         printf("%s: reply too short\n",__FUNCTION__);
  279                                         continue;
  280                                 }
  281                         }
  282                         rp = mtod(m, struct ncp_rphdr*);
  283                         if (len == sizeof(*rp) && rp->type == NCP_POSITIVE_ACK) {
  284                                 NCPSDEBUG("got positive acknowledge\n");
  285                                 m_freem(m);
  286                                 rqp->rexmit = conn->li.retry_count;
  287                                 dosend = 0;     /* server just busy and will reply ASAP */
  288                                 continue;
  289                         }
  290                         NCPSDEBUG("recv:%04x c=%d l=%d s=%d t=%d cc=%02x cs=%02x\n",rp->type,
  291                             (rp->conn_high << 8) + rp->conn_low, len, rp->seq, rp->task,
  292                              rp->completion_code, rp->connection_state);
  293                         NCPDDEBUG(m);
  294                         if ( (rp->type == NCP_REPLY) && 
  295                             ((rq->type == NCP_ALLOC_SLOT) || 
  296                             ((rp->conn_low == rq->conn_low) &&
  297                              (rp->conn_high == rq->conn_high)
  298                             ))) {
  299                                 if (rq->seq > rp->seq || (rq->seq == 0 && rp->seq == 0xff)) {
  300                                         dosend = 1;
  301                                 }
  302                                 if (rp->seq == rq->seq) {
  303                                         if (gotpacket) {
  304                                                 m_freem(m);
  305                                         } else {
  306                                                 gotpacket = 1;
  307                                                 mreply = m;
  308                                                 plen = len;
  309                                         }
  310                                         continue;       /* look up other for other packets */
  311                                 }
  312                         }
  313                         m_freem(m);
  314                         NCPSDEBUG("reply mismatch\n");
  315                 } /* for receive */
  316                 if (error) break;
  317                 if (gotpacket) break;
  318                 /* try to resend, or just wait */
  319         }
  320         splx(s);
  321         conn->seq++;
  322         if (error) {
  323                 NCPSDEBUG("error=%d\n",error);
  324                 if (error != EINTR)                     /* if not just interrupt */
  325                         ncp_conn_invalidate(conn);      /* only reconnect to restore */
  326                 return(error);
  327         }
  328         if (conn->flags & NCPFL_SIGNACTIVE) {
  329                 /* XXX: check reply signature */
  330                 m_adj(mreply, -8);
  331                 plen -= 8;
  332         }
  333         len = plen;
  334         m = mreply;
  335         rp = mtod(m, struct ncp_rphdr*);
  336         len -= sizeof(*rp);
  337         rqp->rpsize = len;
  338         rqp->cc = error = rp->completion_code;
  339         if (error) error |= 0x8900;     /* server error */
  340         rqp->cs = rp->connection_state;
  341         if (rqp->cs & (NCP_CS_BAD_CONN | NCP_CS_SERVER_DOWN)) {
  342                 NCPSDEBUG("server drop us\n");
  343                 ncp_conn_invalidate(conn);
  344                 error = ECONNRESET;
  345         }
  346         rqp->rp = m;
  347         rqp->mrp = m;
  348         rqp->bpos = mtod(m, caddr_t) + sizeof(*rp);
  349         return error;
  350 }
  351 
  352 /*
  353  * Here we will try to restore any loggedin & dropped connection,
  354  * connection should be locked on entry
  355  */
  356 int ncp_restore_login(struct ncp_conn *conn);
  357 int
  358 ncp_restore_login(struct ncp_conn *conn) {
  359         int error, oldflags;
  360 
  361         if (conn->flags & NCPFL_RESTORING) {
  362                 printf("Hey, ncp_restore_login called twise !!!\n");
  363                 return 0;
  364         }
  365         oldflags = conn->flags;
  366         printf("Restoring connection, flags = %d\n",oldflags);
  367         if ((oldflags & NCPFL_LOGGED) == 0) {
  368                 return ECONNRESET;      /* no need to restore empty conn */
  369         }
  370         conn->flags &= ~(NCPFL_LOGGED | NCPFL_ATTACHED);
  371         conn->flags |= NCPFL_RESTORING;
  372         do {    /* not a loop */
  373                 error = ncp_reconnect(conn);
  374                 if (error) break;
  375                 if (conn->li.user)
  376                         error = ncp_login_object(conn, conn->li.user, conn->li.objtype, conn->li.password,conn->procp,conn->ucred);
  377                 if (error) break;
  378                 conn->flags |= NCPFL_LOGGED;
  379         } while(0);
  380         if (error) {
  381                 conn->flags = oldflags | NCPFL_INVALID;
  382         }
  383         conn->flags &= ~NCPFL_RESTORING;
  384         return error;
  385 }
  386 
  387 int
  388 ncp_request(struct ncp_conn *conn, struct ncp_rq *rqp) {
  389         int error, rcnt;
  390 /*      struct ncp_rqhdr *rq = mtod(rqp->rq,struct ncp_rqhdr*);*/
  391 
  392         error = ncp_conn_lock(conn,rqp->p,rqp->cred,NCPM_EXECUTE);
  393         if  (error) return error;
  394         rcnt = NCP_RESTORE_COUNT;
  395         for(;;) {
  396                 if (!ncp_conn_valid(conn)) {
  397                         if (rcnt==0) {
  398                                 error = ECONNRESET;
  399                                 break;
  400                         }
  401                         rcnt--;
  402                         error = ncp_restore_login(conn);
  403                         if (error)
  404                                 continue;
  405                 }
  406                 error=ncp_do_request(conn, rqp);
  407                 if (ncp_conn_valid(conn))       /* not just error ! */
  408                         break;
  409         }
  410         ncp_conn_unlock(conn,rqp->p);
  411         return error;
  412 }
  413 
  414 /*
  415  * All negotiation functions expect a locked connection
  416  */
  417 static int
  418 ncp_negotiate_buffersize(struct ncp_conn *conn, int size, int *target) {
  419         int error;
  420         DECLARE_RQ;
  421 
  422         NCP_RQ_HEAD(0x21,conn->procp,conn->ucred);
  423         ncp_rq_word_hl(rqp, size);
  424         checkbad(ncp_request(conn,rqp));
  425         *target = min(ncp_rp_word_hl(rqp), size);
  426         NCP_RQ_EXIT;
  427         return error;
  428 }
  429 
  430 static int
  431 ncp_negotiate_size_and_options(struct ncp_conn *conn, int size, int options, 
  432             int *ret_size, int *ret_options) {
  433         int error;
  434         int rs;
  435         DECLARE_RQ;
  436 
  437         NCP_RQ_HEAD(0x61,conn->procp,conn->ucred);
  438         ncp_rq_word_hl(rqp, size);
  439         ncp_rq_byte(rqp, options);
  440         checkbad(ncp_request(conn, rqp));
  441         rs = ncp_rp_word_hl(rqp);
  442         *ret_size = (rs == 0) ? size : min(rs, size);
  443         ncp_rp_word_hl(rqp);    /* skip echo socket */
  444         *ret_options = ncp_rp_byte(rqp);
  445         NCP_RQ_EXIT;
  446         return error;
  447 }
  448 
  449 static int
  450 ncp_renegotiate_connparam(struct ncp_conn *conn, int buffsize, int in_options)
  451 {
  452         int neg_buffsize, error, options, sl;
  453 
  454         sl = conn->li.sig_level;
  455         if (sl >= 2)
  456                 in_options |= NCP_SECURITY_LEVEL_SIGN_HEADERS;
  457 #ifdef IPX
  458         if (ipxcksum == 2)
  459                 in_options |= NCP_IPX_CHECKSUM;
  460 #endif
  461         error = ncp_negotiate_size_and_options(conn, buffsize, in_options, 
  462             &neg_buffsize, &options);
  463         if (!error) {
  464 #ifdef IPX
  465                 if ((options ^ in_options) & NCP_IPX_CHECKSUM) {
  466                         if (ipxcksum == 2) {
  467                                 printf("Server refuses to support IPX checksums\n");
  468                                 return NWE_REQUESTER_FAILURE;
  469                         }
  470                         in_options |= NCP_IPX_CHECKSUM;
  471                         error = 1;
  472                 }
  473 #endif /* IPX */
  474                 if ((options ^ in_options) & 2) {
  475                         if (sl == 0 || sl == 3)
  476                                 return NWE_SIGNATURE_LEVEL_CONFLICT;
  477                         if (sl == 1) {
  478                                 in_options |= NCP_SECURITY_LEVEL_SIGN_HEADERS;
  479                                 error = 1;
  480                         }
  481                 }
  482                 if (error) {
  483                         error = ncp_negotiate_size_and_options(conn,
  484                             buffsize, in_options, &neg_buffsize, &options);
  485                         if ((options ^ in_options) & 3) {
  486                                 return NWE_SIGNATURE_LEVEL_CONFLICT;
  487                         }
  488                 }
  489         } else {
  490                 in_options &= ~NCP_SECURITY_LEVEL_SIGN_HEADERS;
  491                 error = ncp_negotiate_buffersize(conn, NCP_DEFAULT_BUFSIZE,
  492                               &neg_buffsize);
  493         }                         
  494         if (error) return error;
  495         if ((neg_buffsize < 512) || (neg_buffsize > NCP_MAX_BUFSIZE))
  496                 return EINVAL;
  497         conn->buffer_size = neg_buffsize;
  498         if (in_options & NCP_SECURITY_LEVEL_SIGN_HEADERS)
  499                 conn->flags |= NCPFL_SIGNWANTED;
  500 #ifdef IPX
  501         ncp_sock_checksum(conn, in_options & NCP_IPX_CHECKSUM);
  502 #endif
  503         return 0;
  504 }
  505 
  506 int
  507 ncp_reconnect(struct ncp_conn *conn) {
  508         int error;
  509 
  510         /* close any open sockets */
  511         ncp_sock_disconnect(conn);
  512         switch( conn->li.saddr.sa_family ) {
  513 #ifdef IPX
  514             case AF_IPX:
  515                 error = ncp_sock_connect_ipx(conn);
  516                 break;
  517 #endif
  518 #ifdef INET
  519             case AF_INET:
  520                 error = ncp_sock_connect_in(conn);
  521                 break;
  522 #endif
  523             default:
  524                 return EPROTONOSUPPORT;
  525         }
  526         if (!error)
  527                 error = ncp_ncp_connect(conn);
  528         return error;
  529 }
  530 
  531 /*
  532  * Create conn structure and try to do low level connect
  533  * Server addr should be filled in.
  534  */
  535 int
  536 ncp_connect(struct ncp_conn_args *li, struct proc *p, struct ucred *cred,
  537         struct ncp_conn **aconn)
  538 {
  539         struct ncp_conn *conn;
  540         struct ucred *owner;
  541         int error, isroot;
  542 
  543         if (li->saddr.sa_family != AF_INET && li->saddr.sa_family != AF_IPX)
  544                 return EPROTONOSUPPORT;
  545         isroot = ncp_suser(cred) == 0;
  546         /*
  547          * Only root can change ownership
  548          */
  549         if (li->owner != NCP_DEFAULT_OWNER && !isroot)
  550                 return EPERM;
  551         if (li->group != NCP_DEFAULT_GROUP &&
  552             !groupmember(li->group, cred) && !isroot)
  553                 return EPERM;
  554         if (li->owner != NCP_DEFAULT_OWNER) {
  555                 owner = crget();
  556                 owner->cr_uid = li->owner;
  557         } else {
  558                 owner = cred;
  559                 crhold(owner);
  560         }
  561         error = ncp_conn_alloc(p, owner, &conn);
  562         if (error)
  563                 return (error);
  564         if (error) {
  565                 ncp_conn_free(conn);
  566                 return error;
  567         }
  568         conn->li = *li;
  569         conn->nc_group = (li->group != NCP_DEFAULT_GROUP) ? 
  570                 li->group : cred->cr_groups[0];
  571 
  572         if (li->retry_count == 0)
  573                 conn->li.retry_count = NCP_RETRY_COUNT;
  574         if (li->timeout == 0)
  575                 conn->li.timeout = NCP_RETRY_TIMEOUT;
  576         error = ncp_reconnect(conn);
  577         if (error) {
  578                 ncp_disconnect(conn);
  579         } else {
  580                 *aconn=conn;
  581         }
  582         return error;
  583 }
  584 /*
  585  * Break connection and deallocate memory
  586  */
  587 int
  588 ncp_disconnect(struct ncp_conn *conn) {
  589 
  590         if (ncp_conn_access(conn,conn->ucred,NCPM_WRITE))
  591                 return EACCES;
  592         if (conn->ref_cnt != 0) return EBUSY;
  593         if (conn->flags & NCPFL_PERMANENT) return EBUSY;
  594         if (ncp_conn_valid(conn)) {
  595                 ncp_ncp_disconnect(conn);
  596         }
  597         ncp_sock_disconnect(conn);
  598         ncp_conn_free(conn);
  599         return 0;
  600 }
  601 
  602 void
  603 ncp_check_rq(struct ncp_conn *conn){
  604         return;
  605         if (conn->flags & NCPFL_INTR) return;
  606         /* first, check for signals */
  607         if (ncp_chkintr(conn,conn->procp)) {
  608                 conn->flags |= NCPFL_INTR;
  609         }
  610         return;
  611 }

Cache object: 88961da90a886a170bbe02c8d5cad197


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