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>
46 #include <sys/mplock2.h>
56 int ncp_version
= NCP_VERSION
;
58 static int ncp_sysent
;
60 SYSCTL_NODE(_net
, OID_AUTO
, ncp
, CTLFLAG_RW
, NULL
, "NetWare requester");
61 SYSCTL_INT(_net_ncp
, OID_AUTO
, sysent
, CTLFLAG_RD
, &ncp_sysent
, 0, "");
62 SYSCTL_INT(_net_ncp
, OID_AUTO
, version
, CTLFLAG_RD
, &ncp_version
, 0, "");
65 ncp_conn_frag_rq(struct ncp_conn
*conn
, struct thread
*td
, struct ncp_conn_frag
*nfp
);
68 * Attach to NCP server
70 struct sncp_connect_args
{
72 struct ncp_conn_args
*li
;
80 sys_sncp_connect(struct sncp_connect_args
*uap
)
82 struct thread
*td
= curthread
;
83 int connHandle
= 0, error
;
84 struct ncp_conn
*conn
;
85 struct ncp_handle
*handle
;
86 struct ncp_conn_args li
;
89 KKASSERT(td
->td_proc
);
92 checkbad(copyin(uap
->li
,&li
,sizeof(li
)));
93 checkbad(copyout(&connHandle
,uap
->connHandle
,sizeof(connHandle
))); /* check before */
94 li
.password
= li
.user
= NULL
;
97 error
= ncp_conn_getattached(&li
, td
, cred
, NCPM_WRITE
| NCPM_EXECUTE
, &conn
);
99 error
= ncp_connect(&li
, td
, cred
, &conn
);
102 error
= ncp_conn_gethandle(conn
, td
, &handle
);
104 copyout(&handle
->nh_id
, uap
->connHandle
, sizeof(uap
->connHandle
));
105 ncp_conn_unlock(conn
,td
);
109 uap
->sysmsg_result
= error
;
113 struct sncp_request_args
{
114 struct sysmsg sysmsg
;
117 struct ncp_buf
*ncpbuf
;
120 static int ncp_conn_handler(struct thread
*td
, struct sncp_request_args
*uap
,
121 struct ncp_conn
*conn
, struct ncp_handle
*handle
);
127 sys_sncp_request(struct sncp_request_args
*uap
)
129 struct thread
*td
= curthread
;
130 int error
= 0, rqsize
;
131 struct ncp_conn
*conn
;
132 struct ncp_handle
*handle
;
141 error
= ncp_conn_findhandle(uap
->connHandle
,td
,&handle
);
144 conn
= handle
->nh_conn
;
145 if (uap
->fn
== NCP_CONN
) {
146 error
= ncp_conn_handler(td
, uap
, conn
, handle
);
149 error
= copyin(&uap
->ncpbuf
->rqsize
, &rqsize
, sizeof(int));
152 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_EXECUTE
);
155 ncp_rq_head(rqp
,NCP_REQUEST
,uap
->fn
,td
,cred
);
157 error
= ncp_rq_usermem(rqp
,(caddr_t
)uap
->ncpbuf
->packet
, rqsize
);
159 error
= ncp_request(conn
, rqp
);
160 if (error
== 0 && rqp
->rpsize
)
161 ncp_rp_usermem(rqp
, (caddr_t
)uap
->ncpbuf
->packet
,
163 copyout(&rqp
->cs
, &uap
->ncpbuf
->cs
, sizeof(rqp
->cs
));
164 copyout(&rqp
->cc
, &uap
->ncpbuf
->cc
, sizeof(rqp
->cc
));
165 copyout(&rqp
->rpsize
, &uap
->ncpbuf
->rpsize
, sizeof(rqp
->rpsize
));
168 ncp_conn_unlock(conn
,td
);
175 ncp_conn_handler(struct thread
*td
, struct sncp_request_args
*uap
,
176 struct ncp_conn
*conn
, struct ncp_handle
*hp
)
178 int error
=0, rqsize
, subfn
;
183 KKASSERT(td
->td_proc
);
186 error
= copyin(&uap
->ncpbuf
->rqsize
, &rqsize
, sizeof(int));
187 if (error
) return(error
);
189 pdata
= uap
->ncpbuf
->packet
;
190 subfn
= *(pdata
++) & 0xff;
193 case NCP_CONN_READ
: case NCP_CONN_WRITE
: {
198 if (rqsize
!= sizeof(rwrq
)) return (EBADRPC
);
199 error
= copyin(pdata
,&rwrq
,rqsize
);
200 if (error
) return (error
);
201 iov
.iov_base
= rwrq
.nrw_base
;
202 iov
.iov_len
= rwrq
.nrw_cnt
;
205 auio
.uio_offset
= rwrq
.nrw_offset
;
206 auio
.uio_resid
= rwrq
.nrw_cnt
;
207 auio
.uio_segflg
= UIO_USERSPACE
;
208 auio
.uio_rw
= (subfn
== NCP_CONN_READ
) ? UIO_READ
: UIO_WRITE
;
210 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_EXECUTE
);
211 if (error
) return(error
);
212 if (subfn
== NCP_CONN_READ
)
213 error
= ncp_read(conn
, &rwrq
.nrw_fh
, &auio
, cred
);
215 error
= ncp_write(conn
, &rwrq
.nrw_fh
, &auio
, cred
);
216 rwrq
.nrw_cnt
-= auio
.uio_resid
;
217 ncp_conn_unlock(conn
,td
);
218 uap
->sysmsg_result
= rwrq
.nrw_cnt
;
220 } /* case int_read/write */
221 case NCP_CONN_SETFLAGS
: {
222 u_int16_t mask
, flags
;
224 error
= copyin(pdata
,&mask
, sizeof(mask
));
225 if (error
) return error
;
226 pdata
+= sizeof(mask
);
227 error
= copyin(pdata
,&flags
,sizeof(flags
));
228 if (error
) return error
;
229 error
= ncp_conn_lock(conn
,td
,cred
,NCPM_WRITE
);
230 if (error
) return error
;
231 if (mask
& NCPFL_PERMANENT
) {
232 conn
->flags
&= ~NCPFL_PERMANENT
;
233 conn
->flags
|= (flags
& NCPFL_PERMANENT
);
235 if (mask
& NCPFL_PRIMARY
) {
236 error
= ncp_conn_setprimary(conn
, flags
& NCPFL_PRIMARY
);
238 ncp_conn_unlock(conn
,td
);
242 ncp_conn_unlock(conn
,td
);
245 case NCP_CONN_LOGIN
: {
246 struct ncp_conn_login la
;
248 if (rqsize
!= sizeof(la
)) return (EBADRPC
);
249 if ((error
= copyin(pdata
,&la
,rqsize
)) != 0) break;
250 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
| NCPM_WRITE
);
251 if (error
) return error
;
252 error
= ncp_login(conn
, la
.username
, la
.objtype
, la
.password
, td
, cred
);
253 ncp_conn_unlock(conn
, td
);
254 uap
->sysmsg_result
= error
;
257 case NCP_CONN_GETINFO
: {
258 struct ncp_conn_stat ncs
;
259 int len
= sizeof(ncs
);
261 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
262 if (error
) return error
;
263 ncp_conn_getinfo(conn
, &ncs
);
264 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
265 error
= copyout(&ncs
, &uap
->ncpbuf
->packet
, len
);
266 ncp_conn_unlock(conn
, td
);
269 case NCP_CONN_GETUSER
: {
272 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
273 if (error
) return error
;
274 len
= (conn
->li
.user
) ? strlen(conn
->li
.user
) + 1 : 0;
275 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
277 error
= copyout(conn
->li
.user
, &uap
->ncpbuf
->packet
, len
);
279 ncp_conn_unlock(conn
, td
);
282 case NCP_CONN_CONN2REF
: {
283 int len
= sizeof(int);
285 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
286 if (error
) return error
;
287 copyout(&len
, &uap
->ncpbuf
->rpsize
, sizeof(int));
289 error
= copyout(&conn
->nc_id
, &uap
->ncpbuf
->packet
, len
);
291 ncp_conn_unlock(conn
, td
);
294 case NCP_CONN_FRAG
: {
295 struct ncp_conn_frag nf
;
297 if (rqsize
!= sizeof(nf
)) return (EBADRPC
);
298 if ((error
= copyin(pdata
, &nf
, rqsize
)) != 0) break;
299 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
);
300 if (error
) return error
;
301 error
= ncp_conn_frag_rq(conn
, td
, &nf
);
302 ncp_conn_unlock(conn
, td
);
303 copyout(&nf
, &pdata
, sizeof(nf
));
304 uap
->sysmsg_result
= error
;
308 struct ncp_handle
*newhp
;
309 int len
= sizeof(NWCONN_HANDLE
);
311 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_READ
);
313 copyout(&len
, &uap
->ncpbuf
->rpsize
, len
);
314 error
= ncp_conn_gethandle(conn
, td
, &newhp
);
316 error
= copyout(&newhp
->nh_id
, uap
->ncpbuf
->packet
, len
);
317 ncp_conn_unlock(conn
,td
);
320 case NCP_CONN_CONNCLOSE
: {
321 error
= ncp_conn_lock(conn
, td
, cred
, NCPM_EXECUTE
);
323 ncp_conn_puthandle(hp
, td
, 0);
324 error
= ncp_disconnect(conn
);
326 ncp_conn_unlock(conn
, td
);
335 struct sncp_conn_scan_args
{
336 struct sysmsg sysmsg
;
337 struct ncp_conn_args
*li
;
345 sys_sncp_conn_scan(struct thread
*td
, struct sncp_conn_scan_args
*uap
)
347 int connHandle
= 0, error
;
348 struct ncp_conn_args li
, *lip
;
349 struct ncp_conn
*conn
;
350 struct ncp_handle
*hp
;
351 char *user
= NULL
, *password
= NULL
;
354 KKASSERT(td
->td_proc
);
358 if (copyin(uap
->li
,&li
,sizeof(li
))) return EFAULT
;
365 lip
->server
[sizeof(lip
->server
)-1]=0; /* just to make sure */
366 ncp_str_upper(lip
->server
);
368 user
= ncp_str_dup(lip
->user
);
369 if (user
== NULL
) return EINVAL
;
373 password
= ncp_str_dup(lip
->password
);
374 if (password
== NULL
) {
376 kfree(user
, M_NCPDATA
);
379 ncp_str_upper(password
);
382 lip
->password
= password
;
386 error
= ncp_conn_getbyli(lip
,td
,cred
,NCPM_EXECUTE
,&conn
);
387 if (!error
) { /* already have this login */
388 ncp_conn_gethandle(conn
, td
, &hp
);
389 connHandle
= hp
->nh_id
;
390 ncp_conn_unlock(conn
,td
);
391 copyout(&connHandle
,uap
->connHandle
,sizeof(connHandle
));
394 if (user
) kfree(user
, M_NCPDATA
);
395 if (password
) kfree(password
, M_NCPDATA
);
396 uap
->sysmsg_result
= error
;
402 ncp_conn_frag_rq(struct ncp_conn
*conn
, struct thread
*td
, struct ncp_conn_frag
*nfp
){
403 int error
= 0, i
, rpsize
;
409 KKASSERT(td
->td_proc
);
412 ncp_rq_head(rqp
,NCP_REQUEST
,nfp
->fn
,td
,cred
);
414 for(fp
= nfp
->rqf
, i
= 0; i
< nfp
->rqfcnt
; i
++, fp
++) {
415 checkbad(ncp_rq_usermem(rqp
,(caddr_t
)fp
->fragAddress
, fp
->fragSize
));
418 checkbad(ncp_request(conn
, rqp
));
419 rpsize
= rqp
->rpsize
;
420 if (rpsize
&& nfp
->rpfcnt
) {
421 for(fp
= nfp
->rpf
, i
= 0; i
< nfp
->rpfcnt
; i
++, fp
++) {
422 checkbad(copyin(&fp
->fragSize
, &fsize
, sizeof (fsize
)));
423 fsize
= min(fsize
, rpsize
);
424 checkbad(ncp_rp_usermem(rqp
,(caddr_t
)fp
->fragAddress
, fsize
));
426 checkbad(copyout(&fsize
, &fp
->fragSize
, sizeof (fsize
)));
436 * Internal functions, here should be all calls that do not require connection.
437 * To simplify possible future movement to cdev, we use IOCTL macros.
438 * Pretty much of this stolen from ioctl() function.
440 struct sncp_intfn_args
{
441 struct sysmsg sysmsg
;
450 sys_sncp_intfn(struct sncp_intfn_args
*uap
)
455 * define our new system calls
457 static struct sysent newent
[] = {
458 {2, (sy_call_t
*)sys_sncp_conn_scan
},
459 {2, (sy_call_t
*)sys_sncp_connect
},
460 {2, (sy_call_t
*)sys_sncp_intfn
},
461 {3, (sy_call_t
*)sys_sncp_request
}
464 #define SC_SIZE sizeof(newent)/sizeof(struct sysent)
466 * Miscellaneous modules must have their own save areas...
468 static struct sysent oldent
[SC_SIZE
]; /* save are for old callslot entry*/
471 * Number of syscall entries for a.out executables
473 /*#define nsysent SYS_MAXSYSCALL*/
474 #define nsysent (aout_sysvec.sv_size)
479 int i
, ff
, scnt
, err
=0;
482 /* Search the table looking for an enough number of slots... */
483 for (scnt
=0, ff
= -1, i
= 0; i
< nsysent
; i
++) {
484 if (sysent
[i
].sy_call
== (sy_call_t
*)sys_lkmnosys
) {
490 if (scnt
== SC_SIZE
) break;
496 /* out of allocable slots?*/
497 if(i
== nsysent
|| ff
== -1) {
503 bcopy(&sysent
[ff
], &oldent
, sizeof(struct sysent
)*SC_SIZE
);
504 bcopy(&newent
, &sysent
[ff
], sizeof(struct sysent
)*SC_SIZE
);
505 ncp_sysent
= ff
; /* slot in sysent[]*/
506 kprintf("ncp_load: [%d-%d]\n",ff
,i
);
516 bcopy(&oldent
, &sysent
[ncp_sysent
], sizeof(struct sysent
) * SC_SIZE
);
517 kprintf( "ncp_unload: unloaded\n");
522 ncp_mod_handler(module_t mod
, int type
, void *data
)
531 error
= ncp_unload();
539 static moduledata_t ncp_mod
= {
544 DECLARE_MODULE(ncp
, ncp_mod
, SI_SUB_PROTO_DOMAIN
, SI_ORDER_ANY
);