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*15359501SGordon Ross * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 379c9af259SGordon Ross */ 384bff34e3Sthurlow 394bff34e3Sthurlow #include <sys/types.h> 404bff34e3Sthurlow #include <ctype.h> 414bff34e3Sthurlow #include <errno.h> 424bff34e3Sthurlow #include <stdio.h> 434bff34e3Sthurlow #include <stdlib.h> 444bff34e3Sthurlow #include <string.h> 454bff34e3Sthurlow #include <strings.h> 464bff34e3Sthurlow #include <libintl.h> 477568150aSgwr #include <assert.h> 484bff34e3Sthurlow 494bff34e3Sthurlow #include <netsmb/smb_lib.h> 504bff34e3Sthurlow #include <netsmb/mchain.h> 514bff34e3Sthurlow 529c9af259SGordon Ross #include "private.h" 53613a2f6bSGordon Ross #include "charsets.h" 544bff34e3Sthurlow 5502d09e03SGordon Ross /* 5602d09e03SGordon Ross * Note: Leaving a little space (8 bytes) between the 5702d09e03SGordon Ross * mbuf header and the start of the data so we can 5802d09e03SGordon Ross * prepend a NetBIOS header in that space. 5902d09e03SGordon Ross */ 6002d09e03SGordon Ross #define M_ALIGNFACTOR (sizeof (long)) 6102d09e03SGordon Ross #define M_ALIGN(len) (((len) + M_ALIGNFACTOR - 1) & ~(M_ALIGNFACTOR - 1)) 6202d09e03SGordon Ross #define M_BASESIZE (sizeof (struct mbuf) + 8) 6302d09e03SGordon Ross #define M_MINSIZE (1024 - M_BASESIZE) 6402d09e03SGordon Ross #define M_TOP(m) ((char *)(m) + M_BASESIZE) 6502d09e03SGordon Ross #define M_TRAILINGSPACE(m) ((m)->m_maxlen - (m)->m_len) 6602d09e03SGordon Ross 6702d09e03SGordon Ross int 6802d09e03SGordon Ross m_get(int len, struct mbuf **mpp) 694bff34e3Sthurlow { 704bff34e3Sthurlow struct mbuf *m; 714bff34e3Sthurlow 727568150aSgwr assert(len < 0x100000); /* sanity */ 737568150aSgwr 744bff34e3Sthurlow len = M_ALIGN(len); 754bff34e3Sthurlow if (len < M_MINSIZE) 764bff34e3Sthurlow len = M_MINSIZE; 774bff34e3Sthurlow m = malloc(M_BASESIZE + len); 784bff34e3Sthurlow if (m == NULL) 794bff34e3Sthurlow return (ENOMEM); 804bff34e3Sthurlow bzero(m, M_BASESIZE + len); 814bff34e3Sthurlow m->m_maxlen = len; 824bff34e3Sthurlow m->m_data = M_TOP(m); 834bff34e3Sthurlow *mpp = m; 844bff34e3Sthurlow return (0); 854bff34e3Sthurlow } 864bff34e3Sthurlow 874bff34e3Sthurlow static void 884bff34e3Sthurlow m_free(struct mbuf *m) 894bff34e3Sthurlow { 904bff34e3Sthurlow free(m); 914bff34e3Sthurlow } 924bff34e3Sthurlow 93613a2f6bSGordon Ross void 944bff34e3Sthurlow m_freem(struct mbuf *m0) 954bff34e3Sthurlow { 964bff34e3Sthurlow struct mbuf *m; 974bff34e3Sthurlow 984bff34e3Sthurlow while (m0) { 994bff34e3Sthurlow m = m0->m_next; 1004bff34e3Sthurlow m_free(m0); 1014bff34e3Sthurlow m0 = m; 1024bff34e3Sthurlow } 1034bff34e3Sthurlow } 1044bff34e3Sthurlow 105613a2f6bSGordon Ross size_t 1064bff34e3Sthurlow m_totlen(struct mbuf *m0) 1074bff34e3Sthurlow { 1084bff34e3Sthurlow struct mbuf *m = m0; 1094bff34e3Sthurlow int len = 0; 1104bff34e3Sthurlow 1114bff34e3Sthurlow while (m) { 1124bff34e3Sthurlow len += m->m_len; 1134bff34e3Sthurlow m = m->m_next; 1144bff34e3Sthurlow } 1154bff34e3Sthurlow return (len); 1164bff34e3Sthurlow } 1174bff34e3Sthurlow 1184bff34e3Sthurlow int 1194bff34e3Sthurlow m_lineup(struct mbuf *m0, struct mbuf **mpp) 1204bff34e3Sthurlow { 1214bff34e3Sthurlow struct mbuf *nm, *m; 1224bff34e3Sthurlow char *dp; 123*15359501SGordon Ross size_t len, totlen; 1244bff34e3Sthurlow int error; 1254bff34e3Sthurlow 1264bff34e3Sthurlow if (m0->m_next == NULL) { 1274bff34e3Sthurlow *mpp = m0; 1284bff34e3Sthurlow return (0); 1294bff34e3Sthurlow } 130*15359501SGordon Ross totlen = m_totlen(m0); 131*15359501SGordon Ross if ((error = m_get(totlen, &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 } 142*15359501SGordon Ross nm->m_len = totlen; 1434bff34e3Sthurlow *mpp = nm; 1444bff34e3Sthurlow return (0); 1454bff34e3Sthurlow } 1464bff34e3Sthurlow 1474bff34e3Sthurlow int 14802d09e03SGordon Ross mb_init(struct mbdata *mbp) 14902d09e03SGordon Ross { 15002d09e03SGordon Ross return (mb_init_sz(mbp, M_MINSIZE)); 15102d09e03SGordon Ross } 15202d09e03SGordon Ross 15302d09e03SGordon Ross int 15402d09e03SGordon Ross mb_init_sz(struct mbdata *mbp, int size) 1554bff34e3Sthurlow { 1564bff34e3Sthurlow struct mbuf *m; 1574bff34e3Sthurlow int error; 1584bff34e3Sthurlow 1594bff34e3Sthurlow if ((error = m_get(size, &m)) != 0) 1604bff34e3Sthurlow return (error); 16102d09e03SGordon Ross mb_initm(mbp, m); 16202d09e03SGordon Ross return (0); 1634bff34e3Sthurlow } 1644bff34e3Sthurlow 16502d09e03SGordon Ross void 1664bff34e3Sthurlow mb_initm(struct mbdata *mbp, struct mbuf *m) 1674bff34e3Sthurlow { 1684bff34e3Sthurlow bzero(mbp, sizeof (*mbp)); 1694bff34e3Sthurlow mbp->mb_top = mbp->mb_cur = m; 1704bff34e3Sthurlow mbp->mb_pos = mtod(m, char *); 1714bff34e3Sthurlow } 1724bff34e3Sthurlow 17302d09e03SGordon Ross void 1744bff34e3Sthurlow mb_done(struct mbdata *mbp) 1754bff34e3Sthurlow { 1764bff34e3Sthurlow if (mbp->mb_top) { 1774bff34e3Sthurlow m_freem(mbp->mb_top); 1784bff34e3Sthurlow mbp->mb_top = NULL; 1794bff34e3Sthurlow } 1804bff34e3Sthurlow } 1814bff34e3Sthurlow 1824bff34e3Sthurlow int 18302d09e03SGordon Ross m_getm(struct mbuf *top, int len, struct mbuf **mpp) 1844bff34e3Sthurlow { 1854bff34e3Sthurlow struct mbuf *m, *mp; 1867568150aSgwr int error, ts; 1874bff34e3Sthurlow 1884bff34e3Sthurlow for (mp = top; ; mp = mp->m_next) { 1897568150aSgwr ts = M_TRAILINGSPACE(mp); 1907568150aSgwr if (len <= ts) 1917568150aSgwr goto out; 1927568150aSgwr len -= ts; 1934bff34e3Sthurlow if (mp->m_next == NULL) 1944bff34e3Sthurlow break; 1954bff34e3Sthurlow 1964bff34e3Sthurlow } 1974bff34e3Sthurlow if (len > 0) { 1984bff34e3Sthurlow if ((error = m_get(len, &m)) != 0) 1994bff34e3Sthurlow return (error); 2004bff34e3Sthurlow mp->m_next = m; 2014bff34e3Sthurlow } 2027568150aSgwr out: 2034bff34e3Sthurlow *mpp = top; 2044bff34e3Sthurlow return (0); 2054bff34e3Sthurlow } 2064bff34e3Sthurlow 2074bff34e3Sthurlow /* 2084bff34e3Sthurlow * Routines to put data in a buffer 2094bff34e3Sthurlow */ 2104bff34e3Sthurlow 21102d09e03SGordon Ross void * 21202d09e03SGordon Ross mb_reserve(mbchain_t *mbp, int size) 21302d09e03SGordon Ross { 21402d09e03SGordon Ross char *p; 21502d09e03SGordon Ross 21602d09e03SGordon Ross if (mb_fit(mbp, size, &p) != 0) 21702d09e03SGordon Ross return (NULL); 21802d09e03SGordon Ross 21902d09e03SGordon Ross return (p); 22002d09e03SGordon Ross } 22102d09e03SGordon Ross 2224bff34e3Sthurlow /* 2234bff34e3Sthurlow * Check if object of size 'size' fit to the current position and 2244bff34e3Sthurlow * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 2254bff34e3Sthurlow * Return pointer to the object placeholder or NULL if any error occured. 2264bff34e3Sthurlow */ 2274bff34e3Sthurlow int 22802d09e03SGordon Ross mb_fit(mbchain_t *mbp, int size, char **pp) 2294bff34e3Sthurlow { 2304bff34e3Sthurlow struct mbuf *m, *mn; 2314bff34e3Sthurlow int error; 2324bff34e3Sthurlow 2334bff34e3Sthurlow m = mbp->mb_cur; 2344bff34e3Sthurlow if (M_TRAILINGSPACE(m) < (int)size) { 2354bff34e3Sthurlow if ((error = m_get(size, &mn)) != 0) 2364bff34e3Sthurlow return (error); 2374bff34e3Sthurlow mbp->mb_pos = mtod(mn, char *); 2384bff34e3Sthurlow mbp->mb_cur = m->m_next = mn; 2394bff34e3Sthurlow m = mn; 2404bff34e3Sthurlow } 2414bff34e3Sthurlow m->m_len += size; 2424bff34e3Sthurlow *pp = mbp->mb_pos; 2434bff34e3Sthurlow mbp->mb_pos += size; 2444bff34e3Sthurlow mbp->mb_count += size; 2454bff34e3Sthurlow return (0); 2464bff34e3Sthurlow } 2474bff34e3Sthurlow 2484bff34e3Sthurlow int 24902d09e03SGordon Ross mb_put_uint8(mbchain_t *mbp, uint8_t x) 2504bff34e3Sthurlow { 2519c9af259SGordon Ross uint8_t y = x; 25202d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2534bff34e3Sthurlow } 2544bff34e3Sthurlow 2554bff34e3Sthurlow int 25602d09e03SGordon Ross mb_put_uint16be(mbchain_t *mbp, uint16_t x) 2574bff34e3Sthurlow { 2589c9af259SGordon Ross uint16_t y = htobes(x); 25902d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2604bff34e3Sthurlow } 2614bff34e3Sthurlow 2624bff34e3Sthurlow int 26302d09e03SGordon Ross mb_put_uint16le(mbchain_t *mbp, uint16_t x) 2644bff34e3Sthurlow { 2659c9af259SGordon Ross uint16_t y = htoles(x); 26602d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2674bff34e3Sthurlow } 2684bff34e3Sthurlow 2694bff34e3Sthurlow int 27002d09e03SGordon Ross mb_put_uint32be(mbchain_t *mbp, uint32_t x) 2714bff34e3Sthurlow { 2729c9af259SGordon Ross uint32_t y = htobel(x); 27302d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2744bff34e3Sthurlow } 2754bff34e3Sthurlow 2764bff34e3Sthurlow int 27702d09e03SGordon Ross mb_put_uint32le(mbchain_t *mbp, uint32_t x) 2784bff34e3Sthurlow { 2799c9af259SGordon Ross uint32_t y = htolel(x); 28002d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2814bff34e3Sthurlow } 2824bff34e3Sthurlow 2834bff34e3Sthurlow int 28402d09e03SGordon Ross mb_put_uint64be(mbchain_t *mbp, uint64_t x) 2854bff34e3Sthurlow { 2869c9af259SGordon Ross uint64_t y = htobeq(x); 28702d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2884bff34e3Sthurlow } 2894bff34e3Sthurlow 2904bff34e3Sthurlow int 29102d09e03SGordon Ross mb_put_uint64le(mbchain_t *mbp, uint64_t x) 2924bff34e3Sthurlow { 2939c9af259SGordon Ross uint64_t y = htoleq(x); 29402d09e03SGordon Ross return (mb_put_mem(mbp, &y, sizeof (y), MB_MINLINE)); 2954bff34e3Sthurlow } 2964bff34e3Sthurlow 29702d09e03SGordon Ross /* ARGSUSED */ 2984bff34e3Sthurlow int 29902d09e03SGordon Ross mb_put_mem(mbchain_t *mbp, const void *vmem, int size, int type) 3004bff34e3Sthurlow { 3014bff34e3Sthurlow struct mbuf *m; 302613a2f6bSGordon Ross const char *src; 3034bff34e3Sthurlow char *dst; 3044bff34e3Sthurlow size_t cplen; 3054bff34e3Sthurlow int error; 3064bff34e3Sthurlow 3074bff34e3Sthurlow if (size == 0) 3084bff34e3Sthurlow return (0); 309613a2f6bSGordon Ross 310613a2f6bSGordon Ross src = vmem; 3114bff34e3Sthurlow m = mbp->mb_cur; 3124bff34e3Sthurlow if ((error = m_getm(m, size, &m)) != 0) 3134bff34e3Sthurlow return (error); 3144bff34e3Sthurlow while (size > 0) { 3154bff34e3Sthurlow cplen = M_TRAILINGSPACE(m); 3164bff34e3Sthurlow if (cplen == 0) { 3174bff34e3Sthurlow m = m->m_next; 3184bff34e3Sthurlow continue; 3194bff34e3Sthurlow } 3204bff34e3Sthurlow if (cplen > size) 3214bff34e3Sthurlow cplen = size; 3224bff34e3Sthurlow dst = mtod(m, char *) + m->m_len; 323613a2f6bSGordon Ross if (src) { 324613a2f6bSGordon Ross bcopy(src, dst, cplen); 325613a2f6bSGordon Ross src += cplen; 3264bff34e3Sthurlow } else 3274bff34e3Sthurlow bzero(dst, cplen); 3284bff34e3Sthurlow size -= cplen; 3294bff34e3Sthurlow m->m_len += cplen; 3304bff34e3Sthurlow mbp->mb_count += cplen; 3314bff34e3Sthurlow } 3324bff34e3Sthurlow mbp->mb_pos = mtod(m, char *) + m->m_len; 3334bff34e3Sthurlow mbp->mb_cur = m; 3344bff34e3Sthurlow return (0); 3354bff34e3Sthurlow } 3364bff34e3Sthurlow 337613a2f6bSGordon Ross /* 338613a2f6bSGordon Ross * Append another mbuf to the mbuf chain. 339613a2f6bSGordon Ross * If what we're appending is smaller than 340613a2f6bSGordon Ross * the current trailing space, just copy. 341613a2f6bSGordon Ross * This always consumes the passed mbuf. 342613a2f6bSGordon Ross */ 3434bff34e3Sthurlow int 34402d09e03SGordon Ross mb_put_mbuf(mbchain_t *mbp, struct mbuf *m) 3454bff34e3Sthurlow { 346613a2f6bSGordon Ross struct mbuf *cm = mbp->mb_cur; 347613a2f6bSGordon Ross int ts = M_TRAILINGSPACE(cm); 348613a2f6bSGordon Ross 349613a2f6bSGordon Ross if (m->m_next == NULL && m->m_len <= ts) { 350613a2f6bSGordon Ross /* just copy */ 35102d09e03SGordon Ross mb_put_mem(mbp, m->m_data, m->m_len, MB_MSYSTEM); 352613a2f6bSGordon Ross m_freem(m); 353613a2f6bSGordon Ross return (0); 354613a2f6bSGordon Ross } 355613a2f6bSGordon Ross 356613a2f6bSGordon Ross cm->m_next = m; 3574bff34e3Sthurlow while (m) { 3584bff34e3Sthurlow mbp->mb_count += m->m_len; 3594bff34e3Sthurlow if (m->m_next == NULL) 3604bff34e3Sthurlow break; 3614bff34e3Sthurlow m = m->m_next; 3624bff34e3Sthurlow } 3634bff34e3Sthurlow mbp->mb_pos = mtod(m, char *) + m->m_len; 3644bff34e3Sthurlow mbp->mb_cur = m; 3654bff34e3Sthurlow return (0); 3664bff34e3Sthurlow } 3674bff34e3Sthurlow 368613a2f6bSGordon Ross /* 369613a2f6bSGordon Ross * Convenience function to put an OEM or Unicode string, 370613a2f6bSGordon Ross * null terminated, and aligned if necessary. 371613a2f6bSGordon Ross */ 3724bff34e3Sthurlow int 37302d09e03SGordon Ross mb_put_string(mbchain_t *mbp, const char *s, int uc) 3744bff34e3Sthurlow { 375613a2f6bSGordon Ross int err; 3764bff34e3Sthurlow 377613a2f6bSGordon Ross if (uc) { 378613a2f6bSGordon Ross /* Put Unicode. align(2) first. */ 379613a2f6bSGordon Ross if (mbp->mb_count & 1) 380613a2f6bSGordon Ross mb_put_uint8(mbp, 0); 381613a2f6bSGordon Ross err = mb_put_ustring(mbp, s); 382613a2f6bSGordon Ross } else { 383613a2f6bSGordon Ross /* Put ASCII (really OEM) */ 384613a2f6bSGordon Ross err = mb_put_astring(mbp, s); 3854bff34e3Sthurlow } 386613a2f6bSGordon Ross 387613a2f6bSGordon Ross return (err); 388613a2f6bSGordon Ross } 389613a2f6bSGordon Ross 390613a2f6bSGordon Ross /* 391613a2f6bSGordon Ross * Put an ASCII string (really OEM), given a UTF-8 string. 392613a2f6bSGordon Ross */ 393613a2f6bSGordon Ross int 39402d09e03SGordon Ross mb_put_astring(mbchain_t *mbp, const char *s) 395613a2f6bSGordon Ross { 396613a2f6bSGordon Ross char *abuf; 397613a2f6bSGordon Ross int err, len; 398613a2f6bSGordon Ross 399613a2f6bSGordon Ross abuf = convert_utf8_to_wincs(s); 400613a2f6bSGordon Ross if (abuf == NULL) 401613a2f6bSGordon Ross return (ENOMEM); 402613a2f6bSGordon Ross len = strlen(abuf) + 1; 40302d09e03SGordon Ross err = mb_put_mem(mbp, abuf, len, MB_MSYSTEM); 404613a2f6bSGordon Ross free(abuf); 405613a2f6bSGordon Ross return (err); 406613a2f6bSGordon Ross } 407613a2f6bSGordon Ross 408613a2f6bSGordon Ross /* 409613a2f6bSGordon Ross * Put UCS-2LE, given a UTF-8 string. 410613a2f6bSGordon Ross */ 411613a2f6bSGordon Ross int 41202d09e03SGordon Ross mb_put_ustring(mbchain_t *mbp, const char *s) 413613a2f6bSGordon Ross { 414613a2f6bSGordon Ross uint16_t *ubuf; 415613a2f6bSGordon Ross int err, len; 416613a2f6bSGordon Ross 417613a2f6bSGordon Ross ubuf = convert_utf8_to_leunicode(s); 418613a2f6bSGordon Ross if (ubuf == NULL) 419613a2f6bSGordon Ross return (ENOMEM); 42002d09e03SGordon Ross len = 2 * (unicode_strlen(ubuf) + 1); 42102d09e03SGordon Ross err = mb_put_mem(mbp, ubuf, len, MB_MSYSTEM); 422613a2f6bSGordon Ross free(ubuf); 423613a2f6bSGordon Ross return (err); 4244bff34e3Sthurlow } 4254bff34e3Sthurlow 4264bff34e3Sthurlow /* 4274bff34e3Sthurlow * Routines for fetching data from an mbuf chain 4284bff34e3Sthurlow */ 4294bff34e3Sthurlow #define mb_left(m, p) (mtod(m, char *) + (m)->m_len - (p)) 4304bff34e3Sthurlow 4314bff34e3Sthurlow int 43202d09e03SGordon Ross md_get_uint8(mdchain_t *mbp, uint8_t *x) 4334bff34e3Sthurlow { 43402d09e03SGordon Ross return (md_get_mem(mbp, x, 1, MB_MINLINE)); 4354bff34e3Sthurlow } 4364bff34e3Sthurlow 4374bff34e3Sthurlow int 43802d09e03SGordon Ross md_get_uint16le(mdchain_t *mbp, uint16_t *x) 4394bff34e3Sthurlow { 4404bff34e3Sthurlow uint16_t v; 441613a2f6bSGordon Ross int err; 4424bff34e3Sthurlow 44302d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 444613a2f6bSGordon Ross return (err); 4454bff34e3Sthurlow if (x != NULL) 4464bff34e3Sthurlow *x = letohs(v); 447613a2f6bSGordon Ross return (0); 4484bff34e3Sthurlow } 4494bff34e3Sthurlow 4504bff34e3Sthurlow int 45102d09e03SGordon Ross md_get_uint16be(mdchain_t *mbp, uint16_t *x) { 4524bff34e3Sthurlow uint16_t v; 453613a2f6bSGordon Ross int err; 4544bff34e3Sthurlow 45502d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 456613a2f6bSGordon Ross return (err); 4574bff34e3Sthurlow if (x != NULL) 4584bff34e3Sthurlow *x = betohs(v); 459613a2f6bSGordon Ross return (0); 4604bff34e3Sthurlow } 4614bff34e3Sthurlow 4624bff34e3Sthurlow int 46302d09e03SGordon Ross md_get_uint32be(mdchain_t *mbp, uint32_t *x) 4644bff34e3Sthurlow { 4654bff34e3Sthurlow uint32_t v; 466613a2f6bSGordon Ross int err; 4674bff34e3Sthurlow 46802d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 469613a2f6bSGordon Ross return (err); 4704bff34e3Sthurlow if (x != NULL) 4714bff34e3Sthurlow *x = betohl(v); 472613a2f6bSGordon Ross return (0); 4734bff34e3Sthurlow } 4744bff34e3Sthurlow 4754bff34e3Sthurlow int 47602d09e03SGordon Ross md_get_uint32le(mdchain_t *mbp, uint32_t *x) 4774bff34e3Sthurlow { 4784bff34e3Sthurlow uint32_t v; 479613a2f6bSGordon Ross int err; 4804bff34e3Sthurlow 48102d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 482613a2f6bSGordon Ross return (err); 4834bff34e3Sthurlow if (x != NULL) 4844bff34e3Sthurlow *x = letohl(v); 485613a2f6bSGordon Ross return (0); 4864bff34e3Sthurlow } 4874bff34e3Sthurlow 4884bff34e3Sthurlow int 48902d09e03SGordon Ross md_get_uint64be(mdchain_t *mbp, uint64_t *x) 4904bff34e3Sthurlow { 4914bff34e3Sthurlow uint64_t v; 492613a2f6bSGordon Ross int err; 4934bff34e3Sthurlow 49402d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 495613a2f6bSGordon Ross return (err); 4964bff34e3Sthurlow if (x != NULL) 4974bff34e3Sthurlow *x = betohq(v); 498613a2f6bSGordon Ross return (0); 4994bff34e3Sthurlow } 5004bff34e3Sthurlow 5014bff34e3Sthurlow int 50202d09e03SGordon Ross md_get_uint64le(mdchain_t *mbp, uint64_t *x) 5034bff34e3Sthurlow { 5044bff34e3Sthurlow uint64_t v; 505613a2f6bSGordon Ross int err; 5064bff34e3Sthurlow 50702d09e03SGordon Ross if ((err = md_get_mem(mbp, &v, sizeof (v), MB_MINLINE)) != 0) 508613a2f6bSGordon Ross return (err); 5094bff34e3Sthurlow if (x != NULL) 5104bff34e3Sthurlow *x = letohq(v); 511613a2f6bSGordon Ross return (0); 5124bff34e3Sthurlow } 5134bff34e3Sthurlow 51402d09e03SGordon Ross /* ARGSUSED */ 5154bff34e3Sthurlow int 51602d09e03SGordon Ross md_get_mem(mdchain_t *mbp, void *vmem, int size, int type) 5174bff34e3Sthurlow { 5184bff34e3Sthurlow struct mbuf *m = mbp->mb_cur; 519613a2f6bSGordon Ross char *dst = vmem; 5204bff34e3Sthurlow uint_t count; 5214bff34e3Sthurlow 5224bff34e3Sthurlow while (size > 0) { 5234bff34e3Sthurlow if (m == NULL) { 524613a2f6bSGordon Ross /* DPRINT("incomplete copy"); */ 5254bff34e3Sthurlow return (EBADRPC); 5264bff34e3Sthurlow } 5274bff34e3Sthurlow count = mb_left(m, mbp->mb_pos); 5284bff34e3Sthurlow if (count == 0) { 5294bff34e3Sthurlow mbp->mb_cur = m = m->m_next; 5304bff34e3Sthurlow if (m) 5314bff34e3Sthurlow mbp->mb_pos = mtod(m, char *); 5324bff34e3Sthurlow continue; 5334bff34e3Sthurlow } 5344bff34e3Sthurlow if (count > size) 5354bff34e3Sthurlow count = size; 5364bff34e3Sthurlow size -= count; 537613a2f6bSGordon Ross if (dst) { 5384bff34e3Sthurlow if (count == 1) { 539613a2f6bSGordon Ross *dst++ = *mbp->mb_pos; 5404bff34e3Sthurlow } else { 541613a2f6bSGordon Ross bcopy(mbp->mb_pos, dst, count); 542613a2f6bSGordon Ross dst += count; 5434bff34e3Sthurlow } 5444bff34e3Sthurlow } 5454bff34e3Sthurlow mbp->mb_pos += count; 5464bff34e3Sthurlow } 5474bff34e3Sthurlow return (0); 5484bff34e3Sthurlow } 549613a2f6bSGordon Ross 550613a2f6bSGordon Ross /* 551613a2f6bSGordon Ross * Get the next SIZE bytes as a separate mblk. 552613a2f6bSGordon Ross * Nothing fancy here - just copy. 553613a2f6bSGordon Ross */ 554613a2f6bSGordon Ross int 55502d09e03SGordon Ross md_get_mbuf(mdchain_t *mbp, int size, mbuf_t **ret) 556613a2f6bSGordon Ross { 557613a2f6bSGordon Ross mbuf_t *m; 558613a2f6bSGordon Ross int err; 559613a2f6bSGordon Ross 560613a2f6bSGordon Ross err = m_get(size, &m); 561613a2f6bSGordon Ross if (err) 562613a2f6bSGordon Ross return (err); 563613a2f6bSGordon Ross 56402d09e03SGordon Ross err = md_get_mem(mbp, m->m_data, size, MB_MSYSTEM); 565613a2f6bSGordon Ross if (err) { 566613a2f6bSGordon Ross m_freem(m); 567613a2f6bSGordon Ross return (err); 568613a2f6bSGordon Ross } 569613a2f6bSGordon Ross m->m_len = size; 570613a2f6bSGordon Ross *ret = m; 571613a2f6bSGordon Ross 572613a2f6bSGordon Ross return (0); 573613a2f6bSGordon Ross } 574613a2f6bSGordon Ross 575613a2f6bSGordon Ross /* 576613a2f6bSGordon Ross * Get a string from the mbuf chain, 577613a2f6bSGordon Ross * either Unicode or OEM chars. 578613a2f6bSGordon Ross */ 579613a2f6bSGordon Ross int 58002d09e03SGordon Ross md_get_string(mdchain_t *mbp, char **str_pp, int uc) 581613a2f6bSGordon Ross { 582613a2f6bSGordon Ross int err; 583613a2f6bSGordon Ross 584613a2f6bSGordon Ross if (uc) 58502d09e03SGordon Ross err = md_get_ustring(mbp, str_pp); 586613a2f6bSGordon Ross else 58702d09e03SGordon Ross err = md_get_astring(mbp, str_pp); 588613a2f6bSGordon Ross return (err); 589613a2f6bSGordon Ross } 590613a2f6bSGordon Ross 591613a2f6bSGordon Ross /* 592613a2f6bSGordon Ross * Get an ASCII (really OEM) string from the mbuf chain 593613a2f6bSGordon Ross * and convert it to UTF-8 59402d09e03SGordon Ross * 59502d09e03SGordon Ross * Similar to md_get_ustring below. 596613a2f6bSGordon Ross */ 597613a2f6bSGordon Ross int 59802d09e03SGordon Ross md_get_astring(mdchain_t *real_mbp, char **str_pp) 599613a2f6bSGordon Ross { 60002d09e03SGordon Ross mdchain_t tmp_mb, *mbp; 601613a2f6bSGordon Ross char *tstr, *ostr; 602613a2f6bSGordon Ross int err, i, slen; 603613a2f6bSGordon Ross uint8_t ch; 604613a2f6bSGordon Ross 605613a2f6bSGordon Ross /* 606613a2f6bSGordon Ross * First, figure out the string length. 607613a2f6bSGordon Ross * Use a copy of the real_mbp so we don't 608613a2f6bSGordon Ross * actually consume it here, then search for 609613a2f6bSGordon Ross * the null (or end of data). 610613a2f6bSGordon Ross */ 611613a2f6bSGordon Ross bcopy(real_mbp, &tmp_mb, sizeof (tmp_mb)); 612613a2f6bSGordon Ross mbp = &tmp_mb; 613613a2f6bSGordon Ross slen = 0; 614613a2f6bSGordon Ross for (;;) { 61502d09e03SGordon Ross err = md_get_uint8(mbp, &ch); 616613a2f6bSGordon Ross if (err) 617613a2f6bSGordon Ross break; 618613a2f6bSGordon Ross if (ch == 0) 619613a2f6bSGordon Ross break; 620613a2f6bSGordon Ross slen++; 621613a2f6bSGordon Ross } 622613a2f6bSGordon Ross 623613a2f6bSGordon Ross /* 624613a2f6bSGordon Ross * Now read the (OEM) string for real. 625613a2f6bSGordon Ross * No need to re-check errors. 626613a2f6bSGordon Ross */ 627613a2f6bSGordon Ross tstr = malloc(slen + 1); 628613a2f6bSGordon Ross if (tstr == NULL) 629613a2f6bSGordon Ross return (ENOMEM); 630613a2f6bSGordon Ross mbp = real_mbp; 631613a2f6bSGordon Ross for (i = 0; i < slen; i++) { 63202d09e03SGordon Ross md_get_uint8(mbp, &ch); 633613a2f6bSGordon Ross tstr[i] = ch; 634613a2f6bSGordon Ross } 635613a2f6bSGordon Ross tstr[i] = 0; 63602d09e03SGordon Ross md_get_uint8(mbp, NULL); 637613a2f6bSGordon Ross 638613a2f6bSGordon Ross /* 639613a2f6bSGordon Ross * Convert OEM to UTF-8 640613a2f6bSGordon Ross */ 641613a2f6bSGordon Ross ostr = convert_wincs_to_utf8(tstr); 642613a2f6bSGordon Ross free(tstr); 643613a2f6bSGordon Ross if (ostr == NULL) 644613a2f6bSGordon Ross return (ENOMEM); 645613a2f6bSGordon Ross 646613a2f6bSGordon Ross *str_pp = ostr; 647613a2f6bSGordon Ross return (0); 648613a2f6bSGordon Ross } 649613a2f6bSGordon Ross 650613a2f6bSGordon Ross /* 651613a2f6bSGordon Ross * Get a UCS-2LE string from the mbuf chain, and 652613a2f6bSGordon Ross * convert it to UTF-8. 653613a2f6bSGordon Ross * 65402d09e03SGordon Ross * Similar to md_get_astring above. 655613a2f6bSGordon Ross */ 656613a2f6bSGordon Ross int 65702d09e03SGordon Ross md_get_ustring(mdchain_t *real_mbp, char **str_pp) 658613a2f6bSGordon Ross { 65902d09e03SGordon Ross mdchain_t tmp_mb, *mbp; 660613a2f6bSGordon Ross uint16_t *tstr; 661613a2f6bSGordon Ross char *ostr; 662613a2f6bSGordon Ross int err, i, slen; 663613a2f6bSGordon Ross uint16_t ch; 664613a2f6bSGordon Ross 665613a2f6bSGordon Ross /* 666613a2f6bSGordon Ross * First, align(2) on the real_mbp 667613a2f6bSGordon Ross */ 668613a2f6bSGordon Ross if (((uintptr_t)real_mbp->mb_pos) & 1) 66902d09e03SGordon Ross md_get_uint8(real_mbp, NULL); 670613a2f6bSGordon Ross 671613a2f6bSGordon Ross /* 672613a2f6bSGordon Ross * Next, figure out the string length. 673613a2f6bSGordon Ross * Use a copy of the real_mbp so we don't 674613a2f6bSGordon Ross * actually consume it here, then search for 675613a2f6bSGordon Ross * the null (or end of data). 676613a2f6bSGordon Ross */ 677613a2f6bSGordon Ross bcopy(real_mbp, &tmp_mb, sizeof (tmp_mb)); 678613a2f6bSGordon Ross mbp = &tmp_mb; 679613a2f6bSGordon Ross slen = 0; 680613a2f6bSGordon Ross for (;;) { 68102d09e03SGordon Ross err = md_get_uint16le(mbp, &ch); 682613a2f6bSGordon Ross if (err) 683613a2f6bSGordon Ross break; 684613a2f6bSGordon Ross if (ch == 0) 685613a2f6bSGordon Ross break; 686613a2f6bSGordon Ross slen++; 687613a2f6bSGordon Ross } 688613a2f6bSGordon Ross 689613a2f6bSGordon Ross /* 690613a2f6bSGordon Ross * Now read the (UCS-2) string for real. 691613a2f6bSGordon Ross * No need to re-check errors. Note: 692613a2f6bSGordon Ross * This puts the UCS-2 in NATIVE order! 693613a2f6bSGordon Ross */ 694613a2f6bSGordon Ross tstr = calloc(slen + 1, 2); 695613a2f6bSGordon Ross if (tstr == NULL) 696613a2f6bSGordon Ross return (ENOMEM); 697613a2f6bSGordon Ross mbp = real_mbp; 698613a2f6bSGordon Ross for (i = 0; i < slen; i++) { 69902d09e03SGordon Ross md_get_uint16le(mbp, &ch); 700613a2f6bSGordon Ross tstr[i] = ch; 701613a2f6bSGordon Ross } 702613a2f6bSGordon Ross tstr[i] = 0; 70302d09e03SGordon Ross md_get_uint16le(mbp, NULL); 704613a2f6bSGordon Ross 705613a2f6bSGordon Ross /* 706613a2f6bSGordon Ross * Convert UCS-2 (native!) to UTF-8 707613a2f6bSGordon Ross */ 708613a2f6bSGordon Ross ostr = convert_unicode_to_utf8(tstr); 709613a2f6bSGordon Ross free(tstr); 710613a2f6bSGordon Ross if (ostr == NULL) 711613a2f6bSGordon Ross return (ENOMEM); 712613a2f6bSGordon Ross 713613a2f6bSGordon Ross *str_pp = ostr; 714613a2f6bSGordon Ross return (0); 715613a2f6bSGordon Ross } 716