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 488deedb62SMark Murray #define MBERROR(format, ...) printf("%s(%d): "format, __func__ , \ 498deedb62SMark Murray __LINE__ , ## __VA_ARGS__) 50d8589bd5SBoris Popov 518deedb62SMark Murray #define MBPANIC(format, ...) printf("%s(%d): "format, __func__ , \ 528deedb62SMark Murray __LINE__ , ## __VA_ARGS__) 53d8589bd5SBoris Popov 54d8589bd5SBoris Popov /* 55d8589bd5SBoris Popov * Various helper functions 56d8589bd5SBoris Popov */ 57d8589bd5SBoris Popov int 58d8589bd5SBoris Popov mb_init(struct mbchain *mbp) 59d8589bd5SBoris Popov { 60d8589bd5SBoris Popov struct mbuf *m; 61d8589bd5SBoris Popov 62d8589bd5SBoris Popov m = m_gethdr(M_TRYWAIT, MT_DATA); 63d8589bd5SBoris Popov if (m == NULL) 64d8589bd5SBoris Popov return ENOBUFS; 65d8589bd5SBoris Popov m->m_len = 0; 66d8589bd5SBoris Popov mb_initm(mbp, m); 67d8589bd5SBoris Popov return 0; 68d8589bd5SBoris Popov } 69d8589bd5SBoris Popov 70d8589bd5SBoris Popov void 71d8589bd5SBoris Popov mb_initm(struct mbchain *mbp, struct mbuf *m) 72d8589bd5SBoris Popov { 73d8589bd5SBoris Popov bzero(mbp, sizeof(*mbp)); 74d8589bd5SBoris Popov mbp->mb_top = mbp->mb_cur = m; 75d8589bd5SBoris Popov mbp->mb_mleft = M_TRAILINGSPACE(m); 76d8589bd5SBoris Popov } 77d8589bd5SBoris Popov 78d8589bd5SBoris Popov void 79d8589bd5SBoris Popov mb_done(struct mbchain *mbp) 80d8589bd5SBoris Popov { 81d8589bd5SBoris Popov if (mbp->mb_top) { 82d8589bd5SBoris Popov m_freem(mbp->mb_top); 83d8589bd5SBoris Popov mbp->mb_top = NULL; 84d8589bd5SBoris Popov } 85d8589bd5SBoris Popov } 86d8589bd5SBoris Popov 87d8589bd5SBoris Popov struct mbuf * 88d8589bd5SBoris Popov mb_detach(struct mbchain *mbp) 89d8589bd5SBoris Popov { 90d8589bd5SBoris Popov struct mbuf *m; 91d8589bd5SBoris Popov 92d8589bd5SBoris Popov m = mbp->mb_top; 93d8589bd5SBoris Popov mbp->mb_top = NULL; 94d8589bd5SBoris Popov return m; 95d8589bd5SBoris Popov } 96d8589bd5SBoris Popov 97d8589bd5SBoris Popov int 98d8589bd5SBoris Popov mb_fixhdr(struct mbchain *mbp) 99d8589bd5SBoris Popov { 100d8589bd5SBoris Popov return mbp->mb_top->m_pkthdr.len = m_fixhdr(mbp->mb_top); 101d8589bd5SBoris Popov } 102d8589bd5SBoris Popov 103d8589bd5SBoris Popov /* 104d8589bd5SBoris Popov * Check if object of size 'size' fit to the current position and 105d8589bd5SBoris Popov * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 106d8589bd5SBoris Popov * Return pointer to the object placeholder or NULL if any error occured. 107d8589bd5SBoris Popov * Note: size should be <= MLEN 108d8589bd5SBoris Popov */ 109d8589bd5SBoris Popov caddr_t 110d8589bd5SBoris Popov mb_reserve(struct mbchain *mbp, int size) 111d8589bd5SBoris Popov { 112d8589bd5SBoris Popov struct mbuf *m, *mn; 113d8589bd5SBoris Popov caddr_t bpos; 114d8589bd5SBoris Popov 115d8589bd5SBoris Popov if (size > MLEN) 116d8589bd5SBoris Popov panic("mb_reserve: size = %d\n", size); 117d8589bd5SBoris Popov m = mbp->mb_cur; 118d8589bd5SBoris Popov if (mbp->mb_mleft < size) { 119d8589bd5SBoris Popov mn = m_get(M_TRYWAIT, MT_DATA); 120d8589bd5SBoris Popov if (mn == NULL) 121d8589bd5SBoris Popov return NULL; 122d8589bd5SBoris Popov mbp->mb_cur = m->m_next = mn; 123d8589bd5SBoris Popov m = mn; 124d8589bd5SBoris Popov m->m_len = 0; 125d8589bd5SBoris Popov mbp->mb_mleft = M_TRAILINGSPACE(m); 126d8589bd5SBoris Popov } 127d8589bd5SBoris Popov mbp->mb_mleft -= size; 128d8589bd5SBoris Popov mbp->mb_count += size; 129d8589bd5SBoris Popov bpos = mtod(m, caddr_t) + m->m_len; 130d8589bd5SBoris Popov m->m_len += size; 131d8589bd5SBoris Popov return bpos; 132d8589bd5SBoris Popov } 133d8589bd5SBoris Popov 134d8589bd5SBoris Popov int 135d8589bd5SBoris Popov mb_put_uint8(struct mbchain *mbp, u_int8_t x) 136d8589bd5SBoris Popov { 137d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 138d8589bd5SBoris Popov } 139d8589bd5SBoris Popov 140d8589bd5SBoris Popov int 141d8589bd5SBoris Popov mb_put_uint16be(struct mbchain *mbp, u_int16_t x) 142d8589bd5SBoris Popov { 143d8589bd5SBoris Popov x = htobes(x); 144d8589bd5SBoris Popov return mb_put_mem(mbp, (caddr_t)&x, sizeof(x), MB_MSYSTEM); 145d8589bd5SBoris Popov } 146d8589bd5SBoris Popov 147d8589bd5SBoris Popov int 148d8589bd5SBoris Popov mb_put_uint16le(struct mbchain *mbp, u_int16_t x) 149d8589bd5SBoris Popov { 150d8589bd5SBoris Popov x = htoles(x); 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_uint32be(struct mbchain *mbp, u_int32_t x) 156d8589bd5SBoris Popov { 157d8589bd5SBoris Popov x = htobel(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_uint32le(struct mbchain *mbp, u_int32_t x) 163d8589bd5SBoris Popov { 164d8589bd5SBoris Popov x = htolel(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_int64be(struct mbchain *mbp, int64_t x) 170d8589bd5SBoris Popov { 171d8589bd5SBoris Popov x = htobeq(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_int64le(struct mbchain *mbp, int64_t x) 177d8589bd5SBoris Popov { 178d8589bd5SBoris Popov x = htoleq(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_mem(struct mbchain *mbp, c_caddr_t source, int size, int type) 184d8589bd5SBoris Popov { 185d8589bd5SBoris Popov struct mbuf *m; 186d8589bd5SBoris Popov caddr_t dst; 187d8589bd5SBoris Popov c_caddr_t src; 188d8589bd5SBoris Popov int cplen, error, mleft, count; 189d8589bd5SBoris Popov 190d8589bd5SBoris Popov m = mbp->mb_cur; 191d8589bd5SBoris Popov mleft = mbp->mb_mleft; 192d8589bd5SBoris Popov 193d8589bd5SBoris Popov while (size > 0) { 194d8589bd5SBoris Popov if (mleft == 0) { 195d8589bd5SBoris Popov if (m->m_next == NULL) { 196d8589bd5SBoris Popov m = m_getm(m, size, M_TRYWAIT, MT_DATA); 197d8589bd5SBoris Popov if (m == NULL) 198d8589bd5SBoris Popov return ENOBUFS; 199d8589bd5SBoris Popov } 200d8589bd5SBoris Popov m = m->m_next; 201d8589bd5SBoris Popov mleft = M_TRAILINGSPACE(m); 202d8589bd5SBoris Popov continue; 203d8589bd5SBoris Popov } 204d8589bd5SBoris Popov cplen = mleft > size ? size : mleft; 205d8589bd5SBoris Popov dst = mtod(m, caddr_t) + m->m_len; 206d8589bd5SBoris Popov switch (type) { 207d8589bd5SBoris Popov case MB_MCUSTOM: 208d8589bd5SBoris Popov error = mbp->mb_copy(mbp, source, dst, cplen); 209d8589bd5SBoris Popov if (error) 210d8589bd5SBoris Popov return error; 211d8589bd5SBoris Popov break; 212d8589bd5SBoris Popov case MB_MINLINE: 213d8589bd5SBoris Popov for (src = source, count = cplen; count; count--) 214d8589bd5SBoris Popov *dst++ = *src++; 215d8589bd5SBoris Popov break; 216d8589bd5SBoris Popov case MB_MSYSTEM: 217d8589bd5SBoris Popov bcopy(source, dst, cplen); 218d8589bd5SBoris Popov break; 219d8589bd5SBoris Popov case MB_MUSER: 220d8589bd5SBoris Popov error = copyin(source, dst, cplen); 221d8589bd5SBoris Popov if (error) 222d8589bd5SBoris Popov return error; 223d8589bd5SBoris Popov break; 224d8589bd5SBoris Popov case MB_MZERO: 225d8589bd5SBoris Popov bzero(dst, cplen); 226d8589bd5SBoris Popov break; 227d8589bd5SBoris Popov } 228d8589bd5SBoris Popov size -= cplen; 229d8589bd5SBoris Popov source += cplen; 230d8589bd5SBoris Popov m->m_len += cplen; 231d8589bd5SBoris Popov mleft -= cplen; 232d8589bd5SBoris Popov mbp->mb_count += cplen; 233d8589bd5SBoris Popov } 234d8589bd5SBoris Popov mbp->mb_cur = m; 235d8589bd5SBoris Popov mbp->mb_mleft = mleft; 236d8589bd5SBoris Popov return 0; 237d8589bd5SBoris Popov } 238d8589bd5SBoris Popov 239d8589bd5SBoris Popov int 240d8589bd5SBoris Popov mb_put_mbuf(struct mbchain *mbp, struct mbuf *m) 241d8589bd5SBoris Popov { 242d8589bd5SBoris Popov mbp->mb_cur->m_next = m; 243d8589bd5SBoris Popov while (m) { 244d8589bd5SBoris Popov mbp->mb_count += m->m_len; 245d8589bd5SBoris Popov if (m->m_next == NULL) 246d8589bd5SBoris Popov break; 247d8589bd5SBoris Popov m = m->m_next; 248d8589bd5SBoris Popov } 249d8589bd5SBoris Popov mbp->mb_mleft = M_TRAILINGSPACE(m); 250d8589bd5SBoris Popov mbp->mb_cur = m; 251d8589bd5SBoris Popov return 0; 252d8589bd5SBoris Popov } 253d8589bd5SBoris Popov 254d8589bd5SBoris Popov /* 255d8589bd5SBoris Popov * copies a uio scatter/gather list to an mbuf chain. 256d8589bd5SBoris Popov */ 257d8589bd5SBoris Popov int 258d8589bd5SBoris Popov mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) 259d8589bd5SBoris Popov { 260d8589bd5SBoris Popov long left; 261d8589bd5SBoris Popov int mtype, error; 262d8589bd5SBoris Popov 263d8589bd5SBoris Popov mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 264d8589bd5SBoris Popov 265cebcee2eSBoris Popov while (size > 0 && uiop->uio_resid) { 266cebcee2eSBoris Popov if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 267cebcee2eSBoris Popov return EFBIG; 268d8589bd5SBoris Popov left = uiop->uio_iov->iov_len; 269cebcee2eSBoris Popov if (left == 0) { 270cebcee2eSBoris Popov uiop->uio_iov++; 271cebcee2eSBoris Popov uiop->uio_iovcnt--; 272cebcee2eSBoris Popov continue; 273cebcee2eSBoris Popov } 274d8589bd5SBoris Popov if (left > size) 275d8589bd5SBoris Popov left = size; 276d8589bd5SBoris Popov error = mb_put_mem(mbp, uiop->uio_iov->iov_base, left, mtype); 277d8589bd5SBoris Popov if (error) 278d8589bd5SBoris Popov return error; 279d8589bd5SBoris Popov uiop->uio_offset += left; 280d8589bd5SBoris Popov uiop->uio_resid -= left; 2812b7f24d2SMike Barcroft uiop->uio_iov->iov_base = 2822b7f24d2SMike Barcroft (char *)uiop->uio_iov->iov_base + left; 283d8589bd5SBoris Popov uiop->uio_iov->iov_len -= left; 284d8589bd5SBoris Popov size -= left; 285d8589bd5SBoris Popov } 286d8589bd5SBoris Popov return 0; 287d8589bd5SBoris Popov } 288d8589bd5SBoris Popov 289d8589bd5SBoris Popov /* 290d8589bd5SBoris Popov * Routines for fetching data from an mbuf chain 291d8589bd5SBoris Popov */ 292d8589bd5SBoris Popov int 293d8589bd5SBoris Popov md_init(struct mdchain *mdp) 294d8589bd5SBoris Popov { 295d8589bd5SBoris Popov struct mbuf *m; 296d8589bd5SBoris Popov 297d8589bd5SBoris Popov m = m_gethdr(M_TRYWAIT, MT_DATA); 298d8589bd5SBoris Popov if (m == NULL) 299d8589bd5SBoris Popov return ENOBUFS; 300d8589bd5SBoris Popov m->m_len = 0; 301d8589bd5SBoris Popov md_initm(mdp, m); 302d8589bd5SBoris Popov return 0; 303d8589bd5SBoris Popov } 304d8589bd5SBoris Popov 305d8589bd5SBoris Popov void 306d8589bd5SBoris Popov md_initm(struct mdchain *mdp, struct mbuf *m) 307d8589bd5SBoris Popov { 308d8589bd5SBoris Popov bzero(mdp, sizeof(*mdp)); 309d8589bd5SBoris Popov mdp->md_top = mdp->md_cur = m; 310d8589bd5SBoris Popov mdp->md_pos = mtod(m, u_char*); 311d8589bd5SBoris Popov } 312d8589bd5SBoris Popov 313d8589bd5SBoris Popov void 314d8589bd5SBoris Popov md_done(struct mdchain *mdp) 315d8589bd5SBoris Popov { 316d8589bd5SBoris Popov if (mdp->md_top) { 317d8589bd5SBoris Popov m_freem(mdp->md_top); 318d8589bd5SBoris Popov mdp->md_top = NULL; 319d8589bd5SBoris Popov } 320d8589bd5SBoris Popov } 321d8589bd5SBoris Popov 322d8589bd5SBoris Popov /* 323d8589bd5SBoris Popov * Append a separate mbuf chain. It is caller responsibility to prevent 324d8589bd5SBoris Popov * multiple calls to fetch/record routines. 325d8589bd5SBoris Popov */ 326d8589bd5SBoris Popov void 327d8589bd5SBoris Popov md_append_record(struct mdchain *mdp, struct mbuf *top) 328d8589bd5SBoris Popov { 329d8589bd5SBoris Popov struct mbuf *m; 330d8589bd5SBoris Popov 331d8589bd5SBoris Popov if (mdp->md_top == NULL) { 332d8589bd5SBoris Popov md_initm(mdp, top); 333d8589bd5SBoris Popov return; 334d8589bd5SBoris Popov } 335d8589bd5SBoris Popov m = mdp->md_top; 336d8589bd5SBoris Popov while (m->m_nextpkt) 337d8589bd5SBoris Popov m = m->m_nextpkt; 338d8589bd5SBoris Popov m->m_nextpkt = top; 339d8589bd5SBoris Popov top->m_nextpkt = NULL; 340d8589bd5SBoris Popov return; 341d8589bd5SBoris Popov } 342d8589bd5SBoris Popov 343d8589bd5SBoris Popov /* 344d8589bd5SBoris Popov * Put next record in place of existing 345d8589bd5SBoris Popov */ 346d8589bd5SBoris Popov int 347d8589bd5SBoris Popov md_next_record(struct mdchain *mdp) 348d8589bd5SBoris Popov { 349d8589bd5SBoris Popov struct mbuf *m; 350d8589bd5SBoris Popov 351d8589bd5SBoris Popov if (mdp->md_top == NULL) 352d8589bd5SBoris Popov return ENOENT; 353d8589bd5SBoris Popov m = mdp->md_top->m_nextpkt; 354d8589bd5SBoris Popov md_done(mdp); 355d8589bd5SBoris Popov if (m == NULL) 356d8589bd5SBoris Popov return ENOENT; 357d8589bd5SBoris Popov md_initm(mdp, m); 358d8589bd5SBoris Popov return 0; 359d8589bd5SBoris Popov } 360d8589bd5SBoris Popov 361d8589bd5SBoris Popov int 362d8589bd5SBoris Popov md_get_uint8(struct mdchain *mdp, u_int8_t *x) 363d8589bd5SBoris Popov { 364d8589bd5SBoris Popov return md_get_mem(mdp, x, 1, MB_MINLINE); 365d8589bd5SBoris Popov } 366d8589bd5SBoris Popov 367d8589bd5SBoris Popov int 368d8589bd5SBoris Popov md_get_uint16(struct mdchain *mdp, u_int16_t *x) 369d8589bd5SBoris Popov { 370d8589bd5SBoris Popov return md_get_mem(mdp, (caddr_t)x, 2, MB_MINLINE); 371d8589bd5SBoris Popov } 372d8589bd5SBoris Popov 373d8589bd5SBoris Popov int 374d8589bd5SBoris Popov md_get_uint16le(struct mdchain *mdp, u_int16_t *x) 375d8589bd5SBoris Popov { 376d8589bd5SBoris Popov u_int16_t v; 377d8589bd5SBoris Popov int error = md_get_uint16(mdp, &v); 378d8589bd5SBoris Popov 379d8589bd5SBoris Popov *x = letohs(v); 380d8589bd5SBoris Popov return error; 381d8589bd5SBoris Popov } 382d8589bd5SBoris Popov 383d8589bd5SBoris Popov int 384d8589bd5SBoris Popov md_get_uint16be(struct mdchain *mdp, u_int16_t *x) { 385d8589bd5SBoris Popov u_int16_t v; 386d8589bd5SBoris Popov int error = md_get_uint16(mdp, &v); 387d8589bd5SBoris Popov 388d8589bd5SBoris Popov *x = betohs(v); 389d8589bd5SBoris Popov return error; 390d8589bd5SBoris Popov } 391d8589bd5SBoris Popov 392d8589bd5SBoris Popov int 393d8589bd5SBoris Popov md_get_uint32(struct mdchain *mdp, u_int32_t *x) 394d8589bd5SBoris Popov { 395d8589bd5SBoris Popov return md_get_mem(mdp, (caddr_t)x, 4, MB_MINLINE); 396d8589bd5SBoris Popov } 397d8589bd5SBoris Popov 398d8589bd5SBoris Popov int 399d8589bd5SBoris Popov md_get_uint32be(struct mdchain *mdp, u_int32_t *x) 400d8589bd5SBoris Popov { 401d8589bd5SBoris Popov u_int32_t v; 402d8589bd5SBoris Popov int error; 403d8589bd5SBoris Popov 404d8589bd5SBoris Popov error = md_get_uint32(mdp, &v); 405d8589bd5SBoris Popov *x = betohl(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); 416d8589bd5SBoris Popov *x = letohl(v); 417d8589bd5SBoris Popov return error; 418d8589bd5SBoris Popov } 419d8589bd5SBoris Popov 420d8589bd5SBoris Popov int 421d8589bd5SBoris Popov md_get_int64(struct mdchain *mdp, int64_t *x) 422d8589bd5SBoris Popov { 423d8589bd5SBoris Popov return md_get_mem(mdp, (caddr_t)x, 8, MB_MINLINE); 424d8589bd5SBoris Popov } 425d8589bd5SBoris Popov 426d8589bd5SBoris Popov int 427d8589bd5SBoris Popov md_get_int64be(struct mdchain *mdp, int64_t *x) 428d8589bd5SBoris Popov { 429d8589bd5SBoris Popov int64_t v; 430d8589bd5SBoris Popov int error; 431d8589bd5SBoris Popov 432d8589bd5SBoris Popov error = md_get_int64(mdp, &v); 433d8589bd5SBoris Popov *x = betohq(v); 434d8589bd5SBoris Popov return error; 435d8589bd5SBoris Popov } 436d8589bd5SBoris Popov 437d8589bd5SBoris Popov int 438d8589bd5SBoris Popov md_get_int64le(struct mdchain *mdp, int64_t *x) 439d8589bd5SBoris Popov { 440d8589bd5SBoris Popov int64_t v; 441d8589bd5SBoris Popov int error; 442d8589bd5SBoris Popov 443d8589bd5SBoris Popov error = md_get_int64(mdp, &v); 444d8589bd5SBoris Popov *x = letohq(v); 445d8589bd5SBoris Popov return error; 446d8589bd5SBoris Popov } 447d8589bd5SBoris Popov 448d8589bd5SBoris Popov int 449d8589bd5SBoris Popov md_get_mem(struct mdchain *mdp, caddr_t target, int size, int type) 450d8589bd5SBoris Popov { 451d8589bd5SBoris Popov struct mbuf *m = mdp->md_cur; 452d8589bd5SBoris Popov int error; 453d8589bd5SBoris Popov u_int count; 454d8589bd5SBoris Popov u_char *s; 455d8589bd5SBoris Popov 456d8589bd5SBoris Popov while (size > 0) { 457d8589bd5SBoris Popov if (m == NULL) { 458d8589bd5SBoris Popov MBERROR("incomplete copy\n"); 459d8589bd5SBoris Popov return EBADRPC; 460d8589bd5SBoris Popov } 461d8589bd5SBoris Popov s = mdp->md_pos; 462d8589bd5SBoris Popov count = mtod(m, u_char*) + m->m_len - s; 463d8589bd5SBoris Popov if (count == 0) { 464d8589bd5SBoris Popov mdp->md_cur = m = m->m_next; 465d8589bd5SBoris Popov if (m) 466d8589bd5SBoris Popov s = mdp->md_pos = mtod(m, caddr_t); 467d8589bd5SBoris Popov continue; 468d8589bd5SBoris Popov } 469d8589bd5SBoris Popov if (count > size) 470d8589bd5SBoris Popov count = size; 471d8589bd5SBoris Popov size -= count; 472d8589bd5SBoris Popov mdp->md_pos += count; 473d8589bd5SBoris Popov if (target == NULL) 474d8589bd5SBoris Popov continue; 475d8589bd5SBoris Popov switch (type) { 476d8589bd5SBoris Popov case MB_MUSER: 477d8589bd5SBoris Popov error = copyout(s, target, count); 478d8589bd5SBoris Popov if (error) 479d8589bd5SBoris Popov return error; 480d8589bd5SBoris Popov break; 481d8589bd5SBoris Popov case MB_MSYSTEM: 482d8589bd5SBoris Popov bcopy(s, target, count); 483d8589bd5SBoris Popov break; 484d8589bd5SBoris Popov case MB_MINLINE: 485d8589bd5SBoris Popov while (count--) 486d8589bd5SBoris Popov *target++ = *s++; 487d8589bd5SBoris Popov continue; 488d8589bd5SBoris Popov } 489d8589bd5SBoris Popov target += count; 490d8589bd5SBoris Popov } 491d8589bd5SBoris Popov return 0; 492d8589bd5SBoris Popov } 493d8589bd5SBoris Popov 494d8589bd5SBoris Popov int 495d8589bd5SBoris Popov md_get_mbuf(struct mdchain *mdp, int size, struct mbuf **ret) 496d8589bd5SBoris Popov { 497d8589bd5SBoris Popov struct mbuf *m = mdp->md_cur, *rm; 498d8589bd5SBoris Popov 499d8589bd5SBoris Popov rm = m_copym(m, mdp->md_pos - mtod(m, u_char*), size, M_TRYWAIT); 500d8589bd5SBoris Popov if (rm == NULL) 501d8589bd5SBoris Popov return EBADRPC; 502d8589bd5SBoris Popov md_get_mem(mdp, NULL, size, MB_MZERO); 503d8589bd5SBoris Popov *ret = rm; 504d8589bd5SBoris Popov return 0; 505d8589bd5SBoris Popov } 506d8589bd5SBoris Popov 507d8589bd5SBoris Popov int 508d8589bd5SBoris Popov md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) 509d8589bd5SBoris Popov { 510d8589bd5SBoris Popov char *uiocp; 511d8589bd5SBoris Popov long left; 512d8589bd5SBoris Popov int mtype, error; 513d8589bd5SBoris Popov 514d8589bd5SBoris Popov mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; 515cebcee2eSBoris Popov while (size > 0 && uiop->uio_resid) { 516d8589bd5SBoris Popov if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 517d8589bd5SBoris Popov return EFBIG; 518d8589bd5SBoris Popov left = uiop->uio_iov->iov_len; 519cebcee2eSBoris Popov if (left == 0) { 520cebcee2eSBoris Popov uiop->uio_iov++; 521cebcee2eSBoris Popov uiop->uio_iovcnt--; 522cebcee2eSBoris Popov continue; 523cebcee2eSBoris Popov } 524d8589bd5SBoris Popov uiocp = uiop->uio_iov->iov_base; 525d8589bd5SBoris Popov if (left > size) 526d8589bd5SBoris Popov left = size; 527d8589bd5SBoris Popov error = md_get_mem(mdp, uiocp, left, mtype); 528d8589bd5SBoris Popov if (error) 529d8589bd5SBoris Popov return error; 530d8589bd5SBoris Popov uiop->uio_offset += left; 531d8589bd5SBoris Popov uiop->uio_resid -= left; 5322b7f24d2SMike Barcroft uiop->uio_iov->iov_base = 5332b7f24d2SMike Barcroft (char *)uiop->uio_iov->iov_base + left; 534d8589bd5SBoris Popov uiop->uio_iov->iov_len -= left; 535d8589bd5SBoris Popov size -= left; 536d8589bd5SBoris Popov } 537d8589bd5SBoris Popov return 0; 538d8589bd5SBoris Popov } 539