14bff34e3Sthurlow /* 24bff34e3Sthurlow * Copyright (c) 2000, Boris Popov 34bff34e3Sthurlow * All rights reserved. 44bff34e3Sthurlow * 54bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 64bff34e3Sthurlow * modification, are permitted provided that the following conditions 74bff34e3Sthurlow * are met: 84bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 94bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 104bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 114bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 124bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 134bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 144bff34e3Sthurlow * must display the following acknowledgement: 154bff34e3Sthurlow * This product includes software developed by Boris Popov. 164bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 174bff34e3Sthurlow * may be used to endorse or promote products derived from this software 184bff34e3Sthurlow * without specific prior written permission. 194bff34e3Sthurlow * 204bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 214bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 244bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304bff34e3Sthurlow * SUCH DAMAGE. 314bff34e3Sthurlow * 324bff34e3Sthurlow * $Id: mbuf.c,v 1.3 2004/12/13 00:25:22 lindak Exp $ 334bff34e3Sthurlow */ 344bff34e3Sthurlow 359c9af259SGordon Ross /* 36613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 379c9af259SGordon Ross * Use is subject to license terms. 389c9af259SGordon Ross */ 394bff34e3Sthurlow 404bff34e3Sthurlow #include <sys/types.h> 414bff34e3Sthurlow #include <ctype.h> 424bff34e3Sthurlow #include <errno.h> 434bff34e3Sthurlow #include <stdio.h> 444bff34e3Sthurlow #include <stdlib.h> 454bff34e3Sthurlow #include <string.h> 464bff34e3Sthurlow #include <strings.h> 474bff34e3Sthurlow #include <libintl.h> 487568150aSgwr #include <assert.h> 494bff34e3Sthurlow 504bff34e3Sthurlow #include <netsmb/smb_lib.h> 514bff34e3Sthurlow #include <netsmb/mchain.h> 524bff34e3Sthurlow 539c9af259SGordon Ross #include "private.h" 54613a2f6bSGordon Ross #include "charsets.h" 554bff34e3Sthurlow 56*02d09e03SGordon Ross /* 57*02d09e03SGordon Ross * Note: Leaving a little space (8 bytes) between the 58*02d09e03SGordon Ross * mbuf header and the start of the data so we can 59*02d09e03SGordon Ross * prepend a NetBIOS header in that space. 60*02d09e03SGordon Ross */ 61*02d09e03SGordon Ross #define M_ALIGNFACTOR (sizeof (long)) 62*02d09e03SGordon Ross #define M_ALIGN(len) (((len) + M_ALIGNFACTOR - 1) & ~(M_ALIGNFACTOR - 1)) 63*02d09e03SGordon Ross #define M_BASESIZE (sizeof (struct mbuf) + 8) 64*02d09e03SGordon Ross #define M_MINSIZE (1024 - M_BASESIZE) 65*02d09e03SGordon Ross #define M_TOP(m) ((char *)(m) + M_BASESIZE) 66*02d09e03SGordon Ross #define M_TRAILINGSPACE(m) ((m)->m_maxlen - (m)->m_len) 67*02d09e03SGordon Ross 68*02d09e03SGordon Ross int 69*02d09e03SGordon Ross m_get(int len, struct mbuf **mpp) 704bff34e3Sthurlow { 714bff34e3Sthurlow struct mbuf *m; 724bff34e3Sthurlow 737568150aSgwr assert(len < 0x100000); /* sanity */ 747568150aSgwr 754bff34e3Sthurlow len = M_ALIGN(len); 764bff34e3Sthurlow if (len < M_MINSIZE) 774bff34e3Sthurlow len = M_MINSIZE; 784bff34e3Sthurlow m = malloc(M_BASESIZE + len); 794bff34e3Sthurlow if (m == NULL) 804bff34e3Sthurlow return (ENOMEM); 814bff34e3Sthurlow bzero(m, M_BASESIZE + len); 824bff34e3Sthurlow m->m_maxlen = len; 834bff34e3Sthurlow m->m_data = M_TOP(m); 844bff34e3Sthurlow *mpp = m; 854bff34e3Sthurlow return (0); 864bff34e3Sthurlow } 874bff34e3Sthurlow 884bff34e3Sthurlow static void 894bff34e3Sthurlow m_free(struct mbuf *m) 904bff34e3Sthurlow { 914bff34e3Sthurlow free(m); 924bff34e3Sthurlow } 934bff34e3Sthurlow 94613a2f6bSGordon Ross void 954bff34e3Sthurlow m_freem(struct mbuf *m0) 964bff34e3Sthurlow { 974bff34e3Sthurlow struct mbuf *m; 984bff34e3Sthurlow 994bff34e3Sthurlow while (m0) { 1004bff34e3Sthurlow m = m0->m_next; 1014bff34e3Sthurlow m_free(m0); 1024bff34e3Sthurlow m0 = m; 1034bff34e3Sthurlow } 1044bff34e3Sthurlow } 1054bff34e3Sthurlow 106613a2f6bSGordon Ross size_t 1074bff34e3Sthurlow m_totlen(struct mbuf *m0) 1084bff34e3Sthurlow { 1094bff34e3Sthurlow struct mbuf *m = m0; 1104bff34e3Sthurlow int len = 0; 1114bff34e3Sthurlow 1124bff34e3Sthurlow while (m) { 1134bff34e3Sthurlow len += m->m_len; 1144bff34e3Sthurlow m = m->m_next; 1154bff34e3Sthurlow } 1164bff34e3Sthurlow return (len); 1174bff34e3Sthurlow } 1184bff34e3Sthurlow 1194bff34e3Sthurlow int 1204bff34e3Sthurlow m_lineup(struct mbuf *m0, struct mbuf **mpp) 1214bff34e3Sthurlow { 1224bff34e3Sthurlow struct mbuf *nm, *m; 1234bff34e3Sthurlow char *dp; 1244bff34e3Sthurlow size_t len; 1254bff34e3Sthurlow int error; 1264bff34e3Sthurlow 1274bff34e3Sthurlow if (m0->m_next == NULL) { 1284bff34e3Sthurlow *mpp = m0; 1294bff34e3Sthurlow return (0); 1304bff34e3Sthurlow } 1314bff34e3Sthurlow if ((error = m_get(m_totlen(m0), &nm)) != 0) 1324bff34e3Sthurlow return (error); 1334bff34e3Sthurlow dp = mtod(nm, char *); 1344bff34e3Sthurlow while (m0) { 1354bff34e3Sthurlow len = m0->m_len; 1364bff34e3Sthurlow bcopy(m0->m_data, dp, len); 1374bff34e3Sthurlow dp += len; 1384bff34e3Sthurlow m = m0->m_next; 1394bff34e3Sthurlow m_free(m0); 1404bff34e3Sthurlow m0 = m; 1414bff34e3Sthurlow } 1424bff34e3Sthurlow *mpp = nm; 1434bff34e3Sthurlow return (0); 1444bff34e3Sthurlow } 1454bff34e3Sthurlow 1464bff34e3Sthurlow int 147*02d09e03SGordon Ross mb_init(struct mbdata *mbp) 148*02d09e03SGordon Ross { 149*02d09e03SGordon Ross return (mb_init_sz(mbp, M_MINSIZE)); 150*02d09e03SGordon Ross } 151*02d09e03SGordon Ross 152*02d09e03SGordon Ross int 153*02d09e03SGordon Ross mb_init_sz(struct mbdata *mbp, int size) 1544bff34e3Sthurlow { 1554bff34e3Sthurlow struct mbuf *m; 1564bff34e3Sthurlow int error; 1574bff34e3Sthurlow 1584bff34e3Sthurlow if ((error = m_get(size, &m)) != 0) 1594bff34e3Sthurlow return (error); 160*02d09e03SGordon Ross mb_initm(mbp, m); 161*02d09e03SGordon Ross return (0); 1624bff34e3Sthurlow } 1634bff34e3Sthurlow 164*02d09e03SGordon Ross void 1654bff34e3Sthurlow mb_initm(struct mbdata *mbp, struct mbuf *m) 1664bff34e3Sthurlow { 1674bff34e3Sthurlow bzero(mbp, sizeof (*mbp)); 1684bff34e3Sthurlow mbp->mb_top = mbp->mb_cur = m; 1694bff34e3Sthurlow mbp->mb_pos = mtod(m, char *); 1704bff34e3Sthurlow } 1714bff34e3Sthurlow 172*02d09e03SGordon Ross void 1734bff34e3Sthurlow mb_done(struct mbdata *mbp) 1744bff34e3Sthurlow { 1754bff34e3Sthurlow if (mbp->mb_top) { 1764bff34e3Sthurlow m_freem(mbp->mb_top); 1774bff34e3Sthurlow mbp->mb_top = NULL; 1784bff34e3Sthurlow } 1794bff34e3Sthurlow } 1804bff34e3Sthurlow 1814bff34e3Sthurlow int 182*02d09e03SGordon Ross m_getm(struct mbuf *top, int len, struct mbuf **mpp) 1834bff34e3Sthurlow { 1844bff34e3Sthurlow struct mbuf *m, *mp; 1857568150aSgwr int error, ts; 1864bff34e3Sthurlow 1874bff34e3Sthurlow for (mp = top; ; mp = mp->m_next) { 1887568150aSgwr ts = M_TRAILINGSPACE(mp); 1897568150aSgwr if (len <= ts) 1907568150aSgwr goto out; 1917568150aSgwr len -= ts; 1924bff34e3Sthurlow if (mp->m_next == NULL) 1934bff34e3Sthurlow break; 1944bff34e3Sthurlow 1954bff34e3Sthurlow } 1964bff34e3Sthurlow if (len > 0) { 1974bff34e3Sthurlow if ((error = m_get(len, &m)) != 0) 1984bff34e3Sthurlow return (error); 1994bff34e3Sthurlow mp->m_next = m; 2004bff34e3Sthurlow } 2017568150aSgwr out: 2024bff34e3Sthurlow *mpp = top; 2034bff34e3Sthurlow return (0); 2044bff34e3Sthurlow } 2054bff34e3Sthurlow 2064bff34e3Sthurlow /* 2074bff34e3Sthurlow * Routines to put data in a buffer 2084bff34e3Sthurlow */ 2094bff34e3Sthurlow 210*02d09e03SGordon Ross void * 211*02d09e03SGordon Ross mb_reserve(mbchain_t *mbp, int size) 212*02d09e03SGordon Ross { 213*02d09e03SGordon Ross char *p; 214*02d09e03SGordon Ross 215*02d09e03SGordon Ross if (mb_fit(mbp, size, &p) != 0) 216*02d09e03SGordon Ross return (NULL); 217*02d09e03SGordon Ross 218*02d09e03SGordon Ross return (p); 219*02d09e03SGordon Ross } 220*02d09e03SGordon Ross 2214bff34e3Sthurlow /* 2224bff34e3Sthurlow * Check if object of size 'size' fit to the current position and 2234bff34e3Sthurlow * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 2244bff34e3Sthurlow * Return pointer to the object placeholder or NULL if any error occured. 2254bff34e3Sthurlow */ 2264bff34e3Sthurlow int 227*02d09e03SGordon Ross mb_fit(mbchain_t *mbp, int size, char **pp) 2284bff34e3Sthurlow { 2294bff34e3Sthurlow struct mbuf *m, *mn; 2304bff34e3Sthurlow int error; 2314bff34e3Sthurlow 2324bff34e3Sthurlow m = mbp->mb_cur; 2334bff34e3Sthurlow if (M_TRAILINGSPACE(m) < (int)size) { 2344bff34e3Sthurlow if ((error = m_get(size, &mn)) != 0) 2354bff34e3Sthurlow return (error); 2364bff34e3Sthurlow mbp->mb_pos = mtod(mn, char *); 2374bff34e3Sthurlow mbp->mb_cur = m->m_next = mn; 2384bff34e3Sthurlow m = mn; 2394bff34e3Sthurlow } 2404bff34e3Sthurlow m->m_len += size; 2414bff34e3Sthurlow *pp = mbp->mb_pos; 2424bff34e3Sthurlow mbp->mb_pos += size; 2434bff34e3Sthurlow mbp->mb_count += size; 2444bff34e3Sthurlow return (0); 2454bff34e3Sthurlow } 2464bff34e3Sthurlow 2474bff34e3Sthurlow int 248*02d09e03SGordon Ross mb_put_uint8(mbchain_t *mbp, uint8_t x) 2494bff34e3Sthurlow { 2509c9af259SGordon Ross uint8_t y = x; 251*02d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2524bff34e3Sthurlow } 2534bff34e3Sthurlow 2544bff34e3Sthurlow int 255*02d09e03SGordon Ross mb_put_uint16be(mbchain_t *mbp, uint16_t x) 2564bff34e3Sthurlow { 2579c9af259SGordon Ross uint16_t y = htobes(x); 258*02d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2594bff34e3Sthurlow } 2604bff34e3Sthurlow 2614bff34e3Sthurlow int 262*02d09e03SGordon Ross mb_put_uint16le(mbchain_t *mbp, uint16_t x) 2634bff34e3Sthurlow { 2649c9af259SGordon Ross uint16_t y = htoles(x); 265*02d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2664bff34e3Sthurlow } 2674bff34e3Sthurlow 2684bff34e3Sthurlow int 269*02d09e03SGordon Ross mb_put_uint32be(mbchain_t *mbp, uint32_t x) 2704bff34e3Sthurlow { 2719c9af259SGordon Ross uint32_t y = htobel(x); 272*02d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2734bff34e3Sthurlow } 2744bff34e3Sthurlow 2754bff34e3Sthurlow int 276*02d09e03SGordon Ross mb_put_uint32le(mbchain_t *mbp, uint32_t x) 2774bff34e3Sthurlow { 2789c9af259SGordon Ross uint32_t y = htolel(x); 279*02d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2804bff34e3Sthurlow } 2814bff34e3Sthurlow 2824bff34e3Sthurlow int 283*02d09e03SGordon Ross mb_put_uint64be(mbchain_t *mbp, uint64_t x) 2844bff34e3Sthurlow { 2859c9af259SGordon Ross uint64_t y = htobeq(x); 286*02d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2874bff34e3Sthurlow } 2884bff34e3Sthurlow 2894bff34e3Sthurlow int 290*02d09e03SGordon Ross mb_put_uint64le(mbchain_t *mbp, uint64_t x) 2914bff34e3Sthurlow { 2929c9af259SGordon Ross uint64_t y = htoleq(x); 293*02d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2944bff34e3Sthurlow } 2954bff34e3Sthurlow 296*02d09e03SGordon Ross /* ARGSUSED */ 2974bff34e3Sthurlow int 298*02d09e03SGordon Ross mb_put_mem(mbchain_t *mbp, const void *vmem, int size, int type) 2994bff34e3Sthurlow { 3004bff34e3Sthurlow struct mbuf *m; 301613a2f6bSGordon Ross const char *src; 3024bff34e3Sthurlow char *dst; 3034bff34e3Sthurlow size_t cplen; 3044bff34e3Sthurlow int error; 3054bff34e3Sthurlow 3064bff34e3Sthurlow if (size == 0) 3074bff34e3Sthurlow return (0); 308613a2f6bSGordon Ross 309613a2f6bSGordon Ross src = vmem; 3104bff34e3Sthurlow m = mbp->mb_cur; 3114bff34e3Sthurlow if ((error = m_getm(m, size, &m)) != 0) 3124bff34e3Sthurlow return (error); 3134bff34e3Sthurlow while (size > 0) { 3144bff34e3Sthurlow cplen = M_TRAILINGSPACE(m); 3154bff34e3Sthurlow if (cplen == 0) { 3164bff34e3Sthurlow m = m->m_next; 3174bff34e3Sthurlow continue; 3184bff34e3Sthurlow } 3194bff34e3Sthurlow if (cplen > size) 3204bff34e3Sthurlow cplen = size; 3214bff34e3Sthurlow dst = mtod(m, char *) + m->m_len; 322613a2f6bSGordon Ross if (src) { 323613a2f6bSGordon Ross bcopy(src, dst, cplen); 324613a2f6bSGordon Ross src += cplen; 3254bff34e3Sthurlow } else 3264bff34e3Sthurlow bzero(dst, cplen); 3274bff34e3Sthurlow size -= cplen; 3284bff34e3Sthurlow m->m_len += cplen; 3294bff34e3Sthurlow mbp->mb_count += cplen; 3304bff34e3Sthurlow } 3314bff34e3Sthurlow mbp->mb_pos = mtod(m, char *) + m->m_len; 3324bff34e3Sthurlow mbp->mb_cur = m; 3334bff34e3Sthurlow return (0); 3344bff34e3Sthurlow } 3354bff34e3Sthurlow 336613a2f6bSGordon Ross /* 337613a2f6bSGordon Ross * Append another mbuf to the mbuf chain. 338613a2f6bSGordon Ross * If what we're appending is smaller than 339613a2f6bSGordon Ross * the current trailing space, just copy. 340613a2f6bSGordon Ross * This always consumes the passed mbuf. 341613a2f6bSGordon Ross */ 3424bff34e3Sthurlow int 343*02d09e03SGordon Ross mb_put_mbuf(mbchain_t *mbp, struct mbuf *m) 3444bff34e3Sthurlow { 345613a2f6bSGordon Ross struct mbuf *cm = mbp->mb_cur; 346613a2f6bSGordon Ross int ts = M_TRAILINGSPACE(cm); 347613a2f6bSGordon Ross 348613a2f6bSGordon Ross if (m->m_next == NULL && m->m_len <= ts) { 349613a2f6bSGordon Ross /* just copy */ 350*02d09e03SGordon Ross mb_put_mem(mbp, m->m_data, m->m_len, MB_MSYSTEM); 351613a2f6bSGordon Ross m_freem(m); 352613a2f6bSGordon Ross return (0); 353613a2f6bSGordon Ross } 354613a2f6bSGordon Ross 355613a2f6bSGordon Ross cm->m_next = m; 3564bff34e3Sthurlow while (m) { 3574bff34e3Sthurlow mbp->mb_count += m->m_len; 3584bff34e3Sthurlow if (m->m_next == NULL) 3594bff34e3Sthurlow break; 3604bff34e3Sthurlow m = m->m_next; 3614bff34e3Sthurlow } 3624bff34e3Sthurlow mbp->mb_pos = mtod(m, char *) + m->m_len; 3634bff34e3Sthurlow mbp->mb_cur = m; 3644bff34e3Sthurlow return (0); 3654bff34e3Sthurlow } 3664bff34e3Sthurlow 367613a2f6bSGordon Ross /* 368613a2f6bSGordon Ross * Convenience function to put an OEM or Unicode string, 369613a2f6bSGordon Ross * null terminated, and aligned if necessary. 370613a2f6bSGordon Ross */ 3714bff34e3Sthurlow int 372*02d09e03SGordon Ross mb_put_string(mbchain_t *mbp, const char *s, int uc) 3734bff34e3Sthurlow { 374613a2f6bSGordon Ross int err; 3754bff34e3Sthurlow 376613a2f6bSGordon Ross if (uc) { 377613a2f6bSGordon Ross /* Put Unicode. align(2) first. */ 378613a2f6bSGordon Ross if (mbp->mb_count & 1) 379613a2f6bSGordon Ross mb_put_uint8(mbp, 0); 380613a2f6bSGordon Ross err = mb_put_ustring(mbp, s); 381613a2f6bSGordon Ross } else { 382613a2f6bSGordon Ross /* Put ASCII (really OEM) */ 383613a2f6bSGordon Ross err = mb_put_astring(mbp, s); 3844bff34e3Sthurlow } 385613a2f6bSGordon Ross 386613a2f6bSGordon Ross return (err); 387613a2f6bSGordon Ross } 388613a2f6bSGordon Ross 389613a2f6bSGordon Ross /* 390613a2f6bSGordon Ross * Put an ASCII string (really OEM), given a UTF-8 string. 391613a2f6bSGordon Ross */ 392613a2f6bSGordon Ross int 393*02d09e03SGordon Ross mb_put_astring(mbchain_t *mbp, const char *s) 394613a2f6bSGordon Ross { 395613a2f6bSGordon Ross char *abuf; 396613a2f6bSGordon Ross int err, len; 397613a2f6bSGordon Ross 398613a2f6bSGordon Ross abuf = convert_utf8_to_wincs(s); 399613a2f6bSGordon Ross if (abuf == NULL) 400613a2f6bSGordon Ross return (ENOMEM); 401613a2f6bSGordon Ross len = strlen(abuf) + 1; 402*02d09e03SGordon Ross err = mb_put_mem(mbp, abuf, len, MB_MSYSTEM); 403613a2f6bSGordon Ross free(abuf); 404613a2f6bSGordon Ross return (err); 405613a2f6bSGordon Ross } 406613a2f6bSGordon Ross 407613a2f6bSGordon Ross /* 408613a2f6bSGordon Ross * Put UCS-2LE, given a UTF-8 string. 409613a2f6bSGordon Ross */ 410613a2f6bSGordon Ross int 411*02d09e03SGordon Ross mb_put_ustring(mbchain_t *mbp, const char *s) 412613a2f6bSGordon Ross { 413613a2f6bSGordon Ross uint16_t *ubuf; 414613a2f6bSGordon Ross int err, len; 415613a2f6bSGordon Ross 416613a2f6bSGordon Ross ubuf = convert_utf8_to_leunicode(s); 417613a2f6bSGordon Ross if (ubuf == NULL) 418613a2f6bSGordon Ross return (ENOMEM); 419*02d09e03SGordon Ross len = 2 * (unicode_strlen(ubuf) + 1); 420*02d09e03SGordon Ross err = mb_put_mem(mbp, ubuf, len, MB_MSYSTEM); 421613a2f6bSGordon Ross free(ubuf); 422613a2f6bSGordon Ross return (err); 4234bff34e3Sthurlow } 4244bff34e3Sthurlow 4254bff34e3Sthurlow /* 4264bff34e3Sthurlow * Routines for fetching data from an mbuf chain 4274bff34e3Sthurlow */ 4284bff34e3Sthurlow #define mb_left(m, p) (mtod(m, char *) + (m)->m_len - (p)) 4294bff34e3Sthurlow 4304bff34e3Sthurlow int 431*02d09e03SGordon Ross md_get_uint8(mdchain_t *mbp, uint8_t *x) 4324bff34e3Sthurlow { 433*02d09e03SGordon Ross return (md_get_mem(mbp, x, 1, MB_MINLINE)); 4344bff34e3Sthurlow } 4354bff34e3Sthurlow 4364bff34e3Sthurlow int 437*02d09e03SGordon Ross md_get_uint16le(mdchain_t *mbp, uint16_t *x) 4384bff34e3Sthurlow { 4394bff34e3Sthurlow uint16_t v; 440613a2f6bSGordon Ross int err; 4414bff34e3Sthurlow 442*02d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 443613a2f6bSGordon Ross return (err); 4444bff34e3Sthurlow if (x != NULL) 4454bff34e3Sthurlow *x = letohs(v); 446613a2f6bSGordon Ross return (0); 4474bff34e3Sthurlow } 4484bff34e3Sthurlow 4494bff34e3Sthurlow int 450*02d09e03SGordon Ross md_get_uint16be(mdchain_t *mbp, uint16_t *x) { 4514bff34e3Sthurlow uint16_t v; 452613a2f6bSGordon Ross int err; 4534bff34e3Sthurlow 454*02d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 455613a2f6bSGordon Ross return (err); 4564bff34e3Sthurlow if (x != NULL) 4574bff34e3Sthurlow *x = betohs(v); 458613a2f6bSGordon Ross return (0); 4594bff34e3Sthurlow } 4604bff34e3Sthurlow 4614bff34e3Sthurlow int 462*02d09e03SGordon Ross md_get_uint32be(mdchain_t *mbp, uint32_t *x) 4634bff34e3Sthurlow { 4644bff34e3Sthurlow uint32_t v; 465613a2f6bSGordon Ross int err; 4664bff34e3Sthurlow 467*02d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 468613a2f6bSGordon Ross return (err); 4694bff34e3Sthurlow if (x != NULL) 4704bff34e3Sthurlow *x = betohl(v); 471613a2f6bSGordon Ross return (0); 4724bff34e3Sthurlow } 4734bff34e3Sthurlow 4744bff34e3Sthurlow int 475*02d09e03SGordon Ross md_get_uint32le(mdchain_t *mbp, uint32_t *x) 4764bff34e3Sthurlow { 4774bff34e3Sthurlow uint32_t v; 478613a2f6bSGordon Ross int err; 4794bff34e3Sthurlow 480*02d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 481613a2f6bSGordon Ross return (err); 4824bff34e3Sthurlow if (x != NULL) 4834bff34e3Sthurlow *x = letohl(v); 484613a2f6bSGordon Ross return (0); 4854bff34e3Sthurlow } 4864bff34e3Sthurlow 4874bff34e3Sthurlow int 488*02d09e03SGordon Ross md_get_uint64be(mdchain_t *mbp, uint64_t *x) 4894bff34e3Sthurlow { 4904bff34e3Sthurlow uint64_t v; 491613a2f6bSGordon Ross int err; 4924bff34e3Sthurlow 493*02d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 494613a2f6bSGordon Ross return (err); 4954bff34e3Sthurlow if (x != NULL) 4964bff34e3Sthurlow *x = betohq(v); 497613a2f6bSGordon Ross return (0); 4984bff34e3Sthurlow } 4994bff34e3Sthurlow 5004bff34e3Sthurlow int 501*02d09e03SGordon Ross md_get_uint64le(mdchain_t *mbp, uint64_t *x) 5024bff34e3Sthurlow { 5034bff34e3Sthurlow uint64_t v; 504613a2f6bSGordon Ross int err; 5054bff34e3Sthurlow 506*02d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 507613a2f6bSGordon Ross return (err); 5084bff34e3Sthurlow if (x != NULL) 5094bff34e3Sthurlow *x = letohq(v); 510613a2f6bSGordon Ross return (0); 5114bff34e3Sthurlow } 5124bff34e3Sthurlow 513*02d09e03SGordon Ross /* ARGSUSED */ 5144bff34e3Sthurlow int 515*02d09e03SGordon Ross md_get_mem(mdchain_t *mbp, void *vmem, int size, int type) 5164bff34e3Sthurlow { 5174bff34e3Sthurlow struct mbuf *m = mbp->mb_cur; 518613a2f6bSGordon Ross char *dst = vmem; 5194bff34e3Sthurlow uint_t count; 5204bff34e3Sthurlow 5214bff34e3Sthurlow while (size > 0) { 5224bff34e3Sthurlow if (m == NULL) { 523613a2f6bSGordon Ross /* DPRINT("incomplete copy"); */ 5244bff34e3Sthurlow return (EBADRPC); 5254bff34e3Sthurlow } 5264bff34e3Sthurlow count = mb_left(m, mbp->mb_pos); 5274bff34e3Sthurlow if (count == 0) { 5284bff34e3Sthurlow mbp->mb_cur = m = m->m_next; 5294bff34e3Sthurlow if (m) 5304bff34e3Sthurlow mbp->mb_pos = mtod(m, char *); 5314bff34e3Sthurlow continue; 5324bff34e3Sthurlow } 5334bff34e3Sthurlow if (count > size) 5344bff34e3Sthurlow count = size; 5354bff34e3Sthurlow size -= count; 536613a2f6bSGordon Ross if (dst) { 5374bff34e3Sthurlow if (count == 1) { 538613a2f6bSGordon Ross *dst++ = *mbp->mb_pos; 5394bff34e3Sthurlow } else { 540613a2f6bSGordon Ross bcopy(mbp->mb_pos, dst, count); 541613a2f6bSGordon Ross dst += count; 5424bff34e3Sthurlow } 5434bff34e3Sthurlow } 5444bff34e3Sthurlow mbp->mb_pos += count; 5454bff34e3Sthurlow } 5464bff34e3Sthurlow return (0); 5474bff34e3Sthurlow } 548613a2f6bSGordon Ross 549613a2f6bSGordon Ross /* 550613a2f6bSGordon Ross * Get the next SIZE bytes as a separate mblk. 551613a2f6bSGordon Ross * Nothing fancy here - just copy. 552613a2f6bSGordon Ross */ 553613a2f6bSGordon Ross int 554*02d09e03SGordon Ross md_get_mbuf(mdchain_t *mbp, int size, mbuf_t **ret) 555613a2f6bSGordon Ross { 556613a2f6bSGordon Ross mbuf_t *m; 557613a2f6bSGordon Ross int err; 558613a2f6bSGordon Ross 559613a2f6bSGordon Ross err = m_get(size, &m); 560613a2f6bSGordon Ross if (err) 561613a2f6bSGordon Ross return (err); 562613a2f6bSGordon Ross 563*02d09e03SGordon Ross err = md_get_mem(mbp, m->m_data, size, MB_MSYSTEM); 564613a2f6bSGordon Ross if (err) { 565613a2f6bSGordon Ross m_freem(m); 566613a2f6bSGordon Ross return (err); 567613a2f6bSGordon Ross } 568613a2f6bSGordon Ross m->m_len = size; 569613a2f6bSGordon Ross *ret = m; 570613a2f6bSGordon Ross 571613a2f6bSGordon Ross return (0); 572613a2f6bSGordon Ross } 573613a2f6bSGordon Ross 574613a2f6bSGordon Ross /* 575613a2f6bSGordon Ross * Get a string from the mbuf chain, 576613a2f6bSGordon Ross * either Unicode or OEM chars. 577613a2f6bSGordon Ross */ 578613a2f6bSGordon Ross int 579*02d09e03SGordon Ross md_get_string(mdchain_t *mbp, char **str_pp, int uc) 580613a2f6bSGordon Ross { 581613a2f6bSGordon Ross int err; 582613a2f6bSGordon Ross 583613a2f6bSGordon Ross if (uc) 584*02d09e03SGordon Ross err = md_get_ustring(mbp, str_pp); 585613a2f6bSGordon Ross else 586*02d09e03SGordon Ross err = md_get_astring(mbp, str_pp); 587613a2f6bSGordon Ross return (err); 588613a2f6bSGordon Ross } 589613a2f6bSGordon Ross 590613a2f6bSGordon Ross /* 591613a2f6bSGordon Ross * Get an ASCII (really OEM) string from the mbuf chain 592613a2f6bSGordon Ross * and convert it to UTF-8 593*02d09e03SGordon Ross * 594*02d09e03SGordon Ross * Similar to md_get_ustring below. 595613a2f6bSGordon Ross */ 596613a2f6bSGordon Ross int 597*02d09e03SGordon Ross md_get_astring(mdchain_t *real_mbp, char **str_pp) 598613a2f6bSGordon Ross { 599*02d09e03SGordon Ross mdchain_t tmp_mb, *mbp; 600613a2f6bSGordon Ross char *tstr, *ostr; 601613a2f6bSGordon Ross int err, i, slen; 602613a2f6bSGordon Ross uint8_t ch; 603613a2f6bSGordon Ross 604613a2f6bSGordon Ross /* 605613a2f6bSGordon Ross * First, figure out the string length. 606613a2f6bSGordon Ross * Use a copy of the real_mbp so we don't 607613a2f6bSGordon Ross * actually consume it here, then search for 608613a2f6bSGordon Ross * the null (or end of data). 609613a2f6bSGordon Ross */ 610613a2f6bSGordon Ross bcopy(real_mbp, &tmp_mb, sizeof (tmp_mb)); 611613a2f6bSGordon Ross mbp = &tmp_mb; 612613a2f6bSGordon Ross slen = 0; 613613a2f6bSGordon Ross for (;;) { 614*02d09e03SGordon Ross err = md_get_uint8(mbp, &ch); 615613a2f6bSGordon Ross if (err) 616613a2f6bSGordon Ross break; 617613a2f6bSGordon Ross if (ch == 0) 618613a2f6bSGordon Ross break; 619613a2f6bSGordon Ross slen++; 620613a2f6bSGordon Ross } 621613a2f6bSGordon Ross 622613a2f6bSGordon Ross /* 623613a2f6bSGordon Ross * Now read the (OEM) string for real. 624613a2f6bSGordon Ross * No need to re-check errors. 625613a2f6bSGordon Ross */ 626613a2f6bSGordon Ross tstr = malloc(slen + 1); 627613a2f6bSGordon Ross if (tstr == NULL) 628613a2f6bSGordon Ross return (ENOMEM); 629613a2f6bSGordon Ross mbp = real_mbp; 630613a2f6bSGordon Ross for (i = 0; i < slen; i++) { 631*02d09e03SGordon Ross md_get_uint8(mbp, &ch); 632613a2f6bSGordon Ross tstr[i] = ch; 633613a2f6bSGordon Ross } 634613a2f6bSGordon Ross tstr[i] = 0; 635*02d09e03SGordon Ross md_get_uint8(mbp, NULL); 636613a2f6bSGordon Ross 637613a2f6bSGordon Ross /* 638613a2f6bSGordon Ross * Convert OEM to UTF-8 639613a2f6bSGordon Ross */ 640613a2f6bSGordon Ross ostr = convert_wincs_to_utf8(tstr); 641613a2f6bSGordon Ross free(tstr); 642613a2f6bSGordon Ross if (ostr == NULL) 643613a2f6bSGordon Ross return (ENOMEM); 644613a2f6bSGordon Ross 645613a2f6bSGordon Ross *str_pp = ostr; 646613a2f6bSGordon Ross return (0); 647613a2f6bSGordon Ross } 648613a2f6bSGordon Ross 649613a2f6bSGordon Ross /* 650613a2f6bSGordon Ross * Get a UCS-2LE string from the mbuf chain, and 651613a2f6bSGordon Ross * convert it to UTF-8. 652613a2f6bSGordon Ross * 653*02d09e03SGordon Ross * Similar to md_get_astring above. 654613a2f6bSGordon Ross */ 655613a2f6bSGordon Ross int 656*02d09e03SGordon Ross md_get_ustring(mdchain_t *real_mbp, char **str_pp) 657613a2f6bSGordon Ross { 658*02d09e03SGordon Ross mdchain_t tmp_mb, *mbp; 659613a2f6bSGordon Ross uint16_t *tstr; 660613a2f6bSGordon Ross char *ostr; 661613a2f6bSGordon Ross int err, i, slen; 662613a2f6bSGordon Ross uint16_t ch; 663613a2f6bSGordon Ross 664613a2f6bSGordon Ross /* 665613a2f6bSGordon Ross * First, align(2) on the real_mbp 666613a2f6bSGordon Ross */ 667613a2f6bSGordon Ross if (((uintptr_t)real_mbp->mb_pos) & 1) 668*02d09e03SGordon Ross md_get_uint8(real_mbp, NULL); 669613a2f6bSGordon Ross 670613a2f6bSGordon Ross /* 671613a2f6bSGordon Ross * Next, figure out the string length. 672613a2f6bSGordon Ross * Use a copy of the real_mbp so we don't 673613a2f6bSGordon Ross * actually consume it here, then search for 674613a2f6bSGordon Ross * the null (or end of data). 675613a2f6bSGordon Ross */ 676613a2f6bSGordon Ross bcopy(real_mbp, &tmp_mb, sizeof (tmp_mb)); 677613a2f6bSGordon Ross mbp = &tmp_mb; 678613a2f6bSGordon Ross slen = 0; 679613a2f6bSGordon Ross for (;;) { 680*02d09e03SGordon Ross err = md_get_uint16le(mbp, &ch); 681613a2f6bSGordon Ross if (err) 682613a2f6bSGordon Ross break; 683613a2f6bSGordon Ross if (ch == 0) 684613a2f6bSGordon Ross break; 685613a2f6bSGordon Ross slen++; 686613a2f6bSGordon Ross } 687613a2f6bSGordon Ross 688613a2f6bSGordon Ross /* 689613a2f6bSGordon Ross * Now read the (UCS-2) string for real. 690613a2f6bSGordon Ross * No need to re-check errors. Note: 691613a2f6bSGordon Ross * This puts the UCS-2 in NATIVE order! 692613a2f6bSGordon Ross */ 693613a2f6bSGordon Ross tstr = calloc(slen + 1, 2); 694613a2f6bSGordon Ross if (tstr == NULL) 695613a2f6bSGordon Ross return (ENOMEM); 696613a2f6bSGordon Ross mbp = real_mbp; 697613a2f6bSGordon Ross for (i = 0; i < slen; i++) { 698*02d09e03SGordon Ross md_get_uint16le(mbp, &ch); 699613a2f6bSGordon Ross tstr[i] = ch; 700613a2f6bSGordon Ross } 701613a2f6bSGordon Ross tstr[i] = 0; 702*02d09e03SGordon Ross md_get_uint16le(mbp, NULL); 703613a2f6bSGordon Ross 704613a2f6bSGordon Ross /* 705613a2f6bSGordon Ross * Convert UCS-2 (native!) to UTF-8 706613a2f6bSGordon Ross */ 707613a2f6bSGordon Ross ostr = convert_unicode_to_utf8(tstr); 708613a2f6bSGordon Ross free(tstr); 709613a2f6bSGordon Ross if (ostr == NULL) 710613a2f6bSGordon Ross return (ENOMEM); 711613a2f6bSGordon Ross 712613a2f6bSGordon Ross *str_pp = ostr; 713613a2f6bSGordon Ross return (0); 714613a2f6bSGordon Ross } 715