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
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/errno.h>
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>
49 static struct mbuf* m_getm(struct mbuf *top, int len);
52 ncp_rq_head(struct ncp_rq *rqp, u_int32_t ptype, u_int8_t fn,struct proc *p,
57 struct ncp_bursthdr *brq;
60 bzero(rqp, sizeof(*rqp));
63 m = m_gethdr(M_WAIT, MT_DATA);
65 return ENOBUFS; /* if M_WAIT ? */
66 m->m_pkthdr.rcvif = NULL;
67 rqp->rq = rqp->mrq = m;
70 case NCP_PACKET_BURST:
71 MH_ALIGN(m, sizeof(*brq) + 24);
72 m->m_len = sizeof(*brq);
73 brq = mtod(m, struct ncp_bursthdr *);
75 brq->bh_streamtype = 0x2;
76 pstart = (caddr_t)brq;
79 MH_ALIGN(m, sizeof(*rq) + 2); /* possible len field in some functions */
80 m->m_len = sizeof(*rq);
81 rq = mtod(m, struct ncp_rqhdr *);
83 rq->seq = 0; /* filled later */
88 rqp->bpos = pstart + m->m_len;
93 ncp_rq_done(struct ncp_rq *rqp) {
96 if (rqp->rp) m_freem(rqp->rp);
102 m_getm(struct mbuf *top, int len) {
103 int rest = len, mlen;
104 struct mbuf *m=0,*mp;
108 /* NCPSDEBUG("%d\n",rest);*/
109 m = m_get(M_WAIT, MT_DATA);
110 if (rest > MINCLSIZE) {
112 mlen = ( (m->m_flags & M_EXT) == 0) ? MLEN : MCLBYTES;
116 m->m_len = 0/*min(mlen,rest)*/;
125 * Routines to fill the request
127 static caddr_t ncp_mchecksize(struct ncp_rq *rqp, int size);
128 #define NCP_RQADD(t) ((t*)(ncp_mchecksize(rqp,sizeof(t))))
131 ncp_mchecksize(struct ncp_rq *rqp, int size) {
135 panic("ncp_mchecksize\n");
136 if (M_TRAILINGSPACE(rqp->mrq)<(size)) {
138 m = m_get(M_WAIT, MT_DATA);
140 rqp->bpos = mtod(m, caddr_t);
141 rqp->mrq->m_next = m;
144 rqp->mrq->m_len += size;
151 ncp_rq_byte(struct ncp_rq *rqp,u_int8_t x) {
152 *NCP_RQADD(u_int8_t)=x;
156 ncp_rq_word_hl(struct ncp_rq *rqp, u_int16_t x) {
157 setwbe(NCP_RQADD(u_int16_t), 0, x);
161 ncp_rq_word_lh(struct ncp_rq *rqp, u_int16_t x) {
162 setwle(NCP_RQADD(u_int16_t), 0, x);
166 ncp_rq_dword_lh(struct ncp_rq *rqp, u_int32_t x) {
167 setdle(NCP_RQADD(u_int32_t), 0, x);
171 ncp_rq_pathstring(struct ncp_rq *rqp, int size, char *name, struct ncp_nlstables *nt) {
175 ncp_rq_byte(rqp, size);
177 cplen = min(size, M_TRAILINGSPACE(m));
179 ncp_pathcopy(name, rqp->bpos, cplen, nt);
188 cplen = min(size, M_TRAILINGSPACE(m));
189 ncp_pathcopy(name, mtod(m, caddr_t) + m->m_len, cplen, nt);
195 rqp->bpos = mtod(m,caddr_t) + m->m_len;
201 ncp_rq_putanymem(struct ncp_rq *rqp, caddr_t source, int size, int type) {
206 cplen = min(size, M_TRAILINGSPACE(m));
209 error = copyin(source, rqp->bpos, cplen);
210 if (error) return error;
212 bcopy(source, rqp->bpos, cplen);
221 cplen = min(size, M_TRAILINGSPACE(m));
223 error = copyin(source, mtod(m, caddr_t) + m->m_len, cplen);
224 if (error) return error;
226 bcopy(source, mtod(m, caddr_t) + m->m_len, cplen);
232 rqp->bpos = mtod(m,caddr_t) + m->m_len;
238 ncp_rq_mbuf(struct ncp_rq *rqp, struct mbuf *m, int size) {
240 rqp->mrq->m_next = m;
242 if (size != M_COPYALL) m->m_len = size;
243 rqp->bpos = mtod(m,caddr_t) + m->m_len;
249 ncp_rq_pstring(struct ncp_rq *rqp, char *s) {
252 nwfs_printf("string too long: %s\n", s);
255 ncp_rq_byte(rqp, len);
256 ncp_rq_mem(rqp, s, len);
261 ncp_rq_dbase_path(struct ncp_rq *rqp, u_int8_t vol_num, u_int32_t dir_base,
262 int namelen, u_char *path, struct ncp_nlstables *nt)
266 ncp_rq_byte(rqp, vol_num);
267 ncp_rq_dword(rqp, dir_base);
268 ncp_rq_byte(rqp, 1); /* with dirbase */
269 if (path != NULL && path[0]) {
272 ncp_rq_byte(rqp, namelen);
273 for(; namelen; namelen--) {
275 ncp_rq_byte(rqp, complen);
276 ncp_rq_mem(rqp, path, complen);
280 ncp_rq_byte(rqp, 1); /* 1 component */
281 ncp_rq_pathstring(rqp, namelen, path, nt);
289 * fetch reply routines
291 #define ncp_mspaceleft (mtod(rqp->mrp,caddr_t)+rqp->mrp->m_len-rqp->bpos)
294 ncp_rp_byte(struct ncp_rq *rqp) {
295 if (rqp->mrp == NULL) return 0;
296 if (ncp_mspaceleft < 1) {
297 rqp->mrp = rqp->mrp->m_next;
298 if (rqp->mrp == NULL) return 0;
299 rqp->bpos = mtod(rqp->mrp, caddr_t);
302 return rqp->bpos[-1];
306 ncp_rp_word_lh(struct ncp_rq *rqp) {
307 caddr_t prev = rqp->bpos;
310 if (rqp->mrp == NULL) return 0;
311 if (ncp_mspaceleft >= 2) {
313 return getwle(prev,0);
315 t = *((u_int8_t*)(rqp->bpos));
316 rqp->mrp = rqp->mrp->m_next;
317 if (rqp->mrp == NULL) return 0;
318 ((u_int8_t *)&t)[1] = *((u_int8_t*)(rqp->bpos = mtod(rqp->mrp, caddr_t)));
324 ncp_rp_word_hl(struct ncp_rq *rqp) {
325 return (ntohs(ncp_rp_word_lh(rqp)));
329 ncp_rp_dword_hl(struct ncp_rq *rqp) {
331 caddr_t prev = rqp->bpos;
334 if (rqp->mrp == NULL) return 0;
335 rest = ncp_mspaceleft;
338 return getdbe(prev,0);
342 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
344 rqp->mrp = rqp->mrp->m_next;
345 if (rqp->mrp == NULL) return 0;
346 prev = mtod(rqp->mrp, caddr_t);
347 rqp->bpos = prev + 4 - togo; /* XXX possible low than togo bytes in next mbuf */
349 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
355 ncp_rp_dword_lh(struct ncp_rq *rqp) {
357 caddr_t prev = rqp->bpos;
360 if (rqp->mrp == NULL) return 0;
361 rest = ncp_mspaceleft;
364 return getdle(prev,0);
368 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
370 rqp->mrp = rqp->mrp->m_next;
371 if (rqp->mrp == NULL) return 0;
372 prev = mtod(rqp->mrp, caddr_t);
373 rqp->bpos = prev + 4 - togo; /* XXX possible low than togo bytes in next mbuf */
375 ((u_int8_t *)&t)[togo++] = *((u_int8_t*)(prev++));
380 ncp_rp_mem(struct ncp_rq *rqp,caddr_t target, int size) {
381 register struct mbuf *m=rqp->mrp;
382 register unsigned count;
385 if (m==0) { /* should be panic */
386 printf("ncp_rp_mem: incomplete copy\n");
389 count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
392 rqp->bpos=mtod(m,caddr_t);
395 count = min(count,size);
396 bcopy(rqp->bpos, target, count);
406 ncp_rp_usermem(struct ncp_rq *rqp,caddr_t target, int size) {
407 register struct mbuf *m=rqp->mrp;
408 register unsigned count;
412 if (m==0) { /* should be panic */
413 printf("ncp_rp_mem: incomplete copy\n");
416 count = mtod(m,caddr_t)+m->m_len-rqp->bpos;
419 rqp->bpos=mtod(m,caddr_t);
422 count = min(count,size);
423 error=copyout(rqp->bpos, target, count);
424 if (error) return error;
434 ncp_rp_mbuf(struct ncp_rq *rqp, int size) {
435 register struct mbuf *m=rqp->mrp, *rm;
436 register unsigned count;
438 rm = m_copym(m, rqp->bpos - mtod(m,caddr_t), size, M_WAIT);
441 printf("ncp_rp_mbuf: can't advance\n");
444 count = mtod(m,caddr_t)+ m->m_len - rqp->bpos;
447 rqp->bpos = mtod(m, caddr_t);
450 count = min(count, size);
459 nwfs_mbuftouio(mrep, uiop, siz, dpos)
461 register struct uio *uiop;
465 register char *mbufcp, *uiocp;
466 register int xfer, left, len;
467 register struct mbuf *mp;
474 len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
476 if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
478 left = uiop->uio_iov->iov_len;
479 uiocp = uiop->uio_iov->iov_base;
488 mbufcp = mtod(mp, caddr_t);
491 xfer = (left > len) ? len : left;
494 if (uiop->uio_iov->iov_op != NULL)
495 (*(uiop->uio_iov->iov_op))
496 (mbufcp, uiocp, xfer);
499 if (uiop->uio_segflg == UIO_SYSSPACE)
500 bcopy(mbufcp, uiocp, xfer);
502 copyout(mbufcp, uiocp, xfer);
507 uiop->uio_offset += xfer;
508 uiop->uio_resid -= xfer;
510 if (uiop->uio_iov->iov_len <= siz) {
514 uiop->uio_iov->iov_base += uiosiz;
515 uiop->uio_iov->iov_len -= uiosiz;
524 * copies a uio scatter/gather list to an mbuf chain.
525 * NOTE: can ony handle iovcnt == 1
528 nwfs_uiotombuf(uiop, mq, siz, bpos)
529 register struct uio *uiop;
534 register char *uiocp;
535 register struct mbuf *mp, *mp2;
536 register int xfer, left, mlen;
540 if (uiop->uio_iovcnt != 1)
541 panic("nfsm_uiotombuf: iovcnt != 1");
544 if (siz > MLEN) /* or should it >= MCLBYTES ?? */
550 left = uiop->uio_iov->iov_len;
551 uiocp = uiop->uio_iov->iov_base;
556 mlen = M_TRAILINGSPACE(mp);
558 MGET(mp, M_WAIT, MT_DATA);
564 mlen = M_TRAILINGSPACE(mp);
566 xfer = (left > mlen) ? mlen : left;
569 if (uiop->uio_iov->iov_op != NULL)
570 (*(uiop->uio_iov->iov_op))
571 (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
574 if (uiop->uio_segflg == UIO_SYSSPACE)
575 bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
577 copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
581 uiop->uio_offset += xfer;
582 uiop->uio_resid -= xfer;
584 uiop->uio_iov->iov_base += uiosiz;
585 uiop->uio_iov->iov_len -= uiosiz;
588 *bpos = mtod(mp, caddr_t)+mp->m_len;