1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 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 * Support for splitting captures into multiple files with a maximum 22 * file size: 23 * 24 * Copyright (c) 2001 25 * Seth Webster <swebster (at) sst.ll.mit.edu> 26 */ 27 28 #ifndef lint 29 static const char copyright[] _U_ = 30 "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ 31 The Regents of the University of California. All rights reserved.\n"; 32 static const char rcsid[] _U_ = 33 "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.253.2.13 2007/09/12 19:48:51 guy Exp $ (LBL)"; 34 #endif 35 36 /* 37 * tcpdump - monitor tcp/ip traffic on an ethernet. 38 * 39 * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. 40 * Mercilessly hacked and occasionally improved since then via the 41 * combined efforts of Van, Steve McCanne and Craig Leres of LBL. 42 */ 43 44 #ifdef HAVE_CONFIG_H 45 #include "config.h" 46 #endif 47 48 #include <tcpdump-stdinc.h> 49 50 #ifdef WIN32 51 #include "getopt.h" 52 #include "w32_fzs.h" 53 extern int strcasecmp (const char *__s1, const char *__s2); 54 extern int SIZE_BUF; 55 #define off_t long 56 #define uint UINT 57 #endif /* WIN32 */ 58 59 #ifdef HAVE_SMI_H 60 #include <smi.h> 61 #endif 62 63 #include <pcap.h> 64 #include <signal.h> 65 #include <stdio.h> 66 #include <stdlib.h> 67 #include <string.h> 68 #ifndef WIN32 69 #include <pwd.h> 70 #include <grp.h> 71 #include <errno.h> 72 #endif /* WIN32 */ 73 74 #include "netdissect.h" 75 #include "interface.h" 76 #include "addrtoname.h" 77 #include "machdep.h" 78 #include "setsignal.h" 79 #include "gmt2local.h" 80 #include "pcap-missing.h" 81 82 netdissect_options Gndo; 83 netdissect_options *gndo = &Gndo; 84 85 /* 86 * Define the maximum number of files for the -C flag, and how many 87 * characters can be added to a filename for the -C flag (which 88 * should be enough to handle MAX_CFLAG - 1). 89 */ 90 #define MAX_CFLAG 1000000 91 #define MAX_CFLAG_CHARS 6 92 93 int dflag; /* print filter code */ 94 int Lflag; /* list available data link types and exit */ 95 96 static int infodelay; 97 static int infoprint; 98 99 char *program_name; 100 101 int32_t thiszone; /* seconds offset from gmt to local time */ 102 103 /* Forwards */ 104 static RETSIGTYPE cleanup(int); 105 static void usage(void) __attribute__((noreturn)); 106 static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn)); 107 108 static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 109 static void ndo_default_print(netdissect_options *, const u_char *, u_int); 110 static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); 111 static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 112 static void droproot(const char *, const char *); 113 static void ndo_error(netdissect_options *ndo, const char *fmt, ...); 114 static void ndo_warning(netdissect_options *ndo, const char *fmt, ...); 115 116 #ifdef SIGINFO 117 RETSIGTYPE requestinfo(int); 118 #endif 119 120 #if defined(USE_WIN32_MM_TIMER) 121 #include <MMsystem.h> 122 static UINT timer_id; 123 static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); 124 #elif defined(HAVE_ALARM) 125 static void verbose_stats_dump(int sig); 126 #endif 127 128 static void info(int); 129 static u_int packets_captured; 130 131 typedef u_int (*if_printer)(const struct pcap_pkthdr *, const u_char *); 132 133 struct printer { 134 if_printer f; 135 int type; 136 }; 137 138 static struct printer printers[] = { 139 { arcnet_if_print, DLT_ARCNET }, 140 #ifdef DLT_ARCNET_LINUX 141 { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 142 #endif 143 { ether_if_print, DLT_EN10MB }, 144 { token_if_print, DLT_IEEE802 }, 145 #ifdef DLT_LANE8023 146 { lane_if_print, DLT_LANE8023 }, 147 #endif 148 #ifdef DLT_CIP 149 { cip_if_print, DLT_CIP }, 150 #endif 151 #ifdef DLT_ATM_CLIP 152 { cip_if_print, DLT_ATM_CLIP }, 153 #endif 154 { sl_if_print, DLT_SLIP }, 155 #ifdef DLT_SLIP_BSDOS 156 { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 157 #endif 158 { ppp_if_print, DLT_PPP }, 159 #ifdef DLT_PPP_WITHDIRECTION 160 { ppp_if_print, DLT_PPP_WITHDIRECTION }, 161 #endif 162 #ifdef DLT_PPP_BSDOS 163 { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 164 #endif 165 { fddi_if_print, DLT_FDDI }, 166 { null_if_print, DLT_NULL }, 167 #ifdef DLT_LOOP 168 { null_if_print, DLT_LOOP }, 169 #endif 170 { raw_if_print, DLT_RAW }, 171 { atm_if_print, DLT_ATM_RFC1483 }, 172 #ifdef DLT_C_HDLC 173 { chdlc_if_print, DLT_C_HDLC }, 174 #endif 175 #ifdef DLT_HDLC 176 { chdlc_if_print, DLT_HDLC }, 177 #endif 178 #ifdef DLT_PPP_SERIAL 179 { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 180 #endif 181 #ifdef DLT_PPP_ETHER 182 { pppoe_if_print, DLT_PPP_ETHER }, 183 #endif 184 #ifdef DLT_LINUX_SLL 185 { sll_if_print, DLT_LINUX_SLL }, 186 #endif 187 #ifdef DLT_IEEE802_11 188 { ieee802_11_if_print, DLT_IEEE802_11}, 189 #endif 190 #ifdef DLT_LTALK 191 { ltalk_if_print, DLT_LTALK }, 192 #endif 193 #if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) 194 { pflog_if_print, DLT_PFLOG }, 195 #endif 196 #ifdef DLT_FR 197 { fr_if_print, DLT_FR }, 198 #endif 199 #ifdef DLT_FRELAY 200 { fr_if_print, DLT_FRELAY }, 201 #endif 202 #ifdef DLT_SUNATM 203 { sunatm_if_print, DLT_SUNATM }, 204 #endif 205 #ifdef DLT_IP_OVER_FC 206 { ipfc_if_print, DLT_IP_OVER_FC }, 207 #endif 208 #ifdef DLT_PRISM_HEADER 209 { prism_if_print, DLT_PRISM_HEADER }, 210 #endif 211 #ifdef DLT_IEEE802_11_RADIO 212 { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 213 #endif 214 #ifdef DLT_ENC 215 { enc_if_print, DLT_ENC }, 216 #endif 217 #ifdef DLT_SYMANTEC_FIREWALL 218 { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 219 #endif 220 #ifdef DLT_APPLE_IP_OVER_IEEE1394 221 { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 222 #endif 223 #ifdef DLT_JUNIPER_ATM1 224 { juniper_atm1_print, DLT_JUNIPER_ATM1 }, 225 #endif 226 #ifdef DLT_JUNIPER_ATM2 227 { juniper_atm2_print, DLT_JUNIPER_ATM2 }, 228 #endif 229 #ifdef DLT_JUNIPER_MFR 230 { juniper_mfr_print, DLT_JUNIPER_MFR }, 231 #endif 232 #ifdef DLT_JUNIPER_MLFR 233 { juniper_mlfr_print, DLT_JUNIPER_MLFR }, 234 #endif 235 #ifdef DLT_JUNIPER_MLPPP 236 { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, 237 #endif 238 #ifdef DLT_JUNIPER_PPPOE 239 { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, 240 #endif 241 #ifdef DLT_JUNIPER_PPPOE_ATM 242 { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, 243 #endif 244 #ifdef DLT_JUNIPER_GGSN 245 { juniper_ggsn_print, DLT_JUNIPER_GGSN }, 246 #endif 247 #ifdef DLT_JUNIPER_ES 248 { juniper_es_print, DLT_JUNIPER_ES }, 249 #endif 250 #ifdef DLT_JUNIPER_MONITOR 251 { juniper_monitor_print, DLT_JUNIPER_MONITOR }, 252 #endif 253 #ifdef DLT_JUNIPER_SERVICES 254 { juniper_services_print, DLT_JUNIPER_SERVICES }, 255 #endif 256 #ifdef DLT_JUNIPER_ETHER 257 { juniper_ether_print, DLT_JUNIPER_ETHER }, 258 #endif 259 #ifdef DLT_JUNIPER_PPP 260 { juniper_ppp_print, DLT_JUNIPER_PPP }, 261 #endif 262 #ifdef DLT_JUNIPER_FRELAY 263 { juniper_frelay_print, DLT_JUNIPER_FRELAY }, 264 #endif 265 #ifdef DLT_JUNIPER_CHDLC 266 { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, 267 #endif 268 #ifdef DLT_MFR 269 { mfr_if_print, DLT_MFR }, 270 #endif 271 { NULL, 0 }, 272 }; 273 274 static if_printer 275 lookup_printer(int type) 276 { 277 struct printer *p; 278 279 for (p = printers; p->f; ++p) 280 if (type == p->type) 281 return p->f; 282 283 return NULL; 284 /* NOTREACHED */ 285 } 286 287 static pcap_t *pd; 288 289 extern int optind; 290 extern int opterr; 291 extern char *optarg; 292 293 struct print_info { 294 if_printer printer; 295 }; 296 297 struct dump_info { 298 char *WFileName; 299 pcap_t *pd; 300 pcap_dumper_t *p; 301 }; 302 303 static void 304 show_dlts_and_exit(pcap_t *pd) 305 { 306 int n_dlts; 307 int *dlts = 0; 308 const char *dlt_name; 309 310 n_dlts = pcap_list_datalinks(pd, &dlts); 311 if (n_dlts < 0) 312 error("%s", pcap_geterr(pd)); 313 else if (n_dlts == 0 || !dlts) 314 error("No data link types."); 315 316 (void) fprintf(stderr, "Data link types (use option -y to set):\n"); 317 318 while (--n_dlts >= 0) { 319 dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); 320 if (dlt_name != NULL) { 321 (void) fprintf(stderr, " %s (%s)", dlt_name, 322 pcap_datalink_val_to_description(dlts[n_dlts])); 323 324 /* 325 * OK, does tcpdump handle that type? 326 */ 327 if (lookup_printer(dlts[n_dlts]) == NULL) 328 (void) fprintf(stderr, " (not supported)"); 329 putchar('\n'); 330 } else { 331 (void) fprintf(stderr, " DLT %d (not supported)\n", 332 dlts[n_dlts]); 333 } 334 } 335 free(dlts); 336 exit(0); 337 } 338 339 /* 340 * Set up flags that might or might not be supported depending on the 341 * version of libpcap we're using. 342 */ 343 #ifdef WIN32 344 #define B_FLAG "B:" 345 #define B_FLAG_USAGE " [ -B size ]" 346 #else /* WIN32 */ 347 #define B_FLAG 348 #define B_FLAG_USAGE 349 #endif /* WIN32 */ 350 351 #ifdef HAVE_PCAP_FINDALLDEVS 352 #ifndef HAVE_PCAP_IF_T 353 #undef HAVE_PCAP_FINDALLDEVS 354 #endif 355 #endif 356 357 #ifdef HAVE_PCAP_FINDALLDEVS 358 #define D_FLAG "D" 359 #else 360 #define D_FLAG 361 #endif 362 363 #ifdef HAVE_PCAP_DUMP_FLUSH 364 #define U_FLAG "U" 365 #else 366 #define U_FLAG 367 #endif 368 369 #ifndef WIN32 370 // not supported on android 371 int initgroups(const char *user, gid_t group) {return 0;} 372 /* Drop root privileges and chroot if necessary */ 373 static void 374 droproot(const char *username, const char *chroot_dir) 375 { 376 struct passwd *pw = NULL; 377 378 if (chroot_dir && !username) { 379 fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); 380 exit(1); 381 } 382 383 pw = getpwnam(username); 384 if (pw) { 385 if (chroot_dir) { 386 if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { 387 fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", 388 chroot_dir, pcap_strerror(errno)); 389 exit(1); 390 } 391 } 392 if (initgroups(pw->pw_name, pw->pw_gid) != 0 || 393 setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { 394 fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", 395 username, 396 (unsigned long)pw->pw_uid, 397 (unsigned long)pw->pw_gid, 398 pcap_strerror(errno)); 399 exit(1); 400 } 401 } 402 else { 403 fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", 404 username); 405 exit(1); 406 } 407 } 408 #endif /* WIN32 */ 409 410 static int 411 getWflagChars(int x) 412 { 413 int c = 0; 414 415 x -= 1; 416 while (x > 0) { 417 c += 1; 418 x /= 10; 419 } 420 421 return c; 422 } 423 424 425 static void 426 MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) 427 { 428 if (cnt == 0 && max_chars == 0) 429 strcpy(buffer, orig_name); 430 else 431 sprintf(buffer, "%s%0*d", orig_name, max_chars, cnt); 432 } 433 434 static int tcpdump_printf(netdissect_options *ndo _U_, 435 const char *fmt, ...) 436 { 437 438 va_list args; 439 int ret; 440 441 va_start(args, fmt); 442 ret=vfprintf(stdout, fmt, args); 443 va_end(args); 444 445 return ret; 446 } 447 448 int 449 main(int argc, char **argv) 450 { 451 register int cnt, op, i; 452 bpf_u_int32 localnet, netmask; 453 register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName, *WFileNameAlt; 454 pcap_handler callback; 455 int type; 456 struct bpf_program fcode; 457 #ifndef WIN32 458 RETSIGTYPE (*oldhandler)(int); 459 #endif 460 struct print_info printinfo; 461 struct dump_info dumpinfo; 462 u_char *pcap_userdata; 463 char ebuf[PCAP_ERRBUF_SIZE]; 464 char *username = NULL; 465 char *chroot_dir = NULL; 466 #ifdef HAVE_PCAP_FINDALLDEVS 467 pcap_if_t *devpointer; 468 int devnum; 469 #endif 470 int status; 471 #ifdef WIN32 472 u_int UserBufferSize = 1000000; 473 if(wsockinit() != 0) return 1; 474 #endif /* WIN32 */ 475 476 gndo->ndo_Oflag=1; 477 gndo->ndo_Rflag=1; 478 gndo->ndo_dlt=-1; 479 gndo->ndo_default_print=ndo_default_print; 480 gndo->ndo_printf=tcpdump_printf; 481 gndo->ndo_error=ndo_error; 482 gndo->ndo_warning=ndo_warning; 483 gndo->ndo_snaplen = DEFAULT_SNAPLEN; 484 485 cnt = -1; 486 device = NULL; 487 infile = NULL; 488 RFileName = NULL; 489 WFileName = NULL; 490 if ((cp = strrchr(argv[0], '/')) != NULL) 491 program_name = cp + 1; 492 else 493 program_name = argv[0]; 494 495 if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) 496 error("%s", ebuf); 497 498 #ifdef LIBSMI 499 smiInit("tcpdump"); 500 #endif 501 502 opterr = 0; 503 while ( 504 (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1) 505 switch (op) { 506 507 case 'a': 508 /* compatibility for old -a */ 509 break; 510 511 case 'A': 512 ++Aflag; 513 break; 514 515 #ifdef WIN32 516 case 'B': 517 UserBufferSize = atoi(optarg)*1024; 518 if (UserBufferSize < 0) 519 error("invalid packet buffer size %s", optarg); 520 break; 521 #endif /* WIN32 */ 522 523 case 'c': 524 cnt = atoi(optarg); 525 if (cnt <= 0) 526 error("invalid packet count %s", optarg); 527 break; 528 529 case 'C': 530 Cflag = atoi(optarg) * 1000000; 531 if (Cflag < 0) 532 error("invalid file size %s", optarg); 533 break; 534 535 case 'd': 536 ++dflag; 537 break; 538 539 #ifdef HAVE_PCAP_FINDALLDEVS 540 case 'D': 541 if (pcap_findalldevs(&devpointer, ebuf) < 0) 542 error("%s", ebuf); 543 else { 544 for (i = 0; devpointer != 0; i++) { 545 printf("%d.%s", i+1, devpointer->name); 546 if (devpointer->description != NULL) 547 printf(" (%s)", devpointer->description); 548 printf("\n"); 549 devpointer = devpointer->next; 550 } 551 } 552 return 0; 553 #endif /* HAVE_PCAP_FINDALLDEVS */ 554 555 case 'L': 556 Lflag++; 557 break; 558 559 case 'e': 560 ++eflag; 561 break; 562 563 case 'E': 564 #ifndef HAVE_LIBCRYPTO 565 warning("crypto code not compiled in"); 566 #endif 567 gndo->ndo_espsecret = optarg; 568 break; 569 570 case 'f': 571 ++fflag; 572 break; 573 574 case 'F': 575 infile = optarg; 576 break; 577 578 case 'i': 579 if (optarg[0] == '0' && optarg[1] == 0) 580 error("Invalid adapter index"); 581 582 #ifdef HAVE_PCAP_FINDALLDEVS 583 /* 584 * If the argument is a number, treat it as 585 * an index into the list of adapters, as 586 * printed by "tcpdump -D". 587 * 588 * This should be OK on UNIX systems, as interfaces 589 * shouldn't have names that begin with digits. 590 * It can be useful on Windows, where more than 591 * one interface can have the same name. 592 */ 593 if ((devnum = atoi(optarg)) != 0) { 594 if (devnum < 0) 595 error("Invalid adapter index"); 596 597 if (pcap_findalldevs(&devpointer, ebuf) < 0) 598 error("%s", ebuf); 599 else { 600 for (i = 0; i < devnum-1; i++){ 601 devpointer = devpointer->next; 602 if (devpointer == NULL) 603 error("Invalid adapter index"); 604 } 605 } 606 device = devpointer->name; 607 break; 608 } 609 #endif /* HAVE_PCAP_FINDALLDEVS */ 610 device = optarg; 611 break; 612 613 case 'l': 614 #ifdef WIN32 615 /* 616 * _IOLBF is the same as _IOFBF in Microsoft's C 617 * libraries; the only alternative they offer 618 * is _IONBF. 619 * 620 * XXX - this should really be checking for MSVC++, 621 * not WIN32, if, for example, MinGW has its own 622 * C library that is more UNIX-compatible. 623 */ 624 setvbuf(stdout, NULL, _IONBF, 0); 625 #else /* WIN32 */ 626 #ifdef HAVE_SETLINEBUF 627 setlinebuf(stdout); 628 #else 629 setvbuf(stdout, NULL, _IOLBF, 0); 630 #endif 631 #endif /* WIN32 */ 632 break; 633 634 case 'n': 635 ++nflag; 636 break; 637 638 case 'N': 639 ++Nflag; 640 break; 641 642 case 'm': 643 #ifdef LIBSMI 644 if (smiLoadModule(optarg) == 0) { 645 error("could not load MIB module %s", optarg); 646 } 647 sflag = 1; 648 #else 649 (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 650 program_name, optarg); 651 (void)fprintf(stderr, "(no libsmi support)\n"); 652 #endif 653 break; 654 655 case 'M': 656 /* TCP-MD5 shared secret */ 657 #ifndef HAVE_LIBCRYPTO 658 warning("crypto code not compiled in"); 659 #endif 660 tcpmd5secret = optarg; 661 break; 662 663 case 'O': 664 Oflag = 0; 665 break; 666 667 case 'p': 668 ++pflag; 669 break; 670 671 case 'q': 672 ++qflag; 673 ++suppress_default_print; 674 break; 675 676 case 'r': 677 RFileName = optarg; 678 break; 679 680 case 'R': 681 Rflag = 0; 682 break; 683 684 case 's': { 685 char *end; 686 687 snaplen = strtol(optarg, &end, 0); 688 if (optarg == end || *end != '\0' 689 || snaplen < 0 || snaplen > 65535) 690 error("invalid snaplen %s", optarg); 691 else if (snaplen == 0) 692 snaplen = 65535; 693 break; 694 } 695 696 case 'S': 697 ++Sflag; 698 break; 699 700 case 't': 701 ++tflag; 702 break; 703 704 case 'T': 705 if (strcasecmp(optarg, "vat") == 0) 706 packettype = PT_VAT; 707 else if (strcasecmp(optarg, "wb") == 0) 708 packettype = PT_WB; 709 else if (strcasecmp(optarg, "rpc") == 0) 710 packettype = PT_RPC; 711 else if (strcasecmp(optarg, "rtp") == 0) 712 packettype = PT_RTP; 713 else if (strcasecmp(optarg, "rtcp") == 0) 714 packettype = PT_RTCP; 715 else if (strcasecmp(optarg, "snmp") == 0) 716 packettype = PT_SNMP; 717 else if (strcasecmp(optarg, "cnfp") == 0) 718 packettype = PT_CNFP; 719 else if (strcasecmp(optarg, "tftp") == 0) 720 packettype = PT_TFTP; 721 else if (strcasecmp(optarg, "aodv") == 0) 722 packettype = PT_AODV; 723 else 724 error("unknown packet type `%s'", optarg); 725 break; 726 727 case 'u': 728 ++uflag; 729 break; 730 731 #ifdef HAVE_PCAP_DUMP_FLUSH 732 case 'U': 733 ++Uflag; 734 break; 735 #endif 736 737 case 'v': 738 ++vflag; 739 break; 740 741 case 'w': 742 WFileName = optarg; 743 break; 744 745 case 'W': 746 Wflag = atoi(optarg); 747 if (Wflag < 0) 748 error("invalid number of output files %s", optarg); 749 WflagChars = getWflagChars(Wflag); 750 break; 751 752 case 'x': 753 ++xflag; 754 ++suppress_default_print; 755 break; 756 757 case 'X': 758 ++Xflag; 759 ++suppress_default_print; 760 break; 761 762 case 'y': 763 gndo->ndo_dltname = optarg; 764 gndo->ndo_dlt = 765 pcap_datalink_name_to_val(gndo->ndo_dltname); 766 if (gndo->ndo_dlt < 0) 767 error("invalid data link type %s", gndo->ndo_dltname); 768 break; 769 770 #if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) 771 case 'Y': 772 { 773 /* Undocumented flag */ 774 #ifdef HAVE_PCAP_DEBUG 775 extern int pcap_debug; 776 pcap_debug = 1; 777 #else 778 extern int yydebug; 779 yydebug = 1; 780 #endif 781 } 782 break; 783 #endif 784 case 'Z': 785 if (optarg) { 786 username = strdup(optarg); 787 } 788 else { 789 usage(); 790 /* NOTREACHED */ 791 } 792 break; 793 794 default: 795 usage(); 796 /* NOTREACHED */ 797 } 798 799 switch (tflag) { 800 801 case 0: /* Default */ 802 case 4: /* Default + Date*/ 803 thiszone = gmt2local(0); 804 break; 805 806 case 1: /* No time stamp */ 807 case 2: /* Unix timeval style */ 808 case 3: /* Microseconds since previous packet */ 809 break; 810 811 default: /* Not supported */ 812 error("only -t, -tt, -ttt, and -tttt are supported"); 813 break; 814 } 815 816 #ifdef WITH_CHROOT 817 /* if run as root, prepare for chrooting */ 818 if (getuid() == 0 || geteuid() == 0) { 819 /* future extensibility for cmd-line arguments */ 820 if (!chroot_dir) 821 chroot_dir = WITH_CHROOT; 822 } 823 #endif 824 825 #ifdef WITH_USER 826 /* if run as root, prepare for dropping root privileges */ 827 if (getuid() == 0 || geteuid() == 0) { 828 /* Run with '-Z root' to restore old behaviour */ 829 if (!username) 830 username = WITH_USER; 831 } 832 #endif 833 834 if (RFileName != NULL) { 835 int dlt; 836 const char *dlt_name; 837 838 #ifndef WIN32 839 /* 840 * We don't need network access, so relinquish any set-UID 841 * or set-GID privileges we have (if any). 842 * 843 * We do *not* want set-UID privileges when opening a 844 * trace file, as that might let the user read other 845 * people's trace files (especially if we're set-UID 846 * root). 847 */ 848 if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) 849 fprintf(stderr, "Warning: setgid/setuid failed !\n"); 850 #endif /* WIN32 */ 851 pd = pcap_open_offline(RFileName, ebuf); 852 if (pd == NULL) 853 error("%s", ebuf); 854 dlt = pcap_datalink(pd); 855 dlt_name = pcap_datalink_val_to_name(dlt); 856 if (dlt_name == NULL) { 857 fprintf(stderr, "reading from file %s, link-type %u\n", 858 RFileName, dlt); 859 } else { 860 fprintf(stderr, 861 "reading from file %s, link-type %s (%s)\n", 862 RFileName, dlt_name, 863 pcap_datalink_val_to_description(dlt)); 864 } 865 localnet = 0; 866 netmask = 0; 867 if (fflag != 0) 868 error("-f and -r options are incompatible"); 869 } else { 870 if (device == NULL) { 871 device = pcap_lookupdev(ebuf); 872 if (device == NULL) 873 error("%s", ebuf); 874 } 875 #ifdef WIN32 876 if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char 877 { //a Unicode string has a \0 as second byte (so strlen() is 1) 878 fprintf(stderr, "%s: listening on %ws\n", program_name, device); 879 } 880 else 881 { 882 fprintf(stderr, "%s: listening on %s\n", program_name, device); 883 } 884 885 fflush(stderr); 886 #endif /* WIN32 */ 887 *ebuf = '\0'; 888 pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 889 if (pd == NULL) 890 error("%s", ebuf); 891 else if (*ebuf) 892 warning("%s", ebuf); 893 /* 894 * Let user own process after socket has been opened. 895 */ 896 #ifndef WIN32 897 if (setgid(getgid()) != 0 || setuid(getuid()) != 0) 898 fprintf(stderr, "Warning: setgid/setuid failed !\n"); 899 #endif /* WIN32 */ 900 #ifdef WIN32 901 if(UserBufferSize != 1000000) 902 if(pcap_setbuff(pd, UserBufferSize)==-1){ 903 error("%s", pcap_geterr(pd)); 904 } 905 #endif /* WIN32 */ 906 if (Lflag) 907 show_dlts_and_exit(pd); 908 if (gndo->ndo_dlt >= 0) { 909 #ifdef HAVE_PCAP_SET_DATALINK 910 if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0) 911 error("%s", pcap_geterr(pd)); 912 #else 913 /* 914 * We don't actually support changing the 915 * data link type, so we only let them 916 * set it to what it already is. 917 */ 918 if (gndo->ndo_dlt != pcap_datalink(pd)) { 919 error("%s is not one of the DLTs supported by this device\n", 920 gndo->ndo_dltname); 921 } 922 #endif 923 (void)fprintf(stderr, "%s: data link type %s\n", 924 program_name, gndo->ndo_dltname); 925 (void)fflush(stderr); 926 } 927 i = pcap_snapshot(pd); 928 if (snaplen < i) { 929 warning("snaplen raised from %d to %d", snaplen, i); 930 snaplen = i; 931 } 932 if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 933 localnet = 0; 934 netmask = 0; 935 warning("%s", ebuf); 936 } 937 } 938 if (infile) 939 cmdbuf = read_infile(infile); 940 else 941 cmdbuf = copy_argv(&argv[optind]); 942 943 if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 944 error("%s", pcap_geterr(pd)); 945 if (dflag) { 946 bpf_dump(&fcode, dflag); 947 pcap_close(pd); 948 exit(0); 949 } 950 init_addrtoname(localnet, netmask); 951 952 #ifndef WIN32 953 (void)setsignal(SIGPIPE, cleanup); 954 #endif /* WIN32 */ 955 (void)setsignal(SIGTERM, cleanup); 956 (void)setsignal(SIGINT, cleanup); 957 /* Cooperate with nohup(1) */ 958 #ifndef WIN32 959 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 960 (void)setsignal(SIGHUP, oldhandler); 961 #endif /* WIN32 */ 962 963 if (pcap_setfilter(pd, &fcode) < 0) 964 error("%s", pcap_geterr(pd)); 965 if (WFileName) { 966 pcap_dumper_t *p; 967 968 WFileNameAlt = (char *)malloc(strlen(WFileName) + MAX_CFLAG_CHARS + 1); 969 if (WFileNameAlt == NULL) 970 error("malloc of WFileNameAlt"); 971 MakeFilename(WFileNameAlt, WFileName, 0, WflagChars); 972 p = pcap_dump_open(pd, WFileNameAlt); 973 if (p == NULL) 974 error("%s", pcap_geterr(pd)); 975 if (Cflag != 0) { 976 callback = dump_packet_and_trunc; 977 dumpinfo.WFileName = WFileName; 978 dumpinfo.pd = pd; 979 dumpinfo.p = p; 980 pcap_userdata = (u_char *)&dumpinfo; 981 } else { 982 callback = dump_packet; 983 pcap_userdata = (u_char *)p; 984 } 985 } else { 986 type = pcap_datalink(pd); 987 printinfo.printer = lookup_printer(type); 988 if (printinfo.printer == NULL) { 989 gndo->ndo_dltname = pcap_datalink_val_to_name(type); 990 if (gndo->ndo_dltname != NULL) 991 error("unsupported data link type %s", 992 gndo->ndo_dltname); 993 else 994 error("unsupported data link type %d", type); 995 } 996 callback = print_packet; 997 pcap_userdata = (u_char *)&printinfo; 998 } 999 #ifndef WIN32 1000 /* 1001 * We cannot do this earlier, because we want to be able to open 1002 * the file (if done) for writing before giving up permissions. 1003 */ 1004 if (getuid() == 0 || geteuid() == 0) { 1005 if (username || chroot_dir) 1006 droproot(username, chroot_dir); 1007 } 1008 #endif /* WIN32 */ 1009 #ifdef SIGINFO 1010 (void)setsignal(SIGINFO, requestinfo); 1011 #endif 1012 1013 if (vflag > 0 && WFileName) { 1014 /* 1015 * When capturing to a file, "-v" means tcpdump should, 1016 * every 10 secodns, "v"erbosely report the number of 1017 * packets captured. 1018 */ 1019 #ifdef USE_WIN32_MM_TIMER 1020 /* call verbose_stats_dump() each 1000 +/-100msec */ 1021 timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); 1022 setvbuf(stderr, NULL, _IONBF, 0); 1023 #elif defined(HAVE_ALARM) 1024 (void)setsignal(SIGALRM, verbose_stats_dump); 1025 alarm(1); 1026 #endif 1027 } 1028 1029 #ifndef WIN32 1030 if (RFileName == NULL) { 1031 int dlt; 1032 const char *dlt_name; 1033 1034 if (!vflag && !WFileName) { 1035 (void)fprintf(stderr, 1036 "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", 1037 program_name); 1038 } else 1039 (void)fprintf(stderr, "%s: ", program_name); 1040 dlt = pcap_datalink(pd); 1041 dlt_name = pcap_datalink_val_to_name(dlt); 1042 if (dlt_name == NULL) { 1043 (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", 1044 device, dlt, snaplen); 1045 } else { 1046 (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", 1047 device, dlt_name, 1048 pcap_datalink_val_to_description(dlt), snaplen); 1049 } 1050 (void)fflush(stderr); 1051 } 1052 #endif /* WIN32 */ 1053 status = pcap_loop(pd, cnt, callback, pcap_userdata); 1054 if (WFileName == NULL) { 1055 /* 1056 * We're printing packets. Flush the printed output, 1057 * so it doesn't get intermingled with error output. 1058 */ 1059 if (status == -2) { 1060 /* 1061 * We got interrupted, so perhaps we didn't 1062 * manage to finish a line we were printing. 1063 * Print an extra newline, just in case. 1064 */ 1065 putchar('\n'); 1066 } 1067 (void)fflush(stdout); 1068 } 1069 if (status == -1) { 1070 /* 1071 * Error. Report it. 1072 */ 1073 (void)fprintf(stderr, "%s: pcap_loop: %s\n", 1074 program_name, pcap_geterr(pd)); 1075 } 1076 if (RFileName == NULL) { 1077 /* 1078 * We're doing a live capture. Report the capture 1079 * statistics. 1080 */ 1081 info(1); 1082 } 1083 pcap_close(pd); 1084 exit(status == -1 ? 1 : 0); 1085 } 1086 1087 /* make a clean exit on interrupts */ 1088 static RETSIGTYPE 1089 cleanup(int signo _U_) 1090 { 1091 #ifdef USE_WIN32_MM_TIMER 1092 if (timer_id) 1093 timeKillEvent(timer_id); 1094 timer_id = 0; 1095 #elif defined(HAVE_ALARM) 1096 alarm(0); 1097 #endif 1098 1099 #ifdef HAVE_PCAP_BREAKLOOP 1100 /* 1101 * We have "pcap_breakloop()"; use it, so that we do as little 1102 * as possible in the signal handler (it's probably not safe 1103 * to do anything with standard I/O streams in a signal handler - 1104 * the ANSI C standard doesn't say it is). 1105 */ 1106 pcap_breakloop(pd); 1107 #else 1108 /* 1109 * We don't have "pcap_breakloop()"; this isn't safe, but 1110 * it's the best we can do. Print the summary if we're 1111 * not reading from a savefile - i.e., if we're doing a 1112 * live capture - and exit. 1113 */ 1114 if (pd != NULL && pcap_file(pd) == NULL) { 1115 /* 1116 * We got interrupted, so perhaps we didn't 1117 * manage to finish a line we were printing. 1118 * Print an extra newline, just in case. 1119 */ 1120 putchar('\n'); 1121 (void)fflush(stdout); 1122 info(1); 1123 } 1124 exit(0); 1125 #endif 1126 } 1127 1128 static void 1129 info(register int verbose) 1130 { 1131 struct pcap_stat stat; 1132 1133 if (pcap_stats(pd, &stat) < 0) { 1134 (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); 1135 return; 1136 } 1137 1138 if (!verbose) 1139 fprintf(stderr, "%s: ", program_name); 1140 1141 (void)fprintf(stderr, "%u packets captured", packets_captured); 1142 if (!verbose) 1143 fputs(", ", stderr); 1144 else 1145 putc('\n', stderr); 1146 (void)fprintf(stderr, "%d packets received by filter", stat.ps_recv); 1147 if (!verbose) 1148 fputs(", ", stderr); 1149 else 1150 putc('\n', stderr); 1151 (void)fprintf(stderr, "%d packets dropped by kernel\n", stat.ps_drop); 1152 infoprint = 0; 1153 } 1154 1155 static void 1156 dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 1157 { 1158 struct dump_info *dump_info; 1159 char *name; 1160 1161 ++packets_captured; 1162 1163 ++infodelay; 1164 1165 dump_info = (struct dump_info *)user; 1166 1167 /* 1168 * XXX - this won't prevent capture files from getting 1169 * larger than Cflag - the last packet written to the 1170 * file could put it over Cflag. 1171 */ 1172 if (pcap_dump_ftell(dump_info->p) > Cflag) { 1173 /* 1174 * Close the current file and open a new one. 1175 */ 1176 pcap_dump_close(dump_info->p); 1177 Cflag_count++; 1178 if (Wflag > 0) { 1179 if (Cflag_count >= Wflag) 1180 Cflag_count = 0; 1181 } else { 1182 if (Cflag_count >= MAX_CFLAG) 1183 error("too many output files"); 1184 } 1185 name = (char *)malloc(strlen(dump_info->WFileName) + MAX_CFLAG_CHARS + 1); 1186 if (name == NULL) 1187 error("dump_packet_and_trunc: malloc"); 1188 MakeFilename(name, dump_info->WFileName, Cflag_count, WflagChars); 1189 dump_info->p = pcap_dump_open(dump_info->pd, name); 1190 free(name); 1191 if (dump_info->p == NULL) 1192 error("%s", pcap_geterr(pd)); 1193 } 1194 1195 pcap_dump((u_char *)dump_info->p, h, sp); 1196 #ifdef HAVE_PCAP_DUMP_FLUSH 1197 if (Uflag) 1198 pcap_dump_flush(dump_info->p); 1199 #endif 1200 1201 --infodelay; 1202 if (infoprint) 1203 info(0); 1204 } 1205 1206 static void 1207 dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 1208 { 1209 ++packets_captured; 1210 1211 ++infodelay; 1212 1213 pcap_dump(user, h, sp); 1214 #ifdef HAVE_PCAP_DUMP_FLUSH 1215 if (Uflag) 1216 pcap_dump_flush((pcap_dumper_t *)user); 1217 #endif 1218 1219 --infodelay; 1220 if (infoprint) 1221 info(0); 1222 } 1223 1224 static void 1225 print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 1226 { 1227 struct print_info *print_info; 1228 u_int hdrlen; 1229 1230 ++packets_captured; 1231 1232 ++infodelay; 1233 ts_print(&h->ts); 1234 1235 print_info = (struct print_info *)user; 1236 1237 /* 1238 * Some printers want to check that they're not walking off the 1239 * end of the packet. 1240 * Rather than pass it all the way down, we set this global. 1241 */ 1242 snapend = sp + h->caplen; 1243 1244 hdrlen = (*print_info->printer)(h, sp); 1245 if (Xflag) { 1246 /* 1247 * Print the raw packet data in hex and ASCII. 1248 */ 1249 if (Xflag > 1) { 1250 /* 1251 * Include the link-layer header. 1252 */ 1253 hex_and_ascii_print("\n\t", sp, h->caplen); 1254 } else { 1255 /* 1256 * Don't include the link-layer header - and if 1257 * we have nothing past the link-layer header, 1258 * print nothing. 1259 */ 1260 if (h->caplen > hdrlen) 1261 hex_and_ascii_print("\n\t", sp + hdrlen, 1262 h->caplen - hdrlen); 1263 } 1264 } else if (xflag) { 1265 /* 1266 * Print the raw packet data in hex. 1267 */ 1268 if (xflag > 1) { 1269 /* 1270 * Include the link-layer header. 1271 */ 1272 hex_print("\n\t", sp, h->caplen); 1273 } else { 1274 /* 1275 * Don't include the link-layer header - and if 1276 * we have nothing past the link-layer header, 1277 * print nothing. 1278 */ 1279 if (h->caplen > hdrlen) 1280 hex_print("\n\t", sp + hdrlen, 1281 h->caplen - hdrlen); 1282 } 1283 } else if (Aflag) { 1284 /* 1285 * Print the raw packet data in ASCII. 1286 */ 1287 if (Aflag > 1) { 1288 /* 1289 * Include the link-layer header. 1290 */ 1291 ascii_print(sp, h->caplen); 1292 } else { 1293 /* 1294 * Don't include the link-layer header - and if 1295 * we have nothing past the link-layer header, 1296 * print nothing. 1297 */ 1298 if (h->caplen > hdrlen) 1299 ascii_print(sp + hdrlen, h->caplen - hdrlen); 1300 } 1301 } 1302 1303 putchar('\n'); 1304 1305 --infodelay; 1306 if (infoprint) 1307 info(0); 1308 } 1309 1310 #ifdef WIN32 1311 /* 1312 * XXX - there should really be libpcap calls to get the version 1313 * number as a string (the string would be generated from #defines 1314 * at run time, so that it's not generated from string constants 1315 * in the library, as, on many UNIX systems, those constants would 1316 * be statically linked into the application executable image, and 1317 * would thus reflect the version of libpcap on the system on 1318 * which the application was *linked*, not the system on which it's 1319 * *running*. 1320 * 1321 * That routine should be documented, unlike the "version[]" 1322 * string, so that UNIX vendors providing their own libpcaps 1323 * don't omit it (as a couple of vendors have...). 1324 * 1325 * Packet.dll should perhaps also export a routine to return the 1326 * version number of the Packet.dll code, to supply the 1327 * "Wpcap_version" information on Windows. 1328 */ 1329 char WDversion[]="current-cvs.tcpdump.org"; 1330 #if !defined(HAVE_GENERATED_VERSION) 1331 char version[]="current-cvs.tcpdump.org"; 1332 #endif 1333 char pcap_version[]="current-cvs.tcpdump.org"; 1334 char Wpcap_version[]="3.1"; 1335 #endif 1336 1337 /* 1338 * By default, print the specified data out in hex and ASCII. 1339 */ 1340 static void 1341 ndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length) 1342 { 1343 hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */ 1344 } 1345 1346 void 1347 default_print(const u_char *bp, u_int length) 1348 { 1349 ndo_default_print(gndo, bp, length); 1350 } 1351 1352 #ifdef SIGINFO 1353 RETSIGTYPE requestinfo(int signo _U_) 1354 { 1355 if (infodelay) 1356 ++infoprint; 1357 else 1358 info(0); 1359 } 1360 #endif 1361 1362 /* 1363 * Called once each second in verbose mode while dumping to file 1364 */ 1365 #ifdef USE_WIN32_MM_TIMER 1366 void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, 1367 DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) 1368 { 1369 struct pcap_stat stat; 1370 1371 if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1372 fprintf(stderr, "Got %u\r", packets_captured); 1373 } 1374 #elif defined(HAVE_ALARM) 1375 static void verbose_stats_dump(int sig _U_) 1376 { 1377 struct pcap_stat stat; 1378 1379 if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1380 fprintf(stderr, "Got %u\r", packets_captured); 1381 alarm(1); 1382 } 1383 #endif 1384 1385 static void 1386 usage(void) 1387 { 1388 extern char version[]; 1389 #ifndef HAVE_PCAP_LIB_VERSION 1390 #if defined(WIN32) || defined(HAVE_PCAP_VERSION) 1391 extern char pcap_version[]; 1392 #else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1393 static char pcap_version[] = "unknown"; 1394 #endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1395 #endif /* HAVE_PCAP_LIB_VERSION */ 1396 1397 #ifdef HAVE_PCAP_LIB_VERSION 1398 #ifdef WIN32 1399 (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1400 #else /* WIN32 */ 1401 (void)fprintf(stderr, "%s version %s\n", program_name, version); 1402 #endif /* WIN32 */ 1403 (void)fprintf(stderr, "%s\n",pcap_lib_version()); 1404 #else /* HAVE_PCAP_LIB_VERSION */ 1405 #ifdef WIN32 1406 (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1407 (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); 1408 #else /* WIN32 */ 1409 (void)fprintf(stderr, "%s version %s\n", program_name, version); 1410 (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 1411 #endif /* WIN32 */ 1412 #endif /* HAVE_PCAP_LIB_VERSION */ 1413 (void)fprintf(stderr, 1414 "Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name); 1415 (void)fprintf(stderr, 1416 "\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]\n"); 1417 (void)fprintf(stderr, 1418 "\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n"); 1419 (void)fprintf(stderr, 1420 "\t\t[ -W filecount ] [ -y datalinktype ] [ -Z user ]\n"); 1421 (void)fprintf(stderr, 1422 "\t\t[ expression ]\n"); 1423 exit(1); 1424 } 1425 1426 1427 1428 /* VARARGS */ 1429 static void 1430 ndo_error(netdissect_options *ndo _U_, const char *fmt, ...) 1431 { 1432 va_list ap; 1433 1434 (void)fprintf(stderr, "%s: ", program_name); 1435 va_start(ap, fmt); 1436 (void)vfprintf(stderr, fmt, ap); 1437 va_end(ap); 1438 if (*fmt) { 1439 fmt += strlen(fmt); 1440 if (fmt[-1] != '\n') 1441 (void)fputc('\n', stderr); 1442 } 1443 exit(1); 1444 /* NOTREACHED */ 1445 } 1446 1447 /* VARARGS */ 1448 static void 1449 ndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) 1450 { 1451 va_list ap; 1452 1453 (void)fprintf(stderr, "%s: WARNING: ", program_name); 1454 va_start(ap, fmt); 1455 (void)vfprintf(stderr, fmt, ap); 1456 va_end(ap); 1457 if (*fmt) { 1458 fmt += strlen(fmt); 1459 if (fmt[-1] != '\n') 1460 (void)fputc('\n', stderr); 1461 } 1462 } 1463