1 /* 2 * Copyright (c) 2000, Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: mbuf.c,v 1.6 2001/02/24 15:56:04 bp Exp $ 33 */ 34 35 #include <sys/types.h> 36 #include <sys/endian.h> 37 #include <arpa/inet.h> 38 #include <ctype.h> 39 #include <errno.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include <netsmb/smb_lib.h> 45 46 #define MBERROR(format, args...) printf("%s(%d): "format, __FUNCTION__ , \ 47 __LINE__ ,## args) 48 49 static int 50 m_get(size_t len, struct mbuf **mpp) 51 { 52 struct mbuf *m; 53 54 len = M_ALIGN(len); 55 if (len < M_MINSIZE) 56 len = M_MINSIZE; 57 m = malloc(M_BASESIZE + len); 58 if (m == NULL) 59 return ENOMEM; 60 bzero(m, M_BASESIZE + len); 61 m->m_maxlen = len; 62 m->m_data = M_TOP(m); 63 *mpp = m; 64 return 0; 65 } 66 67 static void 68 m_free(struct mbuf *m) 69 { 70 free(m); 71 } 72 73 static void 74 m_freem(struct mbuf *m0) 75 { 76 struct mbuf *m; 77 78 while (m0) { 79 m = m0->m_next; 80 m_free(m0); 81 m0 = m; 82 } 83 } 84 85 static size_t 86 m_totlen(struct mbuf *m0) 87 { 88 struct mbuf *m = m0; 89 int len = 0; 90 91 while (m) { 92 len += m->m_len; 93 m = m->m_next; 94 } 95 return len; 96 } 97 98 int 99 m_lineup(struct mbuf *m0, struct mbuf **mpp) 100 { 101 struct mbuf *nm, *m; 102 char *dp; 103 size_t len; 104 int error; 105 106 if (m0->m_next == NULL) { 107 *mpp = m0; 108 return 0; 109 } 110 if ((error = m_get(m_totlen(m0), &nm)) != 0) 111 return error; 112 dp = mtod(nm, char *); 113 while (m0) { 114 len = m0->m_len; 115 bcopy(m0->m_data, dp, len); 116 dp += len; 117 m = m0->m_next; 118 m_free(m0); 119 m0 = m; 120 } 121 *mpp = nm; 122 return 0; 123 } 124 125 int 126 mb_init(struct mbdata *mbp, size_t size) 127 { 128 struct mbuf *m; 129 int error; 130 131 if ((error = m_get(size, &m)) != 0) 132 return error; 133 return mb_initm(mbp, m); 134 } 135 136 int 137 mb_initm(struct mbdata *mbp, struct mbuf *m) 138 { 139 bzero(mbp, sizeof(*mbp)); 140 mbp->mb_top = mbp->mb_cur = m; 141 mbp->mb_pos = mtod(m, char *); 142 return 0; 143 } 144 145 int 146 mb_done(struct mbdata *mbp) 147 { 148 if (mbp->mb_top) { 149 m_freem(mbp->mb_top); 150 mbp->mb_top = NULL; 151 } 152 return 0; 153 } 154 155 /* 156 int 157 mb_fixhdr(struct mbdata *mbp) 158 { 159 struct mbuf *m = mbp->mb_top; 160 int len = 0; 161 162 while (m) { 163 len += m->m_len; 164 m = m->m_next; 165 } 166 mbp->mb_top->m_pkthdr.len = len; 167 return len; 168 } 169 */ 170 int 171 m_getm(struct mbuf *top, size_t len, struct mbuf **mpp) 172 { 173 struct mbuf *m, *mp; 174 int error; 175 176 for (mp = top; ; mp = mp->m_next) { 177 len -= M_TRAILINGSPACE(mp); 178 if (mp->m_next == NULL) 179 break; 180 181 } 182 if (len > 0) { 183 if ((error = m_get(len, &m)) != 0) 184 return error; 185 mp->m_next = m; 186 } 187 *mpp = top; 188 return 0; 189 } 190 191 /* 192 * Routines to put data in a buffer 193 */ 194 #define MB_PUT(t) int error; t *p; \ 195 if ((error = mb_fit(mbp, sizeof(t), (char**)&p)) != 0) \ 196 return error 197 198 /* 199 * Check if object of size 'size' fit to the current position and 200 * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 201 * Return pointer to the object placeholder or NULL if any error occured. 202 */ 203 int 204 mb_fit(struct mbdata *mbp, size_t size, char **pp) 205 { 206 struct mbuf *m, *mn; 207 int error; 208 209 m = mbp->mb_cur; 210 if (M_TRAILINGSPACE(m) < (int)size) { 211 if ((error = m_get(size, &mn)) != 0) 212 return error; 213 mbp->mb_pos = mtod(mn, char *); 214 mbp->mb_cur = m->m_next = mn; 215 m = mn; 216 } 217 m->m_len += size; 218 *pp = mbp->mb_pos; 219 mbp->mb_pos += size; 220 mbp->mb_count += size; 221 return 0; 222 } 223 224 int 225 mb_put_uint8(struct mbdata *mbp, u_int8_t x) 226 { 227 MB_PUT(u_int8_t); 228 *p = x; 229 return 0; 230 } 231 232 int 233 mb_put_uint16be(struct mbdata *mbp, u_int16_t x) 234 { 235 MB_PUT(u_int16_t); 236 setwbe(p, 0, x); 237 return 0; 238 } 239 240 int 241 mb_put_uint16le(struct mbdata *mbp, u_int16_t x) 242 { 243 MB_PUT(u_int16_t); 244 setwle(p, 0, x); 245 return 0; 246 } 247 248 int 249 mb_put_uint32be(struct mbdata *mbp, u_int32_t x) 250 { 251 MB_PUT(u_int32_t); 252 setdbe(p, 0, x); 253 return 0; 254 } 255 256 int 257 mb_put_uint32le(struct mbdata *mbp, u_int32_t x) 258 { 259 MB_PUT(u_int32_t); 260 setdle(p, 0, x); 261 return 0; 262 } 263 264 int 265 mb_put_int64be(struct mbdata *mbp, int64_t x) 266 { 267 MB_PUT(int64_t); 268 *p = htobe64(x); 269 return 0; 270 } 271 272 int 273 mb_put_int64le(struct mbdata *mbp, int64_t x) 274 { 275 MB_PUT(int64_t); 276 *p = htole64(x); 277 return 0; 278 } 279 280 int 281 mb_put_mem(struct mbdata *mbp, const char *source, size_t size) 282 { 283 struct mbuf *m; 284 char * dst; 285 size_t cplen; 286 int error; 287 288 if (size == 0) 289 return 0; 290 m = mbp->mb_cur; 291 if ((error = m_getm(m, size, &m)) != 0) 292 return error; 293 while (size > 0) { 294 cplen = M_TRAILINGSPACE(m); 295 if (cplen == 0) { 296 m = m->m_next; 297 continue; 298 } 299 if (cplen > size) 300 cplen = size; 301 dst = mtod(m, char *) + m->m_len; 302 if (source) { 303 bcopy(source, dst, cplen); 304 source += cplen; 305 } else 306 bzero(dst, cplen); 307 size -= cplen; 308 m->m_len += cplen; 309 mbp->mb_count += cplen; 310 } 311 mbp->mb_pos = mtod(m, char *) + m->m_len; 312 mbp->mb_cur = m; 313 return 0; 314 } 315 316 int 317 mb_put_mbuf(struct mbdata *mbp, struct mbuf *m) 318 { 319 mbp->mb_cur->m_next = m; 320 while (m) { 321 mbp->mb_count += m->m_len; 322 if (m->m_next == NULL) 323 break; 324 m = m->m_next; 325 } 326 mbp->mb_pos = mtod(m, char *) + m->m_len; 327 mbp->mb_cur = m; 328 return 0; 329 } 330 331 int 332 mb_put_pstring(struct mbdata *mbp, const char *s) 333 { 334 int error, len = strlen(s); 335 336 if (len > 255) { 337 len = 255; 338 } 339 if ((error = mb_put_uint8(mbp, len)) != 0) 340 return error; 341 return mb_put_mem(mbp, s, len); 342 } 343 344 /* 345 * Routines for fetching data from an mbuf chain 346 */ 347 #define mb_left(m,p) (mtod(m, char *) + (m)->m_len - (p)) 348 349 int 350 mb_get_uint8(struct mbdata *mbp, u_int8_t *x) 351 { 352 return mb_get_mem(mbp, x, 1); 353 } 354 355 int 356 mb_get_uint16(struct mbdata *mbp, u_int16_t *x) 357 { 358 return mb_get_mem(mbp, (char *)x, 2); 359 } 360 361 int 362 mb_get_uint16le(struct mbdata *mbp, u_int16_t *x) 363 { 364 u_int16_t v; 365 int error = mb_get_uint16(mbp, &v); 366 367 *x = le16toh(v); 368 return error; 369 } 370 371 int 372 mb_get_uint16be(struct mbdata *mbp, u_int16_t *x) { 373 u_int16_t v; 374 int error = mb_get_uint16(mbp, &v); 375 376 *x = be16toh(v); 377 return error; 378 } 379 380 int 381 mb_get_uint32(struct mbdata *mbp, u_int32_t *x) 382 { 383 return mb_get_mem(mbp, (char *)x, 4); 384 } 385 386 int 387 mb_get_uint32be(struct mbdata *mbp, u_int32_t *x) 388 { 389 u_int32_t v; 390 int error; 391 392 error = mb_get_uint32(mbp, &v); 393 *x = be32toh(v); 394 return error; 395 } 396 397 int 398 mb_get_uint32le(struct mbdata *mbp, u_int32_t *x) 399 { 400 u_int32_t v; 401 int error; 402 403 error = mb_get_uint32(mbp, &v); 404 *x = le32toh(v); 405 return error; 406 } 407 408 int 409 mb_get_int64(struct mbdata *mbp, int64_t *x) 410 { 411 return mb_get_mem(mbp, (char *)x, 8); 412 } 413 414 int 415 mb_get_int64be(struct mbdata *mbp, int64_t *x) 416 { 417 int64_t v; 418 int error; 419 420 error = mb_get_int64(mbp, &v); 421 *x = be64toh(v); 422 return error; 423 } 424 425 int 426 mb_get_int64le(struct mbdata *mbp, int64_t *x) 427 { 428 int64_t v; 429 int error; 430 431 error = mb_get_int64(mbp, &v); 432 *x = le64toh(v); 433 return error; 434 } 435 436 int 437 mb_get_mem(struct mbdata *mbp, char * target, size_t size) 438 { 439 struct mbuf *m = mbp->mb_cur; 440 u_int count; 441 442 while (size > 0) { 443 if (m == NULL) { 444 MBERROR("incomplete copy\n"); 445 return EBADRPC; 446 } 447 count = mb_left(m, mbp->mb_pos); 448 if (count == 0) { 449 mbp->mb_cur = m = m->m_next; 450 if (m) 451 mbp->mb_pos = mtod(m, char *); 452 continue; 453 } 454 if (count > size) 455 count = size; 456 size -= count; 457 if (target) { 458 if (count == 1) { 459 *target++ = *mbp->mb_pos; 460 } else { 461 bcopy(mbp->mb_pos, target, count); 462 target += count; 463 } 464 } 465 mbp->mb_pos += count; 466 } 467 return 0; 468 } 469