1 /* 2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22 #include <sys/cdefs.h> 23 #ifndef lint 24 __RCSID("$NetBSD: util.c,v 1.5 2015/03/31 21:59:35 christos Exp $"); 25 #endif 26 27 /* 28 * txtproto_print() derived from original code by Hannes Gredler 29 * (hannes@juniper.net): 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that: (1) source code 33 * distributions retain the above copyright notice and this paragraph 34 * in its entirety, and (2) distributions including binary code include 35 * the above copyright notice and this paragraph in its entirety in 36 * the documentation or other materials provided with the distribution. 37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 38 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 39 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 40 * FOR A PARTICULAR PURPOSE. 41 */ 42 43 #define NETDISSECT_REWORKED 44 #ifdef HAVE_CONFIG_H 45 #include "config.h" 46 #endif 47 48 #include <tcpdump-stdinc.h> 49 50 #include <sys/stat.h> 51 52 #ifdef HAVE_FCNTL_H 53 #include <fcntl.h> 54 #endif 55 #include <stdio.h> 56 #include <stdarg.h> 57 #include <stdlib.h> 58 #include <string.h> 59 60 #include "interface.h" 61 62 /* 63 * Print out a null-terminated filename (or other ascii string). 64 * If ep is NULL, assume no truncation check is needed. 65 * Return true if truncated. 66 */ 67 int 68 fn_print(netdissect_options *ndo, 69 register const u_char *s, register const u_char *ep) 70 { 71 register int ret; 72 register u_char c; 73 74 ret = 1; /* assume truncated */ 75 while (ep == NULL || s < ep) { 76 c = *s++; 77 if (c == '\0') { 78 ret = 0; 79 break; 80 } 81 if (!ND_ISASCII(c)) { 82 c = ND_TOASCII(c); 83 ND_PRINT((ndo, "M-")); 84 } 85 if (!ND_ISPRINT(c)) { 86 c ^= 0x40; /* DEL to ?, others to alpha */ 87 ND_PRINT((ndo, "^")); 88 } 89 ND_PRINT((ndo, "%c", c)); 90 } 91 return(ret); 92 } 93 94 /* 95 * Print out a counted filename (or other ascii string). 96 * If ep is NULL, assume no truncation check is needed. 97 * Return true if truncated. 98 */ 99 int 100 fn_printn(netdissect_options *ndo, 101 register const u_char *s, register u_int n, register const u_char *ep) 102 { 103 register u_char c; 104 105 while (n > 0 && (ep == NULL || s < ep)) { 106 n--; 107 c = *s++; 108 if (!ND_ISASCII(c)) { 109 c = ND_TOASCII(c); 110 ND_PRINT((ndo, "M-")); 111 } 112 if (!ND_ISPRINT(c)) { 113 c ^= 0x40; /* DEL to ?, others to alpha */ 114 ND_PRINT((ndo, "^")); 115 } 116 ND_PRINT((ndo, "%c", c)); 117 } 118 return (n == 0) ? 0 : 1; 119 } 120 121 /* 122 * Print out a null-padded filename (or other ascii string). 123 * If ep is NULL, assume no truncation check is needed. 124 * Return true if truncated. 125 */ 126 int 127 fn_printzp(netdissect_options *ndo, 128 register const u_char *s, register u_int n, 129 register const u_char *ep) 130 { 131 register int ret; 132 register u_char c; 133 134 ret = 1; /* assume truncated */ 135 while (n > 0 && (ep == NULL || s < ep)) { 136 n--; 137 c = *s++; 138 if (c == '\0') { 139 ret = 0; 140 break; 141 } 142 if (!ND_ISASCII(c)) { 143 c = ND_TOASCII(c); 144 ND_PRINT((ndo, "M-")); 145 } 146 if (!ND_ISPRINT(c)) { 147 c ^= 0x40; /* DEL to ?, others to alpha */ 148 ND_PRINT((ndo, "^")); 149 } 150 ND_PRINT((ndo, "%c", c)); 151 } 152 return (n == 0) ? 0 : ret; 153 } 154 155 /* 156 * Format the timestamp 157 */ 158 static char * 159 ts_format(netdissect_options *ndo 160 #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION 161 _U_ 162 #endif 163 , int sec, int usec) 164 { 165 static char buf[sizeof("00:00:00.000000000")]; 166 const char *format; 167 168 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION 169 switch (ndo->ndo_tstamp_precision) { 170 171 case PCAP_TSTAMP_PRECISION_MICRO: 172 format = "%02d:%02d:%02d.%06u"; 173 break; 174 175 case PCAP_TSTAMP_PRECISION_NANO: 176 format = "%02d:%02d:%02d.%09u"; 177 break; 178 179 default: 180 format = "%02d:%02d:%02d.{unknown precision}"; 181 break; 182 } 183 #else 184 format = "%02d:%02d:%02d.%06u"; 185 #endif 186 187 snprintf(buf, sizeof(buf), format, 188 sec / 3600, (sec % 3600) / 60, sec % 60, usec); 189 190 return buf; 191 } 192 193 /* 194 * Print the timestamp 195 */ 196 void 197 ts_print(netdissect_options *ndo, 198 register const struct timeval *tvp) 199 { 200 register int s; 201 struct tm *tm; 202 time_t Time; 203 static unsigned b_sec; 204 static unsigned b_usec; 205 int d_usec; 206 int d_sec; 207 208 switch (ndo->ndo_tflag) { 209 210 case 0: /* Default */ 211 s = (tvp->tv_sec + thiszone) % 86400; 212 ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec))); 213 break; 214 215 case 1: /* No time stamp */ 216 break; 217 218 case 2: /* Unix timeval style */ 219 ND_PRINT((ndo, "%u.%06u ", 220 (unsigned)tvp->tv_sec, 221 (unsigned)tvp->tv_usec)); 222 break; 223 224 case 3: /* Microseconds since previous packet */ 225 case 5: /* Microseconds since first packet */ 226 if (b_sec == 0) { 227 /* init timestamp for first packet */ 228 b_usec = tvp->tv_usec; 229 b_sec = tvp->tv_sec; 230 } 231 232 d_usec = tvp->tv_usec - b_usec; 233 d_sec = tvp->tv_sec - b_sec; 234 235 while (d_usec < 0) { 236 d_usec += 1000000; 237 d_sec--; 238 } 239 240 ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec))); 241 242 if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */ 243 b_sec = tvp->tv_sec; 244 b_usec = tvp->tv_usec; 245 } 246 break; 247 248 case 4: /* Default + Date*/ 249 s = (tvp->tv_sec + thiszone) % 86400; 250 Time = (tvp->tv_sec + thiszone) - s; 251 tm = gmtime (&Time); 252 if (!tm) 253 ND_PRINT((ndo, "Date fail ")); 254 else 255 ND_PRINT((ndo, "%04d-%02d-%02d %s ", 256 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, 257 ts_format(ndo, s, tvp->tv_usec))); 258 break; 259 } 260 } 261 262 /* 263 * Print a relative number of seconds (e.g. hold time, prune timer) 264 * in the form 5m1s. This does no truncation, so 32230861 seconds 265 * is represented as 1y1w1d1h1m1s. 266 */ 267 void 268 relts_print(netdissect_options *ndo, 269 int secs) 270 { 271 static const char *lengths[] = {"y", "w", "d", "h", "m", "s"}; 272 static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; 273 const char **l = lengths; 274 const int *s = seconds; 275 276 if (secs == 0) { 277 ND_PRINT((ndo, "0s")); 278 return; 279 } 280 if (secs < 0) { 281 ND_PRINT((ndo, "-")); 282 secs = -secs; 283 } 284 while (secs > 0) { 285 if (secs >= *s) { 286 ND_PRINT((ndo, "%d%s", secs / *s, *l)); 287 secs -= (secs / *s) * *s; 288 } 289 s++; 290 l++; 291 } 292 } 293 294 /* 295 * this is a generic routine for printing unknown data; 296 * we pass on the linefeed plus indentation string to 297 * get a proper output - returns 0 on error 298 */ 299 300 int 301 print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len) 302 { 303 if (len < 0) { 304 ND_PRINT((ndo,"%sDissector error: print_unknown_data called with negative length", 305 ident)); 306 return(0); 307 } 308 if (ndo->ndo_snapend - cp < len) 309 len = ndo->ndo_snapend - cp; 310 if (len < 0) { 311 ND_PRINT((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet", 312 ident)); 313 return(0); 314 } 315 hex_print(ndo, ident,cp,len); 316 return(1); /* everything is ok */ 317 } 318 319 /* 320 * Convert a token value to a string; use "fmt" if not found. 321 */ 322 const char * 323 tok2strbuf(register const struct tok *lp, register const char *fmt, 324 register u_int v, char *buf, size_t bufsize) 325 { 326 if (lp != NULL) { 327 while (lp->s != NULL) { 328 if (lp->v == v) 329 return (lp->s); 330 ++lp; 331 } 332 } 333 if (fmt == NULL) 334 fmt = "#%d"; 335 336 (void)snprintf(buf, bufsize, fmt, v); 337 return (const char *)buf; 338 } 339 340 /* 341 * Convert a token value to a string; use "fmt" if not found. 342 */ 343 const char * 344 tok2str(register const struct tok *lp, register const char *fmt, 345 register int v) 346 { 347 static char buf[4][128]; 348 static int idx = 0; 349 char *ret; 350 351 ret = buf[idx]; 352 idx = (idx+1) & 3; 353 return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0])); 354 } 355 356 /* 357 * Convert a bit token value to a string; use "fmt" if not found. 358 * this is useful for parsing bitfields, the output strings are seperated 359 * if the s field is positive. 360 */ 361 static char * 362 bittok2str_internal(register const struct tok *lp, register const char *fmt, 363 register int v, register int sep) 364 { 365 static char buf[256]; /* our stringbuffer */ 366 int buflen=0; 367 register int rotbit; /* this is the bit we rotate through all bitpositions */ 368 register int tokval; 369 const char * sepstr = ""; 370 371 while (lp != NULL && lp->s != NULL) { 372 tokval=lp->v; /* load our first value */ 373 rotbit=1; 374 while (rotbit != 0) { 375 /* 376 * lets AND the rotating bit with our token value 377 * and see if we have got a match 378 */ 379 if (tokval == (v&rotbit)) { 380 /* ok we have found something */ 381 buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s", 382 sepstr, lp->s); 383 sepstr = sep ? ", " : ""; 384 break; 385 } 386 rotbit=rotbit<<1; /* no match - lets shift and try again */ 387 } 388 lp++; 389 } 390 391 if (buflen == 0) 392 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */ 393 (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%d" : fmt, v); 394 return (buf); 395 } 396 397 /* 398 * Convert a bit token value to a string; use "fmt" if not found. 399 * this is useful for parsing bitfields, the output strings are not seperated. 400 */ 401 char * 402 bittok2str_nosep(register const struct tok *lp, register const char *fmt, 403 register int v) 404 { 405 return (bittok2str_internal(lp, fmt, v, 0)); 406 } 407 408 /* 409 * Convert a bit token value to a string; use "fmt" if not found. 410 * this is useful for parsing bitfields, the output strings are comma seperated. 411 */ 412 char * 413 bittok2str(register const struct tok *lp, register const char *fmt, 414 register int v) 415 { 416 return (bittok2str_internal(lp, fmt, v, 1)); 417 } 418 419 /* 420 * Convert a value to a string using an array; the macro 421 * tok2strary() in <interface.h> is the public interface to 422 * this function and ensures that the second argument is 423 * correct for bounds-checking. 424 */ 425 const char * 426 tok2strary_internal(register const char **lp, int n, register const char *fmt, 427 register int v) 428 { 429 static char buf[128]; 430 431 if (v >= 0 && v < n && lp[v] != NULL) 432 return lp[v]; 433 if (fmt == NULL) 434 fmt = "#%d"; 435 (void)snprintf(buf, sizeof(buf), fmt, v); 436 return (buf); 437 } 438 439 /* 440 * Convert a 32-bit netmask to prefixlen if possible 441 * the function returns the prefix-len; if plen == -1 442 * then conversion was not possible; 443 */ 444 445 int 446 mask2plen(uint32_t mask) 447 { 448 uint32_t bitmasks[33] = { 449 0x00000000, 450 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 451 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 452 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 453 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 454 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 455 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 456 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 457 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff 458 }; 459 int prefix_len = 32; 460 461 /* let's see if we can transform the mask into a prefixlen */ 462 while (prefix_len >= 0) { 463 if (bitmasks[prefix_len] == mask) 464 break; 465 prefix_len--; 466 } 467 return (prefix_len); 468 } 469 470 #ifdef INET6 471 int 472 mask62plen(const u_char *mask) 473 { 474 u_char bitmasks[9] = { 475 0x00, 476 0x80, 0xc0, 0xe0, 0xf0, 477 0xf8, 0xfc, 0xfe, 0xff 478 }; 479 int byte; 480 int cidr_len = 0; 481 482 for (byte = 0; byte < 16; byte++) { 483 u_int bits; 484 485 for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) { 486 if (mask[byte] == bitmasks[bits]) { 487 cidr_len += bits; 488 break; 489 } 490 } 491 492 if (mask[byte] != 0xff) 493 break; 494 } 495 return (cidr_len); 496 } 497 #endif /* INET6 */ 498 499 /* 500 * Routine to print out information for text-based protocols such as FTP, 501 * HTTP, SMTP, RTSP, SIP, .... 502 */ 503 #define MAX_TOKEN 128 504 505 /* 506 * Fetch a token from a packet, starting at the specified index, 507 * and return the length of the token. 508 * 509 * Returns 0 on error; yes, this is indistinguishable from an empty 510 * token, but an "empty token" isn't a valid token - it just means 511 * either a space character at the beginning of the line (this 512 * includes a blank line) or no more tokens remaining on the line. 513 */ 514 static int 515 fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len, 516 u_char *tbuf, size_t tbuflen) 517 { 518 size_t toklen = 0; 519 520 for (; idx < len; idx++) { 521 if (!ND_TTEST(*(pptr + idx))) { 522 /* ran past end of captured data */ 523 return (0); 524 } 525 if (!isascii(*(pptr + idx))) { 526 /* not an ASCII character */ 527 return (0); 528 } 529 if (isspace(*(pptr + idx))) { 530 /* end of token */ 531 break; 532 } 533 if (!isprint(*(pptr + idx))) { 534 /* not part of a command token or response code */ 535 return (0); 536 } 537 if (toklen + 2 > tbuflen) { 538 /* no room for this character and terminating '\0' */ 539 return (0); 540 } 541 tbuf[toklen] = *(pptr + idx); 542 toklen++; 543 } 544 if (toklen == 0) { 545 /* no token */ 546 return (0); 547 } 548 tbuf[toklen] = '\0'; 549 550 /* 551 * Skip past any white space after the token, until we see 552 * an end-of-line (CR or LF). 553 */ 554 for (; idx < len; idx++) { 555 if (!ND_TTEST(*(pptr + idx))) { 556 /* ran past end of captured data */ 557 break; 558 } 559 if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') { 560 /* end of line */ 561 break; 562 } 563 if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) { 564 /* not a printable ASCII character */ 565 break; 566 } 567 if (!isspace(*(pptr + idx))) { 568 /* beginning of next token */ 569 break; 570 } 571 } 572 return (idx); 573 } 574 575 /* 576 * Scan a buffer looking for a line ending - LF or CR-LF. 577 * Return the index of the character after the line ending or 0 if 578 * we encounter a non-ASCII or non-printable character or don't find 579 * the line ending. 580 */ 581 static u_int 582 print_txt_line(netdissect_options *ndo, const char *protoname, 583 const char *prefix, const u_char *pptr, u_int idx, u_int len) 584 { 585 u_int startidx; 586 u_int linelen; 587 588 startidx = idx; 589 while (idx < len) { 590 ND_TCHECK(*(pptr+idx)); 591 if (*(pptr+idx) == '\n') { 592 /* 593 * LF without CR; end of line. 594 * Skip the LF and print the line, with the 595 * exception of the LF. 596 */ 597 linelen = idx - startidx; 598 idx++; 599 goto print; 600 } else if (*(pptr+idx) == '\r') { 601 /* CR - any LF? */ 602 if ((idx+1) >= len) { 603 /* not in this packet */ 604 return (0); 605 } 606 ND_TCHECK(*(pptr+idx+1)); 607 if (*(pptr+idx+1) == '\n') { 608 /* 609 * CR-LF; end of line. 610 * Skip the CR-LF and print the line, with 611 * the exception of the CR-LF. 612 */ 613 linelen = idx - startidx; 614 idx += 2; 615 goto print; 616 } 617 618 /* 619 * CR followed by something else; treat this 620 * as if it were binary data, and don't print 621 * it. 622 */ 623 return (0); 624 } else if (!isascii(*(pptr+idx)) || 625 (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) { 626 /* 627 * Not a printable ASCII character and not a tab; 628 * treat this as if it were binary data, and 629 * don't print it. 630 */ 631 return (0); 632 } 633 idx++; 634 } 635 636 /* 637 * All printable ASCII, but no line ending after that point 638 * in the buffer; treat this as if it were truncated. 639 */ 640 trunc: 641 linelen = idx - startidx; 642 ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx, 643 protoname)); 644 return (0); 645 646 print: 647 ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx)); 648 return (idx); 649 } 650 651 void 652 txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len, 653 const char *protoname, const char **cmds, u_int flags) 654 { 655 u_int idx, eol; 656 u_char token[MAX_TOKEN+1]; 657 const char *cmd; 658 int is_reqresp = 0; 659 const char *pnp; 660 661 if (cmds != NULL) { 662 /* 663 * This protocol has more than just request and 664 * response lines; see whether this looks like a 665 * request or response. 666 */ 667 idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token)); 668 if (idx != 0) { 669 /* Is this a valid request name? */ 670 while ((cmd = *cmds++) != NULL) { 671 if (strcasecmp((const char *)token, cmd) == 0) { 672 /* Yes. */ 673 is_reqresp = 1; 674 break; 675 } 676 } 677 678 /* 679 * No - is this a valid response code (3 digits)? 680 * 681 * Is this token the response code, or is the next 682 * token the response code? 683 */ 684 if (flags & RESP_CODE_SECOND_TOKEN) { 685 /* 686 * Next token - get it. 687 */ 688 idx = fetch_token(ndo, pptr, idx, len, token, 689 sizeof(token)); 690 } 691 if (idx != 0) { 692 if (isdigit(token[0]) && isdigit(token[1]) && 693 isdigit(token[2]) && token[3] == '\0') { 694 /* Yes. */ 695 is_reqresp = 1; 696 } 697 } 698 } 699 } else { 700 /* 701 * This protocol has only request and response lines 702 * (e.g., FTP, where all the data goes over a 703 * different connection); assume the payload is 704 * a request or response. 705 */ 706 is_reqresp = 1; 707 } 708 709 /* Capitalize the protocol name */ 710 for (pnp = protoname; *pnp != '\0'; pnp++) 711 ND_PRINT((ndo, "%c", toupper((unsigned char)*pnp))); 712 713 if (is_reqresp) { 714 /* 715 * In non-verbose mode, just print the protocol, followed 716 * by the first line as the request or response info. 717 * 718 * In verbose mode, print lines as text until we run out 719 * of characters or see something that's not a 720 * printable-ASCII line. 721 */ 722 if (ndo->ndo_vflag) { 723 /* 724 * We're going to print all the text lines in the 725 * request or response; just print the length 726 * on the first line of the output. 727 */ 728 ND_PRINT((ndo, ", length: %u", len)); 729 for (idx = 0; 730 idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0; 731 idx = eol) 732 ; 733 } else { 734 /* 735 * Just print the first text line. 736 */ 737 print_txt_line(ndo, protoname, ": ", pptr, 0, len); 738 } 739 } 740 } 741 742 /* VARARGS */ 743 void 744 error(const char *fmt, ...) 745 { 746 va_list ap; 747 748 (void)fprintf(stderr, "%s: ", program_name); 749 va_start(ap, fmt); 750 (void)vfprintf(stderr, fmt, ap); 751 va_end(ap); 752 if (*fmt) { 753 fmt += strlen(fmt); 754 if (fmt[-1] != '\n') 755 (void)fputc('\n', stderr); 756 } 757 exit(1); 758 /* NOTREACHED */ 759 } 760 761 /* VARARGS */ 762 void 763 warning(const char *fmt, ...) 764 { 765 va_list ap; 766 767 (void)fprintf(stderr, "%s: WARNING: ", program_name); 768 va_start(ap, fmt); 769 (void)vfprintf(stderr, fmt, ap); 770 va_end(ap); 771 if (*fmt) { 772 fmt += strlen(fmt); 773 if (fmt[-1] != '\n') 774 (void)fputc('\n', stderr); 775 } 776 } 777 778 /* 779 * Copy arg vector into a new buffer, concatenating arguments with spaces. 780 */ 781 char * 782 copy_argv(register char **argv) 783 { 784 register char **p; 785 register u_int len = 0; 786 char *buf; 787 char *src, *dst; 788 789 p = argv; 790 if (*p == 0) 791 return 0; 792 793 while (*p) 794 len += strlen(*p++) + 1; 795 796 buf = (char *)malloc(len); 797 if (buf == NULL) 798 error("copy_argv: malloc"); 799 800 p = argv; 801 dst = buf; 802 while ((src = *p++) != NULL) { 803 while ((*dst++ = *src++) != '\0') 804 ; 805 dst[-1] = ' '; 806 } 807 dst[-1] = '\0'; 808 809 return buf; 810 } 811 812 /* 813 * On Windows, we need to open the file in binary mode, so that 814 * we get all the bytes specified by the size we get from "fstat()". 815 * On UNIX, that's not necessary. O_BINARY is defined on Windows; 816 * we define it as 0 if it's not defined, so it does nothing. 817 */ 818 #ifndef O_BINARY 819 #define O_BINARY 0 820 #endif 821 822 char * 823 read_infile(char *fname) 824 { 825 register int i, fd, cc; 826 register char *cp; 827 struct stat buf; 828 829 fd = open(fname, O_RDONLY|O_BINARY); 830 if (fd < 0) 831 error("can't open %s: %s", fname, pcap_strerror(errno)); 832 833 if (fstat(fd, &buf) < 0) 834 error("can't stat %s: %s", fname, pcap_strerror(errno)); 835 836 cp = malloc((u_int)buf.st_size + 1); 837 if (cp == NULL) 838 error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, 839 fname, pcap_strerror(errno)); 840 cc = read(fd, cp, (u_int)buf.st_size); 841 if (cc < 0) 842 error("read %s: %s", fname, pcap_strerror(errno)); 843 if (cc != buf.st_size) 844 error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); 845 846 close(fd); 847 /* replace "# comment" with spaces */ 848 for (i = 0; i < cc; i++) { 849 if (cp[i] == '#') 850 while (i < cc && cp[i] != '\n') 851 cp[i++] = ' '; 852 } 853 cp[cc] = '\0'; 854 return (cp); 855 } 856 857 void 858 safeputs(netdissect_options *ndo, 859 const u_char *s, const u_int maxlen) 860 { 861 u_int idx = 0; 862 863 while (*s && idx < maxlen) { 864 safeputchar(ndo, *s); 865 idx++; 866 s++; 867 } 868 } 869 870 void 871 safeputchar(netdissect_options *ndo, 872 const u_char c) 873 { 874 ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c)); 875 } 876 877 #ifdef LBL_ALIGN 878 /* 879 * Some compilers try to optimize memcpy(), using the alignment constraint 880 * on the argument pointer type. by using this function, we try to avoid the 881 * optimization. 882 */ 883 void 884 unaligned_memcpy(void *p, const void *q, size_t l) 885 { 886 memcpy(p, q, l); 887 } 888 889 /* As with memcpy(), so with memcmp(). */ 890 int 891 unaligned_memcmp(const void *p, const void *q, size_t l) 892 { 893 return (memcmp(p, q, l)); 894 } 895 #endif 896