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 * Routines to prepare request and fetch reply
34 * $FreeBSD: src/sys/netncp/ncp_rq.c,v 1.1.2.1 2001/05/21 16:27:20 ru Exp $
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
50 ncp_rq_head(struct ncp_rq *rqp, u_int32_t ptype, u_int8_t fn,struct thread *td,
55 struct ncp_bursthdr *brq;
58 bzero(rqp, sizeof(*rqp));
61 m = m_gethdr(MB_WAIT, MT_DATA);
63 return ENOBUFS; /* if MB_WAIT ? */
64 m->m_pkthdr.rcvif = NULL;
65 rqp->rq = rqp->mrq = m;
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 *);
73 brq->bh_streamtype = 0x2;
74 pstart = (caddr_t)brq;
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 *);
81 rq->seq = 0; /* filled later */
86 rqp->bpos = pstart + m->m_len;
91 ncp_rq_done(struct ncp_rq *rqp) {
94 if (rqp->rp) m_freem(rqp->rp);
100 * Routines to fill the request
102 static caddr_t ncp_mchecksize(struct ncp_rq *rqp, int size);
103 #define NCP_RQADD(t) ((t*)(ncp_mchecksize(rqp,sizeof(t))))
106 ncp_mchecksize(struct ncp_rq *rqp, int size) {
110 panic("ncp_mchecksize\n");
111 if (M_TRAILINGSPACE(rqp->mrq)<(size)) {
113 m = m_get(MB_WAIT, MT_DATA);
115 rqp->bpos = mtod(m, caddr_t);
116 rqp->mrq->m_next = m;
119 rqp->mrq->m_len += size;
126 ncp_rq_byte(struct ncp_rq *rqp,u_int8_t x) {
127 *NCP_RQADD(u_int8_t)=x;
131 ncp_rq_word_hl(struct ncp_rq *rqp, u_int16_t x) {
132 setwbe(NCP_RQADD(u_int16_t), 0, x);
136 ncp_rq_word_lh(struct ncp_rq *rqp, u_int16_t x) {
137 setwle(NCP_RQADD(u_int16_t), 0, x);
141 ncp_rq_dword_lh(struct ncp_rq *rqp, u_int32_t x) {
142 setdle(NCP_RQADD(u_int32_t), 0, x);
146 ncp_rq_pathstring(struct ncp_rq *rqp, int size, char *name, struct ncp_nlstables *nt) {
150 ncp_rq_byte(rqp, size);
152 cplen = min(size, M_TRAILINGSPACE(m));
154 ncp_pathcopy(name, rqp->bpos, cplen, nt);
160 m_getm(m, size, MT_DATA, MB_WAIT);
163 cplen = min(size, M_TRAILINGSPACE(m));
164 ncp_pathcopy(name, mtod(m, caddr_t) + m->m_len, cplen, nt);
170 rqp->bpos = mtod(m,caddr_t) + m->m_len;
176 ncp_rq_putanymem(struct ncp_rq *rqp, caddr_t source, int size, int type) {
181 cplen = min(size, M_TRAILINGSPACE(m));
184 error = copyin(source, rqp->bpos, cplen);
185 if (error) return error;
187 bcopy(source, rqp->bpos, cplen);
193 m_getm(m, size, MT_DATA, MB_WAIT);
196 cplen = min(size, M_TRAILINGSPACE(m));
198 error = copyin(source, mtod(m, caddr_t) + m->m_len, cplen);
199 if (error) return error;
201 bcopy(source, mtod(m, caddr_t) + m->m_len, cplen);
207 rqp->bpos = mtod(m,caddr_t) + m->m_len;
213 ncp_rq_mbuf(struct ncp_rq *rqp, struct mbuf *m, int size) {
215 rqp->mrq->m_next = m;
217 if (size != M_COPYALL) m->m_len = size;
218 rqp->bpos = mtod(m,caddr_t) + m->m_len;
224 ncp_rq_pstring(struct ncp_rq *rqp, char *s) {
227 nwfs_printf("string too long: %s\n", s);
230 ncp_rq_byte(rqp, len);
231 ncp_rq_mem(rqp, s, len);
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)
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]) {
247 ncp_rq_byte(rqp, namelen);
248 for(; namelen; namelen--) {
250 ncp_rq_byte(rqp, complen);
251 ncp_rq_mem(rqp, path, complen);
255 ncp_rq_byte(rqp, 1); /* 1 component */
256 ncp_rq_pathstring(rqp, namelen, path, nt);
264 * fetch reply routines
266 #define ncp_mspaceleft (mtod(rqp->mrp,caddr_t)+rqp->mrp->m_len-rqp->bpos)
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);
277 return rqp->bpos[-1];
281 ncp_rp_word_lh(struct ncp_rq *rqp) {
282 caddr_t prev = rqp->bpos;
285 if (rqp->mrp == NULL) return 0;
286 if (ncp_mspaceleft >= 2) {
288 return getwle(prev,0);
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)));
299 ncp_rp_word_hl(struct ncp_rq *rqp) {
300 return (ntohs(ncp_rp_word_lh(rqp)));
304 ncp_rp_dword_hl(struct ncp_rq *rqp) {
306 caddr_t prev = rqp->bpos;
309 if (rqp->mrp == NULL) return 0;
310 rest = ncp_mspaceleft;
313 return getdbe(prev,0);
317 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
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 */
324 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
330 ncp_rp_dword_lh(struct ncp_rq *rqp) {
332 caddr_t prev = rqp->bpos;
335 if (rqp->mrp == NULL) return 0;
336 rest = ncp_mspaceleft;
339 return getdle(prev,0);
343 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
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 */
350 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
355 ncp_rp_mem(struct ncp_rq *rqp,caddr_t target, int size) {
356 struct mbuf *m=rqp->mrp;
360 if (m==NULL) { /* should be panic */
361 kprintf("ncp_rp_mem: incomplete copy\n");
364 count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
367 rqp->bpos=mtod(m,caddr_t);
370 count = min(count,size);
371 bcopy(rqp->bpos, target, count);
381 ncp_rp_usermem(struct ncp_rq *rqp,caddr_t target, int size) {
382 struct mbuf *m=rqp->mrp;
387 if (m==NULL) { /* should be panic */
388 kprintf("ncp_rp_mem: incomplete copy\n");
391 count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
394 rqp->bpos=mtod(m,caddr_t);
397 count = min(count,size);
398 error=copyout(rqp->bpos, target, count);
399 if (error) return error;
409 ncp_rp_mbuf(struct ncp_rq *rqp, int size) {
410 struct mbuf *m=rqp->mrp, *rm;
413 rm = m_copym(m, rqp->bpos - mtod(m,caddr_t), size, MB_WAIT);
416 kprintf("ncp_rp_mbuf: can't advance\n");
419 count = mtod(m,caddr_t)+ m->m_len - rqp->bpos;
422 rqp->bpos = mtod(m, caddr_t);
425 count = min(count, size);
434 nwfs_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
436 char *mbufcp, *uiocp;
445 len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
447 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
449 left = uiop->uio_iov->iov_len;
450 uiocp = uiop->uio_iov->iov_base;
459 mbufcp = mtod(mp, caddr_t);
462 xfer = (left > len) ? len : left;
465 if (uiop->uio_iov->iov_op != NULL)
466 (*(uiop->uio_iov->iov_op))
467 (mbufcp, uiocp, xfer);
470 if (uiop->uio_segflg == UIO_SYSSPACE)
471 bcopy(mbufcp, uiocp, xfer);
473 copyout(mbufcp, uiocp, xfer);
478 uiop->uio_offset += xfer;
479 uiop->uio_resid -= xfer;
481 if (uiop->uio_iov->iov_len <= siz) {
485 uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + uiosiz;
486 uiop->uio_iov->iov_len -= uiosiz;
495 * copies a uio scatter/gather list to an mbuf chain.
496 * NOTE: can ony handle iovcnt == 1
499 nwfs_uiotombuf(struct uio *uiop, struct mbuf **mq, int siz, caddr_t *bpos)
502 struct mbuf *mp, *mp2;
503 int xfer, left, mlen;
507 if (uiop->uio_iovcnt != 1)
508 panic("nfsm_uiotombuf: iovcnt != 1");
511 if (siz > MLEN) /* or should it >= MCLBYTES ?? */
517 left = uiop->uio_iov->iov_len;
518 uiocp = uiop->uio_iov->iov_base;
523 mlen = M_TRAILINGSPACE(mp);
525 MGET(mp, MB_WAIT, MT_DATA);
531 mlen = M_TRAILINGSPACE(mp);
533 xfer = (left > mlen) ? mlen : left;
536 if (uiop->uio_iov->iov_op != NULL)
537 (*(uiop->uio_iov->iov_op))
538 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
541 if (uiop->uio_segflg == UIO_SYSSPACE)
542 bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
544 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
548 uiop->uio_offset += xfer;
549 uiop->uio_resid -= xfer;
551 uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + uiosiz;
552 uiop->uio_iov->iov_len -= uiosiz;
555 *bpos = mtod(mp, caddr_t)+mp->m_len;