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 /* 36*613a2f6bSGordon 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" 54*613a2f6bSGordon Ross #include "charsets.h" 554bff34e3Sthurlow 564bff34e3Sthurlow static int 574bff34e3Sthurlow m_get(size_t len, struct mbuf **mpp) 584bff34e3Sthurlow { 594bff34e3Sthurlow struct mbuf *m; 604bff34e3Sthurlow 617568150aSgwr assert(len < 0x100000); /* sanity */ 627568150aSgwr 634bff34e3Sthurlow len = M_ALIGN(len); 644bff34e3Sthurlow if (len < M_MINSIZE) 654bff34e3Sthurlow len = M_MINSIZE; 664bff34e3Sthurlow m = malloc(M_BASESIZE + len); 674bff34e3Sthurlow if (m == NULL) 684bff34e3Sthurlow return (ENOMEM); 694bff34e3Sthurlow bzero(m, M_BASESIZE + len); 704bff34e3Sthurlow m->m_maxlen = len; 714bff34e3Sthurlow m->m_data = M_TOP(m); 724bff34e3Sthurlow *mpp = m; 734bff34e3Sthurlow return (0); 744bff34e3Sthurlow } 754bff34e3Sthurlow 764bff34e3Sthurlow static void 774bff34e3Sthurlow m_free(struct mbuf *m) 784bff34e3Sthurlow { 794bff34e3Sthurlow free(m); 804bff34e3Sthurlow } 814bff34e3Sthurlow 82*613a2f6bSGordon Ross void 834bff34e3Sthurlow m_freem(struct mbuf *m0) 844bff34e3Sthurlow { 854bff34e3Sthurlow struct mbuf *m; 864bff34e3Sthurlow 874bff34e3Sthurlow while (m0) { 884bff34e3Sthurlow m = m0->m_next; 894bff34e3Sthurlow m_free(m0); 904bff34e3Sthurlow m0 = m; 914bff34e3Sthurlow } 924bff34e3Sthurlow } 934bff34e3Sthurlow 94*613a2f6bSGordon Ross size_t 954bff34e3Sthurlow m_totlen(struct mbuf *m0) 964bff34e3Sthurlow { 974bff34e3Sthurlow struct mbuf *m = m0; 984bff34e3Sthurlow int len = 0; 994bff34e3Sthurlow 1004bff34e3Sthurlow while (m) { 1014bff34e3Sthurlow len += m->m_len; 1024bff34e3Sthurlow m = m->m_next; 1034bff34e3Sthurlow } 1044bff34e3Sthurlow return (len); 1054bff34e3Sthurlow } 1064bff34e3Sthurlow 1074bff34e3Sthurlow int 1084bff34e3Sthurlow m_lineup(struct mbuf *m0, struct mbuf **mpp) 1094bff34e3Sthurlow { 1104bff34e3Sthurlow struct mbuf *nm, *m; 1114bff34e3Sthurlow char *dp; 1124bff34e3Sthurlow size_t len; 1134bff34e3Sthurlow int error; 1144bff34e3Sthurlow 1154bff34e3Sthurlow if (m0->m_next == NULL) { 1164bff34e3Sthurlow *mpp = m0; 1174bff34e3Sthurlow return (0); 1184bff34e3Sthurlow } 1194bff34e3Sthurlow if ((error = m_get(m_totlen(m0), &nm)) != 0) 1204bff34e3Sthurlow return (error); 1214bff34e3Sthurlow dp = mtod(nm, char *); 1224bff34e3Sthurlow while (m0) { 1234bff34e3Sthurlow len = m0->m_len; 1244bff34e3Sthurlow bcopy(m0->m_data, dp, len); 1254bff34e3Sthurlow dp += len; 1264bff34e3Sthurlow m = m0->m_next; 1274bff34e3Sthurlow m_free(m0); 1284bff34e3Sthurlow m0 = m; 1294bff34e3Sthurlow } 1304bff34e3Sthurlow *mpp = nm; 1314bff34e3Sthurlow return (0); 1324bff34e3Sthurlow } 1334bff34e3Sthurlow 1344bff34e3Sthurlow int 1354bff34e3Sthurlow mb_init(struct mbdata *mbp, size_t size) 1364bff34e3Sthurlow { 1374bff34e3Sthurlow struct mbuf *m; 1384bff34e3Sthurlow int error; 1394bff34e3Sthurlow 1404bff34e3Sthurlow if ((error = m_get(size, &m)) != 0) 1414bff34e3Sthurlow return (error); 1424bff34e3Sthurlow return (mb_initm(mbp, m)); 1434bff34e3Sthurlow } 1444bff34e3Sthurlow 1454bff34e3Sthurlow int 1464bff34e3Sthurlow mb_initm(struct mbdata *mbp, struct mbuf *m) 1474bff34e3Sthurlow { 1484bff34e3Sthurlow bzero(mbp, sizeof (*mbp)); 1494bff34e3Sthurlow mbp->mb_top = mbp->mb_cur = m; 1504bff34e3Sthurlow mbp->mb_pos = mtod(m, char *); 1514bff34e3Sthurlow return (0); 1524bff34e3Sthurlow } 1534bff34e3Sthurlow 1544bff34e3Sthurlow int 1554bff34e3Sthurlow mb_done(struct mbdata *mbp) 1564bff34e3Sthurlow { 1574bff34e3Sthurlow if (mbp->mb_top) { 1584bff34e3Sthurlow m_freem(mbp->mb_top); 1594bff34e3Sthurlow mbp->mb_top = NULL; 1604bff34e3Sthurlow } 1614bff34e3Sthurlow return (0); 1624bff34e3Sthurlow } 1634bff34e3Sthurlow 1644bff34e3Sthurlow int 1654bff34e3Sthurlow m_getm(struct mbuf *top, size_t len, struct mbuf **mpp) 1664bff34e3Sthurlow { 1674bff34e3Sthurlow struct mbuf *m, *mp; 1687568150aSgwr int error, ts; 1694bff34e3Sthurlow 1704bff34e3Sthurlow for (mp = top; ; mp = mp->m_next) { 1717568150aSgwr ts = M_TRAILINGSPACE(mp); 1727568150aSgwr if (len <= ts) 1737568150aSgwr goto out; 1747568150aSgwr len -= ts; 1754bff34e3Sthurlow if (mp->m_next == NULL) 1764bff34e3Sthurlow break; 1774bff34e3Sthurlow 1784bff34e3Sthurlow } 1794bff34e3Sthurlow if (len > 0) { 1804bff34e3Sthurlow if ((error = m_get(len, &m)) != 0) 1814bff34e3Sthurlow return (error); 1824bff34e3Sthurlow mp->m_next = m; 1834bff34e3Sthurlow } 1847568150aSgwr out: 1854bff34e3Sthurlow *mpp = top; 1864bff34e3Sthurlow return (0); 1874bff34e3Sthurlow } 1884bff34e3Sthurlow 1894bff34e3Sthurlow /* 1904bff34e3Sthurlow * Routines to put data in a buffer 1914bff34e3Sthurlow */ 1924bff34e3Sthurlow 1934bff34e3Sthurlow /* 1944bff34e3Sthurlow * Check if object of size 'size' fit to the current position and 1954bff34e3Sthurlow * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 1964bff34e3Sthurlow * Return pointer to the object placeholder or NULL if any error occured. 1974bff34e3Sthurlow */ 1984bff34e3Sthurlow int 1994bff34e3Sthurlow mb_fit(struct mbdata *mbp, size_t size, char **pp) 2004bff34e3Sthurlow { 2014bff34e3Sthurlow struct mbuf *m, *mn; 2024bff34e3Sthurlow int error; 2034bff34e3Sthurlow 2044bff34e3Sthurlow m = mbp->mb_cur; 2054bff34e3Sthurlow if (M_TRAILINGSPACE(m) < (int)size) { 2064bff34e3Sthurlow if ((error = m_get(size, &mn)) != 0) 2074bff34e3Sthurlow return (error); 2084bff34e3Sthurlow mbp->mb_pos = mtod(mn, char *); 2094bff34e3Sthurlow mbp->mb_cur = m->m_next = mn; 2104bff34e3Sthurlow m = mn; 2114bff34e3Sthurlow } 2124bff34e3Sthurlow m->m_len += size; 2134bff34e3Sthurlow *pp = mbp->mb_pos; 2144bff34e3Sthurlow mbp->mb_pos += size; 2154bff34e3Sthurlow mbp->mb_count += size; 2164bff34e3Sthurlow return (0); 2174bff34e3Sthurlow } 2184bff34e3Sthurlow 2194bff34e3Sthurlow int 2204bff34e3Sthurlow mb_put_uint8(struct mbdata *mbp, uint8_t x) 2214bff34e3Sthurlow { 2229c9af259SGordon Ross uint8_t y = x; 223*613a2f6bSGordon Ross return (mb_put_mem(mbp, &y, sizeof (y))); 2244bff34e3Sthurlow } 2254bff34e3Sthurlow 2264bff34e3Sthurlow int 2274bff34e3Sthurlow mb_put_uint16be(struct mbdata *mbp, uint16_t x) 2284bff34e3Sthurlow { 2299c9af259SGordon Ross uint16_t y = htobes(x); 230*613a2f6bSGordon Ross return (mb_put_mem(mbp, &y, sizeof (y))); 2314bff34e3Sthurlow } 2324bff34e3Sthurlow 2334bff34e3Sthurlow int 2344bff34e3Sthurlow mb_put_uint16le(struct mbdata *mbp, uint16_t x) 2354bff34e3Sthurlow { 2369c9af259SGordon Ross uint16_t y = htoles(x); 237*613a2f6bSGordon Ross return (mb_put_mem(mbp, &y, sizeof (y))); 2384bff34e3Sthurlow } 2394bff34e3Sthurlow 2404bff34e3Sthurlow int 2414bff34e3Sthurlow mb_put_uint32be(struct mbdata *mbp, uint32_t x) 2424bff34e3Sthurlow { 2439c9af259SGordon Ross uint32_t y = htobel(x); 244*613a2f6bSGordon Ross return (mb_put_mem(mbp, &y, sizeof (y))); 2454bff34e3Sthurlow } 2464bff34e3Sthurlow 2474bff34e3Sthurlow int 2484bff34e3Sthurlow mb_put_uint32le(struct mbdata *mbp, uint32_t x) 2494bff34e3Sthurlow { 2509c9af259SGordon Ross uint32_t y = htolel(x); 251*613a2f6bSGordon Ross return (mb_put_mem(mbp, &y, sizeof (y))); 2524bff34e3Sthurlow } 2534bff34e3Sthurlow 2544bff34e3Sthurlow int 2554bff34e3Sthurlow mb_put_uint64be(struct mbdata *mbp, uint64_t x) 2564bff34e3Sthurlow { 2579c9af259SGordon Ross uint64_t y = htobeq(x); 258*613a2f6bSGordon Ross return (mb_put_mem(mbp, &y, sizeof (y))); 2594bff34e3Sthurlow } 2604bff34e3Sthurlow 2614bff34e3Sthurlow int 2624bff34e3Sthurlow mb_put_uint64le(struct mbdata *mbp, uint64_t x) 2634bff34e3Sthurlow { 2649c9af259SGordon Ross uint64_t y = htoleq(x); 265*613a2f6bSGordon Ross return (mb_put_mem(mbp, &y, sizeof (y))); 2664bff34e3Sthurlow } 2674bff34e3Sthurlow 2684bff34e3Sthurlow int 269*613a2f6bSGordon Ross mb_put_mem(struct mbdata *mbp, const void *vmem, size_t size) 2704bff34e3Sthurlow { 2714bff34e3Sthurlow struct mbuf *m; 272*613a2f6bSGordon Ross const char *src; 2734bff34e3Sthurlow char *dst; 2744bff34e3Sthurlow size_t cplen; 2754bff34e3Sthurlow int error; 2764bff34e3Sthurlow 2774bff34e3Sthurlow if (size == 0) 2784bff34e3Sthurlow return (0); 279*613a2f6bSGordon Ross 280*613a2f6bSGordon Ross src = vmem; 2814bff34e3Sthurlow m = mbp->mb_cur; 2824bff34e3Sthurlow if ((error = m_getm(m, size, &m)) != 0) 2834bff34e3Sthurlow return (error); 2844bff34e3Sthurlow while (size > 0) { 2854bff34e3Sthurlow cplen = M_TRAILINGSPACE(m); 2864bff34e3Sthurlow if (cplen == 0) { 2874bff34e3Sthurlow m = m->m_next; 2884bff34e3Sthurlow continue; 2894bff34e3Sthurlow } 2904bff34e3Sthurlow if (cplen > size) 2914bff34e3Sthurlow cplen = size; 2924bff34e3Sthurlow dst = mtod(m, char *) + m->m_len; 293*613a2f6bSGordon Ross if (src) { 294*613a2f6bSGordon Ross bcopy(src, dst, cplen); 295*613a2f6bSGordon Ross src += cplen; 2964bff34e3Sthurlow } else 2974bff34e3Sthurlow bzero(dst, cplen); 2984bff34e3Sthurlow size -= cplen; 2994bff34e3Sthurlow m->m_len += cplen; 3004bff34e3Sthurlow mbp->mb_count += cplen; 3014bff34e3Sthurlow } 3024bff34e3Sthurlow mbp->mb_pos = mtod(m, char *) + m->m_len; 3034bff34e3Sthurlow mbp->mb_cur = m; 3044bff34e3Sthurlow return (0); 3054bff34e3Sthurlow } 3064bff34e3Sthurlow 307*613a2f6bSGordon Ross /* 308*613a2f6bSGordon Ross * Append another mbuf to the mbuf chain. 309*613a2f6bSGordon Ross * If what we're appending is smaller than 310*613a2f6bSGordon Ross * the current trailing space, just copy. 311*613a2f6bSGordon Ross * This always consumes the passed mbuf. 312*613a2f6bSGordon Ross */ 3134bff34e3Sthurlow int 3144bff34e3Sthurlow mb_put_mbuf(struct mbdata *mbp, struct mbuf *m) 3154bff34e3Sthurlow { 316*613a2f6bSGordon Ross struct mbuf *cm = mbp->mb_cur; 317*613a2f6bSGordon Ross int ts = M_TRAILINGSPACE(cm); 318*613a2f6bSGordon Ross 319*613a2f6bSGordon Ross if (m->m_next == NULL && m->m_len <= ts) { 320*613a2f6bSGordon Ross /* just copy */ 321*613a2f6bSGordon Ross mb_put_mem(mbp, m->m_data, m->m_len); 322*613a2f6bSGordon Ross m_freem(m); 323*613a2f6bSGordon Ross return (0); 324*613a2f6bSGordon Ross } 325*613a2f6bSGordon Ross 326*613a2f6bSGordon Ross cm->m_next = m; 3274bff34e3Sthurlow while (m) { 3284bff34e3Sthurlow mbp->mb_count += m->m_len; 3294bff34e3Sthurlow if (m->m_next == NULL) 3304bff34e3Sthurlow break; 3314bff34e3Sthurlow m = m->m_next; 3324bff34e3Sthurlow } 3334bff34e3Sthurlow mbp->mb_pos = mtod(m, char *) + m->m_len; 3344bff34e3Sthurlow mbp->mb_cur = m; 3354bff34e3Sthurlow return (0); 3364bff34e3Sthurlow } 3374bff34e3Sthurlow 338*613a2f6bSGordon Ross /* 339*613a2f6bSGordon Ross * Convenience function to put an OEM or Unicode string, 340*613a2f6bSGordon Ross * null terminated, and aligned if necessary. 341*613a2f6bSGordon Ross */ 3424bff34e3Sthurlow int 343*613a2f6bSGordon Ross mb_put_dstring(struct mbdata *mbp, const char *s, int uc) 3444bff34e3Sthurlow { 345*613a2f6bSGordon Ross int err; 3464bff34e3Sthurlow 347*613a2f6bSGordon Ross if (uc) { 348*613a2f6bSGordon Ross /* Put Unicode. align(2) first. */ 349*613a2f6bSGordon Ross if (mbp->mb_count & 1) 350*613a2f6bSGordon Ross mb_put_uint8(mbp, 0); 351*613a2f6bSGordon Ross err = mb_put_ustring(mbp, s); 352*613a2f6bSGordon Ross } else { 353*613a2f6bSGordon Ross /* Put ASCII (really OEM) */ 354*613a2f6bSGordon Ross err = mb_put_astring(mbp, s); 3554bff34e3Sthurlow } 356*613a2f6bSGordon Ross 357*613a2f6bSGordon Ross return (err); 358*613a2f6bSGordon Ross } 359*613a2f6bSGordon Ross 360*613a2f6bSGordon Ross /* 361*613a2f6bSGordon Ross * Put an ASCII string (really OEM), given a UTF-8 string. 362*613a2f6bSGordon Ross */ 363*613a2f6bSGordon Ross int 364*613a2f6bSGordon Ross mb_put_astring(struct mbdata *mbp, const char *s) 365*613a2f6bSGordon Ross { 366*613a2f6bSGordon Ross char *abuf; 367*613a2f6bSGordon Ross int err, len; 368*613a2f6bSGordon Ross 369*613a2f6bSGordon Ross abuf = convert_utf8_to_wincs(s); 370*613a2f6bSGordon Ross if (abuf == NULL) 371*613a2f6bSGordon Ross return (ENOMEM); 372*613a2f6bSGordon Ross len = strlen(abuf) + 1; 373*613a2f6bSGordon Ross err = mb_put_mem(mbp, abuf, len); 374*613a2f6bSGordon Ross free(abuf); 375*613a2f6bSGordon Ross return (err); 376*613a2f6bSGordon Ross } 377*613a2f6bSGordon Ross 378*613a2f6bSGordon Ross /* 379*613a2f6bSGordon Ross * Put UCS-2LE, given a UTF-8 string. 380*613a2f6bSGordon Ross */ 381*613a2f6bSGordon Ross int 382*613a2f6bSGordon Ross mb_put_ustring(struct mbdata *mbp, const char *s) 383*613a2f6bSGordon Ross { 384*613a2f6bSGordon Ross uint16_t *ubuf; 385*613a2f6bSGordon Ross int err, len; 386*613a2f6bSGordon Ross 387*613a2f6bSGordon Ross ubuf = convert_utf8_to_leunicode(s); 388*613a2f6bSGordon Ross if (ubuf == NULL) 389*613a2f6bSGordon Ross return (ENOMEM); 390*613a2f6bSGordon Ross len = unicode_strlen(ubuf) + 1; 391*613a2f6bSGordon Ross err = mb_put_mem(mbp, ubuf, (len << 1)); 392*613a2f6bSGordon Ross free(ubuf); 393*613a2f6bSGordon Ross return (err); 3944bff34e3Sthurlow } 3954bff34e3Sthurlow 3964bff34e3Sthurlow /* 3974bff34e3Sthurlow * Routines for fetching data from an mbuf chain 3984bff34e3Sthurlow */ 3994bff34e3Sthurlow #define mb_left(m, p) (mtod(m, char *) + (m)->m_len - (p)) 4004bff34e3Sthurlow 4014bff34e3Sthurlow int 4024bff34e3Sthurlow mb_get_uint8(struct mbdata *mbp, uint8_t *x) 4034bff34e3Sthurlow { 404*613a2f6bSGordon Ross return (mb_get_mem(mbp, x, 1)); 4054bff34e3Sthurlow } 4064bff34e3Sthurlow 4074bff34e3Sthurlow int 4084bff34e3Sthurlow mb_get_uint16(struct mbdata *mbp, uint16_t *x) 4094bff34e3Sthurlow { 410*613a2f6bSGordon Ross return (mb_get_mem(mbp, x, 2)); 4114bff34e3Sthurlow } 4124bff34e3Sthurlow 4134bff34e3Sthurlow int 4144bff34e3Sthurlow mb_get_uint16le(struct mbdata *mbp, uint16_t *x) 4154bff34e3Sthurlow { 4164bff34e3Sthurlow uint16_t v; 417*613a2f6bSGordon Ross int err; 4184bff34e3Sthurlow 419*613a2f6bSGordon Ross if ((err = mb_get_mem(mbp, &v, 2)) != 0) 420*613a2f6bSGordon Ross return (err); 4214bff34e3Sthurlow if (x != NULL) 4224bff34e3Sthurlow *x = letohs(v); 423*613a2f6bSGordon Ross return (0); 4244bff34e3Sthurlow } 4254bff34e3Sthurlow 4264bff34e3Sthurlow int 4274bff34e3Sthurlow mb_get_uint16be(struct mbdata *mbp, uint16_t *x) { 4284bff34e3Sthurlow uint16_t v; 429*613a2f6bSGordon Ross int err; 4304bff34e3Sthurlow 431*613a2f6bSGordon Ross if ((err = mb_get_mem(mbp, &v, 2)) != 0) 432*613a2f6bSGordon Ross return (err); 4334bff34e3Sthurlow if (x != NULL) 4344bff34e3Sthurlow *x = betohs(v); 435*613a2f6bSGordon Ross return (0); 4364bff34e3Sthurlow } 4374bff34e3Sthurlow 4384bff34e3Sthurlow int 4394bff34e3Sthurlow mb_get_uint32(struct mbdata *mbp, uint32_t *x) 4404bff34e3Sthurlow { 441*613a2f6bSGordon Ross return (mb_get_mem(mbp, x, 4)); 4424bff34e3Sthurlow } 4434bff34e3Sthurlow 4444bff34e3Sthurlow int 4454bff34e3Sthurlow mb_get_uint32be(struct mbdata *mbp, uint32_t *x) 4464bff34e3Sthurlow { 4474bff34e3Sthurlow uint32_t v; 448*613a2f6bSGordon Ross int err; 4494bff34e3Sthurlow 450*613a2f6bSGordon Ross if ((err = mb_get_mem(mbp, &v, 4)) != 0) 451*613a2f6bSGordon Ross return (err); 4524bff34e3Sthurlow if (x != NULL) 4534bff34e3Sthurlow *x = betohl(v); 454*613a2f6bSGordon Ross return (0); 4554bff34e3Sthurlow } 4564bff34e3Sthurlow 4574bff34e3Sthurlow int 4584bff34e3Sthurlow mb_get_uint32le(struct mbdata *mbp, uint32_t *x) 4594bff34e3Sthurlow { 4604bff34e3Sthurlow uint32_t v; 461*613a2f6bSGordon Ross int err; 4624bff34e3Sthurlow 463*613a2f6bSGordon Ross if ((err = mb_get_mem(mbp, &v, 4)) != 0) 464*613a2f6bSGordon Ross return (err); 4654bff34e3Sthurlow if (x != NULL) 4664bff34e3Sthurlow *x = letohl(v); 467*613a2f6bSGordon Ross return (0); 4684bff34e3Sthurlow } 4694bff34e3Sthurlow 4704bff34e3Sthurlow int 4714bff34e3Sthurlow mb_get_uint64(struct mbdata *mbp, uint64_t *x) 4724bff34e3Sthurlow { 473*613a2f6bSGordon Ross return (mb_get_mem(mbp, x, 8)); 4744bff34e3Sthurlow } 4754bff34e3Sthurlow 4764bff34e3Sthurlow int 4774bff34e3Sthurlow mb_get_uint64be(struct mbdata *mbp, uint64_t *x) 4784bff34e3Sthurlow { 4794bff34e3Sthurlow uint64_t v; 480*613a2f6bSGordon Ross int err; 4814bff34e3Sthurlow 482*613a2f6bSGordon Ross if ((err = mb_get_mem(mbp, &v, 8)) != 0) 483*613a2f6bSGordon Ross return (err); 4844bff34e3Sthurlow if (x != NULL) 4854bff34e3Sthurlow *x = betohq(v); 486*613a2f6bSGordon Ross return (0); 4874bff34e3Sthurlow } 4884bff34e3Sthurlow 4894bff34e3Sthurlow int 4904bff34e3Sthurlow mb_get_uint64le(struct mbdata *mbp, uint64_t *x) 4914bff34e3Sthurlow { 4924bff34e3Sthurlow uint64_t v; 493*613a2f6bSGordon Ross int err; 4944bff34e3Sthurlow 495*613a2f6bSGordon Ross if ((err = mb_get_mem(mbp, &v, 8)) != 0) 496*613a2f6bSGordon Ross return (err); 4974bff34e3Sthurlow if (x != NULL) 4984bff34e3Sthurlow *x = letohq(v); 499*613a2f6bSGordon Ross return (0); 5004bff34e3Sthurlow } 5014bff34e3Sthurlow 5024bff34e3Sthurlow int 503*613a2f6bSGordon Ross mb_get_mem(struct mbdata *mbp, void *vmem, size_t size) 5044bff34e3Sthurlow { 5054bff34e3Sthurlow struct mbuf *m = mbp->mb_cur; 506*613a2f6bSGordon Ross char *dst = vmem; 5074bff34e3Sthurlow uint_t count; 5084bff34e3Sthurlow 5094bff34e3Sthurlow while (size > 0) { 5104bff34e3Sthurlow if (m == NULL) { 511*613a2f6bSGordon Ross /* DPRINT("incomplete copy"); */ 5124bff34e3Sthurlow return (EBADRPC); 5134bff34e3Sthurlow } 5144bff34e3Sthurlow count = mb_left(m, mbp->mb_pos); 5154bff34e3Sthurlow if (count == 0) { 5164bff34e3Sthurlow mbp->mb_cur = m = m->m_next; 5174bff34e3Sthurlow if (m) 5184bff34e3Sthurlow mbp->mb_pos = mtod(m, char *); 5194bff34e3Sthurlow continue; 5204bff34e3Sthurlow } 5214bff34e3Sthurlow if (count > size) 5224bff34e3Sthurlow count = size; 5234bff34e3Sthurlow size -= count; 524*613a2f6bSGordon Ross if (dst) { 5254bff34e3Sthurlow if (count == 1) { 526*613a2f6bSGordon Ross *dst++ = *mbp->mb_pos; 5274bff34e3Sthurlow } else { 528*613a2f6bSGordon Ross bcopy(mbp->mb_pos, dst, count); 529*613a2f6bSGordon Ross dst += count; 5304bff34e3Sthurlow } 5314bff34e3Sthurlow } 5324bff34e3Sthurlow mbp->mb_pos += count; 5334bff34e3Sthurlow } 5344bff34e3Sthurlow return (0); 5354bff34e3Sthurlow } 536*613a2f6bSGordon Ross 537*613a2f6bSGordon Ross /* 538*613a2f6bSGordon Ross * Get the next SIZE bytes as a separate mblk. 539*613a2f6bSGordon Ross * Nothing fancy here - just copy. 540*613a2f6bSGordon Ross */ 541*613a2f6bSGordon Ross int 542*613a2f6bSGordon Ross mb_get_mbuf(struct mbdata *mbp, int size, struct mbuf **ret) 543*613a2f6bSGordon Ross { 544*613a2f6bSGordon Ross mbuf_t *m; 545*613a2f6bSGordon Ross int err; 546*613a2f6bSGordon Ross 547*613a2f6bSGordon Ross err = m_get(size, &m); 548*613a2f6bSGordon Ross if (err) 549*613a2f6bSGordon Ross return (err); 550*613a2f6bSGordon Ross 551*613a2f6bSGordon Ross err = mb_get_mem(mbp, m->m_data, size); 552*613a2f6bSGordon Ross if (err) { 553*613a2f6bSGordon Ross m_freem(m); 554*613a2f6bSGordon Ross return (err); 555*613a2f6bSGordon Ross } 556*613a2f6bSGordon Ross m->m_len = size; 557*613a2f6bSGordon Ross *ret = m; 558*613a2f6bSGordon Ross 559*613a2f6bSGordon Ross return (0); 560*613a2f6bSGordon Ross } 561*613a2f6bSGordon Ross 562*613a2f6bSGordon Ross /* 563*613a2f6bSGordon Ross * Get a string from the mbuf chain, 564*613a2f6bSGordon Ross * either Unicode or OEM chars. 565*613a2f6bSGordon Ross */ 566*613a2f6bSGordon Ross int 567*613a2f6bSGordon Ross mb_get_string(struct mbdata *mbp, char **str_pp, int uc) 568*613a2f6bSGordon Ross { 569*613a2f6bSGordon Ross int err; 570*613a2f6bSGordon Ross 571*613a2f6bSGordon Ross if (uc) 572*613a2f6bSGordon Ross err = mb_get_ustring(mbp, str_pp); 573*613a2f6bSGordon Ross else 574*613a2f6bSGordon Ross err = mb_get_astring(mbp, str_pp); 575*613a2f6bSGordon Ross return (err); 576*613a2f6bSGordon Ross } 577*613a2f6bSGordon Ross 578*613a2f6bSGordon Ross /* 579*613a2f6bSGordon Ross * Get an ASCII (really OEM) string from the mbuf chain 580*613a2f6bSGordon Ross * and convert it to UTF-8 581*613a2f6bSGordon Ross * Similar to mb_get_ustring below. 582*613a2f6bSGordon Ross */ 583*613a2f6bSGordon Ross int 584*613a2f6bSGordon Ross mb_get_astring(struct mbdata *real_mbp, char **str_pp) 585*613a2f6bSGordon Ross { 586*613a2f6bSGordon Ross struct mbdata tmp_mb, *mbp; 587*613a2f6bSGordon Ross char *tstr, *ostr; 588*613a2f6bSGordon Ross int err, i, slen; 589*613a2f6bSGordon Ross uint8_t ch; 590*613a2f6bSGordon Ross 591*613a2f6bSGordon Ross /* 592*613a2f6bSGordon Ross * First, figure out the string length. 593*613a2f6bSGordon Ross * Use a copy of the real_mbp so we don't 594*613a2f6bSGordon Ross * actually consume it here, then search for 595*613a2f6bSGordon Ross * the null (or end of data). 596*613a2f6bSGordon Ross */ 597*613a2f6bSGordon Ross bcopy(real_mbp, &tmp_mb, sizeof (tmp_mb)); 598*613a2f6bSGordon Ross mbp = &tmp_mb; 599*613a2f6bSGordon Ross slen = 0; 600*613a2f6bSGordon Ross for (;;) { 601*613a2f6bSGordon Ross err = mb_get_uint8(mbp, &ch); 602*613a2f6bSGordon Ross if (err) 603*613a2f6bSGordon Ross break; 604*613a2f6bSGordon Ross if (ch == 0) 605*613a2f6bSGordon Ross break; 606*613a2f6bSGordon Ross slen++; 607*613a2f6bSGordon Ross } 608*613a2f6bSGordon Ross 609*613a2f6bSGordon Ross /* 610*613a2f6bSGordon Ross * Now read the (OEM) string for real. 611*613a2f6bSGordon Ross * No need to re-check errors. 612*613a2f6bSGordon Ross */ 613*613a2f6bSGordon Ross tstr = malloc(slen + 1); 614*613a2f6bSGordon Ross if (tstr == NULL) 615*613a2f6bSGordon Ross return (ENOMEM); 616*613a2f6bSGordon Ross mbp = real_mbp; 617*613a2f6bSGordon Ross for (i = 0; i < slen; i++) { 618*613a2f6bSGordon Ross mb_get_uint8(mbp, &ch); 619*613a2f6bSGordon Ross tstr[i] = ch; 620*613a2f6bSGordon Ross } 621*613a2f6bSGordon Ross tstr[i] = 0; 622*613a2f6bSGordon Ross mb_get_uint8(mbp, NULL); 623*613a2f6bSGordon Ross 624*613a2f6bSGordon Ross /* 625*613a2f6bSGordon Ross * Convert OEM to UTF-8 626*613a2f6bSGordon Ross */ 627*613a2f6bSGordon Ross ostr = convert_wincs_to_utf8(tstr); 628*613a2f6bSGordon Ross free(tstr); 629*613a2f6bSGordon Ross if (ostr == NULL) 630*613a2f6bSGordon Ross return (ENOMEM); 631*613a2f6bSGordon Ross 632*613a2f6bSGordon Ross *str_pp = ostr; 633*613a2f6bSGordon Ross return (0); 634*613a2f6bSGordon Ross } 635*613a2f6bSGordon Ross 636*613a2f6bSGordon Ross /* 637*613a2f6bSGordon Ross * Get a UCS-2LE string from the mbuf chain, and 638*613a2f6bSGordon Ross * convert it to UTF-8. 639*613a2f6bSGordon Ross * 640*613a2f6bSGordon Ross * Similar to mb_get_astring below. 641*613a2f6bSGordon Ross */ 642*613a2f6bSGordon Ross int 643*613a2f6bSGordon Ross mb_get_ustring(struct mbdata *real_mbp, char **str_pp) 644*613a2f6bSGordon Ross { 645*613a2f6bSGordon Ross struct mbdata tmp_mb, *mbp; 646*613a2f6bSGordon Ross uint16_t *tstr; 647*613a2f6bSGordon Ross char *ostr; 648*613a2f6bSGordon Ross int err, i, slen; 649*613a2f6bSGordon Ross uint16_t ch; 650*613a2f6bSGordon Ross 651*613a2f6bSGordon Ross /* 652*613a2f6bSGordon Ross * First, align(2) on the real_mbp 653*613a2f6bSGordon Ross */ 654*613a2f6bSGordon Ross if (((uintptr_t)real_mbp->mb_pos) & 1) 655*613a2f6bSGordon Ross mb_get_uint8(real_mbp, NULL); 656*613a2f6bSGordon Ross 657*613a2f6bSGordon Ross /* 658*613a2f6bSGordon Ross * Next, figure out the string length. 659*613a2f6bSGordon Ross * Use a copy of the real_mbp so we don't 660*613a2f6bSGordon Ross * actually consume it here, then search for 661*613a2f6bSGordon Ross * the null (or end of data). 662*613a2f6bSGordon Ross */ 663*613a2f6bSGordon Ross bcopy(real_mbp, &tmp_mb, sizeof (tmp_mb)); 664*613a2f6bSGordon Ross mbp = &tmp_mb; 665*613a2f6bSGordon Ross slen = 0; 666*613a2f6bSGordon Ross for (;;) { 667*613a2f6bSGordon Ross err = mb_get_uint16le(mbp, &ch); 668*613a2f6bSGordon Ross if (err) 669*613a2f6bSGordon Ross break; 670*613a2f6bSGordon Ross if (ch == 0) 671*613a2f6bSGordon Ross break; 672*613a2f6bSGordon Ross slen++; 673*613a2f6bSGordon Ross } 674*613a2f6bSGordon Ross 675*613a2f6bSGordon Ross /* 676*613a2f6bSGordon Ross * Now read the (UCS-2) string for real. 677*613a2f6bSGordon Ross * No need to re-check errors. Note: 678*613a2f6bSGordon Ross * This puts the UCS-2 in NATIVE order! 679*613a2f6bSGordon Ross */ 680*613a2f6bSGordon Ross tstr = calloc(slen + 1, 2); 681*613a2f6bSGordon Ross if (tstr == NULL) 682*613a2f6bSGordon Ross return (ENOMEM); 683*613a2f6bSGordon Ross mbp = real_mbp; 684*613a2f6bSGordon Ross for (i = 0; i < slen; i++) { 685*613a2f6bSGordon Ross mb_get_uint16le(mbp, &ch); 686*613a2f6bSGordon Ross tstr[i] = ch; 687*613a2f6bSGordon Ross } 688*613a2f6bSGordon Ross tstr[i] = 0; 689*613a2f6bSGordon Ross mb_get_uint16le(mbp, NULL); 690*613a2f6bSGordon Ross 691*613a2f6bSGordon Ross /* 692*613a2f6bSGordon Ross * Convert UCS-2 (native!) to UTF-8 693*613a2f6bSGordon Ross */ 694*613a2f6bSGordon Ross ostr = convert_unicode_to_utf8(tstr); 695*613a2f6bSGordon Ross free(tstr); 696*613a2f6bSGordon Ross if (ostr == NULL) 697*613a2f6bSGordon Ross return (ENOMEM); 698*613a2f6bSGordon Ross 699*613a2f6bSGordon Ross *str_pp = ostr; 700*613a2f6bSGordon Ross return (0); 701*613a2f6bSGordon Ross } 702