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