proc->thread stage 4: rework the VFS and DEVICE subsystems to take thread
[dragonfly.git] / sys / netproto / ncp / ncp_rq.c
... / ...
CommitLineData
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 * Routines to prepare request and fetch reply
33 *
34 * $FreeBSD: src/sys/netncp/ncp_rq.c,v 1.1.2.1 2001/05/21 16:27:20 ru Exp $
35 * $DragonFly: src/sys/netproto/ncp/ncp_rq.c,v 1.3 2003/06/25 03:56:05 dillon Exp $
36 */
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/errno.h>
40#include <sys/mbuf.h>
41#include <sys/uio.h>
42
43#include <netncp/ncp.h>
44#include <netncp/ncp_conn.h>
45#include <netncp/ncp_rq.h>
46#include <netncp/ncp_subr.h>
47#include <netncp/ncp_ncp.h>
48#include <netncp/ncp_nls.h>
49
50int
51ncp_rq_head(struct ncp_rq *rqp, u_int32_t ptype, u_int8_t fn,struct thread *td,
52 struct ucred *cred)
53{
54 struct mbuf *m;
55 struct ncp_rqhdr *rq;
56 struct ncp_bursthdr *brq;
57 caddr_t pstart;
58
59 bzero(rqp, sizeof(*rqp));
60 rqp->td = td;
61 rqp->cred = cred;
62 m = m_gethdr(M_WAIT, MT_DATA);
63 if (m == NULL)
64 return ENOBUFS; /* if M_WAIT ? */
65 m->m_pkthdr.rcvif = NULL;
66 rqp->rq = rqp->mrq = m;
67 rqp->rp = NULL;
68 switch(ptype) {
69 case NCP_PACKET_BURST:
70 MH_ALIGN(m, sizeof(*brq) + 24);
71 m->m_len = sizeof(*brq);
72 brq = mtod(m, struct ncp_bursthdr *);
73 brq->bh_type = ptype;
74 brq->bh_streamtype = 0x2;
75 pstart = (caddr_t)brq;
76 break;
77 default:
78 MH_ALIGN(m, sizeof(*rq) + 2); /* possible len field in some functions */
79 m->m_len = sizeof(*rq);
80 rq = mtod(m, struct ncp_rqhdr *);
81 rq->type = ptype;
82 rq->seq = 0; /* filled later */
83 rq->fn = fn;
84 pstart = (caddr_t)rq;
85 break;
86 }
87 rqp->bpos = pstart + m->m_len;
88 return 0;
89}
90
91int
92ncp_rq_done(struct ncp_rq *rqp) {
93 m_freem(rqp->rq);
94 rqp->rq=NULL;
95 if (rqp->rp) m_freem(rqp->rp);
96 rqp->rp=NULL;
97 return (0);
98}
99
100/*
101 * Routines to fill the request
102 */
103static caddr_t ncp_mchecksize(struct ncp_rq *rqp, int size);
104#define NCP_RQADD(t) ((t*)(ncp_mchecksize(rqp,sizeof(t))))
105
106caddr_t
107ncp_mchecksize(struct ncp_rq *rqp, int size) {
108 caddr_t bpos1;
109
110 if (size>MLEN)
111 panic("ncp_mchecksize\n");
112 if (M_TRAILINGSPACE(rqp->mrq)<(size)) {
113 struct mbuf *m;
114 m = m_get(M_WAIT, MT_DATA);
115 m->m_len = 0;
116 rqp->bpos = mtod(m, caddr_t);
117 rqp->mrq->m_next = m;
118 rqp->mrq = m;
119 }
120 rqp->mrq->m_len += size;
121 bpos1 = rqp->bpos;
122 rqp->bpos += size;
123 return bpos1;
124}
125
126void
127ncp_rq_byte(struct ncp_rq *rqp,u_int8_t x) {
128 *NCP_RQADD(u_int8_t)=x;
129}
130
131void
132ncp_rq_word_hl(struct ncp_rq *rqp, u_int16_t x) {
133 setwbe(NCP_RQADD(u_int16_t), 0, x);
134}
135
136void
137ncp_rq_word_lh(struct ncp_rq *rqp, u_int16_t x) {
138 setwle(NCP_RQADD(u_int16_t), 0, x);
139}
140
141void
142ncp_rq_dword_lh(struct ncp_rq *rqp, u_int32_t x) {
143 setdle(NCP_RQADD(u_int32_t), 0, x);
144}
145
146void
147ncp_rq_pathstring(struct ncp_rq *rqp, int size, char *name, struct ncp_nlstables *nt) {
148 struct mbuf *m;
149 int cplen;
150
151 ncp_rq_byte(rqp, size);
152 m = rqp->mrq;
153 cplen = min(size, M_TRAILINGSPACE(m));
154 if (cplen) {
155 ncp_pathcopy(name, rqp->bpos, cplen, nt);
156 size -= cplen;
157 name += cplen;
158 m->m_len += cplen;
159 }
160 if (size) {
161 m = m_getm(m, size, MT_DATA, M_WAIT);
162 while (size > 0){
163 m = m->m_next;
164 cplen = min(size, M_TRAILINGSPACE(m));
165 ncp_pathcopy(name, mtod(m, caddr_t) + m->m_len, cplen, nt);
166 size -= cplen;
167 name += cplen;
168 m->m_len += cplen;
169 }
170 }
171 rqp->bpos = mtod(m,caddr_t) + m->m_len;
172 rqp->mrq = m;
173 return;
174}
175
176int
177ncp_rq_putanymem(struct ncp_rq *rqp, caddr_t source, int size, int type) {
178 struct mbuf *m;
179 int cplen, error;
180
181 m = rqp->mrq;
182 cplen = min(size, M_TRAILINGSPACE(m));
183 if (cplen) {
184 if (type==1) {
185 error = copyin(source, rqp->bpos, cplen);
186 if (error) return error;
187 } else
188 bcopy(source, rqp->bpos, cplen);
189 size -= cplen;
190 source += cplen;
191 m->m_len += cplen;
192 }
193 if (size) {
194 m = m_getm(m, size, MT_DATA, M_WAIT);
195 while (size > 0){
196 m = m->m_next;
197 cplen = min(size, M_TRAILINGSPACE(m));
198 if (type==1) {
199 error = copyin(source, mtod(m, caddr_t) + m->m_len, cplen);
200 if (error) return error;
201 } else
202 bcopy(source, mtod(m, caddr_t) + m->m_len, cplen);
203 size -= cplen;
204 source += cplen;
205 m->m_len += cplen;
206 }
207 }
208 rqp->bpos = mtod(m,caddr_t) + m->m_len;
209 rqp->mrq = m;
210 return 0;
211}
212
213int
214ncp_rq_mbuf(struct ncp_rq *rqp, struct mbuf *m, int size) {
215
216 rqp->mrq->m_next = m;
217 m->m_next = NULL;
218 if (size != M_COPYALL) m->m_len = size;
219 rqp->bpos = mtod(m,caddr_t) + m->m_len;
220 rqp->mrq = m;
221 return 0;
222}
223
224void
225ncp_rq_pstring(struct ncp_rq *rqp, char *s) {
226 int len = strlen(s);
227 if (len > 255) {
228 nwfs_printf("string too long: %s\n", s);
229 len = 255;
230 }
231 ncp_rq_byte(rqp, len);
232 ncp_rq_mem(rqp, s, len);
233 return;
234}
235
236void
237ncp_rq_dbase_path(struct ncp_rq *rqp, u_int8_t vol_num, u_int32_t dir_base,
238 int namelen, u_char *path, struct ncp_nlstables *nt)
239{
240 int complen;
241
242 ncp_rq_byte(rqp, vol_num);
243 ncp_rq_dword(rqp, dir_base);
244 ncp_rq_byte(rqp, 1); /* with dirbase */
245 if (path != NULL && path[0]) {
246 if (namelen < 0) {
247 namelen = *path++;
248 ncp_rq_byte(rqp, namelen);
249 for(; namelen; namelen--) {
250 complen = *path++;
251 ncp_rq_byte(rqp, complen);
252 ncp_rq_mem(rqp, path, complen);
253 path += complen;
254 }
255 } else {
256 ncp_rq_byte(rqp, 1); /* 1 component */
257 ncp_rq_pathstring(rqp, namelen, path, nt);
258 }
259 } else {
260 ncp_rq_byte(rqp, 0);
261 ncp_rq_byte(rqp, 0);
262 }
263}
264/*
265 * fetch reply routines
266 */
267#define ncp_mspaceleft (mtod(rqp->mrp,caddr_t)+rqp->mrp->m_len-rqp->bpos)
268
269u_int8_t
270ncp_rp_byte(struct ncp_rq *rqp) {
271 if (rqp->mrp == NULL) return 0;
272 if (ncp_mspaceleft < 1) {
273 rqp->mrp = rqp->mrp->m_next;
274 if (rqp->mrp == NULL) return 0;
275 rqp->bpos = mtod(rqp->mrp, caddr_t);
276 }
277 rqp->bpos += 1;
278 return rqp->bpos[-1];
279}
280
281u_int16_t
282ncp_rp_word_lh(struct ncp_rq *rqp) {
283 caddr_t prev = rqp->bpos;
284 u_int16_t t;
285
286 if (rqp->mrp == NULL) return 0;
287 if (ncp_mspaceleft >= 2) {
288 rqp->bpos += 2;
289 return getwle(prev,0);
290 }
291 t = *((u_int8_t*)(rqp->bpos));
292 rqp->mrp = rqp->mrp->m_next;
293 if (rqp->mrp == NULL) return 0;
294 ((u_int8_t *)&t)[1] = *((u_int8_t*)(rqp->bpos = mtod(rqp->mrp, caddr_t)));
295 rqp->bpos += 2;
296 return t;
297}
298
299u_int16_t
300ncp_rp_word_hl(struct ncp_rq *rqp) {
301 return (ntohs(ncp_rp_word_lh(rqp)));
302}
303
304u_int32_t
305ncp_rp_dword_hl(struct ncp_rq *rqp) {
306 int togo, rest;
307 caddr_t prev = rqp->bpos;
308 u_int32_t t;
309
310 if (rqp->mrp == NULL) return 0;
311 rest = ncp_mspaceleft;
312 if (rest >= 4) {
313 rqp->bpos += 4;
314 return getdbe(prev,0);
315 }
316 togo = 0;
317 while (rest--) {
318 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
319 }
320 rqp->mrp = rqp->mrp->m_next;
321 if (rqp->mrp == NULL) return 0;
322 prev = mtod(rqp->mrp, caddr_t);
323 rqp->bpos = prev + 4 - togo; /* XXX possible low than togo bytes in next mbuf */
324 while (togo < 4) {
325 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
326 }
327 return getdbe(&t,0);
328}
329
330u_int32_t
331ncp_rp_dword_lh(struct ncp_rq *rqp) {
332 int rest, togo;
333 caddr_t prev = rqp->bpos;
334 u_int32_t t;
335
336 if (rqp->mrp == NULL) return 0;
337 rest = ncp_mspaceleft;
338 if (rest >= 4) {
339 rqp->bpos += 4;
340 return getdle(prev,0);
341 }
342 togo = 0;
343 while (rest--) {
344 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
345 }
346 rqp->mrp = rqp->mrp->m_next;
347 if (rqp->mrp == NULL) return 0;
348 prev = mtod(rqp->mrp, caddr_t);
349 rqp->bpos = prev + 4 - togo; /* XXX possible low than togo bytes in next mbuf */
350 while (togo < 4) {
351 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
352 }
353 return getdle(&t,0);
354}
355void
356ncp_rp_mem(struct ncp_rq *rqp,caddr_t target, int size) {
357 register struct mbuf *m=rqp->mrp;
358 register unsigned count;
359
360 while (size > 0) {
361 if (m==0) { /* should be panic */
362 printf("ncp_rp_mem: incomplete copy\n");
363 return;
364 }
365 count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
366 if (count == 0) {
367 m=m->m_next;
368 rqp->bpos=mtod(m,caddr_t);
369 continue;
370 }
371 count = min(count,size);
372 bcopy(rqp->bpos, target, count);
373 size -= count;
374 target += count;
375 rqp->bpos += count;
376 }
377 rqp->mrp=m;
378 return;
379}
380
381int
382ncp_rp_usermem(struct ncp_rq *rqp,caddr_t target, int size) {
383 register struct mbuf *m=rqp->mrp;
384 register unsigned count;
385 int error;
386
387 while (size>0) {
388 if (m==0) { /* should be panic */
389 printf("ncp_rp_mem: incomplete copy\n");
390 return EFAULT;
391 }
392 count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
393 if (count == 0) {
394 m=m->m_next;
395 rqp->bpos=mtod(m,caddr_t);
396 continue;
397 }
398 count = min(count,size);
399 error=copyout(rqp->bpos, target, count);
400 if (error) return error;
401 size -= count;
402 target += count;
403 rqp->bpos += count;
404 }
405 rqp->mrp=m;
406 return 0;
407}
408
409struct mbuf*
410ncp_rp_mbuf(struct ncp_rq *rqp, int size) {
411 register struct mbuf *m=rqp->mrp, *rm;
412 register unsigned count;
413
414 rm = m_copym(m, rqp->bpos - mtod(m,caddr_t), size, M_WAIT);
415 while (size > 0) {
416 if (m == 0) {
417 printf("ncp_rp_mbuf: can't advance\n");
418 return rm;
419 }
420 count = mtod(m,caddr_t)+ m->m_len - rqp->bpos;
421 if (count == 0) {
422 m = m->m_next;
423 rqp->bpos = mtod(m, caddr_t);
424 continue;
425 }
426 count = min(count, size);
427 size -= count;
428 rqp->bpos += count;
429 }
430 rqp->mrp=m;
431 return rm;
432}
433
434int
435nwfs_mbuftouio(mrep, uiop, siz, dpos)
436 struct mbuf **mrep;
437 register struct uio *uiop;
438 int siz;
439 caddr_t *dpos;
440{
441 register char *mbufcp, *uiocp;
442 register int xfer, left, len;
443 register struct mbuf *mp;
444 long uiosiz;
445 int error = 0;
446
447 mp = *mrep;
448 if (!mp) return 0;
449 mbufcp = *dpos;
450 len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
451 while (siz > 0) {
452 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
453 return (EFBIG);
454 left = uiop->uio_iov->iov_len;
455 uiocp = uiop->uio_iov->iov_base;
456 if (left > siz)
457 left = siz;
458 uiosiz = left;
459 while (left > 0) {
460 while (len == 0) {
461 mp = mp->m_next;
462 if (mp == NULL)
463 return (EBADRPC);
464 mbufcp = mtod(mp, caddr_t);
465 len = mp->m_len;
466 }
467 xfer = (left > len) ? len : left;
468#ifdef notdef
469 /* Not Yet.. */
470 if (uiop->uio_iov->iov_op != NULL)
471 (*(uiop->uio_iov->iov_op))
472 (mbufcp, uiocp, xfer);
473 else
474#endif
475 if (uiop->uio_segflg == UIO_SYSSPACE)
476 bcopy(mbufcp, uiocp, xfer);
477 else
478 copyout(mbufcp, uiocp, xfer);
479 left -= xfer;
480 len -= xfer;
481 mbufcp += xfer;
482 uiocp += xfer;
483 uiop->uio_offset += xfer;
484 uiop->uio_resid -= xfer;
485 }
486 if (uiop->uio_iov->iov_len <= siz) {
487 uiop->uio_iovcnt--;
488 uiop->uio_iov++;
489 } else {
490 uiop->uio_iov->iov_base += uiosiz;
491 uiop->uio_iov->iov_len -= uiosiz;
492 }
493 siz -= uiosiz;
494 }
495 *dpos = mbufcp;
496 *mrep = mp;
497 return (error);
498}
499/*
500 * copies a uio scatter/gather list to an mbuf chain.
501 * NOTE: can ony handle iovcnt == 1
502 */
503int
504nwfs_uiotombuf(uiop, mq, siz, bpos)
505 register struct uio *uiop;
506 struct mbuf **mq;
507 int siz;
508 caddr_t *bpos;
509{
510 register char *uiocp;
511 register struct mbuf *mp, *mp2;
512 register int xfer, left, mlen;
513 int uiosiz, clflg;
514
515#ifdef DIAGNOSTIC
516 if (uiop->uio_iovcnt != 1)
517 panic("nfsm_uiotombuf: iovcnt != 1");
518#endif
519
520 if (siz > MLEN) /* or should it >= MCLBYTES ?? */
521 clflg = 1;
522 else
523 clflg = 0;
524 mp = mp2 = *mq;
525 while (siz > 0) {
526 left = uiop->uio_iov->iov_len;
527 uiocp = uiop->uio_iov->iov_base;
528 if (left > siz)
529 left = siz;
530 uiosiz = left;
531 while (left > 0) {
532 mlen = M_TRAILINGSPACE(mp);
533 if (mlen == 0) {
534 MGET(mp, M_WAIT, MT_DATA);
535 if (clflg)
536 MCLGET(mp, M_WAIT);
537 mp->m_len = 0;
538 mp2->m_next = mp;
539 mp2 = mp;
540 mlen = M_TRAILINGSPACE(mp);
541 }
542 xfer = (left > mlen) ? mlen : left;
543#ifdef notdef
544 /* Not Yet.. */
545 if (uiop->uio_iov->iov_op != NULL)
546 (*(uiop->uio_iov->iov_op))
547 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
548 else
549#endif
550 if (uiop->uio_segflg == UIO_SYSSPACE)
551 bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
552 else
553 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
554 mp->m_len += xfer;
555 left -= xfer;
556 uiocp += xfer;
557 uiop->uio_offset += xfer;
558 uiop->uio_resid -= xfer;
559 }
560 uiop->uio_iov->iov_base += uiosiz;
561 uiop->uio_iov->iov_len -= uiosiz;
562 siz -= uiosiz;
563 }
564 *bpos = mtod(mp, caddr_t)+mp->m_len;
565 *mq = mp;
566 return (0);
567}