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