tcpdump.c revision 146778
117680Spst/* 298527Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2098527Sfenner * 2198527Sfenner * Support for splitting captures into multiple files with a maximum 2298527Sfenner * file size: 2398527Sfenner * 2498527Sfenner * Copyright (c) 2001 2598527Sfenner * Seth Webster <swebster@sst.ll.mit.edu> 2617680Spst */ 2717680Spst 2817680Spst#ifndef lint 29127675Sbmsstatic const char copyright[] _U_ = 3098527Sfenner "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ 3117680SpstThe Regents of the University of California. All rights reserved.\n"; 32127675Sbmsstatic const char rcsid[] _U_ = 33146778Ssam "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.253 2005/01/27 18:30:36 hannes Exp $ (LBL)"; 3417680Spst#endif 3517680Spst 3656648Sarchie/* $FreeBSD: head/contrib/tcpdump/tcpdump.c 146778 2005-05-29 19:09:28Z sam $ */ 3756648Sarchie 3817680Spst/* 3917680Spst * tcpdump - monitor tcp/ip traffic on an ethernet. 4017680Spst * 4117680Spst * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. 4217680Spst * Mercilessly hacked and occasionally improved since then via the 4317680Spst * combined efforts of Van, Steve McCanne and Craig Leres of LBL. 4417680Spst */ 4517680Spst 4656896Sfenner#ifdef HAVE_CONFIG_H 4756896Sfenner#include "config.h" 4856896Sfenner#endif 4956896Sfenner 50127675Sbms#include <tcpdump-stdinc.h> 5117680Spst 52127675Sbms#ifdef WIN32 53127675Sbms#include "getopt.h" 54127675Sbms#include "w32_fzs.h" 55127675Sbmsextern int strcasecmp (const char *__s1, const char *__s2); 56127675Sbmsextern int SIZE_BUF; 57127675Sbms#define off_t long 58127675Sbms#define uint UINT 59127675Sbms#endif /* WIN32 */ 6017680Spst 61146778Ssam#ifdef HAVE_SMI_H 62146778Ssam#include <smi.h> 63146778Ssam#endif 64146778Ssam 6517680Spst#include <pcap.h> 6617680Spst#include <signal.h> 6717680Spst#include <stdio.h> 6817680Spst#include <stdlib.h> 6917680Spst#include <string.h> 70146778Ssam#ifndef WIN32 71146778Ssam#include <pwd.h> 72146778Ssam#include <grp.h> 73146778Ssam#include <errno.h> 74146778Ssam#endif /* WIN32 */ 7517680Spst 76146778Ssam#include "netdissect.h" 7717680Spst#include "interface.h" 7817680Spst#include "addrtoname.h" 7917680Spst#include "machdep.h" 8039297Sfenner#include "setsignal.h" 8139297Sfenner#include "gmt2local.h" 82127675Sbms#include "pcap-missing.h" 8317680Spst 84146778Ssamnetdissect_options Gndo; 85146778Ssamnetdissect_options *gndo = &Gndo; 86146778Ssam 87146778Ssam/* 88146778Ssam * Define the maximum number of files for the -C flag, and how many 89146778Ssam * characters can be added to a filename for the -C flag (which 90146778Ssam * should be enough to handle MAX_CFLAG - 1). 91146778Ssam */ 92146778Ssam#define MAX_CFLAG 1000000 93146778Ssam#define MAX_CFLAG_CHARS 6 94146778Ssam 9539297Sfennerint dflag; /* print filter code */ 96109842Sfennerint Lflag; /* list available data link types and exit */ 9739297Sfenner 98127675Sbmsstatic int infodelay; 99127675Sbmsstatic int infoprint; 10017680Spst 10117680Spstchar *program_name; 10217680Spst 10317680Spstint32_t thiszone; /* seconds offset from gmt to local time */ 10417680Spst 10517680Spst/* Forwards */ 10675118Sfennerstatic RETSIGTYPE cleanup(int); 10775118Sfennerstatic void usage(void) __attribute__((noreturn)); 108109842Sfennerstatic void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn)); 10917680Spst 110127675Sbmsstatic void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 111146778Ssamstatic void ndo_default_print(netdissect_options *, const u_char *, u_int); 112127675Sbmsstatic void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); 113127675Sbmsstatic void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 114146778Ssamstatic void droproot(const char *, const char *); 115146778Ssamstatic void ndo_error(netdissect_options *ndo, const char *fmt, ...); 116146778Ssamstatic void ndo_warning(netdissect_options *ndo, const char *fmt, ...); 11798527Sfenner 11898527Sfenner#ifdef SIGINFO 11998527SfennerRETSIGTYPE requestinfo(int); 12098527Sfenner#endif 12198527Sfenner 122146778Ssam#if defined(USE_WIN32_MM_TIMER) 123146778Ssam #include <MMsystem.h> 124146778Ssam static UINT timer_id; 125146778Ssam static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); 126146778Ssam#elif defined(HAVE_ALARM) 127146778Ssam static void verbose_stats_dump(int sig); 128146778Ssam#endif 129146778Ssam 130127675Sbmsstatic void info(int); 131127675Sbmsstatic u_int packets_captured; 132127675Sbms 133127675Sbmstypedef u_int (*if_printer)(const struct pcap_pkthdr *, const u_char *); 134127675Sbms 13517680Spststruct printer { 136127675Sbms if_printer f; 13717680Spst int type; 13817680Spst}; 13917680Spst 14017680Spststatic struct printer printers[] = { 14198527Sfenner { arcnet_if_print, DLT_ARCNET }, 142127675Sbms#ifdef DLT_ARCNET_LINUX 143127675Sbms { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 144127675Sbms#endif 14517680Spst { ether_if_print, DLT_EN10MB }, 14644165Sjulian { token_if_print, DLT_IEEE802 }, 14756896Sfenner#ifdef DLT_LANE8023 14856896Sfenner { lane_if_print, DLT_LANE8023 }, 14956896Sfenner#endif 15056896Sfenner#ifdef DLT_CIP 15156896Sfenner { cip_if_print, DLT_CIP }, 15256896Sfenner#endif 15375118Sfenner#ifdef DLT_ATM_CLIP 15475118Sfenner { cip_if_print, DLT_ATM_CLIP }, 15575118Sfenner#endif 15617680Spst { sl_if_print, DLT_SLIP }, 157127675Sbms#ifdef DLT_SLIP_BSDOS 15839297Sfenner { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 159127675Sbms#endif 16017680Spst { ppp_if_print, DLT_PPP }, 161146778Ssam#ifdef DLT_PPP_WITHDIRECTION 162146778Ssam { ppp_if_print, DLT_PPP_WITHDIRECTION }, 163146778Ssam#endif 164127675Sbms#ifdef DLT_PPP_BSDOS 16539297Sfenner { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 166127675Sbms#endif 16717680Spst { fddi_if_print, DLT_FDDI }, 16817680Spst { null_if_print, DLT_NULL }, 16975118Sfenner#ifdef DLT_LOOP 17075118Sfenner { null_if_print, DLT_LOOP }, 17175118Sfenner#endif 17239297Sfenner { raw_if_print, DLT_RAW }, 17317680Spst { atm_if_print, DLT_ATM_RFC1483 }, 17475118Sfenner#ifdef DLT_C_HDLC 17575118Sfenner { chdlc_if_print, DLT_C_HDLC }, 17656896Sfenner#endif 17798527Sfenner#ifdef DLT_HDLC 17898527Sfenner { chdlc_if_print, DLT_HDLC }, 17998527Sfenner#endif 18075118Sfenner#ifdef DLT_PPP_SERIAL 18175118Sfenner { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 18275118Sfenner#endif 18398527Sfenner#ifdef DLT_PPP_ETHER 18498527Sfenner { pppoe_if_print, DLT_PPP_ETHER }, 18598527Sfenner#endif 18675118Sfenner#ifdef DLT_LINUX_SLL 18775118Sfenner { sll_if_print, DLT_LINUX_SLL }, 18875118Sfenner#endif 18998527Sfenner#ifdef DLT_IEEE802_11 19098527Sfenner { ieee802_11_if_print, DLT_IEEE802_11}, 19198527Sfenner#endif 19298527Sfenner#ifdef DLT_LTALK 19398527Sfenner { ltalk_if_print, DLT_LTALK }, 19498527Sfenner#endif 195127675Sbms#ifdef DLT_PFLOG 196127675Sbms { pflog_if_print, DLT_PFLOG }, 197127675Sbms#endif 198127675Sbms#ifdef DLT_FR 199127675Sbms { fr_if_print, DLT_FR }, 200127675Sbms#endif 201127675Sbms#ifdef DLT_FRELAY 202127675Sbms { fr_if_print, DLT_FRELAY }, 203127675Sbms#endif 204127675Sbms#ifdef DLT_SUNATM 205127675Sbms { sunatm_if_print, DLT_SUNATM }, 206127675Sbms#endif 207127675Sbms#ifdef DLT_IP_OVER_FC 208127675Sbms { ipfc_if_print, DLT_IP_OVER_FC }, 209127675Sbms#endif 210127675Sbms#ifdef DLT_PRISM_HEADER 211127675Sbms { prism_if_print, DLT_PRISM_HEADER }, 212127675Sbms#endif 213127675Sbms#ifdef DLT_IEEE802_11_RADIO 214127675Sbms { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 215127675Sbms#endif 216127675Sbms#ifdef DLT_ENC 217127675Sbms { enc_if_print, DLT_ENC }, 218127675Sbms#endif 219146778Ssam#ifdef DLT_SYMANTEC_FIREWALL 220146778Ssam { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 221146778Ssam#endif 222127675Sbms#ifdef DLT_APPLE_IP_OVER_IEEE1394 223127675Sbms { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 224127675Sbms#endif 225146778Ssam#ifdef DLT_JUNIPER_ATM1 226146778Ssam { juniper_atm1_print, DLT_JUNIPER_ATM1 }, 227146778Ssam#endif 228146778Ssam#ifdef DLT_JUNIPER_ATM2 229146778Ssam { juniper_atm2_print, DLT_JUNIPER_ATM2 }, 230146778Ssam#endif 231146778Ssam#ifdef DLT_JUNIPER_MLFR 232146778Ssam { juniper_mlfr_print, DLT_JUNIPER_MLFR }, 233146778Ssam#endif 234146778Ssam#ifdef DLT_JUNIPER_MLPPP 235146778Ssam { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, 236146778Ssam#endif 23717680Spst { NULL, 0 }, 23817680Spst}; 23917680Spst 240127675Sbmsstatic if_printer 24117680Spstlookup_printer(int type) 24217680Spst{ 24317680Spst struct printer *p; 24417680Spst 24517680Spst for (p = printers; p->f; ++p) 24617680Spst if (type == p->type) 24717680Spst return p->f; 24817680Spst 249127675Sbms return NULL; 25017680Spst /* NOTREACHED */ 25117680Spst} 25217680Spst 25317680Spststatic pcap_t *pd; 25417680Spst 25517680Spstextern int optind; 25617680Spstextern int opterr; 25717680Spstextern char *optarg; 25817680Spst 259127675Sbmsstruct print_info { 260127675Sbms if_printer printer; 261127675Sbms}; 262127675Sbms 26398527Sfennerstruct dump_info { 26498527Sfenner char *WFileName; 26598527Sfenner pcap_t *pd; 26698527Sfenner pcap_dumper_t *p; 26798527Sfenner}; 26898527Sfenner 269109842Sfennerstatic void 270109842Sfennershow_dlts_and_exit(pcap_t *pd) 271109842Sfenner{ 272127675Sbms int n_dlts; 273109842Sfenner int *dlts = 0; 274127675Sbms const char *dlt_name; 275127675Sbms 276109842Sfenner n_dlts = pcap_list_datalinks(pd, &dlts); 277109842Sfenner if (n_dlts < 0) 278109842Sfenner error("%s", pcap_geterr(pd)); 279109842Sfenner else if (n_dlts == 0 || !dlts) 280109842Sfenner error("No data link types."); 281109842Sfenner 282127675Sbms (void) fprintf(stderr, "Data link types (use option -y to set):\n"); 283109842Sfenner 284109842Sfenner while (--n_dlts >= 0) { 285127675Sbms dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); 286127675Sbms if (dlt_name != NULL) { 287127675Sbms (void) fprintf(stderr, " %s (%s)", dlt_name, 288127675Sbms pcap_datalink_val_to_description(dlts[n_dlts])); 289127675Sbms 290127675Sbms /* 291127675Sbms * OK, does tcpdump handle that type? 292127675Sbms */ 293127675Sbms if (lookup_printer(dlts[n_dlts]) == NULL) 294127675Sbms (void) fprintf(stderr, " (not supported)"); 295127675Sbms putchar('\n'); 296127675Sbms } else { 297127675Sbms (void) fprintf(stderr, " DLT %d (not supported)\n", 298127675Sbms dlts[n_dlts]); 299109842Sfenner } 300109842Sfenner } 301109842Sfenner free(dlts); 302109842Sfenner exit(0); 303109842Sfenner} 304109842Sfenner 305127675Sbms/* 306127675Sbms * Set up flags that might or might not be supported depending on the 307127675Sbms * version of libpcap we're using. 308127675Sbms */ 309127675Sbms#ifdef WIN32 310127675Sbms#define B_FLAG "B:" 311127675Sbms#define B_FLAG_USAGE " [ -B size ]" 312127675Sbms#else /* WIN32 */ 313127675Sbms#define B_FLAG 314127675Sbms#define B_FLAG_USAGE 315127675Sbms#endif /* WIN32 */ 316127675Sbms 317127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 318146778Ssam#ifndef HAVE_PCAP_IF_T 319146778Ssam#undef HAVE_PCAP_FINDALLDEVS 320146778Ssam#endif 321146778Ssam#endif 322146778Ssam 323146778Ssam#ifdef HAVE_PCAP_FINDALLDEVS 324127675Sbms#define D_FLAG "D" 325127675Sbms#else 326127675Sbms#define D_FLAG 327127675Sbms#endif 328127675Sbms 329127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 330127675Sbms#define U_FLAG "U" 331127675Sbms#else 332127675Sbms#define U_FLAG 333127675Sbms#endif 334127675Sbms 335146778Ssam#ifndef WIN32 336146778Ssam/* Drop root privileges and chroot if necessary */ 337146778Ssamstatic void 338146778Ssamdroproot(const char *username, const char *chroot_dir) 339146778Ssam{ 340146778Ssam struct passwd *pw = NULL; 341146778Ssam 342146778Ssam if (chroot_dir && !username) { 343146778Ssam fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); 344146778Ssam exit(1); 345146778Ssam } 346146778Ssam 347146778Ssam pw = getpwnam(username); 348146778Ssam if (pw) { 349146778Ssam if (chroot_dir) { 350146778Ssam if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { 351146778Ssam fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", 352146778Ssam chroot_dir, pcap_strerror(errno)); 353146778Ssam exit(1); 354146778Ssam } 355146778Ssam } 356146778Ssam if (initgroups(pw->pw_name, pw->pw_gid) != 0 || 357146778Ssam setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { 358146778Ssam fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", 359146778Ssam username, 360146778Ssam (unsigned long)pw->pw_uid, 361146778Ssam (unsigned long)pw->pw_gid, 362146778Ssam pcap_strerror(errno)); 363146778Ssam exit(1); 364146778Ssam } 365146778Ssam } 366146778Ssam else { 367146778Ssam fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", 368146778Ssam username); 369146778Ssam exit(1); 370146778Ssam } 371146778Ssam} 372146778Ssam#endif /* WIN32 */ 373146778Ssam 374146778Ssamstatic int 375146778SsamgetWflagChars(int x) 376146778Ssam{ 377146778Ssam int c = 0; 378146778Ssam 379146778Ssam x -= 1; 380146778Ssam while (x > 0) { 381146778Ssam c += 1; 382146778Ssam x /= 10; 383146778Ssam } 384146778Ssam 385146778Ssam return c; 386146778Ssam} 387146778Ssam 388146778Ssam 389146778Ssamstatic void 390146778SsamMakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) 391146778Ssam{ 392146778Ssam if (cnt == 0 && max_chars == 0) 393146778Ssam strcpy(buffer, orig_name); 394146778Ssam else 395146778Ssam sprintf(buffer, "%s%0*d", orig_name, max_chars, cnt); 396146778Ssam} 397146778Ssam 398146778Ssamstatic int tcpdump_printf(netdissect_options *ndo _U_, 399146778Ssam const char *fmt, ...) 400146778Ssam{ 401146778Ssam 402146778Ssam va_list args; 403146778Ssam int ret; 404146778Ssam 405146778Ssam va_start(args, fmt); 406146778Ssam ret=vfprintf(stdout, fmt, args); 407146778Ssam va_end(args); 408146778Ssam 409146778Ssam return ret; 410146778Ssam} 411146778Ssam 41217680Spstint 41317680Spstmain(int argc, char **argv) 41417680Spst{ 41517680Spst register int cnt, op, i; 41617680Spst bpf_u_int32 localnet, netmask; 417146778Ssam register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName, *WFileNameAlt; 418127675Sbms pcap_handler callback; 419127675Sbms int type; 42017680Spst struct bpf_program fcode; 421127675Sbms#ifndef WIN32 42239297Sfenner RETSIGTYPE (*oldhandler)(int); 423127675Sbms#endif 424127675Sbms struct print_info printinfo; 42598527Sfenner struct dump_info dumpinfo; 42617680Spst u_char *pcap_userdata; 42717680Spst char ebuf[PCAP_ERRBUF_SIZE]; 428146778Ssam char *username = NULL; 429146778Ssam char *chroot_dir = NULL; 430127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 431127675Sbms pcap_if_t *devpointer; 432127675Sbms int devnum; 433127675Sbms#endif 434127675Sbms int status; 435127675Sbms#ifdef WIN32 436127675Sbms u_int UserBufferSize = 1000000; 437127675Sbms if(wsockinit() != 0) return 1; 438127675Sbms#endif /* WIN32 */ 43917680Spst 440146778Ssam gndo->ndo_Oflag=1; 441146778Ssam gndo->ndo_Rflag=1; 442146778Ssam gndo->ndo_dlt=-1; 443146778Ssam gndo->ndo_default_print=ndo_default_print; 444146778Ssam gndo->ndo_printf=tcpdump_printf; 445146778Ssam gndo->ndo_error=ndo_error; 446146778Ssam gndo->ndo_warning=ndo_warning; 447146778Ssam gndo->ndo_snaplen = DEFAULT_SNAPLEN; 448146778Ssam 44917680Spst cnt = -1; 45017680Spst device = NULL; 45117680Spst infile = NULL; 45217680Spst RFileName = NULL; 45317680Spst WFileName = NULL; 45417680Spst if ((cp = strrchr(argv[0], '/')) != NULL) 45517680Spst program_name = cp + 1; 45617680Spst else 45717680Spst program_name = argv[0]; 45817680Spst 45975118Sfenner if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) 46026180Sfenner error("%s", ebuf); 46117680Spst 46256896Sfenner#ifdef LIBSMI 46356896Sfenner smiInit("tcpdump"); 46456896Sfenner#endif 465127675Sbms 46617680Spst opterr = 0; 46739297Sfenner while ( 468146778Ssam (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) 46917680Spst switch (op) { 47039297Sfenner 47139297Sfenner case 'a': 472127675Sbms /* compatibility for old -a */ 47339297Sfenner break; 47439297Sfenner 475127675Sbms case 'A': 476127675Sbms ++xflag; 477127675Sbms ++Xflag; 478127675Sbms ++Aflag; 479127675Sbms break; 480127675Sbms 481127675Sbms#ifdef WIN32 482127675Sbms case 'B': 483127675Sbms UserBufferSize = atoi(optarg)*1024; 484127675Sbms if (UserBufferSize < 0) 485127675Sbms error("invalid packet buffer size %s", optarg); 486127675Sbms break; 487127675Sbms#endif /* WIN32 */ 488127675Sbms 48917680Spst case 'c': 49017680Spst cnt = atoi(optarg); 49117680Spst if (cnt <= 0) 49217680Spst error("invalid packet count %s", optarg); 49317680Spst break; 49417680Spst 49598527Sfenner case 'C': 49698527Sfenner Cflag = atoi(optarg) * 1000000; 497127675Sbms if (Cflag < 0) 49898527Sfenner error("invalid file size %s", optarg); 49998527Sfenner break; 50098527Sfenner 50117680Spst case 'd': 50217680Spst ++dflag; 50317680Spst break; 50417680Spst 505127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 506127675Sbms case 'D': 507127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 508127675Sbms error("%s", ebuf); 509127675Sbms else { 510127675Sbms for (i = 0; devpointer != 0; i++) { 511127675Sbms printf("%d.%s", i+1, devpointer->name); 512127675Sbms if (devpointer->description != NULL) 513127675Sbms printf(" (%s)", devpointer->description); 514127675Sbms printf("\n"); 515127675Sbms devpointer = devpointer->next; 516127675Sbms } 517127675Sbms } 518127675Sbms return 0; 519127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 520127675Sbms 521109842Sfenner case 'L': 522109842Sfenner Lflag++; 523109842Sfenner break; 524109842Sfenner 52517680Spst case 'e': 52617680Spst ++eflag; 52717680Spst break; 52817680Spst 52956896Sfenner case 'E': 53075118Sfenner#ifndef HAVE_LIBCRYPTO 53156896Sfenner warning("crypto code not compiled in"); 53256896Sfenner#endif 533146778Ssam gndo->ndo_espsecret = optarg; 53456896Sfenner break; 53556896Sfenner 53617680Spst case 'f': 53717680Spst ++fflag; 53817680Spst break; 53917680Spst 54017680Spst case 'F': 54117680Spst infile = optarg; 54217680Spst break; 54317680Spst 54417680Spst case 'i': 545127675Sbms if (optarg[0] == '0' && optarg[1] == 0) 546127675Sbms error("Invalid adapter index"); 547127675Sbms 548127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 549127675Sbms /* 550127675Sbms * If the argument is a number, treat it as 551127675Sbms * an index into the list of adapters, as 552127675Sbms * printed by "tcpdump -D". 553127675Sbms * 554127675Sbms * This should be OK on UNIX systems, as interfaces 555127675Sbms * shouldn't have names that begin with digits. 556127675Sbms * It can be useful on Windows, where more than 557127675Sbms * one interface can have the same name. 558127675Sbms */ 559127675Sbms if ((devnum = atoi(optarg)) != 0) { 560127675Sbms if (devnum < 0) 561127675Sbms error("Invalid adapter index"); 562127675Sbms 563127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 564127675Sbms error("%s", ebuf); 565127675Sbms else { 566127675Sbms for (i = 0; i < devnum-1; i++){ 567127675Sbms devpointer = devpointer->next; 568127675Sbms if (devpointer == NULL) 569127675Sbms error("Invalid adapter index"); 570127675Sbms } 571127675Sbms } 572127675Sbms device = devpointer->name; 573127675Sbms break; 574127675Sbms } 575127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 57617680Spst device = optarg; 57717680Spst break; 57817680Spst 57917680Spst case 'l': 580127675Sbms#ifdef WIN32 581127675Sbms /* 582127675Sbms * _IOLBF is the same as _IOFBF in Microsoft's C 583127675Sbms * libraries; the only alternative they offer 584127675Sbms * is _IONBF. 585127675Sbms * 586127675Sbms * XXX - this should really be checking for MSVC++, 587127675Sbms * not WIN32, if, for example, MinGW has its own 588127675Sbms * C library that is more UNIX-compatible. 589127675Sbms */ 590127675Sbms setvbuf(stdout, NULL, _IONBF, 0); 591127675Sbms#else /* WIN32 */ 59217680Spst#ifdef HAVE_SETLINEBUF 59317680Spst setlinebuf(stdout); 59417680Spst#else 59517680Spst setvbuf(stdout, NULL, _IOLBF, 0); 59617680Spst#endif 597127675Sbms#endif /* WIN32 */ 59817680Spst break; 59917680Spst 60017680Spst case 'n': 60117680Spst ++nflag; 60217680Spst break; 60317680Spst 60417680Spst case 'N': 60517680Spst ++Nflag; 60617680Spst break; 60717680Spst 60856896Sfenner case 'm': 60956896Sfenner#ifdef LIBSMI 61056896Sfenner if (smiLoadModule(optarg) == 0) { 61156896Sfenner error("could not load MIB module %s", optarg); 61256896Sfenner } 61356896Sfenner sflag = 1; 61456896Sfenner#else 61556896Sfenner (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 61656896Sfenner program_name, optarg); 61756896Sfenner (void)fprintf(stderr, "(no libsmi support)\n"); 61856896Sfenner#endif 619127675Sbms break; 620127675Sbms 621146778Ssam case 'M': 622146778Ssam /* TCP-MD5 shared secret */ 623146778Ssam#ifndef HAVE_LIBCRYPTO 624146778Ssam warning("crypto code not compiled in"); 625146778Ssam#endif 626146778Ssam tcpmd5secret = optarg; 627146778Ssam break; 628146778Ssam 62917680Spst case 'O': 63017680Spst Oflag = 0; 63117680Spst break; 63217680Spst 63317680Spst case 'p': 63417680Spst ++pflag; 63517680Spst break; 63617680Spst 63717680Spst case 'q': 63817680Spst ++qflag; 63917680Spst break; 64017680Spst 64117680Spst case 'r': 64217680Spst RFileName = optarg; 64317680Spst break; 64417680Spst 64556896Sfenner case 'R': 64656896Sfenner Rflag = 0; 64756896Sfenner break; 64856896Sfenner 64975118Sfenner case 's': { 65075118Sfenner char *end; 65175118Sfenner 65275118Sfenner snaplen = strtol(optarg, &end, 0); 65375118Sfenner if (optarg == end || *end != '\0' 65475118Sfenner || snaplen < 0 || snaplen > 65535) 65517680Spst error("invalid snaplen %s", optarg); 65675118Sfenner else if (snaplen == 0) 65775118Sfenner snaplen = 65535; 65817680Spst break; 65975118Sfenner } 66017680Spst 66117680Spst case 'S': 66217680Spst ++Sflag; 66317680Spst break; 66417680Spst 66517680Spst case 't': 666146778Ssam ++tflag; 66717680Spst break; 66817680Spst 66917680Spst case 'T': 67017680Spst if (strcasecmp(optarg, "vat") == 0) 67117680Spst packettype = PT_VAT; 67217680Spst else if (strcasecmp(optarg, "wb") == 0) 67317680Spst packettype = PT_WB; 67417680Spst else if (strcasecmp(optarg, "rpc") == 0) 67517680Spst packettype = PT_RPC; 67617680Spst else if (strcasecmp(optarg, "rtp") == 0) 67717680Spst packettype = PT_RTP; 67817680Spst else if (strcasecmp(optarg, "rtcp") == 0) 67917680Spst packettype = PT_RTCP; 68056896Sfenner else if (strcasecmp(optarg, "snmp") == 0) 68156896Sfenner packettype = PT_SNMP; 68275118Sfenner else if (strcasecmp(optarg, "cnfp") == 0) 68375118Sfenner packettype = PT_CNFP; 684127675Sbms else if (strcasecmp(optarg, "tftp") == 0) 685127675Sbms packettype = PT_TFTP; 686127675Sbms else if (strcasecmp(optarg, "aodv") == 0) 687127675Sbms packettype = PT_AODV; 68817680Spst else 68917680Spst error("unknown packet type `%s'", optarg); 69017680Spst break; 69117680Spst 69275118Sfenner case 'u': 69375118Sfenner ++uflag; 69475118Sfenner break; 695127675Sbms 696127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 697127675Sbms case 'U': 698127675Sbms ++Uflag; 699127675Sbms break; 700127675Sbms#endif 701127675Sbms 70217680Spst case 'v': 70317680Spst ++vflag; 70417680Spst break; 70517680Spst 70617680Spst case 'w': 70717680Spst WFileName = optarg; 70817680Spst break; 70956896Sfenner 710146778Ssam case 'W': 711146778Ssam Wflag = atoi(optarg); 712146778Ssam if (Wflag < 0) 713146778Ssam error("invalid number of output files %s", optarg); 714146778Ssam WflagChars = getWflagChars(Wflag); 715146778Ssam break; 716146778Ssam 71756896Sfenner case 'x': 71856896Sfenner ++xflag; 71956896Sfenner break; 72056896Sfenner 72156896Sfenner case 'X': 72256896Sfenner ++Xflag; 72356896Sfenner break; 72456896Sfenner 725109842Sfenner case 'y': 726146778Ssam gndo->ndo_dltname = optarg; 727146778Ssam gndo->ndo_dlt = 728146778Ssam pcap_datalink_name_to_val(gndo->ndo_dltname); 729146778Ssam if (gndo->ndo_dlt < 0) 730146778Ssam error("invalid data link type %s", gndo->ndo_dltname); 731109842Sfenner break; 732109842Sfenner 733127675Sbms#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) 73417680Spst case 'Y': 73517680Spst { 73617680Spst /* Undocumented flag */ 737127675Sbms#ifdef HAVE_PCAP_DEBUG 738127675Sbms extern int pcap_debug; 739127675Sbms pcap_debug = 1; 740127675Sbms#else 74117680Spst extern int yydebug; 74217680Spst yydebug = 1; 743127675Sbms#endif 74417680Spst } 74517680Spst break; 74617680Spst#endif 747146778Ssam case 'Z': 748146778Ssam if (optarg) { 749146778Ssam username = strdup(optarg); 750146778Ssam } 751146778Ssam else { 752146778Ssam usage(); 753146778Ssam /* NOTREACHED */ 754146778Ssam } 755146778Ssam break; 756146778Ssam 75717680Spst default: 75817680Spst usage(); 75917680Spst /* NOTREACHED */ 76017680Spst } 76117680Spst 762146778Ssam switch (tflag) { 763146778Ssam 764146778Ssam case 0: /* Default */ 765146778Ssam case 4: /* Default + Date*/ 76639297Sfenner thiszone = gmt2local(0); 767146778Ssam break; 76817680Spst 769146778Ssam case 1: /* No time stamp */ 770146778Ssam case 2: /* Unix timeval style */ 771146778Ssam case 3: /* Microseconds since previous packet */ 772146778Ssam break; 773146778Ssam 774146778Ssam default: /* Not supported */ 775146778Ssam error("only -t, -tt, -ttt, and -tttt are supported"); 776146778Ssam break; 777146778Ssam } 778146778Ssam 779146778Ssam#ifdef WITH_CHROOT 780146778Ssam /* if run as root, prepare for chrooting */ 781146778Ssam if (getuid() == 0 || geteuid() == 0) { 782146778Ssam /* future extensibility for cmd-line arguments */ 783146778Ssam if (!chroot_dir) 784146778Ssam chroot_dir = WITH_CHROOT; 785146778Ssam } 786146778Ssam#endif 787146778Ssam 788146778Ssam#ifdef WITH_USER 789146778Ssam /* if run as root, prepare for dropping root privileges */ 790146778Ssam if (getuid() == 0 || geteuid() == 0) { 791146778Ssam /* Run with '-Z root' to restore old behaviour */ 792146778Ssam if (!username) 793146778Ssam username = WITH_USER; 794146778Ssam } 795146778Ssam#endif 796146778Ssam 79717680Spst if (RFileName != NULL) { 798127675Sbms int dlt; 799127675Sbms const char *dlt_name; 800127675Sbms 801127675Sbms#ifndef WIN32 80217680Spst /* 803127675Sbms * We don't need network access, so relinquish any set-UID 804127675Sbms * or set-GID privileges we have (if any). 805127675Sbms * 806127675Sbms * We do *not* want set-UID privileges when opening a 807127675Sbms * trace file, as that might let the user read other 808127675Sbms * people's trace files (especially if we're set-UID 809127675Sbms * root). 81017680Spst */ 811146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) 812146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 813127675Sbms#endif /* WIN32 */ 81417680Spst pd = pcap_open_offline(RFileName, ebuf); 81517680Spst if (pd == NULL) 81626180Sfenner error("%s", ebuf); 817127675Sbms dlt = pcap_datalink(pd); 818127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 819127675Sbms if (dlt_name == NULL) { 820127675Sbms fprintf(stderr, "reading from file %s, link-type %u\n", 821127675Sbms RFileName, dlt); 822127675Sbms } else { 823127675Sbms fprintf(stderr, 824127675Sbms "reading from file %s, link-type %s (%s)\n", 825127675Sbms RFileName, dlt_name, 826127675Sbms pcap_datalink_val_to_description(dlt)); 827127675Sbms } 82817680Spst localnet = 0; 82917680Spst netmask = 0; 83017680Spst if (fflag != 0) 83117680Spst error("-f and -r options are incompatible"); 83217680Spst } else { 83317680Spst if (device == NULL) { 83417680Spst device = pcap_lookupdev(ebuf); 83517680Spst if (device == NULL) 83626180Sfenner error("%s", ebuf); 83717680Spst } 838127675Sbms#ifdef WIN32 839146778Ssam if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char 840146778Ssam { //a Unicode string has a \0 as second byte (so strlen() is 1) 841127675Sbms fprintf(stderr, "%s: listening on %ws\n", program_name, device); 842127675Sbms } 843127675Sbms else 844127675Sbms { 845127675Sbms fprintf(stderr, "%s: listening on %s\n", program_name, device); 846127675Sbms } 847127675Sbms 848127675Sbms fflush(stderr); 849127675Sbms#endif /* WIN32 */ 85098527Sfenner *ebuf = '\0'; 85117680Spst pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 85217680Spst if (pd == NULL) 85326180Sfenner error("%s", ebuf); 85498527Sfenner else if (*ebuf) 85598527Sfenner warning("%s", ebuf); 856146778Ssam /* 857146778Ssam * Let user own process after socket has been opened. 858146778Ssam */ 859146778Ssam#ifndef WIN32 860146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0) 861146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 862146778Ssam#endif /* WIN32 */ 863146778Ssam#ifdef WIN32 864146778Ssam if(UserBufferSize != 1000000) 865146778Ssam if(pcap_setbuff(pd, UserBufferSize)==-1){ 866146778Ssam error("%s", pcap_geterr(pd)); 867146778Ssam } 868146778Ssam#endif /* WIN32 */ 869127675Sbms if (Lflag) 870109842Sfenner show_dlts_and_exit(pd); 871146778Ssam if (gndo->ndo_dlt >= 0) { 872127675Sbms#ifdef HAVE_PCAP_SET_DATALINK 873146778Ssam if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0) 874109842Sfenner error("%s", pcap_geterr(pd)); 875127675Sbms#else 876127675Sbms /* 877127675Sbms * We don't actually support changing the 878127675Sbms * data link type, so we only let them 879127675Sbms * set it to what it already is. 880127675Sbms */ 881146778Ssam if (gndo->ndo_dlt != pcap_datalink(pd)) { 882127675Sbms error("%s is not one of the DLTs supported by this device\n", 883146778Ssam gndo->ndo_dltname); 884127675Sbms } 885127675Sbms#endif 886109842Sfenner (void)fprintf(stderr, "%s: data link type %s\n", 887146778Ssam program_name, gndo->ndo_dltname); 888109842Sfenner (void)fflush(stderr); 889109842Sfenner } 89017680Spst i = pcap_snapshot(pd); 89117680Spst if (snaplen < i) { 89217680Spst warning("snaplen raised from %d to %d", snaplen, i); 89317680Spst snaplen = i; 89417680Spst } 89539297Sfenner if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 89639297Sfenner localnet = 0; 89739297Sfenner netmask = 0; 89839297Sfenner warning("%s", ebuf); 89939297Sfenner } 90017680Spst } 90117680Spst if (infile) 90217680Spst cmdbuf = read_infile(infile); 90317680Spst else 90417680Spst cmdbuf = copy_argv(&argv[optind]); 90517680Spst 90617680Spst if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 90726180Sfenner error("%s", pcap_geterr(pd)); 90817680Spst if (dflag) { 90917680Spst bpf_dump(&fcode, dflag); 910127675Sbms pcap_close(pd); 91117680Spst exit(0); 91217680Spst } 91339297Sfenner init_addrtoname(localnet, netmask); 91417680Spst 915127675Sbms#ifndef WIN32 916127675Sbms (void)setsignal(SIGPIPE, cleanup); 917127675Sbms#endif /* WIN32 */ 91839297Sfenner (void)setsignal(SIGTERM, cleanup); 91939297Sfenner (void)setsignal(SIGINT, cleanup); 92039297Sfenner /* Cooperate with nohup(1) */ 921127675Sbms#ifndef WIN32 92239297Sfenner if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 92339297Sfenner (void)setsignal(SIGHUP, oldhandler); 924127675Sbms#endif /* WIN32 */ 92517680Spst 92617680Spst if (pcap_setfilter(pd, &fcode) < 0) 92726180Sfenner error("%s", pcap_geterr(pd)); 92817680Spst if (WFileName) { 929146778Ssam pcap_dumper_t *p; 930146778Ssam 931146778Ssam WFileNameAlt = (char *)malloc(strlen(WFileName) + MAX_CFLAG_CHARS + 1); 932146778Ssam if (WFileNameAlt == NULL) 933146778Ssam error("malloc of WFileNameAlt"); 934146778Ssam MakeFilename(WFileNameAlt, WFileName, 0, WflagChars); 935146778Ssam p = pcap_dump_open(pd, WFileNameAlt); 93617680Spst if (p == NULL) 93726180Sfenner error("%s", pcap_geterr(pd)); 93898527Sfenner if (Cflag != 0) { 939127675Sbms callback = dump_packet_and_trunc; 94098527Sfenner dumpinfo.WFileName = WFileName; 94198527Sfenner dumpinfo.pd = pd; 94298527Sfenner dumpinfo.p = p; 94398527Sfenner pcap_userdata = (u_char *)&dumpinfo; 94498527Sfenner } else { 945127675Sbms callback = dump_packet; 94698527Sfenner pcap_userdata = (u_char *)p; 94798527Sfenner } 94817680Spst } else { 949127675Sbms type = pcap_datalink(pd); 950127675Sbms printinfo.printer = lookup_printer(type); 951127675Sbms if (printinfo.printer == NULL) { 952146778Ssam gndo->ndo_dltname = pcap_datalink_val_to_name(type); 953146778Ssam if (gndo->ndo_dltname != NULL) 954146778Ssam error("unsupported data link type %s", 955146778Ssam gndo->ndo_dltname); 956127675Sbms else 957127675Sbms error("unsupported data link type %d", type); 958127675Sbms } 959127675Sbms callback = print_packet; 960127675Sbms pcap_userdata = (u_char *)&printinfo; 961127675Sbms } 962146778Ssam#ifndef WIN32 963146778Ssam /* 964146778Ssam * We cannot do this earlier, because we want to be able to open 965146778Ssam * the file (if done) for writing before giving up permissions. 966146778Ssam */ 967146778Ssam if (getuid() == 0 || geteuid() == 0) { 968146778Ssam if (username || chroot_dir) 969146778Ssam droproot(username, chroot_dir); 970146778Ssam } 971146778Ssam#endif /* WIN32 */ 97298527Sfenner#ifdef SIGINFO 973127675Sbms (void)setsignal(SIGINFO, requestinfo); 97498527Sfenner#endif 975146778Ssam 976146778Ssam if (vflag > 0 && WFileName) { 977146778Ssam /* 978146778Ssam * When capturing to a file, "-v" means tcpdump should, 979146778Ssam * every 10 secodns, "v"erbosely report the number of 980146778Ssam * packets captured. 981146778Ssam */ 982146778Ssam#ifdef USE_WIN32_MM_TIMER 983146778Ssam /* call verbose_stats_dump() each 1000 +/-100msec */ 984146778Ssam timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); 985146778Ssam setvbuf(stderr, NULL, _IONBF, 0); 986146778Ssam#elif defined(HAVE_ALARM) 987146778Ssam (void)setsignal(SIGALRM, verbose_stats_dump); 988146778Ssam alarm(1); 989146778Ssam#endif 990146778Ssam } 991146778Ssam 992127675Sbms#ifndef WIN32 99317680Spst if (RFileName == NULL) { 994127675Sbms int dlt; 995127675Sbms const char *dlt_name; 996127675Sbms 997127675Sbms if (!vflag && !WFileName) { 998127675Sbms (void)fprintf(stderr, 999127675Sbms "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", 1000127675Sbms program_name); 1001127675Sbms } else 1002127675Sbms (void)fprintf(stderr, "%s: ", program_name); 1003127675Sbms dlt = pcap_datalink(pd); 1004127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1005127675Sbms if (dlt_name == NULL) { 1006127675Sbms (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", 1007127675Sbms device, dlt, snaplen); 1008127675Sbms } else { 1009127675Sbms (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", 1010127675Sbms device, dlt_name, 1011127675Sbms pcap_datalink_val_to_description(dlt), snaplen); 1012127675Sbms } 101317680Spst (void)fflush(stderr); 101417680Spst } 1015127675Sbms#endif /* WIN32 */ 1016127675Sbms status = pcap_loop(pd, cnt, callback, pcap_userdata); 1017127675Sbms if (WFileName == NULL) { 1018127675Sbms /* 1019127675Sbms * We're printing packets. Flush the printed output, 1020127675Sbms * so it doesn't get intermingled with error output. 1021127675Sbms */ 1022127675Sbms if (status == -2) { 1023127675Sbms /* 1024127675Sbms * We got interrupted, so perhaps we didn't 1025127675Sbms * manage to finish a line we were printing. 1026127675Sbms * Print an extra newline, just in case. 1027127675Sbms */ 1028127675Sbms putchar('\n'); 1029127675Sbms } 1030127675Sbms (void)fflush(stdout); 1031127675Sbms } 1032127675Sbms if (status == -1) { 1033127675Sbms /* 1034127675Sbms * Error. Report it. 1035127675Sbms */ 103617680Spst (void)fprintf(stderr, "%s: pcap_loop: %s\n", 103717680Spst program_name, pcap_geterr(pd)); 103817680Spst } 1039127675Sbms if (RFileName == NULL) { 1040127675Sbms /* 1041127675Sbms * We're doing a live capture. Report the capture 1042127675Sbms * statistics. 1043127675Sbms */ 104498527Sfenner info(1); 1045127675Sbms } 104617680Spst pcap_close(pd); 1047127675Sbms exit(status == -1 ? 1 : 0); 104817680Spst} 104917680Spst 105017680Spst/* make a clean exit on interrupts */ 105175118Sfennerstatic RETSIGTYPE 1052127675Sbmscleanup(int signo _U_) 105317680Spst{ 1054146778Ssam#ifdef USE_WIN32_MM_TIMER 1055146778Ssam if (timer_id) 1056146778Ssam timeKillEvent(timer_id); 1057146778Ssam timer_id = 0; 1058146778Ssam#elif defined(HAVE_ALARM) 1059146778Ssam alarm(0); 1060146778Ssam#endif 1061146778Ssam 1062127675Sbms#ifdef HAVE_PCAP_BREAKLOOP 1063127675Sbms /* 1064127675Sbms * We have "pcap_breakloop()"; use it, so that we do as little 1065127675Sbms * as possible in the signal handler (it's probably not safe 1066127675Sbms * to do anything with standard I/O streams in a signal handler - 1067127675Sbms * the ANSI C standard doesn't say it is). 1068127675Sbms */ 1069127675Sbms pcap_breakloop(pd); 1070127675Sbms#else 1071127675Sbms /* 1072127675Sbms * We don't have "pcap_breakloop()"; this isn't safe, but 1073127675Sbms * it's the best we can do. Print the summary if we're 1074127675Sbms * not reading from a savefile - i.e., if we're doing a 1075127675Sbms * live capture - and exit. 1076127675Sbms */ 107717680Spst if (pd != NULL && pcap_file(pd) == NULL) { 1078127675Sbms /* 1079127675Sbms * We got interrupted, so perhaps we didn't 1080127675Sbms * manage to finish a line we were printing. 1081127675Sbms * Print an extra newline, just in case. 1082127675Sbms */ 1083127675Sbms putchar('\n'); 108417680Spst (void)fflush(stdout); 108598527Sfenner info(1); 108617680Spst } 108717680Spst exit(0); 1088127675Sbms#endif 108917680Spst} 109017680Spst 1091127675Sbmsstatic void 109298527Sfennerinfo(register int verbose) 109398527Sfenner{ 109498527Sfenner struct pcap_stat stat; 109598527Sfenner 109698527Sfenner if (pcap_stats(pd, &stat) < 0) { 109798527Sfenner (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); 109898527Sfenner return; 109998527Sfenner } 1100127675Sbms 110198527Sfenner if (!verbose) 110298527Sfenner fprintf(stderr, "%s: ", program_name); 1103127675Sbms 1104127675Sbms (void)fprintf(stderr, "%u packets captured", packets_captured); 1105127675Sbms if (!verbose) 1106127675Sbms fputs(", ", stderr); 1107127675Sbms else 1108127675Sbms putc('\n', stderr); 110998527Sfenner (void)fprintf(stderr, "%d packets received by filter", stat.ps_recv); 111098527Sfenner if (!verbose) 111198527Sfenner fputs(", ", stderr); 111298527Sfenner else 111398527Sfenner putc('\n', stderr); 111498527Sfenner (void)fprintf(stderr, "%d packets dropped by kernel\n", stat.ps_drop); 111598527Sfenner infoprint = 0; 111698527Sfenner} 111798527Sfenner 111898527Sfennerstatic void 1119127675Sbmsdump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 112098527Sfenner{ 1121127675Sbms struct dump_info *dump_info; 112298527Sfenner char *name; 112398527Sfenner 1124127675Sbms ++packets_captured; 1125127675Sbms 1126127675Sbms ++infodelay; 1127127675Sbms 1128127675Sbms dump_info = (struct dump_info *)user; 1129127675Sbms 113098527Sfenner /* 113198527Sfenner * XXX - this won't prevent capture files from getting 113298527Sfenner * larger than Cflag - the last packet written to the 113398527Sfenner * file could put it over Cflag. 113498527Sfenner */ 1135127675Sbms if (ftell((FILE *)dump_info->p) > Cflag) { 1136127675Sbms /* 1137127675Sbms * Close the current file and open a new one. 1138127675Sbms */ 1139127675Sbms pcap_dump_close(dump_info->p); 1140146778Ssam Cflag_count++; 1141146778Ssam if (Wflag > 0) { 1142146778Ssam if (Cflag_count >= Wflag) 1143146778Ssam Cflag_count = 0; 1144146778Ssam } else { 1145146778Ssam if (Cflag_count >= MAX_CFLAG) 1146146778Ssam error("too many output files"); 1147146778Ssam } 1148146778Ssam name = (char *)malloc(strlen(dump_info->WFileName) + MAX_CFLAG_CHARS + 1); 114998527Sfenner if (name == NULL) 1150127675Sbms error("dump_packet_and_trunc: malloc"); 1151146778Ssam MakeFilename(name, dump_info->WFileName, Cflag_count, WflagChars); 1152127675Sbms dump_info->p = pcap_dump_open(dump_info->pd, name); 115398527Sfenner free(name); 1154127675Sbms if (dump_info->p == NULL) 115598527Sfenner error("%s", pcap_geterr(pd)); 115698527Sfenner } 115798527Sfenner 1158127675Sbms pcap_dump((u_char *)dump_info->p, h, sp); 1159127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1160127675Sbms if (Uflag) 1161127675Sbms pcap_dump_flush(dump_info->p); 1162127675Sbms#endif 1163127675Sbms 1164127675Sbms --infodelay; 1165127675Sbms if (infoprint) 1166127675Sbms info(0); 116798527Sfenner} 116898527Sfenner 1169127675Sbmsstatic void 1170127675Sbmsdump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 117117680Spst{ 1172127675Sbms ++packets_captured; 117317680Spst 1174127675Sbms ++infodelay; 1175127675Sbms 1176127675Sbms pcap_dump(user, h, sp); 1177127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1178127675Sbms if (Uflag) 1179127675Sbms pcap_dump_flush((pcap_dumper_t *)user); 1180127675Sbms#endif 1181127675Sbms 1182127675Sbms --infodelay; 1183127675Sbms if (infoprint) 1184127675Sbms info(0); 1185127675Sbms} 1186127675Sbms 1187127675Sbmsstatic void 1188127675Sbmsprint_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 1189127675Sbms{ 1190127675Sbms struct print_info *print_info; 1191127675Sbms u_int hdrlen; 1192127675Sbms 1193127675Sbms ++packets_captured; 1194127675Sbms 1195127675Sbms ++infodelay; 1196127675Sbms ts_print(&h->ts); 1197127675Sbms 1198127675Sbms print_info = (struct print_info *)user; 1199127675Sbms 1200127675Sbms /* 1201127675Sbms * Some printers want to check that they're not walking off the 1202127675Sbms * end of the packet. 1203127675Sbms * Rather than pass it all the way down, we set this global. 1204127675Sbms */ 1205127675Sbms snapend = sp + h->caplen; 1206127675Sbms 1207127675Sbms hdrlen = (*print_info->printer)(h, sp); 1208127675Sbms if (xflag) { 1209127675Sbms /* 1210127675Sbms * Print the raw packet data. 1211127675Sbms */ 1212127675Sbms if (xflag > 1) { 1213127675Sbms /* 1214127675Sbms * Include the link-layer header. 1215127675Sbms */ 1216146778Ssam hex_print("\n\t", sp, h->caplen); 1217127675Sbms } else { 1218127675Sbms /* 1219127675Sbms * Don't include the link-layer header - and if 1220127675Sbms * we have nothing past the link-layer header, 1221127675Sbms * print nothing. 1222127675Sbms */ 1223127675Sbms if (h->caplen > hdrlen) 1224146778Ssam hex_print("\n\t", sp + hdrlen, 1225127675Sbms h->caplen - hdrlen); 1226127675Sbms } 1227146778Ssam } else if (Xflag) { 1228146778Ssam /* 1229146778Ssam * Print the raw packet data. 1230146778Ssam */ 1231146778Ssam if (Xflag > 1) { 1232146778Ssam /* 1233146778Ssam * Include the link-layer header. 1234146778Ssam */ 1235146778Ssam ascii_print("\n\t", sp, h->caplen); 1236146778Ssam } else { 1237146778Ssam /* 1238146778Ssam * Don't include the link-layer header - and if 1239146778Ssam * we have nothing past the link-layer header, 1240146778Ssam * print nothing. 1241146778Ssam */ 1242146778Ssam if (h->caplen > hdrlen) 1243146778Ssam ascii_print("\n\t", sp + hdrlen, 1244146778Ssam h->caplen - hdrlen); 1245146778Ssam } 124617680Spst } 1247127675Sbms 1248127675Sbms putchar('\n'); 1249127675Sbms 1250127675Sbms --infodelay; 1251127675Sbms if (infoprint) 1252127675Sbms info(0); 125317680Spst} 125417680Spst 1255127675Sbms#ifdef WIN32 1256127675Sbms /* 1257127675Sbms * XXX - there should really be libpcap calls to get the version 1258127675Sbms * number as a string (the string would be generated from #defines 1259127675Sbms * at run time, so that it's not generated from string constants 1260127675Sbms * in the library, as, on many UNIX systems, those constants would 1261127675Sbms * be statically linked into the application executable image, and 1262127675Sbms * would thus reflect the version of libpcap on the system on 1263127675Sbms * which the application was *linked*, not the system on which it's 1264127675Sbms * *running*. 1265127675Sbms * 1266127675Sbms * That routine should be documented, unlike the "version[]" 1267127675Sbms * string, so that UNIX vendors providing their own libpcaps 1268127675Sbms * don't omit it (as a couple of vendors have...). 1269127675Sbms * 1270127675Sbms * Packet.dll should perhaps also export a routine to return the 1271127675Sbms * version number of the Packet.dll code, to supply the 1272127675Sbms * "Wpcap_version" information on Windows. 1273127675Sbms */ 1274127675Sbms char WDversion[]="current-cvs.tcpdump.org"; 1275146778Ssam#if !defined(HAVE_GENERATED_VERSION) 1276127675Sbms char version[]="current-cvs.tcpdump.org"; 1277146778Ssam#endif 1278127675Sbms char pcap_version[]="current-cvs.tcpdump.org"; 1279146778Ssam char Wpcap_version[]="3.1"; 1280127675Sbms#endif 1281127675Sbms 128239297Sfenner/* 1283127675Sbms * By default, print the specified data out in hex. 128439297Sfenner */ 1285146778Ssamstatic void 1286146778Ssamndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length) 1287146778Ssam{ 1288146778Ssam ascii_print("\n\t", bp, length); /* pass on lf and identation string */ 1289146778Ssam} 1290146778Ssam 129117680Spstvoid 1292146778Ssamdefault_print(const u_char *bp, u_int length) 129317680Spst{ 1294146778Ssam ndo_default_print(gndo, bp, length); 129517680Spst} 129617680Spst 129798527Sfenner#ifdef SIGINFO 1298127675SbmsRETSIGTYPE requestinfo(int signo _U_) 129998527Sfenner{ 130098527Sfenner if (infodelay) 130198527Sfenner ++infoprint; 130298527Sfenner else 130398527Sfenner info(0); 130498527Sfenner} 130598527Sfenner#endif 130698527Sfenner 1307146778Ssam/* 1308146778Ssam * Called once each second in verbose mode while dumping to file 1309146778Ssam */ 1310146778Ssam#ifdef USE_WIN32_MM_TIMER 1311146778Ssamvoid CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, 1312146778Ssam DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) 1313146778Ssam{ 1314146778Ssam struct pcap_stat stat; 1315146778Ssam 1316146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1317146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 1318146778Ssam} 1319146778Ssam#elif defined(HAVE_ALARM) 1320146778Ssamstatic void verbose_stats_dump(int sig _U_) 1321146778Ssam{ 1322146778Ssam struct pcap_stat stat; 1323146778Ssam 1324146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1325146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 1326146778Ssam alarm(1); 1327146778Ssam} 1328146778Ssam#endif 1329146778Ssam 133075118Sfennerstatic void 133126180Sfennerusage(void) 133217680Spst{ 133317680Spst extern char version[]; 1334127675Sbms#ifndef HAVE_PCAP_LIB_VERSION 1335127675Sbms#if defined(WIN32) || defined(HAVE_PCAP_VERSION) 133639297Sfenner extern char pcap_version[]; 1337127675Sbms#else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1338127675Sbms static char pcap_version[] = "unknown"; 1339127675Sbms#endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1340127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 134117680Spst 1342127675Sbms#ifdef HAVE_PCAP_LIB_VERSION 1343146778Ssam#ifdef WIN32 1344146778Ssam (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1345146778Ssam#else /* WIN32 */ 134639297Sfenner (void)fprintf(stderr, "%s version %s\n", program_name, version); 1347146778Ssam#endif /* WIN32 */ 1348146778Ssam (void)fprintf(stderr, "%s\n",pcap_lib_version()); 1349127675Sbms#else /* HAVE_PCAP_LIB_VERSION */ 1350127675Sbms#ifdef WIN32 1351127675Sbms (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1352127675Sbms (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); 1353127675Sbms#else /* WIN32 */ 1354127675Sbms (void)fprintf(stderr, "%s version %s\n", program_name, version); 135539297Sfenner (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 1356127675Sbms#endif /* WIN32 */ 1357127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 135817680Spst (void)fprintf(stderr, 1359127675Sbms"Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name); 136017680Spst (void)fprintf(stderr, 1361146778Ssam"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]\n"); 136217680Spst (void)fprintf(stderr, 1363146778Ssam"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n"); 1364109842Sfenner (void)fprintf(stderr, 1365146778Ssam"\t\t[ -W filecount ] [ -y datalinktype ] [ -Z user ]\n"); 1366146778Ssam (void)fprintf(stderr, 1367109842Sfenner"\t\t[ expression ]\n"); 136898527Sfenner exit(1); 136917680Spst} 1370146778Ssam 1371146778Ssam 1372146778Ssam 1373146778Ssam/* VARARGS */ 1374146778Ssamstatic void 1375146778Ssamndo_error(netdissect_options *ndo _U_, const char *fmt, ...) 1376146778Ssam{ 1377146778Ssam va_list ap; 1378146778Ssam 1379146778Ssam (void)fprintf(stderr, "%s: ", program_name); 1380146778Ssam va_start(ap, fmt); 1381146778Ssam (void)vfprintf(stderr, fmt, ap); 1382146778Ssam va_end(ap); 1383146778Ssam if (*fmt) { 1384146778Ssam fmt += strlen(fmt); 1385146778Ssam if (fmt[-1] != '\n') 1386146778Ssam (void)fputc('\n', stderr); 1387146778Ssam } 1388146778Ssam exit(1); 1389146778Ssam /* NOTREACHED */ 1390146778Ssam} 1391146778Ssam 1392146778Ssam/* VARARGS */ 1393146778Ssamstatic void 1394146778Ssamndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) 1395146778Ssam{ 1396146778Ssam va_list ap; 1397146778Ssam 1398146778Ssam (void)fprintf(stderr, "%s: WARNING: ", program_name); 1399146778Ssam va_start(ap, fmt); 1400146778Ssam (void)vfprintf(stderr, fmt, ap); 1401146778Ssam va_end(ap); 1402146778Ssam if (*fmt) { 1403146778Ssam fmt += strlen(fmt); 1404146778Ssam if (fmt[-1] != '\n') 1405146778Ssam (void)fputc('\n', stderr); 1406146778Ssam } 1407146778Ssam} 1408146778Ssam 1409