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
;
78 sys_sncp_connect(struct sncp_connect_args
*uap
)
80 struct thread
*td
= curthread
;
81 int connHandle
= 0, error
;
82 struct ncp_conn
*conn
;
83 struct ncp_handle
*handle
;
84 struct ncp_conn_args li
;
87 KKASSERT(td
->td_proc
);
88 cred
= td
->td_proc
->p_ucred
;
90 checkbad(copyin(uap
->li
,&li
,sizeof(li
)));
91 checkbad(copyout(&connHandle
,uap
->connHandle
,sizeof(connHandle
))); /* check before */
92 li
.password
= li
.user
= NULL
;
95 error
= ncp_conn_getattached(&li
, td
, cred
, NCPM_WRITE
| NCPM_EXECUTE
, &conn
);
97 error
= ncp_connect(&li
, td
, cred
, &conn
);
100 error
= ncp_conn_gethandle(conn
, td
, &handle
);
102 copyout(&handle
->nh_id
, uap
->connHandle
, sizeof(uap
->connHandle
));
103 ncp_conn_unlock(conn
,td
);
107 uap
->sysmsg_result
= error
;
111 struct sncp_request_args
{
112 struct sysmsg sysmsg
;
115 struct ncp_buf
*ncpbuf
;
118 static int ncp_conn_handler(struct thread
*td
, struct sncp_request_args
*uap
,
119 struct ncp_conn
*conn
, struct ncp_handle
*handle
);
125 sys_sncp_request(struct sncp_request_args
*uap
)
127 struct thread
*td
= curthread
;
128 int error
= 0, rqsize
;
129 struct ncp_conn
*conn
;
130 struct ncp_handle
*handle
;
137 cred
= td
->td_proc
->p_ucred
;
139 error
= ncp_conn_findhandle(uap
->connHandle
,td
,&handle
);
142 conn
= handle
->nh_conn
;
143 if (uap
->fn
== NCP_CONN
) {
144 error
= ncp_conn_handler(td
, uap
, conn
, handle
);
147 error
= copyin(&uap
->ncpbuf
->rqsize
, &rqsize
, sizeof(int));
150 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_EXECUTE
);
153 ncp_rq_head(rqp
,NCP_REQUEST
,uap
->fn
,td
,cred
);
155 error
= ncp_rq_usermem(rqp
,(caddr_t
)uap
->ncpbuf
->packet
, rqsize
);
157 error
= ncp_request(conn
, rqp
);
158 if (error
== 0 && rqp
->rpsize
)
159 ncp_rp_usermem(rqp
, (caddr_t
)uap
->ncpbuf
->packet
,
161 copyout(&rqp
->cs
, &uap
->ncpbuf
->cs
, sizeof(rqp
->cs
));
162 copyout(&rqp
->cc
, &uap
->ncpbuf
->cc
, sizeof(rqp
->cc
));
163 copyout(&rqp
->rpsize
, &uap
->ncpbuf
->rpsize
, sizeof(rqp
->rpsize
));
166 ncp_conn_unlock(conn
,td
);
173 ncp_conn_handler(struct thread
*td
, struct sncp_request_args
*uap
,
174 struct ncp_conn
*conn
, struct ncp_handle
*hp
)
176 int error
=0, rqsize
, subfn
;
181 KKASSERT(td
->td_proc
);
182 cred
= td
->td_proc
->p_ucred
;
184 error
= copyin(&uap
->ncpbuf
->rqsize
, &rqsize
, sizeof(int));
185 if (error
) return(error
);
187 pdata
= uap
->ncpbuf
->packet
;
188 subfn
= *(pdata
++) & 0xff;
191 case NCP_CONN_READ
: case NCP_CONN_WRITE
: {
196 if (rqsize
!= sizeof(rwrq
)) return (EBADRPC
);
197 error
= copyin(pdata
,&rwrq
,rqsize
);
198 if (error
) return (error
);
199 iov
.iov_base
= rwrq
.nrw_base
;
200 iov
.iov_len
= rwrq
.nrw_cnt
;
203 auio
.uio_offset
= rwrq
.nrw_offset
;
204 auio
.uio_resid
= rwrq
.nrw_cnt
;
205 auio
.uio_segflg
= UIO_USERSPACE
;
206 auio
.uio_rw
= (subfn
== NCP_CONN_READ
) ? UIO_READ
: UIO_WRITE
;
208 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_EXECUTE
);
209 if (error
) return(error
);
210 if (subfn
== NCP_CONN_READ
)
211 error
= ncp_read(conn
, &rwrq
.nrw_fh
, &auio
, cred
);
213 error
= ncp_write(conn
, &rwrq
.nrw_fh
, &auio
, cred
);
214 rwrq
.nrw_cnt
-= auio
.uio_resid
;
215 ncp_conn_unlock(conn
,td
);
216 uap
->sysmsg_result
= rwrq
.nrw_cnt
;
218 } /* case int_read/write */
219 case NCP_CONN_SETFLAGS
: {
220 u_int16_t mask
, flags
;
222 error
= copyin(pdata
,&mask
, sizeof(mask
));
223 if (error
) return error
;
224 pdata
+= sizeof(mask
);
225 error
= copyin(pdata
,&flags
,sizeof(flags
));
226 if (error
) return error
;
227 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_WRITE
);
228 if (error
) return error
;
229 if (mask
& NCPFL_PERMANENT
) {
230 conn
->flags
&= ~NCPFL_PERMANENT
;
231 conn
->flags
|= (flags
& NCPFL_PERMANENT
);
233 if (mask
& NCPFL_PRIMARY
) {
234 error
= ncp_conn_setprimary(conn
, flags
& NCPFL_PRIMARY
);
236 ncp_conn_unlock(conn
,td
);
240 ncp_conn_unlock(conn
,td
);
243 case NCP_CONN_LOGIN
: {
244 struct ncp_conn_login la
;
246 if (rqsize
!= sizeof(la
)) return (EBADRPC
);
247 if ((error
= copyin(pdata
,&la
,rqsize
)) != 0) break;
248 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
| NCPM_WRITE
);
249 if (error
) return error
;
250 error
= ncp_login(conn
, la
.username
, la
.objtype
, la
.password
, td
, cred
);
251 ncp_conn_unlock(conn
, td
);
252 uap
->sysmsg_result
= error
;
255 case NCP_CONN_GETINFO
: {
256 struct ncp_conn_stat ncs
;
257 int len
= sizeof(ncs
);
259 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
260 if (error
) return error
;
261 ncp_conn_getinfo(conn
, &ncs
);
262 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
263 error
= copyout(&ncs
, &uap
->ncpbuf
->packet
, len
);
264 ncp_conn_unlock(conn
, td
);
267 case NCP_CONN_GETUSER
: {
270 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
271 if (error
) return error
;
272 len
= (conn
->li
.user
) ? strlen(conn
->li
.user
) + 1 : 0;
273 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
275 error
= copyout(conn
->li
.user
, &uap
->ncpbuf
->packet
, len
);
277 ncp_conn_unlock(conn
, td
);
280 case NCP_CONN_CONN2REF
: {
281 int len
= sizeof(int);
283 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
284 if (error
) return error
;
285 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
287 error
= copyout(&conn
->nc_id
, &uap
->ncpbuf
->packet
, len
);
289 ncp_conn_unlock(conn
, td
);
292 case NCP_CONN_FRAG
: {
293 struct ncp_conn_frag nf
;
295 if (rqsize
!= sizeof(nf
)) return (EBADRPC
);
296 if ((error
= copyin(pdata
, &nf
, rqsize
)) != 0) break;
297 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
);
298 if (error
) return error
;
299 error
= ncp_conn_frag_rq(conn
, td
, &nf
);
300 ncp_conn_unlock(conn
, td
);
301 copyout(&nf
, &pdata
, sizeof(nf
));
302 uap
->sysmsg_result
= error
;
306 struct ncp_handle
*newhp
;
307 int len
= sizeof(NWCONN_HANDLE
);
309 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
311 copyout(&len
, &uap
->ncpbuf
->rpsize
, len
);
312 error
= ncp_conn_gethandle(conn
, td
, &newhp
);
314 error
= copyout(&newhp
->nh_id
, uap
->ncpbuf
->packet
, len
);
315 ncp_conn_unlock(conn
,td
);
318 case NCP_CONN_CONNCLOSE
: {
319 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
);
321 ncp_conn_puthandle(hp
, td
, 0);
322 error
= ncp_disconnect(conn
);
324 ncp_conn_unlock(conn
, td
);
333 struct sncp_conn_scan_args
{
334 struct sysmsg sysmsg
;
335 struct ncp_conn_args
*li
;
343 sys_sncp_conn_scan(struct thread
*td
, struct sncp_conn_scan_args
*uap
)
345 int connHandle
= 0, error
;
346 struct ncp_conn_args li
, *lip
;
347 struct ncp_conn
*conn
;
348 struct ncp_handle
*hp
;
349 char *user
= NULL
, *password
= NULL
;
352 KKASSERT(td
->td_proc
);
353 cred
= td
->td_proc
->p_ucred
;
356 if (copyin(uap
->li
,&li
,sizeof(li
))) return EFAULT
;
363 lip
->server
[sizeof(lip
->server
)-1]=0; /* just to make sure */
364 ncp_str_upper(lip
->server
);
366 user
= ncp_str_dup(lip
->user
);
367 if (user
== NULL
) return EINVAL
;
371 password
= ncp_str_dup(lip
->password
);
372 if (password
== NULL
) {
374 kfree(user
, M_NCPDATA
);
377 ncp_str_upper(password
);
380 lip
->password
= password
;
384 error
= ncp_conn_getbyli(lip
,td
,cred
,NCPM_EXECUTE
,&conn
);
385 if (!error
) { /* already have this login */
386 ncp_conn_gethandle(conn
, td
, &hp
);
387 connHandle
= hp
->nh_id
;
388 ncp_conn_unlock(conn
,td
);
389 copyout(&connHandle
,uap
->connHandle
,sizeof(connHandle
));
392 if (user
) kfree(user
, M_NCPDATA
);
393 if (password
) kfree(password
, M_NCPDATA
);
394 uap
->sysmsg_result
= error
;
400 ncp_conn_frag_rq(struct ncp_conn
*conn
, struct thread
*td
, struct ncp_conn_frag
*nfp
){
401 int error
= 0, i
, rpsize
;
407 KKASSERT(td
->td_proc
);
408 cred
= td
->td_proc
->p_ucred
;
410 ncp_rq_head(rqp
,NCP_REQUEST
,nfp
->fn
,td
,cred
);
412 for(fp
= nfp
->rqf
, i
= 0; i
< nfp
->rqfcnt
; i
++, fp
++) {
413 checkbad(ncp_rq_usermem(rqp
,(caddr_t
)fp
->fragAddress
, fp
->fragSize
));
416 checkbad(ncp_request(conn
, rqp
));
417 rpsize
= rqp
->rpsize
;
418 if (rpsize
&& nfp
->rpfcnt
) {
419 for(fp
= nfp
->rpf
, i
= 0; i
< nfp
->rpfcnt
; i
++, fp
++) {
420 checkbad(copyin(&fp
->fragSize
, &fsize
, sizeof (fsize
)));
421 fsize
= min(fsize
, rpsize
);
422 checkbad(ncp_rp_usermem(rqp
,(caddr_t
)fp
->fragAddress
, fsize
));
424 checkbad(copyout(&fsize
, &fp
->fragSize
, sizeof (fsize
)));
434 * Internal functions, here should be all calls that do not require connection.
435 * To simplify possible future movement to cdev, we use IOCTL macros.
436 * Pretty much of this stolen from ioctl() function.
438 struct sncp_intfn_args
{
439 struct sysmsg sysmsg
;
448 sys_sncp_intfn(struct sncp_intfn_args
*uap
)
453 * define our new system calls
455 static struct sysent newent
[] = {
456 {2, (sy_call_t
*)sys_sncp_conn_scan
},
457 {2, (sy_call_t
*)sys_sncp_connect
},
458 {2, (sy_call_t
*)sys_sncp_intfn
},
459 {3, (sy_call_t
*)sys_sncp_request
}
462 #define SC_SIZE sizeof(newent)/sizeof(struct sysent)
464 * Miscellaneous modules must have their own save areas...
466 static struct sysent oldent
[SC_SIZE
]; /* save are for old callslot entry*/
469 * Number of syscall entries for a.out executables
471 /*#define nsysent SYS_MAXSYSCALL*/
472 #define nsysent (aout_sysvec.sv_size)
477 int i
, ff
, scnt
, err
=0;
480 /* Search the table looking for an enough number of slots... */
481 for (scnt
=0, ff
= -1, i
= 0; i
< nsysent
; i
++) {
482 if (sysent
[i
].sy_call
== (sy_call_t
*)sys_lkmnosys
) {
488 if (scnt
== SC_SIZE
) break;
494 /* out of allocable slots?*/
495 if(i
== nsysent
|| ff
== -1) {
501 bcopy(&sysent
[ff
], &oldent
, sizeof(struct sysent
)*SC_SIZE
);
502 bcopy(&newent
, &sysent
[ff
], sizeof(struct sysent
)*SC_SIZE
);
503 ncp_sysent
= ff
; /* slot in sysent[]*/
504 kprintf("ncp_load: [%d-%d]\n",ff
,i
);
514 bcopy(&oldent
, &sysent
[ncp_sysent
], sizeof(struct sysent
) * SC_SIZE
);
515 kprintf( "ncp_unload: unloaded\n");
520 ncp_mod_handler(module_t mod
, int type
, void *data
)
529 error
= ncp_unload();
537 static moduledata_t ncp_mod
= {
542 DECLARE_MODULE(ncp
, ncp_mod
, SI_SUB_PROTO_DOMAIN
, SI_ORDER_ANY
);