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> 71253004Spjd#ifdef __FreeBSD__ 72253004Spjd#include <sys/capability.h> 73253004Spjd#include <sys/ioccom.h> 74253827Srpaulo#include <sys/types.h> 75253827Srpaulo#include <sys/sysctl.h> 76253004Spjd#include <net/bpf.h> 77253004Spjd#include <fcntl.h> 78253004Spjd#include <libgen.h> 79253004Spjd#endif /* __FreeBSD__ */ 80146778Ssam#ifndef WIN32 81190207Srpaulo#include <sys/wait.h> 82190207Srpaulo#include <sys/resource.h> 83146778Ssam#include <pwd.h> 84146778Ssam#include <grp.h> 85146778Ssam#include <errno.h> 86146778Ssam#endif /* WIN32 */ 8717680Spst 88251158Sdelphij/* capabilities convinience library */ 89251158Sdelphij#ifdef HAVE_CAP_NG_H 90251158Sdelphij#include <cap-ng.h> 91251158Sdelphij#endif /* HAVE_CAP_NG_H */ 92190207Srpaulo 93146778Ssam#include "netdissect.h" 9417680Spst#include "interface.h" 9517680Spst#include "addrtoname.h" 9617680Spst#include "machdep.h" 9739297Sfenner#include "setsignal.h" 9839297Sfenner#include "gmt2local.h" 99127675Sbms#include "pcap-missing.h" 10017680Spst 101251158Sdelphij#ifndef PATH_MAX 102251158Sdelphij#define PATH_MAX 1024 103190207Srpaulo#endif 104190207Srpaulo 105241235Sdelphij#ifdef SIGINFO 106241235Sdelphij#define SIGNAL_REQ_INFO SIGINFO 107241235Sdelphij#elif SIGUSR1 108241235Sdelphij#define SIGNAL_REQ_INFO SIGUSR1 109241235Sdelphij#endif 110241235Sdelphij 111146778Ssamnetdissect_options Gndo; 112146778Ssamnetdissect_options *gndo = &Gndo; 113146778Ssam 114214478Srpaulostatic int dflag; /* print filter code */ 115214478Srpaulostatic int Lflag; /* list available data link types and exit */ 116235530Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 117235530Sdelphijstatic int Jflag; /* list available time stamp types */ 118235530Sdelphij#endif 119214478Srpaulostatic char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ 12039297Sfenner 121127675Sbmsstatic int infodelay; 122127675Sbmsstatic int infoprint; 12317680Spst 12417680Spstchar *program_name; 12517680Spst 12617680Spstint32_t thiszone; /* seconds offset from gmt to local time */ 12717680Spst 12817680Spst/* Forwards */ 12975118Sfennerstatic RETSIGTYPE cleanup(int); 130190207Srpaulostatic RETSIGTYPE child_cleanup(int); 13175118Sfennerstatic void usage(void) __attribute__((noreturn)); 132214478Srpaulostatic void show_dlts_and_exit(const char *device, pcap_t *pd) __attribute__((noreturn)); 13317680Spst 134127675Sbmsstatic void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 135146778Ssamstatic void ndo_default_print(netdissect_options *, const u_char *, u_int); 136127675Sbmsstatic void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); 137127675Sbmsstatic void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 138146778Ssamstatic void droproot(const char *, const char *); 139235530Sdelphijstatic void ndo_error(netdissect_options *ndo, const char *fmt, ...) 140235530Sdelphij __attribute__ ((noreturn, format (printf, 2, 3))); 141146778Ssamstatic void ndo_warning(netdissect_options *ndo, const char *fmt, ...); 14298527Sfenner 143241235Sdelphij#ifdef SIGNAL_REQ_INFO 14498527SfennerRETSIGTYPE requestinfo(int); 14598527Sfenner#endif 14698527Sfenner 147146778Ssam#if defined(USE_WIN32_MM_TIMER) 148146778Ssam #include <MMsystem.h> 149146778Ssam static UINT timer_id; 150146778Ssam static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); 151146778Ssam#elif defined(HAVE_ALARM) 152146778Ssam static void verbose_stats_dump(int sig); 153146778Ssam#endif 154146778Ssam 155127675Sbmsstatic void info(int); 156127675Sbmsstatic u_int packets_captured; 157127675Sbms 15817680Spststruct printer { 159214478Srpaulo if_printer f; 16017680Spst int type; 16117680Spst}; 16217680Spst 163214478Srpaulo 164214478Srpaulostruct ndo_printer { 165214478Srpaulo if_ndo_printer f; 166214478Srpaulo int type; 167214478Srpaulo}; 168214478Srpaulo 169214478Srpaulo 17017680Spststatic struct printer printers[] = { 17198527Sfenner { arcnet_if_print, DLT_ARCNET }, 172127675Sbms#ifdef DLT_ARCNET_LINUX 173127675Sbms { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 174127675Sbms#endif 17544165Sjulian { token_if_print, DLT_IEEE802 }, 17656896Sfenner#ifdef DLT_LANE8023 17756896Sfenner { lane_if_print, DLT_LANE8023 }, 17856896Sfenner#endif 17956896Sfenner#ifdef DLT_CIP 18056896Sfenner { cip_if_print, DLT_CIP }, 18156896Sfenner#endif 18275118Sfenner#ifdef DLT_ATM_CLIP 183214478Srpaulo { cip_if_print, DLT_ATM_CLIP }, 18475118Sfenner#endif 18517680Spst { sl_if_print, DLT_SLIP }, 186127675Sbms#ifdef DLT_SLIP_BSDOS 18739297Sfenner { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 188127675Sbms#endif 18917680Spst { ppp_if_print, DLT_PPP }, 190146778Ssam#ifdef DLT_PPP_WITHDIRECTION 191146778Ssam { ppp_if_print, DLT_PPP_WITHDIRECTION }, 192146778Ssam#endif 193127675Sbms#ifdef DLT_PPP_BSDOS 19439297Sfenner { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 195127675Sbms#endif 19617680Spst { fddi_if_print, DLT_FDDI }, 19717680Spst { null_if_print, DLT_NULL }, 19875118Sfenner#ifdef DLT_LOOP 19975118Sfenner { null_if_print, DLT_LOOP }, 20075118Sfenner#endif 20139297Sfenner { raw_if_print, DLT_RAW }, 20217680Spst { atm_if_print, DLT_ATM_RFC1483 }, 20375118Sfenner#ifdef DLT_C_HDLC 20475118Sfenner { chdlc_if_print, DLT_C_HDLC }, 20556896Sfenner#endif 20698527Sfenner#ifdef DLT_HDLC 20798527Sfenner { chdlc_if_print, DLT_HDLC }, 20898527Sfenner#endif 20975118Sfenner#ifdef DLT_PPP_SERIAL 210214478Srpaulo { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 21175118Sfenner#endif 21298527Sfenner#ifdef DLT_PPP_ETHER 21398527Sfenner { pppoe_if_print, DLT_PPP_ETHER }, 21498527Sfenner#endif 21575118Sfenner#ifdef DLT_LINUX_SLL 21675118Sfenner { sll_if_print, DLT_LINUX_SLL }, 21775118Sfenner#endif 21898527Sfenner#ifdef DLT_IEEE802_11 21998527Sfenner { ieee802_11_if_print, DLT_IEEE802_11}, 22098527Sfenner#endif 22198527Sfenner#ifdef DLT_LTALK 22298527Sfenner { ltalk_if_print, DLT_LTALK }, 22398527Sfenner#endif 224172686Smlaier#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) 225214478Srpaulo { pflog_if_print, DLT_PFLOG }, 226127675Sbms#endif 227127675Sbms#ifdef DLT_FR 228127675Sbms { fr_if_print, DLT_FR }, 229127675Sbms#endif 230127675Sbms#ifdef DLT_FRELAY 231127675Sbms { fr_if_print, DLT_FRELAY }, 232127675Sbms#endif 233127675Sbms#ifdef DLT_SUNATM 234127675Sbms { sunatm_if_print, DLT_SUNATM }, 235127675Sbms#endif 236127675Sbms#ifdef DLT_IP_OVER_FC 237127675Sbms { ipfc_if_print, DLT_IP_OVER_FC }, 238127675Sbms#endif 239127675Sbms#ifdef DLT_PRISM_HEADER 240127675Sbms { prism_if_print, DLT_PRISM_HEADER }, 241127675Sbms#endif 242127675Sbms#ifdef DLT_IEEE802_11_RADIO 243127675Sbms { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 244127675Sbms#endif 245127675Sbms#ifdef DLT_ENC 246214478Srpaulo { enc_if_print, DLT_ENC }, 247127675Sbms#endif 248146778Ssam#ifdef DLT_SYMANTEC_FIREWALL 249214478Srpaulo { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 250146778Ssam#endif 251127675Sbms#ifdef DLT_APPLE_IP_OVER_IEEE1394 252127675Sbms { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 253127675Sbms#endif 254190207Srpaulo#ifdef DLT_IEEE802_11_RADIO_AVS 255190207Srpaulo { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, 256190207Srpaulo#endif 257146778Ssam#ifdef DLT_JUNIPER_ATM1 258146778Ssam { juniper_atm1_print, DLT_JUNIPER_ATM1 }, 259146778Ssam#endif 260146778Ssam#ifdef DLT_JUNIPER_ATM2 261146778Ssam { juniper_atm2_print, DLT_JUNIPER_ATM2 }, 262146778Ssam#endif 263147904Ssam#ifdef DLT_JUNIPER_MFR 264147904Ssam { juniper_mfr_print, DLT_JUNIPER_MFR }, 265147904Ssam#endif 266146778Ssam#ifdef DLT_JUNIPER_MLFR 267146778Ssam { juniper_mlfr_print, DLT_JUNIPER_MLFR }, 268146778Ssam#endif 269146778Ssam#ifdef DLT_JUNIPER_MLPPP 270146778Ssam { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, 271146778Ssam#endif 272147904Ssam#ifdef DLT_JUNIPER_PPPOE 273147904Ssam { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, 274147904Ssam#endif 275147904Ssam#ifdef DLT_JUNIPER_PPPOE_ATM 276147904Ssam { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, 277147904Ssam#endif 278147904Ssam#ifdef DLT_JUNIPER_GGSN 279147904Ssam { juniper_ggsn_print, DLT_JUNIPER_GGSN }, 280147904Ssam#endif 281147904Ssam#ifdef DLT_JUNIPER_ES 282147904Ssam { juniper_es_print, DLT_JUNIPER_ES }, 283147904Ssam#endif 284147904Ssam#ifdef DLT_JUNIPER_MONITOR 285147904Ssam { juniper_monitor_print, DLT_JUNIPER_MONITOR }, 286147904Ssam#endif 287147904Ssam#ifdef DLT_JUNIPER_SERVICES 288147904Ssam { juniper_services_print, DLT_JUNIPER_SERVICES }, 289147904Ssam#endif 290162021Ssam#ifdef DLT_JUNIPER_ETHER 291214478Srpaulo { juniper_ether_print, DLT_JUNIPER_ETHER }, 292162021Ssam#endif 293162021Ssam#ifdef DLT_JUNIPER_PPP 294214478Srpaulo { juniper_ppp_print, DLT_JUNIPER_PPP }, 295162021Ssam#endif 296162021Ssam#ifdef DLT_JUNIPER_FRELAY 297214478Srpaulo { juniper_frelay_print, DLT_JUNIPER_FRELAY }, 298162021Ssam#endif 299162021Ssam#ifdef DLT_JUNIPER_CHDLC 300214478Srpaulo { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, 301162021Ssam#endif 302172686Smlaier#ifdef DLT_MFR 303214478Srpaulo { mfr_if_print, DLT_MFR }, 304172686Smlaier#endif 305190207Srpaulo#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) 306214478Srpaulo { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, 307190207Srpaulo#endif 308214478Srpaulo#ifdef HAVE_PCAP_USB_H 309214478Srpaulo#ifdef DLT_USB_LINUX 310214478Srpaulo { usb_linux_48_byte_print, DLT_USB_LINUX}, 311214478Srpaulo#endif /* DLT_USB_LINUX */ 312214478Srpaulo#ifdef DLT_USB_LINUX_MMAPPED 313214478Srpaulo { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED}, 314214478Srpaulo#endif /* DLT_USB_LINUX_MMAPPED */ 315214478Srpaulo#endif /* HAVE_PCAP_USB_H */ 316214478Srpaulo#ifdef DLT_IPV4 317214478Srpaulo { raw_if_print, DLT_IPV4 }, 318214478Srpaulo#endif 319214478Srpaulo#ifdef DLT_IPV6 320214478Srpaulo { raw_if_print, DLT_IPV6 }, 321214478Srpaulo#endif 32217680Spst { NULL, 0 }, 32317680Spst}; 32417680Spst 325214478Srpaulostatic struct ndo_printer ndo_printers[] = { 326235530Sdelphij { ether_if_print, DLT_EN10MB }, 327214478Srpaulo#ifdef DLT_IPNET 328214478Srpaulo { ipnet_if_print, DLT_IPNET }, 329214478Srpaulo#endif 330235530Sdelphij#ifdef DLT_IEEE802_15_4 331235530Sdelphij { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, 332235530Sdelphij#endif 333235530Sdelphij#ifdef DLT_IEEE802_15_4_NOFCS 334235530Sdelphij { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, 335235530Sdelphij#endif 336235530Sdelphij#ifdef DLT_PPI 337235530Sdelphij { ppi_if_print, DLT_PPI }, 338235530Sdelphij#endif 339235530Sdelphij#ifdef DLT_NETANALYZER 340235530Sdelphij { netanalyzer_if_print, DLT_NETANALYZER }, 341235530Sdelphij#endif 342235530Sdelphij#ifdef DLT_NETANALYZER_TRANSPARENT 343235530Sdelphij { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, 344235530Sdelphij#endif 345214478Srpaulo { NULL, 0 }, 346214478Srpaulo}; 347214478Srpaulo 348235530Sdelphijif_printer 34917680Spstlookup_printer(int type) 35017680Spst{ 35117680Spst struct printer *p; 35217680Spst 35317680Spst for (p = printers; p->f; ++p) 35417680Spst if (type == p->type) 35517680Spst return p->f; 35617680Spst 357127675Sbms return NULL; 35817680Spst /* NOTREACHED */ 35917680Spst} 36017680Spst 361235530Sdelphijif_ndo_printer 362214478Srpaulolookup_ndo_printer(int type) 363214478Srpaulo{ 364214478Srpaulo struct ndo_printer *p; 365214478Srpaulo 366214478Srpaulo for (p = ndo_printers; p->f; ++p) 367214478Srpaulo if (type == p->type) 368214478Srpaulo return p->f; 369214478Srpaulo 370214478Srpaulo return NULL; 371214478Srpaulo /* NOTREACHED */ 372214478Srpaulo} 373214478Srpaulo 37417680Spststatic pcap_t *pd; 37517680Spst 376214478Srpaulostatic int supports_monitor_mode; 377214478Srpaulo 37817680Spstextern int optind; 37917680Spstextern int opterr; 38017680Spstextern char *optarg; 38117680Spst 382127675Sbmsstruct print_info { 383214478Srpaulo netdissect_options *ndo; 384214478Srpaulo union { 385214478Srpaulo if_printer printer; 386214478Srpaulo if_ndo_printer ndo_printer; 387214478Srpaulo } p; 388214478Srpaulo int ndo_type; 389127675Sbms}; 390127675Sbms 39198527Sfennerstruct dump_info { 39298527Sfenner char *WFileName; 393190207Srpaulo char *CurrentFileName; 39498527Sfenner pcap_t *pd; 39598527Sfenner pcap_dumper_t *p; 396253004Spjd#ifdef __FreeBSD__ 397253004Spjd int dirfd; 398253004Spjd#endif 39998527Sfenner}; 40098527Sfenner 401235530Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 402109842Sfennerstatic void 403235530Sdelphijshow_tstamp_types_and_exit(const char *device, pcap_t *pd) 404235530Sdelphij{ 405235530Sdelphij int n_tstamp_types; 406235530Sdelphij int *tstamp_types = 0; 407235530Sdelphij const char *tstamp_type_name; 408235530Sdelphij int i; 409235530Sdelphij 410235530Sdelphij n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types); 411235530Sdelphij if (n_tstamp_types < 0) 412235530Sdelphij error("%s", pcap_geterr(pd)); 413235530Sdelphij 414235530Sdelphij if (n_tstamp_types == 0) { 415235530Sdelphij fprintf(stderr, "Time stamp type cannot be set for %s\n", 416235530Sdelphij device); 417235530Sdelphij exit(0); 418235530Sdelphij } 419235530Sdelphij fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", 420235530Sdelphij device); 421235530Sdelphij for (i = 0; i < n_tstamp_types; i++) { 422235530Sdelphij tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); 423235530Sdelphij if (tstamp_type_name != NULL) { 424235530Sdelphij (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, 425235530Sdelphij pcap_tstamp_type_val_to_description(tstamp_types[i])); 426235530Sdelphij } else { 427235530Sdelphij (void) fprintf(stderr, " %d\n", tstamp_types[i]); 428235530Sdelphij } 429235530Sdelphij } 430235530Sdelphij pcap_free_tstamp_types(tstamp_types); 431235530Sdelphij exit(0); 432235530Sdelphij} 433235530Sdelphij#endif 434235530Sdelphij 435235530Sdelphijstatic void 436214478Srpauloshow_dlts_and_exit(const char *device, pcap_t *pd) 437109842Sfenner{ 438127675Sbms int n_dlts; 439109842Sfenner int *dlts = 0; 440127675Sbms const char *dlt_name; 441127675Sbms 442109842Sfenner n_dlts = pcap_list_datalinks(pd, &dlts); 443109842Sfenner if (n_dlts < 0) 444109842Sfenner error("%s", pcap_geterr(pd)); 445109842Sfenner else if (n_dlts == 0 || !dlts) 446109842Sfenner error("No data link types."); 447109842Sfenner 448214478Srpaulo /* 449214478Srpaulo * If the interface is known to support monitor mode, indicate 450214478Srpaulo * whether these are the data link types available when not in 451214478Srpaulo * monitor mode, if -I wasn't specified, or when in monitor mode, 452214478Srpaulo * when -I was specified (the link-layer types available in 453214478Srpaulo * monitor mode might be different from the ones available when 454214478Srpaulo * not in monitor mode). 455214478Srpaulo */ 456214478Srpaulo if (supports_monitor_mode) 457214478Srpaulo (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", 458214478Srpaulo device, 459214478Srpaulo Iflag ? "when in monitor mode" : "when not in monitor mode"); 460214478Srpaulo else 461214478Srpaulo (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", 462214478Srpaulo device); 463109842Sfenner 464109842Sfenner while (--n_dlts >= 0) { 465127675Sbms dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); 466127675Sbms if (dlt_name != NULL) { 467127675Sbms (void) fprintf(stderr, " %s (%s)", dlt_name, 468127675Sbms pcap_datalink_val_to_description(dlts[n_dlts])); 469127675Sbms 470127675Sbms /* 471127675Sbms * OK, does tcpdump handle that type? 472127675Sbms */ 473214478Srpaulo if (lookup_printer(dlts[n_dlts]) == NULL 474214478Srpaulo && lookup_ndo_printer(dlts[n_dlts]) == NULL) 475190207Srpaulo (void) fprintf(stderr, " (printing not supported)"); 476235530Sdelphij fprintf(stderr, "\n"); 477127675Sbms } else { 478190207Srpaulo (void) fprintf(stderr, " DLT %d (printing not supported)\n", 479127675Sbms dlts[n_dlts]); 480109842Sfenner } 481109842Sfenner } 482251158Sdelphij#ifdef HAVE_PCAP_FREE_DATALINKS 483235530Sdelphij pcap_free_datalinks(dlts); 484251158Sdelphij#endif 485109842Sfenner exit(0); 486109842Sfenner} 487109842Sfenner 488127675Sbms/* 489127675Sbms * Set up flags that might or might not be supported depending on the 490127675Sbms * version of libpcap we're using. 491127675Sbms */ 492190207Srpaulo#if defined(HAVE_PCAP_CREATE) || defined(WIN32) 493127675Sbms#define B_FLAG "B:" 494127675Sbms#define B_FLAG_USAGE " [ -B size ]" 495190207Srpaulo#else /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 496127675Sbms#define B_FLAG 497127675Sbms#define B_FLAG_USAGE 498190207Srpaulo#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 499127675Sbms 500190207Srpaulo#ifdef HAVE_PCAP_CREATE 501190207Srpaulo#define I_FLAG "I" 502190207Srpaulo#else /* HAVE_PCAP_CREATE */ 503190207Srpaulo#define I_FLAG 504190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 505190207Srpaulo 506235530Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 507235530Sdelphij#define j_FLAG "j:" 508235530Sdelphij#define j_FLAG_USAGE " [ -j tstamptype ]" 509235530Sdelphij#define J_FLAG "J" 510235530Sdelphij#else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ 511235530Sdelphij#define j_FLAG 512235530Sdelphij#define j_FLAG_USAGE 513235530Sdelphij#define J_FLAG 514235530Sdelphij#endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ 515235530Sdelphij 516127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 517146778Ssam#ifndef HAVE_PCAP_IF_T 518146778Ssam#undef HAVE_PCAP_FINDALLDEVS 519146778Ssam#endif 520146778Ssam#endif 521146778Ssam 522146778Ssam#ifdef HAVE_PCAP_FINDALLDEVS 523127675Sbms#define D_FLAG "D" 524127675Sbms#else 525127675Sbms#define D_FLAG 526127675Sbms#endif 527127675Sbms 528127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 529127675Sbms#define U_FLAG "U" 530127675Sbms#else 531127675Sbms#define U_FLAG 532127675Sbms#endif 533127675Sbms 534146778Ssam#ifndef WIN32 535146778Ssam/* Drop root privileges and chroot if necessary */ 536146778Ssamstatic void 537146778Ssamdroproot(const char *username, const char *chroot_dir) 538146778Ssam{ 539146778Ssam struct passwd *pw = NULL; 540146778Ssam 541146778Ssam if (chroot_dir && !username) { 542146778Ssam fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); 543146778Ssam exit(1); 544146778Ssam } 545146778Ssam 546146778Ssam pw = getpwnam(username); 547146778Ssam if (pw) { 548146778Ssam if (chroot_dir) { 549146778Ssam if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { 550146778Ssam fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", 551146778Ssam chroot_dir, pcap_strerror(errno)); 552146778Ssam exit(1); 553146778Ssam } 554146778Ssam } 555251158Sdelphij#ifdef HAVE_CAP_NG_H 556251158Sdelphij int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); 557251158Sdelphij if (ret < 0) { 558251158Sdelphij printf("error : ret %d\n", ret); 559251158Sdelphij } 560251158Sdelphij /* We don't need CAP_SETUID and CAP_SETGID */ 561251158Sdelphij capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); 562251158Sdelphij capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); 563251158Sdelphij capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); 564251158Sdelphij capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); 565251158Sdelphij capng_apply(CAPNG_SELECT_BOTH); 566251158Sdelphij 567251158Sdelphij#else 568146778Ssam if (initgroups(pw->pw_name, pw->pw_gid) != 0 || 569146778Ssam setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { 570146778Ssam fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", 571146778Ssam username, 572146778Ssam (unsigned long)pw->pw_uid, 573146778Ssam (unsigned long)pw->pw_gid, 574146778Ssam pcap_strerror(errno)); 575146778Ssam exit(1); 576146778Ssam } 577251158Sdelphij#endif /* HAVE_CAP_NG_H */ 578146778Ssam } 579146778Ssam else { 580146778Ssam fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", 581146778Ssam username); 582146778Ssam exit(1); 583146778Ssam } 584146778Ssam} 585146778Ssam#endif /* WIN32 */ 586146778Ssam 587146778Ssamstatic int 588146778SsamgetWflagChars(int x) 589146778Ssam{ 590146778Ssam int c = 0; 591146778Ssam 592146778Ssam x -= 1; 593146778Ssam while (x > 0) { 594146778Ssam c += 1; 595146778Ssam x /= 10; 596146778Ssam } 597146778Ssam 598146778Ssam return c; 599146778Ssam} 600146778Ssam 601146778Ssam 602146778Ssamstatic void 603146778SsamMakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) 604146778Ssam{ 605251158Sdelphij char *filename = malloc(PATH_MAX + 1); 606251158Sdelphij if (filename == NULL) 607251158Sdelphij error("Makefilename: malloc"); 608190207Srpaulo 609190207Srpaulo /* Process with strftime if Gflag is set. */ 610190207Srpaulo if (Gflag != 0) { 611190207Srpaulo struct tm *local_tm; 612190207Srpaulo 613190207Srpaulo /* Convert Gflag_time to a usable format */ 614190207Srpaulo if ((local_tm = localtime(&Gflag_time)) == NULL) { 615190207Srpaulo error("MakeTimedFilename: localtime"); 616190207Srpaulo } 617190207Srpaulo 618190207Srpaulo /* There's no good way to detect an error in strftime since a return 619190207Srpaulo * value of 0 isn't necessarily failure. 620190207Srpaulo */ 621251158Sdelphij strftime(filename, PATH_MAX, orig_name, local_tm); 622190207Srpaulo } else { 623251158Sdelphij strncpy(filename, orig_name, PATH_MAX); 624190207Srpaulo } 625190207Srpaulo 626146778Ssam if (cnt == 0 && max_chars == 0) 627251158Sdelphij strncpy(buffer, filename, PATH_MAX + 1); 628146778Ssam else 629251158Sdelphij if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) 630190207Srpaulo /* Report an error if the filename is too large */ 631251158Sdelphij error("too many output files or filename is too long (> %d)", PATH_MAX); 632190207Srpaulo free(filename); 633146778Ssam} 634146778Ssam 635146778Ssamstatic int tcpdump_printf(netdissect_options *ndo _U_, 636146778Ssam const char *fmt, ...) 637146778Ssam{ 638146778Ssam 639146778Ssam va_list args; 640146778Ssam int ret; 641146778Ssam 642146778Ssam va_start(args, fmt); 643146778Ssam ret=vfprintf(stdout, fmt, args); 644146778Ssam va_end(args); 645146778Ssam 646146778Ssam return ret; 647146778Ssam} 648146778Ssam 649251158Sdelphijstatic struct print_info 650251158Sdelphijget_print_info(int type) 651251158Sdelphij{ 652251158Sdelphij struct print_info printinfo; 653251158Sdelphij 654251158Sdelphij printinfo.ndo_type = 1; 655251158Sdelphij printinfo.ndo = gndo; 656251158Sdelphij printinfo.p.ndo_printer = lookup_ndo_printer(type); 657251158Sdelphij if (printinfo.p.ndo_printer == NULL) { 658251158Sdelphij printinfo.p.printer = lookup_printer(type); 659251158Sdelphij printinfo.ndo_type = 0; 660251158Sdelphij if (printinfo.p.printer == NULL) { 661251158Sdelphij gndo->ndo_dltname = pcap_datalink_val_to_name(type); 662251158Sdelphij if (gndo->ndo_dltname != NULL) 663251158Sdelphij error("packet printing is not supported for link type %s: use -w", 664251158Sdelphij gndo->ndo_dltname); 665251158Sdelphij else 666251158Sdelphij error("packet printing is not supported for link type %d: use -w", type); 667251158Sdelphij } 668251158Sdelphij } 669251158Sdelphij return (printinfo); 670251158Sdelphij} 671251158Sdelphij 672251158Sdelphijstatic char * 673251158Sdelphijget_next_file(FILE *VFile, char *ptr) 674251158Sdelphij{ 675251158Sdelphij char *ret; 676251158Sdelphij 677251158Sdelphij ret = fgets(ptr, PATH_MAX, VFile); 678251158Sdelphij if (!ret) 679251158Sdelphij return NULL; 680251158Sdelphij 681251158Sdelphij if (ptr[strlen(ptr) - 1] == '\n') 682251158Sdelphij ptr[strlen(ptr) - 1] = '\0'; 683251158Sdelphij 684251158Sdelphij return ret; 685251158Sdelphij} 686251158Sdelphij 68717680Spstint 68817680Spstmain(int argc, char **argv) 68917680Spst{ 69017680Spst register int cnt, op, i; 69117680Spst bpf_u_int32 localnet, netmask; 692251158Sdelphij register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; 693127675Sbms pcap_handler callback; 694127675Sbms int type; 695251158Sdelphij int dlt; 696251158Sdelphij int new_dlt; 697251158Sdelphij const char *dlt_name; 69817680Spst struct bpf_program fcode; 699127675Sbms#ifndef WIN32 70039297Sfenner RETSIGTYPE (*oldhandler)(int); 701127675Sbms#endif 702127675Sbms struct print_info printinfo; 70398527Sfenner struct dump_info dumpinfo; 70417680Spst u_char *pcap_userdata; 70517680Spst char ebuf[PCAP_ERRBUF_SIZE]; 706251158Sdelphij char VFileLine[PATH_MAX + 1]; 707146778Ssam char *username = NULL; 708146778Ssam char *chroot_dir = NULL; 709251158Sdelphij char *ret = NULL; 710251158Sdelphij char *end; 711127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 712127675Sbms pcap_if_t *devpointer; 713127675Sbms int devnum; 714127675Sbms#endif 715127675Sbms int status; 716251158Sdelphij FILE *VFile; 717253004Spjd#ifdef __FreeBSD__ 718255219Spjd cap_rights_t rights; 719253004Spjd int cansandbox; 720255219Spjd#endif /* __FreeBSD__ */ 721253004Spjd 722127675Sbms#ifdef WIN32 723127675Sbms if(wsockinit() != 0) return 1; 724127675Sbms#endif /* WIN32 */ 72517680Spst 726235530Sdelphij jflag=-1; /* not set */ 727146778Ssam gndo->ndo_Oflag=1; 728146778Ssam gndo->ndo_Rflag=1; 729146778Ssam gndo->ndo_dlt=-1; 730146778Ssam gndo->ndo_default_print=ndo_default_print; 731146778Ssam gndo->ndo_printf=tcpdump_printf; 732146778Ssam gndo->ndo_error=ndo_error; 733146778Ssam gndo->ndo_warning=ndo_warning; 734146778Ssam gndo->ndo_snaplen = DEFAULT_SNAPLEN; 735146778Ssam 73617680Spst cnt = -1; 73717680Spst device = NULL; 73817680Spst infile = NULL; 73917680Spst RFileName = NULL; 740251158Sdelphij VFileName = NULL; 741251158Sdelphij VFile = NULL; 74217680Spst WFileName = NULL; 743251158Sdelphij dlt = -1; 74417680Spst if ((cp = strrchr(argv[0], '/')) != NULL) 74517680Spst program_name = cp + 1; 74617680Spst else 74717680Spst program_name = argv[0]; 74817680Spst 74975118Sfenner if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) 75026180Sfenner error("%s", ebuf); 75117680Spst 75256896Sfenner#ifdef LIBSMI 75356896Sfenner smiInit("tcpdump"); 75456896Sfenner#endif 755127675Sbms 75639297Sfenner while ( 757251158Sdelphij (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) 75817680Spst switch (op) { 75939297Sfenner 76039297Sfenner case 'a': 761127675Sbms /* compatibility for old -a */ 76239297Sfenner break; 76339297Sfenner 764127675Sbms case 'A': 765127675Sbms ++Aflag; 766127675Sbms break; 767127675Sbms 768214478Srpaulo case 'b': 769214478Srpaulo ++bflag; 770214478Srpaulo break; 771214478Srpaulo 772190207Srpaulo#if defined(HAVE_PCAP_CREATE) || defined(WIN32) 773127675Sbms case 'B': 774190207Srpaulo Bflag = atoi(optarg)*1024; 775190207Srpaulo if (Bflag <= 0) 776127675Sbms error("invalid packet buffer size %s", optarg); 777127675Sbms break; 778190207Srpaulo#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ 779127675Sbms 78017680Spst case 'c': 78117680Spst cnt = atoi(optarg); 78217680Spst if (cnt <= 0) 78317680Spst error("invalid packet count %s", optarg); 78417680Spst break; 78517680Spst 78698527Sfenner case 'C': 78798527Sfenner Cflag = atoi(optarg) * 1000000; 788127675Sbms if (Cflag < 0) 78998527Sfenner error("invalid file size %s", optarg); 79098527Sfenner break; 79198527Sfenner 79217680Spst case 'd': 79317680Spst ++dflag; 79417680Spst break; 79517680Spst 796127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 797127675Sbms case 'D': 798127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 799127675Sbms error("%s", ebuf); 800127675Sbms else { 801127675Sbms for (i = 0; devpointer != 0; i++) { 802127675Sbms printf("%d.%s", i+1, devpointer->name); 803127675Sbms if (devpointer->description != NULL) 804127675Sbms printf(" (%s)", devpointer->description); 805127675Sbms printf("\n"); 806127675Sbms devpointer = devpointer->next; 807127675Sbms } 808127675Sbms } 809127675Sbms return 0; 810127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 811127675Sbms 812109842Sfenner case 'L': 813109842Sfenner Lflag++; 814109842Sfenner break; 815109842Sfenner 81617680Spst case 'e': 81717680Spst ++eflag; 81817680Spst break; 81917680Spst 82056896Sfenner case 'E': 82175118Sfenner#ifndef HAVE_LIBCRYPTO 82256896Sfenner warning("crypto code not compiled in"); 82356896Sfenner#endif 824146778Ssam gndo->ndo_espsecret = optarg; 82556896Sfenner break; 82656896Sfenner 82717680Spst case 'f': 82817680Spst ++fflag; 82917680Spst break; 83017680Spst 83117680Spst case 'F': 83217680Spst infile = optarg; 83317680Spst break; 83417680Spst 835190207Srpaulo case 'G': 836190207Srpaulo Gflag = atoi(optarg); 837190207Srpaulo if (Gflag < 0) 838190207Srpaulo error("invalid number of seconds %s", optarg); 839190207Srpaulo 840190207Srpaulo /* We will create one file initially. */ 841190207Srpaulo Gflag_count = 0; 842190207Srpaulo 843190207Srpaulo /* Grab the current time for rotation use. */ 844190207Srpaulo if ((Gflag_time = time(NULL)) == (time_t)-1) { 845190207Srpaulo error("main: can't get current time: %s", 846190207Srpaulo pcap_strerror(errno)); 847190207Srpaulo } 848190207Srpaulo break; 849190207Srpaulo 850235530Sdelphij case 'h': 851235530Sdelphij usage(); 852235530Sdelphij break; 853235530Sdelphij 854235530Sdelphij case 'H': 855235530Sdelphij ++Hflag; 856235530Sdelphij break; 857235530Sdelphij 85817680Spst case 'i': 859127675Sbms if (optarg[0] == '0' && optarg[1] == 0) 860127675Sbms error("Invalid adapter index"); 861127675Sbms 862127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 863127675Sbms /* 864127675Sbms * If the argument is a number, treat it as 865127675Sbms * an index into the list of adapters, as 866127675Sbms * printed by "tcpdump -D". 867127675Sbms * 868127675Sbms * This should be OK on UNIX systems, as interfaces 869127675Sbms * shouldn't have names that begin with digits. 870127675Sbms * It can be useful on Windows, where more than 871127675Sbms * one interface can have the same name. 872127675Sbms */ 873251158Sdelphij devnum = strtol(optarg, &end, 10); 874251158Sdelphij if (optarg != end && *end == '\0') { 875127675Sbms if (devnum < 0) 876127675Sbms error("Invalid adapter index"); 877127675Sbms 878127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 879127675Sbms error("%s", ebuf); 880127675Sbms else { 881214478Srpaulo /* 882214478Srpaulo * Look for the devnum-th entry 883214478Srpaulo * in the list of devices 884214478Srpaulo * (1-based). 885214478Srpaulo */ 886214478Srpaulo for (i = 0; 887214478Srpaulo i < devnum-1 && devpointer != NULL; 888214478Srpaulo i++, devpointer = devpointer->next) 889214478Srpaulo ; 890214478Srpaulo if (devpointer == NULL) 891214478Srpaulo error("Invalid adapter index"); 892127675Sbms } 893127675Sbms device = devpointer->name; 894127675Sbms break; 895127675Sbms } 896127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 89717680Spst device = optarg; 89817680Spst break; 89917680Spst 900190207Srpaulo#ifdef HAVE_PCAP_CREATE 901190207Srpaulo case 'I': 902190207Srpaulo ++Iflag; 903190207Srpaulo break; 904190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 905190207Srpaulo 906235530Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 907235530Sdelphij case 'j': 908235530Sdelphij jflag = pcap_tstamp_type_name_to_val(optarg); 909235530Sdelphij if (jflag < 0) 910235530Sdelphij error("invalid time stamp type %s", optarg); 911235530Sdelphij break; 912235530Sdelphij 913235530Sdelphij case 'J': 914235530Sdelphij Jflag++; 915235530Sdelphij break; 916235530Sdelphij#endif 917235530Sdelphij 91817680Spst case 'l': 919127675Sbms#ifdef WIN32 920127675Sbms /* 921127675Sbms * _IOLBF is the same as _IOFBF in Microsoft's C 922127675Sbms * libraries; the only alternative they offer 923127675Sbms * is _IONBF. 924127675Sbms * 925127675Sbms * XXX - this should really be checking for MSVC++, 926127675Sbms * not WIN32, if, for example, MinGW has its own 927127675Sbms * C library that is more UNIX-compatible. 928127675Sbms */ 929127675Sbms setvbuf(stdout, NULL, _IONBF, 0); 930127675Sbms#else /* WIN32 */ 93117680Spst#ifdef HAVE_SETLINEBUF 93217680Spst setlinebuf(stdout); 93317680Spst#else 93417680Spst setvbuf(stdout, NULL, _IOLBF, 0); 93517680Spst#endif 936127675Sbms#endif /* WIN32 */ 93717680Spst break; 93817680Spst 939190207Srpaulo case 'K': 940190207Srpaulo ++Kflag; 94117680Spst break; 94217680Spst 94356896Sfenner case 'm': 94456896Sfenner#ifdef LIBSMI 945190207Srpaulo if (smiLoadModule(optarg) == 0) { 94656896Sfenner error("could not load MIB module %s", optarg); 947190207Srpaulo } 94856896Sfenner sflag = 1; 94956896Sfenner#else 95056896Sfenner (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 95156896Sfenner program_name, optarg); 95256896Sfenner (void)fprintf(stderr, "(no libsmi support)\n"); 95356896Sfenner#endif 954127675Sbms break; 955127675Sbms 956146778Ssam case 'M': 957146778Ssam /* TCP-MD5 shared secret */ 958146778Ssam#ifndef HAVE_LIBCRYPTO 959146778Ssam warning("crypto code not compiled in"); 960146778Ssam#endif 961214478Srpaulo sigsecret = optarg; 962146778Ssam break; 963146778Ssam 964190207Srpaulo case 'n': 965190207Srpaulo ++nflag; 966190207Srpaulo break; 967190207Srpaulo 968190207Srpaulo case 'N': 969190207Srpaulo ++Nflag; 970190207Srpaulo break; 971190207Srpaulo 97217680Spst case 'O': 97317680Spst Oflag = 0; 97417680Spst break; 97517680Spst 97617680Spst case 'p': 97717680Spst ++pflag; 97817680Spst break; 97917680Spst 98017680Spst case 'q': 98117680Spst ++qflag; 982162021Ssam ++suppress_default_print; 98317680Spst break; 98417680Spst 98517680Spst case 'r': 98617680Spst RFileName = optarg; 98717680Spst break; 98817680Spst 98956896Sfenner case 'R': 99056896Sfenner Rflag = 0; 99156896Sfenner break; 99256896Sfenner 993251158Sdelphij case 's': 99475118Sfenner snaplen = strtol(optarg, &end, 0); 99575118Sfenner if (optarg == end || *end != '\0' 996214478Srpaulo || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN) 99717680Spst error("invalid snaplen %s", optarg); 99875118Sfenner else if (snaplen == 0) 999214478Srpaulo snaplen = MAXIMUM_SNAPLEN; 100017680Spst break; 100117680Spst 100217680Spst case 'S': 100317680Spst ++Sflag; 100417680Spst break; 100517680Spst 100617680Spst case 't': 1007146778Ssam ++tflag; 100817680Spst break; 100917680Spst 101017680Spst case 'T': 101117680Spst if (strcasecmp(optarg, "vat") == 0) 101217680Spst packettype = PT_VAT; 101317680Spst else if (strcasecmp(optarg, "wb") == 0) 101417680Spst packettype = PT_WB; 101517680Spst else if (strcasecmp(optarg, "rpc") == 0) 101617680Spst packettype = PT_RPC; 101717680Spst else if (strcasecmp(optarg, "rtp") == 0) 101817680Spst packettype = PT_RTP; 101917680Spst else if (strcasecmp(optarg, "rtcp") == 0) 102017680Spst packettype = PT_RTCP; 102156896Sfenner else if (strcasecmp(optarg, "snmp") == 0) 102256896Sfenner packettype = PT_SNMP; 102375118Sfenner else if (strcasecmp(optarg, "cnfp") == 0) 102475118Sfenner packettype = PT_CNFP; 1025127675Sbms else if (strcasecmp(optarg, "tftp") == 0) 1026127675Sbms packettype = PT_TFTP; 1027127675Sbms else if (strcasecmp(optarg, "aodv") == 0) 1028127675Sbms packettype = PT_AODV; 1029235530Sdelphij else if (strcasecmp(optarg, "carp") == 0) 1030235530Sdelphij packettype = PT_CARP; 1031251158Sdelphij else if (strcasecmp(optarg, "radius") == 0) 1032251158Sdelphij packettype = PT_RADIUS; 1033251158Sdelphij else if (strcasecmp(optarg, "zmtp1") == 0) 1034251158Sdelphij packettype = PT_ZMTP1; 1035251158Sdelphij else if (strcasecmp(optarg, "vxlan") == 0) 1036251158Sdelphij packettype = PT_VXLAN; 103717680Spst else 103817680Spst error("unknown packet type `%s'", optarg); 103917680Spst break; 104017680Spst 104175118Sfenner case 'u': 104275118Sfenner ++uflag; 104375118Sfenner break; 1044127675Sbms 1045127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1046127675Sbms case 'U': 1047127675Sbms ++Uflag; 1048127675Sbms break; 1049127675Sbms#endif 1050127675Sbms 105117680Spst case 'v': 105217680Spst ++vflag; 105317680Spst break; 105417680Spst 1055251158Sdelphij case 'V': 1056251158Sdelphij VFileName = optarg; 1057251158Sdelphij break; 1058251158Sdelphij 105917680Spst case 'w': 106017680Spst WFileName = optarg; 106117680Spst break; 106256896Sfenner 1063146778Ssam case 'W': 1064146778Ssam Wflag = atoi(optarg); 1065146778Ssam if (Wflag < 0) 1066146778Ssam error("invalid number of output files %s", optarg); 1067146778Ssam WflagChars = getWflagChars(Wflag); 1068146778Ssam break; 1069146778Ssam 107056896Sfenner case 'x': 107156896Sfenner ++xflag; 1072162021Ssam ++suppress_default_print; 107356896Sfenner break; 107456896Sfenner 107556896Sfenner case 'X': 107656896Sfenner ++Xflag; 1077162021Ssam ++suppress_default_print; 107856896Sfenner break; 107956896Sfenner 1080109842Sfenner case 'y': 1081146778Ssam gndo->ndo_dltname = optarg; 1082146778Ssam gndo->ndo_dlt = 1083146778Ssam pcap_datalink_name_to_val(gndo->ndo_dltname); 1084146778Ssam if (gndo->ndo_dlt < 0) 1085146778Ssam error("invalid data link type %s", gndo->ndo_dltname); 1086109842Sfenner break; 1087109842Sfenner 1088127675Sbms#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) 108917680Spst case 'Y': 109017680Spst { 109117680Spst /* Undocumented flag */ 1092127675Sbms#ifdef HAVE_PCAP_DEBUG 1093127675Sbms extern int pcap_debug; 1094127675Sbms pcap_debug = 1; 1095127675Sbms#else 109617680Spst extern int yydebug; 109717680Spst yydebug = 1; 1098127675Sbms#endif 109917680Spst } 110017680Spst break; 110117680Spst#endif 1102190207Srpaulo case 'z': 1103190207Srpaulo if (optarg) { 1104190207Srpaulo zflag = strdup(optarg); 1105190207Srpaulo } else { 1106190207Srpaulo usage(); 1107190207Srpaulo /* NOTREACHED */ 1108190207Srpaulo } 1109190207Srpaulo break; 1110190207Srpaulo 1111146778Ssam case 'Z': 1112146778Ssam if (optarg) { 1113146778Ssam username = strdup(optarg); 1114146778Ssam } 1115146778Ssam else { 1116146778Ssam usage(); 1117146778Ssam /* NOTREACHED */ 1118146778Ssam } 1119146778Ssam break; 1120146778Ssam 112117680Spst default: 112217680Spst usage(); 112317680Spst /* NOTREACHED */ 112417680Spst } 112517680Spst 1126146778Ssam switch (tflag) { 1127146778Ssam 1128146778Ssam case 0: /* Default */ 1129146778Ssam case 4: /* Default + Date*/ 113039297Sfenner thiszone = gmt2local(0); 1131146778Ssam break; 113217680Spst 1133146778Ssam case 1: /* No time stamp */ 1134146778Ssam case 2: /* Unix timeval style */ 1135146778Ssam case 3: /* Microseconds since previous packet */ 1136190207Srpaulo case 5: /* Microseconds since first packet */ 1137146778Ssam break; 1138146778Ssam 1139146778Ssam default: /* Not supported */ 1140190207Srpaulo error("only -t, -tt, -ttt, -tttt and -ttttt are supported"); 1141146778Ssam break; 1142146778Ssam } 1143146778Ssam 1144251158Sdelphij if (fflag != 0 && (VFileName != NULL || RFileName != NULL)) 1145251158Sdelphij error("-f can not be used with -V or -r"); 1146251158Sdelphij 1147251158Sdelphij if (VFileName != NULL && RFileName != NULL) 1148251158Sdelphij error("-V and -r are mutually exclusive."); 1149251158Sdelphij 1150146778Ssam#ifdef WITH_CHROOT 1151146778Ssam /* if run as root, prepare for chrooting */ 1152146778Ssam if (getuid() == 0 || geteuid() == 0) { 1153146778Ssam /* future extensibility for cmd-line arguments */ 1154146778Ssam if (!chroot_dir) 1155146778Ssam chroot_dir = WITH_CHROOT; 1156146778Ssam } 1157146778Ssam#endif 1158146778Ssam 1159146778Ssam#ifdef WITH_USER 1160146778Ssam /* if run as root, prepare for dropping root privileges */ 1161146778Ssam if (getuid() == 0 || geteuid() == 0) { 1162146778Ssam /* Run with '-Z root' to restore old behaviour */ 1163146778Ssam if (!username) 1164146778Ssam username = WITH_USER; 1165146778Ssam } 1166146778Ssam#endif 1167146778Ssam 1168251158Sdelphij if (RFileName != NULL || VFileName != NULL) { 1169251158Sdelphij /* 1170251158Sdelphij * If RFileName is non-null, it's the pathname of a 1171251158Sdelphij * savefile to read. If VFileName is non-null, it's 1172251158Sdelphij * the pathname of a file containing a list of pathnames 1173251158Sdelphij * (one per line) of savefiles to read. 1174251158Sdelphij * 1175251158Sdelphij * In either case, we're reading a savefile, not doing 1176251158Sdelphij * a live capture. 1177251158Sdelphij */ 1178127675Sbms#ifndef WIN32 117917680Spst /* 1180127675Sbms * We don't need network access, so relinquish any set-UID 1181127675Sbms * or set-GID privileges we have (if any). 1182127675Sbms * 1183127675Sbms * We do *not* want set-UID privileges when opening a 1184127675Sbms * trace file, as that might let the user read other 1185127675Sbms * people's trace files (especially if we're set-UID 1186127675Sbms * root). 118717680Spst */ 1188146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) 1189146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 1190127675Sbms#endif /* WIN32 */ 1191251158Sdelphij if (VFileName != NULL) { 1192251158Sdelphij if (VFileName[0] == '-' && VFileName[1] == '\0') 1193251158Sdelphij VFile = stdin; 1194251158Sdelphij else 1195251158Sdelphij VFile = fopen(VFileName, "r"); 1196251158Sdelphij 1197251158Sdelphij if (VFile == NULL) 1198251158Sdelphij error("Unable to open file: %s\n", strerror(errno)); 1199251158Sdelphij 1200251158Sdelphij ret = get_next_file(VFile, VFileLine); 1201251158Sdelphij if (!ret) 1202251158Sdelphij error("Nothing in %s\n", VFileName); 1203251158Sdelphij RFileName = VFileLine; 1204251158Sdelphij } 1205251158Sdelphij 120617680Spst pd = pcap_open_offline(RFileName, ebuf); 120717680Spst if (pd == NULL) 120826180Sfenner error("%s", ebuf); 1209253004Spjd#ifdef __FreeBSD__ 1210255219Spjd cap_rights_init(&rights, CAP_READ); 1211255219Spjd if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && 1212253004Spjd errno != ENOSYS) { 1213253004Spjd error("unable to limit pcap descriptor"); 1214253004Spjd } 1215253004Spjd#endif 1216127675Sbms dlt = pcap_datalink(pd); 1217127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1218127675Sbms if (dlt_name == NULL) { 1219127675Sbms fprintf(stderr, "reading from file %s, link-type %u\n", 1220127675Sbms RFileName, dlt); 1221127675Sbms } else { 1222127675Sbms fprintf(stderr, 1223127675Sbms "reading from file %s, link-type %s (%s)\n", 1224127675Sbms RFileName, dlt_name, 1225127675Sbms pcap_datalink_val_to_description(dlt)); 1226127675Sbms } 122717680Spst localnet = 0; 122817680Spst netmask = 0; 122917680Spst } else { 1230251158Sdelphij /* 1231251158Sdelphij * We're doing a live capture. 1232251158Sdelphij */ 123317680Spst if (device == NULL) { 123417680Spst device = pcap_lookupdev(ebuf); 123517680Spst if (device == NULL) 123626180Sfenner error("%s", ebuf); 123717680Spst } 1238127675Sbms#ifdef WIN32 1239251158Sdelphij /* 1240251158Sdelphij * Print a message to the standard error on Windows. 1241251158Sdelphij * XXX - why do it here, with a different message? 1242251158Sdelphij */ 1243146778Ssam if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char 1244146778Ssam { //a Unicode string has a \0 as second byte (so strlen() is 1) 1245127675Sbms fprintf(stderr, "%s: listening on %ws\n", program_name, device); 1246127675Sbms } 1247127675Sbms else 1248127675Sbms { 1249127675Sbms fprintf(stderr, "%s: listening on %s\n", program_name, device); 1250127675Sbms } 1251127675Sbms 1252127675Sbms fflush(stderr); 1253127675Sbms#endif /* WIN32 */ 1254190207Srpaulo#ifdef HAVE_PCAP_CREATE 1255190207Srpaulo pd = pcap_create(device, ebuf); 1256190207Srpaulo if (pd == NULL) 1257190207Srpaulo error("%s", ebuf); 1258235530Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 1259235530Sdelphij if (Jflag) 1260235530Sdelphij show_tstamp_types_and_exit(device, pd); 1261235530Sdelphij#endif 1262214478Srpaulo /* 1263214478Srpaulo * Is this an interface that supports monitor mode? 1264214478Srpaulo */ 1265214478Srpaulo if (pcap_can_set_rfmon(pd) == 1) 1266214478Srpaulo supports_monitor_mode = 1; 1267214478Srpaulo else 1268214478Srpaulo supports_monitor_mode = 0; 1269190207Srpaulo status = pcap_set_snaplen(pd, snaplen); 1270190207Srpaulo if (status != 0) 1271235530Sdelphij error("%s: Can't set snapshot length: %s", 1272190207Srpaulo device, pcap_statustostr(status)); 1273190207Srpaulo status = pcap_set_promisc(pd, !pflag); 1274190207Srpaulo if (status != 0) 1275235530Sdelphij error("%s: Can't set promiscuous mode: %s", 1276190207Srpaulo device, pcap_statustostr(status)); 1277190207Srpaulo if (Iflag) { 1278190207Srpaulo status = pcap_set_rfmon(pd, 1); 1279190207Srpaulo if (status != 0) 1280235530Sdelphij error("%s: Can't set monitor mode: %s", 1281190207Srpaulo device, pcap_statustostr(status)); 1282190207Srpaulo } 1283190207Srpaulo status = pcap_set_timeout(pd, 1000); 1284190207Srpaulo if (status != 0) 1285190207Srpaulo error("%s: pcap_set_timeout failed: %s", 1286190207Srpaulo device, pcap_statustostr(status)); 1287190207Srpaulo if (Bflag != 0) { 1288190207Srpaulo status = pcap_set_buffer_size(pd, Bflag); 1289190207Srpaulo if (status != 0) 1290235530Sdelphij error("%s: Can't set buffer size: %s", 1291190207Srpaulo device, pcap_statustostr(status)); 1292190207Srpaulo } 1293235530Sdelphij#ifdef HAVE_PCAP_SET_TSTAMP_TYPE 1294235530Sdelphij if (jflag != -1) { 1295235530Sdelphij status = pcap_set_tstamp_type(pd, jflag); 1296235530Sdelphij if (status < 0) 1297235530Sdelphij error("%s: Can't set time stamp type: %s", 1298235530Sdelphij device, pcap_statustostr(status)); 1299235530Sdelphij } 1300235530Sdelphij#endif 1301190207Srpaulo status = pcap_activate(pd); 1302190207Srpaulo if (status < 0) { 1303190207Srpaulo /* 1304190207Srpaulo * pcap_activate() failed. 1305190207Srpaulo */ 1306190207Srpaulo cp = pcap_geterr(pd); 1307190207Srpaulo if (status == PCAP_ERROR) 1308190207Srpaulo error("%s", cp); 1309190207Srpaulo else if ((status == PCAP_ERROR_NO_SUCH_DEVICE || 1310190207Srpaulo status == PCAP_ERROR_PERM_DENIED) && 1311190207Srpaulo *cp != '\0') 1312190207Srpaulo error("%s: %s\n(%s)", device, 1313190207Srpaulo pcap_statustostr(status), cp); 1314253827Srpaulo#ifdef __FreeBSD__ 1315253827Srpaulo else if (status == PCAP_ERROR_RFMON_NOTSUP && 1316253827Srpaulo strncmp(device, "wlan", 4) == 0) { 1317253827Srpaulo char parent[8], newdev[8]; 1318253827Srpaulo char sysctl[32]; 1319253827Srpaulo size_t s = sizeof(parent); 1320253827Srpaulo 1321253827Srpaulo snprintf(sysctl, sizeof(sysctl), 1322253827Srpaulo "net.wlan.%d.%%parent", atoi(device + 4)); 1323253827Srpaulo sysctlbyname(sysctl, parent, &s, NULL, 0); 1324253827Srpaulo strlcpy(newdev, device, sizeof(newdev)); 1325253827Srpaulo /* Suggest a new wlan device. */ 1326253827Srpaulo newdev[strlen(newdev)-1]++; 1327253827Srpaulo error("%s is not a monitor mode VAP\n" 1328253827Srpaulo "To create a new monitor mode VAP use:\n" 1329253827Srpaulo " ifconfig %s create wlandev %s wlanmode " 1330253827Srpaulo "monitor\nand use %s as the tcpdump " 1331253827Srpaulo "interface", device, newdev, parent, 1332253827Srpaulo newdev); 1333253827Srpaulo } 1334253827Srpaulo#endif 1335190207Srpaulo else 1336190207Srpaulo error("%s: %s", device, 1337190207Srpaulo pcap_statustostr(status)); 1338190207Srpaulo } else if (status > 0) { 1339190207Srpaulo /* 1340190207Srpaulo * pcap_activate() succeeded, but it's warning us 1341190207Srpaulo * of a problem it had. 1342190207Srpaulo */ 1343190207Srpaulo cp = pcap_geterr(pd); 1344190207Srpaulo if (status == PCAP_WARNING) 1345190207Srpaulo warning("%s", cp); 1346190207Srpaulo else if (status == PCAP_WARNING_PROMISC_NOTSUP && 1347190207Srpaulo *cp != '\0') 1348190207Srpaulo warning("%s: %s\n(%s)", device, 1349190207Srpaulo pcap_statustostr(status), cp); 1350190207Srpaulo else 1351190207Srpaulo warning("%s: %s", device, 1352190207Srpaulo pcap_statustostr(status)); 1353190207Srpaulo } 1354190207Srpaulo#else 135598527Sfenner *ebuf = '\0'; 135617680Spst pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 135717680Spst if (pd == NULL) 135826180Sfenner error("%s", ebuf); 135998527Sfenner else if (*ebuf) 136098527Sfenner warning("%s", ebuf); 1361190207Srpaulo#endif /* HAVE_PCAP_CREATE */ 1362146778Ssam /* 1363146778Ssam * Let user own process after socket has been opened. 1364146778Ssam */ 1365146778Ssam#ifndef WIN32 1366146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0) 1367146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 1368146778Ssam#endif /* WIN32 */ 1369190207Srpaulo#if !defined(HAVE_PCAP_CREATE) && defined(WIN32) 1370190207Srpaulo if(Bflag != 0) 1371190207Srpaulo if(pcap_setbuff(pd, Bflag)==-1){ 1372146778Ssam error("%s", pcap_geterr(pd)); 1373146778Ssam } 1374190207Srpaulo#endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */ 1375127675Sbms if (Lflag) 1376214478Srpaulo show_dlts_and_exit(device, pd); 1377146778Ssam if (gndo->ndo_dlt >= 0) { 1378127675Sbms#ifdef HAVE_PCAP_SET_DATALINK 1379146778Ssam if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0) 1380109842Sfenner error("%s", pcap_geterr(pd)); 1381127675Sbms#else 1382127675Sbms /* 1383127675Sbms * We don't actually support changing the 1384127675Sbms * data link type, so we only let them 1385127675Sbms * set it to what it already is. 1386127675Sbms */ 1387146778Ssam if (gndo->ndo_dlt != pcap_datalink(pd)) { 1388127675Sbms error("%s is not one of the DLTs supported by this device\n", 1389146778Ssam gndo->ndo_dltname); 1390127675Sbms } 1391127675Sbms#endif 1392109842Sfenner (void)fprintf(stderr, "%s: data link type %s\n", 1393190207Srpaulo program_name, gndo->ndo_dltname); 1394109842Sfenner (void)fflush(stderr); 1395109842Sfenner } 139617680Spst i = pcap_snapshot(pd); 139717680Spst if (snaplen < i) { 139817680Spst warning("snaplen raised from %d to %d", snaplen, i); 139917680Spst snaplen = i; 140017680Spst } 140139297Sfenner if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 140239297Sfenner localnet = 0; 140339297Sfenner netmask = 0; 140439297Sfenner warning("%s", ebuf); 140539297Sfenner } 140617680Spst } 140717680Spst if (infile) 140817680Spst cmdbuf = read_infile(infile); 140917680Spst else 141017680Spst cmdbuf = copy_argv(&argv[optind]); 141117680Spst 141217680Spst if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 141326180Sfenner error("%s", pcap_geterr(pd)); 141417680Spst if (dflag) { 141517680Spst bpf_dump(&fcode, dflag); 1416127675Sbms pcap_close(pd); 1417251158Sdelphij free(cmdbuf); 141817680Spst exit(0); 141917680Spst } 142039297Sfenner init_addrtoname(localnet, netmask); 1421190207Srpaulo init_checksum(); 142217680Spst 1423127675Sbms#ifndef WIN32 1424127675Sbms (void)setsignal(SIGPIPE, cleanup); 142539297Sfenner (void)setsignal(SIGTERM, cleanup); 142639297Sfenner (void)setsignal(SIGINT, cleanup); 1427235530Sdelphij#endif /* WIN32 */ 1428235530Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 1429190207Srpaulo (void)setsignal(SIGCHLD, child_cleanup); 1430235530Sdelphij#endif 143139297Sfenner /* Cooperate with nohup(1) */ 1432127675Sbms#ifndef WIN32 143339297Sfenner if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 143439297Sfenner (void)setsignal(SIGHUP, oldhandler); 1435127675Sbms#endif /* WIN32 */ 143617680Spst 1437235530Sdelphij#ifndef WIN32 1438235530Sdelphij /* 1439235530Sdelphij * If a user name was specified with "-Z", attempt to switch to 1440235530Sdelphij * that user's UID. This would probably be used with sudo, 1441235530Sdelphij * to allow tcpdump to be run in a special restricted 1442235530Sdelphij * account (if you just want to allow users to open capture 1443235530Sdelphij * devices, and can't just give users that permission, 1444235530Sdelphij * you'd make tcpdump set-UID or set-GID). 1445235530Sdelphij * 1446235530Sdelphij * Tcpdump doesn't necessarily write only to one savefile; 1447235530Sdelphij * the general only way to allow a -Z instance to write to 1448235530Sdelphij * savefiles as the user under whose UID it's run, rather 1449235530Sdelphij * than as the user specified with -Z, would thus be to switch 1450235530Sdelphij * to the original user ID before opening a capture file and 1451235530Sdelphij * then switch back to the -Z user ID after opening the savefile. 1452235530Sdelphij * Switching to the -Z user ID only after opening the first 1453235530Sdelphij * savefile doesn't handle the general case. 1454235530Sdelphij */ 1455251158Sdelphij 1456251158Sdelphij#ifdef HAVE_CAP_NG_H 1457251158Sdelphij /* We are running as root and we will be writing to savefile */ 1458251158Sdelphij if ((getuid() == 0 || geteuid() == 0) && WFileName) { 1459251158Sdelphij if (username) { 1460251158Sdelphij /* Drop all capabilities from effective set */ 1461251158Sdelphij capng_clear(CAPNG_EFFECTIVE); 1462251158Sdelphij /* Add capabilities we will need*/ 1463251158Sdelphij capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETUID); 1464251158Sdelphij capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETGID); 1465251158Sdelphij capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_DAC_OVERRIDE); 1466251158Sdelphij 1467251158Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETUID); 1468251158Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETGID); 1469251158Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); 1470251158Sdelphij 1471251158Sdelphij capng_apply(CAPNG_SELECT_BOTH); 1472251158Sdelphij } 1473251158Sdelphij } 1474251158Sdelphij#endif /* HAVE_CAP_NG_H */ 1475251158Sdelphij 1476235530Sdelphij if (getuid() == 0 || geteuid() == 0) { 1477235530Sdelphij if (username || chroot_dir) 1478235530Sdelphij droproot(username, chroot_dir); 1479251158Sdelphij 1480235530Sdelphij } 1481235530Sdelphij#endif /* WIN32 */ 1482235530Sdelphij 148317680Spst if (pcap_setfilter(pd, &fcode) < 0) 148426180Sfenner error("%s", pcap_geterr(pd)); 1485253004Spjd#ifdef __FreeBSD__ 1486253004Spjd if (RFileName == NULL && VFileName == NULL) { 1487253004Spjd static const unsigned long cmds[] = { BIOCGSTATS }; 1488253004Spjd 1489255219Spjd cap_rights_init(&rights, CAP_IOCTL, CAP_READ); 1490255219Spjd if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && 1491255219Spjd errno != ENOSYS) { 1492253004Spjd error("unable to limit pcap descriptor"); 1493253004Spjd } 1494253004Spjd if (cap_ioctls_limit(pcap_fileno(pd), cmds, 1495253004Spjd sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { 1496253004Spjd error("unable to limit ioctls on pcap descriptor"); 1497253004Spjd } 1498253004Spjd } 1499253004Spjd#endif 150017680Spst if (WFileName) { 1501146778Ssam pcap_dumper_t *p; 1502251158Sdelphij /* Do not exceed the default PATH_MAX for files. */ 1503251158Sdelphij dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1); 1504146778Ssam 1505190207Srpaulo if (dumpinfo.CurrentFileName == NULL) 1506190207Srpaulo error("malloc of dumpinfo.CurrentFileName"); 1507190207Srpaulo 1508190207Srpaulo /* We do not need numbering for dumpfiles if Cflag isn't set. */ 1509190207Srpaulo if (Cflag != 0) 1510190207Srpaulo MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); 1511190207Srpaulo else 1512190207Srpaulo MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); 1513190207Srpaulo 1514190207Srpaulo p = pcap_dump_open(pd, dumpinfo.CurrentFileName); 1515251158Sdelphij#ifdef HAVE_CAP_NG_H 1516251158Sdelphij /* Give up capabilities, clear Effective set */ 1517251158Sdelphij capng_clear(CAPNG_EFFECTIVE); 1518251158Sdelphij#endif 151917680Spst if (p == NULL) 152026180Sfenner error("%s", pcap_geterr(pd)); 1521253004Spjd#ifdef __FreeBSD__ 1522255219Spjd cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); 1523255219Spjd if (cap_rights_limit(fileno(pcap_dump_file(p)), &rights) < 0 && 1524255219Spjd errno != ENOSYS) { 1525253004Spjd error("unable to limit dump descriptor"); 1526253004Spjd } 1527253004Spjd#endif 1528190207Srpaulo if (Cflag != 0 || Gflag != 0) { 1529253004Spjd#ifdef __FreeBSD__ 1530253004Spjd dumpinfo.WFileName = strdup(basename(WFileName)); 1531253004Spjd dumpinfo.dirfd = open(dirname(WFileName), 1532253004Spjd O_DIRECTORY | O_RDONLY); 1533253004Spjd if (dumpinfo.dirfd < 0) { 1534253004Spjd error("unable to open directory %s", 1535253004Spjd dirname(WFileName)); 1536253004Spjd } 1537255219Spjd cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, 1538255219Spjd CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); 1539255219Spjd if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && 1540255219Spjd errno != ENOSYS) { 1541253004Spjd error("unable to limit directory rights"); 1542253004Spjd } 1543253004Spjd#else /* !__FreeBSD__ */ 1544253004Spjd dumpinfo.WFileName = WFileName; 1545253004Spjd#endif 1546127675Sbms callback = dump_packet_and_trunc; 154798527Sfenner dumpinfo.pd = pd; 154898527Sfenner dumpinfo.p = p; 154998527Sfenner pcap_userdata = (u_char *)&dumpinfo; 155098527Sfenner } else { 1551127675Sbms callback = dump_packet; 155298527Sfenner pcap_userdata = (u_char *)p; 155398527Sfenner } 1554235530Sdelphij#ifdef HAVE_PCAP_DUMP_FLUSH 1555235530Sdelphij if (Uflag) 1556235530Sdelphij pcap_dump_flush(p); 1557235530Sdelphij#endif 155817680Spst } else { 1559127675Sbms type = pcap_datalink(pd); 1560251158Sdelphij printinfo = get_print_info(type); 1561127675Sbms callback = print_packet; 1562127675Sbms pcap_userdata = (u_char *)&printinfo; 1563127675Sbms } 1564235530Sdelphij 1565241235Sdelphij#ifdef SIGNAL_REQ_INFO 1566190207Srpaulo /* 1567190207Srpaulo * We can't get statistics when reading from a file rather 1568190207Srpaulo * than capturing from a device. 1569190207Srpaulo */ 1570190207Srpaulo if (RFileName == NULL) 1571241235Sdelphij (void)setsignal(SIGNAL_REQ_INFO, requestinfo); 157298527Sfenner#endif 1573146778Ssam 1574146778Ssam if (vflag > 0 && WFileName) { 1575146778Ssam /* 1576146778Ssam * When capturing to a file, "-v" means tcpdump should, 1577146778Ssam * every 10 secodns, "v"erbosely report the number of 1578146778Ssam * packets captured. 1579146778Ssam */ 1580146778Ssam#ifdef USE_WIN32_MM_TIMER 1581146778Ssam /* call verbose_stats_dump() each 1000 +/-100msec */ 1582146778Ssam timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); 1583146778Ssam setvbuf(stderr, NULL, _IONBF, 0); 1584146778Ssam#elif defined(HAVE_ALARM) 1585146778Ssam (void)setsignal(SIGALRM, verbose_stats_dump); 1586146778Ssam alarm(1); 1587146778Ssam#endif 1588146778Ssam } 1589146778Ssam 1590127675Sbms#ifndef WIN32 159117680Spst if (RFileName == NULL) { 1592251158Sdelphij /* 1593251158Sdelphij * Live capture (if -V was specified, we set RFileName 1594251158Sdelphij * to a file from the -V file). Print a message to 1595251158Sdelphij * the standard error on UN*X. 1596251158Sdelphij */ 1597127675Sbms if (!vflag && !WFileName) { 1598127675Sbms (void)fprintf(stderr, 1599127675Sbms "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", 1600127675Sbms program_name); 1601127675Sbms } else 1602127675Sbms (void)fprintf(stderr, "%s: ", program_name); 1603127675Sbms dlt = pcap_datalink(pd); 1604127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1605127675Sbms if (dlt_name == NULL) { 1606127675Sbms (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", 1607127675Sbms device, dlt, snaplen); 1608127675Sbms } else { 1609127675Sbms (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", 1610127675Sbms device, dlt_name, 1611127675Sbms pcap_datalink_val_to_description(dlt), snaplen); 1612127675Sbms } 161317680Spst (void)fflush(stderr); 161417680Spst } 1615127675Sbms#endif /* WIN32 */ 1616253004Spjd 1617253004Spjd#ifdef __FreeBSD__ 1618253004Spjd cansandbox = (nflag && VFileName == NULL && zflag == NULL); 1619253004Spjd if (cansandbox && cap_enter() < 0 && errno != ENOSYS) 1620253004Spjd error("unable to enter the capability mode"); 1621253004Spjd if (cap_sandboxed()) 1622253004Spjd fprintf(stderr, "capability mode sandbox enabled\n"); 1623255219Spjd#endif /* __FreeBSD__ */ 1624253004Spjd 1625251158Sdelphij do { 1626251158Sdelphij status = pcap_loop(pd, cnt, callback, pcap_userdata); 1627251158Sdelphij if (WFileName == NULL) { 1628127675Sbms /* 1629251158Sdelphij * We're printing packets. Flush the printed output, 1630251158Sdelphij * so it doesn't get intermingled with error output. 1631127675Sbms */ 1632251158Sdelphij if (status == -2) { 1633251158Sdelphij /* 1634251158Sdelphij * We got interrupted, so perhaps we didn't 1635251158Sdelphij * manage to finish a line we were printing. 1636251158Sdelphij * Print an extra newline, just in case. 1637251158Sdelphij */ 1638251158Sdelphij putchar('\n'); 1639251158Sdelphij } 1640251158Sdelphij (void)fflush(stdout); 1641127675Sbms } 1642251158Sdelphij if (status == -1) { 1643251158Sdelphij /* 1644251158Sdelphij * Error. Report it. 1645251158Sdelphij */ 1646251158Sdelphij (void)fprintf(stderr, "%s: pcap_loop: %s\n", 1647251158Sdelphij program_name, pcap_geterr(pd)); 1648251158Sdelphij } 1649251158Sdelphij if (RFileName == NULL) { 1650251158Sdelphij /* 1651251158Sdelphij * We're doing a live capture. Report the capture 1652251158Sdelphij * statistics. 1653251158Sdelphij */ 1654251158Sdelphij info(1); 1655251158Sdelphij } 1656251158Sdelphij pcap_close(pd); 1657251158Sdelphij if (VFileName != NULL) { 1658251158Sdelphij ret = get_next_file(VFile, VFileLine); 1659251158Sdelphij if (ret) { 1660251158Sdelphij RFileName = VFileLine; 1661251158Sdelphij pd = pcap_open_offline(RFileName, ebuf); 1662251158Sdelphij if (pd == NULL) 1663251158Sdelphij error("%s", ebuf); 1664253004Spjd#ifdef __FreeBSD__ 1665255219Spjd cap_rights_init(&rights, CAP_READ); 1666253004Spjd if (cap_rights_limit(fileno(pcap_file(pd)), 1667255219Spjd &rights) < 0 && errno != ENOSYS) { 1668253004Spjd error("unable to limit pcap descriptor"); 1669253004Spjd } 1670253004Spjd#endif 1671251158Sdelphij new_dlt = pcap_datalink(pd); 1672251158Sdelphij if (WFileName && new_dlt != dlt) 1673251158Sdelphij error("%s: new dlt does not match original", RFileName); 1674251158Sdelphij printinfo = get_print_info(new_dlt); 1675251158Sdelphij dlt_name = pcap_datalink_val_to_name(new_dlt); 1676251158Sdelphij if (dlt_name == NULL) { 1677251158Sdelphij fprintf(stderr, "reading from file %s, link-type %u\n", 1678251158Sdelphij RFileName, new_dlt); 1679251158Sdelphij } else { 1680251158Sdelphij fprintf(stderr, 1681251158Sdelphij "reading from file %s, link-type %s (%s)\n", 1682251158Sdelphij RFileName, dlt_name, 1683251158Sdelphij pcap_datalink_val_to_description(new_dlt)); 1684251158Sdelphij } 1685251158Sdelphij if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 1686251158Sdelphij error("%s", pcap_geterr(pd)); 1687251158Sdelphij if (pcap_setfilter(pd, &fcode) < 0) 1688251158Sdelphij error("%s", pcap_geterr(pd)); 1689251158Sdelphij } 1690251158Sdelphij } 1691127675Sbms } 1692251158Sdelphij while (ret != NULL); 1693251158Sdelphij 1694251158Sdelphij free(cmdbuf); 1695127675Sbms exit(status == -1 ? 1 : 0); 169617680Spst} 169717680Spst 169817680Spst/* make a clean exit on interrupts */ 169975118Sfennerstatic RETSIGTYPE 1700127675Sbmscleanup(int signo _U_) 170117680Spst{ 1702146778Ssam#ifdef USE_WIN32_MM_TIMER 1703146778Ssam if (timer_id) 1704146778Ssam timeKillEvent(timer_id); 1705146778Ssam timer_id = 0; 1706146778Ssam#elif defined(HAVE_ALARM) 1707146778Ssam alarm(0); 1708146778Ssam#endif 1709146778Ssam 1710127675Sbms#ifdef HAVE_PCAP_BREAKLOOP 1711127675Sbms /* 1712127675Sbms * We have "pcap_breakloop()"; use it, so that we do as little 1713127675Sbms * as possible in the signal handler (it's probably not safe 1714127675Sbms * to do anything with standard I/O streams in a signal handler - 1715127675Sbms * the ANSI C standard doesn't say it is). 1716127675Sbms */ 1717127675Sbms pcap_breakloop(pd); 1718127675Sbms#else 1719127675Sbms /* 1720127675Sbms * We don't have "pcap_breakloop()"; this isn't safe, but 1721127675Sbms * it's the best we can do. Print the summary if we're 1722127675Sbms * not reading from a savefile - i.e., if we're doing a 1723127675Sbms * live capture - and exit. 1724127675Sbms */ 172517680Spst if (pd != NULL && pcap_file(pd) == NULL) { 1726127675Sbms /* 1727127675Sbms * We got interrupted, so perhaps we didn't 1728127675Sbms * manage to finish a line we were printing. 1729127675Sbms * Print an extra newline, just in case. 1730127675Sbms */ 1731127675Sbms putchar('\n'); 173217680Spst (void)fflush(stdout); 173398527Sfenner info(1); 173417680Spst } 173517680Spst exit(0); 1736127675Sbms#endif 173717680Spst} 173817680Spst 1739190207Srpaulo/* 1740190207Srpaulo On windows, we do not use a fork, so we do not care less about 1741190207Srpaulo waiting a child processes to die 1742190207Srpaulo */ 1743235530Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 1744190207Srpaulostatic RETSIGTYPE 1745190207Srpaulochild_cleanup(int signo _U_) 1746190207Srpaulo{ 1747190207Srpaulo wait(NULL); 1748190207Srpaulo} 1749235530Sdelphij#endif /* HAVE_FORK && HAVE_VFORK */ 1750190207Srpaulo 1751127675Sbmsstatic void 175298527Sfennerinfo(register int verbose) 175398527Sfenner{ 175498527Sfenner struct pcap_stat stat; 175598527Sfenner 1756214478Srpaulo /* 1757214478Srpaulo * Older versions of libpcap didn't set ps_ifdrop on some 1758214478Srpaulo * platforms; initialize it to 0 to handle that. 1759214478Srpaulo */ 1760214478Srpaulo stat.ps_ifdrop = 0; 176198527Sfenner if (pcap_stats(pd, &stat) < 0) { 176298527Sfenner (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); 1763173819Smlaier infoprint = 0; 176498527Sfenner return; 176598527Sfenner } 1766127675Sbms 176798527Sfenner if (!verbose) 176898527Sfenner fprintf(stderr, "%s: ", program_name); 1769127675Sbms 1770235530Sdelphij (void)fprintf(stderr, "%u packet%s captured", packets_captured, 1771235530Sdelphij PLURAL_SUFFIX(packets_captured)); 1772127675Sbms if (!verbose) 1773127675Sbms fputs(", ", stderr); 1774127675Sbms else 1775127675Sbms putc('\n', stderr); 1776235530Sdelphij (void)fprintf(stderr, "%u packet%s received by filter", stat.ps_recv, 1777235530Sdelphij PLURAL_SUFFIX(stat.ps_recv)); 177898527Sfenner if (!verbose) 177998527Sfenner fputs(", ", stderr); 178098527Sfenner else 178198527Sfenner putc('\n', stderr); 1782235530Sdelphij (void)fprintf(stderr, "%u packet%s dropped by kernel", stat.ps_drop, 1783235530Sdelphij PLURAL_SUFFIX(stat.ps_drop)); 1784214478Srpaulo if (stat.ps_ifdrop != 0) { 1785214478Srpaulo if (!verbose) 1786214478Srpaulo fputs(", ", stderr); 1787214478Srpaulo else 1788214478Srpaulo putc('\n', stderr); 1789235530Sdelphij (void)fprintf(stderr, "%u packet%s dropped by interface\n", 1790235530Sdelphij stat.ps_ifdrop, PLURAL_SUFFIX(stat.ps_ifdrop)); 1791214478Srpaulo } else 1792214478Srpaulo putc('\n', stderr); 179398527Sfenner infoprint = 0; 179498527Sfenner} 179598527Sfenner 1796235530Sdelphij#if defined(HAVE_FORK) || defined(HAVE_VFORK) 179798527Sfennerstatic void 1798190207Srpaulocompress_savefile(const char *filename) 1799190207Srpaulo{ 1800235530Sdelphij# ifdef HAVE_FORK 1801190207Srpaulo if (fork()) 1802235530Sdelphij# else 1803235530Sdelphij if (vfork()) 1804235530Sdelphij# endif 1805190207Srpaulo return; 1806190207Srpaulo /* 1807190207Srpaulo * Set to lowest priority so that this doesn't disturb the capture 1808190207Srpaulo */ 1809190207Srpaulo#ifdef NZERO 1810190207Srpaulo setpriority(PRIO_PROCESS, 0, NZERO - 1); 1811190207Srpaulo#else 1812190207Srpaulo setpriority(PRIO_PROCESS, 0, 19); 1813190207Srpaulo#endif 1814214478Srpaulo if (execlp(zflag, zflag, filename, (char *)NULL) == -1) 1815190207Srpaulo fprintf(stderr, 1816190207Srpaulo "compress_savefile:execlp(%s, %s): %s\n", 1817190207Srpaulo zflag, 1818190207Srpaulo filename, 1819190207Srpaulo strerror(errno)); 1820235530Sdelphij# ifdef HAVE_FORK 1821235530Sdelphij exit(1); 1822235530Sdelphij# else 1823235530Sdelphij _exit(1); 1824235530Sdelphij# endif 1825190207Srpaulo} 1826235530Sdelphij#else /* HAVE_FORK && HAVE_VFORK */ 1827190207Srpaulostatic void 1828190207Srpaulocompress_savefile(const char *filename) 1829190207Srpaulo{ 1830190207Srpaulo fprintf(stderr, 1831235530Sdelphij "compress_savefile failed. Functionality not implemented under your system\n"); 1832190207Srpaulo} 1833235530Sdelphij#endif /* HAVE_FORK && HAVE_VFORK */ 1834190207Srpaulo 1835190207Srpaulostatic void 1836127675Sbmsdump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 183798527Sfenner{ 1838127675Sbms struct dump_info *dump_info; 1839255219Spjd#ifdef __FreeBSD__ 1840255219Spjd cap_rights_t rights; 1841255219Spjd#endif 184298527Sfenner 1843127675Sbms ++packets_captured; 1844127675Sbms 1845127675Sbms ++infodelay; 1846127675Sbms 1847127675Sbms dump_info = (struct dump_info *)user; 1848127675Sbms 184998527Sfenner /* 1850190207Srpaulo * XXX - this won't force the file to rotate on the specified time 1851190207Srpaulo * boundary, but it will rotate on the first packet received after the 1852190207Srpaulo * specified Gflag number of seconds. Note: if a Gflag time boundary 1853190207Srpaulo * and a Cflag size boundary coincide, the time rotation will occur 1854190207Srpaulo * first thereby cancelling the Cflag boundary (since the file should 1855190207Srpaulo * be 0). 1856190207Srpaulo */ 1857190207Srpaulo if (Gflag != 0) { 1858190207Srpaulo /* Check if it is time to rotate */ 1859190207Srpaulo time_t t; 1860190207Srpaulo 1861190207Srpaulo /* Get the current time */ 1862190207Srpaulo if ((t = time(NULL)) == (time_t)-1) { 1863190207Srpaulo error("dump_and_trunc_packet: can't get current_time: %s", 1864190207Srpaulo pcap_strerror(errno)); 1865190207Srpaulo } 1866190207Srpaulo 1867190207Srpaulo 1868190207Srpaulo /* If the time is greater than the specified window, rotate */ 1869190207Srpaulo if (t - Gflag_time >= Gflag) { 1870253004Spjd#ifdef __FreeBSD__ 1871253004Spjd FILE *fp; 1872253004Spjd int fd; 1873253004Spjd#endif 1874253004Spjd 1875190207Srpaulo /* Update the Gflag_time */ 1876190207Srpaulo Gflag_time = t; 1877190207Srpaulo /* Update Gflag_count */ 1878190207Srpaulo Gflag_count++; 1879190207Srpaulo /* 1880190207Srpaulo * Close the current file and open a new one. 1881190207Srpaulo */ 1882190207Srpaulo pcap_dump_close(dump_info->p); 1883190207Srpaulo 1884190207Srpaulo /* 1885190207Srpaulo * Compress the file we just closed, if the user asked for it 1886190207Srpaulo */ 1887190207Srpaulo if (zflag != NULL) 1888190207Srpaulo compress_savefile(dump_info->CurrentFileName); 1889190207Srpaulo 1890190207Srpaulo /* 1891190207Srpaulo * Check to see if we've exceeded the Wflag (when 1892190207Srpaulo * not using Cflag). 1893190207Srpaulo */ 1894190207Srpaulo if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) { 1895190207Srpaulo (void)fprintf(stderr, "Maximum file limit reached: %d\n", 1896190207Srpaulo Wflag); 1897190207Srpaulo exit(0); 1898190207Srpaulo /* NOTREACHED */ 1899190207Srpaulo } 1900190207Srpaulo if (dump_info->CurrentFileName != NULL) 1901190207Srpaulo free(dump_info->CurrentFileName); 1902190207Srpaulo /* Allocate space for max filename + \0. */ 1903251158Sdelphij dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); 1904190207Srpaulo if (dump_info->CurrentFileName == NULL) 1905190207Srpaulo error("dump_packet_and_trunc: malloc"); 1906190207Srpaulo /* 1907190207Srpaulo * This is always the first file in the Cflag 1908190207Srpaulo * rotation: e.g. 0 1909190207Srpaulo * We also don't need numbering if Cflag is not set. 1910190207Srpaulo */ 1911190207Srpaulo if (Cflag != 0) 1912190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 1913190207Srpaulo WflagChars); 1914190207Srpaulo else 1915190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); 1916190207Srpaulo 1917251158Sdelphij#ifdef HAVE_CAP_NG_H 1918251158Sdelphij capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); 1919251158Sdelphij capng_apply(CAPNG_EFFECTIVE); 1920251158Sdelphij#endif /* HAVE_CAP_NG_H */ 1921253004Spjd#ifdef __FreeBSD__ 1922253004Spjd fd = openat(dump_info->dirfd, 1923253004Spjd dump_info->CurrentFileName, 1924253004Spjd O_CREAT | O_WRONLY | O_TRUNC, 0644); 1925253004Spjd if (fd < 0) { 1926253004Spjd error("unable to open file %s", 1927253004Spjd dump_info->CurrentFileName); 1928253004Spjd } 1929253004Spjd fp = fdopen(fd, "w"); 1930253004Spjd if (fp == NULL) { 1931253004Spjd error("unable to fdopen file %s", 1932253004Spjd dump_info->CurrentFileName); 1933253004Spjd } 1934253004Spjd dump_info->p = pcap_dump_fopen(dump_info->pd, fp); 1935253004Spjd#else /* !__FreeBSD__ */ 1936190207Srpaulo dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); 1937253004Spjd#endif 1938251158Sdelphij#ifdef HAVE_CAP_NG_H 1939251158Sdelphij capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); 1940251158Sdelphij capng_apply(CAPNG_EFFECTIVE); 1941251158Sdelphij#endif /* HAVE_CAP_NG_H */ 1942190207Srpaulo if (dump_info->p == NULL) 1943190207Srpaulo error("%s", pcap_geterr(pd)); 1944253004Spjd#ifdef __FreeBSD__ 1945255219Spjd cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); 1946253004Spjd if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), 1947255219Spjd &rights) < 0 && errno != ENOSYS) { 1948253004Spjd error("unable to limit dump descriptor"); 1949253004Spjd } 1950253004Spjd#endif 1951190207Srpaulo } 1952190207Srpaulo } 1953190207Srpaulo 1954190207Srpaulo /* 195598527Sfenner * XXX - this won't prevent capture files from getting 195698527Sfenner * larger than Cflag - the last packet written to the 195798527Sfenner * file could put it over Cflag. 195898527Sfenner */ 1959190207Srpaulo if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { 1960253004Spjd#ifdef __FreeBSD__ 1961253004Spjd FILE *fp; 1962253004Spjd int fd; 1963253004Spjd#endif 1964253004Spjd 1965127675Sbms /* 1966127675Sbms * Close the current file and open a new one. 1967127675Sbms */ 1968127675Sbms pcap_dump_close(dump_info->p); 1969190207Srpaulo 1970190207Srpaulo /* 1971190207Srpaulo * Compress the file we just closed, if the user asked for it 1972190207Srpaulo */ 1973190207Srpaulo if (zflag != NULL) 1974190207Srpaulo compress_savefile(dump_info->CurrentFileName); 1975190207Srpaulo 1976146778Ssam Cflag_count++; 1977146778Ssam if (Wflag > 0) { 1978146778Ssam if (Cflag_count >= Wflag) 1979146778Ssam Cflag_count = 0; 1980146778Ssam } 1981190207Srpaulo if (dump_info->CurrentFileName != NULL) 1982190207Srpaulo free(dump_info->CurrentFileName); 1983251158Sdelphij dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); 1984190207Srpaulo if (dump_info->CurrentFileName == NULL) 1985127675Sbms error("dump_packet_and_trunc: malloc"); 1986190207Srpaulo MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); 1987253004Spjd#ifdef __FreeBSD__ 1988253004Spjd fd = openat(dump_info->dirfd, dump_info->CurrentFileName, 1989253004Spjd O_CREAT | O_WRONLY | O_TRUNC, 0644); 1990253004Spjd if (fd < 0) { 1991253004Spjd error("unable to open file %s", 1992253004Spjd dump_info->CurrentFileName); 1993253004Spjd } 1994253004Spjd fp = fdopen(fd, "w"); 1995253004Spjd if (fp == NULL) { 1996253004Spjd error("unable to fdopen file %s", 1997253004Spjd dump_info->CurrentFileName); 1998253004Spjd } 1999253004Spjd dump_info->p = pcap_dump_fopen(dump_info->pd, fp); 2000253004Spjd#else /* !__FreeBSD__ */ 2001190207Srpaulo dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); 2002253004Spjd#endif 2003127675Sbms if (dump_info->p == NULL) 200498527Sfenner error("%s", pcap_geterr(pd)); 2005253004Spjd#ifdef __FreeBSD__ 2006255219Spjd cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); 2007253004Spjd if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), 2008255219Spjd &rights) < 0 && errno != ENOSYS) { 2009253004Spjd error("unable to limit dump descriptor"); 2010253004Spjd } 2011253004Spjd#endif 201298527Sfenner } 201398527Sfenner 2014127675Sbms pcap_dump((u_char *)dump_info->p, h, sp); 2015127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 2016127675Sbms if (Uflag) 2017127675Sbms pcap_dump_flush(dump_info->p); 2018127675Sbms#endif 2019127675Sbms 2020127675Sbms --infodelay; 2021127675Sbms if (infoprint) 2022127675Sbms info(0); 202398527Sfenner} 202498527Sfenner 2025127675Sbmsstatic void 2026127675Sbmsdump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 202717680Spst{ 2028127675Sbms ++packets_captured; 202917680Spst 2030127675Sbms ++infodelay; 2031127675Sbms 2032127675Sbms pcap_dump(user, h, sp); 2033127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 2034127675Sbms if (Uflag) 2035127675Sbms pcap_dump_flush((pcap_dumper_t *)user); 2036127675Sbms#endif 2037127675Sbms 2038127675Sbms --infodelay; 2039127675Sbms if (infoprint) 2040127675Sbms info(0); 2041127675Sbms} 2042127675Sbms 2043127675Sbmsstatic void 2044127675Sbmsprint_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 2045127675Sbms{ 2046127675Sbms struct print_info *print_info; 2047127675Sbms u_int hdrlen; 2048127675Sbms 2049127675Sbms ++packets_captured; 2050127675Sbms 2051127675Sbms ++infodelay; 2052127675Sbms ts_print(&h->ts); 2053127675Sbms 2054127675Sbms print_info = (struct print_info *)user; 2055127675Sbms 2056127675Sbms /* 2057127675Sbms * Some printers want to check that they're not walking off the 2058127675Sbms * end of the packet. 2059127675Sbms * Rather than pass it all the way down, we set this global. 2060127675Sbms */ 2061127675Sbms snapend = sp + h->caplen; 2062127675Sbms 2063214478Srpaulo if(print_info->ndo_type) { 2064214478Srpaulo hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp); 2065214478Srpaulo } else { 2066214478Srpaulo hdrlen = (*print_info->p.printer)(h, sp); 2067214478Srpaulo } 2068214478Srpaulo 2069162021Ssam if (Xflag) { 2070127675Sbms /* 2071162021Ssam * Print the raw packet data in hex and ASCII. 2072127675Sbms */ 2073162021Ssam if (Xflag > 1) { 2074162021Ssam /* 2075162021Ssam * Include the link-layer header. 2076162021Ssam */ 2077162021Ssam hex_and_ascii_print("\n\t", sp, h->caplen); 2078162021Ssam } else { 2079162021Ssam /* 2080162021Ssam * Don't include the link-layer header - and if 2081162021Ssam * we have nothing past the link-layer header, 2082162021Ssam * print nothing. 2083162021Ssam */ 2084162021Ssam if (h->caplen > hdrlen) 2085162021Ssam hex_and_ascii_print("\n\t", sp + hdrlen, 2086162021Ssam h->caplen - hdrlen); 2087162021Ssam } 2088162021Ssam } else if (xflag) { 2089162021Ssam /* 2090162021Ssam * Print the raw packet data in hex. 2091162021Ssam */ 2092127675Sbms if (xflag > 1) { 2093127675Sbms /* 2094127675Sbms * Include the link-layer header. 2095127675Sbms */ 2096146778Ssam hex_print("\n\t", sp, h->caplen); 2097127675Sbms } else { 2098127675Sbms /* 2099127675Sbms * Don't include the link-layer header - and if 2100127675Sbms * we have nothing past the link-layer header, 2101127675Sbms * print nothing. 2102127675Sbms */ 2103127675Sbms if (h->caplen > hdrlen) 2104146778Ssam hex_print("\n\t", sp + hdrlen, 2105127675Sbms h->caplen - hdrlen); 2106127675Sbms } 2107162021Ssam } else if (Aflag) { 2108146778Ssam /* 2109162021Ssam * Print the raw packet data in ASCII. 2110146778Ssam */ 2111162021Ssam if (Aflag > 1) { 2112146778Ssam /* 2113146778Ssam * Include the link-layer header. 2114146778Ssam */ 2115162021Ssam ascii_print(sp, h->caplen); 2116146778Ssam } else { 2117146778Ssam /* 2118146778Ssam * Don't include the link-layer header - and if 2119146778Ssam * we have nothing past the link-layer header, 2120146778Ssam * print nothing. 2121146778Ssam */ 2122146778Ssam if (h->caplen > hdrlen) 2123162021Ssam ascii_print(sp + hdrlen, h->caplen - hdrlen); 2124146778Ssam } 212517680Spst } 2126127675Sbms 2127127675Sbms putchar('\n'); 2128127675Sbms 2129127675Sbms --infodelay; 2130127675Sbms if (infoprint) 2131127675Sbms info(0); 213217680Spst} 213317680Spst 2134127675Sbms#ifdef WIN32 2135127675Sbms /* 2136127675Sbms * XXX - there should really be libpcap calls to get the version 2137127675Sbms * number as a string (the string would be generated from #defines 2138127675Sbms * at run time, so that it's not generated from string constants 2139127675Sbms * in the library, as, on many UNIX systems, those constants would 2140127675Sbms * be statically linked into the application executable image, and 2141127675Sbms * would thus reflect the version of libpcap on the system on 2142127675Sbms * which the application was *linked*, not the system on which it's 2143127675Sbms * *running*. 2144127675Sbms * 2145127675Sbms * That routine should be documented, unlike the "version[]" 2146127675Sbms * string, so that UNIX vendors providing their own libpcaps 2147127675Sbms * don't omit it (as a couple of vendors have...). 2148127675Sbms * 2149127675Sbms * Packet.dll should perhaps also export a routine to return the 2150127675Sbms * version number of the Packet.dll code, to supply the 2151127675Sbms * "Wpcap_version" information on Windows. 2152127675Sbms */ 2153127675Sbms char WDversion[]="current-cvs.tcpdump.org"; 2154146778Ssam#if !defined(HAVE_GENERATED_VERSION) 2155127675Sbms char version[]="current-cvs.tcpdump.org"; 2156146778Ssam#endif 2157127675Sbms char pcap_version[]="current-cvs.tcpdump.org"; 2158146778Ssam char Wpcap_version[]="3.1"; 2159127675Sbms#endif 2160127675Sbms 216139297Sfenner/* 2162162021Ssam * By default, print the specified data out in hex and ASCII. 216339297Sfenner */ 2164146778Ssamstatic void 2165146778Ssamndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length) 2166146778Ssam{ 2167162021Ssam hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */ 2168146778Ssam} 2169146778Ssam 217017680Spstvoid 2171146778Ssamdefault_print(const u_char *bp, u_int length) 217217680Spst{ 2173146778Ssam ndo_default_print(gndo, bp, length); 217417680Spst} 217517680Spst 2176241235Sdelphij#ifdef SIGNAL_REQ_INFO 2177127675SbmsRETSIGTYPE requestinfo(int signo _U_) 217898527Sfenner{ 217998527Sfenner if (infodelay) 218098527Sfenner ++infoprint; 218198527Sfenner else 218298527Sfenner info(0); 218398527Sfenner} 218498527Sfenner#endif 218598527Sfenner 2186146778Ssam/* 2187146778Ssam * Called once each second in verbose mode while dumping to file 2188146778Ssam */ 2189146778Ssam#ifdef USE_WIN32_MM_TIMER 2190146778Ssamvoid CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, 2191190207Srpaulo DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) 2192146778Ssam{ 2193146778Ssam struct pcap_stat stat; 2194146778Ssam 2195146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 2196146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 2197146778Ssam} 2198146778Ssam#elif defined(HAVE_ALARM) 2199146778Ssamstatic void verbose_stats_dump(int sig _U_) 2200146778Ssam{ 2201146778Ssam struct pcap_stat stat; 2202146778Ssam 2203146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 2204146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 2205146778Ssam alarm(1); 2206146778Ssam} 2207146778Ssam#endif 2208146778Ssam 220975118Sfennerstatic void 221026180Sfennerusage(void) 221117680Spst{ 221217680Spst extern char version[]; 2213127675Sbms#ifndef HAVE_PCAP_LIB_VERSION 2214127675Sbms#if defined(WIN32) || defined(HAVE_PCAP_VERSION) 221539297Sfenner extern char pcap_version[]; 2216127675Sbms#else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 2217127675Sbms static char pcap_version[] = "unknown"; 2218127675Sbms#endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 2219127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 222017680Spst 2221127675Sbms#ifdef HAVE_PCAP_LIB_VERSION 2222146778Ssam#ifdef WIN32 2223146778Ssam (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 2224146778Ssam#else /* WIN32 */ 222539297Sfenner (void)fprintf(stderr, "%s version %s\n", program_name, version); 2226146778Ssam#endif /* WIN32 */ 2227146778Ssam (void)fprintf(stderr, "%s\n",pcap_lib_version()); 2228127675Sbms#else /* HAVE_PCAP_LIB_VERSION */ 2229127675Sbms#ifdef WIN32 2230127675Sbms (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 2231127675Sbms (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); 2232127675Sbms#else /* WIN32 */ 2233127675Sbms (void)fprintf(stderr, "%s version %s\n", program_name, version); 223439297Sfenner (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 2235127675Sbms#endif /* WIN32 */ 2236127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 223717680Spst (void)fprintf(stderr, 2238235530Sdelphij"Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name); 223917680Spst (void)fprintf(stderr, 2240190207Srpaulo"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); 224117680Spst (void)fprintf(stderr, 2242235530Sdelphij"\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ]\n"); 2243109842Sfenner (void)fprintf(stderr, 2244251158Sdelphij"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -V file ] [ -w file ]\n"); 2245146778Ssam (void)fprintf(stderr, 2246235530Sdelphij"\t\t[ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); 2247190207Srpaulo (void)fprintf(stderr, 2248235530Sdelphij"\t\t[ -Z user ] [ expression ]\n"); 224998527Sfenner exit(1); 225017680Spst} 2251146778Ssam 2252146778Ssam 2253146778Ssam 2254146778Ssam/* VARARGS */ 2255146778Ssamstatic void 2256146778Ssamndo_error(netdissect_options *ndo _U_, const char *fmt, ...) 2257146778Ssam{ 2258146778Ssam va_list ap; 2259146778Ssam 2260146778Ssam (void)fprintf(stderr, "%s: ", program_name); 2261146778Ssam va_start(ap, fmt); 2262146778Ssam (void)vfprintf(stderr, fmt, ap); 2263146778Ssam va_end(ap); 2264146778Ssam if (*fmt) { 2265146778Ssam fmt += strlen(fmt); 2266146778Ssam if (fmt[-1] != '\n') 2267146778Ssam (void)fputc('\n', stderr); 2268146778Ssam } 2269146778Ssam exit(1); 2270146778Ssam /* NOTREACHED */ 2271146778Ssam} 2272146778Ssam 2273146778Ssam/* VARARGS */ 2274146778Ssamstatic void 2275146778Ssamndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) 2276146778Ssam{ 2277146778Ssam va_list ap; 2278146778Ssam 2279146778Ssam (void)fprintf(stderr, "%s: WARNING: ", program_name); 2280146778Ssam va_start(ap, fmt); 2281146778Ssam (void)vfprintf(stderr, fmt, ap); 2282146778Ssam va_end(ap); 2283146778Ssam if (*fmt) { 2284146778Ssam fmt += strlen(fmt); 2285146778Ssam if (fmt[-1] != '\n') 2286146778Ssam (void)fputc('\n', stderr); 2287146778Ssam } 2288146778Ssam} 2289