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