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  * $FreeBSD: releng/5.1/sys/netncp/ncp_mod.c 112037 2003-03-09 11:03:45Z phk $
   34  */
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/conf.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 #include <sys/ioccom.h>
   44 
   45 #include <netncp/ncp.h>
   46 #include <netncp/ncp_conn.h>
   47 #include <netncp/ncp_subr.h>
   48 #include <netncp/ncp_ncp.h>
   49 #include <netncp/ncp_user.h>
   50 #include <netncp/ncp_rq.h>
   51 #include <netncp/ncp_nls.h>
   52 #include <netncp/ncpio.h>
   53 
   54 int ncp_version = NCP_VERSION;
   55 
   56 SYSCTL_NODE(_net, OID_AUTO, ncp, CTLFLAG_RW, NULL, "NetWare requester");
   57 SYSCTL_INT(_net_ncp, OID_AUTO, version, CTLFLAG_RD, &ncp_version, 0, "");
   58 
   59 MODULE_VERSION(ncp, 1);
   60 MODULE_DEPEND(ncp, libmchain, 1, 1, 1);
   61 
   62 static dev_t            ncp_dev;
   63 
   64 static d_ioctl_t        ncp_ioctl;
   65 
   66 static struct cdevsw ncp_cdevsw = {
   67         .d_open =       nullopen,
   68         .d_close =      nullclose,
   69         .d_ioctl =      ncp_ioctl,
   70         .d_name =       "ncp",
   71 };
   72 
   73 static int ncp_conn_frag_rq(struct ncp_conn *, struct thread *,
   74     struct ncp_conn_frag *);
   75 static int ncp_conn_handler(struct thread *, struct ncpioc_request *,
   76     struct ncp_conn *, struct ncp_handle *);
   77 static int sncp_conn_scan(struct thread *, struct ncpioc_connscan *);
   78 static int sncp_connect(struct thread *, struct ncpioc_connect *);
   79 static int sncp_request(struct thread *, struct ncpioc_request *);
   80 
   81 static int
   82 ncp_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
   83 {
   84 
   85         switch (cmd) {
   86         case NCPIOC_CONNECT:
   87                 return (sncp_connect(td, (struct ncpioc_connect *)data));
   88         case NCPIOC_CONNSCAN:
   89                 return (sncp_conn_scan(td, (struct ncpioc_connscan *)data));
   90         case NCPIOC_REQUEST:
   91                 return (sncp_request(td, (struct ncpioc_request *)data));
   92         }
   93         return (EINVAL);
   94 }
   95 
   96 /*
   97  * Attach to NCP server
   98  */
   99 
  100 static int
  101 sncp_connect(struct thread *td, struct ncpioc_connect *args)
  102 {
  103         int connHandle = 0, error;
  104         struct ncp_conn *conn;
  105         struct ncp_handle *handle;
  106         struct ncp_conn_args li;
  107 
  108         checkbad(copyin(args->ioc_li,&li,sizeof(li)));
  109         /* XXX Should be useracc() */
  110         checkbad(copyout(&connHandle,args->ioc_connhandle,
  111             sizeof(connHandle)));
  112         li.password = li.user = NULL;
  113         error = ncp_conn_getattached(&li, td, td->td_ucred, NCPM_WRITE | NCPM_EXECUTE, &conn);
  114         if (error) {
  115                 error = ncp_conn_alloc(&li, td, td->td_ucred, &conn);
  116                 if (error)
  117                         goto bad;
  118                 error = ncp_conn_reconnect(conn);
  119                 if (error)
  120                         ncp_conn_free(conn);
  121         }
  122         if (!error) {
  123                 error = ncp_conn_gethandle(conn, td, &handle);
  124                 copyout(&handle->nh_id, args->ioc_connhandle,
  125                     sizeof(args->ioc_connhandle));
  126                 ncp_conn_unlock(conn,td);
  127         }
  128 bad:
  129         return error;
  130 }
  131 
  132 static int
  133 sncp_request(struct thread *td, struct ncpioc_request *args)
  134 {
  135         struct ncp_rq *rqp;
  136         struct ncp_conn *conn;
  137         struct ncp_handle *handle;
  138         int error = 0, rqsize;
  139 
  140         error = ncp_conn_findhandle(args->ioc_connhandle, td, &handle);
  141         if (error)
  142                 return error;
  143         conn = handle->nh_conn;
  144         if (args->ioc_fn == NCP_CONN)
  145                 return ncp_conn_handler(td, args, conn, handle);
  146         error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int));
  147         if (error)
  148                 return(error);
  149         error = ncp_rq_alloc(args->ioc_fn, conn, td, td->td_ucred, &rqp);
  150         if (error)
  151                 return error;
  152         if (rqsize) {
  153                 error = mb_put_mem(&rqp->rq, (caddr_t)args->ioc_ncpbuf->packet,
  154                     rqsize, MB_MUSER);
  155                 if (error)
  156                         goto bad;
  157         }
  158         rqp->nr_flags |= NCPR_DONTFREEONERR;
  159         error = ncp_request(rqp);
  160         if (error == 0 && rqp->nr_rpsize)
  161                 error = md_get_mem(&rqp->rp, (caddr_t)args->ioc_ncpbuf->packet, 
  162                                 rqp->nr_rpsize, MB_MUSER);
  163         copyout(&rqp->nr_cs, &args->ioc_ncpbuf->cs, sizeof(rqp->nr_cs));
  164         copyout(&rqp->nr_cc, &args->ioc_ncpbuf->cc, sizeof(rqp->nr_cc));
  165         copyout(&rqp->nr_rpsize, &args->ioc_ncpbuf->rpsize, sizeof(rqp->nr_rpsize));
  166 bad:
  167         ncp_rq_done(rqp);
  168         return error;
  169 }
  170 
  171 static int
  172 ncp_mod_login(struct ncp_conn *conn, char *user, int objtype, char *password,
  173         struct thread *td, struct ucred *cred)
  174 {
  175         int error;
  176 
  177         if (ncp_suser(cred) != 0 && cred->cr_uid != conn->nc_owner->cr_uid)
  178                 return EACCES;
  179         conn->li.user = ncp_str_dup(user);
  180         if (conn->li.user == NULL)
  181                 return ENOMEM;
  182         conn->li.password = ncp_str_dup(password);
  183         if (conn->li.password == NULL) {
  184                 error = ENOMEM;
  185                 goto bad;
  186         }
  187         ncp_str_upper(conn->li.user);
  188         if ((conn->li.opt & NCP_OPT_NOUPCASEPASS) == 0)
  189                 ncp_str_upper(conn->li.password);
  190         conn->li.objtype = objtype;
  191         error = ncp_conn_login(conn, td, cred);
  192         return error;
  193 bad:
  194         if (conn->li.user) {
  195                 free(conn->li.user, M_NCPDATA);
  196                 conn->li.user = NULL;
  197         }
  198         if (conn->li.password) {
  199                 free(conn->li.password, M_NCPDATA);
  200                 conn->li.password = NULL;
  201         }
  202         return error;
  203 }
  204 
  205 static int
  206 ncp_conn_handler(struct thread *td, struct ncpioc_request *args,
  207         struct ncp_conn *conn, struct ncp_handle *hp)
  208 {
  209         int error = 0, rqsize, subfn;
  210         struct ucred *cred;
  211 
  212         char *pdata;
  213 
  214         cred = td->td_ucred;
  215         error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int));
  216         if (error)
  217                 return(error);
  218         error = 0;
  219         pdata = args->ioc_ncpbuf->packet;
  220         subfn = *(pdata++) & 0xff;
  221         rqsize--;
  222         switch (subfn) {
  223             case NCP_CONN_READ: case NCP_CONN_WRITE: {
  224                 struct ncp_rw rwrq;
  225                 struct uio auio;
  226                 struct iovec iov;
  227 
  228                 if (rqsize != sizeof(rwrq))
  229                         return (EBADRPC);
  230                 error = copyin(pdata,&rwrq,rqsize);
  231                 if (error)
  232                         return (error);
  233                 iov.iov_base = rwrq.nrw_base;
  234                 iov.iov_len = rwrq.nrw_cnt;
  235                 auio.uio_iov = &iov;
  236                 auio.uio_iovcnt = 1;
  237                 auio.uio_offset = rwrq.nrw_offset;
  238                 auio.uio_resid = rwrq.nrw_cnt;
  239                 auio.uio_segflg = UIO_USERSPACE;
  240                 auio.uio_rw = (subfn == NCP_CONN_READ) ? UIO_READ : UIO_WRITE;
  241                 auio.uio_td = td;
  242                 if (subfn == NCP_CONN_READ)
  243                         error = ncp_read(conn, &rwrq.nrw_fh, &auio, cred);
  244                 else
  245                         error = ncp_write(conn, &rwrq.nrw_fh, &auio, cred);
  246                 rwrq.nrw_cnt -= auio.uio_resid;
  247                 /*td->td_retval[0] = rwrq.nrw_cnt;*/
  248                 break;
  249             } /* case int_read/write */
  250             case NCP_CONN_SETFLAGS: {
  251                 u_int16_t mask, flags;
  252 
  253                 error = copyin(pdata,&mask, sizeof(mask));
  254                 if (error)
  255                         return error;
  256                 pdata += sizeof(mask);
  257                 error = copyin(pdata,&flags,sizeof(flags));
  258                 if (error)
  259                         return error;
  260                 error = ncp_conn_lock(conn, td, cred, NCPM_WRITE);
  261                 if (error)
  262                         return error;
  263                 if (mask & NCPFL_PERMANENT) {
  264                         conn->flags &= ~NCPFL_PERMANENT;
  265                         conn->flags |= (flags & NCPFL_PERMANENT);
  266                 }
  267                 if (mask & NCPFL_PRIMARY) {
  268                         error = ncp_conn_setprimary(conn, flags & NCPFL_PRIMARY);
  269                         if (error) {
  270                                 ncp_conn_unlock(conn, td);
  271                                 break;
  272                         }
  273                 }
  274                 ncp_conn_unlock(conn, td);
  275                 break;
  276             }
  277             case NCP_CONN_LOGIN: {
  278                 struct ncp_conn_login la;
  279 
  280                 if (rqsize != sizeof(la))
  281                         return EBADRPC;
  282                 if (conn->flags & NCPFL_LOGGED)
  283                         return EALREADY;
  284                 if ((error = copyin(pdata,&la,rqsize)) != 0)
  285                         break;
  286                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE | NCPM_WRITE);
  287                 if (error)
  288                         return error;
  289                 error = ncp_mod_login(conn, la.username, la.objtype,
  290                     la.password, td, td->td_ucred);
  291                 ncp_conn_unlock(conn, td);
  292                 break;
  293             }
  294             case NCP_CONN_GETINFO: {
  295                 struct ncp_conn_stat ncs;
  296                 int len = sizeof(ncs);
  297 
  298                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  299                 if (error)
  300                         return error;
  301                 ncp_conn_getinfo(conn, &ncs);
  302                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  303                 error = copyout(&ncs, &args->ioc_ncpbuf->packet, len);
  304                 ncp_conn_unlock(conn, td);
  305                 break;
  306             }
  307             case NCP_CONN_GETUSER: {
  308                 int len;
  309 
  310                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  311                 if (error)
  312                         return error;
  313                 len = (conn->li.user) ? strlen(conn->li.user) + 1 : 0;
  314                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  315                 if (len) {
  316                         error = copyout(conn->li.user,
  317                             &args->ioc_ncpbuf->packet, len);
  318                 }
  319                 ncp_conn_unlock(conn, td);
  320                 break;
  321             }
  322             case NCP_CONN_CONN2REF: {
  323                 int len = sizeof(int);
  324 
  325                 error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ);
  326                 if (error)
  327                         return error;
  328                 copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int));
  329                 if (len) {
  330                         error = copyout(&conn->nc_id,
  331                             &args->ioc_ncpbuf->packet, len);
  332                 }
  333                 ncp_conn_unlock(conn, td);
  334                 break;
  335             }
  336             case NCP_CONN_FRAG: {
  337                 struct ncp_conn_frag nf;
  338 
  339                 if (rqsize != sizeof(nf))
  340                         return (EBADRPC);
  341                 if ((error = copyin(pdata, &nf, rqsize)) != 0) break;
  342                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE);
  343                 if (error)
  344                         return error;
  345                 error = ncp_conn_frag_rq(conn, td, &nf);
  346                 ncp_conn_unlock(conn, td);
  347                 copyout(&nf, &pdata, sizeof(nf));
  348                 td->td_retval[0] = error;
  349                 break;
  350             }
  351             case NCP_CONN_DUP: {
  352                 struct ncp_handle *newhp;
  353                 int len = sizeof(NWCONN_HANDLE);
  354 
  355                 error = ncp_conn_lock(conn, td, cred, NCPM_READ);
  356                 if (error) break;
  357                 copyout(&len, &args->ioc_ncpbuf->rpsize, len);
  358                 error = ncp_conn_gethandle(conn, td, &newhp);
  359                 if (!error)
  360                         error = copyout(&newhp->nh_id,
  361                             args->ioc_ncpbuf->packet, len);
  362                 ncp_conn_unlock(conn, td);
  363                 break;
  364             }
  365             case NCP_CONN_CONNCLOSE: {
  366                 error = ncp_conn_lock(conn, td, cred, NCPM_EXECUTE);
  367                 if (error) break;
  368                 ncp_conn_puthandle(hp, td, 0);
  369                 error = ncp_conn_free(conn);
  370                 if (error)
  371                         ncp_conn_unlock(conn, td);
  372                 break;
  373             }
  374             default:
  375                     error = EOPNOTSUPP;
  376         }
  377         return error;
  378 }
  379 
  380 static int
  381 sncp_conn_scan(struct thread *td, struct ncpioc_connscan *args)
  382 {
  383         int connHandle = 0, error;
  384         struct ncp_conn_args li, *lip;
  385         struct ncp_conn *conn;
  386         struct ncp_handle *hp;
  387         char *user = NULL, *password = NULL;
  388 
  389         if (args->ioc_li) {
  390                 if (copyin(args->ioc_li, &li, sizeof(li)))
  391                         return EFAULT;
  392                 lip = &li;
  393         } else {
  394                 lip = NULL;
  395         }
  396 
  397         if (lip != NULL) {
  398                 lip->server[sizeof(lip->server)-1]=0; /* just to make sure */
  399                 ncp_str_upper(lip->server);
  400                 if (lip->user) {
  401                         user = ncp_str_dup(lip->user);
  402                         if (user == NULL)
  403                                 return EINVAL;
  404                         ncp_str_upper(user);
  405                 }
  406                 if (lip->password) {
  407                         password = ncp_str_dup(lip->password);
  408                         if (password == NULL) {
  409                                 if (user)
  410                                         free(user, M_NCPDATA);
  411                                 return EINVAL;
  412                         }
  413                         ncp_str_upper(password);
  414                 }
  415                 lip->user = user;
  416                 lip->password = password;
  417         }
  418         error = ncp_conn_getbyli(lip, td, td->td_ucred, NCPM_EXECUTE, &conn);
  419         if (!error) {           /* already have this login */
  420                 ncp_conn_gethandle(conn, td, &hp);
  421                 connHandle = hp->nh_id;
  422                 ncp_conn_unlock(conn, td);
  423                 copyout(&connHandle, args->ioc_connhandle, sizeof(connHandle));
  424         }
  425         if (user)
  426                 free(user, M_NCPDATA);
  427         if (password)
  428                 free(password, M_NCPDATA);
  429         return error;
  430 
  431 }
  432 
  433 int
  434 ncp_conn_frag_rq(struct ncp_conn *conn, struct thread *td,
  435                  struct ncp_conn_frag *nfp)
  436 {
  437         NW_FRAGMENT *fp;
  438         struct ncp_rq *rqp;
  439         u_int32_t fsize;
  440         int error, i, rpsize;
  441 
  442         error = ncp_rq_alloc(nfp->fn, conn, td, td->td_ucred, &rqp);
  443         if (error)
  444                 return error;
  445         for(fp = nfp->rqf, i = 0; i < nfp->rqfcnt; i++, fp++) {
  446                 error = mb_put_mem(&rqp->rq, (caddr_t)fp->fragAddress, fp->fragSize, MB_MUSER);
  447                 if (error)
  448                         goto bad;
  449         }
  450         rqp->nr_flags |= NCPR_DONTFREEONERR;
  451         error = ncp_request(rqp);
  452         if (error)
  453                 goto bad;
  454         rpsize = rqp->nr_rpsize;
  455         if (rpsize && nfp->rpfcnt) {
  456                 for(fp = nfp->rpf, i = 0; i < nfp->rpfcnt; i++, fp++) {
  457                         error = copyin(&fp->fragSize, &fsize, sizeof (fsize));
  458                         if (error)
  459                                 break;
  460                         fsize = min(fsize, rpsize);
  461                         error = md_get_mem(&rqp->rp, (caddr_t)fp->fragAddress, fsize, MB_MUSER);
  462                         if (error)
  463                                 break;
  464                         rpsize -= fsize;
  465                         error = copyout(&fsize, &fp->fragSize, sizeof (fsize));
  466                         if (error)
  467                                 break;
  468                 }
  469         }
  470         nfp->cs = rqp->nr_cs;
  471         nfp->cc = rqp->nr_cc;
  472 bad:
  473         ncp_rq_done(rqp);
  474         return error;
  475 }
  476 
  477 static int
  478 ncp_load(void)
  479 {
  480         int error;
  481 
  482         if ((error = ncp_init()) != 0)
  483                 return (error);
  484         ncp_dev = make_dev(&ncp_cdevsw, 0, 0, 0, 0666, "ncp");
  485         printf("ncp_load: loaded\n");
  486         return (0);
  487 }
  488 
  489 static int
  490 ncp_unload(void)
  491 {
  492         int error;
  493 
  494         error = ncp_done();
  495         if (error)
  496                 return (error);
  497         destroy_dev(ncp_dev);
  498         printf("ncp_unload: unloaded\n");
  499         return (0);
  500 }
  501 
  502 static int
  503 ncp_mod_handler(module_t mod, int type, void *data)
  504 {
  505         int error;
  506 
  507         switch (type) {
  508         case MOD_LOAD:
  509                 error = ncp_load();
  510                 break;
  511         case MOD_UNLOAD:
  512                 error = ncp_unload();
  513                 break;
  514         default:
  515                 error = EINVAL;
  516         }
  517         return error;
  518 }
  519 
  520 static moduledata_t ncp_mod = {
  521         "ncp",
  522         ncp_mod_handler,
  523         NULL
  524 };
  525 DECLARE_MODULE(ncp, ncp_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY);

Cache object: 0ecac7a3d9e6738974cd52dcd1e481b9


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