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 $
35 * $DragonFly: src/sys/netproto/ncp/ncp_rq.c,v 1.10 2006/12/22 23:57:54 swildner Exp $
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/errno.h>
51 ncp_rq_head(struct ncp_rq
*rqp
, u_int32_t ptype
, u_int8_t fn
,struct thread
*td
,
56 struct ncp_bursthdr
*brq
;
59 bzero(rqp
, sizeof(*rqp
));
62 m
= m_gethdr(MB_WAIT
, MT_DATA
);
64 return ENOBUFS
; /* if MB_WAIT ? */
65 m
->m_pkthdr
.rcvif
= NULL
;
66 rqp
->rq
= rqp
->mrq
= m
;
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
*);
74 brq
->bh_streamtype
= 0x2;
75 pstart
= (caddr_t
)brq
;
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
*);
82 rq
->seq
= 0; /* filled later */
87 rqp
->bpos
= pstart
+ m
->m_len
;
92 ncp_rq_done(struct ncp_rq
*rqp
) {
95 if (rqp
->rp
) m_freem(rqp
->rp
);
101 * Routines to fill the request
103 static caddr_t
ncp_mchecksize(struct ncp_rq
*rqp
, int size
);
104 #define NCP_RQADD(t) ((t*)(ncp_mchecksize(rqp,sizeof(t))))
107 ncp_mchecksize(struct ncp_rq
*rqp
, int size
) {
111 panic("ncp_mchecksize\n");
112 if (M_TRAILINGSPACE(rqp
->mrq
)<(size
)) {
114 m
= m_get(MB_WAIT
, MT_DATA
);
116 rqp
->bpos
= mtod(m
, caddr_t
);
117 rqp
->mrq
->m_next
= m
;
120 rqp
->mrq
->m_len
+= size
;
127 ncp_rq_byte(struct ncp_rq
*rqp
,u_int8_t x
) {
128 *NCP_RQADD(u_int8_t
)=x
;
132 ncp_rq_word_hl(struct ncp_rq
*rqp
, u_int16_t x
) {
133 setwbe(NCP_RQADD(u_int16_t
), 0, x
);
137 ncp_rq_word_lh(struct ncp_rq
*rqp
, u_int16_t x
) {
138 setwle(NCP_RQADD(u_int16_t
), 0, x
);
142 ncp_rq_dword_lh(struct ncp_rq
*rqp
, u_int32_t x
) {
143 setdle(NCP_RQADD(u_int32_t
), 0, x
);
147 ncp_rq_pathstring(struct ncp_rq
*rqp
, int size
, char *name
, struct ncp_nlstables
*nt
) {
151 ncp_rq_byte(rqp
, size
);
153 cplen
= min(size
, M_TRAILINGSPACE(m
));
155 ncp_pathcopy(name
, rqp
->bpos
, cplen
, nt
);
161 m_getm(m
, size
, MT_DATA
, MB_WAIT
);
164 cplen
= min(size
, M_TRAILINGSPACE(m
));
165 ncp_pathcopy(name
, mtod(m
, caddr_t
) + m
->m_len
, cplen
, nt
);
171 rqp
->bpos
= mtod(m
,caddr_t
) + m
->m_len
;
177 ncp_rq_putanymem(struct ncp_rq
*rqp
, caddr_t source
, int size
, int type
) {
182 cplen
= min(size
, M_TRAILINGSPACE(m
));
185 error
= copyin(source
, rqp
->bpos
, cplen
);
186 if (error
) return error
;
188 bcopy(source
, rqp
->bpos
, cplen
);
194 m_getm(m
, size
, MT_DATA
, MB_WAIT
);
197 cplen
= min(size
, M_TRAILINGSPACE(m
));
199 error
= copyin(source
, mtod(m
, caddr_t
) + m
->m_len
, cplen
);
200 if (error
) return error
;
202 bcopy(source
, mtod(m
, caddr_t
) + m
->m_len
, cplen
);
208 rqp
->bpos
= mtod(m
,caddr_t
) + m
->m_len
;
214 ncp_rq_mbuf(struct ncp_rq
*rqp
, struct mbuf
*m
, int size
) {
216 rqp
->mrq
->m_next
= m
;
218 if (size
!= M_COPYALL
) m
->m_len
= size
;
219 rqp
->bpos
= mtod(m
,caddr_t
) + m
->m_len
;
225 ncp_rq_pstring(struct ncp_rq
*rqp
, char *s
) {
228 nwfs_printf("string too long: %s\n", s
);
231 ncp_rq_byte(rqp
, len
);
232 ncp_rq_mem(rqp
, s
, len
);
237 ncp_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
)
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]) {
248 ncp_rq_byte(rqp
, namelen
);
249 for(; namelen
; namelen
--) {
251 ncp_rq_byte(rqp
, complen
);
252 ncp_rq_mem(rqp
, path
, complen
);
256 ncp_rq_byte(rqp
, 1); /* 1 component */
257 ncp_rq_pathstring(rqp
, namelen
, path
, nt
);
265 * fetch reply routines
267 #define ncp_mspaceleft (mtod(rqp->mrp,caddr_t)+rqp->mrp->m_len-rqp->bpos)
270 ncp_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
);
278 return rqp
->bpos
[-1];
282 ncp_rp_word_lh(struct ncp_rq
*rqp
) {
283 caddr_t prev
= rqp
->bpos
;
286 if (rqp
->mrp
== NULL
) return 0;
287 if (ncp_mspaceleft
>= 2) {
289 return getwle(prev
,0);
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
)));
300 ncp_rp_word_hl(struct ncp_rq
*rqp
) {
301 return (ntohs(ncp_rp_word_lh(rqp
)));
305 ncp_rp_dword_hl(struct ncp_rq
*rqp
) {
307 caddr_t prev
= rqp
->bpos
;
310 if (rqp
->mrp
== NULL
) return 0;
311 rest
= ncp_mspaceleft
;
314 return getdbe(prev
,0);
318 ((u_int8_t
*)&t
)[togo
++] = *((u_int8_t
*)(prev
++));
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 */
325 ((u_int8_t
*)&t
)[togo
++] = *((u_int8_t
*)(prev
++));
331 ncp_rp_dword_lh(struct ncp_rq
*rqp
) {
333 caddr_t prev
= rqp
->bpos
;
336 if (rqp
->mrp
== NULL
) return 0;
337 rest
= ncp_mspaceleft
;
340 return getdle(prev
,0);
344 ((u_int8_t
*)&t
)[togo
++] = *((u_int8_t
*)(prev
++));
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 */
351 ((u_int8_t
*)&t
)[togo
++] = *((u_int8_t
*)(prev
++));
356 ncp_rp_mem(struct ncp_rq
*rqp
,caddr_t target
, int size
) {
357 struct mbuf
*m
=rqp
->mrp
;
361 if (m
==0) { /* should be panic */
362 kprintf("ncp_rp_mem: incomplete copy\n");
365 count
= mtod(m
,caddr_t
)+m
->m_len
-rqp
->bpos
;
368 rqp
->bpos
=mtod(m
,caddr_t
);
371 count
= min(count
,size
);
372 bcopy(rqp
->bpos
, target
, count
);
382 ncp_rp_usermem(struct ncp_rq
*rqp
,caddr_t target
, int size
) {
383 struct mbuf
*m
=rqp
->mrp
;
388 if (m
==0) { /* should be panic */
389 kprintf("ncp_rp_mem: incomplete copy\n");
392 count
= mtod(m
,caddr_t
)+m
->m_len
-rqp
->bpos
;
395 rqp
->bpos
=mtod(m
,caddr_t
);
398 count
= min(count
,size
);
399 error
=copyout(rqp
->bpos
, target
, count
);
400 if (error
) return error
;
410 ncp_rp_mbuf(struct ncp_rq
*rqp
, int size
) {
411 struct mbuf
*m
=rqp
->mrp
, *rm
;
414 rm
= m_copym(m
, rqp
->bpos
- mtod(m
,caddr_t
), size
, MB_WAIT
);
417 kprintf("ncp_rp_mbuf: can't advance\n");
420 count
= mtod(m
,caddr_t
)+ m
->m_len
- rqp
->bpos
;
423 rqp
->bpos
= mtod(m
, caddr_t
);
426 count
= min(count
, size
);
435 nwfs_mbuftouio(struct mbuf
**mrep
, struct uio
*uiop
, int siz
, caddr_t
*dpos
)
437 char *mbufcp
, *uiocp
;
446 len
= mtod(mp
, caddr_t
)+mp
->m_len
-mbufcp
;
448 if (uiop
->uio_iovcnt
<= 0 || uiop
->uio_iov
== NULL
)
450 left
= uiop
->uio_iov
->iov_len
;
451 uiocp
= uiop
->uio_iov
->iov_base
;
460 mbufcp
= mtod(mp
, caddr_t
);
463 xfer
= (left
> len
) ? len
: left
;
466 if (uiop
->uio_iov
->iov_op
!= NULL
)
467 (*(uiop
->uio_iov
->iov_op
))
468 (mbufcp
, uiocp
, xfer
);
471 if (uiop
->uio_segflg
== UIO_SYSSPACE
)
472 bcopy(mbufcp
, uiocp
, xfer
);
474 copyout(mbufcp
, uiocp
, xfer
);
479 uiop
->uio_offset
+= xfer
;
480 uiop
->uio_resid
-= xfer
;
482 if (uiop
->uio_iov
->iov_len
<= siz
) {
486 uiop
->uio_iov
->iov_base
= (char *)uiop
->uio_iov
->iov_base
+ uiosiz
;
487 uiop
->uio_iov
->iov_len
-= uiosiz
;
496 * copies a uio scatter/gather list to an mbuf chain.
497 * NOTE: can ony handle iovcnt == 1
500 nwfs_uiotombuf(struct uio
*uiop
, struct mbuf
**mq
, int siz
, caddr_t
*bpos
)
503 struct mbuf
*mp
, *mp2
;
504 int xfer
, left
, mlen
;
508 if (uiop
->uio_iovcnt
!= 1)
509 panic("nfsm_uiotombuf: iovcnt != 1");
512 if (siz
> MLEN
) /* or should it >= MCLBYTES ?? */
518 left
= uiop
->uio_iov
->iov_len
;
519 uiocp
= uiop
->uio_iov
->iov_base
;
524 mlen
= M_TRAILINGSPACE(mp
);
526 MGET(mp
, MB_WAIT
, MT_DATA
);
532 mlen
= M_TRAILINGSPACE(mp
);
534 xfer
= (left
> mlen
) ? mlen
: left
;
537 if (uiop
->uio_iov
->iov_op
!= NULL
)
538 (*(uiop
->uio_iov
->iov_op
))
539 (uiocp
, mtod(mp
, caddr_t
)+mp
->m_len
, xfer
);
542 if (uiop
->uio_segflg
== UIO_SYSSPACE
)
543 bcopy(uiocp
, mtod(mp
, caddr_t
)+mp
->m_len
, xfer
);
545 copyin(uiocp
, mtod(mp
, caddr_t
)+mp
->m_len
, xfer
);
549 uiop
->uio_offset
+= xfer
;
550 uiop
->uio_resid
-= xfer
;
552 uiop
->uio_iov
->iov_base
= (char *)uiop
->uio_iov
->iov_base
+ uiosiz
;
553 uiop
->uio_iov
->iov_len
-= uiosiz
;
556 *bpos
= mtod(mp
, caddr_t
)+mp
->m_len
;