tcpdump.c revision 162021
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_ = 33162021Ssam "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.253.2.11 2005/08/23 10:29:41 hannes Exp $ (LBL)"; 3417680Spst#endif 3517680Spst 3656648Sarchie/* $FreeBSD: head/contrib/tcpdump/tcpdump.c 162021 2006-09-04 20:25:04Z sam $ */ 3756648Sarchie 3817680Spst/* 3917680Spst * tcpdump - monitor tcp/ip traffic on an ethernet. 4017680Spst * 4117680Spst * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. 4217680Spst * Mercilessly hacked and occasionally improved since then via the 4317680Spst * combined efforts of Van, Steve McCanne and Craig Leres of LBL. 4417680Spst */ 4517680Spst 4656896Sfenner#ifdef HAVE_CONFIG_H 4756896Sfenner#include "config.h" 4856896Sfenner#endif 4956896Sfenner 50127675Sbms#include <tcpdump-stdinc.h> 5117680Spst 52127675Sbms#ifdef WIN32 53127675Sbms#include "getopt.h" 54127675Sbms#include "w32_fzs.h" 55127675Sbmsextern int strcasecmp (const char *__s1, const char *__s2); 56127675Sbmsextern int SIZE_BUF; 57127675Sbms#define off_t long 58127675Sbms#define uint UINT 59127675Sbms#endif /* WIN32 */ 6017680Spst 61146778Ssam#ifdef HAVE_SMI_H 62146778Ssam#include <smi.h> 63146778Ssam#endif 64146778Ssam 6517680Spst#include <pcap.h> 6617680Spst#include <signal.h> 6717680Spst#include <stdio.h> 6817680Spst#include <stdlib.h> 6917680Spst#include <string.h> 70146778Ssam#ifndef WIN32 71146778Ssam#include <pwd.h> 72146778Ssam#include <grp.h> 73146778Ssam#include <errno.h> 74146778Ssam#endif /* WIN32 */ 7517680Spst 76146778Ssam#include "netdissect.h" 7717680Spst#include "interface.h" 7817680Spst#include "addrtoname.h" 7917680Spst#include "machdep.h" 8039297Sfenner#include "setsignal.h" 8139297Sfenner#include "gmt2local.h" 82127675Sbms#include "pcap-missing.h" 8317680Spst 84146778Ssamnetdissect_options Gndo; 85146778Ssamnetdissect_options *gndo = &Gndo; 86146778Ssam 87146778Ssam/* 88146778Ssam * Define the maximum number of files for the -C flag, and how many 89146778Ssam * characters can be added to a filename for the -C flag (which 90146778Ssam * should be enough to handle MAX_CFLAG - 1). 91146778Ssam */ 92146778Ssam#define MAX_CFLAG 1000000 93146778Ssam#define MAX_CFLAG_CHARS 6 94146778Ssam 9539297Sfennerint dflag; /* print filter code */ 96109842Sfennerint Lflag; /* list available data link types and exit */ 9739297Sfenner 98127675Sbmsstatic int infodelay; 99127675Sbmsstatic int infoprint; 10017680Spst 10117680Spstchar *program_name; 10217680Spst 10317680Spstint32_t thiszone; /* seconds offset from gmt to local time */ 10417680Spst 10517680Spst/* Forwards */ 10675118Sfennerstatic RETSIGTYPE cleanup(int); 10775118Sfennerstatic void usage(void) __attribute__((noreturn)); 108109842Sfennerstatic void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn)); 10917680Spst 110127675Sbmsstatic void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 111146778Ssamstatic void ndo_default_print(netdissect_options *, const u_char *, u_int); 112127675Sbmsstatic void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); 113127675Sbmsstatic void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); 114146778Ssamstatic void droproot(const char *, const char *); 115146778Ssamstatic void ndo_error(netdissect_options *ndo, const char *fmt, ...); 116146778Ssamstatic void ndo_warning(netdissect_options *ndo, const char *fmt, ...); 11798527Sfenner 11898527Sfenner#ifdef SIGINFO 11998527SfennerRETSIGTYPE requestinfo(int); 12098527Sfenner#endif 12198527Sfenner 122146778Ssam#if defined(USE_WIN32_MM_TIMER) 123146778Ssam #include <MMsystem.h> 124146778Ssam static UINT timer_id; 125146778Ssam static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); 126146778Ssam#elif defined(HAVE_ALARM) 127146778Ssam static void verbose_stats_dump(int sig); 128146778Ssam#endif 129146778Ssam 130127675Sbmsstatic void info(int); 131127675Sbmsstatic u_int packets_captured; 132127675Sbms 133127675Sbmstypedef u_int (*if_printer)(const struct pcap_pkthdr *, const u_char *); 134127675Sbms 13517680Spststruct printer { 136127675Sbms if_printer f; 13717680Spst int type; 13817680Spst}; 13917680Spst 14017680Spststatic struct printer printers[] = { 14198527Sfenner { arcnet_if_print, DLT_ARCNET }, 142127675Sbms#ifdef DLT_ARCNET_LINUX 143127675Sbms { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 144127675Sbms#endif 14517680Spst { ether_if_print, DLT_EN10MB }, 14644165Sjulian { token_if_print, DLT_IEEE802 }, 14756896Sfenner#ifdef DLT_LANE8023 14856896Sfenner { lane_if_print, DLT_LANE8023 }, 14956896Sfenner#endif 15056896Sfenner#ifdef DLT_CIP 15156896Sfenner { cip_if_print, DLT_CIP }, 15256896Sfenner#endif 15375118Sfenner#ifdef DLT_ATM_CLIP 15475118Sfenner { cip_if_print, DLT_ATM_CLIP }, 15575118Sfenner#endif 15617680Spst { sl_if_print, DLT_SLIP }, 157127675Sbms#ifdef DLT_SLIP_BSDOS 15839297Sfenner { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 159127675Sbms#endif 16017680Spst { ppp_if_print, DLT_PPP }, 161146778Ssam#ifdef DLT_PPP_WITHDIRECTION 162146778Ssam { ppp_if_print, DLT_PPP_WITHDIRECTION }, 163146778Ssam#endif 164127675Sbms#ifdef DLT_PPP_BSDOS 16539297Sfenner { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 166127675Sbms#endif 16717680Spst { fddi_if_print, DLT_FDDI }, 16817680Spst { null_if_print, DLT_NULL }, 16975118Sfenner#ifdef DLT_LOOP 17075118Sfenner { null_if_print, DLT_LOOP }, 17175118Sfenner#endif 17239297Sfenner { raw_if_print, DLT_RAW }, 17317680Spst { atm_if_print, DLT_ATM_RFC1483 }, 17475118Sfenner#ifdef DLT_C_HDLC 17575118Sfenner { chdlc_if_print, DLT_C_HDLC }, 17656896Sfenner#endif 17798527Sfenner#ifdef DLT_HDLC 17898527Sfenner { chdlc_if_print, DLT_HDLC }, 17998527Sfenner#endif 18075118Sfenner#ifdef DLT_PPP_SERIAL 18175118Sfenner { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 18275118Sfenner#endif 18398527Sfenner#ifdef DLT_PPP_ETHER 18498527Sfenner { pppoe_if_print, DLT_PPP_ETHER }, 18598527Sfenner#endif 18675118Sfenner#ifdef DLT_LINUX_SLL 18775118Sfenner { sll_if_print, DLT_LINUX_SLL }, 18875118Sfenner#endif 18998527Sfenner#ifdef DLT_IEEE802_11 19098527Sfenner { ieee802_11_if_print, DLT_IEEE802_11}, 19198527Sfenner#endif 19298527Sfenner#ifdef DLT_LTALK 19398527Sfenner { ltalk_if_print, DLT_LTALK }, 19498527Sfenner#endif 195127675Sbms#ifdef DLT_PFLOG 196127675Sbms { pflog_if_print, DLT_PFLOG }, 197127675Sbms#endif 198127675Sbms#ifdef DLT_FR 199127675Sbms { fr_if_print, DLT_FR }, 200127675Sbms#endif 201127675Sbms#ifdef DLT_FRELAY 202127675Sbms { fr_if_print, DLT_FRELAY }, 203127675Sbms#endif 204127675Sbms#ifdef DLT_SUNATM 205127675Sbms { sunatm_if_print, DLT_SUNATM }, 206127675Sbms#endif 207127675Sbms#ifdef DLT_IP_OVER_FC 208127675Sbms { ipfc_if_print, DLT_IP_OVER_FC }, 209127675Sbms#endif 210127675Sbms#ifdef DLT_PRISM_HEADER 211127675Sbms { prism_if_print, DLT_PRISM_HEADER }, 212127675Sbms#endif 213127675Sbms#ifdef DLT_IEEE802_11_RADIO 214127675Sbms { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 215127675Sbms#endif 216127675Sbms#ifdef DLT_ENC 217127675Sbms { enc_if_print, DLT_ENC }, 218127675Sbms#endif 219146778Ssam#ifdef DLT_SYMANTEC_FIREWALL 220146778Ssam { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 221146778Ssam#endif 222127675Sbms#ifdef DLT_APPLE_IP_OVER_IEEE1394 223127675Sbms { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 224127675Sbms#endif 225146778Ssam#ifdef DLT_JUNIPER_ATM1 226146778Ssam { juniper_atm1_print, DLT_JUNIPER_ATM1 }, 227146778Ssam#endif 228146778Ssam#ifdef DLT_JUNIPER_ATM2 229146778Ssam { juniper_atm2_print, DLT_JUNIPER_ATM2 }, 230146778Ssam#endif 231147904Ssam#ifdef DLT_JUNIPER_MFR 232147904Ssam { juniper_mfr_print, DLT_JUNIPER_MFR }, 233147904Ssam#endif 234146778Ssam#ifdef DLT_JUNIPER_MLFR 235146778Ssam { juniper_mlfr_print, DLT_JUNIPER_MLFR }, 236146778Ssam#endif 237146778Ssam#ifdef DLT_JUNIPER_MLPPP 238146778Ssam { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, 239146778Ssam#endif 240147904Ssam#ifdef DLT_JUNIPER_PPPOE 241147904Ssam { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, 242147904Ssam#endif 243147904Ssam#ifdef DLT_JUNIPER_PPPOE_ATM 244147904Ssam { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, 245147904Ssam#endif 246147904Ssam#ifdef DLT_JUNIPER_GGSN 247147904Ssam { juniper_ggsn_print, DLT_JUNIPER_GGSN }, 248147904Ssam#endif 249147904Ssam#ifdef DLT_JUNIPER_ES 250147904Ssam { juniper_es_print, DLT_JUNIPER_ES }, 251147904Ssam#endif 252147904Ssam#ifdef DLT_JUNIPER_MONITOR 253147904Ssam { juniper_monitor_print, DLT_JUNIPER_MONITOR }, 254147904Ssam#endif 255147904Ssam#ifdef DLT_JUNIPER_SERVICES 256147904Ssam { juniper_services_print, DLT_JUNIPER_SERVICES }, 257147904Ssam#endif 258162021Ssam#ifdef DLT_JUNIPER_ETHER 259162021Ssam { juniper_ether_print, DLT_JUNIPER_ETHER }, 260162021Ssam#endif 261162021Ssam#ifdef DLT_JUNIPER_PPP 262162021Ssam { juniper_ppp_print, DLT_JUNIPER_PPP }, 263162021Ssam#endif 264162021Ssam#ifdef DLT_JUNIPER_FRELAY 265162021Ssam { juniper_frelay_print, DLT_JUNIPER_FRELAY }, 266162021Ssam#endif 267162021Ssam#ifdef DLT_JUNIPER_CHDLC 268162021Ssam { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, 269162021Ssam#endif 27017680Spst { NULL, 0 }, 27117680Spst}; 27217680Spst 273127675Sbmsstatic if_printer 27417680Spstlookup_printer(int type) 27517680Spst{ 27617680Spst struct printer *p; 27717680Spst 27817680Spst for (p = printers; p->f; ++p) 27917680Spst if (type == p->type) 28017680Spst return p->f; 28117680Spst 282127675Sbms return NULL; 28317680Spst /* NOTREACHED */ 28417680Spst} 28517680Spst 28617680Spststatic pcap_t *pd; 28717680Spst 28817680Spstextern int optind; 28917680Spstextern int opterr; 29017680Spstextern char *optarg; 29117680Spst 292127675Sbmsstruct print_info { 293127675Sbms if_printer printer; 294127675Sbms}; 295127675Sbms 29698527Sfennerstruct dump_info { 29798527Sfenner char *WFileName; 29898527Sfenner pcap_t *pd; 29998527Sfenner pcap_dumper_t *p; 30098527Sfenner}; 30198527Sfenner 302109842Sfennerstatic void 303109842Sfennershow_dlts_and_exit(pcap_t *pd) 304109842Sfenner{ 305127675Sbms int n_dlts; 306109842Sfenner int *dlts = 0; 307127675Sbms const char *dlt_name; 308127675Sbms 309109842Sfenner n_dlts = pcap_list_datalinks(pd, &dlts); 310109842Sfenner if (n_dlts < 0) 311109842Sfenner error("%s", pcap_geterr(pd)); 312109842Sfenner else if (n_dlts == 0 || !dlts) 313109842Sfenner error("No data link types."); 314109842Sfenner 315127675Sbms (void) fprintf(stderr, "Data link types (use option -y to set):\n"); 316109842Sfenner 317109842Sfenner while (--n_dlts >= 0) { 318127675Sbms dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); 319127675Sbms if (dlt_name != NULL) { 320127675Sbms (void) fprintf(stderr, " %s (%s)", dlt_name, 321127675Sbms pcap_datalink_val_to_description(dlts[n_dlts])); 322127675Sbms 323127675Sbms /* 324127675Sbms * OK, does tcpdump handle that type? 325127675Sbms */ 326127675Sbms if (lookup_printer(dlts[n_dlts]) == NULL) 327127675Sbms (void) fprintf(stderr, " (not supported)"); 328127675Sbms putchar('\n'); 329127675Sbms } else { 330127675Sbms (void) fprintf(stderr, " DLT %d (not supported)\n", 331127675Sbms dlts[n_dlts]); 332109842Sfenner } 333109842Sfenner } 334109842Sfenner free(dlts); 335109842Sfenner exit(0); 336109842Sfenner} 337109842Sfenner 338127675Sbms/* 339127675Sbms * Set up flags that might or might not be supported depending on the 340127675Sbms * version of libpcap we're using. 341127675Sbms */ 342127675Sbms#ifdef WIN32 343127675Sbms#define B_FLAG "B:" 344127675Sbms#define B_FLAG_USAGE " [ -B size ]" 345127675Sbms#else /* WIN32 */ 346127675Sbms#define B_FLAG 347127675Sbms#define B_FLAG_USAGE 348127675Sbms#endif /* WIN32 */ 349127675Sbms 350127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 351146778Ssam#ifndef HAVE_PCAP_IF_T 352146778Ssam#undef HAVE_PCAP_FINDALLDEVS 353146778Ssam#endif 354146778Ssam#endif 355146778Ssam 356146778Ssam#ifdef HAVE_PCAP_FINDALLDEVS 357127675Sbms#define D_FLAG "D" 358127675Sbms#else 359127675Sbms#define D_FLAG 360127675Sbms#endif 361127675Sbms 362127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 363127675Sbms#define U_FLAG "U" 364127675Sbms#else 365127675Sbms#define U_FLAG 366127675Sbms#endif 367127675Sbms 368146778Ssam#ifndef WIN32 369146778Ssam/* Drop root privileges and chroot if necessary */ 370146778Ssamstatic void 371146778Ssamdroproot(const char *username, const char *chroot_dir) 372146778Ssam{ 373146778Ssam struct passwd *pw = NULL; 374146778Ssam 375146778Ssam if (chroot_dir && !username) { 376146778Ssam fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); 377146778Ssam exit(1); 378146778Ssam } 379146778Ssam 380146778Ssam pw = getpwnam(username); 381146778Ssam if (pw) { 382146778Ssam if (chroot_dir) { 383146778Ssam if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { 384146778Ssam fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", 385146778Ssam chroot_dir, pcap_strerror(errno)); 386146778Ssam exit(1); 387146778Ssam } 388146778Ssam } 389146778Ssam if (initgroups(pw->pw_name, pw->pw_gid) != 0 || 390146778Ssam setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { 391146778Ssam fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", 392146778Ssam username, 393146778Ssam (unsigned long)pw->pw_uid, 394146778Ssam (unsigned long)pw->pw_gid, 395146778Ssam pcap_strerror(errno)); 396146778Ssam exit(1); 397146778Ssam } 398146778Ssam } 399146778Ssam else { 400146778Ssam fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", 401146778Ssam username); 402146778Ssam exit(1); 403146778Ssam } 404146778Ssam} 405146778Ssam#endif /* WIN32 */ 406146778Ssam 407146778Ssamstatic int 408146778SsamgetWflagChars(int x) 409146778Ssam{ 410146778Ssam int c = 0; 411146778Ssam 412146778Ssam x -= 1; 413146778Ssam while (x > 0) { 414146778Ssam c += 1; 415146778Ssam x /= 10; 416146778Ssam } 417146778Ssam 418146778Ssam return c; 419146778Ssam} 420146778Ssam 421146778Ssam 422146778Ssamstatic void 423146778SsamMakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) 424146778Ssam{ 425146778Ssam if (cnt == 0 && max_chars == 0) 426146778Ssam strcpy(buffer, orig_name); 427146778Ssam else 428146778Ssam sprintf(buffer, "%s%0*d", orig_name, max_chars, cnt); 429146778Ssam} 430146778Ssam 431146778Ssamstatic int tcpdump_printf(netdissect_options *ndo _U_, 432146778Ssam const char *fmt, ...) 433146778Ssam{ 434146778Ssam 435146778Ssam va_list args; 436146778Ssam int ret; 437146778Ssam 438146778Ssam va_start(args, fmt); 439146778Ssam ret=vfprintf(stdout, fmt, args); 440146778Ssam va_end(args); 441146778Ssam 442146778Ssam return ret; 443146778Ssam} 444146778Ssam 44517680Spstint 44617680Spstmain(int argc, char **argv) 44717680Spst{ 44817680Spst register int cnt, op, i; 44917680Spst bpf_u_int32 localnet, netmask; 450146778Ssam register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName, *WFileNameAlt; 451127675Sbms pcap_handler callback; 452127675Sbms int type; 45317680Spst struct bpf_program fcode; 454127675Sbms#ifndef WIN32 45539297Sfenner RETSIGTYPE (*oldhandler)(int); 456127675Sbms#endif 457127675Sbms struct print_info printinfo; 45898527Sfenner struct dump_info dumpinfo; 45917680Spst u_char *pcap_userdata; 46017680Spst char ebuf[PCAP_ERRBUF_SIZE]; 461146778Ssam char *username = NULL; 462146778Ssam char *chroot_dir = NULL; 463127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 464127675Sbms pcap_if_t *devpointer; 465127675Sbms int devnum; 466127675Sbms#endif 467127675Sbms int status; 468127675Sbms#ifdef WIN32 469127675Sbms u_int UserBufferSize = 1000000; 470127675Sbms if(wsockinit() != 0) return 1; 471127675Sbms#endif /* WIN32 */ 47217680Spst 473146778Ssam gndo->ndo_Oflag=1; 474146778Ssam gndo->ndo_Rflag=1; 475146778Ssam gndo->ndo_dlt=-1; 476146778Ssam gndo->ndo_default_print=ndo_default_print; 477146778Ssam gndo->ndo_printf=tcpdump_printf; 478146778Ssam gndo->ndo_error=ndo_error; 479146778Ssam gndo->ndo_warning=ndo_warning; 480146778Ssam gndo->ndo_snaplen = DEFAULT_SNAPLEN; 481146778Ssam 48217680Spst cnt = -1; 48317680Spst device = NULL; 48417680Spst infile = NULL; 48517680Spst RFileName = NULL; 48617680Spst WFileName = NULL; 48717680Spst if ((cp = strrchr(argv[0], '/')) != NULL) 48817680Spst program_name = cp + 1; 48917680Spst else 49017680Spst program_name = argv[0]; 49117680Spst 49275118Sfenner if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) 49326180Sfenner error("%s", ebuf); 49417680Spst 49556896Sfenner#ifdef LIBSMI 49656896Sfenner smiInit("tcpdump"); 49756896Sfenner#endif 498127675Sbms 49917680Spst opterr = 0; 50039297Sfenner while ( 501146778Ssam (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1) 50217680Spst switch (op) { 50339297Sfenner 50439297Sfenner case 'a': 505127675Sbms /* compatibility for old -a */ 50639297Sfenner break; 50739297Sfenner 508127675Sbms case 'A': 509127675Sbms ++Aflag; 510127675Sbms break; 511127675Sbms 512127675Sbms#ifdef WIN32 513127675Sbms case 'B': 514127675Sbms UserBufferSize = atoi(optarg)*1024; 515127675Sbms if (UserBufferSize < 0) 516127675Sbms error("invalid packet buffer size %s", optarg); 517127675Sbms break; 518127675Sbms#endif /* WIN32 */ 519127675Sbms 52017680Spst case 'c': 52117680Spst cnt = atoi(optarg); 52217680Spst if (cnt <= 0) 52317680Spst error("invalid packet count %s", optarg); 52417680Spst break; 52517680Spst 52698527Sfenner case 'C': 52798527Sfenner Cflag = atoi(optarg) * 1000000; 528127675Sbms if (Cflag < 0) 52998527Sfenner error("invalid file size %s", optarg); 53098527Sfenner break; 53198527Sfenner 53217680Spst case 'd': 53317680Spst ++dflag; 53417680Spst break; 53517680Spst 536127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 537127675Sbms case 'D': 538127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 539127675Sbms error("%s", ebuf); 540127675Sbms else { 541127675Sbms for (i = 0; devpointer != 0; i++) { 542127675Sbms printf("%d.%s", i+1, devpointer->name); 543127675Sbms if (devpointer->description != NULL) 544127675Sbms printf(" (%s)", devpointer->description); 545127675Sbms printf("\n"); 546127675Sbms devpointer = devpointer->next; 547127675Sbms } 548127675Sbms } 549127675Sbms return 0; 550127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 551127675Sbms 552109842Sfenner case 'L': 553109842Sfenner Lflag++; 554109842Sfenner break; 555109842Sfenner 55617680Spst case 'e': 55717680Spst ++eflag; 55817680Spst break; 55917680Spst 56056896Sfenner case 'E': 56175118Sfenner#ifndef HAVE_LIBCRYPTO 56256896Sfenner warning("crypto code not compiled in"); 56356896Sfenner#endif 564146778Ssam gndo->ndo_espsecret = optarg; 56556896Sfenner break; 56656896Sfenner 56717680Spst case 'f': 56817680Spst ++fflag; 56917680Spst break; 57017680Spst 57117680Spst case 'F': 57217680Spst infile = optarg; 57317680Spst break; 57417680Spst 57517680Spst case 'i': 576127675Sbms if (optarg[0] == '0' && optarg[1] == 0) 577127675Sbms error("Invalid adapter index"); 578127675Sbms 579127675Sbms#ifdef HAVE_PCAP_FINDALLDEVS 580127675Sbms /* 581127675Sbms * If the argument is a number, treat it as 582127675Sbms * an index into the list of adapters, as 583127675Sbms * printed by "tcpdump -D". 584127675Sbms * 585127675Sbms * This should be OK on UNIX systems, as interfaces 586127675Sbms * shouldn't have names that begin with digits. 587127675Sbms * It can be useful on Windows, where more than 588127675Sbms * one interface can have the same name. 589127675Sbms */ 590127675Sbms if ((devnum = atoi(optarg)) != 0) { 591127675Sbms if (devnum < 0) 592127675Sbms error("Invalid adapter index"); 593127675Sbms 594127675Sbms if (pcap_findalldevs(&devpointer, ebuf) < 0) 595127675Sbms error("%s", ebuf); 596127675Sbms else { 597127675Sbms for (i = 0; i < devnum-1; i++){ 598127675Sbms devpointer = devpointer->next; 599127675Sbms if (devpointer == NULL) 600127675Sbms error("Invalid adapter index"); 601127675Sbms } 602127675Sbms } 603127675Sbms device = devpointer->name; 604127675Sbms break; 605127675Sbms } 606127675Sbms#endif /* HAVE_PCAP_FINDALLDEVS */ 60717680Spst device = optarg; 60817680Spst break; 60917680Spst 61017680Spst case 'l': 611127675Sbms#ifdef WIN32 612127675Sbms /* 613127675Sbms * _IOLBF is the same as _IOFBF in Microsoft's C 614127675Sbms * libraries; the only alternative they offer 615127675Sbms * is _IONBF. 616127675Sbms * 617127675Sbms * XXX - this should really be checking for MSVC++, 618127675Sbms * not WIN32, if, for example, MinGW has its own 619127675Sbms * C library that is more UNIX-compatible. 620127675Sbms */ 621127675Sbms setvbuf(stdout, NULL, _IONBF, 0); 622127675Sbms#else /* WIN32 */ 62317680Spst#ifdef HAVE_SETLINEBUF 62417680Spst setlinebuf(stdout); 62517680Spst#else 62617680Spst setvbuf(stdout, NULL, _IOLBF, 0); 62717680Spst#endif 628127675Sbms#endif /* WIN32 */ 62917680Spst break; 63017680Spst 63117680Spst case 'n': 63217680Spst ++nflag; 63317680Spst break; 63417680Spst 63517680Spst case 'N': 63617680Spst ++Nflag; 63717680Spst break; 63817680Spst 63956896Sfenner case 'm': 64056896Sfenner#ifdef LIBSMI 64156896Sfenner if (smiLoadModule(optarg) == 0) { 64256896Sfenner error("could not load MIB module %s", optarg); 64356896Sfenner } 64456896Sfenner sflag = 1; 64556896Sfenner#else 64656896Sfenner (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 64756896Sfenner program_name, optarg); 64856896Sfenner (void)fprintf(stderr, "(no libsmi support)\n"); 64956896Sfenner#endif 650127675Sbms break; 651127675Sbms 652146778Ssam case 'M': 653146778Ssam /* TCP-MD5 shared secret */ 654146778Ssam#ifndef HAVE_LIBCRYPTO 655146778Ssam warning("crypto code not compiled in"); 656146778Ssam#endif 657146778Ssam tcpmd5secret = optarg; 658146778Ssam break; 659146778Ssam 66017680Spst case 'O': 66117680Spst Oflag = 0; 66217680Spst break; 66317680Spst 66417680Spst case 'p': 66517680Spst ++pflag; 66617680Spst break; 66717680Spst 66817680Spst case 'q': 66917680Spst ++qflag; 670162021Ssam ++suppress_default_print; 67117680Spst break; 67217680Spst 67317680Spst case 'r': 67417680Spst RFileName = optarg; 67517680Spst break; 67617680Spst 67756896Sfenner case 'R': 67856896Sfenner Rflag = 0; 67956896Sfenner break; 68056896Sfenner 68175118Sfenner case 's': { 68275118Sfenner char *end; 68375118Sfenner 68475118Sfenner snaplen = strtol(optarg, &end, 0); 68575118Sfenner if (optarg == end || *end != '\0' 68675118Sfenner || snaplen < 0 || snaplen > 65535) 68717680Spst error("invalid snaplen %s", optarg); 68875118Sfenner else if (snaplen == 0) 68975118Sfenner snaplen = 65535; 69017680Spst break; 69175118Sfenner } 69217680Spst 69317680Spst case 'S': 69417680Spst ++Sflag; 69517680Spst break; 69617680Spst 69717680Spst case 't': 698146778Ssam ++tflag; 69917680Spst break; 70017680Spst 70117680Spst case 'T': 70217680Spst if (strcasecmp(optarg, "vat") == 0) 70317680Spst packettype = PT_VAT; 70417680Spst else if (strcasecmp(optarg, "wb") == 0) 70517680Spst packettype = PT_WB; 70617680Spst else if (strcasecmp(optarg, "rpc") == 0) 70717680Spst packettype = PT_RPC; 70817680Spst else if (strcasecmp(optarg, "rtp") == 0) 70917680Spst packettype = PT_RTP; 71017680Spst else if (strcasecmp(optarg, "rtcp") == 0) 71117680Spst packettype = PT_RTCP; 71256896Sfenner else if (strcasecmp(optarg, "snmp") == 0) 71356896Sfenner packettype = PT_SNMP; 71475118Sfenner else if (strcasecmp(optarg, "cnfp") == 0) 71575118Sfenner packettype = PT_CNFP; 716127675Sbms else if (strcasecmp(optarg, "tftp") == 0) 717127675Sbms packettype = PT_TFTP; 718127675Sbms else if (strcasecmp(optarg, "aodv") == 0) 719127675Sbms packettype = PT_AODV; 72017680Spst else 72117680Spst error("unknown packet type `%s'", optarg); 72217680Spst break; 72317680Spst 72475118Sfenner case 'u': 72575118Sfenner ++uflag; 72675118Sfenner break; 727127675Sbms 728127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 729127675Sbms case 'U': 730127675Sbms ++Uflag; 731127675Sbms break; 732127675Sbms#endif 733127675Sbms 73417680Spst case 'v': 73517680Spst ++vflag; 73617680Spst break; 73717680Spst 73817680Spst case 'w': 73917680Spst WFileName = optarg; 74017680Spst break; 74156896Sfenner 742146778Ssam case 'W': 743146778Ssam Wflag = atoi(optarg); 744146778Ssam if (Wflag < 0) 745146778Ssam error("invalid number of output files %s", optarg); 746146778Ssam WflagChars = getWflagChars(Wflag); 747146778Ssam break; 748146778Ssam 74956896Sfenner case 'x': 75056896Sfenner ++xflag; 751162021Ssam ++suppress_default_print; 75256896Sfenner break; 75356896Sfenner 75456896Sfenner case 'X': 75556896Sfenner ++Xflag; 756162021Ssam ++suppress_default_print; 75756896Sfenner break; 75856896Sfenner 759109842Sfenner case 'y': 760146778Ssam gndo->ndo_dltname = optarg; 761146778Ssam gndo->ndo_dlt = 762146778Ssam pcap_datalink_name_to_val(gndo->ndo_dltname); 763146778Ssam if (gndo->ndo_dlt < 0) 764146778Ssam error("invalid data link type %s", gndo->ndo_dltname); 765109842Sfenner break; 766109842Sfenner 767127675Sbms#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) 76817680Spst case 'Y': 76917680Spst { 77017680Spst /* Undocumented flag */ 771127675Sbms#ifdef HAVE_PCAP_DEBUG 772127675Sbms extern int pcap_debug; 773127675Sbms pcap_debug = 1; 774127675Sbms#else 77517680Spst extern int yydebug; 77617680Spst yydebug = 1; 777127675Sbms#endif 77817680Spst } 77917680Spst break; 78017680Spst#endif 781146778Ssam case 'Z': 782146778Ssam if (optarg) { 783146778Ssam username = strdup(optarg); 784146778Ssam } 785146778Ssam else { 786146778Ssam usage(); 787146778Ssam /* NOTREACHED */ 788146778Ssam } 789146778Ssam break; 790146778Ssam 79117680Spst default: 79217680Spst usage(); 79317680Spst /* NOTREACHED */ 79417680Spst } 79517680Spst 796146778Ssam switch (tflag) { 797146778Ssam 798146778Ssam case 0: /* Default */ 799146778Ssam case 4: /* Default + Date*/ 80039297Sfenner thiszone = gmt2local(0); 801146778Ssam break; 80217680Spst 803146778Ssam case 1: /* No time stamp */ 804146778Ssam case 2: /* Unix timeval style */ 805146778Ssam case 3: /* Microseconds since previous packet */ 806146778Ssam break; 807146778Ssam 808146778Ssam default: /* Not supported */ 809146778Ssam error("only -t, -tt, -ttt, and -tttt are supported"); 810146778Ssam break; 811146778Ssam } 812146778Ssam 813146778Ssam#ifdef WITH_CHROOT 814146778Ssam /* if run as root, prepare for chrooting */ 815146778Ssam if (getuid() == 0 || geteuid() == 0) { 816146778Ssam /* future extensibility for cmd-line arguments */ 817146778Ssam if (!chroot_dir) 818146778Ssam chroot_dir = WITH_CHROOT; 819146778Ssam } 820146778Ssam#endif 821146778Ssam 822146778Ssam#ifdef WITH_USER 823146778Ssam /* if run as root, prepare for dropping root privileges */ 824146778Ssam if (getuid() == 0 || geteuid() == 0) { 825146778Ssam /* Run with '-Z root' to restore old behaviour */ 826146778Ssam if (!username) 827146778Ssam username = WITH_USER; 828146778Ssam } 829146778Ssam#endif 830146778Ssam 83117680Spst if (RFileName != NULL) { 832127675Sbms int dlt; 833127675Sbms const char *dlt_name; 834127675Sbms 835127675Sbms#ifndef WIN32 83617680Spst /* 837127675Sbms * We don't need network access, so relinquish any set-UID 838127675Sbms * or set-GID privileges we have (if any). 839127675Sbms * 840127675Sbms * We do *not* want set-UID privileges when opening a 841127675Sbms * trace file, as that might let the user read other 842127675Sbms * people's trace files (especially if we're set-UID 843127675Sbms * root). 84417680Spst */ 845146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) 846146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 847127675Sbms#endif /* WIN32 */ 84817680Spst pd = pcap_open_offline(RFileName, ebuf); 84917680Spst if (pd == NULL) 85026180Sfenner error("%s", ebuf); 851127675Sbms dlt = pcap_datalink(pd); 852127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 853127675Sbms if (dlt_name == NULL) { 854127675Sbms fprintf(stderr, "reading from file %s, link-type %u\n", 855127675Sbms RFileName, dlt); 856127675Sbms } else { 857127675Sbms fprintf(stderr, 858127675Sbms "reading from file %s, link-type %s (%s)\n", 859127675Sbms RFileName, dlt_name, 860127675Sbms pcap_datalink_val_to_description(dlt)); 861127675Sbms } 86217680Spst localnet = 0; 86317680Spst netmask = 0; 86417680Spst if (fflag != 0) 86517680Spst error("-f and -r options are incompatible"); 86617680Spst } else { 86717680Spst if (device == NULL) { 86817680Spst device = pcap_lookupdev(ebuf); 86917680Spst if (device == NULL) 87026180Sfenner error("%s", ebuf); 87117680Spst } 872127675Sbms#ifdef WIN32 873146778Ssam if(strlen(device) == 1) //we assume that an ASCII string is always longer than 1 char 874146778Ssam { //a Unicode string has a \0 as second byte (so strlen() is 1) 875127675Sbms fprintf(stderr, "%s: listening on %ws\n", program_name, device); 876127675Sbms } 877127675Sbms else 878127675Sbms { 879127675Sbms fprintf(stderr, "%s: listening on %s\n", program_name, device); 880127675Sbms } 881127675Sbms 882127675Sbms fflush(stderr); 883127675Sbms#endif /* WIN32 */ 88498527Sfenner *ebuf = '\0'; 88517680Spst pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 88617680Spst if (pd == NULL) 88726180Sfenner error("%s", ebuf); 88898527Sfenner else if (*ebuf) 88998527Sfenner warning("%s", ebuf); 890146778Ssam /* 891146778Ssam * Let user own process after socket has been opened. 892146778Ssam */ 893146778Ssam#ifndef WIN32 894146778Ssam if (setgid(getgid()) != 0 || setuid(getuid()) != 0) 895146778Ssam fprintf(stderr, "Warning: setgid/setuid failed !\n"); 896146778Ssam#endif /* WIN32 */ 897146778Ssam#ifdef WIN32 898146778Ssam if(UserBufferSize != 1000000) 899146778Ssam if(pcap_setbuff(pd, UserBufferSize)==-1){ 900146778Ssam error("%s", pcap_geterr(pd)); 901146778Ssam } 902146778Ssam#endif /* WIN32 */ 903127675Sbms if (Lflag) 904109842Sfenner show_dlts_and_exit(pd); 905146778Ssam if (gndo->ndo_dlt >= 0) { 906127675Sbms#ifdef HAVE_PCAP_SET_DATALINK 907146778Ssam if (pcap_set_datalink(pd, gndo->ndo_dlt) < 0) 908109842Sfenner error("%s", pcap_geterr(pd)); 909127675Sbms#else 910127675Sbms /* 911127675Sbms * We don't actually support changing the 912127675Sbms * data link type, so we only let them 913127675Sbms * set it to what it already is. 914127675Sbms */ 915146778Ssam if (gndo->ndo_dlt != pcap_datalink(pd)) { 916127675Sbms error("%s is not one of the DLTs supported by this device\n", 917146778Ssam gndo->ndo_dltname); 918127675Sbms } 919127675Sbms#endif 920109842Sfenner (void)fprintf(stderr, "%s: data link type %s\n", 921146778Ssam program_name, gndo->ndo_dltname); 922109842Sfenner (void)fflush(stderr); 923109842Sfenner } 92417680Spst i = pcap_snapshot(pd); 92517680Spst if (snaplen < i) { 92617680Spst warning("snaplen raised from %d to %d", snaplen, i); 92717680Spst snaplen = i; 92817680Spst } 92939297Sfenner if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 93039297Sfenner localnet = 0; 93139297Sfenner netmask = 0; 93239297Sfenner warning("%s", ebuf); 93339297Sfenner } 93417680Spst } 93517680Spst if (infile) 93617680Spst cmdbuf = read_infile(infile); 93717680Spst else 93817680Spst cmdbuf = copy_argv(&argv[optind]); 93917680Spst 94017680Spst if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 94126180Sfenner error("%s", pcap_geterr(pd)); 94217680Spst if (dflag) { 94317680Spst bpf_dump(&fcode, dflag); 944127675Sbms pcap_close(pd); 94517680Spst exit(0); 94617680Spst } 94739297Sfenner init_addrtoname(localnet, netmask); 94817680Spst 949127675Sbms#ifndef WIN32 950127675Sbms (void)setsignal(SIGPIPE, cleanup); 951127675Sbms#endif /* WIN32 */ 95239297Sfenner (void)setsignal(SIGTERM, cleanup); 95339297Sfenner (void)setsignal(SIGINT, cleanup); 95439297Sfenner /* Cooperate with nohup(1) */ 955127675Sbms#ifndef WIN32 95639297Sfenner if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 95739297Sfenner (void)setsignal(SIGHUP, oldhandler); 958127675Sbms#endif /* WIN32 */ 95917680Spst 96017680Spst if (pcap_setfilter(pd, &fcode) < 0) 96126180Sfenner error("%s", pcap_geterr(pd)); 96217680Spst if (WFileName) { 963146778Ssam pcap_dumper_t *p; 964146778Ssam 965146778Ssam WFileNameAlt = (char *)malloc(strlen(WFileName) + MAX_CFLAG_CHARS + 1); 966146778Ssam if (WFileNameAlt == NULL) 967146778Ssam error("malloc of WFileNameAlt"); 968146778Ssam MakeFilename(WFileNameAlt, WFileName, 0, WflagChars); 969146778Ssam p = pcap_dump_open(pd, WFileNameAlt); 97017680Spst if (p == NULL) 97126180Sfenner error("%s", pcap_geterr(pd)); 97298527Sfenner if (Cflag != 0) { 973127675Sbms callback = dump_packet_and_trunc; 97498527Sfenner dumpinfo.WFileName = WFileName; 97598527Sfenner dumpinfo.pd = pd; 97698527Sfenner dumpinfo.p = p; 97798527Sfenner pcap_userdata = (u_char *)&dumpinfo; 97898527Sfenner } else { 979127675Sbms callback = dump_packet; 98098527Sfenner pcap_userdata = (u_char *)p; 98198527Sfenner } 98217680Spst } else { 983127675Sbms type = pcap_datalink(pd); 984127675Sbms printinfo.printer = lookup_printer(type); 985127675Sbms if (printinfo.printer == NULL) { 986146778Ssam gndo->ndo_dltname = pcap_datalink_val_to_name(type); 987146778Ssam if (gndo->ndo_dltname != NULL) 988146778Ssam error("unsupported data link type %s", 989146778Ssam gndo->ndo_dltname); 990127675Sbms else 991127675Sbms error("unsupported data link type %d", type); 992127675Sbms } 993127675Sbms callback = print_packet; 994127675Sbms pcap_userdata = (u_char *)&printinfo; 995127675Sbms } 996146778Ssam#ifndef WIN32 997146778Ssam /* 998146778Ssam * We cannot do this earlier, because we want to be able to open 999146778Ssam * the file (if done) for writing before giving up permissions. 1000146778Ssam */ 1001146778Ssam if (getuid() == 0 || geteuid() == 0) { 1002146778Ssam if (username || chroot_dir) 1003146778Ssam droproot(username, chroot_dir); 1004146778Ssam } 1005146778Ssam#endif /* WIN32 */ 100698527Sfenner#ifdef SIGINFO 1007127675Sbms (void)setsignal(SIGINFO, requestinfo); 100898527Sfenner#endif 1009146778Ssam 1010146778Ssam if (vflag > 0 && WFileName) { 1011146778Ssam /* 1012146778Ssam * When capturing to a file, "-v" means tcpdump should, 1013146778Ssam * every 10 secodns, "v"erbosely report the number of 1014146778Ssam * packets captured. 1015146778Ssam */ 1016146778Ssam#ifdef USE_WIN32_MM_TIMER 1017146778Ssam /* call verbose_stats_dump() each 1000 +/-100msec */ 1018146778Ssam timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); 1019146778Ssam setvbuf(stderr, NULL, _IONBF, 0); 1020146778Ssam#elif defined(HAVE_ALARM) 1021146778Ssam (void)setsignal(SIGALRM, verbose_stats_dump); 1022146778Ssam alarm(1); 1023146778Ssam#endif 1024146778Ssam } 1025146778Ssam 1026127675Sbms#ifndef WIN32 102717680Spst if (RFileName == NULL) { 1028127675Sbms int dlt; 1029127675Sbms const char *dlt_name; 1030127675Sbms 1031127675Sbms if (!vflag && !WFileName) { 1032127675Sbms (void)fprintf(stderr, 1033127675Sbms "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", 1034127675Sbms program_name); 1035127675Sbms } else 1036127675Sbms (void)fprintf(stderr, "%s: ", program_name); 1037127675Sbms dlt = pcap_datalink(pd); 1038127675Sbms dlt_name = pcap_datalink_val_to_name(dlt); 1039127675Sbms if (dlt_name == NULL) { 1040127675Sbms (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", 1041127675Sbms device, dlt, snaplen); 1042127675Sbms } else { 1043127675Sbms (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", 1044127675Sbms device, dlt_name, 1045127675Sbms pcap_datalink_val_to_description(dlt), snaplen); 1046127675Sbms } 104717680Spst (void)fflush(stderr); 104817680Spst } 1049127675Sbms#endif /* WIN32 */ 1050127675Sbms status = pcap_loop(pd, cnt, callback, pcap_userdata); 1051127675Sbms if (WFileName == NULL) { 1052127675Sbms /* 1053127675Sbms * We're printing packets. Flush the printed output, 1054127675Sbms * so it doesn't get intermingled with error output. 1055127675Sbms */ 1056127675Sbms if (status == -2) { 1057127675Sbms /* 1058127675Sbms * We got interrupted, so perhaps we didn't 1059127675Sbms * manage to finish a line we were printing. 1060127675Sbms * Print an extra newline, just in case. 1061127675Sbms */ 1062127675Sbms putchar('\n'); 1063127675Sbms } 1064127675Sbms (void)fflush(stdout); 1065127675Sbms } 1066127675Sbms if (status == -1) { 1067127675Sbms /* 1068127675Sbms * Error. Report it. 1069127675Sbms */ 107017680Spst (void)fprintf(stderr, "%s: pcap_loop: %s\n", 107117680Spst program_name, pcap_geterr(pd)); 107217680Spst } 1073127675Sbms if (RFileName == NULL) { 1074127675Sbms /* 1075127675Sbms * We're doing a live capture. Report the capture 1076127675Sbms * statistics. 1077127675Sbms */ 107898527Sfenner info(1); 1079127675Sbms } 108017680Spst pcap_close(pd); 1081127675Sbms exit(status == -1 ? 1 : 0); 108217680Spst} 108317680Spst 108417680Spst/* make a clean exit on interrupts */ 108575118Sfennerstatic RETSIGTYPE 1086127675Sbmscleanup(int signo _U_) 108717680Spst{ 1088146778Ssam#ifdef USE_WIN32_MM_TIMER 1089146778Ssam if (timer_id) 1090146778Ssam timeKillEvent(timer_id); 1091146778Ssam timer_id = 0; 1092146778Ssam#elif defined(HAVE_ALARM) 1093146778Ssam alarm(0); 1094146778Ssam#endif 1095146778Ssam 1096127675Sbms#ifdef HAVE_PCAP_BREAKLOOP 1097127675Sbms /* 1098127675Sbms * We have "pcap_breakloop()"; use it, so that we do as little 1099127675Sbms * as possible in the signal handler (it's probably not safe 1100127675Sbms * to do anything with standard I/O streams in a signal handler - 1101127675Sbms * the ANSI C standard doesn't say it is). 1102127675Sbms */ 1103127675Sbms pcap_breakloop(pd); 1104127675Sbms#else 1105127675Sbms /* 1106127675Sbms * We don't have "pcap_breakloop()"; this isn't safe, but 1107127675Sbms * it's the best we can do. Print the summary if we're 1108127675Sbms * not reading from a savefile - i.e., if we're doing a 1109127675Sbms * live capture - and exit. 1110127675Sbms */ 111117680Spst if (pd != NULL && pcap_file(pd) == NULL) { 1112127675Sbms /* 1113127675Sbms * We got interrupted, so perhaps we didn't 1114127675Sbms * manage to finish a line we were printing. 1115127675Sbms * Print an extra newline, just in case. 1116127675Sbms */ 1117127675Sbms putchar('\n'); 111817680Spst (void)fflush(stdout); 111998527Sfenner info(1); 112017680Spst } 112117680Spst exit(0); 1122127675Sbms#endif 112317680Spst} 112417680Spst 1125127675Sbmsstatic void 112698527Sfennerinfo(register int verbose) 112798527Sfenner{ 112898527Sfenner struct pcap_stat stat; 112998527Sfenner 113098527Sfenner if (pcap_stats(pd, &stat) < 0) { 113198527Sfenner (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); 113298527Sfenner return; 113398527Sfenner } 1134127675Sbms 113598527Sfenner if (!verbose) 113698527Sfenner fprintf(stderr, "%s: ", program_name); 1137127675Sbms 1138127675Sbms (void)fprintf(stderr, "%u packets captured", packets_captured); 1139127675Sbms if (!verbose) 1140127675Sbms fputs(", ", stderr); 1141127675Sbms else 1142127675Sbms putc('\n', stderr); 114398527Sfenner (void)fprintf(stderr, "%d packets received by filter", stat.ps_recv); 114498527Sfenner if (!verbose) 114598527Sfenner fputs(", ", stderr); 114698527Sfenner else 114798527Sfenner putc('\n', stderr); 114898527Sfenner (void)fprintf(stderr, "%d packets dropped by kernel\n", stat.ps_drop); 114998527Sfenner infoprint = 0; 115098527Sfenner} 115198527Sfenner 115298527Sfennerstatic void 1153127675Sbmsdump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 115498527Sfenner{ 1155127675Sbms struct dump_info *dump_info; 115698527Sfenner char *name; 115798527Sfenner 1158127675Sbms ++packets_captured; 1159127675Sbms 1160127675Sbms ++infodelay; 1161127675Sbms 1162127675Sbms dump_info = (struct dump_info *)user; 1163127675Sbms 116498527Sfenner /* 116598527Sfenner * XXX - this won't prevent capture files from getting 116698527Sfenner * larger than Cflag - the last packet written to the 116798527Sfenner * file could put it over Cflag. 116898527Sfenner */ 1169147904Ssam if (pcap_dump_ftell(dump_info->p) > Cflag) { 1170127675Sbms /* 1171127675Sbms * Close the current file and open a new one. 1172127675Sbms */ 1173127675Sbms pcap_dump_close(dump_info->p); 1174146778Ssam Cflag_count++; 1175146778Ssam if (Wflag > 0) { 1176146778Ssam if (Cflag_count >= Wflag) 1177146778Ssam Cflag_count = 0; 1178146778Ssam } else { 1179146778Ssam if (Cflag_count >= MAX_CFLAG) 1180146778Ssam error("too many output files"); 1181146778Ssam } 1182146778Ssam name = (char *)malloc(strlen(dump_info->WFileName) + MAX_CFLAG_CHARS + 1); 118398527Sfenner if (name == NULL) 1184127675Sbms error("dump_packet_and_trunc: malloc"); 1185146778Ssam MakeFilename(name, dump_info->WFileName, Cflag_count, WflagChars); 1186127675Sbms dump_info->p = pcap_dump_open(dump_info->pd, name); 118798527Sfenner free(name); 1188127675Sbms if (dump_info->p == NULL) 118998527Sfenner error("%s", pcap_geterr(pd)); 119098527Sfenner } 119198527Sfenner 1192127675Sbms pcap_dump((u_char *)dump_info->p, h, sp); 1193127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1194127675Sbms if (Uflag) 1195127675Sbms pcap_dump_flush(dump_info->p); 1196127675Sbms#endif 1197127675Sbms 1198127675Sbms --infodelay; 1199127675Sbms if (infoprint) 1200127675Sbms info(0); 120198527Sfenner} 120298527Sfenner 1203127675Sbmsstatic void 1204127675Sbmsdump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 120517680Spst{ 1206127675Sbms ++packets_captured; 120717680Spst 1208127675Sbms ++infodelay; 1209127675Sbms 1210127675Sbms pcap_dump(user, h, sp); 1211127675Sbms#ifdef HAVE_PCAP_DUMP_FLUSH 1212127675Sbms if (Uflag) 1213127675Sbms pcap_dump_flush((pcap_dumper_t *)user); 1214127675Sbms#endif 1215127675Sbms 1216127675Sbms --infodelay; 1217127675Sbms if (infoprint) 1218127675Sbms info(0); 1219127675Sbms} 1220127675Sbms 1221127675Sbmsstatic void 1222127675Sbmsprint_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 1223127675Sbms{ 1224127675Sbms struct print_info *print_info; 1225127675Sbms u_int hdrlen; 1226127675Sbms 1227127675Sbms ++packets_captured; 1228127675Sbms 1229127675Sbms ++infodelay; 1230127675Sbms ts_print(&h->ts); 1231127675Sbms 1232127675Sbms print_info = (struct print_info *)user; 1233127675Sbms 1234127675Sbms /* 1235127675Sbms * Some printers want to check that they're not walking off the 1236127675Sbms * end of the packet. 1237127675Sbms * Rather than pass it all the way down, we set this global. 1238127675Sbms */ 1239127675Sbms snapend = sp + h->caplen; 1240127675Sbms 1241127675Sbms hdrlen = (*print_info->printer)(h, sp); 1242162021Ssam if (Xflag) { 1243127675Sbms /* 1244162021Ssam * Print the raw packet data in hex and ASCII. 1245127675Sbms */ 1246162021Ssam if (Xflag > 1) { 1247162021Ssam /* 1248162021Ssam * Include the link-layer header. 1249162021Ssam */ 1250162021Ssam hex_and_ascii_print("\n\t", sp, h->caplen); 1251162021Ssam } else { 1252162021Ssam /* 1253162021Ssam * Don't include the link-layer header - and if 1254162021Ssam * we have nothing past the link-layer header, 1255162021Ssam * print nothing. 1256162021Ssam */ 1257162021Ssam if (h->caplen > hdrlen) 1258162021Ssam hex_and_ascii_print("\n\t", sp + hdrlen, 1259162021Ssam h->caplen - hdrlen); 1260162021Ssam } 1261162021Ssam } else if (xflag) { 1262162021Ssam /* 1263162021Ssam * Print the raw packet data in hex. 1264162021Ssam */ 1265127675Sbms if (xflag > 1) { 1266127675Sbms /* 1267127675Sbms * Include the link-layer header. 1268127675Sbms */ 1269146778Ssam hex_print("\n\t", sp, h->caplen); 1270127675Sbms } else { 1271127675Sbms /* 1272127675Sbms * Don't include the link-layer header - and if 1273127675Sbms * we have nothing past the link-layer header, 1274127675Sbms * print nothing. 1275127675Sbms */ 1276127675Sbms if (h->caplen > hdrlen) 1277146778Ssam hex_print("\n\t", sp + hdrlen, 1278127675Sbms h->caplen - hdrlen); 1279127675Sbms } 1280162021Ssam } else if (Aflag) { 1281146778Ssam /* 1282162021Ssam * Print the raw packet data in ASCII. 1283146778Ssam */ 1284162021Ssam if (Aflag > 1) { 1285146778Ssam /* 1286146778Ssam * Include the link-layer header. 1287146778Ssam */ 1288162021Ssam ascii_print(sp, h->caplen); 1289146778Ssam } else { 1290146778Ssam /* 1291146778Ssam * Don't include the link-layer header - and if 1292146778Ssam * we have nothing past the link-layer header, 1293146778Ssam * print nothing. 1294146778Ssam */ 1295146778Ssam if (h->caplen > hdrlen) 1296162021Ssam ascii_print(sp + hdrlen, h->caplen - hdrlen); 1297146778Ssam } 129817680Spst } 1299127675Sbms 1300127675Sbms putchar('\n'); 1301127675Sbms 1302127675Sbms --infodelay; 1303127675Sbms if (infoprint) 1304127675Sbms info(0); 130517680Spst} 130617680Spst 1307127675Sbms#ifdef WIN32 1308127675Sbms /* 1309127675Sbms * XXX - there should really be libpcap calls to get the version 1310127675Sbms * number as a string (the string would be generated from #defines 1311127675Sbms * at run time, so that it's not generated from string constants 1312127675Sbms * in the library, as, on many UNIX systems, those constants would 1313127675Sbms * be statically linked into the application executable image, and 1314127675Sbms * would thus reflect the version of libpcap on the system on 1315127675Sbms * which the application was *linked*, not the system on which it's 1316127675Sbms * *running*. 1317127675Sbms * 1318127675Sbms * That routine should be documented, unlike the "version[]" 1319127675Sbms * string, so that UNIX vendors providing their own libpcaps 1320127675Sbms * don't omit it (as a couple of vendors have...). 1321127675Sbms * 1322127675Sbms * Packet.dll should perhaps also export a routine to return the 1323127675Sbms * version number of the Packet.dll code, to supply the 1324127675Sbms * "Wpcap_version" information on Windows. 1325127675Sbms */ 1326127675Sbms char WDversion[]="current-cvs.tcpdump.org"; 1327146778Ssam#if !defined(HAVE_GENERATED_VERSION) 1328127675Sbms char version[]="current-cvs.tcpdump.org"; 1329146778Ssam#endif 1330127675Sbms char pcap_version[]="current-cvs.tcpdump.org"; 1331146778Ssam char Wpcap_version[]="3.1"; 1332127675Sbms#endif 1333127675Sbms 133439297Sfenner/* 1335162021Ssam * By default, print the specified data out in hex and ASCII. 133639297Sfenner */ 1337146778Ssamstatic void 1338146778Ssamndo_default_print(netdissect_options *ndo _U_, const u_char *bp, u_int length) 1339146778Ssam{ 1340162021Ssam hex_and_ascii_print("\n\t", bp, length); /* pass on lf and identation string */ 1341146778Ssam} 1342146778Ssam 134317680Spstvoid 1344146778Ssamdefault_print(const u_char *bp, u_int length) 134517680Spst{ 1346146778Ssam ndo_default_print(gndo, bp, length); 134717680Spst} 134817680Spst 134998527Sfenner#ifdef SIGINFO 1350127675SbmsRETSIGTYPE requestinfo(int signo _U_) 135198527Sfenner{ 135298527Sfenner if (infodelay) 135398527Sfenner ++infoprint; 135498527Sfenner else 135598527Sfenner info(0); 135698527Sfenner} 135798527Sfenner#endif 135898527Sfenner 1359146778Ssam/* 1360146778Ssam * Called once each second in verbose mode while dumping to file 1361146778Ssam */ 1362146778Ssam#ifdef USE_WIN32_MM_TIMER 1363146778Ssamvoid CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, 1364146778Ssam DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) 1365146778Ssam{ 1366146778Ssam struct pcap_stat stat; 1367146778Ssam 1368146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1369146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 1370146778Ssam} 1371146778Ssam#elif defined(HAVE_ALARM) 1372146778Ssamstatic void verbose_stats_dump(int sig _U_) 1373146778Ssam{ 1374146778Ssam struct pcap_stat stat; 1375146778Ssam 1376146778Ssam if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) 1377146778Ssam fprintf(stderr, "Got %u\r", packets_captured); 1378146778Ssam alarm(1); 1379146778Ssam} 1380146778Ssam#endif 1381146778Ssam 138275118Sfennerstatic void 138326180Sfennerusage(void) 138417680Spst{ 138517680Spst extern char version[]; 1386127675Sbms#ifndef HAVE_PCAP_LIB_VERSION 1387127675Sbms#if defined(WIN32) || defined(HAVE_PCAP_VERSION) 138839297Sfenner extern char pcap_version[]; 1389127675Sbms#else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1390127675Sbms static char pcap_version[] = "unknown"; 1391127675Sbms#endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ 1392127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 139317680Spst 1394127675Sbms#ifdef HAVE_PCAP_LIB_VERSION 1395146778Ssam#ifdef WIN32 1396146778Ssam (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1397146778Ssam#else /* WIN32 */ 139839297Sfenner (void)fprintf(stderr, "%s version %s\n", program_name, version); 1399146778Ssam#endif /* WIN32 */ 1400146778Ssam (void)fprintf(stderr, "%s\n",pcap_lib_version()); 1401127675Sbms#else /* HAVE_PCAP_LIB_VERSION */ 1402127675Sbms#ifdef WIN32 1403127675Sbms (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); 1404127675Sbms (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); 1405127675Sbms#else /* WIN32 */ 1406127675Sbms (void)fprintf(stderr, "%s version %s\n", program_name, version); 140739297Sfenner (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 1408127675Sbms#endif /* WIN32 */ 1409127675Sbms#endif /* HAVE_PCAP_LIB_VERSION */ 141017680Spst (void)fprintf(stderr, 1411127675Sbms"Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name); 141217680Spst (void)fprintf(stderr, 1413146778Ssam"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]\n"); 141417680Spst (void)fprintf(stderr, 1415146778Ssam"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n"); 1416109842Sfenner (void)fprintf(stderr, 1417146778Ssam"\t\t[ -W filecount ] [ -y datalinktype ] [ -Z user ]\n"); 1418146778Ssam (void)fprintf(stderr, 1419109842Sfenner"\t\t[ expression ]\n"); 142098527Sfenner exit(1); 142117680Spst} 1422146778Ssam 1423146778Ssam 1424146778Ssam 1425146778Ssam/* VARARGS */ 1426146778Ssamstatic void 1427146778Ssamndo_error(netdissect_options *ndo _U_, const char *fmt, ...) 1428146778Ssam{ 1429146778Ssam va_list ap; 1430146778Ssam 1431146778Ssam (void)fprintf(stderr, "%s: ", program_name); 1432146778Ssam va_start(ap, fmt); 1433146778Ssam (void)vfprintf(stderr, fmt, ap); 1434146778Ssam va_end(ap); 1435146778Ssam if (*fmt) { 1436146778Ssam fmt += strlen(fmt); 1437146778Ssam if (fmt[-1] != '\n') 1438146778Ssam (void)fputc('\n', stderr); 1439146778Ssam } 1440146778Ssam exit(1); 1441146778Ssam /* NOTREACHED */ 1442146778Ssam} 1443146778Ssam 1444146778Ssam/* VARARGS */ 1445146778Ssamstatic void 1446146778Ssamndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) 1447146778Ssam{ 1448146778Ssam va_list ap; 1449146778Ssam 1450146778Ssam (void)fprintf(stderr, "%s: WARNING: ", program_name); 1451146778Ssam va_start(ap, fmt); 1452146778Ssam (void)vfprintf(stderr, fmt, ap); 1453146778Ssam va_end(ap); 1454146778Ssam if (*fmt) { 1455146778Ssam fmt += strlen(fmt); 1456146778Ssam if (fmt[-1] != '\n') 1457146778Ssam (void)fputc('\n', stderr); 1458146778Ssam } 1459146778Ssam} 1460146778Ssam 1461