diff options
author | tjr <tjr@FreeBSD.org> | 2003-02-28 04:31:29 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2003-02-28 04:31:29 +0000 |
commit | c072d36bb918825d157424cd39c2b0bc6381ad2a (patch) | |
tree | 4546286a0530aacd98f941d017d6426d949085f7 /sys/netncp | |
parent | a95892f08b4e8c28320530dcd5c77d27d419ef7e (diff) | |
download | FreeBSD-src-c072d36bb918825d157424cd39c2b0bc6381ad2a.zip FreeBSD-src-c072d36bb918825d157424cd39c2b0bc6381ad2a.tar.gz |
Use a character device and ioctl() for communication between libncp
and the kernel instead of adding more syscalls at runtime. As a bonus,
you can now restrict access to the kernel NCP interface with chmod.
Diffstat (limited to 'sys/netncp')
-rw-r--r-- | sys/netncp/ncp.h | 2 | ||||
-rw-r--r-- | sys/netncp/ncp_mod.c | 229 | ||||
-rw-r--r-- | sys/netncp/ncpio.h | 62 |
3 files changed, 155 insertions, 138 deletions
diff --git a/sys/netncp/ncp.h b/sys/netncp/ncp.h index c00f935..cfe60ab 100644 --- a/sys/netncp/ncp.h +++ b/sys/netncp/ncp.h @@ -11,7 +11,7 @@ #define _NETNCP_NCP_H_ #define NCP_VERMAJ 1 -#define NCP_VERMIN 3400 +#define NCP_VERMIN 3500 #define NCP_VERSION (NCP_VERMAJ*100000 + NCP_VERMIN) typedef u_int32_t nwdirent; diff --git a/sys/netncp/ncp_mod.c b/sys/netncp/ncp_mod.c index e08ed13..877528c 100644 --- a/sys/netncp/ncp_mod.c +++ b/sys/netncp/ncp_mod.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2003 Tim J. Robbins. * Copyright (c) 1999, 2000, 2001 Boris Popov * All rights reserved. * @@ -33,14 +34,13 @@ */ #include <sys/param.h> #include <sys/systm.h> -#include <sys/sysproto.h> -#include <sys/sysent.h> +#include <sys/conf.h> #include <sys/proc.h> #include <sys/kernel.h> -#include <sys/syscall.h> #include <sys/sysctl.h> #include <sys/malloc.h> #include <sys/uio.h> +#include <sys/ioccom.h> #include <netncp/ncp.h> #include <netncp/ncp_conn.h> @@ -49,40 +49,75 @@ #include <netncp/ncp_user.h> #include <netncp/ncp_rq.h> #include <netncp/ncp_nls.h> +#include <netncp/ncpio.h> int ncp_version = NCP_VERSION; -static int ncp_sysent; - SYSCTL_NODE(_net, OID_AUTO, ncp, CTLFLAG_RW, NULL, "NetWare requester"); -SYSCTL_INT(_net_ncp, OID_AUTO, sysent, CTLFLAG_RD, &ncp_sysent, 0, ""); SYSCTL_INT(_net_ncp, OID_AUTO, version, CTLFLAG_RD, &ncp_version, 0, ""); MODULE_VERSION(ncp, 1); MODULE_DEPEND(ncp, libmchain, 1, 1, 1); +static dev_t ncp_dev; + +static d_ioctl_t ncp_ioctl; + +static struct cdevsw ncp_cdevsw = { + /* open */ nullopen, + /* close */ nullclose, + /* read */ noread, + /* write */ nowrite, + /* ioctl */ ncp_ioctl, + /* poll */ nopoll, + /* mmap */ nommap, + /* strategy */ nostrategy, + /* name */ "ncp", + /* maj */ MAJOR_AUTO, + /* dump */ nodump, + /* psize */ nopsize, + /* flags */ 0 +}; + +static int ncp_conn_frag_rq(struct ncp_conn *, struct thread *, + struct ncp_conn_frag *); +static int ncp_conn_handler(struct thread *, struct ncpioc_request *, + struct ncp_conn *, struct ncp_handle *); +static int sncp_conn_scan(struct thread *, struct ncpioc_connscan *); +static int sncp_connect(struct thread *, struct ncpioc_connect *); +static int sncp_request(struct thread *, struct ncpioc_request *); + static int -ncp_conn_frag_rq(struct ncp_conn *conn, struct thread *td, - struct ncp_conn_frag *nfp); +ncp_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) +{ + + switch (cmd) { + case NCPIOC_CONNECT: + return (sncp_connect(td, (struct ncpioc_connect *)data)); + case NCPIOC_CONNSCAN: + return (sncp_conn_scan(td, (struct ncpioc_connscan *)data)); + case NCPIOC_REQUEST: + return (sncp_request(td, (struct ncpioc_request *)data)); + } + return (EINVAL); +} /* * Attach to NCP server */ -struct sncp_connect_args { - struct ncp_conn_args *li; - int *connHandle; -}; static int -sncp_connect(struct thread *td, struct sncp_connect_args *uap) +sncp_connect(struct thread *td, struct ncpioc_connect *args) { int connHandle = 0, error; struct ncp_conn *conn; struct ncp_handle *handle; struct ncp_conn_args li; - checkbad(copyin(uap->li,&li,sizeof(li))); - checkbad(copyout(&connHandle,uap->connHandle,sizeof(connHandle))); /* check before */ + checkbad(copyin(args->ioc_li,&li,sizeof(li))); + /* XXX Should be useracc() */ + checkbad(copyout(&connHandle,args->ioc_connhandle, + sizeof(connHandle))); li.password = li.user = NULL; error = ncp_conn_getattached(&li, td, td->td_ucred, NCPM_WRITE | NCPM_EXECUTE, &conn); if (error) { @@ -95,45 +130,36 @@ sncp_connect(struct thread *td, struct sncp_connect_args *uap) } if (!error) { error = ncp_conn_gethandle(conn, td, &handle); - copyout(&handle->nh_id, uap->connHandle, sizeof(uap->connHandle)); + copyout(&handle->nh_id, args->ioc_connhandle, + sizeof(args->ioc_connhandle)); ncp_conn_unlock(conn,td); } bad: - td->td_retval[0]=error; return error; } -struct sncp_request_args { - int connHandle; - int fn; - struct ncp_buf *ncpbuf; -}; - -static int ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, - struct ncp_conn *conn, struct ncp_handle *handle); - static int -sncp_request(struct thread *td, struct sncp_request_args *uap) +sncp_request(struct thread *td, struct ncpioc_request *args) { struct ncp_rq *rqp; struct ncp_conn *conn; struct ncp_handle *handle; int error = 0, rqsize; - error = ncp_conn_findhandle(uap->connHandle, td, &handle); + error = ncp_conn_findhandle(args->ioc_connhandle, td, &handle); if (error) return error; conn = handle->nh_conn; - if (uap->fn == NCP_CONN) - return ncp_conn_handler(td, uap, conn, handle); - error = copyin(&uap->ncpbuf->rqsize, &rqsize, sizeof(int)); + if (args->ioc_fn == NCP_CONN) + return ncp_conn_handler(td, args, conn, handle); + error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int)); if (error) return(error); - error = ncp_rq_alloc(uap->fn, conn, td, td->td_ucred, &rqp); + error = ncp_rq_alloc(args->ioc_fn, conn, td, td->td_ucred, &rqp); if (error) return error; if (rqsize) { - error = mb_put_mem(&rqp->rq, (caddr_t)uap->ncpbuf->packet, + error = mb_put_mem(&rqp->rq, (caddr_t)args->ioc_ncpbuf->packet, rqsize, MB_MUSER); if (error) goto bad; @@ -141,11 +167,11 @@ sncp_request(struct thread *td, struct sncp_request_args *uap) rqp->nr_flags |= NCPR_DONTFREEONERR; error = ncp_request(rqp); if (error == 0 && rqp->nr_rpsize) - error = md_get_mem(&rqp->rp, (caddr_t)uap->ncpbuf->packet, + error = md_get_mem(&rqp->rp, (caddr_t)args->ioc_ncpbuf->packet, rqp->nr_rpsize, MB_MUSER); - copyout(&rqp->nr_cs, &uap->ncpbuf->cs, sizeof(rqp->nr_cs)); - copyout(&rqp->nr_cc, &uap->ncpbuf->cc, sizeof(rqp->nr_cc)); - copyout(&rqp->nr_rpsize, &uap->ncpbuf->rpsize, sizeof(rqp->nr_rpsize)); + copyout(&rqp->nr_cs, &args->ioc_ncpbuf->cs, sizeof(rqp->nr_cs)); + copyout(&rqp->nr_cc, &args->ioc_ncpbuf->cc, sizeof(rqp->nr_cc)); + copyout(&rqp->nr_rpsize, &args->ioc_ncpbuf->rpsize, sizeof(rqp->nr_rpsize)); bad: ncp_rq_done(rqp); return error; @@ -186,7 +212,7 @@ bad: } static int -ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, +ncp_conn_handler(struct thread *td, struct ncpioc_request *args, struct ncp_conn *conn, struct ncp_handle *hp) { int error = 0, rqsize, subfn; @@ -195,11 +221,11 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, char *pdata; cred = td->td_ucred; - error = copyin(&uap->ncpbuf->rqsize, &rqsize, sizeof(int)); + error = copyin(&args->ioc_ncpbuf->rqsize, &rqsize, sizeof(int)); if (error) return(error); error = 0; - pdata = uap->ncpbuf->packet; + pdata = args->ioc_ncpbuf->packet; subfn = *(pdata++) & 0xff; rqsize--; switch (subfn) { @@ -227,7 +253,7 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, else error = ncp_write(conn, &rwrq.nrw_fh, &auio, cred); rwrq.nrw_cnt -= auio.uio_resid; - td->td_retval[0] = rwrq.nrw_cnt; + /*td->td_retval[0] = rwrq.nrw_cnt;*/ break; } /* case int_read/write */ case NCP_CONN_SETFLAGS: { @@ -272,7 +298,6 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, error = ncp_mod_login(conn, la.username, la.objtype, la.password, td, td->td_ucred); ncp_conn_unlock(conn, td); - td->td_retval[0] = error; break; } case NCP_CONN_GETINFO: { @@ -283,8 +308,8 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, if (error) return error; ncp_conn_getinfo(conn, &ncs); - copyout(&len, &uap->ncpbuf->rpsize, sizeof(int)); - error = copyout(&ncs, &uap->ncpbuf->packet, len); + copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int)); + error = copyout(&ncs, &args->ioc_ncpbuf->packet, len); ncp_conn_unlock(conn, td); break; } @@ -295,9 +320,10 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, if (error) return error; len = (conn->li.user) ? strlen(conn->li.user) + 1 : 0; - copyout(&len, &uap->ncpbuf->rpsize, sizeof(int)); + copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int)); if (len) { - error = copyout(conn->li.user, &uap->ncpbuf->packet, len); + error = copyout(conn->li.user, + &args->ioc_ncpbuf->packet, len); } ncp_conn_unlock(conn, td); break; @@ -308,9 +334,10 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, error = ncp_conn_lock(conn, td, td->td_ucred, NCPM_READ); if (error) return error; - copyout(&len, &uap->ncpbuf->rpsize, sizeof(int)); + copyout(&len, &args->ioc_ncpbuf->rpsize, sizeof(int)); if (len) { - error = copyout(&conn->nc_id, &uap->ncpbuf->packet, len); + error = copyout(&conn->nc_id, + &args->ioc_ncpbuf->packet, len); } ncp_conn_unlock(conn, td); break; @@ -336,10 +363,11 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, error = ncp_conn_lock(conn, td, cred, NCPM_READ); if (error) break; - copyout(&len, &uap->ncpbuf->rpsize, len); + copyout(&len, &args->ioc_ncpbuf->rpsize, len); error = ncp_conn_gethandle(conn, td, &newhp); if (!error) - error = copyout(&newhp->nh_id, uap->ncpbuf->packet, len); + error = copyout(&newhp->nh_id, + args->ioc_ncpbuf->packet, len); ncp_conn_unlock(conn, td); break; } @@ -358,13 +386,8 @@ ncp_conn_handler(struct thread *td, struct sncp_request_args *uap, return error; } -struct sncp_conn_scan_args { - struct ncp_conn_args *li; - int *connHandle; -}; - static int -sncp_conn_scan(struct thread *td, struct sncp_conn_scan_args *uap) +sncp_conn_scan(struct thread *td, struct ncpioc_connscan *args) { int connHandle = 0, error; struct ncp_conn_args li, *lip; @@ -372,8 +395,8 @@ sncp_conn_scan(struct thread *td, struct sncp_conn_scan_args *uap) struct ncp_handle *hp; char *user = NULL, *password = NULL; - if (uap->li) { - if (copyin(uap->li, &li, sizeof(li))) + if (args->ioc_li) { + if (copyin(args->ioc_li, &li, sizeof(li))) return EFAULT; lip = &li; } else { @@ -406,13 +429,12 @@ sncp_conn_scan(struct thread *td, struct sncp_conn_scan_args *uap) ncp_conn_gethandle(conn, td, &hp); connHandle = hp->nh_id; ncp_conn_unlock(conn, td); - copyout(&connHandle, uap->connHandle, sizeof(connHandle)); + copyout(&connHandle, args->ioc_connhandle, sizeof(connHandle)); } if (user) free(user, M_NCPDATA); if (password) free(password, M_NCPDATA); - td->td_retval[0] = error; return error; } @@ -461,83 +483,16 @@ bad: return error; } -/* - * Internal functions, here should be all calls that do not require connection. - * To simplify possible future movement to cdev, we use IOCTL macros. - * Pretty much of this stolen from ioctl() function. - */ -struct sncp_intfn_args { - u_long com; - caddr_t data; -}; - -static int -sncp_intfn(struct proc *p, struct sncp_intfn_args *uap) -{ - return ENOSYS; -} - -/* - * define our new system calls - */ -static struct sysent newent[] = { - {2, (sy_call_t*)sncp_conn_scan}, - {2, (sy_call_t*)sncp_connect}, - {2, (sy_call_t*)sncp_intfn}, - {3, (sy_call_t*)sncp_request} -}; - -#define SC_SIZE sizeof(newent)/sizeof(struct sysent) - -/* - * Miscellaneous modules must have their own save areas... - */ -static struct sysent oldent[SC_SIZE]; /* save are for old callslot entry*/ - -/* - * Number of syscall entries for a.out executables - */ -#define nsysent SYS_MAXSYSCALL -/* #define nsysent (elf_sysvec.sv_size) */ - - static int ncp_load(void) { - int i, ff, scnt, err = 0; - - while (1) { - /* Search the table looking for an enough number of slots... */ - for (scnt = 0, ff = -1, i = 0; i < nsysent; i++) { - if (sysent[i].sy_call == (sy_call_t *)lkmnosys) { - if (ff == -1) { - ff = i; - scnt = 1; - } else { - scnt++; - if (scnt == SC_SIZE) - break; - } - } else { - ff = -1; - } - } - /* out of allocable slots?*/ - if (i == nsysent || ff == -1) { - err = ENFILE; - break; - } - err = ncp_init(); - if (err) - break; - bcopy(&sysent[ff], &oldent, sizeof(struct sysent) * SC_SIZE); - bcopy(&newent, &sysent[ff], sizeof(struct sysent) * SC_SIZE); - ncp_sysent = ff; /* slot in sysent[]*/ - printf("ncp_load: [%d-%d]\n", ff, i); - break; - } + int error; - return (err); + if ((error = ncp_init()) != 0) + return (error); + ncp_dev = make_dev(&ncp_cdevsw, 0, 0, 0, 0666, "ncp"); + printf("ncp_load: loaded\n"); + return (0); } static int @@ -547,10 +502,10 @@ ncp_unload(void) error = ncp_done(); if (error) - return error; - bcopy(&oldent, &sysent[ncp_sysent], sizeof(struct sysent) * SC_SIZE); - printf( "ncp_unload: unloaded\n"); - return 0; + return (error); + destroy_dev(ncp_dev); + printf("ncp_unload: unloaded\n"); + return (0); } static int diff --git a/sys/netncp/ncpio.h b/sys/netncp/ncpio.h new file mode 100644 index 0000000..53c90ea --- /dev/null +++ b/sys/netncp/ncpio.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2003 Tim J. Robbins. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NETNCP_NCPIO_H_ +#define _NETNCP_NCPIO_H_ + +#ifndef _KERNEL +#include <sys/types.h> +#endif +#include <sys/ioccom.h> + +#define NCP_NAME "ncp" + +struct ncp_conn_args; +struct ncp_buf; + +struct ncpioc_connect { + struct ncp_conn_args *ioc_li; + int *ioc_connhandle; +}; + +struct ncpioc_request { + int ioc_connhandle; + int ioc_fn; + struct ncp_buf *ioc_ncpbuf; +}; + +struct ncpioc_connscan { + struct ncp_conn_args *ioc_li; + int *ioc_connhandle; +}; + +#define NCPIOC_CONNECT _IOW('N', 100, struct ncpioc_connect) +#define NCPIOC_REQUEST _IOW('N', 101, struct ncpioc_request) +#define NCPIOC_CONNSCAN _IOW('N', 102, struct ncpioc_connscan) + +#endif /* _NETNCP_NCPIO_H_ */ |