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) 2003 Tim J. Robbins.
    3  * Copyright (c) 1999, 2000, 2001 Boris Popov
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *    This product includes software developed by Boris Popov.
   17  * 4. Neither the name of the author nor the names of any co-contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/6.3/sys/netncp/ncp_mod.c 139823 2005-01-07 01:45:51Z imp $");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/conf.h>
   40 #include <sys/proc.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/malloc.h>
   45 #include <sys/uio.h>
   46 #include <sys/ioccom.h>
   47 
   48 #include <netncp/ncp.h>
   49 #include <netncp/ncp_conn.h>
   50 #include <netncp/ncp_subr.h>
   51 #include <netncp/ncp_ncp.h>
   52 #include <netncp/ncp_user.h>
   53 #include <netncp/ncp_rq.h>
   54 #include <netncp/ncp_nls.h>
   55 #include <netncp/ncpio.h>
   56 
   57 int ncp_version = NCP_VERSION;
   58 
   59 SYSCTL_NODE(_net, OID_AUTO, ncp, CTLFLAG_RW, NULL, "NetWare requester");
   60 SYSCTL_INT(_net_ncp, OID_AUTO, version, CTLFLAG_RD, &ncp_version, 0, "");
   61 
   62 MODULE_VERSION(ncp, 1);
   63 MODULE_DEPEND(ncp, libmchain, 1, 1, 1);
   64 
   65 static struct cdev *ncp_dev;
   66 
   67 static d_ioctl_t        ncp_ioctl;
   68 
   69 static struct cdevsw ncp_cdevsw = {
   70         .d_version =    D_VERSION,
   71         .d_flags =      D_NEEDGIANT,
   72         .d_ioctl =      ncp_ioctl,
   73         .d_name =       "ncp",
   74 };
   75 
   76 static int ncp_conn_frag_rq(struct ncp_conn *, struct thread *,
   77     struct ncp_conn_frag *);
   78 static int ncp_conn_handler(struct thread *, struct ncpioc_request *,
   79     struct ncp_conn *, struct ncp_handle *);
   80 static int sncp_conn_scan(struct thread *, struct ncpioc_connscan *);
   81 static int sncp_connect(struct thread *, struct ncpioc_connect *);
   82 static int sncp_request(struct thread *, struct ncpioc_request *);
   83 
   84 static int
   85 ncp_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
   86 {
   87 
   88         switch (cmd) {
   89         case NCPIOC_CONNECT:
   90                 return (sncp_connect(td, (struct ncpioc_connect *)data));
   91         case NCPIOC_CONNSCAN:
   92                 return (sncp_conn_scan(td, (struct ncpioc_connscan *)data));
   93         case NCPIOC_REQUEST:
   94                 return (sncp_request(td, (struct ncpioc_request *)data));
   95         }
   96         return (EINVAL);
   97 }
   98 
   99 /*
  100  * Attach to NCP server
  101  */
  102 
  103 static int
  104 sncp_connect(struct thread *td, struct ncpioc_connect *args)
  105 {
  106         int connHandle = 0, error;
  107         struct ncp_conn *conn;
  108         struct ncp_handle *handle;
  109         struct ncp_conn_args li;
  110 
  111         checkbad(copyin(args->ioc_li,&li,sizeof(li)));
  112         /* XXX Should be useracc() */
  113         checkbad(copyout(&connHandle,args->ioc_connhandle,
  114             sizeof(connHandle)));
  115         li.password = li.user = NULL;
  116         error = ncp_conn_getattached(&li, td, td->td_ucred, NCPM_WRITE | NCPM_EXECUTE, &conn);
  117         if (error) {
  118                 error = ncp_conn_alloc(&li, td, td->td_ucred, &conn);
  119                 if (error)
  120                         goto bad;
  121                 error = ncp_conn_reconnect(conn);
  122                 if (error)
  123                         ncp_conn_free(conn);
  124         }
  125         if (!error) {
  126                 error = ncp_conn_gethandle(conn, td, &handle);
  127                 copyout(&handle->nh_id, args->ioc_connhandle,
  128                     sizeof(args->ioc_connhandle));
  129                 ncp_conn_unlock(conn,td);
  130         }
  131 bad:
  132         return error;
  133 }
  134 
  135 static int
  136 sncp_request(struct thread *td, struct ncpioc_request *args)
  137 {
  138         struct ncp_rq *rqp;
  139         struct ncp_conn *conn;
  140         struct ncp_handle *handle;
  141         int error = 0, rqsize;
  142 
  143         error = ncp_conn_findhandle(args->ioc_connhandle, td, &handle);
  144         if (error)
  145                 return error;
  146         conn = handle->nh_conn;
  147         if (args->ioc_fn == NCP_CONN)
  148                 return ncp_conn_handler(td, args, conn, handle);
  149         error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int));
  150         if (error)
  151                 return(error);
  152         error = ncp_rq_alloc(args->ioc_fn, conn, td, td->td_ucred, &rqp);
  153         if (error)
  154                 return error;
  155         if (rqsize) {
  156                 error = mb_put_mem(&rqp->rq, (caddr_t)args->ioc_ncpbuf->packet,
  157                     rqsize, MB_MUSER);
  158                 if (error)
  159                         goto bad;
  160         }
  161         rqp->nr_flags |= NCPR_DONTFREEONERR;
  162         error = ncp_request(rqp);
  163         if (error == 0 && rqp->nr_rpsize)
  164                 error = md_get_mem(&rqp->rp, (caddr_t)args->ioc_ncpbuf->packet, 
  165                                 rqp->nr_rpsize, MB_MUSER);
  166         copyout(&rqp->nr_cs, &args->ioc_ncpbuf->cs, sizeof(rqp->nr_cs));
  167         copyout(&rqp->nr_cc, &args->ioc_ncpbuf->cc, sizeof(rqp->nr_cc));
  168         copyout(&rqp->nr_rpsize, &args->ioc_ncpbuf->rpsize, sizeof(rqp->nr_rpsize));
  169 bad:
  170         ncp_rq_done(rqp);
  171         return error;
  172 }
  173 
  174 static int
  175 ncp_mod_login(struct ncp_conn *conn, char *user, int objtype, char *password,
  176         struct thread *td, struct ucred *cred)
  177 {
  178         int error;
  179 
  180         if (ncp_suser(cred) != 0 && cred->cr_uid != conn->nc_owner->cr_uid)
  181                 return EACCES;
  182         conn->li.user = ncp_str_dup(user);
  183         if (conn->li.user == NULL)
  184                 return ENOMEM;
  185         conn->li.password = ncp_str_dup(password);
  186         if (conn->li.password == NULL) {
  187                 error = ENOMEM;
  188                 goto bad;
  189         }
  190         ncp_str_upper(conn->li.user);
  191         if ((conn->li.opt & NCP_OPT_NOUPCASEPASS) == 0)
  192                 ncp_str_upper(conn->li.password);
  193         conn->li.objtype = objtype;
  194         error = ncp_conn_login(conn, td, cred);
  195         return error;
  196 bad:
  197         if (conn->li.user) {
  198                 free(conn->li.user, M_NCPDATA);
  199                 conn->li.user = NULL;
  200         }
  201         if (conn->li.password) {
  202                 free(conn->li.password, M_NCPDATA);
  203                 conn->li.password = NULL;
  204         }
  205         return error;
  206 }
  207 
  208 static int
  209 ncp_conn_handler(struct thread *td, struct ncpioc_request *args,
  210         struct ncp_conn *conn, struct ncp_handle *hp)
  211 {
  212         int error = 0, rqsize, subfn;
  213         struct ucred *cred;
  214 
  215         char *pdata;
  216 
  217         cred = td->td_ucred;
  218         error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int));
  219         if (error)
  220                 return(error);
  221         error = 0;
  222         pdata = args->ioc_ncpbuf->packet;
  223         subfn = *(pdata++) & 0xff;
  224         rqsize--;
  225         switch (subfn) {
  226             case NCP_CONN_READ: case NCP_CONN_WRITE: {
  227                 struct ncp_rw rwrq;
  228                 struct uio auio;
  229                 struct iovec iov;
  230 
  231                 if (rqsize != sizeof(rwrq))
  232                         return (EBADRPC);
  233                 error = copyin(pdata,&rwrq,rqsize);
  234                 if (error)
  235                         return (error);
  236                 iov.iov_base = rwrq.nrw_base;
  237                 iov.iov_len = rwrq.nrw_cnt;
  238                 auio.uio_iov = &iov;
  239                 auio.uio_iovcnt = 1;
  240                 auio.uio_offset = rwrq.nrw_offset;
  241                 auio.uio_resid = rwrq.nrw_cnt;
  242                 auio.uio_segflg = UIO_USERSPACE;
  243                 auio.uio_rw = (subfn == NCP_CONN_READ) ? UIO_READ : UIO_WRITE;
  244                 auio.uio_td = td;
  245                 if (subfn == NCP_CONN_READ)
  246                         error = ncp_read(conn, &rwrq.nrw_fh, &auio, cred);
  247                 else
  248                         error = ncp_write(conn, &rwrq.nrw_fh, &auio, cred);
  249                 rwrq.nrw_cnt -= auio.uio_resid;
  250                 /*td->td_retval[0] = rwrq.nrw_cnt;*/
  251                 break;
  252             } /* case int_read/write */
  253             case NCP_CONN_SETFLAGS: {
  254                 u_int16_t mask, flags;
  255 
  256                 error = copyin(pdata,&mask, sizeof(mask));
  257                 if (error)
  258                         return error;
  259                 pdata += sizeof(mask);
  260                 error = copyin(pdata,&flags,sizeof(flags));
  261                 if (error)
  262                         return error;
  263                 error = ncp_conn_lock(conn, td, cred, NCPM_WRITE);
  264                 if (error)
  265                         return error;
  266                 if (mask & NCPFL_PERMANENT) {
  267                         conn->flags &= ~NCPFL_PERMANENT;
  268                         conn->flags |= (flags & NCPFL_PERMANENT);
  269                 }
  270                 if (mask & NCPFL_PRIMARY) {
  271                         error = ncp_conn_setprimary(conn, flags & NCPFL_PRIMARY);
  272                         if (error) {
  273                                 ncp_conn_unlock(conn, td);
  274                                 break;
  275                         }
  276                 }
  277                 ncp_conn_unlock(conn, td);
  278                 break;
  279             }
  280             case NCP_CONN_LOGIN: {
  281                 struct ncp_conn_login la;
  282 
  283                 if (rqsize != sizeof(la))
  284                         return EBADRPC;
  285                 if (conn->flags & NCPFL_LOGGED)
  286                         return EALREADY;
  287                 if ((error = copyin(pdata,&la,rqsize)) != 0)
  288                         break;
  289                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE | NCPM_WRITE);
  290                 if (error)
  291                         return error;
  292                 error = ncp_mod_login(conn, la.username, la.objtype,
  293                     la.password, td, td->td_ucred);
  294                 ncp_conn_unlock(conn, td);
  295                 break;
  296             }
  297             case NCP_CONN_GETINFO: {
  298                 struct ncp_conn_stat ncs;
  299                 int len = sizeof(ncs);
  300 
  301                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  302                 if (error)
  303                         return error;
  304                 ncp_conn_getinfo(conn, &ncs);
  305                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  306                 error = copyout(&ncs, &args->ioc_ncpbuf->packet, len);
  307                 ncp_conn_unlock(conn, td);
  308                 break;
  309             }
  310             case NCP_CONN_GETUSER: {
  311                 int len;
  312 
  313                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  314                 if (error)
  315                         return error;
  316                 len = (conn->li.user) ? strlen(conn->li.user) + 1 : 0;
  317                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  318                 if (len) {
  319                         error = copyout(conn->li.user,
  320                             &args->ioc_ncpbuf->packet, len);
  321                 }
  322                 ncp_conn_unlock(conn, td);
  323                 break;
  324             }
  325             case NCP_CONN_CONN2REF: {
  326                 int len = sizeof(int);
  327 
  328                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  329                 if (error)
  330                         return error;
  331                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  332                 if (len) {
  333                         error = copyout(&conn->nc_id,
  334                             &args->ioc_ncpbuf->packet, len);
  335                 }
  336                 ncp_conn_unlock(conn, td);
  337                 break;
  338             }
  339             case NCP_CONN_FRAG: {
  340                 struct ncp_conn_frag nf;
  341 
  342                 if (rqsize != sizeof(nf))
  343                         return (EBADRPC);
  344                 if ((error = copyin(pdata, &nf, rqsize)) != 0) break;
  345                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE);
  346                 if (error)
  347                         return error;
  348                 error = ncp_conn_frag_rq(conn, td, &nf);
  349                 ncp_conn_unlock(conn, td);
  350                 copyout(&nf, &pdata, sizeof(nf));
  351                 td->td_retval[0] = error;
  352                 break;
  353             }
  354             case NCP_CONN_DUP: {
  355                 struct ncp_handle *newhp;
  356                 int len = sizeof(NWCONN_HANDLE);
  357 
  358                 error = ncp_conn_lock(conn, td, cred, NCPM_READ);
  359                 if (error) break;
  360                 copyout(&len, &args->ioc_ncpbuf->rpsize, len);
  361                 error = ncp_conn_gethandle(conn, td, &newhp);
  362                 if (!error)
  363                         error = copyout(&newhp->nh_id,
  364                             args->ioc_ncpbuf->packet, len);
  365                 ncp_conn_unlock(conn, td);
  366                 break;
  367             }
  368             case NCP_CONN_CONNCLOSE: {
  369                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE);
  370                 if (error) break;
  371                 ncp_conn_puthandle(hp, td, 0);
  372                 error = ncp_conn_free(conn);
  373                 if (error)
  374                         ncp_conn_unlock(conn, td);
  375                 break;
  376             }
  377             default:
  378                     error = EOPNOTSUPP;
  379         }
  380         return error;
  381 }
  382 
  383 static int
  384 sncp_conn_scan(struct thread *td, struct ncpioc_connscan *args)
  385 {
  386         int connHandle = 0, error;
  387         struct ncp_conn_args li, *lip;
  388         struct ncp_conn *conn;
  389         struct ncp_handle *hp;
  390         char *user = NULL, *password = NULL;
  391 
  392         if (args->ioc_li) {
  393                 if (copyin(args->ioc_li, &li, sizeof(li)))
  394                         return EFAULT;
  395                 lip = &li;
  396         } else {
  397                 lip = NULL;
  398         }
  399 
  400         if (lip != NULL) {
  401                 lip->server[sizeof(lip->server)-1]=0; /* just to make sure */
  402                 ncp_str_upper(lip->server);
  403                 if (lip->user) {
  404                         user = ncp_str_dup(lip->user);
  405                         if (user == NULL)
  406                                 return EINVAL;
  407                         ncp_str_upper(user);
  408                 }
  409                 if (lip->password) {
  410                         password = ncp_str_dup(lip->password);
  411                         if (password == NULL) {
  412                                 if (user)
  413                                         free(user, M_NCPDATA);
  414                                 return EINVAL;
  415                         }
  416                         ncp_str_upper(password);
  417                 }
  418                 lip->user = user;
  419                 lip->password = password;
  420         }
  421         error = ncp_conn_getbyli(lip, td, td->td_ucred, NCPM_EXECUTE, &conn);
  422         if (!error) {           /* already have this login */
  423                 ncp_conn_gethandle(conn, td, &hp);
  424                 connHandle = hp->nh_id;
  425                 ncp_conn_unlock(conn, td);
  426                 copyout(&connHandle, args->ioc_connhandle, sizeof(connHandle));
  427         }
  428         if (user)
  429                 free(user, M_NCPDATA);
  430         if (password)
  431                 free(password, M_NCPDATA);
  432         return error;
  433 
  434 }
  435 
  436 int
  437 ncp_conn_frag_rq(struct ncp_conn *conn, struct thread *td,
  438                  struct ncp_conn_frag *nfp)
  439 {
  440         NW_FRAGMENT *fp;
  441         struct ncp_rq *rqp;
  442         u_int32_t fsize;
  443         int error, i, rpsize;
  444 
  445         error = ncp_rq_alloc(nfp->fn, conn, td, td->td_ucred, &rqp);
  446         if (error)
  447                 return error;
  448         for(fp = nfp->rqf, i = 0; i < nfp->rqfcnt; i++, fp++) {
  449                 error = mb_put_mem(&rqp->rq, (caddr_t)fp->fragAddress, fp->fragSize, MB_MUSER);
  450                 if (error)
  451                         goto bad;
  452         }
  453         rqp->nr_flags |= NCPR_DONTFREEONERR;
  454         error = ncp_request(rqp);
  455         if (error)
  456                 goto bad;
  457         rpsize = rqp->nr_rpsize;
  458         if (rpsize && nfp->rpfcnt) {
  459                 for(fp = nfp->rpf, i = 0; i < nfp->rpfcnt; i++, fp++) {
  460                         error = copyin(&fp->fragSize, &fsize, sizeof (fsize));
  461                         if (error)
  462                                 break;
  463                         fsize = min(fsize, rpsize);
  464                         error = md_get_mem(&rqp->rp, (caddr_t)fp->fragAddress, fsize, MB_MUSER);
  465                         if (error)
  466                                 break;
  467                         rpsize -= fsize;
  468                         error = copyout(&fsize, &fp->fragSize, sizeof (fsize));
  469                         if (error)
  470                                 break;
  471                 }
  472         }
  473         nfp->cs = rqp->nr_cs;
  474         nfp->cc = rqp->nr_cc;
  475 bad:
  476         ncp_rq_done(rqp);
  477         return error;
  478 }
  479 
  480 static int
  481 ncp_load(void)
  482 {
  483         int error;
  484 
  485         if ((error = ncp_init()) != 0)
  486                 return (error);
  487         ncp_dev = make_dev(&ncp_cdevsw, 0, 0, 0, 0666, "ncp");
  488         printf("ncp_load: loaded\n");
  489         return (0);
  490 }
  491 
  492 static int
  493 ncp_unload(void)
  494 {
  495         int error;
  496 
  497         error = ncp_done();
  498         if (error)
  499                 return (error);
  500         destroy_dev(ncp_dev);
  501         printf("ncp_unload: unloaded\n");
  502         return (0);
  503 }
  504 
  505 static int
  506 ncp_mod_handler(module_t mod, int type, void *data)
  507 {
  508         int error;
  509 
  510         switch (type) {
  511         case MOD_LOAD:
  512                 error = ncp_load();
  513                 break;
  514         case MOD_UNLOAD:
  515                 error = ncp_unload();
  516                 break;
  517         default:
  518                 error = EINVAL;
  519         }
  520         return error;
  521 }
  522 
  523 static moduledata_t ncp_mod = {
  524         "ncp",
  525         ncp_mod_handler,
  526         NULL
  527 };
  528 DECLARE_MODULE(ncp, ncp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);

Cache object: 09b46663284c15c8c96527895bef53e6


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