2 * Copyright (c) 2000, 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 * from: Id: mbuf.c,v 1.6 2001/02/24 15:56:04 bp Exp
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: mbuf.c,v 1.7 2006/10/16 03:38:08 christos Exp $");
38 #include <sys/types.h>
39 #include <sys/endian.h>
46 #include <netsmb/smb_lib.h>
48 #define MBERROR(x) printf x
51 m_get(size_t len
, struct mbuf
**mpp
)
58 m
= malloc(M_BASESIZE
+ len
);
61 bzero(m
, M_BASESIZE
+ len
);
69 m_free(struct mbuf
*m
)
75 m_freem(struct mbuf
*m0
)
87 m_totlen(struct mbuf
*m0
)
100 m_lineup(struct mbuf
*m0
, struct mbuf
**mpp
)
107 if (m0
->m_next
== NULL
) {
111 if ((error
= m_get(m_totlen(m0
), &nm
)) != 0)
113 dp
= mtod(nm
, char *);
116 bcopy(m0
->m_data
, dp
, len
);
127 mb_init(struct mbdata
*mbp
, size_t size
)
132 if ((error
= m_get(size
, &m
)) != 0)
134 return mb_initm(mbp
, m
);
138 mb_initm(struct mbdata
*mbp
, struct mbuf
*m
)
140 bzero(mbp
, sizeof(*mbp
));
141 mbp
->mb_top
= mbp
->mb_cur
= m
;
142 mbp
->mb_pos
= mtod(m
, char *);
147 mb_done(struct mbdata
*mbp
)
150 m_freem(mbp
->mb_top
);
158 mb_fixhdr(struct mbdata *mbp)
160 struct mbuf *m = mbp->mb_top;
167 mbp->mb_top->m_pkthdr.len = len;
172 m_getm(struct mbuf
*top
, size_t len
, struct mbuf
**mpp
)
177 for (mp
= top
; ; mp
= mp
->m_next
) {
178 len
-= M_TRAILINGSPACE(mp
);
179 if (mp
->m_next
== NULL
)
184 if ((error
= m_get(len
, &m
)) != 0)
193 * Routines to put data in a buffer
195 #define MB_PUT(t) int error; t *p; \
196 if ((error = mb_fit(mbp, sizeof(t), \
197 (void **)(void *)&p)) != 0) \
201 * Check if object of size 'size' fit to the current position and
202 * allocate new mbuf if not. Advance pointers and increase length of mbuf(s).
203 * Return pointer to the object placeholder or NULL if any error occured.
206 mb_fit(struct mbdata
*mbp
, size_t size
, void **pp
)
212 if (M_TRAILINGSPACE(m
) < (int)size
) {
213 if ((error
= m_get(size
, &mn
)) != 0)
215 mbp
->mb_pos
= mtod(mn
, char *);
216 mbp
->mb_cur
= m
->m_next
= mn
;
222 mbp
->mb_count
+= size
;
227 mb_put_uint8(struct mbdata
*mbp
, u_int8_t x
)
235 mb_put_uint16be(struct mbdata
*mbp
, u_int16_t x
)
243 mb_put_uint16le(struct mbdata
*mbp
, u_int16_t x
)
251 mb_put_uint32be(struct mbdata
*mbp
, u_int32_t x
)
259 mb_put_uint32le(struct mbdata
*mbp
, u_int32_t x
)
267 mb_put_int64be(struct mbdata
*mbp
, int64_t x
)
275 mb_put_int64le(struct mbdata
*mbp
, int64_t x
)
283 mb_put_mem(struct mbdata
*mbp
, const char *source
, size_t size
)
293 if ((error
= m_getm(m
, size
, &m
)) != 0)
296 cplen
= M_TRAILINGSPACE(m
);
303 dst
= mtod(m
, char *) + m
->m_len
;
305 bcopy(source
, dst
, cplen
);
311 mbp
->mb_count
+= cplen
;
313 mbp
->mb_pos
= mtod(m
, char *) + m
->m_len
;
319 mb_put_mbuf(struct mbdata
*mbp
, struct mbuf
*m
)
321 mbp
->mb_cur
->m_next
= m
;
323 mbp
->mb_count
+= m
->m_len
;
324 if (m
->m_next
== NULL
)
328 mbp
->mb_pos
= mtod(m
, char *) + m
->m_len
;
334 mb_put_pstring(struct mbdata
*mbp
, const char *s
)
336 int error
, len
= strlen(s
);
341 if ((error
= mb_put_uint8(mbp
, len
)) != 0)
343 return mb_put_mem(mbp
, s
, len
);
347 * Routines for fetching data from an mbuf chain
349 #define mb_left(m,p) (mtod(m, char *) + (m)->m_len - (p))
352 mb_get_uint8(struct mbdata
*mbp
, u_int8_t
*x
)
354 return mb_get_mem(mbp
, x
, 1);
358 mb_get_uint16(struct mbdata
*mbp
, u_int16_t
*x
)
360 return mb_get_mem(mbp
, (char *)x
, 2);
364 mb_get_uint16le(struct mbdata
*mbp
, u_int16_t
*x
)
367 int error
= mb_get_uint16(mbp
, &v
);
374 mb_get_uint16be(struct mbdata
*mbp
, u_int16_t
*x
) {
376 int error
= mb_get_uint16(mbp
, &v
);
383 mb_get_uint32(struct mbdata
*mbp
, u_int32_t
*x
)
385 return mb_get_mem(mbp
, (char *)x
, 4);
389 mb_get_uint32be(struct mbdata
*mbp
, u_int32_t
*x
)
394 error
= mb_get_uint32(mbp
, &v
);
400 mb_get_uint32le(struct mbdata
*mbp
, u_int32_t
*x
)
405 error
= mb_get_uint32(mbp
, &v
);
411 mb_get_int64(struct mbdata
*mbp
, int64_t *x
)
413 return mb_get_mem(mbp
, (char *)x
, 8);
417 mb_get_int64be(struct mbdata
*mbp
, int64_t *x
)
422 error
= mb_get_int64(mbp
, &v
);
428 mb_get_int64le(struct mbdata
*mbp
, int64_t *x
)
433 error
= mb_get_int64(mbp
, &v
);
439 mb_get_mem(struct mbdata
*mbp
, char * target
, size_t size
)
441 struct mbuf
*m
= mbp
->mb_cur
;
446 MBERROR(("incomplete copy\n"));
449 count
= mb_left(m
, mbp
->mb_pos
);
451 mbp
->mb_cur
= m
= m
->m_next
;
453 mbp
->mb_pos
= mtod(m
, char *);
461 *target
++ = *mbp
->mb_pos
;
463 bcopy(mbp
->mb_pos
, target
, count
);
467 mbp
->mb_pos
+= count
;