187866Ssheldonh/* 287866Ssheldonh * Copyright (c) 2000, Boris Popov 387866Ssheldonh * All rights reserved. 487866Ssheldonh * 587866Ssheldonh * Redistribution and use in source and binary forms, with or without 687866Ssheldonh * modification, are permitted provided that the following conditions 787866Ssheldonh * are met: 887866Ssheldonh * 1. Redistributions of source code must retain the above copyright 987866Ssheldonh * notice, this list of conditions and the following disclaimer. 1087866Ssheldonh * 2. Redistributions in binary form must reproduce the above copyright 1187866Ssheldonh * notice, this list of conditions and the following disclaimer in the 1287866Ssheldonh * documentation and/or other materials provided with the distribution. 1387866Ssheldonh * 3. All advertising materials mentioning features or use of this software 1487866Ssheldonh * must display the following acknowledgement: 1587866Ssheldonh * This product includes software developed by Boris Popov. 1687866Ssheldonh * 4. Neither the name of the author nor the names of any co-contributors 1787866Ssheldonh * may be used to endorse or promote products derived from this software 1887866Ssheldonh * without specific prior written permission. 1987866Ssheldonh * 2087866Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2187866Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2287866Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2387866Ssheldonh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2487866Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2587866Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2687866Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2787866Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2887866Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2987866Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3087866Ssheldonh * SUCH DAMAGE. 3187866Ssheldonh * 3287866Ssheldonh * $Id: mbuf.c,v 1.6 2001/02/24 15:56:04 bp Exp $ 3387866Ssheldonh */ 3487866Ssheldonh 35136700Sobrien#include <sys/cdefs.h> 36136700Sobrien__FBSDID("$FreeBSD$"); 37136700Sobrien 3887866Ssheldonh#include <sys/types.h> 39150312Simura#include <sys/endian.h> 40136700Sobrien#include <arpa/inet.h> 4187866Ssheldonh#include <ctype.h> 4287866Ssheldonh#include <errno.h> 4387866Ssheldonh#include <stdio.h> 4487866Ssheldonh#include <stdlib.h> 4587866Ssheldonh#include <string.h> 4687866Ssheldonh 4787866Ssheldonh#include <netsmb/smb_lib.h> 4887866Ssheldonh 4987866Ssheldonh#define MBERROR(format, args...) printf("%s(%d): "format, __FUNCTION__ , \ 5087866Ssheldonh __LINE__ ,## args) 5187866Ssheldonh 5287866Ssheldonhstatic int 5387866Ssheldonhm_get(size_t len, struct mbuf **mpp) 5487866Ssheldonh{ 5587866Ssheldonh struct mbuf *m; 5687866Ssheldonh 5787866Ssheldonh len = M_ALIGN(len); 5887866Ssheldonh if (len < M_MINSIZE) 5987866Ssheldonh len = M_MINSIZE; 6087866Ssheldonh m = malloc(M_BASESIZE + len); 6187866Ssheldonh if (m == NULL) 6287866Ssheldonh return ENOMEM; 6387866Ssheldonh bzero(m, M_BASESIZE + len); 6487866Ssheldonh m->m_maxlen = len; 6587866Ssheldonh m->m_data = M_TOP(m); 6687866Ssheldonh *mpp = m; 6787866Ssheldonh return 0; 6887866Ssheldonh} 6987866Ssheldonh 7087866Ssheldonhstatic void 7187866Ssheldonhm_free(struct mbuf *m) 7287866Ssheldonh{ 7387866Ssheldonh free(m); 7487866Ssheldonh} 7587866Ssheldonh 7687866Ssheldonhstatic void 7787866Ssheldonhm_freem(struct mbuf *m0) 7887866Ssheldonh{ 7987866Ssheldonh struct mbuf *m; 8087866Ssheldonh 8187866Ssheldonh while (m0) { 8287866Ssheldonh m = m0->m_next; 8387866Ssheldonh m_free(m0); 8487866Ssheldonh m0 = m; 8587866Ssheldonh } 8687866Ssheldonh} 8787866Ssheldonh 8887866Ssheldonhstatic size_t 8987866Ssheldonhm_totlen(struct mbuf *m0) 9087866Ssheldonh{ 9187866Ssheldonh struct mbuf *m = m0; 9287866Ssheldonh int len = 0; 9387866Ssheldonh 9487866Ssheldonh while (m) { 9587866Ssheldonh len += m->m_len; 9687866Ssheldonh m = m->m_next; 9787866Ssheldonh } 9887866Ssheldonh return len; 9987866Ssheldonh} 10087866Ssheldonh 10187866Ssheldonhint 10287866Ssheldonhm_lineup(struct mbuf *m0, struct mbuf **mpp) 10387866Ssheldonh{ 10487866Ssheldonh struct mbuf *nm, *m; 10587866Ssheldonh char *dp; 10687866Ssheldonh size_t len; 10787866Ssheldonh int error; 10887866Ssheldonh 10987866Ssheldonh if (m0->m_next == NULL) { 11087866Ssheldonh *mpp = m0; 11187866Ssheldonh return 0; 11287866Ssheldonh } 11387866Ssheldonh if ((error = m_get(m_totlen(m0), &nm)) != 0) 11487866Ssheldonh return error; 11587866Ssheldonh dp = mtod(nm, char *); 11687866Ssheldonh while (m0) { 11787866Ssheldonh len = m0->m_len; 11887866Ssheldonh bcopy(m0->m_data, dp, len); 11987866Ssheldonh dp += len; 12087866Ssheldonh m = m0->m_next; 12187866Ssheldonh m_free(m0); 12287866Ssheldonh m0 = m; 12387866Ssheldonh } 12487866Ssheldonh *mpp = nm; 12587866Ssheldonh return 0; 12687866Ssheldonh} 12787866Ssheldonh 12887866Ssheldonhint 12987866Ssheldonhmb_init(struct mbdata *mbp, size_t size) 13087866Ssheldonh{ 13187866Ssheldonh struct mbuf *m; 13287866Ssheldonh int error; 13387866Ssheldonh 13487866Ssheldonh if ((error = m_get(size, &m)) != 0) 13587866Ssheldonh return error; 13687866Ssheldonh return mb_initm(mbp, m); 13787866Ssheldonh} 13887866Ssheldonh 13987866Ssheldonhint 14087866Ssheldonhmb_initm(struct mbdata *mbp, struct mbuf *m) 14187866Ssheldonh{ 14287866Ssheldonh bzero(mbp, sizeof(*mbp)); 14387866Ssheldonh mbp->mb_top = mbp->mb_cur = m; 14487866Ssheldonh mbp->mb_pos = mtod(m, char *); 14587866Ssheldonh return 0; 14687866Ssheldonh} 14787866Ssheldonh 14887866Ssheldonhint 14987866Ssheldonhmb_done(struct mbdata *mbp) 15087866Ssheldonh{ 15187866Ssheldonh if (mbp->mb_top) { 15287866Ssheldonh m_freem(mbp->mb_top); 15387866Ssheldonh mbp->mb_top = NULL; 15487866Ssheldonh } 15587866Ssheldonh return 0; 15687866Ssheldonh} 15787866Ssheldonh 15887866Ssheldonh/* 15987866Ssheldonhint 16087866Ssheldonhmb_fixhdr(struct mbdata *mbp) 16187866Ssheldonh{ 16287866Ssheldonh struct mbuf *m = mbp->mb_top; 16387866Ssheldonh int len = 0; 16487866Ssheldonh 16587866Ssheldonh while (m) { 16687866Ssheldonh len += m->m_len; 16787866Ssheldonh m = m->m_next; 16887866Ssheldonh } 16987866Ssheldonh mbp->mb_top->m_pkthdr.len = len; 17087866Ssheldonh return len; 17187866Ssheldonh} 17287866Ssheldonh*/ 17387866Ssheldonhint 17487866Ssheldonhm_getm(struct mbuf *top, size_t len, struct mbuf **mpp) 17587866Ssheldonh{ 17687866Ssheldonh struct mbuf *m, *mp; 17787866Ssheldonh int error; 17887866Ssheldonh 17987866Ssheldonh for (mp = top; ; mp = mp->m_next) { 18087866Ssheldonh len -= M_TRAILINGSPACE(mp); 18187866Ssheldonh if (mp->m_next == NULL) 18287866Ssheldonh break; 18387866Ssheldonh 18487866Ssheldonh } 18587866Ssheldonh if (len > 0) { 18687866Ssheldonh if ((error = m_get(len, &m)) != 0) 18787866Ssheldonh return error; 18887866Ssheldonh mp->m_next = m; 18987866Ssheldonh } 19087866Ssheldonh *mpp = top; 19187866Ssheldonh return 0; 19287866Ssheldonh} 19387866Ssheldonh 19487866Ssheldonh/* 19587866Ssheldonh * Routines to put data in a buffer 19687866Ssheldonh */ 19787866Ssheldonh#define MB_PUT(t) int error; t *p; \ 19887866Ssheldonh if ((error = mb_fit(mbp, sizeof(t), (char**)&p)) != 0) \ 19987866Ssheldonh return error 20087866Ssheldonh 20187866Ssheldonh/* 20287866Ssheldonh * Check if object of size 'size' fit to the current position and 20387866Ssheldonh * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 20487866Ssheldonh * Return pointer to the object placeholder or NULL if any error occured. 20587866Ssheldonh */ 20687866Ssheldonhint 20787866Ssheldonhmb_fit(struct mbdata *mbp, size_t size, char **pp) 20887866Ssheldonh{ 20987866Ssheldonh struct mbuf *m, *mn; 21087866Ssheldonh int error; 21187866Ssheldonh 21287866Ssheldonh m = mbp->mb_cur; 21387866Ssheldonh if (M_TRAILINGSPACE(m) < (int)size) { 21487866Ssheldonh if ((error = m_get(size, &mn)) != 0) 21587866Ssheldonh return error; 21687866Ssheldonh mbp->mb_pos = mtod(mn, char *); 21787866Ssheldonh mbp->mb_cur = m->m_next = mn; 21887866Ssheldonh m = mn; 21987866Ssheldonh } 22087866Ssheldonh m->m_len += size; 22187866Ssheldonh *pp = mbp->mb_pos; 22287866Ssheldonh mbp->mb_pos += size; 22387866Ssheldonh mbp->mb_count += size; 22487866Ssheldonh return 0; 22587866Ssheldonh} 22687866Ssheldonh 22787866Ssheldonhint 22887866Ssheldonhmb_put_uint8(struct mbdata *mbp, u_int8_t x) 22987866Ssheldonh{ 23087866Ssheldonh MB_PUT(u_int8_t); 23187866Ssheldonh *p = x; 23287866Ssheldonh return 0; 23387866Ssheldonh} 23487866Ssheldonh 23587866Ssheldonhint 23687866Ssheldonhmb_put_uint16be(struct mbdata *mbp, u_int16_t x) 23787866Ssheldonh{ 23887866Ssheldonh MB_PUT(u_int16_t); 23987866Ssheldonh setwbe(p, 0, x); 24087866Ssheldonh return 0; 24187866Ssheldonh} 24287866Ssheldonh 24387866Ssheldonhint 24487866Ssheldonhmb_put_uint16le(struct mbdata *mbp, u_int16_t x) 24587866Ssheldonh{ 24687866Ssheldonh MB_PUT(u_int16_t); 24787866Ssheldonh setwle(p, 0, x); 24887866Ssheldonh return 0; 24987866Ssheldonh} 25087866Ssheldonh 25187866Ssheldonhint 25287866Ssheldonhmb_put_uint32be(struct mbdata *mbp, u_int32_t x) 25387866Ssheldonh{ 25487866Ssheldonh MB_PUT(u_int32_t); 25587866Ssheldonh setdbe(p, 0, x); 25687866Ssheldonh return 0; 25787866Ssheldonh} 25887866Ssheldonh 25987866Ssheldonhint 26087866Ssheldonhmb_put_uint32le(struct mbdata *mbp, u_int32_t x) 26187866Ssheldonh{ 26287866Ssheldonh MB_PUT(u_int32_t); 26387866Ssheldonh setdle(p, 0, x); 26487866Ssheldonh return 0; 26587866Ssheldonh} 26687866Ssheldonh 26787866Ssheldonhint 26887866Ssheldonhmb_put_int64be(struct mbdata *mbp, int64_t x) 26987866Ssheldonh{ 27087866Ssheldonh MB_PUT(int64_t); 271150312Simura *p = htobe64(x); 27287866Ssheldonh return 0; 27387866Ssheldonh} 27487866Ssheldonh 27587866Ssheldonhint 27687866Ssheldonhmb_put_int64le(struct mbdata *mbp, int64_t x) 27787866Ssheldonh{ 27887866Ssheldonh MB_PUT(int64_t); 279150312Simura *p = htole64(x); 28087866Ssheldonh return 0; 28187866Ssheldonh} 28287866Ssheldonh 28387866Ssheldonhint 28487866Ssheldonhmb_put_mem(struct mbdata *mbp, const char *source, size_t size) 28587866Ssheldonh{ 28687866Ssheldonh struct mbuf *m; 28787866Ssheldonh char * dst; 28887866Ssheldonh size_t cplen; 28987866Ssheldonh int error; 29087866Ssheldonh 29187866Ssheldonh if (size == 0) 29287866Ssheldonh return 0; 29387866Ssheldonh m = mbp->mb_cur; 29487866Ssheldonh if ((error = m_getm(m, size, &m)) != 0) 29587866Ssheldonh return error; 29687866Ssheldonh while (size > 0) { 29787866Ssheldonh cplen = M_TRAILINGSPACE(m); 29887866Ssheldonh if (cplen == 0) { 29987866Ssheldonh m = m->m_next; 30087866Ssheldonh continue; 30187866Ssheldonh } 30287866Ssheldonh if (cplen > size) 30387866Ssheldonh cplen = size; 30487866Ssheldonh dst = mtod(m, char *) + m->m_len; 30587866Ssheldonh if (source) { 30687866Ssheldonh bcopy(source, dst, cplen); 30787866Ssheldonh source += cplen; 30887866Ssheldonh } else 30987866Ssheldonh bzero(dst, cplen); 31087866Ssheldonh size -= cplen; 31187866Ssheldonh m->m_len += cplen; 31287866Ssheldonh mbp->mb_count += cplen; 31387866Ssheldonh } 31487866Ssheldonh mbp->mb_pos = mtod(m, char *) + m->m_len; 31587866Ssheldonh mbp->mb_cur = m; 31687866Ssheldonh return 0; 31787866Ssheldonh} 31887866Ssheldonh 31987866Ssheldonhint 32087866Ssheldonhmb_put_mbuf(struct mbdata *mbp, struct mbuf *m) 32187866Ssheldonh{ 32287866Ssheldonh mbp->mb_cur->m_next = m; 32387866Ssheldonh while (m) { 32487866Ssheldonh mbp->mb_count += m->m_len; 32587866Ssheldonh if (m->m_next == NULL) 32687866Ssheldonh break; 32787866Ssheldonh m = m->m_next; 32887866Ssheldonh } 32987866Ssheldonh mbp->mb_pos = mtod(m, char *) + m->m_len; 33087866Ssheldonh mbp->mb_cur = m; 33187866Ssheldonh return 0; 33287866Ssheldonh} 33387866Ssheldonh 33487866Ssheldonhint 33587866Ssheldonhmb_put_pstring(struct mbdata *mbp, const char *s) 33687866Ssheldonh{ 33787866Ssheldonh int error, len = strlen(s); 33887866Ssheldonh 33987866Ssheldonh if (len > 255) { 34087866Ssheldonh len = 255; 34187866Ssheldonh } 34287866Ssheldonh if ((error = mb_put_uint8(mbp, len)) != 0) 34387866Ssheldonh return error; 34487866Ssheldonh return mb_put_mem(mbp, s, len); 34587866Ssheldonh} 34687866Ssheldonh 34787866Ssheldonh/* 34887866Ssheldonh * Routines for fetching data from an mbuf chain 34987866Ssheldonh */ 35087866Ssheldonh#define mb_left(m,p) (mtod(m, char *) + (m)->m_len - (p)) 35187866Ssheldonh 35287866Ssheldonhint 35387866Ssheldonhmb_get_uint8(struct mbdata *mbp, u_int8_t *x) 35487866Ssheldonh{ 35587866Ssheldonh return mb_get_mem(mbp, x, 1); 35687866Ssheldonh} 35787866Ssheldonh 35887866Ssheldonhint 35987866Ssheldonhmb_get_uint16(struct mbdata *mbp, u_int16_t *x) 36087866Ssheldonh{ 36187866Ssheldonh return mb_get_mem(mbp, (char *)x, 2); 36287866Ssheldonh} 36387866Ssheldonh 36487866Ssheldonhint 36587866Ssheldonhmb_get_uint16le(struct mbdata *mbp, u_int16_t *x) 36687866Ssheldonh{ 36787866Ssheldonh u_int16_t v; 36887866Ssheldonh int error = mb_get_uint16(mbp, &v); 36987866Ssheldonh 370150312Simura *x = le16toh(v); 37187866Ssheldonh return error; 37287866Ssheldonh} 37387866Ssheldonh 37487866Ssheldonhint 37587866Ssheldonhmb_get_uint16be(struct mbdata *mbp, u_int16_t *x) { 37687866Ssheldonh u_int16_t v; 37787866Ssheldonh int error = mb_get_uint16(mbp, &v); 37887866Ssheldonh 379150312Simura *x = be16toh(v); 38087866Ssheldonh return error; 38187866Ssheldonh} 38287866Ssheldonh 38387866Ssheldonhint 38487866Ssheldonhmb_get_uint32(struct mbdata *mbp, u_int32_t *x) 38587866Ssheldonh{ 38687866Ssheldonh return mb_get_mem(mbp, (char *)x, 4); 38787866Ssheldonh} 38887866Ssheldonh 38987866Ssheldonhint 39087866Ssheldonhmb_get_uint32be(struct mbdata *mbp, u_int32_t *x) 39187866Ssheldonh{ 39287866Ssheldonh u_int32_t v; 39387866Ssheldonh int error; 39487866Ssheldonh 39587866Ssheldonh error = mb_get_uint32(mbp, &v); 396150312Simura *x = be32toh(v); 39787866Ssheldonh return error; 39887866Ssheldonh} 39987866Ssheldonh 40087866Ssheldonhint 40187866Ssheldonhmb_get_uint32le(struct mbdata *mbp, u_int32_t *x) 40287866Ssheldonh{ 40387866Ssheldonh u_int32_t v; 40487866Ssheldonh int error; 40587866Ssheldonh 40687866Ssheldonh error = mb_get_uint32(mbp, &v); 407150312Simura *x = le32toh(v); 40887866Ssheldonh return error; 40987866Ssheldonh} 41087866Ssheldonh 41187866Ssheldonhint 41287866Ssheldonhmb_get_int64(struct mbdata *mbp, int64_t *x) 41387866Ssheldonh{ 41487866Ssheldonh return mb_get_mem(mbp, (char *)x, 8); 41587866Ssheldonh} 41687866Ssheldonh 41787866Ssheldonhint 41887866Ssheldonhmb_get_int64be(struct mbdata *mbp, int64_t *x) 41987866Ssheldonh{ 42087866Ssheldonh int64_t v; 42187866Ssheldonh int error; 42287866Ssheldonh 42387866Ssheldonh error = mb_get_int64(mbp, &v); 424150312Simura *x = be64toh(v); 42587866Ssheldonh return error; 42687866Ssheldonh} 42787866Ssheldonh 42887866Ssheldonhint 42987866Ssheldonhmb_get_int64le(struct mbdata *mbp, int64_t *x) 43087866Ssheldonh{ 43187866Ssheldonh int64_t v; 43287866Ssheldonh int error; 43387866Ssheldonh 43487866Ssheldonh error = mb_get_int64(mbp, &v); 435150312Simura *x = le64toh(v); 43687866Ssheldonh return error; 43787866Ssheldonh} 43887866Ssheldonh 43987866Ssheldonhint 44087866Ssheldonhmb_get_mem(struct mbdata *mbp, char * target, size_t size) 44187866Ssheldonh{ 44287866Ssheldonh struct mbuf *m = mbp->mb_cur; 44387866Ssheldonh u_int count; 44487866Ssheldonh 44587866Ssheldonh while (size > 0) { 44687866Ssheldonh if (m == NULL) { 44787866Ssheldonh MBERROR("incomplete copy\n"); 44887866Ssheldonh return EBADRPC; 44987866Ssheldonh } 45087866Ssheldonh count = mb_left(m, mbp->mb_pos); 45187866Ssheldonh if (count == 0) { 45287866Ssheldonh mbp->mb_cur = m = m->m_next; 45387866Ssheldonh if (m) 45487866Ssheldonh mbp->mb_pos = mtod(m, char *); 45587866Ssheldonh continue; 45687866Ssheldonh } 45787866Ssheldonh if (count > size) 45887866Ssheldonh count = size; 45987866Ssheldonh size -= count; 46087866Ssheldonh if (target) { 46187866Ssheldonh if (count == 1) { 46287866Ssheldonh *target++ = *mbp->mb_pos; 46387866Ssheldonh } else { 46487866Ssheldonh bcopy(mbp->mb_pos, target, count); 46587866Ssheldonh target += count; 46687866Ssheldonh } 46787866Ssheldonh } 46887866Ssheldonh mbp->mb_pos += count; 46987866Ssheldonh } 47087866Ssheldonh return 0; 47187866Ssheldonh} 472