tcpdump.c revision 242485
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_ = 33214478Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.283 2008-09-25 21:45:50 guy Exp $ (LBL)"; 3417680Spst#endif 3517680Spst 3656648Sarchie/* $FreeBSD: stable/9/contrib/tcpdump/tcpdump.c 242485 2012-11-02 16:57:51Z delphij $ */ 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> 70190207Srpaulo#include <limits.h> 71146778Ssam#ifndef WIN32 72190207Srpaulo#include <sys/wait.h> 73190207Srpaulo#include <sys/resource.h> 74146778Ssam#include <pwd.h> 75146778Ssam#include <grp.h> 76146778Ssam#include <errno.h> 77146778Ssam#endif /* WIN32 */ 7817680Spst 79190207Srpaulo 80146778Ssam#include "netdissect.h" 8117680Spst#include "interface.h" 8217680Spst#include "addrtoname.h" 8317680Spst#include "machdep.h" 8439297Sfenner#include "setsignal.h" 8539297Sfenner#include "gmt2local.h" 86127675Sbms#include "pcap-missing.h" 8717680Spst 88190207Srpaulo#ifndef NAME_MAX 89190207Srpaulo#define NAME_MAX 255 90190207Srpaulo#endif 91190207Srpaulo 92242485Sdelphij#ifdef SIGINFO 93242485Sdelphij#define SIGNAL_REQ_INFO SIGINFO 94242485Sdelphij#elif SIGUSR1 95242485Sdelphij#define SIGNAL_REQ_INFO SIGUSR1 96242485Sdelphij#endif 97242485Sdelphij 98146778Ssamnetdissect_options Gndo; 99146778Ssamnetdissect_options *gndo = &Gndo; 100146778Ssam 101214478Srpaulostatic int dflag; /* print filter code */ 102214478Srpaulostatic int Lflag; /* list available data link types and exit */ 103236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 104236192Sdelphijstatic int Jflag; /* list available time stamp types */ 105236192Sdelphij#endif 106214478Srpaulostatic char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ 10739297Sfenner 108127675Sbmsstatic int infodelay; 109127675Sbmsstatic int infoprint; 11017680Spst 11117680Spstchar *program_name; 11217680Spst 11317680Spstint32_t thiszone; /* seconds offset from gmt to local time */ 11417680Spst 11517680Spst/* Forwards */ 11675118Sfennerstatic RETSIGTYPE cleanup(int); 117190207Srpaulostatic RETSIGTYPE child_cleanup(int); 11875118Sfennerstatic void usage(void) __attribute__((noreturn)); 119214478Srpaulostatic void show_dlts_and_exit(const char *device, pcap_t *pd) __attribute__((noreturn)); 12017680Spst 121127675Sbmsstatic void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 122146778Ssamstatic void ndo_default_print(netdissect_options *, const u_char *, u_int); 123127675Sbmsstatic void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); 124127675Sbmsstatic void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 125146778Ssamstatic void droproot(const char *, const char *); 126236192Sdelphijstatic void ndo_error(netdissect_options *ndo, const char *fmt, ...) 127236192Sdelphij __attribute__ ((noreturn, format (printf, 2, 3))); 128146778Ssamstatic void ndo_warning(netdissect_options *ndo, const char *fmt, ...); 12998527Sfenner 130242485Sdelphij#ifdef SIGNAL_REQ_INFO 13198527SfennerRETSIGTYPE requestinfo(int); 13298527Sfenner#endif 13398527Sfenner 134146778Ssam#if defined(USE_WIN32_MM_TIMER) 135146778Ssam #include <MMsystem.h> 136146778Ssam static UINT timer_id; 137146778Ssam static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); 138146778Ssam#elif defined(HAVE_ALARM) 139146778Ssam static void verbose_stats_dump(int sig); 140146778Ssam#endif 141146778Ssam 142127675Sbmsstatic void info(int); 143127675Sbmsstatic u_int packets_captured; 144127675Sbms 14517680Spststruct printer { 146214478Srpaulo if_printer f; 14717680Spst int type; 14817680Spst}; 14917680Spst 150214478Srpaulo 151214478Srpaulostruct ndo_printer { 152214478Srpaulo if_ndo_printer f; 153214478Srpaulo int type; 154214478Srpaulo}; 155214478Srpaulo 156214478Srpaulo 15717680Spststatic struct printer printers[] = { 15898527Sfenner { arcnet_if_print, DLT_ARCNET }, 159127675Sbms#ifdef DLT_ARCNET_LINUX 160127675Sbms { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 161127675Sbms#endif 16244165Sjulian { token_if_print, DLT_IEEE802 }, 16356896Sfenner#ifdef DLT_LANE8023 16456896Sfenner { lane_if_print, DLT_LANE8023 }, 16556896Sfenner#endif 16656896Sfenner#ifdef DLT_CIP 16756896Sfenner { cip_if_print, DLT_CIP }, 16856896Sfenner#endif 16975118Sfenner#ifdef DLT_ATM_CLIP 170214478Srpaulo { cip_if_print, DLT_ATM_CLIP }, 17175118Sfenner#endif 17217680Spst { sl_if_print, DLT_SLIP }, 173127675Sbms#ifdef DLT_SLIP_BSDOS 17439297Sfenner { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 175127675Sbms#endif 17617680Spst { ppp_if_print, DLT_PPP }, 177146778Ssam#ifdef DLT_PPP_WITHDIRECTION 178146778Ssam { ppp_if_print, DLT_PPP_WITHDIRECTION }, 179146778Ssam#endif 180127675Sbms#ifdef DLT_PPP_BSDOS 18139297Sfenner { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 182127675Sbms#endif 18317680Spst { fddi_if_print, DLT_FDDI }, 18417680Spst { null_if_print, DLT_NULL }, 18575118Sfenner#ifdef DLT_LOOP 18675118Sfenner { null_if_print, DLT_LOOP }, 18775118Sfenner#endif 18839297Sfenner { raw_if_print, DLT_RAW }, 18917680Spst { atm_if_print, DLT_ATM_RFC1483 }, 19075118Sfenner#ifdef DLT_C_HDLC 19175118Sfenner { chdlc_if_print, DLT_C_HDLC }, 19256896Sfenner#endif 19398527Sfenner#ifdef DLT_HDLC 19498527Sfenner { chdlc_if_print, DLT_HDLC }, 19598527Sfenner#endif 19675118Sfenner#ifdef DLT_PPP_SERIAL 197214478Srpaulo { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 19875118Sfenner#endif 19998527Sfenner#ifdef DLT_PPP_ETHER 20098527Sfenner { pppoe_if_print, DLT_PPP_ETHER }, 20198527Sfenner#endif 20275118Sfenner#ifdef DLT_LINUX_SLL 20375118Sfenner { sll_if_print, DLT_LINUX_SLL }, 20475118Sfenner#endif 20598527Sfenner#ifdef DLT_IEEE802_11 20698527Sfenner { ieee802_11_if_print, DLT_IEEE802_11}, 20798527Sfenner#endif 20898527Sfenner#ifdef DLT_LTALK 20998527Sfenner { ltalk_if_print, DLT_LTALK }, 21098527Sfenner#endif 211172686Smlaier#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) 212214478Srpaulo { pflog_if_print, DLT_PFLOG }, 213127675Sbms#endif 214127675Sbms#ifdef DLT_FR 215127675Sbms { fr_if_print, DLT_FR }, 216127675Sbms#endif 217127675Sbms#ifdef DLT_FRELAY 218127675Sbms { fr_if_print, DLT_FRELAY }, 219127675Sbms#endif 220127675Sbms#ifdef DLT_SUNATM 221127675Sbms { sunatm_if_print, DLT_SUNATM }, 222127675Sbms#endif 223127675Sbms#ifdef DLT_IP_OVER_FC 224127675Sbms { ipfc_if_print, DLT_IP_OVER_FC }, 225127675Sbms#endif 226127675Sbms#ifdef DLT_PRISM_HEADER 227127675Sbms { prism_if_print, DLT_PRISM_HEADER }, 228127675Sbms#endif 229127675Sbms#ifdef DLT_IEEE802_11_RADIO 230127675Sbms { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 231127675Sbms#endif 232127675Sbms#ifdef DLT_ENC 233214478Srpaulo { enc_if_print, DLT_ENC }, 234127675Sbms#endif 235146778Ssam#ifdef DLT_SYMANTEC_FIREWALL 236214478Srpaulo { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 237146778Ssam#endif 238127675Sbms#ifdef DLT_APPLE_IP_OVER_IEEE1394 239127675Sbms { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 240127675Sbms#endif 241190207Srpaulo#ifdef DLT_IEEE802_11_RADIO_AVS 242190207Srpaulo { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, 243190207Srpaulo#endif 244146778Ssam#ifdef DLT_JUNIPER_ATM1 245146778Ssam { juniper_atm1_print, DLT_JUNIPER_ATM1 }, 246146778Ssam#endif 247146778Ssam#ifdef DLT_JUNIPER_ATM2 248146778Ssam { juniper_atm2_print, DLT_JUNIPER_ATM2 }, 249146778Ssam#endif 250147904Ssam#ifdef DLT_JUNIPER_MFR 251147904Ssam { juniper_mfr_print, DLT_JUNIPER_MFR }, 252147904Ssam#endif 253146778Ssam#ifdef DLT_JUNIPER_MLFR 254146778Ssam { juniper_mlfr_print, DLT_JUNIPER_MLFR }, 255146778Ssam#endif 256146778Ssam#ifdef DLT_JUNIPER_MLPPP 257146778Ssam { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, 258146778Ssam#endif 259147904Ssam#ifdef DLT_JUNIPER_PPPOE 260147904Ssam { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, 261147904Ssam#endif 262147904Ssam#ifdef DLT_JUNIPER_PPPOE_ATM 263147904Ssam { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, 264147904Ssam#endif 265147904Ssam#ifdef DLT_JUNIPER_GGSN 266147904Ssam { juniper_ggsn_print, DLT_JUNIPER_GGSN }, 267147904Ssam#endif 268147904Ssam#ifdef DLT_JUNIPER_ES 269147904Ssam { juniper_es_print, DLT_JUNIPER_ES }, 270147904Ssam#endif 271147904Ssam#ifdef DLT_JUNIPER_MONITOR 272147904Ssam { juniper_monitor_print, DLT_JUNIPER_MONITOR }, 273147904Ssam#endif 274147904Ssam#ifdef DLT_JUNIPER_SERVICES 275147904Ssam { juniper_services_print, DLT_JUNIPER_SERVICES }, 276147904Ssam#endif 277162021Ssam#ifdef DLT_JUNIPER_ETHER 278214478Srpaulo { juniper_ether_print, DLT_JUNIPER_ETHER }, 279162021Ssam#endif 280162021Ssam#ifdef DLT_JUNIPER_PPP 281214478Srpaulo { juniper_ppp_print, DLT_JUNIPER_PPP }, 282162021Ssam#endif 283162021Ssam#ifdef DLT_JUNIPER_FRELAY 284214478Srpaulo { juniper_frelay_print, DLT_JUNIPER_FRELAY }, 285162021Ssam#endif 286162021Ssam#ifdef DLT_JUNIPER_CHDLC 287214478Srpaulo { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, 288162021Ssam#endif 289172686Smlaier#ifdef DLT_MFR 290214478Srpaulo { mfr_if_print, DLT_MFR }, 291172686Smlaier#endif 292190207Srpaulo#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) 293214478Srpaulo { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, 294190207Srpaulo#endif 295214478Srpaulo#ifdef HAVE_PCAP_USB_H 296214478Srpaulo#ifdef DLT_USB_LINUX 297214478Srpaulo { usb_linux_48_byte_print, DLT_USB_LINUX}, 298214478Srpaulo#endif /* DLT_USB_LINUX */ 299214478Srpaulo#ifdef DLT_USB_LINUX_MMAPPED 300214478Srpaulo { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED}, 301214478Srpaulo#endif /* DLT_USB_LINUX_MMAPPED */ 302214478Srpaulo#endif /* HAVE_PCAP_USB_H */ 303214478Srpaulo#ifdef DLT_IPV4 304214478Srpaulo { raw_if_print, DLT_IPV4 }, 305214478Srpaulo#endif 306214478Srpaulo#ifdef DLT_IPV6 307214478Srpaulo { raw_if_print, DLT_IPV6 }, 308214478Srpaulo#endif 30917680Spst { NULL, 0 }, 31017680Spst}; 31117680Spst 312214478Srpaulostatic struct ndo_printer ndo_printers[] = { 313236192Sdelphij { ether_if_print, DLT_EN10MB }, 314214478Srpaulo#ifdef DLT_IPNET 315214478Srpaulo { ipnet_if_print, DLT_IPNET }, 316214478Srpaulo#endif 317236192Sdelphij#ifdef DLT_IEEE802_15_4 318236192Sdelphij { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, 319236192Sdelphij#endif 320236192Sdelphij#ifdef DLT_IEEE802_15_4_NOFCS 321236192Sdelphij { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, 322236192Sdelphij#endif 323236192Sdelphij#ifdef DLT_PPI 324236192Sdelphij { ppi_if_print, DLT_PPI }, 325236192Sdelphij#endif 326236192Sdelphij#ifdef DLT_NETANALYZER 327236192Sdelphij { netanalyzer_if_print, DLT_NETANALYZER }, 328236192Sdelphij#endif 329236192Sdelphij#ifdef DLT_NETANALYZER_TRANSPARENT 330236192Sdelphij { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, 331236192Sdelphij#endif 332214478Srpaulo { NULL, 0 }, 333214478Srpaulo}; 334214478Srpaulo 335236192Sdelphijif_printer 33617680Spstlookup_printer(int type) 33717680Spst{ 33817680Spst struct printer *p; 33917680Spst 34017680Spst for (p = printers; p->f; ++p) 34117680Spst if (type == p->type) 34217680Spst return p->f; 34317680Spst 344127675Sbms return NULL; 34517680Spst /* NOTREACHED */ 34617680Spst} 34717680Spst 348236192Sdelphijif_ndo_printer 349214478Srpaulolookup_ndo_printer(int type) 350214478Srpaulo{ 351214478Srpaulo struct ndo_printer *p; 352214478Srpaulo 353214478Srpaulo for (p = ndo_printers; p->f; ++p) 354214478Srpaulo if (type == p->type) 355214478Srpaulo return p->f; 356214478Srpaulo 357214478Srpaulo return NULL; 358214478Srpaulo /* NOTREACHED */ 359214478Srpaulo} 360214478Srpaulo 36117680Spststatic pcap_t *pd; 36217680Spst 363214478Srpaulostatic int supports_monitor_mode; 364214478Srpaulo 36517680Spstextern int optind; 36617680Spstextern int opterr; 36717680Spstextern char *optarg; 36817680Spst 369127675Sbmsstruct print_info { 370214478Srpaulo netdissect_options *ndo; 371214478Srpaulo union { 372214478Srpaulo if_printer printer; 373214478Srpaulo if_ndo_printer ndo_printer; 374214478Srpaulo } p; 375214478Srpaulo int ndo_type; 376127675Sbms}; 377127675Sbms 37898527Sfennerstruct dump_info { 37998527Sfenner char *WFileName; 380190207Srpaulo char *CurrentFileName; 38198527Sfenner pcap_t *pd; 38298527Sfenner pcap_dumper_t *p; 38398527Sfenner}; 38498527Sfenner 385236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 386109842Sfennerstatic void 387236192Sdelphijshow_tstamp_types_and_exit(const char *device, pcap_t *pd) 388236192Sdelphij{ 389236192Sdelphij int n_tstamp_types; 390236192Sdelphij int *tstamp_types = 0; 391236192Sdelphij const char *tstamp_type_name; 392236192Sdelphij int i; 393236192Sdelphij 394236192Sdelphij n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types); 395236192Sdelphij if (n_tstamp_types < 0) 396236192Sdelphij error("%s", pcap_geterr(pd)); 397236192Sdelphij 398236192Sdelphij if (n_tstamp_types == 0) { 399236192Sdelphij fprintf(stderr, "Time stamp type cannot be set for %s\n", 400236192Sdelphij device); 401236192Sdelphij exit(0); 402236192Sdelphij } 403236192Sdelphij fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", 404236192Sdelphij device); 405236192Sdelphij for (i = 0; i < n_tstamp_types; i++) { 406236192Sdelphij tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); 407236192Sdelphij if (tstamp_type_name != NULL) { 408236192Sdelphij (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, 409236192Sdelphij pcap_tstamp_type_val_to_description(tstamp_types[i])); 410236192Sdelphij } else { 411236192Sdelphij (void) fprintf(stderr, " %d\n", tstamp_types[i]); 412236192Sdelphij } 413236192Sdelphij } 414236192Sdelphij pcap_free_tstamp_types(tstamp_types); 415236192Sdelphij exit(0); 416236192Sdelphij} 417236192Sdelphij#endif 418236192Sdelphij 419236192Sdelphijstatic void 420214478Srpauloshow_dlts_and_exit(const char *device, pcap_t *pd) 421109842Sfenner{ 422127675Sbms int n_dlts; 423109842Sfenner int *dlts = 0; 424127675Sbms const char *dlt_name; 425127675Sbms 426109842Sfenner n_dlts = pcap_list_datalinks(pd, &dlts); 427109842Sfenner if (n_dlts < 0) 428109842Sfenner error("%s", pcap_geterr(pd)); 429109842Sfenner else if (n_dlts == 0 || !dlts) 430109842Sfenner error("No data link types."); 431109842Sfenner 432214478Srpaulo /* 433214478Srpaulo * If the interface is known to support monitor mode, indicate 434214478Srpaulo * whether these are the data link types available when not in 435214478Srpaulo * monitor mode, if -I wasn't specified, or when in monitor mode, 436214478Srpaulo * when -I was specified (the link-layer types available in 437214478Srpaulo * monitor mode might be different from the ones available when 438214478Srpaulo * not in monitor mode). 439214478Srpaulo */ 440214478Srpaulo if (supports_monitor_mode) 441214478Srpaulo (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", 442214478Srpaulo device, 443214478Srpaulo Iflag ? "when in monitor mode" : "when not in monitor mode"); 444214478Srpaulo else 445214478Srpaulo (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", 446214478Srpaulo device); 447109842Sfenner 448109842Sfenner while (--n_dlts >= 0) { 449127675Sbms dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); 450127675Sbms if (dlt_name != NULL) { 451127675Sbms (void) fprintf(stderr, " %s (%s)", dlt_name, 452127675Sbms pcap_datalink_val_to_description(dlts[n_dlts])); 453127675Sbms 454127675Sbms /* 455127675Sbms * OK, does tcpdump handle that type? 456127675Sbms */ 457214478Srpaulo if (lookup_printer(dlts[n_dlts]) == NULL 458214478Srpaulo && lookup_ndo_printer(dlts[n_dlts]) == NULL) 459190207Srpaulo (void) fprintf(stderr, " (printing not supported)"); 460236192Sdelphij fprintf(stderr, "\n"); 461127675Sbms } else { 462190207Srpaulo (void) fprintf(stderr, " DLT %d (printing not supported)\n", 463127675Sbms dlts[n_dlts]); 464109842Sfenner } 465109842Sfenner } 466236192Sdelphij pcap_free_datalinks(dlts); 467109842Sfenner exit(0); 468109842Sfenner} 469109842Sfenner 470127675Sbms/* 471127675Sbms * Set up flags that might or might not be supported depending on the 472127675Sbms * version of libpcap we're using. 473127675Sbms */ 474190207Srpaulo#if defined(HAVE_PCAP_CREATE) || defined(WIN32) 475127675Sbms#define B_FLAG "B:" 476127675Sbms#define B_FLAG_USAGE " [ -B size ]" 477190207Srpaulo#else /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 478127675Sbms#define B_FLAG 479127675Sbms#define B_FLAG_USAGE 480190207Srpaulo#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 481127675Sbms 482190207Srpaulo#ifdef HAVE_PCAP_CREATE 483190207Srpaulo#define I_FLAG "I" 484190207Srpaulo#else /* HAVE_PCAP_CREATE */ 485190207Srpaulo#define I_FLAG 486190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 487190207Srpaulo 488236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 489236192Sdelphij#define j_FLAG "j:" 490236192Sdelphij#define j_FLAG_USAGE " [ -j tstamptype ]" 491236192Sdelphij#define J_FLAG "J" 492236192Sdelphij#else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ 493236192Sdelphij#define j_FLAG 494236192Sdelphij#define j_FLAG_USAGE 495236192Sdelphij#define J_FLAG 496236192Sdelphij#endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ 497236192Sdelphij 498127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 499146778Ssam#ifndef HAVE_PCAP_IF_T 500146778Ssam#undef HAVE_PCAP_FINDALLDEVS 501146778Ssam#endif 502146778Ssam#endif 503146778Ssam 504146778Ssam#ifdef HAVE_PCAP_FINDALLDEVS 505127675Sbms#define D_FLAG "D" 506127675Sbms#else 507127675Sbms#define D_FLAG 508127675Sbms#endif 509127675Sbms 510127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 511127675Sbms#define U_FLAG "U" 512127675Sbms#else 513127675Sbms#define U_FLAG 514127675Sbms#endif 515127675Sbms 516146778Ssam#ifndef WIN32 517146778Ssam/* Drop root privileges and chroot if necessary */ 518146778Ssamstatic void 519146778Ssamdroproot(const char *username, const char *chroot_dir) 520146778Ssam{ 521146778Ssam struct passwd *pw = NULL; 522146778Ssam 523146778Ssam if (chroot_dir && !username) { 524146778Ssam fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); 525146778Ssam exit(1); 526146778Ssam } 527146778Ssam 528146778Ssam pw = getpwnam(username); 529146778Ssam if (pw) { 530146778Ssam if (chroot_dir) { 531146778Ssam if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { 532146778Ssam fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", 533146778Ssam chroot_dir, pcap_strerror(errno)); 534146778Ssam exit(1); 535146778Ssam } 536146778Ssam } 537146778Ssam if (initgroups(pw->pw_name, pw->pw_gid) != 0 || 538146778Ssam setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { 539146778Ssam fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", 540146778Ssam username, 541146778Ssam (unsigned long)pw->pw_uid, 542146778Ssam (unsigned long)pw->pw_gid, 543146778Ssam pcap_strerror(errno)); 544146778Ssam exit(1); 545146778Ssam } 546146778Ssam } 547146778Ssam else { 548146778Ssam fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", 549146778Ssam username); 550146778Ssam exit(1); 551146778Ssam } 552146778Ssam} 553146778Ssam#endif /* WIN32 */ 554146778Ssam 555146778Ssamstatic int 556146778SsamgetWflagChars(int x) 557146778Ssam{ 558146778Ssam int c = 0; 559146778Ssam 560146778Ssam x -= 1; 561146778Ssam while (x > 0) { 562146778Ssam c += 1; 563146778Ssam x /= 10; 564146778Ssam } 565146778Ssam 566146778Ssam return c; 567146778Ssam} 568146778Ssam 569146778Ssam 570146778Ssamstatic void 571146778SsamMakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) 572146778Ssam{ 573190207Srpaulo char *filename = malloc(NAME_MAX + 1); 574190207Srpaulo 575190207Srpaulo /* Process with strftime if Gflag is set. */ 576190207Srpaulo if (Gflag != 0) { 577190207Srpaulo struct tm *local_tm; 578190207Srpaulo 579190207Srpaulo /* Convert Gflag_time to a usable format */ 580190207Srpaulo if ((local_tm = localtime(&Gflag_time)) == NULL) { 581190207Srpaulo error("MakeTimedFilename: localtime"); 582190207Srpaulo } 583190207Srpaulo 584190207Srpaulo /* There's no good way to detect an error in strftime since a return 585190207Srpaulo * value of 0 isn't necessarily failure. 586190207Srpaulo */ 587190207Srpaulo strftime(filename, NAME_MAX, orig_name, local_tm); 588190207Srpaulo } else { 589190207Srpaulo strncpy(filename, orig_name, NAME_MAX); 590190207Srpaulo } 591190207Srpaulo 592146778Ssam if (cnt == 0 && max_chars == 0) 593190207Srpaulo strncpy(buffer, filename, NAME_MAX + 1); 594146778Ssam else 595190207Srpaulo if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX) 596190207Srpaulo /* Report an error if the filename is too large */ 597190207Srpaulo error("too many output files or filename is too long (> %d)", NAME_MAX); 598190207Srpaulo free(filename); 599146778Ssam} 600146778Ssam 601146778Ssamstatic int tcpdump_printf(netdissect_options *ndo _U_, 602146778Ssam const char *fmt, ...) 603146778Ssam{ 604146778Ssam 605146778Ssam va_list args; 606146778Ssam int ret; 607146778Ssam 608146778Ssam va_start(args, fmt); 609146778Ssam ret=vfprintf(stdout, fmt, args); 610146778Ssam va_end(args); 611146778Ssam 612146778Ssam return ret; 613146778Ssam} 614146778Ssam 61517680Spstint 61617680Spstmain(int argc, char **argv) 61717680Spst{ 61817680Spst register int cnt, op, i; 61917680Spst bpf_u_int32 localnet, netmask; 620190207Srpaulo register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; 621127675Sbms pcap_handler callback; 622127675Sbms int type; 62317680Spst struct bpf_program fcode; 624127675Sbms#ifndef WIN32 62539297Sfenner RETSIGTYPE (*oldhandler)(int); 626127675Sbms#endif 627127675Sbms struct print_info printinfo; 62898527Sfenner struct dump_info dumpinfo; 62917680Spst u_char *pcap_userdata; 63017680Spst char ebuf[PCAP_ERRBUF_SIZE]; 631146778Ssam char *username = NULL; 632146778Ssam char *chroot_dir = NULL; 633127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 634127675Sbms pcap_if_t *devpointer; 635127675Sbms int devnum; 636127675Sbms#endif 637127675Sbms int status; 638127675Sbms#ifdef WIN32 639127675Sbms if(wsockinit() != 0) return 1; 640127675Sbms#endif /* WIN32 */ 64117680Spst 642236192Sdelphij jflag=-1; /* not set */ 643146778Ssam gndo->ndo_Oflag=1; 644146778Ssam gndo->ndo_Rflag=1; 645146778Ssam gndo->ndo_dlt=-1; 646146778Ssam gndo->ndo_default_print=ndo_default_print; 647146778Ssam gndo->ndo_printf=tcpdump_printf; 648146778Ssam gndo->ndo_error=ndo_error; 649146778Ssam gndo->ndo_warning=ndo_warning; 650146778Ssam gndo->ndo_snaplen = DEFAULT_SNAPLEN; 651146778Ssam 65217680Spst cnt = -1; 65317680Spst device = NULL; 65417680Spst infile = NULL; 65517680Spst RFileName = NULL; 65617680Spst WFileName = NULL; 65717680Spst if ((cp = strrchr(argv[0], '/')) != NULL) 65817680Spst program_name = cp + 1; 65917680Spst else 66017680Spst program_name = argv[0]; 66117680Spst 66275118Sfenner if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) 66326180Sfenner error("%s", ebuf); 66417680Spst 66556896Sfenner#ifdef LIBSMI 66656896Sfenner smiInit("tcpdump"); 66756896Sfenner#endif 668127675Sbms 66939297Sfenner while ( 670236192Sdelphij (op = getopt(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1) 67117680Spst switch (op) { 67239297Sfenner 67339297Sfenner case 'a': 674127675Sbms /* compatibility for old -a */ 67539297Sfenner break; 67639297Sfenner 677127675Sbms case 'A': 678127675Sbms ++Aflag; 679127675Sbms break; 680127675Sbms 681214478Srpaulo case 'b': 682214478Srpaulo ++bflag; 683214478Srpaulo break; 684214478Srpaulo 685190207Srpaulo#if defined(HAVE_PCAP_CREATE) || defined(WIN32) 686127675Sbms case 'B': 687190207Srpaulo Bflag = atoi(optarg)*1024; 688190207Srpaulo if (Bflag <= 0) 689127675Sbms error("invalid packet buffer size %s", optarg); 690127675Sbms break; 691190207Srpaulo#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 692127675Sbms 69317680Spst case 'c': 69417680Spst cnt = atoi(optarg); 69517680Spst if (cnt <= 0) 69617680Spst error("invalid packet count %s", optarg); 69717680Spst break; 69817680Spst 69998527Sfenner case 'C': 70098527Sfenner Cflag = atoi(optarg) * 1000000; 701127675Sbms if (Cflag < 0) 70298527Sfenner error("invalid file size %s", optarg); 70398527Sfenner break; 70498527Sfenner 70517680Spst case 'd': 70617680Spst ++dflag; 70717680Spst break; 70817680Spst 709127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 710127675Sbms case 'D': 711127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 712127675Sbms error("%s", ebuf); 713127675Sbms else { 714127675Sbms for (i = 0; devpointer != 0; i++) { 715127675Sbms printf("%d.%s", i+1, devpointer->name); 716127675Sbms if (devpointer->description != NULL) 717127675Sbms printf(" (%s)", devpointer->description); 718127675Sbms printf("\n"); 719127675Sbms devpointer = devpointer->next; 720127675Sbms } 721127675Sbms } 722127675Sbms return 0; 723127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 724127675Sbms 725109842Sfenner case 'L': 726109842Sfenner Lflag++; 727109842Sfenner break; 728109842Sfenner 72917680Spst case 'e': 73017680Spst ++eflag; 73117680Spst break; 73217680Spst 73356896Sfenner case 'E': 73475118Sfenner#ifndef HAVE_LIBCRYPTO 73556896Sfenner warning("crypto code not compiled in"); 73656896Sfenner#endif 737146778Ssam gndo->ndo_espsecret = optarg; 73856896Sfenner break; 73956896Sfenner 74017680Spst case 'f': 74117680Spst ++fflag; 74217680Spst break; 74317680Spst 74417680Spst case 'F': 74517680Spst infile = optarg; 74617680Spst break; 74717680Spst 748190207Srpaulo case 'G': 749190207Srpaulo Gflag = atoi(optarg); 750190207Srpaulo if (Gflag < 0) 751190207Srpaulo error("invalid number of seconds %s", optarg); 752190207Srpaulo 753190207Srpaulo /* We will create one file initially. */ 754190207Srpaulo Gflag_count = 0; 755190207Srpaulo 756190207Srpaulo /* Grab the current time for rotation use. */ 757190207Srpaulo if ((Gflag_time = time(NULL)) == (time_t)-1) { 758190207Srpaulo error("main: can't get current time: %s", 759190207Srpaulo pcap_strerror(errno)); 760190207Srpaulo } 761190207Srpaulo break; 762190207Srpaulo 763236192Sdelphij case 'h': 764236192Sdelphij usage(); 765236192Sdelphij break; 766236192Sdelphij 767236192Sdelphij case 'H': 768236192Sdelphij ++Hflag; 769236192Sdelphij break; 770236192Sdelphij 77117680Spst case 'i': 772127675Sbms if (optarg[0] == '0' && optarg[1] == 0) 773127675Sbms error("Invalid adapter index"); 774127675Sbms 775127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 776127675Sbms /* 777127675Sbms * If the argument is a number, treat it as 778127675Sbms * an index into the list of adapters, as 779127675Sbms * printed by "tcpdump -D". 780127675Sbms * 781127675Sbms * This should be OK on UNIX systems, as interfaces 782127675Sbms * shouldn't have names that begin with digits. 783127675Sbms * It can be useful on Windows, where more than 784127675Sbms * one interface can have the same name. 785127675Sbms */ 786127675Sbms if ((devnum = atoi(optarg)) != 0) { 787127675Sbms if (devnum < 0) 788127675Sbms error("Invalid adapter index"); 789127675Sbms 790127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 791127675Sbms error("%s", ebuf); 792127675Sbms else { 793214478Srpaulo /* 794214478Srpaulo * Look for the devnum-th entry 795214478Srpaulo * in the list of devices 796214478Srpaulo * (1-based). 797214478Srpaulo */ 798214478Srpaulo for (i = 0; 799214478Srpaulo i < devnum-1 && devpointer != NULL; 800214478Srpaulo i++, devpointer = devpointer->next) 801214478Srpaulo ; 802214478Srpaulo if (devpointer == NULL) 803214478Srpaulo error("Invalid adapter index"); 804127675Sbms } 805127675Sbms device = devpointer->name; 806127675Sbms break; 807127675Sbms } 808127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 80917680Spst device = optarg; 81017680Spst break; 81117680Spst 812190207Srpaulo#ifdef HAVE_PCAP_CREATE 813190207Srpaulo case 'I': 814190207Srpaulo ++Iflag; 815190207Srpaulo break; 816190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 817190207Srpaulo 818236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 819236192Sdelphij case 'j': 820236192Sdelphij jflag = pcap_tstamp_type_name_to_val(optarg); 821236192Sdelphij if (jflag < 0) 822236192Sdelphij error("invalid time stamp type %s", optarg); 823236192Sdelphij break; 824236192Sdelphij 825236192Sdelphij case 'J': 826236192Sdelphij Jflag++; 827236192Sdelphij break; 828236192Sdelphij#endif 829236192Sdelphij 83017680Spst case 'l': 831127675Sbms#ifdef WIN32 832127675Sbms /* 833127675Sbms * _IOLBF is the same as _IOFBF in Microsoft's C 834127675Sbms * libraries; the only alternative they offer 835127675Sbms * is _IONBF. 836127675Sbms * 837127675Sbms * XXX - this should really be checking for MSVC++, 838127675Sbms * not WIN32, if, for example, MinGW has its own 839127675Sbms * C library that is more UNIX-compatible. 840127675Sbms */ 841127675Sbms setvbuf(stdout, NULL, _IONBF, 0); 842127675Sbms#else /* WIN32 */ 84317680Spst#ifdef HAVE_SETLINEBUF 84417680Spst setlinebuf(stdout); 84517680Spst#else 84617680Spst setvbuf(stdout, NULL, _IOLBF, 0); 84717680Spst#endif 848127675Sbms#endif /* WIN32 */ 84917680Spst break; 85017680Spst 851190207Srpaulo case 'K': 852190207Srpaulo ++Kflag; 85317680Spst break; 85417680Spst 85556896Sfenner case 'm': 85656896Sfenner#ifdef LIBSMI 857190207Srpaulo if (smiLoadModule(optarg) == 0) { 85856896Sfenner error("could not load MIB module %s", optarg); 859190207Srpaulo } 86056896Sfenner sflag = 1; 86156896Sfenner#else 86256896Sfenner (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 86356896Sfenner program_name, optarg); 86456896Sfenner (void)fprintf(stderr, "(no libsmi support)\n"); 86556896Sfenner#endif 866127675Sbms break; 867127675Sbms 868146778Ssam case 'M': 869146778Ssam /* TCP-MD5 shared secret */ 870146778Ssam#ifndef HAVE_LIBCRYPTO 871146778Ssam warning("crypto code not compiled in"); 872146778Ssam#endif 873214478Srpaulo sigsecret = optarg; 874146778Ssam break; 875146778Ssam 876190207Srpaulo case 'n': 877190207Srpaulo ++nflag; 878190207Srpaulo break; 879190207Srpaulo 880190207Srpaulo case 'N': 881190207Srpaulo ++Nflag; 882190207Srpaulo break; 883190207Srpaulo 88417680Spst case 'O': 88517680Spst Oflag = 0; 88617680Spst break; 88717680Spst 88817680Spst case 'p': 88917680Spst ++pflag; 89017680Spst break; 89117680Spst 89217680Spst case 'q': 89317680Spst ++qflag; 894162021Ssam ++suppress_default_print; 89517680Spst break; 89617680Spst 89717680Spst case 'r': 89817680Spst RFileName = optarg; 89917680Spst break; 90017680Spst 90156896Sfenner case 'R': 90256896Sfenner Rflag = 0; 90356896Sfenner break; 90456896Sfenner 90575118Sfenner case 's': { 90675118Sfenner char *end; 90775118Sfenner 90875118Sfenner snaplen = strtol(optarg, &end, 0); 90975118Sfenner if (optarg == end || *end != '\0' 910214478Srpaulo || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN) 91117680Spst error("invalid snaplen %s", optarg); 91275118Sfenner else if (snaplen == 0) 913214478Srpaulo snaplen = MAXIMUM_SNAPLEN; 91417680Spst break; 91575118Sfenner } 91617680Spst 91717680Spst case 'S': 91817680Spst ++Sflag; 91917680Spst break; 92017680Spst 92117680Spst case 't': 922146778Ssam ++tflag; 92317680Spst break; 92417680Spst 92517680Spst case 'T': 92617680Spst if (strcasecmp(optarg, "vat") == 0) 92717680Spst packettype = PT_VAT; 92817680Spst else if (strcasecmp(optarg, "wb") == 0) 92917680Spst packettype = PT_WB; 93017680Spst else if (strcasecmp(optarg, "rpc") == 0) 93117680Spst packettype = PT_RPC; 93217680Spst else if (strcasecmp(optarg, "rtp") == 0) 93317680Spst packettype = PT_RTP; 93417680Spst else if (strcasecmp(optarg, "rtcp") == 0) 93517680Spst packettype = PT_RTCP; 93656896Sfenner else if (strcasecmp(optarg, "snmp") == 0) 93756896Sfenner packettype = PT_SNMP; 93875118Sfenner else if (strcasecmp(optarg, "cnfp") == 0) 93975118Sfenner packettype = PT_CNFP; 940127675Sbms else if (strcasecmp(optarg, "tftp") == 0) 941127675Sbms packettype = PT_TFTP; 942127675Sbms else if (strcasecmp(optarg, "aodv") == 0) 943127675Sbms packettype = PT_AODV; 944236192Sdelphij else if (strcasecmp(optarg, "carp") == 0) 945236192Sdelphij packettype = PT_CARP; 94617680Spst else 94717680Spst error("unknown packet type `%s'", optarg); 94817680Spst break; 94917680Spst 95075118Sfenner case 'u': 95175118Sfenner ++uflag; 95275118Sfenner break; 953127675Sbms 954127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 955127675Sbms case 'U': 956127675Sbms ++Uflag; 957127675Sbms break; 958127675Sbms#endif 959127675Sbms 96017680Spst case 'v': 96117680Spst ++vflag; 96217680Spst break; 96317680Spst 96417680Spst case 'w': 96517680Spst WFileName = optarg; 96617680Spst break; 96756896Sfenner 968146778Ssam case 'W': 969146778Ssam Wflag = atoi(optarg); 970146778Ssam if (Wflag < 0) 971146778Ssam error("invalid number of output files %s", optarg); 972146778Ssam WflagChars = getWflagChars(Wflag); 973146778Ssam break; 974146778Ssam 97556896Sfenner case 'x': 97656896Sfenner ++xflag; 977162021Ssam ++suppress_default_print; 97856896Sfenner break; 97956896Sfenner 98056896Sfenner case 'X': 98156896Sfenner ++Xflag; 982162021Ssam ++suppress_default_print; 98356896Sfenner break; 98456896Sfenner 985109842Sfenner case 'y': 986146778Ssam gndo->ndo_dltname = optarg; 987146778Ssam gndo->ndo_dlt = 988146778Ssam pcap_datalink_name_to_val(gndo->ndo_dltname); 989146778Ssam if (gndo->ndo_dlt < 0) 990146778Ssam error("invalid data link type %s", gndo->ndo_dltname); 991109842Sfenner break; 992109842Sfenner 993127675Sbms#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) 99417680Spst case 'Y': 99517680Spst { 99617680Spst /* Undocumented flag */ 997127675Sbms#ifdef HAVE_PCAP_DEBUG 998127675Sbms extern int pcap_debug; 999127675Sbms pcap_debug = 1; 1000127675Sbms#else 100117680Spst extern int yydebug; 100217680Spst yydebug = 1; 1003127675Sbms#endif 100417680Spst } 100517680Spst break; 100617680Spst#endif 1007190207Srpaulo case 'z': 1008190207Srpaulo if (optarg) { 1009190207Srpaulo zflag = strdup(optarg); 1010190207Srpaulo } else { 1011190207Srpaulo usage(); 1012190207Srpaulo /* NOTREACHED */ 1013190207Srpaulo } 1014190207Srpaulo break; 1015190207Srpaulo 1016146778Ssam case 'Z': 1017146778Ssam if (optarg) { 1018146778Ssam username = strdup(optarg); 1019146778Ssam } 1020146778Ssam else { 1021146778Ssam usage(); 1022146778Ssam /* NOTREACHED */ 1023146778Ssam } 1024146778Ssam break; 1025146778Ssam 102617680Spst default: 102717680Spst usage(); 102817680Spst /* NOTREACHED */ 102917680Spst } 103017680Spst 1031146778Ssam switch (tflag) { 1032146778Ssam 1033146778Ssam case 0: /* Default */ 1034146778Ssam case 4: /* Default + Date*/ 103539297Sfenner thiszone = gmt2local(0); 1036146778Ssam break; 103717680Spst 1038146778Ssam case 1: /* No time stamp */ 1039146778Ssam case 2: /* Unix timeval style */ 1040146778Ssam case 3: /* Microseconds since previous packet */ 1041190207Srpaulo case 5: /* Microseconds since first packet */ 1042146778Ssam break; 1043146778Ssam 1044146778Ssam default: /* Not supported */ 1045190207Srpaulo error("only -t, -tt, -ttt, -tttt and -ttttt are supported"); 1046146778Ssam break; 1047146778Ssam } 1048146778Ssam 1049146778Ssam#ifdef WITH_CHROOT 1050146778Ssam /* if run as root, prepare for chrooting */ 1051146778Ssam if (getuid() == 0 || geteuid() == 0) { 1052146778Ssam /* future extensibility for cmd-line arguments */ 1053146778Ssam if (!chroot_dir) 1054146778Ssam chroot_dir = WITH_CHROOT; 1055146778Ssam } 1056146778Ssam#endif 1057146778Ssam 1058146778Ssam#ifdef WITH_USER 1059146778Ssam /* if run as root, prepare for dropping root privileges */ 1060146778Ssam if (getuid() == 0 || geteuid() == 0) { 1061146778Ssam /* Run with '-Z root' to restore old behaviour */ 1062146778Ssam if (!username) 1063146778Ssam username = WITH_USER; 1064146778Ssam } 1065146778Ssam#endif 1066146778Ssam 106717680Spst if (RFileName != NULL) { 1068127675Sbms int dlt; 1069127675Sbms const char *dlt_name; 1070127675Sbms 1071127675Sbms#ifndef WIN32 107217680Spst /* 1073127675Sbms * We don't need network access, so relinquish any set-UID 1074127675Sbms * or set-GID privileges we have (if any). 1075127675Sbms * 1076127675Sbms * We do *not* want set-UID privileges when opening a 1077127675Sbms * trace file, as that might let the user read other 1078127675Sbms * people's trace files (especially if we're set-UID 1079127675Sbms * root). 108017680Spst */ 1081146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) 1082146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 1083127675Sbms#endif /* WIN32 */ 108417680Spst pd = pcap_open_offline(RFileName, ebuf); 108517680Spst if (pd == NULL) 108626180Sfenner error("%s", ebuf); 1087127675Sbms dlt = pcap_datalink(pd); 1088127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1089127675Sbms if (dlt_name == NULL) { 1090127675Sbms fprintf(stderr, "reading from file %s, link-type %u\n", 1091127675Sbms RFileName, dlt); 1092127675Sbms } else { 1093127675Sbms fprintf(stderr, 1094127675Sbms "reading from file %s, link-type %s (%s)\n", 1095127675Sbms RFileName, dlt_name, 1096127675Sbms pcap_datalink_val_to_description(dlt)); 1097127675Sbms } 109817680Spst localnet = 0; 109917680Spst netmask = 0; 110017680Spst if (fflag != 0) 110117680Spst error("-f and -r options are incompatible"); 110217680Spst } else { 110317680Spst if (device == NULL) { 110417680Spst device = pcap_lookupdev(ebuf); 110517680Spst if (device == NULL) 110626180Sfenner error("%s", ebuf); 110717680Spst } 1108127675Sbms#ifdef WIN32 1109146778Ssam if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char 1110146778Ssam { //a Unicode string has a \0 as second byte (so strlen() is 1) 1111127675Sbms fprintf(stderr, "%s: listening on %ws\n", program_name, device); 1112127675Sbms } 1113127675Sbms else 1114127675Sbms { 1115127675Sbms fprintf(stderr, "%s: listening on %s\n", program_name, device); 1116127675Sbms } 1117127675Sbms 1118127675Sbms fflush(stderr); 1119127675Sbms#endif /* WIN32 */ 1120190207Srpaulo#ifdef HAVE_PCAP_CREATE 1121190207Srpaulo pd = pcap_create(device, ebuf); 1122190207Srpaulo if (pd == NULL) 1123190207Srpaulo error("%s", ebuf); 1124236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 1125236192Sdelphij if (Jflag) 1126236192Sdelphij show_tstamp_types_and_exit(device, pd); 1127236192Sdelphij#endif 1128214478Srpaulo /* 1129214478Srpaulo * Is this an interface that supports monitor mode? 1130214478Srpaulo */ 1131214478Srpaulo if (pcap_can_set_rfmon(pd) == 1) 1132214478Srpaulo supports_monitor_mode = 1; 1133214478Srpaulo else 1134214478Srpaulo supports_monitor_mode = 0; 1135190207Srpaulo status = pcap_set_snaplen(pd, snaplen); 1136190207Srpaulo if (status != 0) 1137236192Sdelphij error("%s: Can't set snapshot length: %s", 1138190207Srpaulo device, pcap_statustostr(status)); 1139190207Srpaulo status = pcap_set_promisc(pd, !pflag); 1140190207Srpaulo if (status != 0) 1141236192Sdelphij error("%s: Can't set promiscuous mode: %s", 1142190207Srpaulo device, pcap_statustostr(status)); 1143190207Srpaulo if (Iflag) { 1144190207Srpaulo status = pcap_set_rfmon(pd, 1); 1145190207Srpaulo if (status != 0) 1146236192Sdelphij error("%s: Can't set monitor mode: %s", 1147190207Srpaulo device, pcap_statustostr(status)); 1148190207Srpaulo } 1149190207Srpaulo status = pcap_set_timeout(pd, 1000); 1150190207Srpaulo if (status != 0) 1151190207Srpaulo error("%s: pcap_set_timeout failed: %s", 1152190207Srpaulo device, pcap_statustostr(status)); 1153190207Srpaulo if (Bflag != 0) { 1154190207Srpaulo status = pcap_set_buffer_size(pd, Bflag); 1155190207Srpaulo if (status != 0) 1156236192Sdelphij error("%s: Can't set buffer size: %s", 1157190207Srpaulo device, pcap_statustostr(status)); 1158190207Srpaulo } 1159236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 1160236192Sdelphij if (jflag != -1) { 1161236192Sdelphij status = pcap_set_tstamp_type(pd, jflag); 1162236192Sdelphij if (status < 0) 1163236192Sdelphij error("%s: Can't set time stamp type: %s", 1164236192Sdelphij device, pcap_statustostr(status)); 1165236192Sdelphij } 1166236192Sdelphij#endif 1167190207Srpaulo status = pcap_activate(pd); 1168190207Srpaulo if (status < 0) { 1169190207Srpaulo /* 1170190207Srpaulo * pcap_activate() failed. 1171190207Srpaulo */ 1172190207Srpaulo cp = pcap_geterr(pd); 1173190207Srpaulo if (status == PCAP_ERROR) 1174190207Srpaulo error("%s", cp); 1175190207Srpaulo else if ((status == PCAP_ERROR_NO_SUCH_DEVICE || 1176190207Srpaulo status == PCAP_ERROR_PERM_DENIED) && 1177190207Srpaulo *cp != '\0') 1178190207Srpaulo error("%s: %s\n(%s)", device, 1179190207Srpaulo pcap_statustostr(status), cp); 1180190207Srpaulo else 1181190207Srpaulo error("%s: %s", device, 1182190207Srpaulo pcap_statustostr(status)); 1183190207Srpaulo } else if (status > 0) { 1184190207Srpaulo /* 1185190207Srpaulo * pcap_activate() succeeded, but it's warning us 1186190207Srpaulo * of a problem it had. 1187190207Srpaulo */ 1188190207Srpaulo cp = pcap_geterr(pd); 1189190207Srpaulo if (status == PCAP_WARNING) 1190190207Srpaulo warning("%s", cp); 1191190207Srpaulo else if (status == PCAP_WARNING_PROMISC_NOTSUP && 1192190207Srpaulo *cp != '\0') 1193190207Srpaulo warning("%s: %s\n(%s)", device, 1194190207Srpaulo pcap_statustostr(status), cp); 1195190207Srpaulo else 1196190207Srpaulo warning("%s: %s", device, 1197190207Srpaulo pcap_statustostr(status)); 1198190207Srpaulo } 1199190207Srpaulo#else 120098527Sfenner *ebuf = '\0'; 120117680Spst pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 120217680Spst if (pd == NULL) 120326180Sfenner error("%s", ebuf); 120498527Sfenner else if (*ebuf) 120598527Sfenner warning("%s", ebuf); 1206190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 1207146778Ssam /* 1208146778Ssam * Let user own process after socket has been opened. 1209146778Ssam */ 1210146778Ssam#ifndef WIN32 1211146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0) 1212146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 1213146778Ssam#endif /* WIN32 */ 1214190207Srpaulo#if !defined(HAVE_PCAP_CREATE) && defined(WIN32) 1215190207Srpaulo if(Bflag != 0) 1216190207Srpaulo if(pcap_setbuff(pd, Bflag)==-1){ 1217146778Ssam error("%s", pcap_geterr(pd)); 1218146778Ssam } 1219190207Srpaulo#endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */ 1220127675Sbms if (Lflag) 1221214478Srpaulo show_dlts_and_exit(device, pd); 1222146778Ssam if (gndo->ndo_dlt >= 0) { 1223127675Sbms#ifdef HAVE_PCAP_SET_DATALINK 1224146778Ssam if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0) 1225109842Sfenner error("%s", pcap_geterr(pd)); 1226127675Sbms#else 1227127675Sbms /* 1228127675Sbms * We don't actually support changing the 1229127675Sbms * data link type, so we only let them 1230127675Sbms * set it to what it already is. 1231127675Sbms */ 1232146778Ssam if (gndo->ndo_dlt != pcap_datalink(pd)) { 1233127675Sbms error("%s is not one of the DLTs supported by this device\n", 1234146778Ssam gndo->ndo_dltname); 1235127675Sbms } 1236127675Sbms#endif 1237109842Sfenner (void)fprintf(stderr, "%s: data link type %s\n", 1238190207Srpaulo program_name, gndo->ndo_dltname); 1239109842Sfenner (void)fflush(stderr); 1240109842Sfenner } 124117680Spst i = pcap_snapshot(pd); 124217680Spst if (snaplen < i) { 124317680Spst warning("snaplen raised from %d to %d", snaplen, i); 124417680Spst snaplen = i; 124517680Spst } 124639297Sfenner if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 124739297Sfenner localnet = 0; 124839297Sfenner netmask = 0; 124939297Sfenner warning("%s", ebuf); 125039297Sfenner } 125117680Spst } 125217680Spst if (infile) 125317680Spst cmdbuf = read_infile(infile); 125417680Spst else 125517680Spst cmdbuf = copy_argv(&argv[optind]); 125617680Spst 125717680Spst if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 125826180Sfenner error("%s", pcap_geterr(pd)); 1259214478Srpaulo free(cmdbuf); 126017680Spst if (dflag) { 126117680Spst bpf_dump(&fcode, dflag); 1262127675Sbms pcap_close(pd); 126317680Spst exit(0); 126417680Spst } 126539297Sfenner init_addrtoname(localnet, netmask); 1266190207Srpaulo init_checksum(); 126717680Spst 1268127675Sbms#ifndef WIN32 1269127675Sbms (void)setsignal(SIGPIPE, cleanup); 127039297Sfenner (void)setsignal(SIGTERM, cleanup); 127139297Sfenner (void)setsignal(SIGINT, cleanup); 1272236192Sdelphij#endif /* WIN32 */ 1273236192Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 1274190207Srpaulo (void)setsignal(SIGCHLD, child_cleanup); 1275236192Sdelphij#endif 127639297Sfenner /* Cooperate with nohup(1) */ 1277127675Sbms#ifndef WIN32 127839297Sfenner if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 127939297Sfenner (void)setsignal(SIGHUP, oldhandler); 1280127675Sbms#endif /* WIN32 */ 128117680Spst 1282236192Sdelphij#ifndef WIN32 1283236192Sdelphij /* 1284236192Sdelphij * If a user name was specified with "-Z", attempt to switch to 1285236192Sdelphij * that user's UID. This would probably be used with sudo, 1286236192Sdelphij * to allow tcpdump to be run in a special restricted 1287236192Sdelphij * account (if you just want to allow users to open capture 1288236192Sdelphij * devices, and can't just give users that permission, 1289236192Sdelphij * you'd make tcpdump set-UID or set-GID). 1290236192Sdelphij * 1291236192Sdelphij * Tcpdump doesn't necessarily write only to one savefile; 1292236192Sdelphij * the general only way to allow a -Z instance to write to 1293236192Sdelphij * savefiles as the user under whose UID it's run, rather 1294236192Sdelphij * than as the user specified with -Z, would thus be to switch 1295236192Sdelphij * to the original user ID before opening a capture file and 1296236192Sdelphij * then switch back to the -Z user ID after opening the savefile. 1297236192Sdelphij * Switching to the -Z user ID only after opening the first 1298236192Sdelphij * savefile doesn't handle the general case. 1299236192Sdelphij */ 1300236192Sdelphij if (getuid() == 0 || geteuid() == 0) { 1301236192Sdelphij if (username || chroot_dir) 1302236192Sdelphij droproot(username, chroot_dir); 1303236192Sdelphij } 1304236192Sdelphij#endif /* WIN32 */ 1305236192Sdelphij 130617680Spst if (pcap_setfilter(pd, &fcode) < 0) 130726180Sfenner error("%s", pcap_geterr(pd)); 130817680Spst if (WFileName) { 1309146778Ssam pcap_dumper_t *p; 1310190207Srpaulo /* Do not exceed the default NAME_MAX for files. */ 1311190207Srpaulo dumpinfo.CurrentFileName = (char *)malloc(NAME_MAX + 1); 1312146778Ssam 1313190207Srpaulo if (dumpinfo.CurrentFileName == NULL) 1314190207Srpaulo error("malloc of dumpinfo.CurrentFileName"); 1315190207Srpaulo 1316190207Srpaulo /* We do not need numbering for dumpfiles if Cflag isn't set. */ 1317190207Srpaulo if (Cflag != 0) 1318190207Srpaulo MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); 1319190207Srpaulo else 1320190207Srpaulo MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); 1321190207Srpaulo 1322190207Srpaulo p = pcap_dump_open(pd, dumpinfo.CurrentFileName); 132317680Spst if (p == NULL) 132426180Sfenner error("%s", pcap_geterr(pd)); 1325190207Srpaulo if (Cflag != 0 || Gflag != 0) { 1326127675Sbms callback = dump_packet_and_trunc; 132798527Sfenner dumpinfo.WFileName = WFileName; 132898527Sfenner dumpinfo.pd = pd; 132998527Sfenner dumpinfo.p = p; 133098527Sfenner pcap_userdata = (u_char *)&dumpinfo; 133198527Sfenner } else { 1332127675Sbms callback = dump_packet; 133398527Sfenner pcap_userdata = (u_char *)p; 133498527Sfenner } 1335236192Sdelphij#ifdef HAVE_PCAP_DUMP_FLUSH 1336236192Sdelphij if (Uflag) 1337236192Sdelphij pcap_dump_flush(p); 1338236192Sdelphij#endif 133917680Spst } else { 1340127675Sbms type = pcap_datalink(pd); 1341214478Srpaulo printinfo.ndo_type = 1; 1342214478Srpaulo printinfo.ndo = gndo; 1343214478Srpaulo printinfo.p.ndo_printer = lookup_ndo_printer(type); 1344214478Srpaulo if (printinfo.p.ndo_printer == NULL) { 1345214478Srpaulo printinfo.p.printer = lookup_printer(type); 1346214478Srpaulo printinfo.ndo_type = 0; 1347214478Srpaulo if (printinfo.p.printer == NULL) { 1348214478Srpaulo gndo->ndo_dltname = pcap_datalink_val_to_name(type); 1349214478Srpaulo if (gndo->ndo_dltname != NULL) 1350214478Srpaulo error("packet printing is not supported for link type %s: use -w", 1351214478Srpaulo gndo->ndo_dltname); 1352214478Srpaulo else 1353214478Srpaulo error("packet printing is not supported for link type %d: use -w", type); 1354214478Srpaulo } 1355214478Srpaulo } 1356127675Sbms callback = print_packet; 1357127675Sbms pcap_userdata = (u_char *)&printinfo; 1358127675Sbms } 1359236192Sdelphij 1360242485Sdelphij#ifdef SIGNAL_REQ_INFO 1361190207Srpaulo /* 1362190207Srpaulo * We can't get statistics when reading from a file rather 1363190207Srpaulo * than capturing from a device. 1364190207Srpaulo */ 1365190207Srpaulo if (RFileName == NULL) 1366242485Sdelphij (void)setsignal(SIGNAL_REQ_INFO, requestinfo); 136798527Sfenner#endif 1368146778Ssam 1369146778Ssam if (vflag > 0 && WFileName) { 1370146778Ssam /* 1371146778Ssam * When capturing to a file, "-v" means tcpdump should, 1372146778Ssam * every 10 secodns, "v"erbosely report the number of 1373146778Ssam * packets captured. 1374146778Ssam */ 1375146778Ssam#ifdef USE_WIN32_MM_TIMER 1376146778Ssam /* call verbose_stats_dump() each 1000 +/-100msec */ 1377146778Ssam timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); 1378146778Ssam setvbuf(stderr, NULL, _IONBF, 0); 1379146778Ssam#elif defined(HAVE_ALARM) 1380146778Ssam (void)setsignal(SIGALRM, verbose_stats_dump); 1381146778Ssam alarm(1); 1382146778Ssam#endif 1383146778Ssam } 1384146778Ssam 1385127675Sbms#ifndef WIN32 138617680Spst if (RFileName == NULL) { 1387127675Sbms int dlt; 1388127675Sbms const char *dlt_name; 1389127675Sbms 1390127675Sbms if (!vflag && !WFileName) { 1391127675Sbms (void)fprintf(stderr, 1392127675Sbms "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", 1393127675Sbms program_name); 1394127675Sbms } else 1395127675Sbms (void)fprintf(stderr, "%s: ", program_name); 1396127675Sbms dlt = pcap_datalink(pd); 1397127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1398127675Sbms if (dlt_name == NULL) { 1399127675Sbms (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", 1400127675Sbms device, dlt, snaplen); 1401127675Sbms } else { 1402127675Sbms (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", 1403127675Sbms device, dlt_name, 1404127675Sbms pcap_datalink_val_to_description(dlt), snaplen); 1405127675Sbms } 140617680Spst (void)fflush(stderr); 140717680Spst } 1408127675Sbms#endif /* WIN32 */ 1409127675Sbms status = pcap_loop(pd, cnt, callback, pcap_userdata); 1410127675Sbms if (WFileName == NULL) { 1411127675Sbms /* 1412127675Sbms * We're printing packets. Flush the printed output, 1413127675Sbms * so it doesn't get intermingled with error output. 1414127675Sbms */ 1415127675Sbms if (status == -2) { 1416127675Sbms /* 1417127675Sbms * We got interrupted, so perhaps we didn't 1418127675Sbms * manage to finish a line we were printing. 1419127675Sbms * Print an extra newline, just in case. 1420127675Sbms */ 1421127675Sbms putchar('\n'); 1422127675Sbms } 1423127675Sbms (void)fflush(stdout); 1424127675Sbms } 1425127675Sbms if (status == -1) { 1426127675Sbms /* 1427127675Sbms * Error. Report it. 1428127675Sbms */ 142917680Spst (void)fprintf(stderr, "%s: pcap_loop: %s\n", 143017680Spst program_name, pcap_geterr(pd)); 143117680Spst } 1432127675Sbms if (RFileName == NULL) { 1433127675Sbms /* 1434127675Sbms * We're doing a live capture. Report the capture 1435127675Sbms * statistics. 1436127675Sbms */ 143798527Sfenner info(1); 1438127675Sbms } 143917680Spst pcap_close(pd); 1440127675Sbms exit(status == -1 ? 1 : 0); 144117680Spst} 144217680Spst 144317680Spst/* make a clean exit on interrupts */ 144475118Sfennerstatic RETSIGTYPE 1445127675Sbmscleanup(int signo _U_) 144617680Spst{ 1447146778Ssam#ifdef USE_WIN32_MM_TIMER 1448146778Ssam if (timer_id) 1449146778Ssam timeKillEvent(timer_id); 1450146778Ssam timer_id = 0; 1451146778Ssam#elif defined(HAVE_ALARM) 1452146778Ssam alarm(0); 1453146778Ssam#endif 1454146778Ssam 1455127675Sbms#ifdef HAVE_PCAP_BREAKLOOP 1456127675Sbms /* 1457127675Sbms * We have "pcap_breakloop()"; use it, so that we do as little 1458127675Sbms * as possible in the signal handler (it's probably not safe 1459127675Sbms * to do anything with standard I/O streams in a signal handler - 1460127675Sbms * the ANSI C standard doesn't say it is). 1461127675Sbms */ 1462127675Sbms pcap_breakloop(pd); 1463127675Sbms#else 1464127675Sbms /* 1465127675Sbms * We don't have "pcap_breakloop()"; this isn't safe, but 1466127675Sbms * it's the best we can do. Print the summary if we're 1467127675Sbms * not reading from a savefile - i.e., if we're doing a 1468127675Sbms * live capture - and exit. 1469127675Sbms */ 147017680Spst if (pd != NULL && pcap_file(pd) == NULL) { 1471127675Sbms /* 1472127675Sbms * We got interrupted, so perhaps we didn't 1473127675Sbms * manage to finish a line we were printing. 1474127675Sbms * Print an extra newline, just in case. 1475127675Sbms */ 1476127675Sbms putchar('\n'); 147717680Spst (void)fflush(stdout); 147898527Sfenner info(1); 147917680Spst } 148017680Spst exit(0); 1481127675Sbms#endif 148217680Spst} 148317680Spst 1484190207Srpaulo/* 1485190207Srpaulo On windows, we do not use a fork, so we do not care less about 1486190207Srpaulo waiting a child processes to die 1487190207Srpaulo */ 1488236192Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 1489190207Srpaulostatic RETSIGTYPE 1490190207Srpaulochild_cleanup(int signo _U_) 1491190207Srpaulo{ 1492190207Srpaulo wait(NULL); 1493190207Srpaulo} 1494236192Sdelphij#endif /* HAVE_FORK && HAVE_VFORK */ 1495190207Srpaulo 1496127675Sbmsstatic void 149798527Sfennerinfo(register int verbose) 149898527Sfenner{ 149998527Sfenner struct pcap_stat stat; 150098527Sfenner 1501214478Srpaulo /* 1502214478Srpaulo * Older versions of libpcap didn't set ps_ifdrop on some 1503214478Srpaulo * platforms; initialize it to 0 to handle that. 1504214478Srpaulo */ 1505214478Srpaulo stat.ps_ifdrop = 0; 150698527Sfenner if (pcap_stats(pd, &stat) < 0) { 150798527Sfenner (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); 1508173819Smlaier infoprint = 0; 150998527Sfenner return; 151098527Sfenner } 1511127675Sbms 151298527Sfenner if (!verbose) 151398527Sfenner fprintf(stderr, "%s: ", program_name); 1514127675Sbms 1515236192Sdelphij (void)fprintf(stderr, "%u packet%s captured", packets_captured, 1516236192Sdelphij PLURAL_SUFFIX(packets_captured)); 1517127675Sbms if (!verbose) 1518127675Sbms fputs(", ", stderr); 1519127675Sbms else 1520127675Sbms putc('\n', stderr); 1521236192Sdelphij (void)fprintf(stderr, "%u packet%s received by filter", stat.ps_recv, 1522236192Sdelphij PLURAL_SUFFIX(stat.ps_recv)); 152398527Sfenner if (!verbose) 152498527Sfenner fputs(", ", stderr); 152598527Sfenner else 152698527Sfenner putc('\n', stderr); 1527236192Sdelphij (void)fprintf(stderr, "%u packet%s dropped by kernel", stat.ps_drop, 1528236192Sdelphij PLURAL_SUFFIX(stat.ps_drop)); 1529214478Srpaulo if (stat.ps_ifdrop != 0) { 1530214478Srpaulo if (!verbose) 1531214478Srpaulo fputs(", ", stderr); 1532214478Srpaulo else 1533214478Srpaulo putc('\n', stderr); 1534236192Sdelphij (void)fprintf(stderr, "%u packet%s dropped by interface\n", 1535236192Sdelphij stat.ps_ifdrop, PLURAL_SUFFIX(stat.ps_ifdrop)); 1536214478Srpaulo } else 1537214478Srpaulo putc('\n', stderr); 153898527Sfenner infoprint = 0; 153998527Sfenner} 154098527Sfenner 1541236192Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 154298527Sfennerstatic void 1543190207Srpaulocompress_savefile(const char *filename) 1544190207Srpaulo{ 1545236192Sdelphij# ifdef HAVE_FORK 1546190207Srpaulo if (fork()) 1547236192Sdelphij# else 1548236192Sdelphij if (vfork()) 1549236192Sdelphij# endif 1550190207Srpaulo return; 1551190207Srpaulo /* 1552190207Srpaulo * Set to lowest priority so that this doesn't disturb the capture 1553190207Srpaulo */ 1554190207Srpaulo#ifdef NZERO 1555190207Srpaulo setpriority(PRIO_PROCESS, 0, NZERO - 1); 1556190207Srpaulo#else 1557190207Srpaulo setpriority(PRIO_PROCESS, 0, 19); 1558190207Srpaulo#endif 1559214478Srpaulo if (execlp(zflag, zflag, filename, (char *)NULL) == -1) 1560190207Srpaulo fprintf(stderr, 1561190207Srpaulo "compress_savefile:execlp(%s, %s): %s\n", 1562190207Srpaulo zflag, 1563190207Srpaulo filename, 1564190207Srpaulo strerror(errno)); 1565236192Sdelphij# ifdef HAVE_FORK 1566236192Sdelphij exit(1); 1567236192Sdelphij# else 1568236192Sdelphij _exit(1); 1569236192Sdelphij# endif 1570190207Srpaulo} 1571236192Sdelphij#else /* HAVE_FORK && HAVE_VFORK */ 1572190207Srpaulostatic void 1573190207Srpaulocompress_savefile(const char *filename) 1574190207Srpaulo{ 1575190207Srpaulo fprintf(stderr, 1576236192Sdelphij "compress_savefile failed. Functionality not implemented under your system\n"); 1577190207Srpaulo} 1578236192Sdelphij#endif /* HAVE_FORK && HAVE_VFORK */ 1579190207Srpaulo 1580190207Srpaulostatic void 1581127675Sbmsdump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 158298527Sfenner{ 1583127675Sbms struct dump_info *dump_info; 158498527Sfenner 1585127675Sbms ++packets_captured; 1586127675Sbms 1587127675Sbms ++infodelay; 1588127675Sbms 1589127675Sbms dump_info = (struct dump_info *)user; 1590127675Sbms 159198527Sfenner /* 1592190207Srpaulo * XXX - this won't force the file to rotate on the specified time 1593190207Srpaulo * boundary, but it will rotate on the first packet received after the 1594190207Srpaulo * specified Gflag number of seconds. Note: if a Gflag time boundary 1595190207Srpaulo * and a Cflag size boundary coincide, the time rotation will occur 1596190207Srpaulo * first thereby cancelling the Cflag boundary (since the file should 1597190207Srpaulo * be 0). 1598190207Srpaulo */ 1599190207Srpaulo if (Gflag != 0) { 1600190207Srpaulo /* Check if it is time to rotate */ 1601190207Srpaulo time_t t; 1602190207Srpaulo 1603190207Srpaulo /* Get the current time */ 1604190207Srpaulo if ((t = time(NULL)) == (time_t)-1) { 1605190207Srpaulo error("dump_and_trunc_packet: can't get current_time: %s", 1606190207Srpaulo pcap_strerror(errno)); 1607190207Srpaulo } 1608190207Srpaulo 1609190207Srpaulo 1610190207Srpaulo /* If the time is greater than the specified window, rotate */ 1611190207Srpaulo if (t - Gflag_time >= Gflag) { 1612190207Srpaulo /* Update the Gflag_time */ 1613190207Srpaulo Gflag_time = t; 1614190207Srpaulo /* Update Gflag_count */ 1615190207Srpaulo Gflag_count++; 1616190207Srpaulo /* 1617190207Srpaulo * Close the current file and open a new one. 1618190207Srpaulo */ 1619190207Srpaulo pcap_dump_close(dump_info->p); 1620190207Srpaulo 1621190207Srpaulo /* 1622190207Srpaulo * Compress the file we just closed, if the user asked for it 1623190207Srpaulo */ 1624190207Srpaulo if (zflag != NULL) 1625190207Srpaulo compress_savefile(dump_info->CurrentFileName); 1626190207Srpaulo 1627190207Srpaulo /* 1628190207Srpaulo * Check to see if we've exceeded the Wflag (when 1629190207Srpaulo * not using Cflag). 1630190207Srpaulo */ 1631190207Srpaulo if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) { 1632190207Srpaulo (void)fprintf(stderr, "Maximum file limit reached: %d\n", 1633190207Srpaulo Wflag); 1634190207Srpaulo exit(0); 1635190207Srpaulo /* NOTREACHED */ 1636190207Srpaulo } 1637190207Srpaulo if (dump_info->CurrentFileName != NULL) 1638190207Srpaulo free(dump_info->CurrentFileName); 1639190207Srpaulo /* Allocate space for max filename + \0. */ 1640190207Srpaulo dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1); 1641190207Srpaulo if (dump_info->CurrentFileName == NULL) 1642190207Srpaulo error("dump_packet_and_trunc: malloc"); 1643190207Srpaulo /* 1644190207Srpaulo * This is always the first file in the Cflag 1645190207Srpaulo * rotation: e.g. 0 1646190207Srpaulo * We also don't need numbering if Cflag is not set. 1647190207Srpaulo */ 1648190207Srpaulo if (Cflag != 0) 1649190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 1650190207Srpaulo WflagChars); 1651190207Srpaulo else 1652190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); 1653190207Srpaulo 1654190207Srpaulo dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); 1655190207Srpaulo if (dump_info->p == NULL) 1656190207Srpaulo error("%s", pcap_geterr(pd)); 1657190207Srpaulo } 1658190207Srpaulo } 1659190207Srpaulo 1660190207Srpaulo /* 166198527Sfenner * XXX - this won't prevent capture files from getting 166298527Sfenner * larger than Cflag - the last packet written to the 166398527Sfenner * file could put it over Cflag. 166498527Sfenner */ 1665190207Srpaulo if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { 1666127675Sbms /* 1667127675Sbms * Close the current file and open a new one. 1668127675Sbms */ 1669127675Sbms pcap_dump_close(dump_info->p); 1670190207Srpaulo 1671190207Srpaulo /* 1672190207Srpaulo * Compress the file we just closed, if the user asked for it 1673190207Srpaulo */ 1674190207Srpaulo if (zflag != NULL) 1675190207Srpaulo compress_savefile(dump_info->CurrentFileName); 1676190207Srpaulo 1677146778Ssam Cflag_count++; 1678146778Ssam if (Wflag > 0) { 1679146778Ssam if (Cflag_count >= Wflag) 1680146778Ssam Cflag_count = 0; 1681146778Ssam } 1682190207Srpaulo if (dump_info->CurrentFileName != NULL) 1683190207Srpaulo free(dump_info->CurrentFileName); 1684190207Srpaulo dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1); 1685190207Srpaulo if (dump_info->CurrentFileName == NULL) 1686127675Sbms error("dump_packet_and_trunc: malloc"); 1687190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); 1688190207Srpaulo dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); 1689127675Sbms if (dump_info->p == NULL) 169098527Sfenner error("%s", pcap_geterr(pd)); 169198527Sfenner } 169298527Sfenner 1693127675Sbms pcap_dump((u_char *)dump_info->p, h, sp); 1694127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1695127675Sbms if (Uflag) 1696127675Sbms pcap_dump_flush(dump_info->p); 1697127675Sbms#endif 1698127675Sbms 1699127675Sbms --infodelay; 1700127675Sbms if (infoprint) 1701127675Sbms info(0); 170298527Sfenner} 170398527Sfenner 1704127675Sbmsstatic void 1705127675Sbmsdump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 170617680Spst{ 1707127675Sbms ++packets_captured; 170817680Spst 1709127675Sbms ++infodelay; 1710127675Sbms 1711127675Sbms pcap_dump(user, h, sp); 1712127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1713127675Sbms if (Uflag) 1714127675Sbms pcap_dump_flush((pcap_dumper_t *)user); 1715127675Sbms#endif 1716127675Sbms 1717127675Sbms --infodelay; 1718127675Sbms if (infoprint) 1719127675Sbms info(0); 1720127675Sbms} 1721127675Sbms 1722127675Sbmsstatic void 1723127675Sbmsprint_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 1724127675Sbms{ 1725127675Sbms struct print_info *print_info; 1726127675Sbms u_int hdrlen; 1727127675Sbms 1728127675Sbms ++packets_captured; 1729127675Sbms 1730127675Sbms ++infodelay; 1731127675Sbms ts_print(&h->ts); 1732127675Sbms 1733127675Sbms print_info = (struct print_info *)user; 1734127675Sbms 1735127675Sbms /* 1736127675Sbms * Some printers want to check that they're not walking off the 1737127675Sbms * end of the packet. 1738127675Sbms * Rather than pass it all the way down, we set this global. 1739127675Sbms */ 1740127675Sbms snapend = sp + h->caplen; 1741127675Sbms 1742214478Srpaulo if(print_info->ndo_type) { 1743214478Srpaulo hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp); 1744214478Srpaulo } else { 1745214478Srpaulo hdrlen = (*print_info->p.printer)(h, sp); 1746214478Srpaulo } 1747214478Srpaulo 1748162021Ssam if (Xflag) { 1749127675Sbms /* 1750162021Ssam * Print the raw packet data in hex and ASCII. 1751127675Sbms */ 1752162021Ssam if (Xflag > 1) { 1753162021Ssam /* 1754162021Ssam * Include the link-layer header. 1755162021Ssam */ 1756162021Ssam hex_and_ascii_print("\n\t", sp, h->caplen); 1757162021Ssam } else { 1758162021Ssam /* 1759162021Ssam * Don't include the link-layer header - and if 1760162021Ssam * we have nothing past the link-layer header, 1761162021Ssam * print nothing. 1762162021Ssam */ 1763162021Ssam if (h->caplen > hdrlen) 1764162021Ssam hex_and_ascii_print("\n\t", sp + hdrlen, 1765162021Ssam h->caplen - hdrlen); 1766162021Ssam } 1767162021Ssam } else if (xflag) { 1768162021Ssam /* 1769162021Ssam * Print the raw packet data in hex. 1770162021Ssam */ 1771127675Sbms if (xflag > 1) { 1772127675Sbms /* 1773127675Sbms * Include the link-layer header. 1774127675Sbms */ 1775146778Ssam hex_print("\n\t", sp, h->caplen); 1776127675Sbms } else { 1777127675Sbms /* 1778127675Sbms * Don't include the link-layer header - and if 1779127675Sbms * we have nothing past the link-layer header, 1780127675Sbms * print nothing. 1781127675Sbms */ 1782127675Sbms if (h->caplen > hdrlen) 1783146778Ssam hex_print("\n\t", sp + hdrlen, 1784127675Sbms h->caplen - hdrlen); 1785127675Sbms } 1786162021Ssam } else if (Aflag) { 1787146778Ssam /* 1788162021Ssam * Print the raw packet data in ASCII. 1789146778Ssam */ 1790162021Ssam if (Aflag > 1) { 1791146778Ssam /* 1792146778Ssam * Include the link-layer header. 1793146778Ssam */ 1794162021Ssam ascii_print(sp, h->caplen); 1795146778Ssam } else { 1796146778Ssam /* 1797146778Ssam * Don't include the link-layer header - and if 1798146778Ssam * we have nothing past the link-layer header, 1799146778Ssam * print nothing. 1800146778Ssam */ 1801146778Ssam if (h->caplen > hdrlen) 1802162021Ssam ascii_print(sp + hdrlen, h->caplen - hdrlen); 1803146778Ssam } 180417680Spst } 1805127675Sbms 1806127675Sbms putchar('\n'); 1807127675Sbms 1808127675Sbms --infodelay; 1809127675Sbms if (infoprint) 1810127675Sbms info(0); 181117680Spst} 181217680Spst 1813127675Sbms#ifdef WIN32 1814127675Sbms /* 1815127675Sbms * XXX - there should really be libpcap calls to get the version 1816127675Sbms * number as a string (the string would be generated from #defines 1817127675Sbms * at run time, so that it's not generated from string constants 1818127675Sbms * in the library, as, on many UNIX systems, those constants would 1819127675Sbms * be statically linked into the application executable image, and 1820127675Sbms * would thus reflect the version of libpcap on the system on 1821127675Sbms * which the application was *linked*, not the system on which it's 1822127675Sbms * *running*. 1823127675Sbms * 1824127675Sbms * That routine should be documented, unlike the "version[]" 1825127675Sbms * string, so that UNIX vendors providing their own libpcaps 1826127675Sbms * don't omit it (as a couple of vendors have...). 1827127675Sbms * 1828127675Sbms * Packet.dll should perhaps also export a routine to return the 1829127675Sbms * version number of the Packet.dll code, to supply the 1830127675Sbms * "Wpcap_version" information on Windows. 1831127675Sbms */ 1832127675Sbms char WDversion[]="current-cvs.tcpdump.org"; 1833146778Ssam#if !defined(HAVE_GENERATED_VERSION) 1834127675Sbms char version[]="current-cvs.tcpdump.org"; 1835146778Ssam#endif 1836127675Sbms char pcap_version[]="current-cvs.tcpdump.org"; 1837146778Ssam char Wpcap_version[]="3.1"; 1838127675Sbms#endif 1839127675Sbms 184039297Sfenner/* 1841162021Ssam * By default, print the specified data out in hex and ASCII. 184239297Sfenner */ 1843146778Ssamstatic void 1844146778Ssamndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length) 1845146778Ssam{ 1846162021Ssam hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */ 1847146778Ssam} 1848146778Ssam 184917680Spstvoid 1850146778Ssamdefault_print(const u_char *bp, u_int length) 185117680Spst{ 1852146778Ssam ndo_default_print(gndo, bp, length); 185317680Spst} 185417680Spst 1855242485Sdelphij#ifdef SIGNAL_REQ_INFO 1856127675SbmsRETSIGTYPE requestinfo(int signo _U_) 185798527Sfenner{ 185898527Sfenner if (infodelay) 185998527Sfenner ++infoprint; 186098527Sfenner else 186198527Sfenner info(0); 186298527Sfenner} 186398527Sfenner#endif 186498527Sfenner 1865146778Ssam/* 1866146778Ssam * Called once each second in verbose mode while dumping to file 1867146778Ssam */ 1868146778Ssam#ifdef USE_WIN32_MM_TIMER 1869146778Ssamvoid CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, 1870190207Srpaulo DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) 1871146778Ssam{ 1872146778Ssam struct pcap_stat stat; 1873146778Ssam 1874146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1875146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 1876146778Ssam} 1877146778Ssam#elif defined(HAVE_ALARM) 1878146778Ssamstatic void verbose_stats_dump(int sig _U_) 1879146778Ssam{ 1880146778Ssam struct pcap_stat stat; 1881146778Ssam 1882146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1883146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 1884146778Ssam alarm(1); 1885146778Ssam} 1886146778Ssam#endif 1887146778Ssam 188875118Sfennerstatic void 188926180Sfennerusage(void) 189017680Spst{ 189117680Spst extern char version[]; 1892127675Sbms#ifndef HAVE_PCAP_LIB_VERSION 1893127675Sbms#if defined(WIN32) || defined(HAVE_PCAP_VERSION) 189439297Sfenner extern char pcap_version[]; 1895127675Sbms#else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1896127675Sbms static char pcap_version[] = "unknown"; 1897127675Sbms#endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1898127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 189917680Spst 1900127675Sbms#ifdef HAVE_PCAP_LIB_VERSION 1901146778Ssam#ifdef WIN32 1902146778Ssam (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1903146778Ssam#else /* WIN32 */ 190439297Sfenner (void)fprintf(stderr, "%s version %s\n", program_name, version); 1905146778Ssam#endif /* WIN32 */ 1906146778Ssam (void)fprintf(stderr, "%s\n",pcap_lib_version()); 1907127675Sbms#else /* HAVE_PCAP_LIB_VERSION */ 1908127675Sbms#ifdef WIN32 1909127675Sbms (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1910127675Sbms (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); 1911127675Sbms#else /* WIN32 */ 1912127675Sbms (void)fprintf(stderr, "%s version %s\n", program_name, version); 191339297Sfenner (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 1914127675Sbms#endif /* WIN32 */ 1915127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 191617680Spst (void)fprintf(stderr, 1917236192Sdelphij"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); 191817680Spst (void)fprintf(stderr, 1919190207Srpaulo"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); 192017680Spst (void)fprintf(stderr, 1921236192Sdelphij"\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ]\n"); 1922109842Sfenner (void)fprintf(stderr, 1923236192Sdelphij"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n"); 1924146778Ssam (void)fprintf(stderr, 1925236192Sdelphij"\t\t[ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); 1926190207Srpaulo (void)fprintf(stderr, 1927236192Sdelphij"\t\t[ -Z user ] [ expression ]\n"); 192898527Sfenner exit(1); 192917680Spst} 1930146778Ssam 1931146778Ssam 1932146778Ssam 1933146778Ssam/* VARARGS */ 1934146778Ssamstatic void 1935146778Ssamndo_error(netdissect_options *ndo _U_, const char *fmt, ...) 1936146778Ssam{ 1937146778Ssam va_list ap; 1938146778Ssam 1939146778Ssam (void)fprintf(stderr, "%s: ", program_name); 1940146778Ssam va_start(ap, fmt); 1941146778Ssam (void)vfprintf(stderr, fmt, ap); 1942146778Ssam va_end(ap); 1943146778Ssam if (*fmt) { 1944146778Ssam fmt += strlen(fmt); 1945146778Ssam if (fmt[-1] != '\n') 1946146778Ssam (void)fputc('\n', stderr); 1947146778Ssam } 1948146778Ssam exit(1); 1949146778Ssam /* NOTREACHED */ 1950146778Ssam} 1951146778Ssam 1952146778Ssam/* VARARGS */ 1953146778Ssamstatic void 1954146778Ssamndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) 1955146778Ssam{ 1956146778Ssam va_list ap; 1957146778Ssam 1958146778Ssam (void)fprintf(stderr, "%s: WARNING: ", program_name); 1959146778Ssam va_start(ap, fmt); 1960146778Ssam (void)vfprintf(stderr, fmt, ap); 1961146778Ssam va_end(ap); 1962146778Ssam if (*fmt) { 1963146778Ssam fmt += strlen(fmt); 1964146778Ssam if (fmt[-1] != '\n') 1965146778Ssam (void)fputc('\n', stderr); 1966146778Ssam } 1967146778Ssam} 1968