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_mod.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 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/sysproto.h>
   37 #include <sys/sysent.h>
   38 #include <sys/proc.h>
   39 #include <sys/kernel.h>
   40 #include <sys/sysctl.h>
   41 #include <sys/malloc.h>
   42 #include <sys/uio.h>
   43 
   44 #include <netncp/ncp.h>
   45 #include <netncp/ncp_conn.h>
   46 #include <netncp/ncp_subr.h>
   47 #include <netncp/ncp_ncp.h>
   48 #include <netncp/ncp_user.h>
   49 #include <netncp/ncp_rq.h>
   50 #include <netncp/ncp_nls.h>
   51 
   52 int ncp_version = NCP_VERSION;
   53 
   54 static int ncp_sysent;
   55 
   56 SYSCTL_NODE(_net, OID_AUTO, ncp, CTLFLAG_RW, NULL, "NetWare requester");
   57 SYSCTL_INT(_net_ncp, OID_AUTO, sysent, CTLFLAG_RD, &ncp_sysent, 0, "");
   58 SYSCTL_INT(_net_ncp, OID_AUTO, version, CTLFLAG_RD, &ncp_version, 0, "");
   59 
   60 static int
   61 ncp_conn_frag_rq(struct ncp_conn *conn, struct proc *p, struct ncp_conn_frag *nfp);
   62 
   63 /*
   64  * Attach to NCP server
   65  */
   66 struct sncp_connect_args {
   67         struct ncp_conn_args *li;
   68         int *connHandle;
   69 };
   70 
   71 static int 
   72 __P(sncp_connect(struct proc *p, struct sncp_connect_args *uap)){
   73         int connHandle = 0, error;
   74         struct ncp_conn *conn;
   75         struct ncp_handle *handle;
   76         struct ncp_conn_args li;
   77 
   78         checkbad(copyin(uap->li,&li,sizeof(li)));
   79         checkbad(copyout(&connHandle,uap->connHandle,sizeof(connHandle))); /* check before */
   80         li.password = li.user = NULL;
   81         error = ncp_conn_getattached(&li, p, p->p_ucred, NCPM_WRITE | NCPM_EXECUTE, &conn);
   82         if (error) {
   83                 error = ncp_connect(&li, p, p->p_ucred, &conn);
   84         }
   85         if (!error) {
   86                 error = ncp_conn_gethandle(conn, p, &handle);
   87                 copyout(&handle->nh_id, uap->connHandle, sizeof(uap->connHandle));
   88                 ncp_conn_unlock(conn,p);
   89         }
   90 bad:
   91         p->p_retval[0]=error;
   92         return error;
   93 }
   94 
   95 struct sncp_request_args {
   96         int connHandle;
   97         int fn;
   98         struct ncp_buf *ncpbuf;
   99 };
  100 
  101 static int ncp_conn_handler(struct proc *p, struct sncp_request_args *uap,
  102         struct ncp_conn *conn, struct ncp_handle *handle);
  103 
  104 static int
  105 __P(sncp_request(struct proc *p, struct sncp_request_args *uap)){
  106         int error = 0, rqsize;
  107         struct ncp_conn *conn;
  108         struct ncp_handle *handle;
  109         DECLARE_RQ;
  110 
  111         error = ncp_conn_findhandle(uap->connHandle,p,&handle);
  112         if (error) return error;
  113         conn = handle->nh_conn;
  114         if (uap->fn == NCP_CONN)
  115                 return ncp_conn_handler(p, uap, conn, handle);
  116         error = copyin(&uap->ncpbuf->rqsize, &rqsize, sizeof(int));
  117         if (error) return(error);
  118         error = ncp_conn_lock(conn,p,p->p_ucred,NCPM_EXECUTE);
  119         if (error) return(error);
  120         ncp_rq_head(rqp,NCP_REQUEST,uap->fn,p,p->p_ucred);
  121         if (rqsize)
  122                 error = ncp_rq_usermem(rqp,(caddr_t)uap->ncpbuf->packet, rqsize);
  123         if (!error) {
  124                 error = ncp_request(conn, rqp);
  125                 if (error == 0 && rqp->rpsize)
  126                         ncp_rp_usermem(rqp, (caddr_t)uap->ncpbuf->packet, 
  127                                 rqp->rpsize);
  128                 copyout(&rqp->cs, &uap->ncpbuf->cs, sizeof(rqp->cs));
  129                 copyout(&rqp->cc, &uap->ncpbuf->cc, sizeof(rqp->cc));
  130                 copyout(&rqp->rpsize, &uap->ncpbuf->rpsize, sizeof(rqp->rpsize));
  131         }
  132         ncp_rq_done(rqp);
  133         ncp_conn_unlock(conn,p);
  134         return error;
  135 }
  136 
  137 static int
  138 ncp_conn_handler(struct proc *p, struct sncp_request_args *uap,
  139         struct ncp_conn *conn, struct ncp_handle *hp)
  140 {
  141         int error=0, rqsize, subfn;
  142         struct ucred *cred;
  143         
  144         char *pdata;
  145 
  146         cred = p->p_ucred;
  147         error = copyin(&uap->ncpbuf->rqsize, &rqsize, sizeof(int));
  148         if (error) return(error);
  149         error = 0;
  150         pdata = uap->ncpbuf->packet;
  151         subfn = *(pdata++) & 0xff;
  152         rqsize--;
  153         switch (subfn) {
  154             case NCP_CONN_READ: case NCP_CONN_WRITE: {
  155                 struct ncp_rw rwrq;
  156                 struct uio auio;
  157                 struct iovec iov;
  158         
  159                 if (rqsize != sizeof(rwrq)) return (EBADRPC);   
  160                 error = copyin(pdata,&rwrq,rqsize);
  161                 if (error) return (error);
  162                 iov.iov_base = rwrq.nrw_base;
  163                 iov.iov_len = rwrq.nrw_cnt;
  164                 auio.uio_iov = &iov;
  165                 auio.uio_iovcnt = 1;
  166                 auio.uio_offset = rwrq.nrw_offset;
  167                 auio.uio_resid = rwrq.nrw_cnt;
  168                 auio.uio_segflg = UIO_USERSPACE;
  169                 auio.uio_rw = (subfn == NCP_CONN_READ) ? UIO_READ : UIO_WRITE;
  170                 auio.uio_procp = p;
  171                 error = ncp_conn_lock(conn,p,cred,NCPM_EXECUTE);
  172                 if (error) return(error);
  173                 if (subfn == NCP_CONN_READ)
  174                         error = ncp_read(conn, &rwrq.nrw_fh, &auio, cred);
  175                 else
  176                         error = ncp_write(conn, &rwrq.nrw_fh, &auio, cred);
  177                 rwrq.nrw_cnt -= auio.uio_resid;
  178                 ncp_conn_unlock(conn,p);
  179                 p->p_retval[0] = rwrq.nrw_cnt;
  180                 break;
  181             } /* case int_read/write */
  182             case NCP_CONN_SETFLAGS: {
  183                 u_int16_t mask, flags;
  184 
  185                 error = copyin(pdata,&mask, sizeof(mask));
  186                 if (error) return error;
  187                 pdata += sizeof(mask);
  188                 error = copyin(pdata,&flags,sizeof(flags));
  189                 if (error) return error;
  190                 error = ncp_conn_lock(conn,p,cred,NCPM_WRITE);
  191                 if (error) return error;
  192                 if (mask & NCPFL_PERMANENT) {
  193                         conn->flags &= ~NCPFL_PERMANENT;
  194                         conn->flags |= (flags & NCPFL_PERMANENT);
  195                 }
  196                 if (mask & NCPFL_PRIMARY) {
  197                         error = ncp_conn_setprimary(conn, flags & NCPFL_PRIMARY);
  198                         if (error) {
  199                                 ncp_conn_unlock(conn,p);
  200                                 break;
  201                         }
  202                 }
  203                 ncp_conn_unlock(conn,p);
  204                 break;
  205             }
  206             case NCP_CONN_LOGIN: {
  207                 struct ncp_conn_login la;
  208 
  209                 if (rqsize != sizeof(la)) return (EBADRPC);     
  210                 if ((error = copyin(pdata,&la,rqsize)) != 0) break;
  211                 error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE | NCPM_WRITE);
  212                 if (error) return error;
  213                 error = ncp_login(conn, la.username, la.objtype, la.password, p, p->p_ucred);
  214                 ncp_conn_unlock(conn, p);
  215                 p->p_retval[0] = error;
  216                 break;
  217             }
  218             case NCP_CONN_GETINFO: {
  219                 struct ncp_conn_stat ncs;
  220                 int len = sizeof(ncs);
  221 
  222                 error = ncp_conn_lock(conn, p, p->p_ucred, NCPM_READ);
  223                 if (error) return error;
  224                 ncp_conn_getinfo(conn, &ncs);
  225                 copyout(&len, &uap->ncpbuf->rpsize, sizeof(int));
  226                 error = copyout(&ncs, &uap->ncpbuf->packet, len);
  227                 ncp_conn_unlock(conn, p);
  228                 break;
  229             }
  230             case NCP_CONN_GETUSER: {
  231                 int len;
  232 
  233                 error = ncp_conn_lock(conn, p, p->p_ucred, NCPM_READ);
  234                 if (error) return error;
  235                 len = (conn->li.user) ? strlen(conn->li.user) + 1 : 0;
  236                 copyout(&len, &uap->ncpbuf->rpsize, sizeof(int));
  237                 if (len) {
  238                         error = copyout(conn->li.user, &uap->ncpbuf->packet, len);
  239                 }
  240                 ncp_conn_unlock(conn, p);
  241                 break;
  242             }
  243             case NCP_CONN_CONN2REF: {
  244                 int len = sizeof(int);
  245 
  246                 error = ncp_conn_lock(conn, p, p->p_ucred, NCPM_READ);
  247                 if (error) return error;
  248                 copyout(&len, &uap->ncpbuf->rpsize, sizeof(int));
  249                 if (len) {
  250                         error = copyout(&conn->nc_id, &uap->ncpbuf->packet, len);
  251                 }
  252                 ncp_conn_unlock(conn, p);
  253                 break;
  254             }
  255             case NCP_CONN_FRAG: {
  256                 struct ncp_conn_frag nf;
  257 
  258                 if (rqsize != sizeof(nf)) return (EBADRPC);     
  259                 if ((error = copyin(pdata, &nf, rqsize)) != 0) break;
  260                 error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE);
  261                 if (error) return error;
  262                 error = ncp_conn_frag_rq(conn, p, &nf);
  263                 ncp_conn_unlock(conn, p);
  264                 copyout(&nf, &pdata, sizeof(nf));
  265                 p->p_retval[0] = error;
  266                 break;
  267             }
  268             case NCP_CONN_DUP: {
  269                 struct ncp_handle *newhp;
  270                 int len = sizeof(NWCONN_HANDLE);
  271 
  272                 error = ncp_conn_lock(conn, p, cred, NCPM_READ);
  273                 if (error) break;
  274                 copyout(&len, &uap->ncpbuf->rpsize, len);
  275                 error = ncp_conn_gethandle(conn, p, &newhp);
  276                 if (!error)
  277                         error = copyout(&newhp->nh_id, uap->ncpbuf->packet, len);
  278                 ncp_conn_unlock(conn,p);
  279                 break;
  280             }
  281             case NCP_CONN_CONNCLOSE: {
  282                 error = ncp_conn_lock(conn, p, cred, NCPM_EXECUTE);
  283                 if (error) break;
  284                 ncp_conn_puthandle(hp, p, 0);
  285                 error = ncp_disconnect(conn);
  286                 if (error)
  287                         ncp_conn_unlock(conn, p);
  288                 break;
  289             }
  290             default:
  291                     error = EOPNOTSUPP;
  292         }
  293         return error;
  294 }
  295 
  296 struct sncp_conn_scan_args {
  297         struct ncp_conn_args *li;
  298         int *connHandle;
  299 };
  300 
  301 static int 
  302 __P(sncp_conn_scan(struct proc *p, struct sncp_conn_scan_args *uap)){
  303         int connHandle = 0, error;
  304         struct ncp_conn_args li, *lip;
  305         struct ncp_conn *conn;
  306         struct ncp_handle *hp;
  307         char *user = NULL, *password = NULL;
  308 
  309         if (uap->li) {
  310                 if (copyin(uap->li,&li,sizeof(li))) return EFAULT;
  311                 lip = &li;
  312         } else {
  313                 lip = NULL;
  314         }
  315 
  316         if (lip != NULL) {
  317                 lip->server[sizeof(lip->server)-1]=0; /* just to make sure */
  318                 ncp_str_upper(lip->server);
  319                 if (lip->user) {
  320                         user = ncp_str_dup(lip->user);
  321                         if (user == NULL) return EINVAL;
  322                         ncp_str_upper(user);
  323                 }
  324                 if (lip->password) {
  325                         password = ncp_str_dup(lip->password);
  326                         if (password == NULL) {
  327                                 if (user)
  328                                         free(user, M_NCPDATA);
  329                                 return EINVAL;
  330                         }
  331                         ncp_str_upper(password);
  332                 }
  333                 lip->user = user;
  334                 lip->password = password;
  335         }
  336         error = ncp_conn_getbyli(lip,p,p->p_ucred,NCPM_EXECUTE,&conn);
  337         if (!error) {           /* already have this login */
  338                 ncp_conn_gethandle(conn, p, &hp);
  339                 connHandle = hp->nh_id;
  340                 ncp_conn_unlock(conn,p);
  341                 copyout(&connHandle,uap->connHandle,sizeof(connHandle));
  342         }
  343         if (user) free(user, M_NCPDATA);
  344         if (password) free(password, M_NCPDATA);
  345         p->p_retval[0] = error;
  346         return error;
  347 
  348 }
  349 
  350 int
  351 ncp_conn_frag_rq(struct ncp_conn *conn, struct proc *p, struct ncp_conn_frag *nfp){
  352         int error = 0, i, rpsize;
  353         u_int32_t fsize;
  354         NW_FRAGMENT *fp;
  355         DECLARE_RQ;
  356 
  357         ncp_rq_head(rqp,NCP_REQUEST,nfp->fn,p,p->p_ucred);
  358         if (nfp->rqfcnt) {
  359                 for(fp = nfp->rqf, i = 0; i < nfp->rqfcnt; i++, fp++) {
  360                         checkbad(ncp_rq_usermem(rqp,(caddr_t)fp->fragAddress, fp->fragSize));
  361                 }
  362         }
  363         checkbad(ncp_request(conn, rqp));
  364         rpsize = rqp->rpsize;
  365         if (rpsize && nfp->rpfcnt) {
  366                 for(fp = nfp->rpf, i = 0; i < nfp->rpfcnt; i++, fp++) {
  367                         checkbad(copyin(&fp->fragSize, &fsize, sizeof (fsize)));
  368                         fsize = min(fsize, rpsize);
  369                         checkbad(ncp_rp_usermem(rqp,(caddr_t)fp->fragAddress, fsize));
  370                         rpsize -= fsize;
  371                         checkbad(copyout(&fsize, &fp->fragSize, sizeof (fsize)));
  372                 }
  373         }
  374         nfp->cs = rqp->cs;
  375         nfp->cc = rqp->cc;
  376         NCP_RQ_EXIT;
  377         return error;
  378 }
  379 
  380 /*
  381  * Internal functions, here should be all calls that do not require connection.
  382  * To simplify possible future movement to cdev, we use IOCTL macros.
  383  * Pretty much of this stolen from ioctl() function.
  384  */
  385 struct sncp_intfn_args {
  386         u_long  com;
  387         caddr_t data;
  388 };
  389 
  390 static int
  391 sncp_intfn(struct proc *p, struct sncp_intfn_args *uap)
  392 {
  393         return ENOSYS;
  394 }
  395 /*
  396  * define our new system calls
  397  */
  398 static struct sysent newent[] = {
  399         {2,     (sy_call_t*)sncp_conn_scan},
  400         {2,     (sy_call_t*)sncp_connect},
  401         {2,     (sy_call_t*)sncp_intfn},
  402         {3,     (sy_call_t*)sncp_request}
  403 };
  404 
  405 #define SC_SIZE sizeof(newent)/sizeof(struct sysent)
  406 /*
  407  * Miscellaneous modules must have their own save areas...
  408  */
  409 static struct sysent    oldent[SC_SIZE];        /* save are for old callslot entry*/
  410 
  411 /*
  412  * Number of syscall entries for a.out executables
  413  */
  414 /*#define nsysent SYS_MAXSYSCALL*/
  415 #define nsysent (aout_sysvec.sv_size)
  416 
  417 
  418 static int
  419 ncp_load(void) {
  420         int i, ff, scnt, err=0;
  421 
  422         while(1) {
  423                 /* Search the table looking for an enough number of slots... */
  424                 for (scnt=0, ff = -1, i = 0; i < nsysent; i++) {
  425                         if (sysent[i].sy_call == (sy_call_t *)lkmnosys) {
  426                                 if (ff == -1) {
  427                                     ff = i;
  428                                     scnt = 1;
  429                                 } else {
  430                                     scnt++;
  431                                     if (scnt == SC_SIZE) break;
  432                                 }
  433                         } else {
  434                                 ff = -1;
  435                         }
  436                 }
  437                 /* out of allocable slots?*/
  438                 if(i == nsysent || ff == -1) {
  439                         err = ENFILE;
  440                         break;
  441                 }
  442                 err = ncp_init();
  443                 if (err) break;
  444                 bcopy(&sysent[ff], &oldent, sizeof(struct sysent)*SC_SIZE);
  445                 bcopy(&newent, &sysent[ff], sizeof(struct sysent)*SC_SIZE);
  446                 ncp_sysent = ff;        /* slot in sysent[]*/
  447                 printf("ncp_load: [%d-%d]\n",ff,i);
  448                 break;
  449         }
  450 
  451         return( err);
  452 }
  453 
  454 static int
  455 ncp_unload(void) {
  456         ncp_done();
  457         bcopy(&oldent, &sysent[ncp_sysent], sizeof(struct sysent) * SC_SIZE);
  458         printf( "ncp_unload: unloaded\n");
  459         return 0;
  460 }
  461 
  462 static int
  463 ncp_mod_handler(module_t mod, int type, void *data)
  464 {
  465         int error;
  466 
  467         switch (type) {
  468             case MOD_LOAD:
  469                 error = ncp_load();
  470                 break;
  471             case MOD_UNLOAD:
  472                 error = ncp_unload();
  473                 break;
  474             default:
  475                 error = EINVAL;
  476         }
  477         return error;
  478 }
  479                                                                \
  480 static moduledata_t ncp_mod = {
  481         "ncp",
  482         ncp_mod_handler,
  483         NULL
  484 };
  485 DECLARE_MODULE(ncp, ncp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);

Cache object: 6deb2d69763efab1b0f75f5b8fa25c00


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