2 * Copyright (c) 1999, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
32 * $FreeBSD: src/sys/netncp/ncp_mod.c,v 1.2 1999/10/12 10:36:59 bp Exp $
33 * $DragonFly: src/sys/netproto/ncp/ncp_mod.c,v 1.11 2006/12/22 23:57:54 swildner Exp $
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/sysproto.h>
38 #include <sys/sysent.h>
40 #include <sys/kernel.h>
41 #include <sys/sysctl.h>
42 #include <sys/malloc.h>
44 #include <sys/msgport.h>
54 int ncp_version
= NCP_VERSION
;
56 static int ncp_sysent
;
58 SYSCTL_NODE(_net
, OID_AUTO
, ncp
, CTLFLAG_RW
, NULL
, "NetWare requester");
59 SYSCTL_INT(_net_ncp
, OID_AUTO
, sysent
, CTLFLAG_RD
, &ncp_sysent
, 0, "");
60 SYSCTL_INT(_net_ncp
, OID_AUTO
, version
, CTLFLAG_RD
, &ncp_version
, 0, "");
63 ncp_conn_frag_rq(struct ncp_conn
*conn
, struct thread
*td
, struct ncp_conn_frag
*nfp
);
66 * Attach to NCP server
68 struct sncp_connect_args
{
70 struct ncp_conn_args
*li
;
75 sncp_connect(struct sncp_connect_args
*uap
)
77 struct thread
*td
= curthread
;
78 int connHandle
= 0, error
;
79 struct ncp_conn
*conn
;
80 struct ncp_handle
*handle
;
81 struct ncp_conn_args li
;
84 KKASSERT(td
->td_proc
);
85 cred
= td
->td_proc
->p_ucred
;
87 checkbad(copyin(uap
->li
,&li
,sizeof(li
)));
88 checkbad(copyout(&connHandle
,uap
->connHandle
,sizeof(connHandle
))); /* check before */
89 li
.password
= li
.user
= NULL
;
90 error
= ncp_conn_getattached(&li
, td
, cred
, NCPM_WRITE
| NCPM_EXECUTE
, &conn
);
92 error
= ncp_connect(&li
, td
, cred
, &conn
);
95 error
= ncp_conn_gethandle(conn
, td
, &handle
);
96 copyout(&handle
->nh_id
, uap
->connHandle
, sizeof(uap
->connHandle
));
97 ncp_conn_unlock(conn
,td
);
100 uap
->sysmsg_result
= error
;
104 struct sncp_request_args
{
105 struct sysmsg sysmsg
;
108 struct ncp_buf
*ncpbuf
;
111 static int ncp_conn_handler(struct thread
*td
, struct sncp_request_args
*uap
,
112 struct ncp_conn
*conn
, struct ncp_handle
*handle
);
115 sncp_request(struct sncp_request_args
*uap
)
117 struct thread
*td
= curthread
;
118 int error
= 0, rqsize
;
119 struct ncp_conn
*conn
;
120 struct ncp_handle
*handle
;
125 KKASSERT(td
->td_proc
);
126 cred
= td
->td_proc
->p_ucred
;
128 error
= ncp_conn_findhandle(uap
->connHandle
,td
,&handle
);
129 if (error
) return error
;
130 conn
= handle
->nh_conn
;
131 if (uap
->fn
== NCP_CONN
)
132 return ncp_conn_handler(td
, uap
, conn
, handle
);
133 error
= copyin(&uap
->ncpbuf
->rqsize
, &rqsize
, sizeof(int));
134 if (error
) return(error
);
135 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_EXECUTE
);
136 if (error
) return(error
);
137 ncp_rq_head(rqp
,NCP_REQUEST
,uap
->fn
,td
,cred
);
139 error
= ncp_rq_usermem(rqp
,(caddr_t
)uap
->ncpbuf
->packet
, rqsize
);
141 error
= ncp_request(conn
, rqp
);
142 if (error
== 0 && rqp
->rpsize
)
143 ncp_rp_usermem(rqp
, (caddr_t
)uap
->ncpbuf
->packet
,
145 copyout(&rqp
->cs
, &uap
->ncpbuf
->cs
, sizeof(rqp
->cs
));
146 copyout(&rqp
->cc
, &uap
->ncpbuf
->cc
, sizeof(rqp
->cc
));
147 copyout(&rqp
->rpsize
, &uap
->ncpbuf
->rpsize
, sizeof(rqp
->rpsize
));
150 ncp_conn_unlock(conn
,td
);
155 ncp_conn_handler(struct thread
*td
, struct sncp_request_args
*uap
,
156 struct ncp_conn
*conn
, struct ncp_handle
*hp
)
158 int error
=0, rqsize
, subfn
;
163 KKASSERT(td
->td_proc
);
164 cred
= td
->td_proc
->p_ucred
;
166 error
= copyin(&uap
->ncpbuf
->rqsize
, &rqsize
, sizeof(int));
167 if (error
) return(error
);
169 pdata
= uap
->ncpbuf
->packet
;
170 subfn
= *(pdata
++) & 0xff;
173 case NCP_CONN_READ
: case NCP_CONN_WRITE
: {
178 if (rqsize
!= sizeof(rwrq
)) return (EBADRPC
);
179 error
= copyin(pdata
,&rwrq
,rqsize
);
180 if (error
) return (error
);
181 iov
.iov_base
= rwrq
.nrw_base
;
182 iov
.iov_len
= rwrq
.nrw_cnt
;
185 auio
.uio_offset
= rwrq
.nrw_offset
;
186 auio
.uio_resid
= rwrq
.nrw_cnt
;
187 auio
.uio_segflg
= UIO_USERSPACE
;
188 auio
.uio_rw
= (subfn
== NCP_CONN_READ
) ? UIO_READ
: UIO_WRITE
;
190 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_EXECUTE
);
191 if (error
) return(error
);
192 if (subfn
== NCP_CONN_READ
)
193 error
= ncp_read(conn
, &rwrq
.nrw_fh
, &auio
, cred
);
195 error
= ncp_write(conn
, &rwrq
.nrw_fh
, &auio
, cred
);
196 rwrq
.nrw_cnt
-= auio
.uio_resid
;
197 ncp_conn_unlock(conn
,td
);
198 uap
->sysmsg_result
= rwrq
.nrw_cnt
;
200 } /* case int_read/write */
201 case NCP_CONN_SETFLAGS
: {
202 u_int16_t mask
, flags
;
204 error
= copyin(pdata
,&mask
, sizeof(mask
));
205 if (error
) return error
;
206 pdata
+= sizeof(mask
);
207 error
= copyin(pdata
,&flags
,sizeof(flags
));
208 if (error
) return error
;
209 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_WRITE
);
210 if (error
) return error
;
211 if (mask
& NCPFL_PERMANENT
) {
212 conn
->flags
&= ~NCPFL_PERMANENT
;
213 conn
->flags
|= (flags
& NCPFL_PERMANENT
);
215 if (mask
& NCPFL_PRIMARY
) {
216 error
= ncp_conn_setprimary(conn
, flags
& NCPFL_PRIMARY
);
218 ncp_conn_unlock(conn
,td
);
222 ncp_conn_unlock(conn
,td
);
225 case NCP_CONN_LOGIN
: {
226 struct ncp_conn_login la
;
228 if (rqsize
!= sizeof(la
)) return (EBADRPC
);
229 if ((error
= copyin(pdata
,&la
,rqsize
)) != 0) break;
230 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
| NCPM_WRITE
);
231 if (error
) return error
;
232 error
= ncp_login(conn
, la
.username
, la
.objtype
, la
.password
, td
, cred
);
233 ncp_conn_unlock(conn
, td
);
234 uap
->sysmsg_result
= error
;
237 case NCP_CONN_GETINFO
: {
238 struct ncp_conn_stat ncs
;
239 int len
= sizeof(ncs
);
241 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
242 if (error
) return error
;
243 ncp_conn_getinfo(conn
, &ncs
);
244 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
245 error
= copyout(&ncs
, &uap
->ncpbuf
->packet
, len
);
246 ncp_conn_unlock(conn
, td
);
249 case NCP_CONN_GETUSER
: {
252 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
253 if (error
) return error
;
254 len
= (conn
->li
.user
) ? strlen(conn
->li
.user
) + 1 : 0;
255 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
257 error
= copyout(conn
->li
.user
, &uap
->ncpbuf
->packet
, len
);
259 ncp_conn_unlock(conn
, td
);
262 case NCP_CONN_CONN2REF
: {
263 int len
= sizeof(int);
265 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
266 if (error
) return error
;
267 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
269 error
= copyout(&conn
->nc_id
, &uap
->ncpbuf
->packet
, len
);
271 ncp_conn_unlock(conn
, td
);
274 case NCP_CONN_FRAG
: {
275 struct ncp_conn_frag nf
;
277 if (rqsize
!= sizeof(nf
)) return (EBADRPC
);
278 if ((error
= copyin(pdata
, &nf
, rqsize
)) != 0) break;
279 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
);
280 if (error
) return error
;
281 error
= ncp_conn_frag_rq(conn
, td
, &nf
);
282 ncp_conn_unlock(conn
, td
);
283 copyout(&nf
, &pdata
, sizeof(nf
));
284 uap
->sysmsg_result
= error
;
288 struct ncp_handle
*newhp
;
289 int len
= sizeof(NWCONN_HANDLE
);
291 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
293 copyout(&len
, &uap
->ncpbuf
->rpsize
, len
);
294 error
= ncp_conn_gethandle(conn
, td
, &newhp
);
296 error
= copyout(&newhp
->nh_id
, uap
->ncpbuf
->packet
, len
);
297 ncp_conn_unlock(conn
,td
);
300 case NCP_CONN_CONNCLOSE
: {
301 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
);
303 ncp_conn_puthandle(hp
, td
, 0);
304 error
= ncp_disconnect(conn
);
306 ncp_conn_unlock(conn
, td
);
315 struct sncp_conn_scan_args
{
316 struct sysmsg sysmsg
;
317 struct ncp_conn_args
*li
;
322 sncp_conn_scan(struct thread
*td
, struct sncp_conn_scan_args
*uap
)
324 int connHandle
= 0, error
;
325 struct ncp_conn_args li
, *lip
;
326 struct ncp_conn
*conn
;
327 struct ncp_handle
*hp
;
328 char *user
= NULL
, *password
= NULL
;
331 KKASSERT(td
->td_proc
);
332 cred
= td
->td_proc
->p_ucred
;
335 if (copyin(uap
->li
,&li
,sizeof(li
))) return EFAULT
;
342 lip
->server
[sizeof(lip
->server
)-1]=0; /* just to make sure */
343 ncp_str_upper(lip
->server
);
345 user
= ncp_str_dup(lip
->user
);
346 if (user
== NULL
) return EINVAL
;
350 password
= ncp_str_dup(lip
->password
);
351 if (password
== NULL
) {
353 kfree(user
, M_NCPDATA
);
356 ncp_str_upper(password
);
359 lip
->password
= password
;
361 error
= ncp_conn_getbyli(lip
,td
,cred
,NCPM_EXECUTE
,&conn
);
362 if (!error
) { /* already have this login */
363 ncp_conn_gethandle(conn
, td
, &hp
);
364 connHandle
= hp
->nh_id
;
365 ncp_conn_unlock(conn
,td
);
366 copyout(&connHandle
,uap
->connHandle
,sizeof(connHandle
));
368 if (user
) kfree(user
, M_NCPDATA
);
369 if (password
) kfree(password
, M_NCPDATA
);
370 uap
->sysmsg_result
= error
;
376 ncp_conn_frag_rq(struct ncp_conn
*conn
, struct thread
*td
, struct ncp_conn_frag
*nfp
){
377 int error
= 0, i
, rpsize
;
383 KKASSERT(td
->td_proc
);
384 cred
= td
->td_proc
->p_ucred
;
386 ncp_rq_head(rqp
,NCP_REQUEST
,nfp
->fn
,td
,cred
);
388 for(fp
= nfp
->rqf
, i
= 0; i
< nfp
->rqfcnt
; i
++, fp
++) {
389 checkbad(ncp_rq_usermem(rqp
,(caddr_t
)fp
->fragAddress
, fp
->fragSize
));
392 checkbad(ncp_request(conn
, rqp
));
393 rpsize
= rqp
->rpsize
;
394 if (rpsize
&& nfp
->rpfcnt
) {
395 for(fp
= nfp
->rpf
, i
= 0; i
< nfp
->rpfcnt
; i
++, fp
++) {
396 checkbad(copyin(&fp
->fragSize
, &fsize
, sizeof (fsize
)));
397 fsize
= min(fsize
, rpsize
);
398 checkbad(ncp_rp_usermem(rqp
,(caddr_t
)fp
->fragAddress
, fsize
));
400 checkbad(copyout(&fsize
, &fp
->fragSize
, sizeof (fsize
)));
410 * Internal functions, here should be all calls that do not require connection.
411 * To simplify possible future movement to cdev, we use IOCTL macros.
412 * Pretty much of this stolen from ioctl() function.
414 struct sncp_intfn_args
{
415 struct sysmsg sysmsg
;
421 sncp_intfn(struct sncp_intfn_args
*uap
)
426 * define our new system calls
428 static struct sysent newent
[] = {
429 {2, (sy_call_t
*)sncp_conn_scan
},
430 {2, (sy_call_t
*)sncp_connect
},
431 {2, (sy_call_t
*)sncp_intfn
},
432 {3, (sy_call_t
*)sncp_request
}
435 #define SC_SIZE sizeof(newent)/sizeof(struct sysent)
437 * Miscellaneous modules must have their own save areas...
439 static struct sysent oldent
[SC_SIZE
]; /* save are for old callslot entry*/
442 * Number of syscall entries for a.out executables
444 /*#define nsysent SYS_MAXSYSCALL*/
445 #define nsysent (aout_sysvec.sv_size)
450 int i
, ff
, scnt
, err
=0;
453 /* Search the table looking for an enough number of slots... */
454 for (scnt
=0, ff
= -1, i
= 0; i
< nsysent
; i
++) {
455 if (sysent
[i
].sy_call
== (sy_call_t
*)sys_lkmnosys
) {
461 if (scnt
== SC_SIZE
) break;
467 /* out of allocable slots?*/
468 if(i
== nsysent
|| ff
== -1) {
474 bcopy(&sysent
[ff
], &oldent
, sizeof(struct sysent
)*SC_SIZE
);
475 bcopy(&newent
, &sysent
[ff
], sizeof(struct sysent
)*SC_SIZE
);
476 ncp_sysent
= ff
; /* slot in sysent[]*/
477 kprintf("ncp_load: [%d-%d]\n",ff
,i
);
487 bcopy(&oldent
, &sysent
[ncp_sysent
], sizeof(struct sysent
) * SC_SIZE
);
488 kprintf( "ncp_unload: unloaded\n");
493 ncp_mod_handler(module_t mod
, int type
, void *data
)
502 error
= ncp_unload();
510 static moduledata_t ncp_mod
= {
515 DECLARE_MODULE(ncp
, ncp_mod
, SI_SUB_PROTO_DOMAIN
, SI_ORDER_ANY
);