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