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/mchain.h> 37 #include <ctype.h> 38 #include <errno.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 43 #include <netsmb/smb_lib.h> 44 45 #define MBERROR(format, args...) printf("%s(%d): "format, __FUNCTION__ , \ 46 __LINE__ ,## args) 47 48 static int 49 m_get(size_t len, struct mbuf **mpp) 50 { 51 struct mbuf *m; 52 53 len = M_ALIGN(len); 54 if (len < M_MINSIZE) 55 len = M_MINSIZE; 56 m = malloc(M_BASESIZE + len); 57 if (m == NULL) 58 return ENOMEM; 59 bzero(m, M_BASESIZE + len); 60 m->m_maxlen = len; 61 m->m_data = M_TOP(m); 62 *mpp = m; 63 return 0; 64 } 65 66 static void 67 m_free(struct mbuf *m) 68 { 69 free(m); 70 } 71 72 static void 73 m_freem(struct mbuf *m0) 74 { 75 struct mbuf *m; 76 77 while (m0) { 78 m = m0->m_next; 79 m_free(m0); 80 m0 = m; 81 } 82 } 83 84 static size_t 85 m_totlen(struct mbuf *m0) 86 { 87 struct mbuf *m = m0; 88 int len = 0; 89 90 while (m) { 91 len += m->m_len; 92 m = m->m_next; 93 } 94 return len; 95 } 96 97 int 98 m_lineup(struct mbuf *m0, struct mbuf **mpp) 99 { 100 struct mbuf *nm, *m; 101 char *dp; 102 size_t len; 103 int error; 104 105 if (m0->m_next == NULL) { 106 *mpp = m0; 107 return 0; 108 } 109 if ((error = m_get(m_totlen(m0), &nm)) != 0) 110 return error; 111 dp = mtod(nm, char *); 112 while (m0) { 113 len = m0->m_len; 114 bcopy(m0->m_data, dp, len); 115 dp += len; 116 m = m0->m_next; 117 m_free(m0); 118 m0 = m; 119 } 120 *mpp = nm; 121 return 0; 122 } 123 124 int 125 mb_init(struct mbdata *mbp, size_t size) 126 { 127 struct mbuf *m; 128 int error; 129 130 if ((error = m_get(size, &m)) != 0) 131 return error; 132 return mb_initm(mbp, m); 133 } 134 135 int 136 mb_initm(struct mbdata *mbp, struct mbuf *m) 137 { 138 bzero(mbp, sizeof(*mbp)); 139 mbp->mb_top = mbp->mb_cur = m; 140 mbp->mb_pos = mtod(m, char *); 141 return 0; 142 } 143 144 int 145 mb_done(struct mbdata *mbp) 146 { 147 if (mbp->mb_top) { 148 m_freem(mbp->mb_top); 149 mbp->mb_top = NULL; 150 } 151 return 0; 152 } 153 154 /* 155 int 156 mb_fixhdr(struct mbdata *mbp) 157 { 158 struct mbuf *m = mbp->mb_top; 159 int len = 0; 160 161 while (m) { 162 len += m->m_len; 163 m = m->m_next; 164 } 165 mbp->mb_top->m_pkthdr.len = len; 166 return len; 167 } 168 */ 169 int 170 m_getm(struct mbuf *top, size_t len, struct mbuf **mpp) 171 { 172 struct mbuf *m, *mp; 173 int error; 174 175 for (mp = top; ; mp = mp->m_next) { 176 len -= M_TRAILINGSPACE(mp); 177 if (mp->m_next == NULL) 178 break; 179 180 } 181 if (len > 0) { 182 if ((error = m_get(len, &m)) != 0) 183 return error; 184 mp->m_next = m; 185 } 186 *mpp = top; 187 return 0; 188 } 189 190 /* 191 * Routines to put data in a buffer 192 */ 193 #define MB_PUT(t) int error; t *p; \ 194 if ((error = mb_fit(mbp, sizeof(t), (char**)&p)) != 0) \ 195 return error 196 197 /* 198 * Check if object of size 'size' fit to the current position and 199 * allocate new mbuf if not. Advance pointers and increase length of mbuf(s). 200 * Return pointer to the object placeholder or NULL if any error occured. 201 */ 202 int 203 mb_fit(struct mbdata *mbp, size_t size, char **pp) 204 { 205 struct mbuf *m, *mn; 206 int error; 207 208 m = mbp->mb_cur; 209 if (M_TRAILINGSPACE(m) < (int)size) { 210 if ((error = m_get(size, &mn)) != 0) 211 return error; 212 mbp->mb_pos = mtod(mn, char *); 213 mbp->mb_cur = m->m_next = mn; 214 m = mn; 215 } 216 m->m_len += size; 217 *pp = mbp->mb_pos; 218 mbp->mb_pos += size; 219 mbp->mb_count += size; 220 return 0; 221 } 222 223 int 224 mb_put_uint8(struct mbdata *mbp, u_int8_t x) 225 { 226 MB_PUT(u_int8_t); 227 *p = x; 228 return 0; 229 } 230 231 int 232 mb_put_uint16be(struct mbdata *mbp, u_int16_t x) 233 { 234 MB_PUT(u_int16_t); 235 setwbe(p, 0, x); 236 return 0; 237 } 238 239 int 240 mb_put_uint16le(struct mbdata *mbp, u_int16_t x) 241 { 242 MB_PUT(u_int16_t); 243 setwle(p, 0, x); 244 return 0; 245 } 246 247 int 248 mb_put_uint32be(struct mbdata *mbp, u_int32_t x) 249 { 250 MB_PUT(u_int32_t); 251 setdbe(p, 0, x); 252 return 0; 253 } 254 255 int 256 mb_put_uint32le(struct mbdata *mbp, u_int32_t x) 257 { 258 MB_PUT(u_int32_t); 259 setdle(p, 0, x); 260 return 0; 261 } 262 263 int 264 mb_put_int64be(struct mbdata *mbp, int64_t x) 265 { 266 MB_PUT(int64_t); 267 *p = htobeq(x); 268 return 0; 269 } 270 271 int 272 mb_put_int64le(struct mbdata *mbp, int64_t x) 273 { 274 MB_PUT(int64_t); 275 *p = htoleq(x); 276 return 0; 277 } 278 279 int 280 mb_put_mem(struct mbdata *mbp, const char *source, size_t size) 281 { 282 struct mbuf *m; 283 char * dst; 284 size_t cplen; 285 int error; 286 287 if (size == 0) 288 return 0; 289 m = mbp->mb_cur; 290 if ((error = m_getm(m, size, &m)) != 0) 291 return error; 292 while (size > 0) { 293 cplen = M_TRAILINGSPACE(m); 294 if (cplen == 0) { 295 m = m->m_next; 296 continue; 297 } 298 if (cplen > size) 299 cplen = size; 300 dst = mtod(m, char *) + m->m_len; 301 if (source) { 302 bcopy(source, dst, cplen); 303 source += cplen; 304 } else 305 bzero(dst, cplen); 306 size -= cplen; 307 m->m_len += cplen; 308 mbp->mb_count += cplen; 309 } 310 mbp->mb_pos = mtod(m, char *) + m->m_len; 311 mbp->mb_cur = m; 312 return 0; 313 } 314 315 int 316 mb_put_mbuf(struct mbdata *mbp, struct mbuf *m) 317 { 318 mbp->mb_cur->m_next = m; 319 while (m) { 320 mbp->mb_count += m->m_len; 321 if (m->m_next == NULL) 322 break; 323 m = m->m_next; 324 } 325 mbp->mb_pos = mtod(m, char *) + m->m_len; 326 mbp->mb_cur = m; 327 return 0; 328 } 329 330 int 331 mb_put_pstring(struct mbdata *mbp, const char *s) 332 { 333 int error, len = strlen(s); 334 335 if (len > 255) { 336 len = 255; 337 } 338 if ((error = mb_put_uint8(mbp, len)) != 0) 339 return error; 340 return mb_put_mem(mbp, s, len); 341 } 342 343 /* 344 * Routines for fetching data from an mbuf chain 345 */ 346 #define mb_left(m,p) (mtod(m, char *) + (m)->m_len - (p)) 347 348 int 349 mb_get_uint8(struct mbdata *mbp, u_int8_t *x) 350 { 351 return mb_get_mem(mbp, x, 1); 352 } 353 354 int 355 mb_get_uint16(struct mbdata *mbp, u_int16_t *x) 356 { 357 return mb_get_mem(mbp, (char *)x, 2); 358 } 359 360 int 361 mb_get_uint16le(struct mbdata *mbp, u_int16_t *x) 362 { 363 u_int16_t v; 364 int error = mb_get_uint16(mbp, &v); 365 366 *x = letohs(v); 367 return error; 368 } 369 370 int 371 mb_get_uint16be(struct mbdata *mbp, u_int16_t *x) { 372 u_int16_t v; 373 int error = mb_get_uint16(mbp, &v); 374 375 *x = betohs(v); 376 return error; 377 } 378 379 int 380 mb_get_uint32(struct mbdata *mbp, u_int32_t *x) 381 { 382 return mb_get_mem(mbp, (char *)x, 4); 383 } 384 385 int 386 mb_get_uint32be(struct mbdata *mbp, u_int32_t *x) 387 { 388 u_int32_t v; 389 int error; 390 391 error = mb_get_uint32(mbp, &v); 392 *x = betohl(v); 393 return error; 394 } 395 396 int 397 mb_get_uint32le(struct mbdata *mbp, u_int32_t *x) 398 { 399 u_int32_t v; 400 int error; 401 402 error = mb_get_uint32(mbp, &v); 403 *x = letohl(v); 404 return error; 405 } 406 407 int 408 mb_get_int64(struct mbdata *mbp, int64_t *x) 409 { 410 return mb_get_mem(mbp, (char *)x, 8); 411 } 412 413 int 414 mb_get_int64be(struct mbdata *mbp, int64_t *x) 415 { 416 int64_t v; 417 int error; 418 419 error = mb_get_int64(mbp, &v); 420 *x = betohq(v); 421 return error; 422 } 423 424 int 425 mb_get_int64le(struct mbdata *mbp, int64_t *x) 426 { 427 int64_t v; 428 int error; 429 430 error = mb_get_int64(mbp, &v); 431 *x = letohq(v); 432 return error; 433 } 434 435 int 436 mb_get_mem(struct mbdata *mbp, char * target, size_t size) 437 { 438 struct mbuf *m = mbp->mb_cur; 439 u_int count; 440 441 while (size > 0) { 442 if (m == NULL) { 443 MBERROR("incomplete copy\n"); 444 return EBADRPC; 445 } 446 count = mb_left(m, mbp->mb_pos); 447 if (count == 0) { 448 mbp->mb_cur = m = m->m_next; 449 if (m) 450 mbp->mb_pos = mtod(m, char *); 451 continue; 452 } 453 if (count > size) 454 count = size; 455 size -= count; 456 if (target) { 457 if (count == 1) { 458 *target++ = *mbp->mb_pos; 459 } else { 460 bcopy(mbp->mb_pos, target, count); 461 target += count; 462 } 463 } 464 mbp->mb_pos += count; 465 } 466 return 0; 467 } 468