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