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