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