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$ */ 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 79252283Sdelphij/* capabilities convinience library */ 80252283Sdelphij#ifdef HAVE_CAP_NG_H 81252283Sdelphij#include <cap-ng.h> 82252283Sdelphij#endif /* HAVE_CAP_NG_H */ 83190207Srpaulo 84146778Ssam#include "netdissect.h" 8517680Spst#include "interface.h" 8617680Spst#include "addrtoname.h" 8717680Spst#include "machdep.h" 8839297Sfenner#include "setsignal.h" 8939297Sfenner#include "gmt2local.h" 90127675Sbms#include "pcap-missing.h" 9117680Spst 92252283Sdelphij#ifndef PATH_MAX 93252283Sdelphij#define PATH_MAX 1024 94190207Srpaulo#endif 95190207Srpaulo 96242485Sdelphij#ifdef SIGINFO 97242485Sdelphij#define SIGNAL_REQ_INFO SIGINFO 98242485Sdelphij#elif SIGUSR1 99242485Sdelphij#define SIGNAL_REQ_INFO SIGUSR1 100242485Sdelphij#endif 101242485Sdelphij 102146778Ssamnetdissect_options Gndo; 103146778Ssamnetdissect_options *gndo = &Gndo; 104146778Ssam 105214478Srpaulostatic int dflag; /* print filter code */ 106214478Srpaulostatic int Lflag; /* list available data link types and exit */ 107236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 108236192Sdelphijstatic int Jflag; /* list available time stamp types */ 109236192Sdelphij#endif 110214478Srpaulostatic char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ 11139297Sfenner 112127675Sbmsstatic int infodelay; 113127675Sbmsstatic int infoprint; 11417680Spst 11517680Spstchar *program_name; 11617680Spst 11717680Spstint32_t thiszone; /* seconds offset from gmt to local time */ 11817680Spst 11917680Spst/* Forwards */ 12075118Sfennerstatic RETSIGTYPE cleanup(int); 121190207Srpaulostatic RETSIGTYPE child_cleanup(int); 12275118Sfennerstatic void usage(void) __attribute__((noreturn)); 123214478Srpaulostatic void show_dlts_and_exit(const char *device, pcap_t *pd) __attribute__((noreturn)); 12417680Spst 125127675Sbmsstatic void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 126146778Ssamstatic void ndo_default_print(netdissect_options *, const u_char *, u_int); 127127675Sbmsstatic void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); 128127675Sbmsstatic void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 129146778Ssamstatic void droproot(const char *, const char *); 130236192Sdelphijstatic void ndo_error(netdissect_options *ndo, const char *fmt, ...) 131236192Sdelphij __attribute__ ((noreturn, format (printf, 2, 3))); 132146778Ssamstatic void ndo_warning(netdissect_options *ndo, const char *fmt, ...); 13398527Sfenner 134242485Sdelphij#ifdef SIGNAL_REQ_INFO 13598527SfennerRETSIGTYPE requestinfo(int); 13698527Sfenner#endif 13798527Sfenner 138146778Ssam#if defined(USE_WIN32_MM_TIMER) 139146778Ssam #include <MMsystem.h> 140146778Ssam static UINT timer_id; 141146778Ssam static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); 142146778Ssam#elif defined(HAVE_ALARM) 143146778Ssam static void verbose_stats_dump(int sig); 144146778Ssam#endif 145146778Ssam 146127675Sbmsstatic void info(int); 147127675Sbmsstatic u_int packets_captured; 148127675Sbms 14917680Spststruct printer { 150214478Srpaulo if_printer f; 15117680Spst int type; 15217680Spst}; 15317680Spst 154214478Srpaulo 155214478Srpaulostruct ndo_printer { 156214478Srpaulo if_ndo_printer f; 157214478Srpaulo int type; 158214478Srpaulo}; 159214478Srpaulo 160214478Srpaulo 16117680Spststatic struct printer printers[] = { 16298527Sfenner { arcnet_if_print, DLT_ARCNET }, 163127675Sbms#ifdef DLT_ARCNET_LINUX 164127675Sbms { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 165127675Sbms#endif 16644165Sjulian { token_if_print, DLT_IEEE802 }, 16756896Sfenner#ifdef DLT_LANE8023 16856896Sfenner { lane_if_print, DLT_LANE8023 }, 16956896Sfenner#endif 17056896Sfenner#ifdef DLT_CIP 17156896Sfenner { cip_if_print, DLT_CIP }, 17256896Sfenner#endif 17375118Sfenner#ifdef DLT_ATM_CLIP 174214478Srpaulo { cip_if_print, DLT_ATM_CLIP }, 17575118Sfenner#endif 17617680Spst { sl_if_print, DLT_SLIP }, 177127675Sbms#ifdef DLT_SLIP_BSDOS 17839297Sfenner { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 179127675Sbms#endif 18017680Spst { ppp_if_print, DLT_PPP }, 181146778Ssam#ifdef DLT_PPP_WITHDIRECTION 182146778Ssam { ppp_if_print, DLT_PPP_WITHDIRECTION }, 183146778Ssam#endif 184127675Sbms#ifdef DLT_PPP_BSDOS 18539297Sfenner { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 186127675Sbms#endif 18717680Spst { fddi_if_print, DLT_FDDI }, 18817680Spst { null_if_print, DLT_NULL }, 18975118Sfenner#ifdef DLT_LOOP 19075118Sfenner { null_if_print, DLT_LOOP }, 19175118Sfenner#endif 19239297Sfenner { raw_if_print, DLT_RAW }, 19317680Spst { atm_if_print, DLT_ATM_RFC1483 }, 19475118Sfenner#ifdef DLT_C_HDLC 19575118Sfenner { chdlc_if_print, DLT_C_HDLC }, 19656896Sfenner#endif 19798527Sfenner#ifdef DLT_HDLC 19898527Sfenner { chdlc_if_print, DLT_HDLC }, 19998527Sfenner#endif 20075118Sfenner#ifdef DLT_PPP_SERIAL 201214478Srpaulo { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 20275118Sfenner#endif 20398527Sfenner#ifdef DLT_PPP_ETHER 20498527Sfenner { pppoe_if_print, DLT_PPP_ETHER }, 20598527Sfenner#endif 20675118Sfenner#ifdef DLT_LINUX_SLL 20775118Sfenner { sll_if_print, DLT_LINUX_SLL }, 20875118Sfenner#endif 20998527Sfenner#ifdef DLT_IEEE802_11 21098527Sfenner { ieee802_11_if_print, DLT_IEEE802_11}, 21198527Sfenner#endif 21298527Sfenner#ifdef DLT_LTALK 21398527Sfenner { ltalk_if_print, DLT_LTALK }, 21498527Sfenner#endif 215172686Smlaier#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) 216214478Srpaulo { pflog_if_print, DLT_PFLOG }, 217127675Sbms#endif 218127675Sbms#ifdef DLT_FR 219127675Sbms { fr_if_print, DLT_FR }, 220127675Sbms#endif 221127675Sbms#ifdef DLT_FRELAY 222127675Sbms { fr_if_print, DLT_FRELAY }, 223127675Sbms#endif 224127675Sbms#ifdef DLT_SUNATM 225127675Sbms { sunatm_if_print, DLT_SUNATM }, 226127675Sbms#endif 227127675Sbms#ifdef DLT_IP_OVER_FC 228127675Sbms { ipfc_if_print, DLT_IP_OVER_FC }, 229127675Sbms#endif 230127675Sbms#ifdef DLT_PRISM_HEADER 231127675Sbms { prism_if_print, DLT_PRISM_HEADER }, 232127675Sbms#endif 233127675Sbms#ifdef DLT_IEEE802_11_RADIO 234127675Sbms { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 235127675Sbms#endif 236127675Sbms#ifdef DLT_ENC 237214478Srpaulo { enc_if_print, DLT_ENC }, 238127675Sbms#endif 239146778Ssam#ifdef DLT_SYMANTEC_FIREWALL 240214478Srpaulo { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 241146778Ssam#endif 242127675Sbms#ifdef DLT_APPLE_IP_OVER_IEEE1394 243127675Sbms { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 244127675Sbms#endif 245190207Srpaulo#ifdef DLT_IEEE802_11_RADIO_AVS 246190207Srpaulo { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, 247190207Srpaulo#endif 248146778Ssam#ifdef DLT_JUNIPER_ATM1 249146778Ssam { juniper_atm1_print, DLT_JUNIPER_ATM1 }, 250146778Ssam#endif 251146778Ssam#ifdef DLT_JUNIPER_ATM2 252146778Ssam { juniper_atm2_print, DLT_JUNIPER_ATM2 }, 253146778Ssam#endif 254147904Ssam#ifdef DLT_JUNIPER_MFR 255147904Ssam { juniper_mfr_print, DLT_JUNIPER_MFR }, 256147904Ssam#endif 257146778Ssam#ifdef DLT_JUNIPER_MLFR 258146778Ssam { juniper_mlfr_print, DLT_JUNIPER_MLFR }, 259146778Ssam#endif 260146778Ssam#ifdef DLT_JUNIPER_MLPPP 261146778Ssam { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, 262146778Ssam#endif 263147904Ssam#ifdef DLT_JUNIPER_PPPOE 264147904Ssam { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, 265147904Ssam#endif 266147904Ssam#ifdef DLT_JUNIPER_PPPOE_ATM 267147904Ssam { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, 268147904Ssam#endif 269147904Ssam#ifdef DLT_JUNIPER_GGSN 270147904Ssam { juniper_ggsn_print, DLT_JUNIPER_GGSN }, 271147904Ssam#endif 272147904Ssam#ifdef DLT_JUNIPER_ES 273147904Ssam { juniper_es_print, DLT_JUNIPER_ES }, 274147904Ssam#endif 275147904Ssam#ifdef DLT_JUNIPER_MONITOR 276147904Ssam { juniper_monitor_print, DLT_JUNIPER_MONITOR }, 277147904Ssam#endif 278147904Ssam#ifdef DLT_JUNIPER_SERVICES 279147904Ssam { juniper_services_print, DLT_JUNIPER_SERVICES }, 280147904Ssam#endif 281162021Ssam#ifdef DLT_JUNIPER_ETHER 282214478Srpaulo { juniper_ether_print, DLT_JUNIPER_ETHER }, 283162021Ssam#endif 284162021Ssam#ifdef DLT_JUNIPER_PPP 285214478Srpaulo { juniper_ppp_print, DLT_JUNIPER_PPP }, 286162021Ssam#endif 287162021Ssam#ifdef DLT_JUNIPER_FRELAY 288214478Srpaulo { juniper_frelay_print, DLT_JUNIPER_FRELAY }, 289162021Ssam#endif 290162021Ssam#ifdef DLT_JUNIPER_CHDLC 291214478Srpaulo { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, 292162021Ssam#endif 293172686Smlaier#ifdef DLT_MFR 294214478Srpaulo { mfr_if_print, DLT_MFR }, 295172686Smlaier#endif 296190207Srpaulo#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) 297214478Srpaulo { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, 298190207Srpaulo#endif 299214478Srpaulo#ifdef HAVE_PCAP_USB_H 300214478Srpaulo#ifdef DLT_USB_LINUX 301214478Srpaulo { usb_linux_48_byte_print, DLT_USB_LINUX}, 302214478Srpaulo#endif /* DLT_USB_LINUX */ 303214478Srpaulo#ifdef DLT_USB_LINUX_MMAPPED 304214478Srpaulo { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED}, 305214478Srpaulo#endif /* DLT_USB_LINUX_MMAPPED */ 306214478Srpaulo#endif /* HAVE_PCAP_USB_H */ 307214478Srpaulo#ifdef DLT_IPV4 308214478Srpaulo { raw_if_print, DLT_IPV4 }, 309214478Srpaulo#endif 310214478Srpaulo#ifdef DLT_IPV6 311214478Srpaulo { raw_if_print, DLT_IPV6 }, 312214478Srpaulo#endif 31317680Spst { NULL, 0 }, 31417680Spst}; 31517680Spst 316214478Srpaulostatic struct ndo_printer ndo_printers[] = { 317236192Sdelphij { ether_if_print, DLT_EN10MB }, 318214478Srpaulo#ifdef DLT_IPNET 319214478Srpaulo { ipnet_if_print, DLT_IPNET }, 320214478Srpaulo#endif 321236192Sdelphij#ifdef DLT_IEEE802_15_4 322236192Sdelphij { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, 323236192Sdelphij#endif 324236192Sdelphij#ifdef DLT_IEEE802_15_4_NOFCS 325236192Sdelphij { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, 326236192Sdelphij#endif 327236192Sdelphij#ifdef DLT_PPI 328236192Sdelphij { ppi_if_print, DLT_PPI }, 329236192Sdelphij#endif 330236192Sdelphij#ifdef DLT_NETANALYZER 331236192Sdelphij { netanalyzer_if_print, DLT_NETANALYZER }, 332236192Sdelphij#endif 333236192Sdelphij#ifdef DLT_NETANALYZER_TRANSPARENT 334236192Sdelphij { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, 335236192Sdelphij#endif 336214478Srpaulo { NULL, 0 }, 337214478Srpaulo}; 338214478Srpaulo 339236192Sdelphijif_printer 34017680Spstlookup_printer(int type) 34117680Spst{ 34217680Spst struct printer *p; 34317680Spst 34417680Spst for (p = printers; p->f; ++p) 34517680Spst if (type == p->type) 34617680Spst return p->f; 34717680Spst 348127675Sbms return NULL; 34917680Spst /* NOTREACHED */ 35017680Spst} 35117680Spst 352236192Sdelphijif_ndo_printer 353214478Srpaulolookup_ndo_printer(int type) 354214478Srpaulo{ 355214478Srpaulo struct ndo_printer *p; 356214478Srpaulo 357214478Srpaulo for (p = ndo_printers; p->f; ++p) 358214478Srpaulo if (type == p->type) 359214478Srpaulo return p->f; 360214478Srpaulo 361214478Srpaulo return NULL; 362214478Srpaulo /* NOTREACHED */ 363214478Srpaulo} 364214478Srpaulo 36517680Spststatic pcap_t *pd; 36617680Spst 367214478Srpaulostatic int supports_monitor_mode; 368214478Srpaulo 36917680Spstextern int optind; 37017680Spstextern int opterr; 37117680Spstextern char *optarg; 37217680Spst 373127675Sbmsstruct print_info { 374214478Srpaulo netdissect_options *ndo; 375214478Srpaulo union { 376214478Srpaulo if_printer printer; 377214478Srpaulo if_ndo_printer ndo_printer; 378214478Srpaulo } p; 379214478Srpaulo int ndo_type; 380127675Sbms}; 381127675Sbms 38298527Sfennerstruct dump_info { 38398527Sfenner char *WFileName; 384190207Srpaulo char *CurrentFileName; 38598527Sfenner pcap_t *pd; 38698527Sfenner pcap_dumper_t *p; 38798527Sfenner}; 38898527Sfenner 389236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 390109842Sfennerstatic void 391236192Sdelphijshow_tstamp_types_and_exit(const char *device, pcap_t *pd) 392236192Sdelphij{ 393236192Sdelphij int n_tstamp_types; 394236192Sdelphij int *tstamp_types = 0; 395236192Sdelphij const char *tstamp_type_name; 396236192Sdelphij int i; 397236192Sdelphij 398236192Sdelphij n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types); 399236192Sdelphij if (n_tstamp_types < 0) 400236192Sdelphij error("%s", pcap_geterr(pd)); 401236192Sdelphij 402236192Sdelphij if (n_tstamp_types == 0) { 403236192Sdelphij fprintf(stderr, "Time stamp type cannot be set for %s\n", 404236192Sdelphij device); 405236192Sdelphij exit(0); 406236192Sdelphij } 407236192Sdelphij fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", 408236192Sdelphij device); 409236192Sdelphij for (i = 0; i < n_tstamp_types; i++) { 410236192Sdelphij tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); 411236192Sdelphij if (tstamp_type_name != NULL) { 412236192Sdelphij (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, 413236192Sdelphij pcap_tstamp_type_val_to_description(tstamp_types[i])); 414236192Sdelphij } else { 415236192Sdelphij (void) fprintf(stderr, " %d\n", tstamp_types[i]); 416236192Sdelphij } 417236192Sdelphij } 418236192Sdelphij pcap_free_tstamp_types(tstamp_types); 419236192Sdelphij exit(0); 420236192Sdelphij} 421236192Sdelphij#endif 422236192Sdelphij 423236192Sdelphijstatic void 424214478Srpauloshow_dlts_and_exit(const char *device, pcap_t *pd) 425109842Sfenner{ 426127675Sbms int n_dlts; 427109842Sfenner int *dlts = 0; 428127675Sbms const char *dlt_name; 429127675Sbms 430109842Sfenner n_dlts = pcap_list_datalinks(pd, &dlts); 431109842Sfenner if (n_dlts < 0) 432109842Sfenner error("%s", pcap_geterr(pd)); 433109842Sfenner else if (n_dlts == 0 || !dlts) 434109842Sfenner error("No data link types."); 435109842Sfenner 436214478Srpaulo /* 437214478Srpaulo * If the interface is known to support monitor mode, indicate 438214478Srpaulo * whether these are the data link types available when not in 439214478Srpaulo * monitor mode, if -I wasn't specified, or when in monitor mode, 440214478Srpaulo * when -I was specified (the link-layer types available in 441214478Srpaulo * monitor mode might be different from the ones available when 442214478Srpaulo * not in monitor mode). 443214478Srpaulo */ 444214478Srpaulo if (supports_monitor_mode) 445214478Srpaulo (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", 446214478Srpaulo device, 447214478Srpaulo Iflag ? "when in monitor mode" : "when not in monitor mode"); 448214478Srpaulo else 449214478Srpaulo (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", 450214478Srpaulo device); 451109842Sfenner 452109842Sfenner while (--n_dlts >= 0) { 453127675Sbms dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); 454127675Sbms if (dlt_name != NULL) { 455127675Sbms (void) fprintf(stderr, " %s (%s)", dlt_name, 456127675Sbms pcap_datalink_val_to_description(dlts[n_dlts])); 457127675Sbms 458127675Sbms /* 459127675Sbms * OK, does tcpdump handle that type? 460127675Sbms */ 461214478Srpaulo if (lookup_printer(dlts[n_dlts]) == NULL 462214478Srpaulo && lookup_ndo_printer(dlts[n_dlts]) == NULL) 463190207Srpaulo (void) fprintf(stderr, " (printing not supported)"); 464236192Sdelphij fprintf(stderr, "\n"); 465127675Sbms } else { 466190207Srpaulo (void) fprintf(stderr, " DLT %d (printing not supported)\n", 467127675Sbms dlts[n_dlts]); 468109842Sfenner } 469109842Sfenner } 470252283Sdelphij#ifdef HAVE_PCAP_FREE_DATALINKS 471236192Sdelphij pcap_free_datalinks(dlts); 472252283Sdelphij#endif 473109842Sfenner exit(0); 474109842Sfenner} 475109842Sfenner 476127675Sbms/* 477127675Sbms * Set up flags that might or might not be supported depending on the 478127675Sbms * version of libpcap we're using. 479127675Sbms */ 480190207Srpaulo#if defined(HAVE_PCAP_CREATE) || defined(WIN32) 481127675Sbms#define B_FLAG "B:" 482127675Sbms#define B_FLAG_USAGE " [ -B size ]" 483190207Srpaulo#else /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 484127675Sbms#define B_FLAG 485127675Sbms#define B_FLAG_USAGE 486190207Srpaulo#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 487127675Sbms 488190207Srpaulo#ifdef HAVE_PCAP_CREATE 489190207Srpaulo#define I_FLAG "I" 490190207Srpaulo#else /* HAVE_PCAP_CREATE */ 491190207Srpaulo#define I_FLAG 492190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 493190207Srpaulo 494236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 495236192Sdelphij#define j_FLAG "j:" 496236192Sdelphij#define j_FLAG_USAGE " [ -j tstamptype ]" 497236192Sdelphij#define J_FLAG "J" 498236192Sdelphij#else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ 499236192Sdelphij#define j_FLAG 500236192Sdelphij#define j_FLAG_USAGE 501236192Sdelphij#define J_FLAG 502236192Sdelphij#endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ 503236192Sdelphij 504127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 505146778Ssam#ifndef HAVE_PCAP_IF_T 506146778Ssam#undef HAVE_PCAP_FINDALLDEVS 507146778Ssam#endif 508146778Ssam#endif 509146778Ssam 510146778Ssam#ifdef HAVE_PCAP_FINDALLDEVS 511127675Sbms#define D_FLAG "D" 512127675Sbms#else 513127675Sbms#define D_FLAG 514127675Sbms#endif 515127675Sbms 516127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 517127675Sbms#define U_FLAG "U" 518127675Sbms#else 519127675Sbms#define U_FLAG 520127675Sbms#endif 521127675Sbms 522146778Ssam#ifndef WIN32 523146778Ssam/* Drop root privileges and chroot if necessary */ 524146778Ssamstatic void 525146778Ssamdroproot(const char *username, const char *chroot_dir) 526146778Ssam{ 527146778Ssam struct passwd *pw = NULL; 528146778Ssam 529146778Ssam if (chroot_dir && !username) { 530146778Ssam fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); 531146778Ssam exit(1); 532146778Ssam } 533146778Ssam 534146778Ssam pw = getpwnam(username); 535146778Ssam if (pw) { 536146778Ssam if (chroot_dir) { 537146778Ssam if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { 538146778Ssam fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", 539146778Ssam chroot_dir, pcap_strerror(errno)); 540146778Ssam exit(1); 541146778Ssam } 542146778Ssam } 543252283Sdelphij#ifdef HAVE_CAP_NG_H 544252283Sdelphij int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); 545252283Sdelphij if (ret < 0) { 546252283Sdelphij printf("error : ret %d\n", ret); 547252283Sdelphij } 548252283Sdelphij /* We don't need CAP_SETUID and CAP_SETGID */ 549252283Sdelphij capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); 550252283Sdelphij capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); 551252283Sdelphij capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); 552252283Sdelphij capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); 553252283Sdelphij capng_apply(CAPNG_SELECT_BOTH); 554252283Sdelphij 555252283Sdelphij#else 556146778Ssam if (initgroups(pw->pw_name, pw->pw_gid) != 0 || 557146778Ssam setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { 558146778Ssam fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", 559146778Ssam username, 560146778Ssam (unsigned long)pw->pw_uid, 561146778Ssam (unsigned long)pw->pw_gid, 562146778Ssam pcap_strerror(errno)); 563146778Ssam exit(1); 564146778Ssam } 565252283Sdelphij#endif /* HAVE_CAP_NG_H */ 566146778Ssam } 567146778Ssam else { 568146778Ssam fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", 569146778Ssam username); 570146778Ssam exit(1); 571146778Ssam } 572146778Ssam} 573146778Ssam#endif /* WIN32 */ 574146778Ssam 575146778Ssamstatic int 576146778SsamgetWflagChars(int x) 577146778Ssam{ 578146778Ssam int c = 0; 579146778Ssam 580146778Ssam x -= 1; 581146778Ssam while (x > 0) { 582146778Ssam c += 1; 583146778Ssam x /= 10; 584146778Ssam } 585146778Ssam 586146778Ssam return c; 587146778Ssam} 588146778Ssam 589146778Ssam 590146778Ssamstatic void 591146778SsamMakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) 592146778Ssam{ 593252283Sdelphij char *filename = malloc(PATH_MAX + 1); 594252283Sdelphij if (filename == NULL) 595252283Sdelphij error("Makefilename: malloc"); 596190207Srpaulo 597190207Srpaulo /* Process with strftime if Gflag is set. */ 598190207Srpaulo if (Gflag != 0) { 599190207Srpaulo struct tm *local_tm; 600190207Srpaulo 601190207Srpaulo /* Convert Gflag_time to a usable format */ 602190207Srpaulo if ((local_tm = localtime(&Gflag_time)) == NULL) { 603190207Srpaulo error("MakeTimedFilename: localtime"); 604190207Srpaulo } 605190207Srpaulo 606190207Srpaulo /* There's no good way to detect an error in strftime since a return 607190207Srpaulo * value of 0 isn't necessarily failure. 608190207Srpaulo */ 609252283Sdelphij strftime(filename, PATH_MAX, orig_name, local_tm); 610190207Srpaulo } else { 611252283Sdelphij strncpy(filename, orig_name, PATH_MAX); 612190207Srpaulo } 613190207Srpaulo 614146778Ssam if (cnt == 0 && max_chars == 0) 615252283Sdelphij strncpy(buffer, filename, PATH_MAX + 1); 616146778Ssam else 617252283Sdelphij if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) 618190207Srpaulo /* Report an error if the filename is too large */ 619252283Sdelphij error("too many output files or filename is too long (> %d)", PATH_MAX); 620190207Srpaulo free(filename); 621146778Ssam} 622146778Ssam 623146778Ssamstatic int tcpdump_printf(netdissect_options *ndo _U_, 624146778Ssam const char *fmt, ...) 625146778Ssam{ 626146778Ssam 627146778Ssam va_list args; 628146778Ssam int ret; 629146778Ssam 630146778Ssam va_start(args, fmt); 631146778Ssam ret=vfprintf(stdout, fmt, args); 632146778Ssam va_end(args); 633146778Ssam 634146778Ssam return ret; 635146778Ssam} 636146778Ssam 637252283Sdelphijstatic struct print_info 638252283Sdelphijget_print_info(int type) 639252283Sdelphij{ 640252283Sdelphij struct print_info printinfo; 641252283Sdelphij 642252283Sdelphij printinfo.ndo_type = 1; 643252283Sdelphij printinfo.ndo = gndo; 644252283Sdelphij printinfo.p.ndo_printer = lookup_ndo_printer(type); 645252283Sdelphij if (printinfo.p.ndo_printer == NULL) { 646252283Sdelphij printinfo.p.printer = lookup_printer(type); 647252283Sdelphij printinfo.ndo_type = 0; 648252283Sdelphij if (printinfo.p.printer == NULL) { 649252283Sdelphij gndo->ndo_dltname = pcap_datalink_val_to_name(type); 650252283Sdelphij if (gndo->ndo_dltname != NULL) 651252283Sdelphij error("packet printing is not supported for link type %s: use -w", 652252283Sdelphij gndo->ndo_dltname); 653252283Sdelphij else 654252283Sdelphij error("packet printing is not supported for link type %d: use -w", type); 655252283Sdelphij } 656252283Sdelphij } 657252283Sdelphij return (printinfo); 658252283Sdelphij} 659252283Sdelphij 660252283Sdelphijstatic char * 661252283Sdelphijget_next_file(FILE *VFile, char *ptr) 662252283Sdelphij{ 663252283Sdelphij char *ret; 664252283Sdelphij 665252283Sdelphij ret = fgets(ptr, PATH_MAX, VFile); 666252283Sdelphij if (!ret) 667252283Sdelphij return NULL; 668252283Sdelphij 669252283Sdelphij if (ptr[strlen(ptr) - 1] == '\n') 670252283Sdelphij ptr[strlen(ptr) - 1] = '\0'; 671252283Sdelphij 672252283Sdelphij return ret; 673252283Sdelphij} 674252283Sdelphij 67517680Spstint 67617680Spstmain(int argc, char **argv) 67717680Spst{ 67817680Spst register int cnt, op, i; 67917680Spst bpf_u_int32 localnet, netmask; 680252283Sdelphij register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; 681127675Sbms pcap_handler callback; 682127675Sbms int type; 683252283Sdelphij int dlt; 684252283Sdelphij int new_dlt; 685252283Sdelphij const char *dlt_name; 68617680Spst struct bpf_program fcode; 687127675Sbms#ifndef WIN32 68839297Sfenner RETSIGTYPE (*oldhandler)(int); 689127675Sbms#endif 690127675Sbms struct print_info printinfo; 69198527Sfenner struct dump_info dumpinfo; 69217680Spst u_char *pcap_userdata; 69317680Spst char ebuf[PCAP_ERRBUF_SIZE]; 694252283Sdelphij char VFileLine[PATH_MAX + 1]; 695146778Ssam char *username = NULL; 696146778Ssam char *chroot_dir = NULL; 697252283Sdelphij char *ret = NULL; 698252283Sdelphij char *end; 699127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 700127675Sbms pcap_if_t *devpointer; 701127675Sbms int devnum; 702127675Sbms#endif 703127675Sbms int status; 704252283Sdelphij FILE *VFile; 705127675Sbms#ifdef WIN32 706127675Sbms if(wsockinit() != 0) return 1; 707127675Sbms#endif /* WIN32 */ 70817680Spst 709236192Sdelphij jflag=-1; /* not set */ 710146778Ssam gndo->ndo_Oflag=1; 711146778Ssam gndo->ndo_Rflag=1; 712146778Ssam gndo->ndo_dlt=-1; 713146778Ssam gndo->ndo_default_print=ndo_default_print; 714146778Ssam gndo->ndo_printf=tcpdump_printf; 715146778Ssam gndo->ndo_error=ndo_error; 716146778Ssam gndo->ndo_warning=ndo_warning; 717146778Ssam gndo->ndo_snaplen = DEFAULT_SNAPLEN; 718146778Ssam 71917680Spst cnt = -1; 72017680Spst device = NULL; 72117680Spst infile = NULL; 72217680Spst RFileName = NULL; 723252283Sdelphij VFileName = NULL; 724252283Sdelphij VFile = NULL; 72517680Spst WFileName = NULL; 726252283Sdelphij dlt = -1; 72717680Spst if ((cp = strrchr(argv[0], '/')) != NULL) 72817680Spst program_name = cp + 1; 72917680Spst else 73017680Spst program_name = argv[0]; 73117680Spst 73275118Sfenner if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) 73326180Sfenner error("%s", ebuf); 73417680Spst 73556896Sfenner#ifdef LIBSMI 73656896Sfenner smiInit("tcpdump"); 73756896Sfenner#endif 738127675Sbms 73939297Sfenner while ( 740252283Sdelphij (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 "V:vw:W:xXy:Yz:Z:")) != -1) 74117680Spst switch (op) { 74239297Sfenner 74339297Sfenner case 'a': 744127675Sbms /* compatibility for old -a */ 74539297Sfenner break; 74639297Sfenner 747127675Sbms case 'A': 748127675Sbms ++Aflag; 749127675Sbms break; 750127675Sbms 751214478Srpaulo case 'b': 752214478Srpaulo ++bflag; 753214478Srpaulo break; 754214478Srpaulo 755190207Srpaulo#if defined(HAVE_PCAP_CREATE) || defined(WIN32) 756127675Sbms case 'B': 757190207Srpaulo Bflag = atoi(optarg)*1024; 758190207Srpaulo if (Bflag <= 0) 759127675Sbms error("invalid packet buffer size %s", optarg); 760127675Sbms break; 761190207Srpaulo#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 762127675Sbms 76317680Spst case 'c': 76417680Spst cnt = atoi(optarg); 76517680Spst if (cnt <= 0) 76617680Spst error("invalid packet count %s", optarg); 76717680Spst break; 76817680Spst 76998527Sfenner case 'C': 77098527Sfenner Cflag = atoi(optarg) * 1000000; 771127675Sbms if (Cflag < 0) 77298527Sfenner error("invalid file size %s", optarg); 77398527Sfenner break; 77498527Sfenner 77517680Spst case 'd': 77617680Spst ++dflag; 77717680Spst break; 77817680Spst 779127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 780127675Sbms case 'D': 781127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 782127675Sbms error("%s", ebuf); 783127675Sbms else { 784127675Sbms for (i = 0; devpointer != 0; i++) { 785127675Sbms printf("%d.%s", i+1, devpointer->name); 786127675Sbms if (devpointer->description != NULL) 787127675Sbms printf(" (%s)", devpointer->description); 788127675Sbms printf("\n"); 789127675Sbms devpointer = devpointer->next; 790127675Sbms } 791127675Sbms } 792127675Sbms return 0; 793127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 794127675Sbms 795109842Sfenner case 'L': 796109842Sfenner Lflag++; 797109842Sfenner break; 798109842Sfenner 79917680Spst case 'e': 80017680Spst ++eflag; 80117680Spst break; 80217680Spst 80356896Sfenner case 'E': 80475118Sfenner#ifndef HAVE_LIBCRYPTO 80556896Sfenner warning("crypto code not compiled in"); 80656896Sfenner#endif 807146778Ssam gndo->ndo_espsecret = optarg; 80856896Sfenner break; 80956896Sfenner 81017680Spst case 'f': 81117680Spst ++fflag; 81217680Spst break; 81317680Spst 81417680Spst case 'F': 81517680Spst infile = optarg; 81617680Spst break; 81717680Spst 818190207Srpaulo case 'G': 819190207Srpaulo Gflag = atoi(optarg); 820190207Srpaulo if (Gflag < 0) 821190207Srpaulo error("invalid number of seconds %s", optarg); 822190207Srpaulo 823190207Srpaulo /* We will create one file initially. */ 824190207Srpaulo Gflag_count = 0; 825190207Srpaulo 826190207Srpaulo /* Grab the current time for rotation use. */ 827190207Srpaulo if ((Gflag_time = time(NULL)) == (time_t)-1) { 828190207Srpaulo error("main: can't get current time: %s", 829190207Srpaulo pcap_strerror(errno)); 830190207Srpaulo } 831190207Srpaulo break; 832190207Srpaulo 833236192Sdelphij case 'h': 834236192Sdelphij usage(); 835236192Sdelphij break; 836236192Sdelphij 837236192Sdelphij case 'H': 838236192Sdelphij ++Hflag; 839236192Sdelphij break; 840236192Sdelphij 84117680Spst case 'i': 842127675Sbms if (optarg[0] == '0' && optarg[1] == 0) 843127675Sbms error("Invalid adapter index"); 844127675Sbms 845127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 846127675Sbms /* 847127675Sbms * If the argument is a number, treat it as 848127675Sbms * an index into the list of adapters, as 849127675Sbms * printed by "tcpdump -D". 850127675Sbms * 851127675Sbms * This should be OK on UNIX systems, as interfaces 852127675Sbms * shouldn't have names that begin with digits. 853127675Sbms * It can be useful on Windows, where more than 854127675Sbms * one interface can have the same name. 855127675Sbms */ 856252283Sdelphij devnum = strtol(optarg, &end, 10); 857252283Sdelphij if (optarg != end && *end == '\0') { 858127675Sbms if (devnum < 0) 859127675Sbms error("Invalid adapter index"); 860127675Sbms 861127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 862127675Sbms error("%s", ebuf); 863127675Sbms else { 864214478Srpaulo /* 865214478Srpaulo * Look for the devnum-th entry 866214478Srpaulo * in the list of devices 867214478Srpaulo * (1-based). 868214478Srpaulo */ 869214478Srpaulo for (i = 0; 870214478Srpaulo i < devnum-1 && devpointer != NULL; 871214478Srpaulo i++, devpointer = devpointer->next) 872214478Srpaulo ; 873214478Srpaulo if (devpointer == NULL) 874214478Srpaulo error("Invalid adapter index"); 875127675Sbms } 876127675Sbms device = devpointer->name; 877127675Sbms break; 878127675Sbms } 879127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 88017680Spst device = optarg; 88117680Spst break; 88217680Spst 883190207Srpaulo#ifdef HAVE_PCAP_CREATE 884190207Srpaulo case 'I': 885190207Srpaulo ++Iflag; 886190207Srpaulo break; 887190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 888190207Srpaulo 889236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 890236192Sdelphij case 'j': 891236192Sdelphij jflag = pcap_tstamp_type_name_to_val(optarg); 892236192Sdelphij if (jflag < 0) 893236192Sdelphij error("invalid time stamp type %s", optarg); 894236192Sdelphij break; 895236192Sdelphij 896236192Sdelphij case 'J': 897236192Sdelphij Jflag++; 898236192Sdelphij break; 899236192Sdelphij#endif 900236192Sdelphij 90117680Spst case 'l': 902127675Sbms#ifdef WIN32 903127675Sbms /* 904127675Sbms * _IOLBF is the same as _IOFBF in Microsoft's C 905127675Sbms * libraries; the only alternative they offer 906127675Sbms * is _IONBF. 907127675Sbms * 908127675Sbms * XXX - this should really be checking for MSVC++, 909127675Sbms * not WIN32, if, for example, MinGW has its own 910127675Sbms * C library that is more UNIX-compatible. 911127675Sbms */ 912127675Sbms setvbuf(stdout, NULL, _IONBF, 0); 913127675Sbms#else /* WIN32 */ 91417680Spst#ifdef HAVE_SETLINEBUF 91517680Spst setlinebuf(stdout); 91617680Spst#else 91717680Spst setvbuf(stdout, NULL, _IOLBF, 0); 91817680Spst#endif 919127675Sbms#endif /* WIN32 */ 92017680Spst break; 92117680Spst 922190207Srpaulo case 'K': 923190207Srpaulo ++Kflag; 92417680Spst break; 92517680Spst 92656896Sfenner case 'm': 92756896Sfenner#ifdef LIBSMI 928190207Srpaulo if (smiLoadModule(optarg) == 0) { 92956896Sfenner error("could not load MIB module %s", optarg); 930190207Srpaulo } 93156896Sfenner sflag = 1; 93256896Sfenner#else 93356896Sfenner (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 93456896Sfenner program_name, optarg); 93556896Sfenner (void)fprintf(stderr, "(no libsmi support)\n"); 93656896Sfenner#endif 937127675Sbms break; 938127675Sbms 939146778Ssam case 'M': 940146778Ssam /* TCP-MD5 shared secret */ 941146778Ssam#ifndef HAVE_LIBCRYPTO 942146778Ssam warning("crypto code not compiled in"); 943146778Ssam#endif 944214478Srpaulo sigsecret = optarg; 945146778Ssam break; 946146778Ssam 947190207Srpaulo case 'n': 948190207Srpaulo ++nflag; 949190207Srpaulo break; 950190207Srpaulo 951190207Srpaulo case 'N': 952190207Srpaulo ++Nflag; 953190207Srpaulo break; 954190207Srpaulo 95517680Spst case 'O': 95617680Spst Oflag = 0; 95717680Spst break; 95817680Spst 95917680Spst case 'p': 96017680Spst ++pflag; 96117680Spst break; 96217680Spst 96317680Spst case 'q': 96417680Spst ++qflag; 965162021Ssam ++suppress_default_print; 96617680Spst break; 96717680Spst 96817680Spst case 'r': 96917680Spst RFileName = optarg; 97017680Spst break; 97117680Spst 97256896Sfenner case 'R': 97356896Sfenner Rflag = 0; 97456896Sfenner break; 97556896Sfenner 976252283Sdelphij case 's': 97775118Sfenner snaplen = strtol(optarg, &end, 0); 97875118Sfenner if (optarg == end || *end != '\0' 979214478Srpaulo || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN) 98017680Spst error("invalid snaplen %s", optarg); 98175118Sfenner else if (snaplen == 0) 982214478Srpaulo snaplen = MAXIMUM_SNAPLEN; 98317680Spst break; 98417680Spst 98517680Spst case 'S': 98617680Spst ++Sflag; 98717680Spst break; 98817680Spst 98917680Spst case 't': 990146778Ssam ++tflag; 99117680Spst break; 99217680Spst 99317680Spst case 'T': 99417680Spst if (strcasecmp(optarg, "vat") == 0) 99517680Spst packettype = PT_VAT; 99617680Spst else if (strcasecmp(optarg, "wb") == 0) 99717680Spst packettype = PT_WB; 99817680Spst else if (strcasecmp(optarg, "rpc") == 0) 99917680Spst packettype = PT_RPC; 100017680Spst else if (strcasecmp(optarg, "rtp") == 0) 100117680Spst packettype = PT_RTP; 100217680Spst else if (strcasecmp(optarg, "rtcp") == 0) 100317680Spst packettype = PT_RTCP; 100456896Sfenner else if (strcasecmp(optarg, "snmp") == 0) 100556896Sfenner packettype = PT_SNMP; 100675118Sfenner else if (strcasecmp(optarg, "cnfp") == 0) 100775118Sfenner packettype = PT_CNFP; 1008127675Sbms else if (strcasecmp(optarg, "tftp") == 0) 1009127675Sbms packettype = PT_TFTP; 1010127675Sbms else if (strcasecmp(optarg, "aodv") == 0) 1011127675Sbms packettype = PT_AODV; 1012236192Sdelphij else if (strcasecmp(optarg, "carp") == 0) 1013236192Sdelphij packettype = PT_CARP; 1014252283Sdelphij else if (strcasecmp(optarg, "radius") == 0) 1015252283Sdelphij packettype = PT_RADIUS; 1016252283Sdelphij else if (strcasecmp(optarg, "zmtp1") == 0) 1017252283Sdelphij packettype = PT_ZMTP1; 1018252283Sdelphij else if (strcasecmp(optarg, "vxlan") == 0) 1019252283Sdelphij packettype = PT_VXLAN; 102017680Spst else 102117680Spst error("unknown packet type `%s'", optarg); 102217680Spst break; 102317680Spst 102475118Sfenner case 'u': 102575118Sfenner ++uflag; 102675118Sfenner break; 1027127675Sbms 1028127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1029127675Sbms case 'U': 1030127675Sbms ++Uflag; 1031127675Sbms break; 1032127675Sbms#endif 1033127675Sbms 103417680Spst case 'v': 103517680Spst ++vflag; 103617680Spst break; 103717680Spst 1038252283Sdelphij case 'V': 1039252283Sdelphij VFileName = optarg; 1040252283Sdelphij break; 1041252283Sdelphij 104217680Spst case 'w': 104317680Spst WFileName = optarg; 104417680Spst break; 104556896Sfenner 1046146778Ssam case 'W': 1047146778Ssam Wflag = atoi(optarg); 1048146778Ssam if (Wflag < 0) 1049146778Ssam error("invalid number of output files %s", optarg); 1050146778Ssam WflagChars = getWflagChars(Wflag); 1051146778Ssam break; 1052146778Ssam 105356896Sfenner case 'x': 105456896Sfenner ++xflag; 1055162021Ssam ++suppress_default_print; 105656896Sfenner break; 105756896Sfenner 105856896Sfenner case 'X': 105956896Sfenner ++Xflag; 1060162021Ssam ++suppress_default_print; 106156896Sfenner break; 106256896Sfenner 1063109842Sfenner case 'y': 1064146778Ssam gndo->ndo_dltname = optarg; 1065146778Ssam gndo->ndo_dlt = 1066146778Ssam pcap_datalink_name_to_val(gndo->ndo_dltname); 1067146778Ssam if (gndo->ndo_dlt < 0) 1068146778Ssam error("invalid data link type %s", gndo->ndo_dltname); 1069109842Sfenner break; 1070109842Sfenner 1071127675Sbms#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) 107217680Spst case 'Y': 107317680Spst { 107417680Spst /* Undocumented flag */ 1075127675Sbms#ifdef HAVE_PCAP_DEBUG 1076127675Sbms extern int pcap_debug; 1077127675Sbms pcap_debug = 1; 1078127675Sbms#else 107917680Spst extern int yydebug; 108017680Spst yydebug = 1; 1081127675Sbms#endif 108217680Spst } 108317680Spst break; 108417680Spst#endif 1085190207Srpaulo case 'z': 1086190207Srpaulo if (optarg) { 1087190207Srpaulo zflag = strdup(optarg); 1088190207Srpaulo } else { 1089190207Srpaulo usage(); 1090190207Srpaulo /* NOTREACHED */ 1091190207Srpaulo } 1092190207Srpaulo break; 1093190207Srpaulo 1094146778Ssam case 'Z': 1095146778Ssam if (optarg) { 1096146778Ssam username = strdup(optarg); 1097146778Ssam } 1098146778Ssam else { 1099146778Ssam usage(); 1100146778Ssam /* NOTREACHED */ 1101146778Ssam } 1102146778Ssam break; 1103146778Ssam 110417680Spst default: 110517680Spst usage(); 110617680Spst /* NOTREACHED */ 110717680Spst } 110817680Spst 1109146778Ssam switch (tflag) { 1110146778Ssam 1111146778Ssam case 0: /* Default */ 1112146778Ssam case 4: /* Default + Date*/ 111339297Sfenner thiszone = gmt2local(0); 1114146778Ssam break; 111517680Spst 1116146778Ssam case 1: /* No time stamp */ 1117146778Ssam case 2: /* Unix timeval style */ 1118146778Ssam case 3: /* Microseconds since previous packet */ 1119190207Srpaulo case 5: /* Microseconds since first packet */ 1120146778Ssam break; 1121146778Ssam 1122146778Ssam default: /* Not supported */ 1123190207Srpaulo error("only -t, -tt, -ttt, -tttt and -ttttt are supported"); 1124146778Ssam break; 1125146778Ssam } 1126146778Ssam 1127252283Sdelphij if (fflag != 0 && (VFileName != NULL || RFileName != NULL)) 1128252283Sdelphij error("-f can not be used with -V or -r"); 1129252283Sdelphij 1130252283Sdelphij if (VFileName != NULL && RFileName != NULL) 1131252283Sdelphij error("-V and -r are mutually exclusive."); 1132252283Sdelphij 1133146778Ssam#ifdef WITH_CHROOT 1134146778Ssam /* if run as root, prepare for chrooting */ 1135146778Ssam if (getuid() == 0 || geteuid() == 0) { 1136146778Ssam /* future extensibility for cmd-line arguments */ 1137146778Ssam if (!chroot_dir) 1138146778Ssam chroot_dir = WITH_CHROOT; 1139146778Ssam } 1140146778Ssam#endif 1141146778Ssam 1142146778Ssam#ifdef WITH_USER 1143146778Ssam /* if run as root, prepare for dropping root privileges */ 1144146778Ssam if (getuid() == 0 || geteuid() == 0) { 1145146778Ssam /* Run with '-Z root' to restore old behaviour */ 1146146778Ssam if (!username) 1147146778Ssam username = WITH_USER; 1148146778Ssam } 1149146778Ssam#endif 1150146778Ssam 1151252283Sdelphij if (RFileName != NULL || VFileName != NULL) { 1152252283Sdelphij /* 1153252283Sdelphij * If RFileName is non-null, it's the pathname of a 1154252283Sdelphij * savefile to read. If VFileName is non-null, it's 1155252283Sdelphij * the pathname of a file containing a list of pathnames 1156252283Sdelphij * (one per line) of savefiles to read. 1157252283Sdelphij * 1158252283Sdelphij * In either case, we're reading a savefile, not doing 1159252283Sdelphij * a live capture. 1160252283Sdelphij */ 1161127675Sbms#ifndef WIN32 116217680Spst /* 1163127675Sbms * We don't need network access, so relinquish any set-UID 1164127675Sbms * or set-GID privileges we have (if any). 1165127675Sbms * 1166127675Sbms * We do *not* want set-UID privileges when opening a 1167127675Sbms * trace file, as that might let the user read other 1168127675Sbms * people's trace files (especially if we're set-UID 1169127675Sbms * root). 117017680Spst */ 1171146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) 1172146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 1173127675Sbms#endif /* WIN32 */ 1174252283Sdelphij if (VFileName != NULL) { 1175252283Sdelphij if (VFileName[0] == '-' && VFileName[1] == '\0') 1176252283Sdelphij VFile = stdin; 1177252283Sdelphij else 1178252283Sdelphij VFile = fopen(VFileName, "r"); 1179252283Sdelphij 1180252283Sdelphij if (VFile == NULL) 1181252283Sdelphij error("Unable to open file: %s\n", strerror(errno)); 1182252283Sdelphij 1183252283Sdelphij ret = get_next_file(VFile, VFileLine); 1184252283Sdelphij if (!ret) 1185252283Sdelphij error("Nothing in %s\n", VFileName); 1186252283Sdelphij RFileName = VFileLine; 1187252283Sdelphij } 1188252283Sdelphij 118917680Spst pd = pcap_open_offline(RFileName, ebuf); 119017680Spst if (pd == NULL) 119126180Sfenner error("%s", ebuf); 1192127675Sbms dlt = pcap_datalink(pd); 1193127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1194127675Sbms if (dlt_name == NULL) { 1195127675Sbms fprintf(stderr, "reading from file %s, link-type %u\n", 1196127675Sbms RFileName, dlt); 1197127675Sbms } else { 1198127675Sbms fprintf(stderr, 1199127675Sbms "reading from file %s, link-type %s (%s)\n", 1200127675Sbms RFileName, dlt_name, 1201127675Sbms pcap_datalink_val_to_description(dlt)); 1202127675Sbms } 120317680Spst localnet = 0; 120417680Spst netmask = 0; 120517680Spst } else { 1206252283Sdelphij /* 1207252283Sdelphij * We're doing a live capture. 1208252283Sdelphij */ 120917680Spst if (device == NULL) { 121017680Spst device = pcap_lookupdev(ebuf); 121117680Spst if (device == NULL) 121226180Sfenner error("%s", ebuf); 121317680Spst } 1214127675Sbms#ifdef WIN32 1215252283Sdelphij /* 1216252283Sdelphij * Print a message to the standard error on Windows. 1217252283Sdelphij * XXX - why do it here, with a different message? 1218252283Sdelphij */ 1219146778Ssam if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char 1220146778Ssam { //a Unicode string has a \0 as second byte (so strlen() is 1) 1221127675Sbms fprintf(stderr, "%s: listening on %ws\n", program_name, device); 1222127675Sbms } 1223127675Sbms else 1224127675Sbms { 1225127675Sbms fprintf(stderr, "%s: listening on %s\n", program_name, device); 1226127675Sbms } 1227127675Sbms 1228127675Sbms fflush(stderr); 1229127675Sbms#endif /* WIN32 */ 1230190207Srpaulo#ifdef HAVE_PCAP_CREATE 1231190207Srpaulo pd = pcap_create(device, ebuf); 1232190207Srpaulo if (pd == NULL) 1233190207Srpaulo error("%s", ebuf); 1234236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 1235236192Sdelphij if (Jflag) 1236236192Sdelphij show_tstamp_types_and_exit(device, pd); 1237236192Sdelphij#endif 1238214478Srpaulo /* 1239214478Srpaulo * Is this an interface that supports monitor mode? 1240214478Srpaulo */ 1241214478Srpaulo if (pcap_can_set_rfmon(pd) == 1) 1242214478Srpaulo supports_monitor_mode = 1; 1243214478Srpaulo else 1244214478Srpaulo supports_monitor_mode = 0; 1245190207Srpaulo status = pcap_set_snaplen(pd, snaplen); 1246190207Srpaulo if (status != 0) 1247236192Sdelphij error("%s: Can't set snapshot length: %s", 1248190207Srpaulo device, pcap_statustostr(status)); 1249190207Srpaulo status = pcap_set_promisc(pd, !pflag); 1250190207Srpaulo if (status != 0) 1251236192Sdelphij error("%s: Can't set promiscuous mode: %s", 1252190207Srpaulo device, pcap_statustostr(status)); 1253190207Srpaulo if (Iflag) { 1254190207Srpaulo status = pcap_set_rfmon(pd, 1); 1255190207Srpaulo if (status != 0) 1256236192Sdelphij error("%s: Can't set monitor mode: %s", 1257190207Srpaulo device, pcap_statustostr(status)); 1258190207Srpaulo } 1259190207Srpaulo status = pcap_set_timeout(pd, 1000); 1260190207Srpaulo if (status != 0) 1261190207Srpaulo error("%s: pcap_set_timeout failed: %s", 1262190207Srpaulo device, pcap_statustostr(status)); 1263190207Srpaulo if (Bflag != 0) { 1264190207Srpaulo status = pcap_set_buffer_size(pd, Bflag); 1265190207Srpaulo if (status != 0) 1266236192Sdelphij error("%s: Can't set buffer size: %s", 1267190207Srpaulo device, pcap_statustostr(status)); 1268190207Srpaulo } 1269236192Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 1270236192Sdelphij if (jflag != -1) { 1271236192Sdelphij status = pcap_set_tstamp_type(pd, jflag); 1272236192Sdelphij if (status < 0) 1273236192Sdelphij error("%s: Can't set time stamp type: %s", 1274236192Sdelphij device, pcap_statustostr(status)); 1275236192Sdelphij } 1276236192Sdelphij#endif 1277190207Srpaulo status = pcap_activate(pd); 1278190207Srpaulo if (status < 0) { 1279190207Srpaulo /* 1280190207Srpaulo * pcap_activate() failed. 1281190207Srpaulo */ 1282190207Srpaulo cp = pcap_geterr(pd); 1283190207Srpaulo if (status == PCAP_ERROR) 1284190207Srpaulo error("%s", cp); 1285190207Srpaulo else if ((status == PCAP_ERROR_NO_SUCH_DEVICE || 1286190207Srpaulo status == PCAP_ERROR_PERM_DENIED) && 1287190207Srpaulo *cp != '\0') 1288190207Srpaulo error("%s: %s\n(%s)", device, 1289190207Srpaulo pcap_statustostr(status), cp); 1290190207Srpaulo else 1291190207Srpaulo error("%s: %s", device, 1292190207Srpaulo pcap_statustostr(status)); 1293190207Srpaulo } else if (status > 0) { 1294190207Srpaulo /* 1295190207Srpaulo * pcap_activate() succeeded, but it's warning us 1296190207Srpaulo * of a problem it had. 1297190207Srpaulo */ 1298190207Srpaulo cp = pcap_geterr(pd); 1299190207Srpaulo if (status == PCAP_WARNING) 1300190207Srpaulo warning("%s", cp); 1301190207Srpaulo else if (status == PCAP_WARNING_PROMISC_NOTSUP && 1302190207Srpaulo *cp != '\0') 1303190207Srpaulo warning("%s: %s\n(%s)", device, 1304190207Srpaulo pcap_statustostr(status), cp); 1305190207Srpaulo else 1306190207Srpaulo warning("%s: %s", device, 1307190207Srpaulo pcap_statustostr(status)); 1308190207Srpaulo } 1309190207Srpaulo#else 131098527Sfenner *ebuf = '\0'; 131117680Spst pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 131217680Spst if (pd == NULL) 131326180Sfenner error("%s", ebuf); 131498527Sfenner else if (*ebuf) 131598527Sfenner warning("%s", ebuf); 1316190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 1317146778Ssam /* 1318146778Ssam * Let user own process after socket has been opened. 1319146778Ssam */ 1320146778Ssam#ifndef WIN32 1321146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0) 1322146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 1323146778Ssam#endif /* WIN32 */ 1324190207Srpaulo#if !defined(HAVE_PCAP_CREATE) && defined(WIN32) 1325190207Srpaulo if(Bflag != 0) 1326190207Srpaulo if(pcap_setbuff(pd, Bflag)==-1){ 1327146778Ssam error("%s", pcap_geterr(pd)); 1328146778Ssam } 1329190207Srpaulo#endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */ 1330127675Sbms if (Lflag) 1331214478Srpaulo show_dlts_and_exit(device, pd); 1332146778Ssam if (gndo->ndo_dlt >= 0) { 1333127675Sbms#ifdef HAVE_PCAP_SET_DATALINK 1334146778Ssam if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0) 1335109842Sfenner error("%s", pcap_geterr(pd)); 1336127675Sbms#else 1337127675Sbms /* 1338127675Sbms * We don't actually support changing the 1339127675Sbms * data link type, so we only let them 1340127675Sbms * set it to what it already is. 1341127675Sbms */ 1342146778Ssam if (gndo->ndo_dlt != pcap_datalink(pd)) { 1343127675Sbms error("%s is not one of the DLTs supported by this device\n", 1344146778Ssam gndo->ndo_dltname); 1345127675Sbms } 1346127675Sbms#endif 1347109842Sfenner (void)fprintf(stderr, "%s: data link type %s\n", 1348190207Srpaulo program_name, gndo->ndo_dltname); 1349109842Sfenner (void)fflush(stderr); 1350109842Sfenner } 135117680Spst i = pcap_snapshot(pd); 135217680Spst if (snaplen < i) { 135317680Spst warning("snaplen raised from %d to %d", snaplen, i); 135417680Spst snaplen = i; 135517680Spst } 135639297Sfenner if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 135739297Sfenner localnet = 0; 135839297Sfenner netmask = 0; 135939297Sfenner warning("%s", ebuf); 136039297Sfenner } 136117680Spst } 136217680Spst if (infile) 136317680Spst cmdbuf = read_infile(infile); 136417680Spst else 136517680Spst cmdbuf = copy_argv(&argv[optind]); 136617680Spst 136717680Spst if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 136826180Sfenner error("%s", pcap_geterr(pd)); 136917680Spst if (dflag) { 137017680Spst bpf_dump(&fcode, dflag); 1371127675Sbms pcap_close(pd); 1372252283Sdelphij free(cmdbuf); 137317680Spst exit(0); 137417680Spst } 137539297Sfenner init_addrtoname(localnet, netmask); 1376190207Srpaulo init_checksum(); 137717680Spst 1378127675Sbms#ifndef WIN32 1379127675Sbms (void)setsignal(SIGPIPE, cleanup); 138039297Sfenner (void)setsignal(SIGTERM, cleanup); 138139297Sfenner (void)setsignal(SIGINT, cleanup); 1382236192Sdelphij#endif /* WIN32 */ 1383236192Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 1384190207Srpaulo (void)setsignal(SIGCHLD, child_cleanup); 1385236192Sdelphij#endif 138639297Sfenner /* Cooperate with nohup(1) */ 1387127675Sbms#ifndef WIN32 138839297Sfenner if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 138939297Sfenner (void)setsignal(SIGHUP, oldhandler); 1390127675Sbms#endif /* WIN32 */ 139117680Spst 1392236192Sdelphij#ifndef WIN32 1393236192Sdelphij /* 1394236192Sdelphij * If a user name was specified with "-Z", attempt to switch to 1395236192Sdelphij * that user's UID. This would probably be used with sudo, 1396236192Sdelphij * to allow tcpdump to be run in a special restricted 1397236192Sdelphij * account (if you just want to allow users to open capture 1398236192Sdelphij * devices, and can't just give users that permission, 1399236192Sdelphij * you'd make tcpdump set-UID or set-GID). 1400236192Sdelphij * 1401236192Sdelphij * Tcpdump doesn't necessarily write only to one savefile; 1402236192Sdelphij * the general only way to allow a -Z instance to write to 1403236192Sdelphij * savefiles as the user under whose UID it's run, rather 1404236192Sdelphij * than as the user specified with -Z, would thus be to switch 1405236192Sdelphij * to the original user ID before opening a capture file and 1406236192Sdelphij * then switch back to the -Z user ID after opening the savefile. 1407236192Sdelphij * Switching to the -Z user ID only after opening the first 1408236192Sdelphij * savefile doesn't handle the general case. 1409236192Sdelphij */ 1410252283Sdelphij 1411252283Sdelphij#ifdef HAVE_CAP_NG_H 1412252283Sdelphij /* We are running as root and we will be writing to savefile */ 1413252283Sdelphij if ((getuid() == 0 || geteuid() == 0) && WFileName) { 1414252283Sdelphij if (username) { 1415252283Sdelphij /* Drop all capabilities from effective set */ 1416252283Sdelphij capng_clear(CAPNG_EFFECTIVE); 1417252283Sdelphij /* Add capabilities we will need*/ 1418252283Sdelphij capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETUID); 1419252283Sdelphij capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETGID); 1420252283Sdelphij capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_DAC_OVERRIDE); 1421252283Sdelphij 1422252283Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETUID); 1423252283Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETGID); 1424252283Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); 1425252283Sdelphij 1426252283Sdelphij capng_apply(CAPNG_SELECT_BOTH); 1427252283Sdelphij } 1428252283Sdelphij } 1429252283Sdelphij#endif /* HAVE_CAP_NG_H */ 1430252283Sdelphij 1431236192Sdelphij if (getuid() == 0 || geteuid() == 0) { 1432236192Sdelphij if (username || chroot_dir) 1433236192Sdelphij droproot(username, chroot_dir); 1434252283Sdelphij 1435236192Sdelphij } 1436236192Sdelphij#endif /* WIN32 */ 1437236192Sdelphij 143817680Spst if (pcap_setfilter(pd, &fcode) < 0) 143926180Sfenner error("%s", pcap_geterr(pd)); 144017680Spst if (WFileName) { 1441146778Ssam pcap_dumper_t *p; 1442252283Sdelphij /* Do not exceed the default PATH_MAX for files. */ 1443252283Sdelphij dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1); 1444146778Ssam 1445190207Srpaulo if (dumpinfo.CurrentFileName == NULL) 1446190207Srpaulo error("malloc of dumpinfo.CurrentFileName"); 1447190207Srpaulo 1448190207Srpaulo /* We do not need numbering for dumpfiles if Cflag isn't set. */ 1449190207Srpaulo if (Cflag != 0) 1450190207Srpaulo MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); 1451190207Srpaulo else 1452190207Srpaulo MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); 1453190207Srpaulo 1454190207Srpaulo p = pcap_dump_open(pd, dumpinfo.CurrentFileName); 1455252283Sdelphij#ifdef HAVE_CAP_NG_H 1456252283Sdelphij /* Give up capabilities, clear Effective set */ 1457252283Sdelphij capng_clear(CAPNG_EFFECTIVE); 1458252283Sdelphij#endif 145917680Spst if (p == NULL) 146026180Sfenner error("%s", pcap_geterr(pd)); 1461190207Srpaulo if (Cflag != 0 || Gflag != 0) { 1462127675Sbms callback = dump_packet_and_trunc; 146398527Sfenner dumpinfo.WFileName = WFileName; 146498527Sfenner dumpinfo.pd = pd; 146598527Sfenner dumpinfo.p = p; 146698527Sfenner pcap_userdata = (u_char *)&dumpinfo; 146798527Sfenner } else { 1468127675Sbms callback = dump_packet; 146998527Sfenner pcap_userdata = (u_char *)p; 147098527Sfenner } 1471236192Sdelphij#ifdef HAVE_PCAP_DUMP_FLUSH 1472236192Sdelphij if (Uflag) 1473236192Sdelphij pcap_dump_flush(p); 1474236192Sdelphij#endif 147517680Spst } else { 1476127675Sbms type = pcap_datalink(pd); 1477252283Sdelphij printinfo = get_print_info(type); 1478127675Sbms callback = print_packet; 1479127675Sbms pcap_userdata = (u_char *)&printinfo; 1480127675Sbms } 1481236192Sdelphij 1482242485Sdelphij#ifdef SIGNAL_REQ_INFO 1483190207Srpaulo /* 1484190207Srpaulo * We can't get statistics when reading from a file rather 1485190207Srpaulo * than capturing from a device. 1486190207Srpaulo */ 1487190207Srpaulo if (RFileName == NULL) 1488242485Sdelphij (void)setsignal(SIGNAL_REQ_INFO, requestinfo); 148998527Sfenner#endif 1490146778Ssam 1491146778Ssam if (vflag > 0 && WFileName) { 1492146778Ssam /* 1493146778Ssam * When capturing to a file, "-v" means tcpdump should, 1494146778Ssam * every 10 secodns, "v"erbosely report the number of 1495146778Ssam * packets captured. 1496146778Ssam */ 1497146778Ssam#ifdef USE_WIN32_MM_TIMER 1498146778Ssam /* call verbose_stats_dump() each 1000 +/-100msec */ 1499146778Ssam timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); 1500146778Ssam setvbuf(stderr, NULL, _IONBF, 0); 1501146778Ssam#elif defined(HAVE_ALARM) 1502146778Ssam (void)setsignal(SIGALRM, verbose_stats_dump); 1503146778Ssam alarm(1); 1504146778Ssam#endif 1505146778Ssam } 1506146778Ssam 1507127675Sbms#ifndef WIN32 150817680Spst if (RFileName == NULL) { 1509252283Sdelphij /* 1510252283Sdelphij * Live capture (if -V was specified, we set RFileName 1511252283Sdelphij * to a file from the -V file). Print a message to 1512252283Sdelphij * the standard error on UN*X. 1513252283Sdelphij */ 1514127675Sbms if (!vflag && !WFileName) { 1515127675Sbms (void)fprintf(stderr, 1516127675Sbms "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", 1517127675Sbms program_name); 1518127675Sbms } else 1519127675Sbms (void)fprintf(stderr, "%s: ", program_name); 1520127675Sbms dlt = pcap_datalink(pd); 1521127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1522127675Sbms if (dlt_name == NULL) { 1523127675Sbms (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", 1524127675Sbms device, dlt, snaplen); 1525127675Sbms } else { 1526127675Sbms (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", 1527127675Sbms device, dlt_name, 1528127675Sbms pcap_datalink_val_to_description(dlt), snaplen); 1529127675Sbms } 153017680Spst (void)fflush(stderr); 153117680Spst } 1532127675Sbms#endif /* WIN32 */ 1533252283Sdelphij do { 1534252283Sdelphij status = pcap_loop(pd, cnt, callback, pcap_userdata); 1535252283Sdelphij if (WFileName == NULL) { 1536127675Sbms /* 1537252283Sdelphij * We're printing packets. Flush the printed output, 1538252283Sdelphij * so it doesn't get intermingled with error output. 1539127675Sbms */ 1540252283Sdelphij if (status == -2) { 1541252283Sdelphij /* 1542252283Sdelphij * We got interrupted, so perhaps we didn't 1543252283Sdelphij * manage to finish a line we were printing. 1544252283Sdelphij * Print an extra newline, just in case. 1545252283Sdelphij */ 1546252283Sdelphij putchar('\n'); 1547252283Sdelphij } 1548252283Sdelphij (void)fflush(stdout); 1549127675Sbms } 1550252283Sdelphij if (status == -1) { 1551252283Sdelphij /* 1552252283Sdelphij * Error. Report it. 1553252283Sdelphij */ 1554252283Sdelphij (void)fprintf(stderr, "%s: pcap_loop: %s\n", 1555252283Sdelphij program_name, pcap_geterr(pd)); 1556252283Sdelphij } 1557252283Sdelphij if (RFileName == NULL) { 1558252283Sdelphij /* 1559252283Sdelphij * We're doing a live capture. Report the capture 1560252283Sdelphij * statistics. 1561252283Sdelphij */ 1562252283Sdelphij info(1); 1563252283Sdelphij } 1564252283Sdelphij pcap_close(pd); 1565252283Sdelphij if (VFileName != NULL) { 1566252283Sdelphij ret = get_next_file(VFile, VFileLine); 1567252283Sdelphij if (ret) { 1568252283Sdelphij RFileName = VFileLine; 1569252283Sdelphij pd = pcap_open_offline(RFileName, ebuf); 1570252283Sdelphij if (pd == NULL) 1571252283Sdelphij error("%s", ebuf); 1572252283Sdelphij new_dlt = pcap_datalink(pd); 1573252283Sdelphij if (WFileName && new_dlt != dlt) 1574252283Sdelphij error("%s: new dlt does not match original", RFileName); 1575252283Sdelphij printinfo = get_print_info(new_dlt); 1576252283Sdelphij dlt_name = pcap_datalink_val_to_name(new_dlt); 1577252283Sdelphij if (dlt_name == NULL) { 1578252283Sdelphij fprintf(stderr, "reading from file %s, link-type %u\n", 1579252283Sdelphij RFileName, new_dlt); 1580252283Sdelphij } else { 1581252283Sdelphij fprintf(stderr, 1582252283Sdelphij "reading from file %s, link-type %s (%s)\n", 1583252283Sdelphij RFileName, dlt_name, 1584252283Sdelphij pcap_datalink_val_to_description(new_dlt)); 1585252283Sdelphij } 1586252283Sdelphij if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 1587252283Sdelphij error("%s", pcap_geterr(pd)); 1588252283Sdelphij if (pcap_setfilter(pd, &fcode) < 0) 1589252283Sdelphij error("%s", pcap_geterr(pd)); 1590252283Sdelphij } 1591252283Sdelphij } 1592127675Sbms } 1593252283Sdelphij while (ret != NULL); 1594252283Sdelphij 1595252283Sdelphij free(cmdbuf); 1596127675Sbms exit(status == -1 ? 1 : 0); 159717680Spst} 159817680Spst 159917680Spst/* make a clean exit on interrupts */ 160075118Sfennerstatic RETSIGTYPE 1601127675Sbmscleanup(int signo _U_) 160217680Spst{ 1603146778Ssam#ifdef USE_WIN32_MM_TIMER 1604146778Ssam if (timer_id) 1605146778Ssam timeKillEvent(timer_id); 1606146778Ssam timer_id = 0; 1607146778Ssam#elif defined(HAVE_ALARM) 1608146778Ssam alarm(0); 1609146778Ssam#endif 1610146778Ssam 1611127675Sbms#ifdef HAVE_PCAP_BREAKLOOP 1612127675Sbms /* 1613127675Sbms * We have "pcap_breakloop()"; use it, so that we do as little 1614127675Sbms * as possible in the signal handler (it's probably not safe 1615127675Sbms * to do anything with standard I/O streams in a signal handler - 1616127675Sbms * the ANSI C standard doesn't say it is). 1617127675Sbms */ 1618127675Sbms pcap_breakloop(pd); 1619127675Sbms#else 1620127675Sbms /* 1621127675Sbms * We don't have "pcap_breakloop()"; this isn't safe, but 1622127675Sbms * it's the best we can do. Print the summary if we're 1623127675Sbms * not reading from a savefile - i.e., if we're doing a 1624127675Sbms * live capture - and exit. 1625127675Sbms */ 162617680Spst if (pd != NULL && pcap_file(pd) == NULL) { 1627127675Sbms /* 1628127675Sbms * We got interrupted, so perhaps we didn't 1629127675Sbms * manage to finish a line we were printing. 1630127675Sbms * Print an extra newline, just in case. 1631127675Sbms */ 1632127675Sbms putchar('\n'); 163317680Spst (void)fflush(stdout); 163498527Sfenner info(1); 163517680Spst } 163617680Spst exit(0); 1637127675Sbms#endif 163817680Spst} 163917680Spst 1640190207Srpaulo/* 1641190207Srpaulo On windows, we do not use a fork, so we do not care less about 1642190207Srpaulo waiting a child processes to die 1643190207Srpaulo */ 1644236192Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 1645190207Srpaulostatic RETSIGTYPE 1646190207Srpaulochild_cleanup(int signo _U_) 1647190207Srpaulo{ 1648190207Srpaulo wait(NULL); 1649190207Srpaulo} 1650236192Sdelphij#endif /* HAVE_FORK && HAVE_VFORK */ 1651190207Srpaulo 1652127675Sbmsstatic void 165398527Sfennerinfo(register int verbose) 165498527Sfenner{ 165598527Sfenner struct pcap_stat stat; 165698527Sfenner 1657214478Srpaulo /* 1658214478Srpaulo * Older versions of libpcap didn't set ps_ifdrop on some 1659214478Srpaulo * platforms; initialize it to 0 to handle that. 1660214478Srpaulo */ 1661214478Srpaulo stat.ps_ifdrop = 0; 166298527Sfenner if (pcap_stats(pd, &stat) < 0) { 166398527Sfenner (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); 1664173819Smlaier infoprint = 0; 166598527Sfenner return; 166698527Sfenner } 1667127675Sbms 166898527Sfenner if (!verbose) 166998527Sfenner fprintf(stderr, "%s: ", program_name); 1670127675Sbms 1671236192Sdelphij (void)fprintf(stderr, "%u packet%s captured", packets_captured, 1672236192Sdelphij PLURAL_SUFFIX(packets_captured)); 1673127675Sbms if (!verbose) 1674127675Sbms fputs(", ", stderr); 1675127675Sbms else 1676127675Sbms putc('\n', stderr); 1677236192Sdelphij (void)fprintf(stderr, "%u packet%s received by filter", stat.ps_recv, 1678236192Sdelphij PLURAL_SUFFIX(stat.ps_recv)); 167998527Sfenner if (!verbose) 168098527Sfenner fputs(", ", stderr); 168198527Sfenner else 168298527Sfenner putc('\n', stderr); 1683236192Sdelphij (void)fprintf(stderr, "%u packet%s dropped by kernel", stat.ps_drop, 1684236192Sdelphij PLURAL_SUFFIX(stat.ps_drop)); 1685214478Srpaulo if (stat.ps_ifdrop != 0) { 1686214478Srpaulo if (!verbose) 1687214478Srpaulo fputs(", ", stderr); 1688214478Srpaulo else 1689214478Srpaulo putc('\n', stderr); 1690236192Sdelphij (void)fprintf(stderr, "%u packet%s dropped by interface\n", 1691236192Sdelphij stat.ps_ifdrop, PLURAL_SUFFIX(stat.ps_ifdrop)); 1692214478Srpaulo } else 1693214478Srpaulo putc('\n', stderr); 169498527Sfenner infoprint = 0; 169598527Sfenner} 169698527Sfenner 1697236192Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 169898527Sfennerstatic void 1699190207Srpaulocompress_savefile(const char *filename) 1700190207Srpaulo{ 1701236192Sdelphij# ifdef HAVE_FORK 1702190207Srpaulo if (fork()) 1703236192Sdelphij# else 1704236192Sdelphij if (vfork()) 1705236192Sdelphij# endif 1706190207Srpaulo return; 1707190207Srpaulo /* 1708190207Srpaulo * Set to lowest priority so that this doesn't disturb the capture 1709190207Srpaulo */ 1710190207Srpaulo#ifdef NZERO 1711190207Srpaulo setpriority(PRIO_PROCESS, 0, NZERO - 1); 1712190207Srpaulo#else 1713190207Srpaulo setpriority(PRIO_PROCESS, 0, 19); 1714190207Srpaulo#endif 1715214478Srpaulo if (execlp(zflag, zflag, filename, (char *)NULL) == -1) 1716190207Srpaulo fprintf(stderr, 1717190207Srpaulo "compress_savefile:execlp(%s, %s): %s\n", 1718190207Srpaulo zflag, 1719190207Srpaulo filename, 1720190207Srpaulo strerror(errno)); 1721236192Sdelphij# ifdef HAVE_FORK 1722236192Sdelphij exit(1); 1723236192Sdelphij# else 1724236192Sdelphij _exit(1); 1725236192Sdelphij# endif 1726190207Srpaulo} 1727236192Sdelphij#else /* HAVE_FORK && HAVE_VFORK */ 1728190207Srpaulostatic void 1729190207Srpaulocompress_savefile(const char *filename) 1730190207Srpaulo{ 1731190207Srpaulo fprintf(stderr, 1732236192Sdelphij "compress_savefile failed. Functionality not implemented under your system\n"); 1733190207Srpaulo} 1734236192Sdelphij#endif /* HAVE_FORK && HAVE_VFORK */ 1735190207Srpaulo 1736190207Srpaulostatic void 1737127675Sbmsdump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 173898527Sfenner{ 1739127675Sbms struct dump_info *dump_info; 174098527Sfenner 1741127675Sbms ++packets_captured; 1742127675Sbms 1743127675Sbms ++infodelay; 1744127675Sbms 1745127675Sbms dump_info = (struct dump_info *)user; 1746127675Sbms 174798527Sfenner /* 1748190207Srpaulo * XXX - this won't force the file to rotate on the specified time 1749190207Srpaulo * boundary, but it will rotate on the first packet received after the 1750190207Srpaulo * specified Gflag number of seconds. Note: if a Gflag time boundary 1751190207Srpaulo * and a Cflag size boundary coincide, the time rotation will occur 1752190207Srpaulo * first thereby cancelling the Cflag boundary (since the file should 1753190207Srpaulo * be 0). 1754190207Srpaulo */ 1755190207Srpaulo if (Gflag != 0) { 1756190207Srpaulo /* Check if it is time to rotate */ 1757190207Srpaulo time_t t; 1758190207Srpaulo 1759190207Srpaulo /* Get the current time */ 1760190207Srpaulo if ((t = time(NULL)) == (time_t)-1) { 1761190207Srpaulo error("dump_and_trunc_packet: can't get current_time: %s", 1762190207Srpaulo pcap_strerror(errno)); 1763190207Srpaulo } 1764190207Srpaulo 1765190207Srpaulo 1766190207Srpaulo /* If the time is greater than the specified window, rotate */ 1767190207Srpaulo if (t - Gflag_time >= Gflag) { 1768190207Srpaulo /* Update the Gflag_time */ 1769190207Srpaulo Gflag_time = t; 1770190207Srpaulo /* Update Gflag_count */ 1771190207Srpaulo Gflag_count++; 1772190207Srpaulo /* 1773190207Srpaulo * Close the current file and open a new one. 1774190207Srpaulo */ 1775190207Srpaulo pcap_dump_close(dump_info->p); 1776190207Srpaulo 1777190207Srpaulo /* 1778190207Srpaulo * Compress the file we just closed, if the user asked for it 1779190207Srpaulo */ 1780190207Srpaulo if (zflag != NULL) 1781190207Srpaulo compress_savefile(dump_info->CurrentFileName); 1782190207Srpaulo 1783190207Srpaulo /* 1784190207Srpaulo * Check to see if we've exceeded the Wflag (when 1785190207Srpaulo * not using Cflag). 1786190207Srpaulo */ 1787190207Srpaulo if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) { 1788190207Srpaulo (void)fprintf(stderr, "Maximum file limit reached: %d\n", 1789190207Srpaulo Wflag); 1790190207Srpaulo exit(0); 1791190207Srpaulo /* NOTREACHED */ 1792190207Srpaulo } 1793190207Srpaulo if (dump_info->CurrentFileName != NULL) 1794190207Srpaulo free(dump_info->CurrentFileName); 1795190207Srpaulo /* Allocate space for max filename + \0. */ 1796252283Sdelphij dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); 1797190207Srpaulo if (dump_info->CurrentFileName == NULL) 1798190207Srpaulo error("dump_packet_and_trunc: malloc"); 1799190207Srpaulo /* 1800190207Srpaulo * This is always the first file in the Cflag 1801190207Srpaulo * rotation: e.g. 0 1802190207Srpaulo * We also don't need numbering if Cflag is not set. 1803190207Srpaulo */ 1804190207Srpaulo if (Cflag != 0) 1805190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 1806190207Srpaulo WflagChars); 1807190207Srpaulo else 1808190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); 1809190207Srpaulo 1810252283Sdelphij#ifdef HAVE_CAP_NG_H 1811252283Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); 1812252283Sdelphij capng_apply(CAPNG_EFFECTIVE); 1813252283Sdelphij#endif /* HAVE_CAP_NG_H */ 1814190207Srpaulo dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); 1815252283Sdelphij#ifdef HAVE_CAP_NG_H 1816252283Sdelphij capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); 1817252283Sdelphij capng_apply(CAPNG_EFFECTIVE); 1818252283Sdelphij#endif /* HAVE_CAP_NG_H */ 1819190207Srpaulo if (dump_info->p == NULL) 1820190207Srpaulo error("%s", pcap_geterr(pd)); 1821190207Srpaulo } 1822190207Srpaulo } 1823190207Srpaulo 1824190207Srpaulo /* 182598527Sfenner * XXX - this won't prevent capture files from getting 182698527Sfenner * larger than Cflag - the last packet written to the 182798527Sfenner * file could put it over Cflag. 182898527Sfenner */ 1829190207Srpaulo if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { 1830127675Sbms /* 1831127675Sbms * Close the current file and open a new one. 1832127675Sbms */ 1833127675Sbms pcap_dump_close(dump_info->p); 1834190207Srpaulo 1835190207Srpaulo /* 1836190207Srpaulo * Compress the file we just closed, if the user asked for it 1837190207Srpaulo */ 1838190207Srpaulo if (zflag != NULL) 1839190207Srpaulo compress_savefile(dump_info->CurrentFileName); 1840190207Srpaulo 1841146778Ssam Cflag_count++; 1842146778Ssam if (Wflag > 0) { 1843146778Ssam if (Cflag_count >= Wflag) 1844146778Ssam Cflag_count = 0; 1845146778Ssam } 1846190207Srpaulo if (dump_info->CurrentFileName != NULL) 1847190207Srpaulo free(dump_info->CurrentFileName); 1848252283Sdelphij dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); 1849190207Srpaulo if (dump_info->CurrentFileName == NULL) 1850127675Sbms error("dump_packet_and_trunc: malloc"); 1851190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); 1852190207Srpaulo dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); 1853127675Sbms if (dump_info->p == NULL) 185498527Sfenner error("%s", pcap_geterr(pd)); 185598527Sfenner } 185698527Sfenner 1857127675Sbms pcap_dump((u_char *)dump_info->p, h, sp); 1858127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1859127675Sbms if (Uflag) 1860127675Sbms pcap_dump_flush(dump_info->p); 1861127675Sbms#endif 1862127675Sbms 1863127675Sbms --infodelay; 1864127675Sbms if (infoprint) 1865127675Sbms info(0); 186698527Sfenner} 186798527Sfenner 1868127675Sbmsstatic void 1869127675Sbmsdump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 187017680Spst{ 1871127675Sbms ++packets_captured; 187217680Spst 1873127675Sbms ++infodelay; 1874127675Sbms 1875127675Sbms pcap_dump(user, h, sp); 1876127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1877127675Sbms if (Uflag) 1878127675Sbms pcap_dump_flush((pcap_dumper_t *)user); 1879127675Sbms#endif 1880127675Sbms 1881127675Sbms --infodelay; 1882127675Sbms if (infoprint) 1883127675Sbms info(0); 1884127675Sbms} 1885127675Sbms 1886127675Sbmsstatic void 1887127675Sbmsprint_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 1888127675Sbms{ 1889127675Sbms struct print_info *print_info; 1890127675Sbms u_int hdrlen; 1891127675Sbms 1892127675Sbms ++packets_captured; 1893127675Sbms 1894127675Sbms ++infodelay; 1895127675Sbms ts_print(&h->ts); 1896127675Sbms 1897127675Sbms print_info = (struct print_info *)user; 1898127675Sbms 1899127675Sbms /* 1900127675Sbms * Some printers want to check that they're not walking off the 1901127675Sbms * end of the packet. 1902127675Sbms * Rather than pass it all the way down, we set this global. 1903127675Sbms */ 1904127675Sbms snapend = sp + h->caplen; 1905127675Sbms 1906214478Srpaulo if(print_info->ndo_type) { 1907214478Srpaulo hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp); 1908214478Srpaulo } else { 1909214478Srpaulo hdrlen = (*print_info->p.printer)(h, sp); 1910214478Srpaulo } 1911214478Srpaulo 1912162021Ssam if (Xflag) { 1913127675Sbms /* 1914162021Ssam * Print the raw packet data in hex and ASCII. 1915127675Sbms */ 1916162021Ssam if (Xflag > 1) { 1917162021Ssam /* 1918162021Ssam * Include the link-layer header. 1919162021Ssam */ 1920162021Ssam hex_and_ascii_print("\n\t", sp, h->caplen); 1921162021Ssam } else { 1922162021Ssam /* 1923162021Ssam * Don't include the link-layer header - and if 1924162021Ssam * we have nothing past the link-layer header, 1925162021Ssam * print nothing. 1926162021Ssam */ 1927162021Ssam if (h->caplen > hdrlen) 1928162021Ssam hex_and_ascii_print("\n\t", sp + hdrlen, 1929162021Ssam h->caplen - hdrlen); 1930162021Ssam } 1931162021Ssam } else if (xflag) { 1932162021Ssam /* 1933162021Ssam * Print the raw packet data in hex. 1934162021Ssam */ 1935127675Sbms if (xflag > 1) { 1936127675Sbms /* 1937127675Sbms * Include the link-layer header. 1938127675Sbms */ 1939146778Ssam hex_print("\n\t", sp, h->caplen); 1940127675Sbms } else { 1941127675Sbms /* 1942127675Sbms * Don't include the link-layer header - and if 1943127675Sbms * we have nothing past the link-layer header, 1944127675Sbms * print nothing. 1945127675Sbms */ 1946127675Sbms if (h->caplen > hdrlen) 1947146778Ssam hex_print("\n\t", sp + hdrlen, 1948127675Sbms h->caplen - hdrlen); 1949127675Sbms } 1950162021Ssam } else if (Aflag) { 1951146778Ssam /* 1952162021Ssam * Print the raw packet data in ASCII. 1953146778Ssam */ 1954162021Ssam if (Aflag > 1) { 1955146778Ssam /* 1956146778Ssam * Include the link-layer header. 1957146778Ssam */ 1958162021Ssam ascii_print(sp, h->caplen); 1959146778Ssam } else { 1960146778Ssam /* 1961146778Ssam * Don't include the link-layer header - and if 1962146778Ssam * we have nothing past the link-layer header, 1963146778Ssam * print nothing. 1964146778Ssam */ 1965146778Ssam if (h->caplen > hdrlen) 1966162021Ssam ascii_print(sp + hdrlen, h->caplen - hdrlen); 1967146778Ssam } 196817680Spst } 1969127675Sbms 1970127675Sbms putchar('\n'); 1971127675Sbms 1972127675Sbms --infodelay; 1973127675Sbms if (infoprint) 1974127675Sbms info(0); 197517680Spst} 197617680Spst 1977127675Sbms#ifdef WIN32 1978127675Sbms /* 1979127675Sbms * XXX - there should really be libpcap calls to get the version 1980127675Sbms * number as a string (the string would be generated from #defines 1981127675Sbms * at run time, so that it's not generated from string constants 1982127675Sbms * in the library, as, on many UNIX systems, those constants would 1983127675Sbms * be statically linked into the application executable image, and 1984127675Sbms * would thus reflect the version of libpcap on the system on 1985127675Sbms * which the application was *linked*, not the system on which it's 1986127675Sbms * *running*. 1987127675Sbms * 1988127675Sbms * That routine should be documented, unlike the "version[]" 1989127675Sbms * string, so that UNIX vendors providing their own libpcaps 1990127675Sbms * don't omit it (as a couple of vendors have...). 1991127675Sbms * 1992127675Sbms * Packet.dll should perhaps also export a routine to return the 1993127675Sbms * version number of the Packet.dll code, to supply the 1994127675Sbms * "Wpcap_version" information on Windows. 1995127675Sbms */ 1996127675Sbms char WDversion[]="current-cvs.tcpdump.org"; 1997146778Ssam#if !defined(HAVE_GENERATED_VERSION) 1998127675Sbms char version[]="current-cvs.tcpdump.org"; 1999146778Ssam#endif 2000127675Sbms char pcap_version[]="current-cvs.tcpdump.org"; 2001146778Ssam char Wpcap_version[]="3.1"; 2002127675Sbms#endif 2003127675Sbms 200439297Sfenner/* 2005162021Ssam * By default, print the specified data out in hex and ASCII. 200639297Sfenner */ 2007146778Ssamstatic void 2008146778Ssamndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length) 2009146778Ssam{ 2010162021Ssam hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */ 2011146778Ssam} 2012146778Ssam 201317680Spstvoid 2014146778Ssamdefault_print(const u_char *bp, u_int length) 201517680Spst{ 2016146778Ssam ndo_default_print(gndo, bp, length); 201717680Spst} 201817680Spst 2019242485Sdelphij#ifdef SIGNAL_REQ_INFO 2020127675SbmsRETSIGTYPE requestinfo(int signo _U_) 202198527Sfenner{ 202298527Sfenner if (infodelay) 202398527Sfenner ++infoprint; 202498527Sfenner else 202598527Sfenner info(0); 202698527Sfenner} 202798527Sfenner#endif 202898527Sfenner 2029146778Ssam/* 2030146778Ssam * Called once each second in verbose mode while dumping to file 2031146778Ssam */ 2032146778Ssam#ifdef USE_WIN32_MM_TIMER 2033146778Ssamvoid CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, 2034190207Srpaulo DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) 2035146778Ssam{ 2036146778Ssam struct pcap_stat stat; 2037146778Ssam 2038146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 2039146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 2040146778Ssam} 2041146778Ssam#elif defined(HAVE_ALARM) 2042146778Ssamstatic void verbose_stats_dump(int sig _U_) 2043146778Ssam{ 2044146778Ssam struct pcap_stat stat; 2045146778Ssam 2046146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 2047146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 2048146778Ssam alarm(1); 2049146778Ssam} 2050146778Ssam#endif 2051146778Ssam 205275118Sfennerstatic void 205326180Sfennerusage(void) 205417680Spst{ 205517680Spst extern char version[]; 2056127675Sbms#ifndef HAVE_PCAP_LIB_VERSION 2057127675Sbms#if defined(WIN32) || defined(HAVE_PCAP_VERSION) 205839297Sfenner extern char pcap_version[]; 2059127675Sbms#else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 2060127675Sbms static char pcap_version[] = "unknown"; 2061127675Sbms#endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 2062127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 206317680Spst 2064127675Sbms#ifdef HAVE_PCAP_LIB_VERSION 2065146778Ssam#ifdef WIN32 2066146778Ssam (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 2067146778Ssam#else /* WIN32 */ 206839297Sfenner (void)fprintf(stderr, "%s version %s\n", program_name, version); 2069146778Ssam#endif /* WIN32 */ 2070146778Ssam (void)fprintf(stderr, "%s\n",pcap_lib_version()); 2071127675Sbms#else /* HAVE_PCAP_LIB_VERSION */ 2072127675Sbms#ifdef WIN32 2073127675Sbms (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 2074127675Sbms (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); 2075127675Sbms#else /* WIN32 */ 2076127675Sbms (void)fprintf(stderr, "%s version %s\n", program_name, version); 207739297Sfenner (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 2078127675Sbms#endif /* WIN32 */ 2079127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 208017680Spst (void)fprintf(stderr, 2081236192Sdelphij"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); 208217680Spst (void)fprintf(stderr, 2083190207Srpaulo"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); 208417680Spst (void)fprintf(stderr, 2085236192Sdelphij"\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ]\n"); 2086109842Sfenner (void)fprintf(stderr, 2087252283Sdelphij"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]\n"); 2088146778Ssam (void)fprintf(stderr, 2089236192Sdelphij"\t\t[ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); 2090190207Srpaulo (void)fprintf(stderr, 2091236192Sdelphij"\t\t[ -Z user ] [ expression ]\n"); 209298527Sfenner exit(1); 209317680Spst} 2094146778Ssam 2095146778Ssam 2096146778Ssam 2097146778Ssam/* VARARGS */ 2098146778Ssamstatic void 2099146778Ssamndo_error(netdissect_options *ndo _U_, const char *fmt, ...) 2100146778Ssam{ 2101146778Ssam va_list ap; 2102146778Ssam 2103146778Ssam (void)fprintf(stderr, "%s: ", program_name); 2104146778Ssam va_start(ap, fmt); 2105146778Ssam (void)vfprintf(stderr, fmt, ap); 2106146778Ssam va_end(ap); 2107146778Ssam if (*fmt) { 2108146778Ssam fmt += strlen(fmt); 2109146778Ssam if (fmt[-1] != '\n') 2110146778Ssam (void)fputc('\n', stderr); 2111146778Ssam } 2112146778Ssam exit(1); 2113146778Ssam /* NOTREACHED */ 2114146778Ssam} 2115146778Ssam 2116146778Ssam/* VARARGS */ 2117146778Ssamstatic void 2118146778Ssamndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) 2119146778Ssam{ 2120146778Ssam va_list ap; 2121146778Ssam 2122146778Ssam (void)fprintf(stderr, "%s: WARNING: ", program_name); 2123146778Ssam va_start(ap, fmt); 2124146778Ssam (void)vfprintf(stderr, fmt, ap); 2125146778Ssam va_end(ap); 2126146778Ssam if (*fmt) { 2127146778Ssam fmt += strlen(fmt); 2128146778Ssam if (fmt[-1] != '\n') 2129146778Ssam (void)fputc('\n', stderr); 2130146778Ssam } 2131146778Ssam} 2132