1d8589bd5SBoris Popov /* 2d8589bd5SBoris Popov * Copyright (c) 2000, 2001 Boris Popov 3d8589bd5SBoris Popov * All rights reserved. 4d8589bd5SBoris Popov * 5d8589bd5SBoris Popov * Redistribution and use in source and binary forms, with or without 6d8589bd5SBoris Popov * modification, are permitted provided that the following conditions 7d8589bd5SBoris Popov * are met: 8d8589bd5SBoris Popov * 1. Redistributions of source code must retain the above copyright 9d8589bd5SBoris Popov * notice, this list of conditions and the following disclaimer. 10d8589bd5SBoris Popov * 2. Redistributions in binary form must reproduce the above copyright 11d8589bd5SBoris Popov * notice, this list of conditions and the following disclaimer in the 12d8589bd5SBoris Popov * documentation and/or other materials provided with the distribution. 13d8589bd5SBoris Popov * 3. All advertising materials mentioning features or use of this software 14d8589bd5SBoris Popov * must display the following acknowledgement: 15d8589bd5SBoris Popov * This product includes software developed by Boris Popov. 16d8589bd5SBoris Popov * 4. Neither the name of the author nor the names of any co-contributors 17d8589bd5SBoris Popov * may be used to endorse or promote products derived from this software 18d8589bd5SBoris Popov * without specific prior written permission. 19d8589bd5SBoris Popov * 20d8589bd5SBoris Popov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21d8589bd5SBoris Popov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22d8589bd5SBoris Popov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23d8589bd5SBoris Popov * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24d8589bd5SBoris Popov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25d8589bd5SBoris Popov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26d8589bd5SBoris Popov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27d8589bd5SBoris Popov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28d8589bd5SBoris Popov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29d8589bd5SBoris Popov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30d8589bd5SBoris Popov * SUCH DAMAGE. 31d8589bd5SBoris Popov * 32d8589bd5SBoris Popov * $FreeBSD$ 33d8589bd5SBoris Popov */ 34d8589bd5SBoris Popov 35d8589bd5SBoris Popov 36d8589bd5SBoris Popov #include <sys/param.h> 37d8589bd5SBoris Popov #include <sys/systm.h> 38a30d4b32SMike Barcroft #include <sys/endian.h> 39d8589bd5SBoris Popov #include <sys/errno.h> 40d8589bd5SBoris Popov #include <sys/mbuf.h> 41d8589bd5SBoris Popov #include <sys/module.h> 42d8589bd5SBoris Popov #include <sys/uio.h> 43d8589bd5SBoris Popov 44d8589bd5SBoris Popov #include <sys/mchain.h> 45d8589bd5SBoris Popov 46d8589bd5SBoris Popov MODULE_VERSION(libmchain, 1); 47d8589bd5SBoris Popov 48a48740b6SDavid E. O'Brien #define MBERROR(format, args...) printf("%s(%d): "format, __func__ , \ 49d8589bd5SBoris Popov __LINE__ ,## args) 50d8589bd5SBoris Popov 51a48740b6SDavid E. O'Brien #define MBPANIC(format, args...) printf("%s(%d): "format, __func__ , \ 52d8589bd5SBoris Popov __LINE__ ,## args) 53d8589bd5SBoris Popov 54d8589bd5SBoris Popov /* 55d8589bd5SBoris Popov * Various helper functions 56d8589bd5SBoris Popov */ 57d8589bd5SBoris Popov int 58d8589bd5SBoris Popov m_fixhdr(struct mbuf *m0) 59d8589bd5SBoris Popov { 60d8589bd5SBoris Popov struct mbuf *m = m0; 61d8589bd5SBoris Popov int len = 0; 62d8589bd5SBoris Popov 63d8589bd5SBoris Popov while (m) { 64d8589bd5SBoris Popov len += m->m_len; 65d8589bd5SBoris Popov m = m->m_next; 66d8589bd5SBoris Popov } 67d8589bd5SBoris Popov m0->m_pkthdr.len = len; 68d8589bd5SBoris Popov return len; 69d8589bd5SBoris Popov } 70d8589bd5SBoris Popov 71d8589bd5SBoris Popov int 72d8589bd5SBoris Popov mb_init(struct mbchain *mbp) 73d8589bd5SBoris Popov { 74d8589bd5SBoris Popov struct mbuf *m; 75d8589bd5SBoris Popov 76d8589bd5SBoris Popov m = m_gethdr(M_TRYWAIT, MT_DATA); 77d8589bd5SBoris Popov if (m == NULL) 78d8589bd5SBoris Popov return ENOBUFS; 79d8589bd5SBoris Popov m->m_len = 0; 80d8589bd5SBoris Popov mb_initm(mbp, m); 81d8589bd5SBoris Popov return 0; 82d8589bd5SBoris Popov } 83d8589bd5SBoris Popov 84d8589bd5SBoris Popov void 85d8589bd5SBoris Popov mb_initm(struct mbchain *mbp, struct mbuf *m) 86d8589bd5SBoris Popov { 87d8589bd5SBoris Popov bzero(mbp, sizeof(*mbp)); 88d8589bd5SBoris Popov mbp->mb_top = mbp->mb_cur = m; 89d8589bd5SBoris Popov mbp->mb_mleft = M_TRAILINGSPACE(m); 90d8589bd5SBoris Popov } 91d8589bd5SBoris Popov 92d8589bd5SBoris Popov void 93d8589bd5SBoris Popov mb_done(struct mbchain *mbp) 94d8589bd5SBoris Popov { 95d8589bd5SBoris Popov if (mbp->mb_top) { 96d8589bd5SBoris Popov m_freem(mbp->mb_top); 97d8589bd5SBoris Popov mbp->mb_top = NULL; 98d8589bd5SBoris Popov } 99d8589bd5SBoris Popov } 100d8589bd5SBoris Popov 101d8589bd5SBoris Popov struct mbuf * 102d8589bd5SBoris Popov mb_detach(struct mbchain *mbp) 103d8589bd5SBoris Popov { 104d8589bd5SBoris Popov struct mbuf *m; 105d8589bd5SBoris Popov 106d8589bd5SBoris Popov m = mbp->mb_top; 107d8589bd5SBoris Popov mbp->mb_top = NULL; 108d8589bd5SBoris Popov return m; 109d8589bd5SBoris Popov } 110d8589bd5SBoris Popov 111d8589bd5SBoris Popov int 112d8589bd5SBoris Popov mb_fixhdr(struct mbchain *mbp) 113d8589bd5SBoris Popov { 114d8589bd5SBoris Popov return mbp->mb_top->m_pkthdr.len = m_fixhdr(mbp->mb_top); 115d8589bd5SBoris Popov } 116d8589bd5SBoris Popov 117d8589bd5SBoris Popov /* 118d8589bd5SBoris Popov * Check if object of size 'size' fit to the current position and 119d8589bd5SBoris Popov * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 120d8589bd5SBoris Popov * Return pointer to the object placeholder or NULL if any error occured. 121d8589bd5SBoris Popov * Note: size should be <= MLEN 122d8589bd5SBoris Popov */ 123d8589bd5SBoris Popov caddr_t 124d8589bd5SBoris Popov mb_reserve(struct mbchain *mbp, int size) 125d8589bd5SBoris Popov { 126d8589bd5SBoris Popov struct mbuf *m, *mn; 127d8589bd5SBoris Popov caddr_t bpos; 128d8589bd5SBoris Popov 129d8589bd5SBoris Popov if (size > MLEN) 130d8589bd5SBoris Popov panic("mb_reserve: size = %d\n", size); 131d8589bd5SBoris Popov m = mbp->mb_cur; 132d8589bd5SBoris Popov if (mbp->mb_mleft < size) { 133d8589bd5SBoris Popov mn = m_get(M_TRYWAIT, MT_DATA); 134d8589bd5SBoris Popov if (mn == NULL) 135d8589bd5SBoris Popov return NULL; 136d8589bd5SBoris Popov mbp->mb_cur = m->m_next = mn; 137d8589bd5SBoris Popov m = mn; 138d8589bd5SBoris Popov m->m_len = 0; 139d8589bd5SBoris Popov mbp->mb_mleft = M_TRAILINGSPACE(m); 140d8589bd5SBoris Popov } 141d8589bd5SBoris Popov mbp->mb_mleft -= size; 142d8589bd5SBoris Popov mbp->mb_count += size; 143d8589bd5SBoris Popov bpos = mtod(m, caddr_t) + m->m_len; 144d8589bd5SBoris Popov m->m_len += size; 145d8589bd5SBoris Popov return bpos; 146d8589bd5SBoris Popov } 147d8589bd5SBoris Popov 148d8589bd5SBoris Popov int 149d8589bd5SBoris Popov mb_put_uint8(struct mbchain *mbp, u_int8_t x) 150d8589bd5SBoris Popov { 151d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 152d8589bd5SBoris Popov } 153d8589bd5SBoris Popov 154d8589bd5SBoris Popov int 155d8589bd5SBoris Popov mb_put_uint16be(struct mbchain *mbp, u_int16_t x) 156d8589bd5SBoris Popov { 157d8589bd5SBoris Popov x = htobes(x); 158d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 159d8589bd5SBoris Popov } 160d8589bd5SBoris Popov 161d8589bd5SBoris Popov int 162d8589bd5SBoris Popov mb_put_uint16le(struct mbchain *mbp, u_int16_t x) 163d8589bd5SBoris Popov { 164d8589bd5SBoris Popov x = htoles(x); 165d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 166d8589bd5SBoris Popov } 167d8589bd5SBoris Popov 168d8589bd5SBoris Popov int 169d8589bd5SBoris Popov mb_put_uint32be(struct mbchain *mbp, u_int32_t x) 170d8589bd5SBoris Popov { 171d8589bd5SBoris Popov x = htobel(x); 172d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 173d8589bd5SBoris Popov } 174d8589bd5SBoris Popov 175d8589bd5SBoris Popov int 176d8589bd5SBoris Popov mb_put_uint32le(struct mbchain *mbp, u_int32_t x) 177d8589bd5SBoris Popov { 178d8589bd5SBoris Popov x = htolel(x); 179d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 180d8589bd5SBoris Popov } 181d8589bd5SBoris Popov 182d8589bd5SBoris Popov int 183d8589bd5SBoris Popov mb_put_int64be(struct mbchain *mbp, int64_t x) 184d8589bd5SBoris Popov { 185d8589bd5SBoris Popov x = htobeq(x); 186d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 187d8589bd5SBoris Popov } 188d8589bd5SBoris Popov 189d8589bd5SBoris Popov int 190d8589bd5SBoris Popov mb_put_int64le(struct mbchain *mbp, int64_t x) 191d8589bd5SBoris Popov { 192d8589bd5SBoris Popov x = htoleq(x); 193d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 194d8589bd5SBoris Popov } 195d8589bd5SBoris Popov 196d8589bd5SBoris Popov int 197d8589bd5SBoris Popov mb_put_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) 198d8589bd5SBoris Popov { 199d8589bd5SBoris Popov struct mbuf *m; 200d8589bd5SBoris Popov caddr_t dst; 201d8589bd5SBoris Popov c_caddr_t src; 202d8589bd5SBoris Popov int cplen, error, mleft, count; 203d8589bd5SBoris Popov 204d8589bd5SBoris Popov m = mbp->mb_cur; 205d8589bd5SBoris Popov mleft = mbp->mb_mleft; 206d8589bd5SBoris Popov 207d8589bd5SBoris Popov while (size > 0) { 208d8589bd5SBoris Popov if (mleft == 0) { 209d8589bd5SBoris Popov if (m->m_next == NULL) { 210d8589bd5SBoris Popov m = m_getm(m, size, M_TRYWAIT, MT_DATA); 211d8589bd5SBoris Popov if (m == NULL) 212d8589bd5SBoris Popov return ENOBUFS; 213d8589bd5SBoris Popov } 214d8589bd5SBoris Popov m = m->m_next; 215d8589bd5SBoris Popov mleft = M_TRAILINGSPACE(m); 216d8589bd5SBoris Popov continue; 217d8589bd5SBoris Popov } 218d8589bd5SBoris Popov cplen = mleft > size ? size : mleft; 219d8589bd5SBoris Popov dst = mtod(m, caddr_t) + m->m_len; 220d8589bd5SBoris Popov switch (type) { 221d8589bd5SBoris Popov case MB_MCUSTOM: 222d8589bd5SBoris Popov error = mbp->mb_copy(mbp, source, dst, cplen); 223d8589bd5SBoris Popov if (error) 224d8589bd5SBoris Popov return error; 225d8589bd5SBoris Popov break; 226d8589bd5SBoris Popov case MB_MINLINE: 227d8589bd5SBoris Popov for (src = source, count = cplen; count; count--) 228d8589bd5SBoris Popov *dst++ = *src++; 229d8589bd5SBoris Popov break; 230d8589bd5SBoris Popov case MB_MSYSTEM: 231d8589bd5SBoris Popov bcopy(source, dst, cplen); 232d8589bd5SBoris Popov break; 233d8589bd5SBoris Popov case MB_MUSER: 234d8589bd5SBoris Popov error = copyin(source, dst, cplen); 235d8589bd5SBoris Popov if (error) 236d8589bd5SBoris Popov return error; 237d8589bd5SBoris Popov break; 238d8589bd5SBoris Popov case MB_MZERO: 239d8589bd5SBoris Popov bzero(dst, cplen); 240d8589bd5SBoris Popov break; 241d8589bd5SBoris Popov } 242d8589bd5SBoris Popov size -= cplen; 243d8589bd5SBoris Popov source += cplen; 244d8589bd5SBoris Popov m->m_len += cplen; 245d8589bd5SBoris Popov mleft -= cplen; 246d8589bd5SBoris Popov mbp->mb_count += cplen; 247d8589bd5SBoris Popov } 248d8589bd5SBoris Popov mbp->mb_cur = m; 249d8589bd5SBoris Popov mbp->mb_mleft = mleft; 250d8589bd5SBoris Popov return 0; 251d8589bd5SBoris Popov } 252d8589bd5SBoris Popov 253d8589bd5SBoris Popov int 254d8589bd5SBoris Popov mb_put_mbuf(struct mbchain *mbp, struct mbuf *m) 255d8589bd5SBoris Popov { 256d8589bd5SBoris Popov mbp->mb_cur->m_next = m; 257d8589bd5SBoris Popov while (m) { 258d8589bd5SBoris Popov mbp->mb_count += m->m_len; 259d8589bd5SBoris Popov if (m->m_next == NULL) 260d8589bd5SBoris Popov break; 261d8589bd5SBoris Popov m = m->m_next; 262d8589bd5SBoris Popov } 263d8589bd5SBoris Popov mbp->mb_mleft = M_TRAILINGSPACE(m); 264d8589bd5SBoris Popov mbp->mb_cur = m; 265d8589bd5SBoris Popov return 0; 266d8589bd5SBoris Popov } 267d8589bd5SBoris Popov 268d8589bd5SBoris Popov /* 269d8589bd5SBoris Popov * copies a uio scatter/gather list to an mbuf chain. 270d8589bd5SBoris Popov */ 271d8589bd5SBoris Popov int 272d8589bd5SBoris Popov mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) 273d8589bd5SBoris Popov { 274d8589bd5SBoris Popov long left; 275d8589bd5SBoris Popov int mtype, error; 276d8589bd5SBoris Popov 277d8589bd5SBoris Popov mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 278d8589bd5SBoris Popov 279cebcee2eSBoris Popov while (size > 0 && uiop->uio_resid) { 280cebcee2eSBoris Popov if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 281cebcee2eSBoris Popov return EFBIG; 282d8589bd5SBoris Popov left = uiop->uio_iov->iov_len; 283cebcee2eSBoris Popov if (left == 0) { 284cebcee2eSBoris Popov uiop->uio_iov++; 285cebcee2eSBoris Popov uiop->uio_iovcnt--; 286cebcee2eSBoris Popov continue; 287cebcee2eSBoris Popov } 288d8589bd5SBoris Popov if (left > size) 289d8589bd5SBoris Popov left = size; 290d8589bd5SBoris Popov error = mb_put_mem(mbp, uiop->uio_iov->iov_base, left, mtype); 291d8589bd5SBoris Popov if (error) 292d8589bd5SBoris Popov return error; 293d8589bd5SBoris Popov uiop->uio_offset += left; 294d8589bd5SBoris Popov uiop->uio_resid -= left; 295d8589bd5SBoris Popov uiop->uio_iov->iov_base += left; 296d8589bd5SBoris Popov uiop->uio_iov->iov_len -= left; 297d8589bd5SBoris Popov size -= left; 298d8589bd5SBoris Popov } 299d8589bd5SBoris Popov return 0; 300d8589bd5SBoris Popov } 301d8589bd5SBoris Popov 302d8589bd5SBoris Popov /* 303d8589bd5SBoris Popov * Routines for fetching data from an mbuf chain 304d8589bd5SBoris Popov */ 305d8589bd5SBoris Popov int 306d8589bd5SBoris Popov md_init(struct mdchain *mdp) 307d8589bd5SBoris Popov { 308d8589bd5SBoris Popov struct mbuf *m; 309d8589bd5SBoris Popov 310d8589bd5SBoris Popov m = m_gethdr(M_TRYWAIT, MT_DATA); 311d8589bd5SBoris Popov if (m == NULL) 312d8589bd5SBoris Popov return ENOBUFS; 313d8589bd5SBoris Popov m->m_len = 0; 314d8589bd5SBoris Popov md_initm(mdp, m); 315d8589bd5SBoris Popov return 0; 316d8589bd5SBoris Popov } 317d8589bd5SBoris Popov 318d8589bd5SBoris Popov void 319d8589bd5SBoris Popov md_initm(struct mdchain *mdp, struct mbuf *m) 320d8589bd5SBoris Popov { 321d8589bd5SBoris Popov bzero(mdp, sizeof(*mdp)); 322d8589bd5SBoris Popov mdp->md_top = mdp->md_cur = m; 323d8589bd5SBoris Popov mdp->md_pos = mtod(m, u_char*); 324d8589bd5SBoris Popov } 325d8589bd5SBoris Popov 326d8589bd5SBoris Popov void 327d8589bd5SBoris Popov md_done(struct mdchain *mdp) 328d8589bd5SBoris Popov { 329d8589bd5SBoris Popov if (mdp->md_top) { 330d8589bd5SBoris Popov m_freem(mdp->md_top); 331d8589bd5SBoris Popov mdp->md_top = NULL; 332d8589bd5SBoris Popov } 333d8589bd5SBoris Popov } 334d8589bd5SBoris Popov 335d8589bd5SBoris Popov /* 336d8589bd5SBoris Popov * Append a separate mbuf chain. It is caller responsibility to prevent 337d8589bd5SBoris Popov * multiple calls to fetch/record routines. 338d8589bd5SBoris Popov */ 339d8589bd5SBoris Popov void 340d8589bd5SBoris Popov md_append_record(struct mdchain *mdp, struct mbuf *top) 341d8589bd5SBoris Popov { 342d8589bd5SBoris Popov struct mbuf *m; 343d8589bd5SBoris Popov 344d8589bd5SBoris Popov if (mdp->md_top == NULL) { 345d8589bd5SBoris Popov md_initm(mdp, top); 346d8589bd5SBoris Popov return; 347d8589bd5SBoris Popov } 348d8589bd5SBoris Popov m = mdp->md_top; 349d8589bd5SBoris Popov while (m->m_nextpkt) 350d8589bd5SBoris Popov m = m->m_nextpkt; 351d8589bd5SBoris Popov m->m_nextpkt = top; 352d8589bd5SBoris Popov top->m_nextpkt = NULL; 353d8589bd5SBoris Popov return; 354d8589bd5SBoris Popov } 355d8589bd5SBoris Popov 356d8589bd5SBoris Popov /* 357d8589bd5SBoris Popov * Put next record in place of existing 358d8589bd5SBoris Popov */ 359d8589bd5SBoris Popov int 360d8589bd5SBoris Popov md_next_record(struct mdchain *mdp) 361d8589bd5SBoris Popov { 362d8589bd5SBoris Popov struct mbuf *m; 363d8589bd5SBoris Popov 364d8589bd5SBoris Popov if (mdp->md_top == NULL) 365d8589bd5SBoris Popov return ENOENT; 366d8589bd5SBoris Popov m = mdp->md_top->m_nextpkt; 367d8589bd5SBoris Popov md_done(mdp); 368d8589bd5SBoris Popov if (m == NULL) 369d8589bd5SBoris Popov return ENOENT; 370d8589bd5SBoris Popov md_initm(mdp, m); 371d8589bd5SBoris Popov return 0; 372d8589bd5SBoris Popov } 373d8589bd5SBoris Popov 374d8589bd5SBoris Popov int 375d8589bd5SBoris Popov md_get_uint8(struct mdchain *mdp, u_int8_t *x) 376d8589bd5SBoris Popov { 377d8589bd5SBoris Popov return md_get_mem(mdp, x, 1, MB_MINLINE); 378d8589bd5SBoris Popov } 379d8589bd5SBoris Popov 380d8589bd5SBoris Popov int 381d8589bd5SBoris Popov md_get_uint16(struct mdchain *mdp, u_int16_t *x) 382d8589bd5SBoris Popov { 383d8589bd5SBoris Popov return md_get_mem(mdp, (caddr_t)x, 2, MB_MINLINE); 384d8589bd5SBoris Popov } 385d8589bd5SBoris Popov 386d8589bd5SBoris Popov int 387d8589bd5SBoris Popov md_get_uint16le(struct mdchain *mdp, u_int16_t *x) 388d8589bd5SBoris Popov { 389d8589bd5SBoris Popov u_int16_t v; 390d8589bd5SBoris Popov int error = md_get_uint16(mdp, &v); 391d8589bd5SBoris Popov 392d8589bd5SBoris Popov *x = letohs(v); 393d8589bd5SBoris Popov return error; 394d8589bd5SBoris Popov } 395d8589bd5SBoris Popov 396d8589bd5SBoris Popov int 397d8589bd5SBoris Popov md_get_uint16be(struct mdchain *mdp, u_int16_t *x) { 398d8589bd5SBoris Popov u_int16_t v; 399d8589bd5SBoris Popov int error = md_get_uint16(mdp, &v); 400d8589bd5SBoris Popov 401d8589bd5SBoris Popov *x = betohs(v); 402d8589bd5SBoris Popov return error; 403d8589bd5SBoris Popov } 404d8589bd5SBoris Popov 405d8589bd5SBoris Popov int 406d8589bd5SBoris Popov md_get_uint32(struct mdchain *mdp, u_int32_t *x) 407d8589bd5SBoris Popov { 408d8589bd5SBoris Popov return md_get_mem(mdp, (caddr_t)x, 4, MB_MINLINE); 409d8589bd5SBoris Popov } 410d8589bd5SBoris Popov 411d8589bd5SBoris Popov int 412d8589bd5SBoris Popov md_get_uint32be(struct mdchain *mdp, u_int32_t *x) 413d8589bd5SBoris Popov { 414d8589bd5SBoris Popov u_int32_t v; 415d8589bd5SBoris Popov int error; 416d8589bd5SBoris Popov 417d8589bd5SBoris Popov error = md_get_uint32(mdp, &v); 418d8589bd5SBoris Popov *x = betohl(v); 419d8589bd5SBoris Popov return error; 420d8589bd5SBoris Popov } 421d8589bd5SBoris Popov 422d8589bd5SBoris Popov int 423d8589bd5SBoris Popov md_get_uint32le(struct mdchain *mdp, u_int32_t *x) 424d8589bd5SBoris Popov { 425d8589bd5SBoris Popov u_int32_t v; 426d8589bd5SBoris Popov int error; 427d8589bd5SBoris Popov 428d8589bd5SBoris Popov error = md_get_uint32(mdp, &v); 429d8589bd5SBoris Popov *x = letohl(v); 430d8589bd5SBoris Popov return error; 431d8589bd5SBoris Popov } 432d8589bd5SBoris Popov 433d8589bd5SBoris Popov int 434d8589bd5SBoris Popov md_get_int64(struct mdchain *mdp, int64_t *x) 435d8589bd5SBoris Popov { 436d8589bd5SBoris Popov return md_get_mem(mdp, (caddr_t)x, 8, MB_MINLINE); 437d8589bd5SBoris Popov } 438d8589bd5SBoris Popov 439d8589bd5SBoris Popov int 440d8589bd5SBoris Popov md_get_int64be(struct mdchain *mdp, int64_t *x) 441d8589bd5SBoris Popov { 442d8589bd5SBoris Popov int64_t v; 443d8589bd5SBoris Popov int error; 444d8589bd5SBoris Popov 445d8589bd5SBoris Popov error = md_get_int64(mdp, &v); 446d8589bd5SBoris Popov *x = betohq(v); 447d8589bd5SBoris Popov return error; 448d8589bd5SBoris Popov } 449d8589bd5SBoris Popov 450d8589bd5SBoris Popov int 451d8589bd5SBoris Popov md_get_int64le(struct mdchain *mdp, int64_t *x) 452d8589bd5SBoris Popov { 453d8589bd5SBoris Popov int64_t v; 454d8589bd5SBoris Popov int error; 455d8589bd5SBoris Popov 456d8589bd5SBoris Popov error = md_get_int64(mdp, &v); 457d8589bd5SBoris Popov *x = letohq(v); 458d8589bd5SBoris Popov return error; 459d8589bd5SBoris Popov } 460d8589bd5SBoris Popov 461d8589bd5SBoris Popov int 462d8589bd5SBoris Popov md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type) 463d8589bd5SBoris Popov { 464d8589bd5SBoris Popov struct mbuf *m = mdp->md_cur; 465d8589bd5SBoris Popov int error; 466d8589bd5SBoris Popov u_int count; 467d8589bd5SBoris Popov u_char *s; 468d8589bd5SBoris Popov 469d8589bd5SBoris Popov while (size > 0) { 470d8589bd5SBoris Popov if (m == NULL) { 471d8589bd5SBoris Popov MBERROR("incomplete copy\n"); 472d8589bd5SBoris Popov return EBADRPC; 473d8589bd5SBoris Popov } 474d8589bd5SBoris Popov s = mdp->md_pos; 475d8589bd5SBoris Popov count = mtod(m, u_char*) + m->m_len - s; 476d8589bd5SBoris Popov if (count == 0) { 477d8589bd5SBoris Popov mdp->md_cur = m = m->m_next; 478d8589bd5SBoris Popov if (m) 479d8589bd5SBoris Popov s = mdp->md_pos = mtod(m, caddr_t); 480d8589bd5SBoris Popov continue; 481d8589bd5SBoris Popov } 482d8589bd5SBoris Popov if (count > size) 483d8589bd5SBoris Popov count = size; 484d8589bd5SBoris Popov size -= count; 485d8589bd5SBoris Popov mdp->md_pos += count; 486d8589bd5SBoris Popov if (target == NULL) 487d8589bd5SBoris Popov continue; 488d8589bd5SBoris Popov switch (type) { 489d8589bd5SBoris Popov case MB_MUSER: 490d8589bd5SBoris Popov error = copyout(s, target, count); 491d8589bd5SBoris Popov if (error) 492d8589bd5SBoris Popov return error; 493d8589bd5SBoris Popov break; 494d8589bd5SBoris Popov case MB_MSYSTEM: 495d8589bd5SBoris Popov bcopy(s, target, count); 496d8589bd5SBoris Popov break; 497d8589bd5SBoris Popov case MB_MINLINE: 498d8589bd5SBoris Popov while (count--) 499d8589bd5SBoris Popov *target++ = *s++; 500d8589bd5SBoris Popov continue; 501d8589bd5SBoris Popov } 502d8589bd5SBoris Popov target += count; 503d8589bd5SBoris Popov } 504d8589bd5SBoris Popov return 0; 505d8589bd5SBoris Popov } 506d8589bd5SBoris Popov 507d8589bd5SBoris Popov int 508d8589bd5SBoris Popov md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **ret) 509d8589bd5SBoris Popov { 510d8589bd5SBoris Popov struct mbuf *m = mdp->md_cur, *rm; 511d8589bd5SBoris Popov 512d8589bd5SBoris Popov rm = m_copym(m, mdp->md_pos - mtod(m, u_char*), size, M_TRYWAIT); 513d8589bd5SBoris Popov if (rm == NULL) 514d8589bd5SBoris Popov return EBADRPC; 515d8589bd5SBoris Popov md_get_mem(mdp, NULL, size, MB_MZERO); 516d8589bd5SBoris Popov *ret = rm; 517d8589bd5SBoris Popov return 0; 518d8589bd5SBoris Popov } 519d8589bd5SBoris Popov 520d8589bd5SBoris Popov int 521d8589bd5SBoris Popov md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) 522d8589bd5SBoris Popov { 523d8589bd5SBoris Popov char *uiocp; 524d8589bd5SBoris Popov long left; 525d8589bd5SBoris Popov int mtype, error; 526d8589bd5SBoris Popov 527d8589bd5SBoris Popov mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 528cebcee2eSBoris Popov while (size > 0 && uiop->uio_resid) { 529d8589bd5SBoris Popov if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 530d8589bd5SBoris Popov return EFBIG; 531d8589bd5SBoris Popov left = uiop->uio_iov->iov_len; 532cebcee2eSBoris Popov if (left == 0) { 533cebcee2eSBoris Popov uiop->uio_iov++; 534cebcee2eSBoris Popov uiop->uio_iovcnt--; 535cebcee2eSBoris Popov continue; 536cebcee2eSBoris Popov } 537d8589bd5SBoris Popov uiocp = uiop->uio_iov->iov_base; 538d8589bd5SBoris Popov if (left > size) 539d8589bd5SBoris Popov left = size; 540d8589bd5SBoris Popov error = md_get_mem(mdp, uiocp, left, mtype); 541d8589bd5SBoris Popov if (error) 542d8589bd5SBoris Popov return error; 543d8589bd5SBoris Popov uiop->uio_offset += left; 544d8589bd5SBoris Popov uiop->uio_resid -= left; 545d8589bd5SBoris Popov uiop->uio_iov->iov_base += left; 546d8589bd5SBoris Popov uiop->uio_iov->iov_len -= left; 547d8589bd5SBoris Popov size -= left; 548d8589bd5SBoris Popov } 549d8589bd5SBoris Popov return 0; 550d8589bd5SBoris Popov } 551