From d8589bd5cbad9b1452335c4c7c00a1b704eece8c Mon Sep 17 00:00:00 2001 From: Boris Popov Date: Sat, 24 Feb 2001 15:44:30 +0000 Subject: [PATCH] Introduce API for sequential reads/writes (build/dissect) of mbuf chains. Reviewed by: Ian Dowse , Bosko Milekic , Julian Elischer and arch@/net@ Obtained from: smbfs --- sys/conf/NOTES | 3 + sys/conf/files | 1 + sys/conf/options | 1 + sys/i386/conf/NOTES | 3 + sys/kern/subr_mchain.c | 549 +++++++++++++++++++++++++++++++++ sys/modules/Makefile | 2 +- sys/modules/libmchain/Makefile | 8 + sys/sys/mchain.h | 155 ++++++++++ 8 files changed, 721 insertions(+), 1 deletion(-) create mode 100644 sys/kern/subr_mchain.c create mode 100644 sys/modules/libmchain/Makefile create mode 100644 sys/sys/mchain.h diff --git a/sys/conf/NOTES b/sys/conf/NOTES index a613a71a4599..1b3dc79101f4 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -413,6 +413,9 @@ options NETATALKDEBUG #Appletalk debugging #options NS #Xerox NS protocols #options NSIP #XNS over IP +# mchain library. It can be either loaded as KLD or compiled into kernel +options LIBMCHAIN + # netgraph(4). Enable the base netgraph code with the NETGRAPH option. # Individual node types can be enabled with the corresponding option # listed below; however, this is not strictly necessary as netgraph diff --git a/sys/conf/files b/sys/conf/files index d1b80bc95c7e..93b652a26964 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -697,6 +697,7 @@ kern/subr_diskslice.c standard kern/subr_eventhandler.c standard kern/subr_kobj.c standard kern/subr_log.c standard +kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_prf.c standard kern/subr_prof.c standard diff --git a/sys/conf/options b/sys/conf/options index 86198f649084..5df2902dc268 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -262,6 +262,7 @@ IPSTEALTH IPX opt_ipx.h IPXIP opt_ipx.h IPTUNNEL opt_ipx.h +LIBMCHAIN NCP opt_ncp.h NETATALK opt_atalk.h PPP_BSDCOMP opt_ppp.h diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index a613a71a4599..1b3dc79101f4 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -413,6 +413,9 @@ options NETATALKDEBUG #Appletalk debugging #options NS #Xerox NS protocols #options NSIP #XNS over IP +# mchain library. It can be either loaded as KLD or compiled into kernel +options LIBMCHAIN + # netgraph(4). Enable the base netgraph code with the NETGRAPH option. # Individual node types can be enabled with the corresponding option # listed below; however, this is not strictly necessary as netgraph diff --git a/sys/kern/subr_mchain.c b/sys/kern/subr_mchain.c new file mode 100644 index 000000000000..3f13c80cb10f --- /dev/null +++ b/sys/kern/subr_mchain.c @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2000, 2001 Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + + +#include +#include +#include +#include +#include +#include + +#include + +MODULE_VERSION(libmchain, 1); + +#define MBERROR(format, args...) printf("%s(%d): "format, __FUNCTION__ , \ + __LINE__ ,## args) + +#define MBPANIC(format, args...) printf("%s(%d): "format, __FUNCTION__ , \ + __LINE__ ,## args) + +/* + * Various helper functions + */ +int +m_fixhdr(struct mbuf *m0) +{ + struct mbuf *m = m0; + int len = 0; + + while (m) { + len += m->m_len; + m = m->m_next; + } + m0->m_pkthdr.len = len; + return len; +} + +int +mb_init(struct mbchain *mbp) +{ + struct mbuf *m; + + m = m_gethdr(M_TRYWAIT, MT_DATA); + if (m == NULL) + return ENOBUFS; + m->m_pkthdr.rcvif = NULL; + m->m_len = 0; + mb_initm(mbp, m); + return 0; +} + +void +mb_initm(struct mbchain *mbp, struct mbuf *m) +{ + bzero(mbp, sizeof(*mbp)); + mbp->mb_top = mbp->mb_cur = m; + mbp->mb_mleft = M_TRAILINGSPACE(m); +} + +void +mb_done(struct mbchain *mbp) +{ + if (mbp->mb_top) { + m_freem(mbp->mb_top); + mbp->mb_top = NULL; + } +} + +struct mbuf * +mb_detach(struct mbchain *mbp) +{ + struct mbuf *m; + + m = mbp->mb_top; + mbp->mb_top = NULL; + return m; +} + +int +mb_fixhdr(struct mbchain *mbp) +{ + return mbp->mb_top->m_pkthdr.len = m_fixhdr(mbp->mb_top); +} + +/* + * Check if object of size 'size' fit to the current position and + * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). + * Return pointer to the object placeholder or NULL if any error occured. + * Note: size should be <= MLEN + */ +caddr_t +mb_reserve(struct mbchain *mbp, int size) +{ + struct mbuf *m, *mn; + caddr_t bpos; + + if (size > MLEN) + panic("mb_reserve: size = %d\n", size); + m = mbp->mb_cur; + if (mbp->mb_mleft < size) { + mn = m_get(M_TRYWAIT, MT_DATA); + if (mn == NULL) + return NULL; + mbp->mb_cur = m->m_next = mn; + m = mn; + m->m_len = 0; + mbp->mb_mleft = M_TRAILINGSPACE(m); + } + mbp->mb_mleft -= size; + mbp->mb_count += size; + bpos = mtod(m, caddr_t) + m->m_len; + m->m_len += size; + return bpos; +} + +int +mb_put_uint8(struct mbchain *mbp, u_int8_t x) +{ + return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); +} + +int +mb_put_uint16be(struct mbchain *mbp, u_int16_t x) +{ + x = htobes(x); + return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); +} + +int +mb_put_uint16le(struct mbchain *mbp, u_int16_t x) +{ + x = htoles(x); + return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); +} + +int +mb_put_uint32be(struct mbchain *mbp, u_int32_t x) +{ + x = htobel(x); + return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); +} + +int +mb_put_uint32le(struct mbchain *mbp, u_int32_t x) +{ + x = htolel(x); + return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); +} + +int +mb_put_int64be(struct mbchain *mbp, int64_t x) +{ + x = htobeq(x); + return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); +} + +int +mb_put_int64le(struct mbchain *mbp, int64_t x) +{ + x = htoleq(x); + return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); +} + +int +mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) +{ + struct mbuf *m; + caddr_t dst; + c_caddr_t src; + int cplen, error, mleft, count; + + m = mbp->mb_cur; + mleft = mbp->mb_mleft; + + while (size > 0) { + if (mleft == 0) { + if (m->m_next == NULL) { + m = m_getm(m, size, M_TRYWAIT, MT_DATA); + if (m == NULL) + return ENOBUFS; + } + m = m->m_next; + mleft = M_TRAILINGSPACE(m); + continue; + } + cplen = mleft > size ? size : mleft; + dst = mtod(m, caddr_t) + m->m_len; + switch (type) { + case MB_MCUSTOM: + error = mbp->mb_copy(mbp, source, dst, cplen); + if (error) + return error; + break; + case MB_MINLINE: + for (src = source, count = cplen; count; count--) + *dst++ = *src++; + break; + case MB_MSYSTEM: + bcopy(source, dst, cplen); + break; + case MB_MUSER: + error = copyin(source, dst, cplen); + if (error) + return error; + break; + case MB_MZERO: + bzero(dst, cplen); + break; + } + size -= cplen; + source += cplen; + m->m_len += cplen; + mleft -= cplen; + mbp->mb_count += cplen; + } + mbp->mb_cur = m; + mbp->mb_mleft = mleft; + return 0; +} + +int +mb_put_mbuf(struct mbchain *mbp, struct mbuf *m) +{ + mbp->mb_cur->m_next = m; + while (m) { + mbp->mb_count += m->m_len; + if (m->m_next == NULL) + break; + m = m->m_next; + } + mbp->mb_mleft = M_TRAILINGSPACE(m); + mbp->mb_cur = m; + return 0; +} + +/* + * copies a uio scatter/gather list to an mbuf chain. + * NOTE: can ony handle iovcnt == 1 + */ +int +mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) +{ + long left; + int mtype, error; + +#ifdef DIAGNOSTIC + if (uiop->uio_iovcnt != 1) + MBPANIC("iovcnt != 1"); +#endif + mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; + + while (size > 0) { + left = uiop->uio_iov->iov_len; + if (left > size) + left = size; + error = mb_put_mem(mbp, uiop->uio_iov->iov_base, left, mtype); + if (error) + return error; + uiop->uio_offset += left; + uiop->uio_resid -= left; + uiop->uio_iov->iov_base += left; + uiop->uio_iov->iov_len -= left; + size -= left; + } + return 0; +} + +/* + * Routines for fetching data from an mbuf chain + */ +int +md_init(struct mdchain *mdp) +{ + struct mbuf *m; + + m = m_gethdr(M_TRYWAIT, MT_DATA); + if (m == NULL) + return ENOBUFS; + m->m_pkthdr.rcvif = NULL; + m->m_len = 0; + md_initm(mdp, m); + return 0; +} + +void +md_initm(struct mdchain *mdp, struct mbuf *m) +{ + bzero(mdp, sizeof(*mdp)); + mdp->md_top = mdp->md_cur = m; + mdp->md_pos = mtod(m, u_char*); +} + +void +md_done(struct mdchain *mdp) +{ + if (mdp->md_top) { + m_freem(mdp->md_top); + mdp->md_top = NULL; + } +} + +/* + * Append a separate mbuf chain. It is caller responsibility to prevent + * multiple calls to fetch/record routines. + */ +void +md_append_record(struct mdchain *mdp, struct mbuf *top) +{ + struct mbuf *m; + + if (mdp->md_top == NULL) { + md_initm(mdp, top); + return; + } + m = mdp->md_top; + while (m->m_nextpkt) + m = m->m_nextpkt; + m->m_nextpkt = top; + top->m_nextpkt = NULL; + return; +} + +/* + * Put next record in place of existing + */ +int +md_next_record(struct mdchain *mdp) +{ + struct mbuf *m; + + if (mdp->md_top == NULL) + return ENOENT; + m = mdp->md_top->m_nextpkt; + md_done(mdp); + if (m == NULL) + return ENOENT; + md_initm(mdp, m); + return 0; +} + +int +md_get_uint8(struct mdchain *mdp, u_int8_t *x) +{ + return md_get_mem(mdp, x, 1, MB_MINLINE); +} + +int +md_get_uint16(struct mdchain *mdp, u_int16_t *x) +{ + return md_get_mem(mdp, (caddr_t)x, 2, MB_MINLINE); +} + +int +md_get_uint16le(struct mdchain *mdp, u_int16_t *x) +{ + u_int16_t v; + int error = md_get_uint16(mdp, &v); + + *x = letohs(v); + return error; +} + +int +md_get_uint16be(struct mdchain *mdp, u_int16_t *x) { + u_int16_t v; + int error = md_get_uint16(mdp, &v); + + *x = betohs(v); + return error; +} + +int +md_get_uint32(struct mdchain *mdp, u_int32_t *x) +{ + return md_get_mem(mdp, (caddr_t)x, 4, MB_MINLINE); +} + +int +md_get_uint32be(struct mdchain *mdp, u_int32_t *x) +{ + u_int32_t v; + int error; + + error = md_get_uint32(mdp, &v); + *x = betohl(v); + return error; +} + +int +md_get_uint32le(struct mdchain *mdp, u_int32_t *x) +{ + u_int32_t v; + int error; + + error = md_get_uint32(mdp, &v); + *x = letohl(v); + return error; +} + +int +md_get_int64(struct mdchain *mdp, int64_t *x) +{ + return md_get_mem(mdp, (caddr_t)x, 8, MB_MINLINE); +} + +int +md_get_int64be(struct mdchain *mdp, int64_t *x) +{ + int64_t v; + int error; + + error = md_get_int64(mdp, &v); + *x = betohq(v); + return error; +} + +int +md_get_int64le(struct mdchain *mdp, int64_t *x) +{ + int64_t v; + int error; + + error = md_get_int64(mdp, &v); + *x = letohq(v); + return error; +} + +int +md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type) +{ + struct mbuf *m = mdp->md_cur; + int error; + u_int count; + u_char *s; + + while (size > 0) { + if (m == NULL) { + MBERROR("incomplete copy\n"); + return EBADRPC; + } + s = mdp->md_pos; + count = mtod(m, u_char*) + m->m_len - s; + if (count == 0) { + mdp->md_cur = m = m->m_next; + if (m) + s = mdp->md_pos = mtod(m, caddr_t); + continue; + } + if (count > size) + count = size; + size -= count; + mdp->md_pos += count; + if (target == NULL) + continue; + switch (type) { + case MB_MUSER: + error = copyout(s, target, count); + if (error) + return error; + break; + case MB_MSYSTEM: + bcopy(s, target, count); + break; + case MB_MINLINE: + while (count--) + *target++ = *s++; + continue; + } + target += count; + } + return 0; +} + +int +md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **ret) +{ + struct mbuf *m = mdp->md_cur, *rm; + + rm = m_copym(m, mdp->md_pos - mtod(m, u_char*), size, M_TRYWAIT); + if (rm == NULL) + return EBADRPC; + md_get_mem(mdp, NULL, size, MB_MZERO); + *ret = rm; + return 0; +} + +int +md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) +{ + char *uiocp; + long left; + int mtype, error; + + mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; + while (size > 0) { + if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) + return EFBIG; + left = uiop->uio_iov->iov_len; + uiocp = uiop->uio_iov->iov_base; + if (left > size) + left = size; + error = md_get_mem(mdp, uiocp, left, mtype); + if (error) + return error; + uiop->uio_offset += left; + uiop->uio_resid -= left; + if (uiop->uio_iov->iov_len <= size) { + uiop->uio_iovcnt--; + uiop->uio_iov++; + } else { + uiop->uio_iov->iov_base += left; + uiop->uio_iov->iov_len -= left; + } + size -= left; + } + return 0; +} diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 50cdc43fdd65..fd7f58f3ed49 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -9,7 +9,7 @@ _random= random SUBDIR= 3dfx accf_data accf_http agp aha amr an aue \ cam ccd cd9660 coda cue dc de ed fdesc fxp if_disc if_ef \ if_ppp if_sl if_tap if_tun ip6fw ipfilter ipfw ispfw joy kue \ - linux lnc md mfs mii mlx msdos ncp netgraph nfs ntfs nullfs \ + libmchain linux lnc md mfs mii mlx msdos ncp netgraph nfs ntfs nullfs \ nwfs pcn portal procfs ${_random} \ rl rp sf sis sk sn sound sppp ste sym syscons sysvipc ti tl twe tx \ udbp ugen uhid ukbd ulpt umapfs umass umodem ums union urio usb \ diff --git a/sys/modules/libmchain/Makefile b/sys/modules/libmchain/Makefile new file mode 100644 index 000000000000..39cfeb042767 --- /dev/null +++ b/sys/modules/libmchain/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../kern + +KMOD= libmchain +SRCS= subr_mchain.c + +.include diff --git a/sys/sys/mchain.h b/sys/sys/mchain.h new file mode 100644 index 000000000000..e79fbfb03524 --- /dev/null +++ b/sys/sys/mchain.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2000, 2001 Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _SYS_MCHAIN_H_ +#define _SYS_MCHAIN_H_ + +#include + +/* + * This macros probably belongs to the endian.h + */ +#if (BYTE_ORDER == LITTLE_ENDIAN) + +#define htoles(x) ((u_int16_t)(x)) +#define letohs(x) ((u_int16_t)(x)) +#define htolel(x) ((u_int32_t)(x)) +#define letohl(x) ((u_int32_t)(x)) +#define htoleq(x) ((int64_t)(x)) +#define letohq(x) ((int64_t)(x)) + +#define htobes(x) (htons(x)) +#define betohs(x) (ntohs(x)) +#define htobel(x) (htonl(x)) +#define betohl(x) (ntohl(x)) + +static __inline int64_t +htobeq(int64_t x) +{ + return (int64_t)htonl((u_int32_t)(x >> 32)) | + (int64_t)htonl((u_int32_t)(x & 0xffffffff)) << 32; +} + +static __inline int64_t +betohq(int64_t x) +{ + return (int64_t)ntohl((u_int32_t)(x >> 32)) | + (int64_t)ntohl((u_int32_t)(x & 0xffffffff)) << 32; +} + +#else /* (BYTE_ORDER == LITTLE_ENDIAN) */ + +#error "Macros for Big-Endians are incomplete" + +/* +#define htoles(x) ((u_int16_t)(x)) +#define letohs(x) ((u_int16_t)(x)) +#define htolel(x) ((u_int32_t)(x)) +#define letohl(x) ((u_int32_t)(x)) +*/ +#endif /* (BYTE_ORDER == LITTLE_ENDIAN) */ + + +#ifdef _KERNEL + +/* + * Type of copy for mb_{put|get}_mem() + */ +#define MB_MSYSTEM 0 /* use bcopy() */ +#define MB_MUSER 1 /* use copyin()/copyout() */ +#define MB_MINLINE 2 /* use an inline copy loop */ +#define MB_MZERO 3 /* bzero(), mb_put_mem only */ +#define MB_MCUSTOM 4 /* use an user defined function */ + +struct mbuf; +struct mbchain; + +typedef int mb_copy_t(struct mbchain *mbp, c_caddr_t src, caddr_t dst, int len); + +struct mbchain { + struct mbuf * mb_top; /* head of mbufs chain */ + struct mbuf * mb_cur; /* current mbuf */ + int mb_mleft; /* free space in the current mbuf */ + int mb_count; /* total number of bytes */ + mb_copy_t * mb_copy; /* user defined copy function */ + void * mb_udata; /* user data */ +}; + +struct mdchain { + struct mbuf * md_top; /* head of mbufs chain */ + struct mbuf * md_cur; /* current mbuf */ + u_char * md_pos; /* offset in the current mbuf */ +}; + +int m_fixhdr(struct mbuf *m); + +int mb_init(struct mbchain *mbp); +void mb_initm(struct mbchain *mbp, struct mbuf *m); +void mb_done(struct mbchain *mbp); +struct mbuf *mb_detach(struct mbchain *mbp); +int mb_fixhdr(struct mbchain *mbp); +caddr_t mb_reserve(struct mbchain *mbp, int size); + +int mb_put_uint8(struct mbchain *mbp, u_int8_t x); +int mb_put_uint16be(struct mbchain *mbp, u_int16_t x); +int mb_put_uint16le(struct mbchain *mbp, u_int16_t x); +int mb_put_uint32be(struct mbchain *mbp, u_int32_t x); +int mb_put_uint32le(struct mbchain *mbp, u_int32_t x); +int mb_put_int64be(struct mbchain *mbp, int64_t x); +int mb_put_int64le(struct mbchain *mbp, int64_t x); +int mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type); +int mb_put_mbuf(struct mbchain *mbp, struct mbuf *m); +int mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size); + +int md_init(struct mdchain *mdp); +void md_initm(struct mdchain *mbp, struct mbuf *m); +void md_done(struct mdchain *mdp); +void md_append_record(struct mdchain *mdp, struct mbuf *top); +int md_next_record(struct mdchain *mdp); +int md_get_uint8(struct mdchain *mdp, u_int8_t *x); +int md_get_uint16(struct mdchain *mdp, u_int16_t *x); +int md_get_uint16le(struct mdchain *mdp, u_int16_t *x); +int md_get_uint16be(struct mdchain *mdp, u_int16_t *x); +int md_get_uint32(struct mdchain *mdp, u_int32_t *x); +int md_get_uint32be(struct mdchain *mdp, u_int32_t *x); +int md_get_uint32le(struct mdchain *mdp, u_int32_t *x); +int md_get_int64(struct mdchain *mdp, int64_t *x); +int md_get_int64be(struct mdchain *mdp, int64_t *x); +int md_get_int64le(struct mdchain *mdp, int64_t *x); +int md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type); +int md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **m); +int md_get_uio(struct mdchain *mdp, struct uio *uiop, int size); + +#endif /* ifdef _KERNEL */ + +#endif /* !_SYS_MCHAIN_H_ */