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