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 if (x != NULL) 368 *x = le16toh(v); 369 return error; 370 } 371 372 int 373 mb_get_uint16be(struct mbdata *mbp, u_int16_t *x) { 374 u_int16_t v; 375 int error = mb_get_uint16(mbp, &v); 376 377 if (x != NULL) 378 *x = be16toh(v); 379 return error; 380 } 381 382 int 383 mb_get_uint32(struct mbdata *mbp, u_int32_t *x) 384 { 385 return mb_get_mem(mbp, (char *)x, 4); 386 } 387 388 int 389 mb_get_uint32be(struct mbdata *mbp, u_int32_t *x) 390 { 391 u_int32_t v; 392 int error; 393 394 error = mb_get_uint32(mbp, &v); 395 if (x != NULL) 396 *x = be32toh(v); 397 return error; 398 } 399 400 int 401 mb_get_uint32le(struct mbdata *mbp, u_int32_t *x) 402 { 403 u_int32_t v; 404 int error; 405 406 error = mb_get_uint32(mbp, &v); 407 if (x != NULL) 408 *x = le32toh(v); 409 return error; 410 } 411 412 int 413 mb_get_int64(struct mbdata *mbp, int64_t *x) 414 { 415 return mb_get_mem(mbp, (char *)x, 8); 416 } 417 418 int 419 mb_get_int64be(struct mbdata *mbp, int64_t *x) 420 { 421 int64_t v; 422 int error; 423 424 error = mb_get_int64(mbp, &v); 425 if (x != NULL) 426 *x = be64toh(v); 427 return error; 428 } 429 430 int 431 mb_get_int64le(struct mbdata *mbp, int64_t *x) 432 { 433 int64_t v; 434 int error; 435 436 error = mb_get_int64(mbp, &v); 437 if (x != NULL) 438 *x = le64toh(v); 439 return error; 440 } 441 442 int 443 mb_get_mem(struct mbdata *mbp, char * target, size_t size) 444 { 445 struct mbuf *m = mbp->mb_cur; 446 u_int count; 447 448 while (size > 0) { 449 if (m == NULL) { 450 MBERROR("incomplete copy\n"); 451 return EBADRPC; 452 } 453 count = mb_left(m, mbp->mb_pos); 454 if (count == 0) { 455 mbp->mb_cur = m = m->m_next; 456 if (m) 457 mbp->mb_pos = mtod(m, char *); 458 continue; 459 } 460 if (count > size) 461 count = size; 462 size -= count; 463 if (target) { 464 if (count == 1) { 465 *target++ = *mbp->mb_pos; 466 } else { 467 bcopy(mbp->mb_pos, target, count); 468 target += count; 469 } 470 } 471 mbp->mb_pos += count; 472 } 473 return 0; 474 } 475