| @@ -1,1206 +1,1208 @@ | | | @@ -1,1206 +1,1208 @@ |
1 | /* | | 1 | /* |
2 | * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 | | 2 | * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 |
3 | * The Regents of the University of California. All rights reserved. | | 3 | * The Regents of the University of California. All rights reserved. |
4 | * | | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that: (1) source code distributions | | 6 | * modification, are permitted provided that: (1) source code distributions |
7 | * retain the above copyright notice and this paragraph in its entirety, (2) | | 7 | * retain the above copyright notice and this paragraph in its entirety, (2) |
8 | * distributions including binary code include the above copyright notice and | | 8 | * distributions including binary code include the above copyright notice and |
9 | * this paragraph in its entirety in the documentation or other materials | | 9 | * this paragraph in its entirety in the documentation or other materials |
10 | * provided with the distribution, and (3) all advertising materials mentioning | | 10 | * provided with the distribution, and (3) all advertising materials mentioning |
11 | * features or use of this software display the following acknowledgement: | | 11 | * features or use of this software display the following acknowledgement: |
12 | * ``This product includes software developed by the University of California, | | 12 | * ``This product includes software developed by the University of California, |
13 | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of | | 13 | * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
14 | * the University nor the names of its contributors may be used to endorse | | 14 | * the University nor the names of its contributors may be used to endorse |
15 | * or promote products derived from this software without specific prior | | 15 | * or promote products derived from this software without specific prior |
16 | * written permission. | | 16 | * written permission. |
17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED | | 17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
18 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | | 18 | * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | | 19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
20 | * | | 20 | * |
21 | * Support for splitting captures into multiple files with a maximum | | 21 | * Support for splitting captures into multiple files with a maximum |
22 | * file size: | | 22 | * file size: |
23 | * | | 23 | * |
24 | * Copyright (c) 2001 | | 24 | * Copyright (c) 2001 |
25 | * Seth Webster <swebster@sst.ll.mit.edu> | | 25 | * Seth Webster <swebster@sst.ll.mit.edu> |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | #include <sys/cdefs.h> | | 28 | #include <sys/cdefs.h> |
29 | #ifndef lint | | 29 | #ifndef lint |
30 | static const char copyright[] _U_ = | | 30 | static const char copyright[] _U_ = |
31 | "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ | | 31 | "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ |
32 | The Regents of the University of California. All rights reserved.\n"; | | 32 | The Regents of the University of California. All rights reserved.\n"; |
33 | __RCSID("$NetBSD: tcpdump.c,v 1.13 2017/01/24 23:29:14 christos Exp $"); | | 33 | __RCSID("$NetBSD: tcpdump.c,v 1.14 2017/01/30 13:15:43 christos Exp $"); |
34 | #endif | | 34 | #endif |
35 | | | 35 | |
36 | /* | | 36 | /* |
37 | * tcpdump - dump traffic on a network | | 37 | * tcpdump - dump traffic on a network |
38 | * | | 38 | * |
39 | * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. | | 39 | * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. |
40 | * Mercilessly hacked and occasionally improved since then via the | | 40 | * Mercilessly hacked and occasionally improved since then via the |
41 | * combined efforts of Van, Steve McCanne and Craig Leres of LBL. | | 41 | * combined efforts of Van, Steve McCanne and Craig Leres of LBL. |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #ifdef HAVE_CONFIG_H | | 44 | #ifdef HAVE_CONFIG_H |
45 | #include "config.h" | | 45 | #include "config.h" |
46 | #endif | | 46 | #endif |
47 | | | 47 | |
48 | /* | | 48 | /* |
49 | * Mac OS X may ship pcap.h from libpcap 0.6 with a libpcap based on | | 49 | * Mac OS X may ship pcap.h from libpcap 0.6 with a libpcap based on |
50 | * 0.8. That means it has pcap_findalldevs() but the header doesn't | | 50 | * 0.8. That means it has pcap_findalldevs() but the header doesn't |
51 | * define pcap_if_t, meaning that we can't actually *use* pcap_findalldevs(). | | 51 | * define pcap_if_t, meaning that we can't actually *use* pcap_findalldevs(). |
52 | */ | | 52 | */ |
53 | #ifdef HAVE_PCAP_FINDALLDEVS | | 53 | #ifdef HAVE_PCAP_FINDALLDEVS |
54 | #ifndef HAVE_PCAP_IF_T | | 54 | #ifndef HAVE_PCAP_IF_T |
55 | #undef HAVE_PCAP_FINDALLDEVS | | 55 | #undef HAVE_PCAP_FINDALLDEVS |
56 | #endif | | 56 | #endif |
57 | #endif | | 57 | #endif |
58 | | | 58 | |
59 | #include <netdissect-stdinc.h> | | 59 | #include <netdissect-stdinc.h> |
60 | | | 60 | |
61 | #ifdef USE_LIBSMI | | 61 | #ifdef USE_LIBSMI |
62 | #include <smi.h> | | 62 | #include <smi.h> |
63 | #endif | | 63 | #endif |
64 | | | 64 | |
65 | #ifdef HAVE_LIBCRYPTO | | 65 | #ifdef HAVE_LIBCRYPTO |
66 | #include <openssl/crypto.h> | | 66 | #include <openssl/crypto.h> |
67 | #endif | | 67 | #endif |
68 | | | 68 | |
69 | #ifdef HAVE_GETOPT_LONG | | 69 | #ifdef HAVE_GETOPT_LONG |
70 | #include <getopt.h> | | 70 | #include <getopt.h> |
71 | #else | | 71 | #else |
72 | #include "getopt_long.h" | | 72 | #include "getopt_long.h" |
73 | #endif | | 73 | #endif |
74 | /* Capsicum-specific code requires macros from <net/bpf.h>, which will fail | | 74 | /* Capsicum-specific code requires macros from <net/bpf.h>, which will fail |
75 | * to compile if <pcap.h> has already been included; including the headers | | 75 | * to compile if <pcap.h> has already been included; including the headers |
76 | * in the opposite order works fine. | | 76 | * in the opposite order works fine. |
77 | */ | | 77 | */ |
78 | #ifdef HAVE_CAPSICUM | | 78 | #ifdef HAVE_CAPSICUM |
79 | #include <sys/capability.h> | | 79 | #include <sys/capability.h> |
80 | #include <sys/ioccom.h> | | 80 | #include <sys/ioccom.h> |
81 | #include <net/bpf.h> | | 81 | #include <net/bpf.h> |
82 | #include <fcntl.h> | | 82 | #include <fcntl.h> |
83 | #include <libgen.h> | | 83 | #include <libgen.h> |
84 | #endif /* HAVE_CAPSICUM */ | | 84 | #endif /* HAVE_CAPSICUM */ |
85 | #include <pcap.h> | | 85 | #include <pcap.h> |
86 | #include <signal.h> | | 86 | #include <signal.h> |
87 | #include <stdio.h> | | 87 | #include <stdio.h> |
88 | #include <stdlib.h> | | 88 | #include <stdlib.h> |
89 | #include <string.h> | | 89 | #include <string.h> |
90 | #include <limits.h> | | 90 | #include <limits.h> |
91 | #include <resolv.h> | | 91 | #include <resolv.h> |
92 | #ifndef _WIN32 | | 92 | #ifndef _WIN32 |
93 | #include <sys/wait.h> | | 93 | #include <sys/wait.h> |
94 | #include <sys/resource.h> | | 94 | #include <sys/resource.h> |
95 | #include <pwd.h> | | 95 | #include <pwd.h> |
96 | #include <grp.h> | | 96 | #include <grp.h> |
97 | #endif /* _WIN32 */ | | 97 | #endif /* _WIN32 */ |
98 | | | 98 | |
99 | /* capabilities convenience library */ | | 99 | /* capabilities convenience library */ |
100 | /* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H. | | 100 | /* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H. |
101 | * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG. | | 101 | * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG. |
102 | * Thus, the later tests are done only on HAVE_LIBCAP_NG. | | 102 | * Thus, the later tests are done only on HAVE_LIBCAP_NG. |
103 | */ | | 103 | */ |
104 | #ifdef HAVE_LIBCAP_NG | | 104 | #ifdef HAVE_LIBCAP_NG |
105 | #ifdef HAVE_CAP_NG_H | | 105 | #ifdef HAVE_CAP_NG_H |
106 | #include <cap-ng.h> | | 106 | #include <cap-ng.h> |
107 | #else | | 107 | #else |
108 | #undef HAVE_LIBCAP_NG | | 108 | #undef HAVE_LIBCAP_NG |
109 | #endif /* HAVE_CAP_NG_H */ | | 109 | #endif /* HAVE_CAP_NG_H */ |
110 | #endif /* HAVE_LIBCAP_NG */ | | 110 | #endif /* HAVE_LIBCAP_NG */ |
111 | | | 111 | |
112 | #include "netdissect.h" | | 112 | #include "netdissect.h" |
113 | #include "interface.h" | | 113 | #include "interface.h" |
114 | #include "addrtoname.h" | | 114 | #include "addrtoname.h" |
115 | #include "machdep.h" | | 115 | #include "machdep.h" |
116 | #include "setsignal.h" | | 116 | #include "setsignal.h" |
117 | #include "gmt2local.h" | | 117 | #include "gmt2local.h" |
118 | #include "pcap-missing.h" | | 118 | #include "pcap-missing.h" |
119 | #include "ascii_strcasecmp.h" | | 119 | #include "ascii_strcasecmp.h" |
120 | | | 120 | |
121 | #include "print.h" | | 121 | #include "print.h" |
122 | | | 122 | |
123 | #ifndef PATH_MAX | | 123 | #ifndef PATH_MAX |
124 | #define PATH_MAX 1024 | | 124 | #define PATH_MAX 1024 |
125 | #endif | | 125 | #endif |
126 | | | 126 | |
127 | #ifdef SIGINFO | | 127 | #ifdef SIGINFO |
128 | #define SIGNAL_REQ_INFO SIGINFO | | 128 | #define SIGNAL_REQ_INFO SIGINFO |
129 | #elif SIGUSR1 | | 129 | #elif SIGUSR1 |
130 | #define SIGNAL_REQ_INFO SIGUSR1 | | 130 | #define SIGNAL_REQ_INFO SIGUSR1 |
131 | #endif | | 131 | #endif |
132 | | | 132 | |
133 | static int Cflag; /* rotate dump files after this many bytes */ | | 133 | static int Cflag; /* rotate dump files after this many bytes */ |
134 | static int Cflag_count; /* Keep track of which file number we're writing */ | | 134 | static int Cflag_count; /* Keep track of which file number we're writing */ |
135 | static int Dflag; /* list available devices and exit */ | | 135 | static int Dflag; /* list available devices and exit */ |
136 | /* | | 136 | /* |
137 | * This is exported because, in some versions of libpcap, if libpcap | | 137 | * This is exported because, in some versions of libpcap, if libpcap |
138 | * is built with optimizer debugging code (which is *NOT* the default | | 138 | * is built with optimizer debugging code (which is *NOT* the default |
139 | * configuration!), the library *imports*(!) a variable named dflag, | | 139 | * configuration!), the library *imports*(!) a variable named dflag, |
140 | * under the expectation that tcpdump is exporting it, to govern | | 140 | * under the expectation that tcpdump is exporting it, to govern |
141 | * how much debugging information to print when optimizing | | 141 | * how much debugging information to print when optimizing |
142 | * the generated BPF code. | | 142 | * the generated BPF code. |
143 | * | | 143 | * |
144 | * This is a horrible hack; newer versions of libpcap don't import | | 144 | * This is a horrible hack; newer versions of libpcap don't import |
145 | * dflag but, instead, *if* built with optimizer debugging code, | | 145 | * dflag but, instead, *if* built with optimizer debugging code, |
146 | * *export* a routine to set that flag. | | 146 | * *export* a routine to set that flag. |
147 | */ | | 147 | */ |
148 | int dflag; /* print filter code */ | | 148 | int dflag; /* print filter code */ |
149 | static int Gflag; /* rotate dump files after this many seconds */ | | 149 | static int Gflag; /* rotate dump files after this many seconds */ |
150 | static int Gflag_count; /* number of files created with Gflag rotation */ | | 150 | static int Gflag_count; /* number of files created with Gflag rotation */ |
151 | static time_t Gflag_time; /* The last time_t the dump file was rotated. */ | | 151 | static time_t Gflag_time; /* The last time_t the dump file was rotated. */ |
152 | static int Lflag; /* list available data link types and exit */ | | 152 | static int Lflag; /* list available data link types and exit */ |
153 | static int Iflag; /* rfmon (monitor) mode */ | | 153 | static int Iflag; /* rfmon (monitor) mode */ |
154 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE | | 154 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE |
155 | static int Jflag; /* list available time stamp types */ | | 155 | static int Jflag; /* list available time stamp types */ |
156 | #endif | | 156 | #endif |
157 | #ifdef HAVE_PCAP_SETDIRECTION | | 157 | #ifdef HAVE_PCAP_SETDIRECTION |
158 | int Qflag = -1; /* restrict captured packet by send/receive direction */ | | 158 | int Qflag = -1; /* restrict captured packet by send/receive direction */ |
159 | #endif | | 159 | #endif |
160 | static int Uflag; /* "unbuffered" output of dump files */ | | 160 | static int Uflag; /* "unbuffered" output of dump files */ |
161 | static int Wflag; /* recycle output files after this number of files */ | | 161 | static int Wflag; /* recycle output files after this number of files */ |
162 | static int WflagChars; | | 162 | static int WflagChars; |
163 | static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ | | 163 | static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ |
164 | | | 164 | |
165 | static int infodelay; | | 165 | static int infodelay; |
166 | static int infoprint; | | 166 | static int infoprint; |
167 | | | 167 | |
168 | char *program_name; | | 168 | char *program_name; |
169 | | | 169 | |
170 | /* Forwards */ | | 170 | /* Forwards */ |
171 | static RETSIGTYPE cleanup(int); | | 171 | static RETSIGTYPE cleanup(int); |
172 | static RETSIGTYPE child_cleanup(int); | | 172 | static RETSIGTYPE child_cleanup(int); |
173 | static void print_version(void); | | 173 | static void print_version(void); |
174 | static void print_usage(void); | | 174 | static void print_usage(void); |
175 | static void show_tstamp_types_and_exit(const char *device) __attribute__((noreturn)); | | 175 | static void show_tstamp_types_and_exit(const char *device) __attribute__((noreturn)); |
176 | static void show_dlts_and_exit(const char *device) __attribute__((noreturn)); | | 176 | static void show_dlts_and_exit(const char *device) __attribute__((noreturn)); |
177 | | | 177 | |
178 | static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); | | 178 | static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); |
179 | static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); | | 179 | static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); |
180 | static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); | | 180 | static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); |
181 | static void droproot(const char *, const char *); | | 181 | static void droproot(const char *, const char *); |
182 | | | 182 | |
183 | #ifdef SIGNAL_REQ_INFO | | 183 | #ifdef SIGNAL_REQ_INFO |
184 | RETSIGTYPE requestinfo(int); | | 184 | RETSIGTYPE requestinfo(int); |
185 | #endif | | 185 | #endif |
186 | | | 186 | |
187 | #if defined(USE_WIN32_MM_TIMER) | | 187 | #if defined(USE_WIN32_MM_TIMER) |
188 | #include <MMsystem.h> | | 188 | #include <MMsystem.h> |
189 | static UINT timer_id; | | 189 | static UINT timer_id; |
190 | static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); | | 190 | static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); |
191 | #elif defined(HAVE_ALARM) | | 191 | #elif defined(HAVE_ALARM) |
192 | static void verbose_stats_dump(int sig); | | 192 | static void verbose_stats_dump(int sig); |
193 | #endif | | 193 | #endif |
194 | | | 194 | |
195 | static void info(int); | | 195 | static void info(int); |
196 | static u_int packets_captured; | | 196 | static u_int packets_captured; |
197 | | | 197 | |
| | | 198 | #ifdef HAVE_PCAP_FINDALLDEVS |
198 | static const struct tok status_flags[] = { | | 199 | static const struct tok status_flags[] = { |
199 | #ifdef PCAP_IF_UP | | 200 | #ifdef PCAP_IF_UP |
200 | { PCAP_IF_UP, "Up" }, | | 201 | { PCAP_IF_UP, "Up" }, |
201 | #endif | | 202 | #endif |
202 | #ifdef PCAP_IF_RUNNING | | 203 | #ifdef PCAP_IF_RUNNING |
203 | { PCAP_IF_RUNNING, "Running" }, | | 204 | { PCAP_IF_RUNNING, "Running" }, |
204 | #endif | | 205 | #endif |
205 | { PCAP_IF_LOOPBACK, "Loopback" }, | | 206 | { PCAP_IF_LOOPBACK, "Loopback" }, |
206 | { 0, NULL } | | 207 | { 0, NULL } |
207 | }; | | 208 | }; |
| | | 209 | #endif |
208 | | | 210 | |
209 | static pcap_t *pd; | | 211 | static pcap_t *pd; |
210 | | | 212 | |
211 | static int supports_monitor_mode; | | 213 | static int supports_monitor_mode; |
212 | | | 214 | |
213 | extern int optind; | | 215 | extern int optind; |
214 | extern int opterr; | | 216 | extern int opterr; |
215 | extern char *optarg; | | 217 | extern char *optarg; |
216 | | | 218 | |
217 | struct dump_info { | | 219 | struct dump_info { |
218 | char *WFileName; | | 220 | char *WFileName; |
219 | char *CurrentFileName; | | 221 | char *CurrentFileName; |
220 | pcap_t *pd; | | 222 | pcap_t *pd; |
221 | pcap_dumper_t *p; | | 223 | pcap_dumper_t *p; |
222 | #ifdef HAVE_CAPSICUM | | 224 | #ifdef HAVE_CAPSICUM |
223 | int dirfd; | | 225 | int dirfd; |
224 | #endif | | 226 | #endif |
225 | }; | | 227 | }; |
226 | | | 228 | |
227 | #if defined(HAVE_PCAP_SET_PARSER_DEBUG) | | 229 | #if defined(HAVE_PCAP_SET_PARSER_DEBUG) |
228 | /* | | 230 | /* |
229 | * We have pcap_set_parser_debug() in libpcap; declare it (it's not declared | | 231 | * We have pcap_set_parser_debug() in libpcap; declare it (it's not declared |
230 | * by any libpcap header, because it's a special hack, only available if | | 232 | * by any libpcap header, because it's a special hack, only available if |
231 | * libpcap was configured to include it, and only intended for use by | | 233 | * libpcap was configured to include it, and only intended for use by |
232 | * libpcap developers trying to debug the parser for filter expressions). | | 234 | * libpcap developers trying to debug the parser for filter expressions). |
233 | */ | | 235 | */ |
234 | #ifdef _WIN32 | | 236 | #ifdef _WIN32 |
235 | __declspec(dllimport) | | 237 | __declspec(dllimport) |
236 | #else /* _WIN32 */ | | 238 | #else /* _WIN32 */ |
237 | extern | | 239 | extern |
238 | #endif /* _WIN32 */ | | 240 | #endif /* _WIN32 */ |
239 | void pcap_set_parser_debug(int); | | 241 | void pcap_set_parser_debug(int); |
240 | #elif defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) | | 242 | #elif defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) |
241 | /* | | 243 | /* |
242 | * We don't have pcap_set_parser_debug() in libpcap, but we do have | | 244 | * We don't have pcap_set_parser_debug() in libpcap, but we do have |
243 | * pcap_debug or yydebug. Make a local version of pcap_set_parser_debug() | | 245 | * pcap_debug or yydebug. Make a local version of pcap_set_parser_debug() |
244 | * to set the flag, and define HAVE_PCAP_SET_PARSER_DEBUG. | | 246 | * to set the flag, and define HAVE_PCAP_SET_PARSER_DEBUG. |
245 | */ | | 247 | */ |
246 | static void | | 248 | static void |
247 | pcap_set_parser_debug(int value) | | 249 | pcap_set_parser_debug(int value) |
248 | { | | 250 | { |
249 | #ifdef HAVE_PCAP_DEBUG | | 251 | #ifdef HAVE_PCAP_DEBUG |
250 | extern int pcap_debug; | | 252 | extern int pcap_debug; |
251 | | | 253 | |
252 | pcap_debug = value; | | 254 | pcap_debug = value; |
253 | #else /* HAVE_PCAP_DEBUG */ | | 255 | #else /* HAVE_PCAP_DEBUG */ |
254 | extern int yydebug; | | 256 | extern int yydebug; |
255 | | | 257 | |
256 | yydebug = value; | | 258 | yydebug = value; |
257 | #endif /* HAVE_PCAP_DEBUG */ | | 259 | #endif /* HAVE_PCAP_DEBUG */ |
258 | } | | 260 | } |
259 | | | 261 | |
260 | #define HAVE_PCAP_SET_PARSER_DEBUG | | 262 | #define HAVE_PCAP_SET_PARSER_DEBUG |
261 | #endif | | 263 | #endif |
262 | | | 264 | |
263 | #if defined(HAVE_PCAP_SET_OPTIMIZER_DEBUG) | | 265 | #if defined(HAVE_PCAP_SET_OPTIMIZER_DEBUG) |
264 | /* | | 266 | /* |
265 | * We have pcap_set_optimizer_debug() in libpcap; declare it (it's not declared | | 267 | * We have pcap_set_optimizer_debug() in libpcap; declare it (it's not declared |
266 | * by any libpcap header, because it's a special hack, only available if | | 268 | * by any libpcap header, because it's a special hack, only available if |
267 | * libpcap was configured to include it, and only intended for use by | | 269 | * libpcap was configured to include it, and only intended for use by |
268 | * libpcap developers trying to debug the optimizer for filter expressions). | | 270 | * libpcap developers trying to debug the optimizer for filter expressions). |
269 | */ | | 271 | */ |
270 | #ifdef _WIN32 | | 272 | #ifdef _WIN32 |
271 | __declspec(dllimport) | | 273 | __declspec(dllimport) |
272 | #else /* _WIN32 */ | | 274 | #else /* _WIN32 */ |
273 | extern | | 275 | extern |
274 | #endif /* _WIN32 */ | | 276 | #endif /* _WIN32 */ |
275 | void pcap_set_optimizer_debug(int); | | 277 | void pcap_set_optimizer_debug(int); |
276 | #endif | | 278 | #endif |
277 | | | 279 | |
278 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE | | 280 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE |
279 | static void | | 281 | static void |
280 | show_tstamp_types_and_exit(const char *device) | | 282 | show_tstamp_types_and_exit(const char *device) |
281 | { | | 283 | { |
282 | int n_tstamp_types; | | 284 | int n_tstamp_types; |
283 | int *tstamp_types = 0; | | 285 | int *tstamp_types = 0; |
284 | const char *tstamp_type_name; | | 286 | const char *tstamp_type_name; |
285 | int i; | | 287 | int i; |
286 | | | 288 | |
287 | n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types); | | 289 | n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types); |
288 | if (n_tstamp_types < 0) | | 290 | if (n_tstamp_types < 0) |
289 | error("%s", pcap_geterr(pd)); | | 291 | error("%s", pcap_geterr(pd)); |
290 | | | 292 | |
291 | if (n_tstamp_types == 0) { | | 293 | if (n_tstamp_types == 0) { |
292 | fprintf(stderr, "Time stamp type cannot be set for %s\n", | | 294 | fprintf(stderr, "Time stamp type cannot be set for %s\n", |
293 | device); | | 295 | device); |
294 | exit(0); | | 296 | exit(0); |
295 | } | | 297 | } |
296 | fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", | | 298 | fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", |
297 | device); | | 299 | device); |
298 | for (i = 0; i < n_tstamp_types; i++) { | | 300 | for (i = 0; i < n_tstamp_types; i++) { |
299 | tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); | | 301 | tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); |
300 | if (tstamp_type_name != NULL) { | | 302 | if (tstamp_type_name != NULL) { |
301 | (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, | | 303 | (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, |
302 | pcap_tstamp_type_val_to_description(tstamp_types[i])); | | 304 | pcap_tstamp_type_val_to_description(tstamp_types[i])); |
303 | } else { | | 305 | } else { |
304 | (void) fprintf(stderr, " %d\n", tstamp_types[i]); | | 306 | (void) fprintf(stderr, " %d\n", tstamp_types[i]); |
305 | } | | 307 | } |
306 | } | | 308 | } |
307 | pcap_free_tstamp_types(tstamp_types); | | 309 | pcap_free_tstamp_types(tstamp_types); |
308 | exit(0); | | 310 | exit(0); |
309 | } | | 311 | } |
310 | #endif | | 312 | #endif |
311 | | | 313 | |
312 | static void | | 314 | static void |
313 | show_dlts_and_exit(const char *device) | | 315 | show_dlts_and_exit(const char *device) |
314 | { | | 316 | { |
315 | int n_dlts, i; | | 317 | int n_dlts, i; |
316 | int *dlts = 0; | | 318 | int *dlts = 0; |
317 | const char *dlt_name; | | 319 | const char *dlt_name; |
318 | | | 320 | |
319 | n_dlts = pcap_list_datalinks(pd, &dlts); | | 321 | n_dlts = pcap_list_datalinks(pd, &dlts); |
320 | if (n_dlts < 0) | | 322 | if (n_dlts < 0) |
321 | error("%s", pcap_geterr(pd)); | | 323 | error("%s", pcap_geterr(pd)); |
322 | else if (n_dlts == 0 || !dlts) | | 324 | else if (n_dlts == 0 || !dlts) |
323 | error("No data link types."); | | 325 | error("No data link types."); |
324 | | | 326 | |
325 | /* | | 327 | /* |
326 | * If the interface is known to support monitor mode, indicate | | 328 | * If the interface is known to support monitor mode, indicate |
327 | * whether these are the data link types available when not in | | 329 | * whether these are the data link types available when not in |
328 | * monitor mode, if -I wasn't specified, or when in monitor mode, | | 330 | * monitor mode, if -I wasn't specified, or when in monitor mode, |
329 | * when -I was specified (the link-layer types available in | | 331 | * when -I was specified (the link-layer types available in |
330 | * monitor mode might be different from the ones available when | | 332 | * monitor mode might be different from the ones available when |
331 | * not in monitor mode). | | 333 | * not in monitor mode). |
332 | */ | | 334 | */ |
333 | if (supports_monitor_mode) | | 335 | if (supports_monitor_mode) |
334 | (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", | | 336 | (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", |
335 | device, | | 337 | device, |
336 | Iflag ? "when in monitor mode" : "when not in monitor mode"); | | 338 | Iflag ? "when in monitor mode" : "when not in monitor mode"); |
337 | else | | 339 | else |
338 | (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", | | 340 | (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", |
339 | device); | | 341 | device); |
340 | | | 342 | |
341 | for (i = 0; i < n_dlts; i++) { | | 343 | for (i = 0; i < n_dlts; i++) { |
342 | dlt_name = pcap_datalink_val_to_name(dlts[i]); | | 344 | dlt_name = pcap_datalink_val_to_name(dlts[i]); |
343 | if (dlt_name != NULL) { | | 345 | if (dlt_name != NULL) { |
344 | (void) fprintf(stderr, " %s (%s)", dlt_name, | | 346 | (void) fprintf(stderr, " %s (%s)", dlt_name, |
345 | pcap_datalink_val_to_description(dlts[i])); | | 347 | pcap_datalink_val_to_description(dlts[i])); |
346 | | | 348 | |
347 | /* | | 349 | /* |
348 | * OK, does tcpdump handle that type? | | 350 | * OK, does tcpdump handle that type? |
349 | */ | | 351 | */ |
350 | if (!has_printer(dlts[i])) | | 352 | if (!has_printer(dlts[i])) |
351 | (void) fprintf(stderr, " (printing not supported)"); | | 353 | (void) fprintf(stderr, " (printing not supported)"); |
352 | fprintf(stderr, "\n"); | | 354 | fprintf(stderr, "\n"); |
353 | } else { | | 355 | } else { |
354 | (void) fprintf(stderr, " DLT %d (printing not supported)\n", | | 356 | (void) fprintf(stderr, " DLT %d (printing not supported)\n", |
355 | dlts[i]); | | 357 | dlts[i]); |
356 | } | | 358 | } |
357 | } | | 359 | } |
358 | #ifdef HAVE_PCAP_FREE_DATALINKS | | 360 | #ifdef HAVE_PCAP_FREE_DATALINKS |
359 | pcap_free_datalinks(dlts); | | 361 | pcap_free_datalinks(dlts); |
360 | #endif | | 362 | #endif |
361 | exit(0); | | 363 | exit(0); |
362 | } | | 364 | } |
363 | | | 365 | |
364 | #ifdef HAVE_PCAP_FINDALLDEVS | | 366 | #ifdef HAVE_PCAP_FINDALLDEVS |
365 | static void | | 367 | static void |
366 | show_devices_and_exit (void) | | 368 | show_devices_and_exit (void) |
367 | { | | 369 | { |
368 | pcap_if_t *dev, *devlist; | | 370 | pcap_if_t *dev, *devlist; |
369 | char ebuf[PCAP_ERRBUF_SIZE]; | | 371 | char ebuf[PCAP_ERRBUF_SIZE]; |
370 | int i; | | 372 | int i; |
371 | | | 373 | |
372 | if (pcap_findalldevs(&devlist, ebuf) < 0) | | 374 | if (pcap_findalldevs(&devlist, ebuf) < 0) |
373 | error("%s", ebuf); | | 375 | error("%s", ebuf); |
374 | for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) { | | 376 | for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) { |
375 | printf("%d.%s", i+1, dev->name); | | 377 | printf("%d.%s", i+1, dev->name); |
376 | if (dev->description != NULL) | | 378 | if (dev->description != NULL) |
377 | printf(" (%s)", dev->description); | | 379 | printf(" (%s)", dev->description); |
378 | if (dev->flags != 0) | | 380 | if (dev->flags != 0) |
379 | printf(" [%s]", bittok2str(status_flags, "none", dev->flags)); | | 381 | printf(" [%s]", bittok2str(status_flags, "none", dev->flags)); |
380 | printf("\n"); | | 382 | printf("\n"); |
381 | } | | 383 | } |
382 | pcap_freealldevs(devlist); | | 384 | pcap_freealldevs(devlist); |
383 | exit(0); | | 385 | exit(0); |
384 | } | | 386 | } |
385 | #endif /* HAVE_PCAP_FINDALLDEVS */ | | 387 | #endif /* HAVE_PCAP_FINDALLDEVS */ |
386 | | | 388 | |
387 | /* | | 389 | /* |
388 | * Short options. | | 390 | * Short options. |
389 | * | | 391 | * |
390 | * Note that there we use all letters for short options except for g, k, | | 392 | * Note that there we use all letters for short options except for g, k, |
391 | * o, and P, and those are used by other versions of tcpdump, and we should | | 393 | * o, and P, and those are used by other versions of tcpdump, and we should |
392 | * only use them for the same purposes that the other versions of tcpdump | | 394 | * only use them for the same purposes that the other versions of tcpdump |
393 | * use them: | | 395 | * use them: |
394 | * | | 396 | * |
395 | * OS X tcpdump uses -g to force non--v output for IP to be on one | | 397 | * OS X tcpdump uses -g to force non--v output for IP to be on one |
396 | * line, making it more "g"repable; | | 398 | * line, making it more "g"repable; |
397 | * | | 399 | * |
398 | * OS X tcpdump uses -k tospecify that packet comments in pcap-ng files | | 400 | * OS X tcpdump uses -k tospecify that packet comments in pcap-ng files |
399 | * should be printed; | | 401 | * should be printed; |
400 | * | | 402 | * |
401 | * OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done | | 403 | * OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done |
402 | * for hosts sending TCP SYN packets; | | 404 | * for hosts sending TCP SYN packets; |
403 | * | | 405 | * |
404 | * OS X tcpdump uses -P to indicate that -w should write pcap-ng rather | | 406 | * OS X tcpdump uses -P to indicate that -w should write pcap-ng rather |
405 | * than pcap files. | | 407 | * than pcap files. |
406 | * | | 408 | * |
407 | * OS X tcpdump also uses -Q to specify expressions that match packet | | 409 | * OS X tcpdump also uses -Q to specify expressions that match packet |
408 | * metadata, including but not limited to the packet direction. | | 410 | * metadata, including but not limited to the packet direction. |
409 | * The expression syntax is different from a simple "in|out|inout", | | 411 | * The expression syntax is different from a simple "in|out|inout", |
410 | * and those expressions aren't accepted by OS X tcpdump, but the | | 412 | * and those expressions aren't accepted by OS X tcpdump, but the |
411 | * equivalents would be "in" = "dir=in", "out" = "dir=out", and | | 413 | * equivalents would be "in" = "dir=in", "out" = "dir=out", and |
412 | * "inout" = "dir=in or dir=out", and the parser could conceivably | | 414 | * "inout" = "dir=in or dir=out", and the parser could conceivably |
413 | * special-case "in", "out", and "inout" as expressions for backwards | | 415 | * special-case "in", "out", and "inout" as expressions for backwards |
414 | * compatibility, so all is not (yet) lost. | | 416 | * compatibility, so all is not (yet) lost. |
415 | */ | | 417 | */ |
416 | | | 418 | |
417 | /* | | 419 | /* |
418 | * Set up flags that might or might not be supported depending on the | | 420 | * Set up flags that might or might not be supported depending on the |
419 | * version of libpcap we're using. | | 421 | * version of libpcap we're using. |
420 | */ | | 422 | */ |
421 | #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) | | 423 | #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) |
422 | #define B_FLAG "B:" | | 424 | #define B_FLAG "B:" |
423 | #define B_FLAG_USAGE " [ -B size ]" | | 425 | #define B_FLAG_USAGE " [ -B size ]" |
424 | #else /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ | | 426 | #else /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ |
425 | #define B_FLAG | | 427 | #define B_FLAG |
426 | #define B_FLAG_USAGE | | 428 | #define B_FLAG_USAGE |
427 | #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ | | 429 | #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ |
428 | | | 430 | |
429 | #ifdef HAVE_PCAP_CREATE | | 431 | #ifdef HAVE_PCAP_CREATE |
430 | #define I_FLAG "I" | | 432 | #define I_FLAG "I" |
431 | #else /* HAVE_PCAP_CREATE */ | | 433 | #else /* HAVE_PCAP_CREATE */ |
432 | #define I_FLAG | | 434 | #define I_FLAG |
433 | #endif /* HAVE_PCAP_CREATE */ | | 435 | #endif /* HAVE_PCAP_CREATE */ |
434 | | | 436 | |
435 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE | | 437 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE |
436 | #define j_FLAG "j:" | | 438 | #define j_FLAG "j:" |
437 | #define j_FLAG_USAGE " [ -j tstamptype ]" | | 439 | #define j_FLAG_USAGE " [ -j tstamptype ]" |
438 | #define J_FLAG "J" | | 440 | #define J_FLAG "J" |
439 | #else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ | | 441 | #else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ |
440 | #define j_FLAG | | 442 | #define j_FLAG |
441 | #define j_FLAG_USAGE | | 443 | #define j_FLAG_USAGE |
442 | #define J_FLAG | | 444 | #define J_FLAG |
443 | #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ | | 445 | #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ |
444 | | | 446 | |
445 | #ifdef HAVE_PCAP_FINDALLDEVS | | 447 | #ifdef HAVE_PCAP_FINDALLDEVS |
446 | #define D_FLAG "D" | | 448 | #define D_FLAG "D" |
447 | #else | | 449 | #else |
448 | #define D_FLAG | | 450 | #define D_FLAG |
449 | #endif | | 451 | #endif |
450 | | | 452 | |
451 | #ifdef HAVE_PCAP_DUMP_FLUSH | | 453 | #ifdef HAVE_PCAP_DUMP_FLUSH |
452 | #define U_FLAG "U" | | 454 | #define U_FLAG "U" |
453 | #else | | 455 | #else |
454 | #define U_FLAG | | 456 | #define U_FLAG |
455 | #endif | | 457 | #endif |
456 | | | 458 | |
457 | #ifdef HAVE_PCAP_SETDIRECTION | | 459 | #ifdef HAVE_PCAP_SETDIRECTION |
458 | #define Q_FLAG "Q:" | | 460 | #define Q_FLAG "Q:" |
459 | #else | | 461 | #else |
460 | #define Q_FLAG | | 462 | #define Q_FLAG |
461 | #endif | | 463 | #endif |
462 | | | 464 | |
463 | #define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#" | | 465 | #define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#" |
464 | | | 466 | |
465 | /* | | 467 | /* |
466 | * Long options. | | 468 | * Long options. |
467 | * | | 469 | * |
468 | * We do not currently have long options corresponding to all short | | 470 | * We do not currently have long options corresponding to all short |
469 | * options; we should probably pick appropriate option names for them. | | 471 | * options; we should probably pick appropriate option names for them. |
470 | * | | 472 | * |
471 | * However, the short options where the number of times the option is | | 473 | * However, the short options where the number of times the option is |
472 | * specified matters, such as -v and -d and -t, should probably not | | 474 | * specified matters, such as -v and -d and -t, should probably not |
473 | * just map to a long option, as saying | | 475 | * just map to a long option, as saying |
474 | * | | 476 | * |
475 | * tcpdump --verbose --verbose | | 477 | * tcpdump --verbose --verbose |
476 | * | | 478 | * |
477 | * doesn't make sense; it should be --verbosity={N} or something such | | 479 | * doesn't make sense; it should be --verbosity={N} or something such |
478 | * as that. | | 480 | * as that. |
479 | * | | 481 | * |
480 | * For long options with no corresponding short options, we define values | | 482 | * For long options with no corresponding short options, we define values |
481 | * outside the range of ASCII graphic characters, make that the last | | 483 | * outside the range of ASCII graphic characters, make that the last |
482 | * component of the entry for the long option, and have a case for that | | 484 | * component of the entry for the long option, and have a case for that |
483 | * option in the switch statement. | | 485 | * option in the switch statement. |
484 | */ | | 486 | */ |
485 | #define OPTION_VERSION 128 | | 487 | #define OPTION_VERSION 128 |
486 | #define OPTION_TSTAMP_PRECISION 129 | | 488 | #define OPTION_TSTAMP_PRECISION 129 |
487 | #define OPTION_IMMEDIATE_MODE 130 | | 489 | #define OPTION_IMMEDIATE_MODE 130 |
488 | | | 490 | |
489 | static const struct option longopts[] = { | | 491 | static const struct option longopts[] = { |
490 | #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) | | 492 | #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) |
491 | { "buffer-size", required_argument, NULL, 'B' }, | | 493 | { "buffer-size", required_argument, NULL, 'B' }, |
492 | #endif | | 494 | #endif |
493 | { "list-interfaces", no_argument, NULL, 'D' }, | | 495 | { "list-interfaces", no_argument, NULL, 'D' }, |
494 | { "help", no_argument, NULL, 'h' }, | | 496 | { "help", no_argument, NULL, 'h' }, |
495 | { "interface", required_argument, NULL, 'i' }, | | 497 | { "interface", required_argument, NULL, 'i' }, |
496 | #ifdef HAVE_PCAP_CREATE | | 498 | #ifdef HAVE_PCAP_CREATE |
497 | { "monitor-mode", no_argument, NULL, 'I' }, | | 499 | { "monitor-mode", no_argument, NULL, 'I' }, |
498 | #endif | | 500 | #endif |
499 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE | | 501 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE |
500 | { "time-stamp-type", required_argument, NULL, 'j' }, | | 502 | { "time-stamp-type", required_argument, NULL, 'j' }, |
501 | { "list-time-stamp-types", no_argument, NULL, 'J' }, | | 503 | { "list-time-stamp-types", no_argument, NULL, 'J' }, |
502 | #endif | | 504 | #endif |
503 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION | | 505 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION |
504 | { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, | | 506 | { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, |
505 | #endif | | 507 | #endif |
506 | { "dont-verify-checksums", no_argument, NULL, 'K' }, | | 508 | { "dont-verify-checksums", no_argument, NULL, 'K' }, |
507 | { "list-data-link-types", no_argument, NULL, 'L' }, | | 509 | { "list-data-link-types", no_argument, NULL, 'L' }, |
508 | { "no-optimize", no_argument, NULL, 'O' }, | | 510 | { "no-optimize", no_argument, NULL, 'O' }, |
509 | { "no-promiscuous-mode", no_argument, NULL, 'p' }, | | 511 | { "no-promiscuous-mode", no_argument, NULL, 'p' }, |
510 | #ifdef HAVE_PCAP_SETDIRECTION | | 512 | #ifdef HAVE_PCAP_SETDIRECTION |
511 | { "direction", required_argument, NULL, 'Q' }, | | 513 | { "direction", required_argument, NULL, 'Q' }, |
512 | #endif | | 514 | #endif |
513 | { "snapshot-length", required_argument, NULL, 's' }, | | 515 | { "snapshot-length", required_argument, NULL, 's' }, |
514 | { "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' }, | | 516 | { "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' }, |
515 | #ifdef HAVE_PCAP_DUMP_FLUSH | | 517 | #ifdef HAVE_PCAP_DUMP_FLUSH |
516 | { "packet-buffered", no_argument, NULL, 'U' }, | | 518 | { "packet-buffered", no_argument, NULL, 'U' }, |
517 | #endif | | 519 | #endif |
518 | { "linktype", required_argument, NULL, 'y' }, | | 520 | { "linktype", required_argument, NULL, 'y' }, |
519 | #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE | | 521 | #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE |
520 | { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE }, | | 522 | { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE }, |
521 | #endif | | 523 | #endif |
522 | #ifdef HAVE_PCAP_SET_PARSER_DEBUG | | 524 | #ifdef HAVE_PCAP_SET_PARSER_DEBUG |
523 | { "debug-filter-parser", no_argument, NULL, 'Y' }, | | 525 | { "debug-filter-parser", no_argument, NULL, 'Y' }, |
524 | #endif | | 526 | #endif |
525 | { "relinquish-privileges", required_argument, NULL, 'Z' }, | | 527 | { "relinquish-privileges", required_argument, NULL, 'Z' }, |
526 | { "number", no_argument, NULL, '#' }, | | 528 | { "number", no_argument, NULL, '#' }, |
527 | { "version", no_argument, NULL, OPTION_VERSION }, | | 529 | { "version", no_argument, NULL, OPTION_VERSION }, |
528 | { NULL, 0, NULL, 0 } | | 530 | { NULL, 0, NULL, 0 } |
529 | }; | | 531 | }; |
530 | | | 532 | |
531 | #ifndef _WIN32 | | 533 | #ifndef _WIN32 |
532 | /* Drop root privileges and chroot if necessary */ | | 534 | /* Drop root privileges and chroot if necessary */ |
533 | static void | | 535 | static void |
534 | droproot(const char *username, const char *chroot_dir) | | 536 | droproot(const char *username, const char *chroot_dir) |
535 | { | | 537 | { |
536 | struct passwd *pw = NULL; | | 538 | struct passwd *pw = NULL; |
537 | | | 539 | |
538 | if (chroot_dir && !username) { | | 540 | if (chroot_dir && !username) { |
539 | fprintf(stderr, "%s: Chroot without dropping root is insecure\n", | | 541 | fprintf(stderr, "%s: Chroot without dropping root is insecure\n", |
540 | program_name); | | 542 | program_name); |
541 | exit(1); | | 543 | exit(1); |
542 | } | | 544 | } |
543 | | | 545 | |
544 | pw = getpwnam(username); | | 546 | pw = getpwnam(username); |
545 | if (pw) { | | 547 | if (pw) { |
546 | if (initgroups(pw->pw_name, pw->pw_gid) != 0) { | | 548 | if (initgroups(pw->pw_name, pw->pw_gid) != 0) { |
547 | fprintf(stderr, "tcpdump: Couldn't initgroups to " | | 549 | fprintf(stderr, "tcpdump: Couldn't initgroups to " |
548 | "'%.32s' gid=%lu: %s\n", pw->pw_name, | | 550 | "'%.32s' gid=%lu: %s\n", pw->pw_name, |
549 | (unsigned long)pw->pw_gid, | | 551 | (unsigned long)pw->pw_gid, |
550 | pcap_strerror(errno)); | | 552 | pcap_strerror(errno)); |
551 | exit(1); | | 553 | exit(1); |
552 | } | | 554 | } |
553 | if (chroot_dir) { | | 555 | if (chroot_dir) { |
554 | setprotoent(1); | | 556 | setprotoent(1); |
555 | res_init(); | | 557 | res_init(); |
556 | if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { | | 558 | if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { |
557 | fprintf(stderr, "%s: Couldn't chroot/chdir to '%.64s': %s\n", | | 559 | fprintf(stderr, "%s: Couldn't chroot/chdir to '%.64s': %s\n", |
558 | program_name, chroot_dir, pcap_strerror(errno)); | | 560 | program_name, chroot_dir, pcap_strerror(errno)); |
559 | exit(1); | | 561 | exit(1); |
560 | } | | 562 | } |
561 | } | | 563 | } |
562 | #ifdef HAVE_LIBCAP_NG | | 564 | #ifdef HAVE_LIBCAP_NG |
563 | { | | 565 | { |
564 | int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); | | 566 | int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); |
565 | if (ret < 0) { | | 567 | if (ret < 0) { |
566 | fprintf(stderr, "error : ret %d\n", ret); | | 568 | fprintf(stderr, "error : ret %d\n", ret); |
567 | } else { | | 569 | } else { |
568 | fprintf(stderr, "dropped privs to %s\n", username); | | 570 | fprintf(stderr, "dropped privs to %s\n", username); |
569 | } | | 571 | } |
570 | } | | 572 | } |
571 | #else | | 573 | #else |
572 | if (initgroups(pw->pw_name, pw->pw_gid) != 0 || | | 574 | if (initgroups(pw->pw_name, pw->pw_gid) != 0 || |
573 | setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { | | 575 | setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { |
574 | fprintf(stderr, "%s: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", | | 576 | fprintf(stderr, "%s: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", |
575 | program_name, username, | | 577 | program_name, username, |
576 | (unsigned long)pw->pw_uid, | | 578 | (unsigned long)pw->pw_uid, |
577 | (unsigned long)pw->pw_gid, | | 579 | (unsigned long)pw->pw_gid, |
578 | pcap_strerror(errno)); | | 580 | pcap_strerror(errno)); |
579 | exit(1); | | 581 | exit(1); |
580 | } | | 582 | } |
581 | else { | | 583 | else { |
582 | // fprintf(stderr, "dropped privs to %s\n", username); | | 584 | // fprintf(stderr, "dropped privs to %s\n", username); |
583 | } | | 585 | } |
584 | #endif /* HAVE_LIBCAP_NG */ | | 586 | #endif /* HAVE_LIBCAP_NG */ |
585 | } | | 587 | } |
586 | else { | | 588 | else { |
587 | fprintf(stderr, "%s: Couldn't find user '%.32s'\n", | | 589 | fprintf(stderr, "%s: Couldn't find user '%.32s'\n", |
588 | program_name, username); | | 590 | program_name, username); |
589 | exit(1); | | 591 | exit(1); |
590 | } | | 592 | } |
591 | #ifdef HAVE_LIBCAP_NG | | 593 | #ifdef HAVE_LIBCAP_NG |
592 | /* We don't need CAP_SETUID and CAP_SETGID any more. */ | | 594 | /* We don't need CAP_SETUID and CAP_SETGID any more. */ |
593 | capng_updatev( | | 595 | capng_updatev( |
594 | CAPNG_DROP, | | 596 | CAPNG_DROP, |
595 | CAPNG_EFFECTIVE | CAPNG_PERMITTED, | | 597 | CAPNG_EFFECTIVE | CAPNG_PERMITTED, |
596 | CAP_SETUID, | | 598 | CAP_SETUID, |
597 | CAP_SETGID, | | 599 | CAP_SETGID, |
598 | -1); | | 600 | -1); |
599 | capng_apply(CAPNG_SELECT_BOTH); | | 601 | capng_apply(CAPNG_SELECT_BOTH); |
600 | #endif /* HAVE_LIBCAP_NG */ | | 602 | #endif /* HAVE_LIBCAP_NG */ |
601 | | | 603 | |
602 | } | | 604 | } |
603 | #endif /* _WIN32 */ | | 605 | #endif /* _WIN32 */ |
604 | | | 606 | |
605 | static int | | 607 | static int |
606 | getWflagChars(int x) | | 608 | getWflagChars(int x) |
607 | { | | 609 | { |
608 | int c = 0; | | 610 | int c = 0; |
609 | | | 611 | |
610 | x -= 1; | | 612 | x -= 1; |
611 | while (x > 0) { | | 613 | while (x > 0) { |
612 | c += 1; | | 614 | c += 1; |
613 | x /= 10; | | 615 | x /= 10; |
614 | } | | 616 | } |
615 | | | 617 | |
616 | return c; | | 618 | return c; |
617 | } | | 619 | } |
618 | | | 620 | |
619 | | | 621 | |
620 | static void | | 622 | static void |
621 | MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) | | 623 | MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) |
622 | { | | 624 | { |
623 | char *filename = malloc(PATH_MAX + 1); | | 625 | char *filename = malloc(PATH_MAX + 1); |
624 | if (filename == NULL) | | 626 | if (filename == NULL) |
625 | error("Makefilename: malloc"); | | 627 | error("Makefilename: malloc"); |
626 | | | 628 | |
627 | /* Process with strftime if Gflag is set. */ | | 629 | /* Process with strftime if Gflag is set. */ |
628 | if (Gflag != 0) { | | 630 | if (Gflag != 0) { |
629 | struct tm *local_tm; | | 631 | struct tm *local_tm; |
630 | | | 632 | |
631 | /* Convert Gflag_time to a usable format */ | | 633 | /* Convert Gflag_time to a usable format */ |
632 | if ((local_tm = localtime(&Gflag_time)) == NULL) { | | 634 | if ((local_tm = localtime(&Gflag_time)) == NULL) { |
633 | error("MakeTimedFilename: localtime"); | | 635 | error("MakeTimedFilename: localtime"); |
634 | } | | 636 | } |
635 | | | 637 | |
636 | /* There's no good way to detect an error in strftime since a return | | 638 | /* There's no good way to detect an error in strftime since a return |
637 | * value of 0 isn't necessarily failure. | | 639 | * value of 0 isn't necessarily failure. |
638 | */ | | 640 | */ |
639 | strftime(filename, PATH_MAX, orig_name, local_tm); | | 641 | strftime(filename, PATH_MAX, orig_name, local_tm); |
640 | } else { | | 642 | } else { |
641 | strncpy(filename, orig_name, PATH_MAX); | | 643 | strncpy(filename, orig_name, PATH_MAX); |
642 | } | | 644 | } |
643 | | | 645 | |
644 | if (cnt == 0 && max_chars == 0) | | 646 | if (cnt == 0 && max_chars == 0) |
645 | strncpy(buffer, filename, PATH_MAX + 1); | | 647 | strncpy(buffer, filename, PATH_MAX + 1); |
646 | else | | 648 | else |
647 | if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) | | 649 | if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) |
648 | /* Report an error if the filename is too large */ | | 650 | /* Report an error if the filename is too large */ |
649 | error("too many output files or filename is too long (> %d)", PATH_MAX); | | 651 | error("too many output files or filename is too long (> %d)", PATH_MAX); |
650 | free(filename); | | 652 | free(filename); |
651 | } | | 653 | } |
652 | | | 654 | |
653 | static char * | | 655 | static char * |
654 | get_next_file(FILE *VFile, char *ptr) | | 656 | get_next_file(FILE *VFile, char *ptr) |
655 | { | | 657 | { |
656 | char *ret; | | 658 | char *ret; |
657 | | | 659 | |
658 | ret = fgets(ptr, PATH_MAX, VFile); | | 660 | ret = fgets(ptr, PATH_MAX, VFile); |
659 | if (!ret) | | 661 | if (!ret) |
660 | return NULL; | | 662 | return NULL; |
661 | | | 663 | |
662 | if (ptr[strlen(ptr) - 1] == '\n') | | 664 | if (ptr[strlen(ptr) - 1] == '\n') |
663 | ptr[strlen(ptr) - 1] = '\0'; | | 665 | ptr[strlen(ptr) - 1] = '\0'; |
664 | | | 666 | |
665 | return ret; | | 667 | return ret; |
666 | } | | 668 | } |
667 | | | 669 | |
668 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION | | 670 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION |
669 | static int | | 671 | static int |
670 | tstamp_precision_from_string(const char *precision) | | 672 | tstamp_precision_from_string(const char *precision) |
671 | { | | 673 | { |
672 | if (strncmp(precision, "nano", strlen("nano")) == 0) | | 674 | if (strncmp(precision, "nano", strlen("nano")) == 0) |
673 | return PCAP_TSTAMP_PRECISION_NANO; | | 675 | return PCAP_TSTAMP_PRECISION_NANO; |
674 | | | 676 | |
675 | if (strncmp(precision, "micro", strlen("micro")) == 0) | | 677 | if (strncmp(precision, "micro", strlen("micro")) == 0) |
676 | return PCAP_TSTAMP_PRECISION_MICRO; | | 678 | return PCAP_TSTAMP_PRECISION_MICRO; |
677 | | | 679 | |
678 | return -EINVAL; | | 680 | return -EINVAL; |
679 | } | | 681 | } |
680 | | | 682 | |
681 | static const char * | | 683 | static const char * |
682 | tstamp_precision_to_string(int precision) | | 684 | tstamp_precision_to_string(int precision) |
683 | { | | 685 | { |
684 | switch (precision) { | | 686 | switch (precision) { |
685 | | | 687 | |
686 | case PCAP_TSTAMP_PRECISION_MICRO: | | 688 | case PCAP_TSTAMP_PRECISION_MICRO: |
687 | return "micro"; | | 689 | return "micro"; |
688 | | | 690 | |
689 | case PCAP_TSTAMP_PRECISION_NANO: | | 691 | case PCAP_TSTAMP_PRECISION_NANO: |
690 | return "nano"; | | 692 | return "nano"; |
691 | | | 693 | |
692 | default: | | 694 | default: |
693 | return "unknown"; | | 695 | return "unknown"; |
694 | } | | 696 | } |
695 | } | | 697 | } |
696 | #endif | | 698 | #endif |
697 | | | 699 | |
698 | #ifdef HAVE_CAPSICUM | | 700 | #ifdef HAVE_CAPSICUM |
699 | /* | | 701 | /* |
700 | * Ensure that, on a dump file's descriptor, we have all the rights | | 702 | * Ensure that, on a dump file's descriptor, we have all the rights |
701 | * necessary to make the standard I/O library work with an fdopen()ed | | 703 | * necessary to make the standard I/O library work with an fdopen()ed |
702 | * FILE * from that descriptor. | | 704 | * FILE * from that descriptor. |
703 | * | | 705 | * |
704 | * A long time ago, in a galaxy far far away, AT&T decided that, instead | | 706 | * A long time ago, in a galaxy far far away, AT&T decided that, instead |
705 | * of providing separate APIs for getting and setting the FD_ flags on a | | 707 | * of providing separate APIs for getting and setting the FD_ flags on a |
706 | * descriptor, getting and setting the O_ flags on a descriptor, and | | 708 | * descriptor, getting and setting the O_ flags on a descriptor, and |
707 | * locking files, they'd throw them all into a kitchen-sink fcntl() call | | 709 | * locking files, they'd throw them all into a kitchen-sink fcntl() call |
708 | * along the lines of ioctl(), the fact that ioctl() operations are | | 710 | * along the lines of ioctl(), the fact that ioctl() operations are |
709 | * largely specific to particular character devices but fcntl() operations | | 711 | * largely specific to particular character devices but fcntl() operations |
710 | * are either generic to all descriptors or generic to all descriptors for | | 712 | * are either generic to all descriptors or generic to all descriptors for |
711 | * regular files nonwithstanding. | | 713 | * regular files nonwithstanding. |
712 | * | | 714 | * |
713 | * The Capsicum people decided that fine-grained control of descriptor | | 715 | * The Capsicum people decided that fine-grained control of descriptor |
714 | * operations was required, so that you need to grant permission for | | 716 | * operations was required, so that you need to grant permission for |
715 | * reading, writing, seeking, and fcntl-ing. The latter, courtesy of | | 717 | * reading, writing, seeking, and fcntl-ing. The latter, courtesy of |
716 | * AT&T's decision, means that "fcntl-ing" isn't a thing, but a motley | | 718 | * AT&T's decision, means that "fcntl-ing" isn't a thing, but a motley |
717 | * collection of things, so there are *individual* fcntls for which | | 719 | * collection of things, so there are *individual* fcntls for which |
718 | * permission needs to be granted. | | 720 | * permission needs to be granted. |
719 | * | | 721 | * |
720 | * The FreeBSD standard I/O people implemented some optimizations that | | 722 | * The FreeBSD standard I/O people implemented some optimizations that |
721 | * requires that the standard I/O routines be able to determine whether | | 723 | * requires that the standard I/O routines be able to determine whether |
722 | * the descriptor for the FILE * is open append-only or not; as that | | 724 | * the descriptor for the FILE * is open append-only or not; as that |
723 | * descriptor could have come from an open() rather than an fopen(), | | 725 | * descriptor could have come from an open() rather than an fopen(), |
724 | * that requires that it be able to do an F_GETFL fcntl() to read | | 726 | * that requires that it be able to do an F_GETFL fcntl() to read |
725 | * the O_ flags. | | 727 | * the O_ flags. |
726 | * | | 728 | * |
727 | * Tcpdump uses ftell() to determine how much data has been written | | 729 | * Tcpdump uses ftell() to determine how much data has been written |
728 | * to a file in order to, when used with -C, determine when it's time | | 730 | * to a file in order to, when used with -C, determine when it's time |
729 | * to rotate capture files. ftell() therefore needs to do an lseek() | | 731 | * to rotate capture files. ftell() therefore needs to do an lseek() |
730 | * to find out the file offset and must, thanks to the aforementioned | | 732 | * to find out the file offset and must, thanks to the aforementioned |
731 | * optimization, also know whether the descriptor is open append-only | | 733 | * optimization, also know whether the descriptor is open append-only |
732 | * or not. | | 734 | * or not. |
733 | * | | 735 | * |
734 | * The net result of all the above is that we need to grant CAP_SEEK, | | 736 | * The net result of all the above is that we need to grant CAP_SEEK, |
735 | * CAP_WRITE, and CAP_FCNTL with the CAP_FCNTL_GETFL subcapability. | | 737 | * CAP_WRITE, and CAP_FCNTL with the CAP_FCNTL_GETFL subcapability. |
736 | * | | 738 | * |
737 | * Perhaps this is the universe's way of saying that either | | 739 | * Perhaps this is the universe's way of saying that either |
738 | * | | 740 | * |
739 | * 1) there needs to be an fopenat() call and a pcap_dump_openat() call | | 741 | * 1) there needs to be an fopenat() call and a pcap_dump_openat() call |
740 | * using it, so that Capsicum-capable tcpdump wouldn't need to do | | 742 | * using it, so that Capsicum-capable tcpdump wouldn't need to do |
741 | * an fdopen() | | 743 | * an fdopen() |
742 | * | | 744 | * |
743 | * or | | 745 | * or |
744 | * | | 746 | * |
745 | * 2) there needs to be a cap_fdopen() call in the FreeBSD standard | | 747 | * 2) there needs to be a cap_fdopen() call in the FreeBSD standard |
746 | * I/O library that knows what rights are needed by the standard | | 748 | * I/O library that knows what rights are needed by the standard |
747 | * I/O library, based on the open mode, and assigns them, perhaps | | 749 | * I/O library, based on the open mode, and assigns them, perhaps |
748 | * with an additional argument indicating, for example, whether | | 750 | * with an additional argument indicating, for example, whether |
749 | * seeking should be allowed, so that tcpdump doesn't need to know | | 751 | * seeking should be allowed, so that tcpdump doesn't need to know |
750 | * what the standard I/O library happens to require this week. | | 752 | * what the standard I/O library happens to require this week. |
751 | */ | | 753 | */ |
752 | static void | | 754 | static void |
753 | set_dumper_capsicum_rights(pcap_dumper_t *p) | | 755 | set_dumper_capsicum_rights(pcap_dumper_t *p) |
754 | { | | 756 | { |
755 | int fd = fileno(pcap_dump_file(p)); | | 757 | int fd = fileno(pcap_dump_file(p)); |
756 | cap_rights_t rights; | | 758 | cap_rights_t rights; |
757 | | | 759 | |
758 | cap_rights_init(&rights, CAP_SEEK, CAP_WRITE, CAP_FCNTL); | | 760 | cap_rights_init(&rights, CAP_SEEK, CAP_WRITE, CAP_FCNTL); |
759 | if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) { | | 761 | if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) { |
760 | error("unable to limit dump descriptor"); | | 762 | error("unable to limit dump descriptor"); |
761 | } | | 763 | } |
762 | if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) { | | 764 | if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) { |
763 | error("unable to limit dump descriptor fcntls"); | | 765 | error("unable to limit dump descriptor fcntls"); |
764 | } | | 766 | } |
765 | } | | 767 | } |
766 | #endif | | 768 | #endif |
767 | | | 769 | |
768 | int | | 770 | int |
769 | main(int argc, char **argv) | | 771 | main(int argc, char **argv) |
770 | { | | 772 | { |
771 | register int cnt, op, i; | | 773 | register int cnt, op, i; |
772 | bpf_u_int32 localnet =0 , netmask = 0; | | 774 | bpf_u_int32 localnet =0 , netmask = 0; |
773 | int timezone_offset = 0; | | 775 | int timezone_offset = 0; |
774 | register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; | | 776 | register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; |
775 | pcap_handler callback; | | 777 | pcap_handler callback; |
776 | int dlt; | | 778 | int dlt; |
777 | const char *dlt_name; | | 779 | const char *dlt_name; |
778 | struct bpf_program fcode; | | 780 | struct bpf_program fcode; |
779 | #ifndef _WIN32 | | 781 | #ifndef _WIN32 |
780 | RETSIGTYPE (*oldhandler)(int); | | 782 | RETSIGTYPE (*oldhandler)(int); |
781 | #endif | | 783 | #endif |
782 | struct dump_info dumpinfo; | | 784 | struct dump_info dumpinfo; |
783 | u_char *pcap_userdata; | | 785 | u_char *pcap_userdata; |
784 | char ebuf[PCAP_ERRBUF_SIZE]; | | 786 | char ebuf[PCAP_ERRBUF_SIZE]; |
785 | char VFileLine[PATH_MAX + 1]; | | 787 | char VFileLine[PATH_MAX + 1]; |
786 | char *username = NULL; | | 788 | char *username = NULL; |
787 | char *chroot_dir = NULL; | | 789 | char *chroot_dir = NULL; |
788 | char *ret = NULL; | | 790 | char *ret = NULL; |
789 | char *end; | | 791 | char *end; |
790 | #ifdef HAVE_PCAP_FINDALLDEVS | | 792 | #ifdef HAVE_PCAP_FINDALLDEVS |
791 | pcap_if_t *dev, *devlist; | | 793 | pcap_if_t *dev, *devlist; |
792 | int devnum; | | 794 | int devnum; |
793 | #endif | | 795 | #endif |
794 | int status; | | 796 | int status; |
795 | FILE *VFile; | | 797 | FILE *VFile; |
796 | #ifdef HAVE_CAPSICUM | | 798 | #ifdef HAVE_CAPSICUM |
797 | cap_rights_t rights; | | 799 | cap_rights_t rights; |
798 | int cansandbox; | | 800 | int cansandbox; |
799 | #endif /* HAVE_CAPSICUM */ | | 801 | #endif /* HAVE_CAPSICUM */ |
800 | int Bflag = 0; /* buffer size */ | | 802 | int Bflag = 0; /* buffer size */ |
801 | int jflag = -1; /* packet time stamp source */ | | 803 | int jflag = -1; /* packet time stamp source */ |
802 | int Oflag = 1; /* run filter code optimizer */ | | 804 | int Oflag = 1; /* run filter code optimizer */ |
803 | int pflag = 0; /* don't go promiscuous */ | | 805 | int pflag = 0; /* don't go promiscuous */ |
804 | int yflag_dlt = -1; | | 806 | int yflag_dlt = -1; |
805 | const char *yflag_dlt_name = NULL; | | 807 | const char *yflag_dlt_name = NULL; |
806 | | | 808 | |
807 | netdissect_options Ndo; | | 809 | netdissect_options Ndo; |
808 | netdissect_options *ndo = &Ndo; | | 810 | netdissect_options *ndo = &Ndo; |
809 | int immediate_mode = 0; | | 811 | int immediate_mode = 0; |
810 | | | 812 | |
811 | memset(ndo, 0, sizeof(*ndo)); | | 813 | memset(ndo, 0, sizeof(*ndo)); |
812 | ndo_set_function_pointers(ndo); | | 814 | ndo_set_function_pointers(ndo); |
813 | ndo->ndo_snaplen = DEFAULT_SNAPLEN; | | 815 | ndo->ndo_snaplen = DEFAULT_SNAPLEN; |
814 | | | 816 | |
815 | cnt = -1; | | 817 | cnt = -1; |
816 | device = NULL; | | 818 | device = NULL; |
817 | infile = NULL; | | 819 | infile = NULL; |
818 | RFileName = NULL; | | 820 | RFileName = NULL; |
819 | VFileName = NULL; | | 821 | VFileName = NULL; |
820 | VFile = NULL; | | 822 | VFile = NULL; |
821 | WFileName = NULL; | | 823 | WFileName = NULL; |
822 | dlt = -1; | | 824 | dlt = -1; |
823 | if ((cp = strrchr(argv[0], '/')) != NULL) | | 825 | if ((cp = strrchr(argv[0], '/')) != NULL) |
824 | ndo->program_name = program_name = cp + 1; | | 826 | ndo->program_name = program_name = cp + 1; |
825 | else | | 827 | else |
826 | ndo->program_name = program_name = argv[0]; | | 828 | ndo->program_name = program_name = argv[0]; |
827 | | | 829 | |
828 | #ifdef _WIN32 | | 830 | #ifdef _WIN32 |
829 | if (pcap_wsockinit() != 0) | | 831 | if (pcap_wsockinit() != 0) |
830 | error("Attempting to initialize Winsock failed"); | | 832 | error("Attempting to initialize Winsock failed"); |
831 | #endif /* _WIN32 */ | | 833 | #endif /* _WIN32 */ |
832 | | | 834 | |
833 | /* | | 835 | /* |
834 | * On platforms where the CPU doesn't support unaligned loads, | | 836 | * On platforms where the CPU doesn't support unaligned loads, |
835 | * force unaligned accesses to abort with SIGBUS, rather than | | 837 | * force unaligned accesses to abort with SIGBUS, rather than |
836 | * being fixed up (slowly) by the OS kernel; on those platforms, | | 838 | * being fixed up (slowly) by the OS kernel; on those platforms, |
837 | * misaligned accesses are bugs, and we want tcpdump to crash so | | 839 | * misaligned accesses are bugs, and we want tcpdump to crash so |
838 | * that the bugs are reported. | | 840 | * that the bugs are reported. |
839 | */ | | 841 | */ |
840 | if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) | | 842 | if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) |
841 | error("%s", ebuf); | | 843 | error("%s", ebuf); |
842 | | | 844 | |
843 | #ifdef USE_LIBSMI | | 845 | #ifdef USE_LIBSMI |
844 | smiInit("tcpdump"); | | 846 | smiInit("tcpdump"); |
845 | #endif | | 847 | #endif |
846 | | | 848 | |
847 | while ( | | 849 | while ( |
848 | (op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1) | | 850 | (op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1) |
849 | switch (op) { | | 851 | switch (op) { |
850 | | | 852 | |
851 | case 'a': | | 853 | case 'a': |
852 | /* compatibility for old -a */ | | 854 | /* compatibility for old -a */ |
853 | break; | | 855 | break; |
854 | | | 856 | |
855 | case 'A': | | 857 | case 'A': |
856 | ++ndo->ndo_Aflag; | | 858 | ++ndo->ndo_Aflag; |
857 | break; | | 859 | break; |
858 | | | 860 | |
859 | case 'b': | | 861 | case 'b': |
860 | ++ndo->ndo_bflag; | | 862 | ++ndo->ndo_bflag; |
861 | break; | | 863 | break; |
862 | | | 864 | |
863 | #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) | | 865 | #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) |
864 | case 'B': | | 866 | case 'B': |
865 | Bflag = atoi(optarg)*1024; | | 867 | Bflag = atoi(optarg)*1024; |
866 | if (Bflag <= 0) | | 868 | if (Bflag <= 0) |
867 | error("invalid packet buffer size %s", optarg); | | 869 | error("invalid packet buffer size %s", optarg); |
868 | break; | | 870 | break; |
869 | #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ | | 871 | #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ |
870 | | | 872 | |
871 | case 'c': | | 873 | case 'c': |
872 | cnt = atoi(optarg); | | 874 | cnt = atoi(optarg); |
873 | if (cnt <= 0) | | 875 | if (cnt <= 0) |
874 | error("invalid packet count %s", optarg); | | 876 | error("invalid packet count %s", optarg); |
875 | break; | | 877 | break; |
876 | | | 878 | |
877 | case 'C': | | 879 | case 'C': |
878 | Cflag = atoi(optarg) * 1000000; | | 880 | Cflag = atoi(optarg) * 1000000; |
879 | if (Cflag <= 0) | | 881 | if (Cflag <= 0) |
880 | error("invalid file size %s", optarg); | | 882 | error("invalid file size %s", optarg); |
881 | break; | | 883 | break; |
882 | | | 884 | |
883 | case 'd': | | 885 | case 'd': |
884 | ++dflag; | | 886 | ++dflag; |
885 | break; | | 887 | break; |
886 | | | 888 | |
887 | case 'D': | | 889 | case 'D': |
888 | Dflag++; | | 890 | Dflag++; |
889 | break; | | 891 | break; |
890 | | | 892 | |
891 | case 'L': | | 893 | case 'L': |
892 | Lflag++; | | 894 | Lflag++; |
893 | break; | | 895 | break; |
894 | | | 896 | |
895 | case 'e': | | 897 | case 'e': |
896 | ++ndo->ndo_eflag; | | 898 | ++ndo->ndo_eflag; |
897 | break; | | 899 | break; |
898 | | | 900 | |
899 | case 'E': | | 901 | case 'E': |
900 | #ifndef HAVE_LIBCRYPTO | | 902 | #ifndef HAVE_LIBCRYPTO |
901 | warning("crypto code not compiled in"); | | 903 | warning("crypto code not compiled in"); |
902 | #endif | | 904 | #endif |
903 | ndo->ndo_espsecret = optarg; | | 905 | ndo->ndo_espsecret = optarg; |
904 | break; | | 906 | break; |
905 | | | 907 | |
906 | case 'f': | | 908 | case 'f': |
907 | ++ndo->ndo_fflag; | | 909 | ++ndo->ndo_fflag; |
908 | break; | | 910 | break; |
909 | | | 911 | |
910 | case 'F': | | 912 | case 'F': |
911 | infile = optarg; | | 913 | infile = optarg; |
912 | break; | | 914 | break; |
913 | | | 915 | |
914 | case 'G': | | 916 | case 'G': |
915 | Gflag = atoi(optarg); | | 917 | Gflag = atoi(optarg); |
916 | if (Gflag < 0) | | 918 | if (Gflag < 0) |
917 | error("invalid number of seconds %s", optarg); | | 919 | error("invalid number of seconds %s", optarg); |
918 | | | 920 | |
919 | /* We will create one file initially. */ | | 921 | /* We will create one file initially. */ |
920 | Gflag_count = 0; | | 922 | Gflag_count = 0; |
921 | | | 923 | |
922 | /* Grab the current time for rotation use. */ | | 924 | /* Grab the current time for rotation use. */ |
923 | if ((Gflag_time = time(NULL)) == (time_t)-1) { | | 925 | if ((Gflag_time = time(NULL)) == (time_t)-1) { |
924 | error("main: can't get current time: %s", | | 926 | error("main: can't get current time: %s", |
925 | pcap_strerror(errno)); | | 927 | pcap_strerror(errno)); |
926 | } | | 928 | } |
927 | break; | | 929 | break; |
928 | | | 930 | |
929 | case 'h': | | 931 | case 'h': |
930 | print_usage(); | | 932 | print_usage(); |
931 | exit(0); | | 933 | exit(0); |
932 | break; | | 934 | break; |
933 | | | 935 | |
934 | case 'H': | | 936 | case 'H': |
935 | ++ndo->ndo_Hflag; | | 937 | ++ndo->ndo_Hflag; |
936 | break; | | 938 | break; |
937 | | | 939 | |
938 | case 'i': | | 940 | case 'i': |
939 | if (optarg[0] == '0' && optarg[1] == 0) | | 941 | if (optarg[0] == '0' && optarg[1] == 0) |
940 | error("Invalid adapter index"); | | 942 | error("Invalid adapter index"); |
941 | | | 943 | |
942 | #ifdef HAVE_PCAP_FINDALLDEVS | | 944 | #ifdef HAVE_PCAP_FINDALLDEVS |
943 | /* | | 945 | /* |
944 | * If the argument is a number, treat it as | | 946 | * If the argument is a number, treat it as |
945 | * an index into the list of adapters, as | | 947 | * an index into the list of adapters, as |
946 | * printed by "tcpdump -D". | | 948 | * printed by "tcpdump -D". |
947 | * | | 949 | * |
948 | * This should be OK on UNIX systems, as interfaces | | 950 | * This should be OK on UNIX systems, as interfaces |
949 | * shouldn't have names that begin with digits. | | 951 | * shouldn't have names that begin with digits. |
950 | * It can be useful on Windows, where more than | | 952 | * It can be useful on Windows, where more than |
951 | * one interface can have the same name. | | 953 | * one interface can have the same name. |
952 | */ | | 954 | */ |
953 | devnum = strtol(optarg, &end, 10); | | 955 | devnum = strtol(optarg, &end, 10); |
954 | if (optarg != end && *end == '\0') { | | 956 | if (optarg != end && *end == '\0') { |
955 | if (devnum < 0) | | 957 | if (devnum < 0) |
956 | error("Invalid adapter index"); | | 958 | error("Invalid adapter index"); |
957 | | | 959 | |
958 | if (pcap_findalldevs(&devlist, ebuf) < 0) | | 960 | if (pcap_findalldevs(&devlist, ebuf) < 0) |
959 | error("%s", ebuf); | | 961 | error("%s", ebuf); |
960 | /* | | 962 | /* |
961 | * Look for the devnum-th entry in the | | 963 | * Look for the devnum-th entry in the |
962 | * list of devices (1-based). | | 964 | * list of devices (1-based). |
963 | */ | | 965 | */ |
964 | for (i = 0, dev = devlist; | | 966 | for (i = 0, dev = devlist; |
965 | i < devnum-1 && dev != NULL; | | 967 | i < devnum-1 && dev != NULL; |
966 | i++, dev = dev->next) | | 968 | i++, dev = dev->next) |
967 | ; | | 969 | ; |
968 | if (dev == NULL) | | 970 | if (dev == NULL) |
969 | error("Invalid adapter index"); | | 971 | error("Invalid adapter index"); |
970 | device = strdup(dev->name); | | 972 | device = strdup(dev->name); |
971 | pcap_freealldevs(devlist); | | 973 | pcap_freealldevs(devlist); |
972 | break; | | 974 | break; |
973 | } | | 975 | } |
974 | #endif /* HAVE_PCAP_FINDALLDEVS */ | | 976 | #endif /* HAVE_PCAP_FINDALLDEVS */ |
975 | device = optarg; | | 977 | device = optarg; |
976 | break; | | 978 | break; |
977 | | | 979 | |
978 | #ifdef HAVE_PCAP_CREATE | | 980 | #ifdef HAVE_PCAP_CREATE |
979 | case 'I': | | 981 | case 'I': |
980 | ++Iflag; | | 982 | ++Iflag; |
981 | break; | | 983 | break; |
982 | #endif /* HAVE_PCAP_CREATE */ | | 984 | #endif /* HAVE_PCAP_CREATE */ |
983 | | | 985 | |
984 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE | | 986 | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE |
985 | case 'j': | | 987 | case 'j': |
986 | jflag = pcap_tstamp_type_name_to_val(optarg); | | 988 | jflag = pcap_tstamp_type_name_to_val(optarg); |
987 | if (jflag < 0) | | 989 | if (jflag < 0) |
988 | error("invalid time stamp type %s", optarg); | | 990 | error("invalid time stamp type %s", optarg); |
989 | break; | | 991 | break; |
990 | | | 992 | |
991 | case 'J': | | 993 | case 'J': |
992 | Jflag++; | | 994 | Jflag++; |
993 | break; | | 995 | break; |
994 | #endif | | 996 | #endif |
995 | | | 997 | |
996 | case 'l': | | 998 | case 'l': |
997 | #ifdef _WIN32 | | 999 | #ifdef _WIN32 |
998 | /* | | 1000 | /* |
999 | * _IOLBF is the same as _IOFBF in Microsoft's C | | 1001 | * _IOLBF is the same as _IOFBF in Microsoft's C |
1000 | * libraries; the only alternative they offer | | 1002 | * libraries; the only alternative they offer |
1001 | * is _IONBF. | | 1003 | * is _IONBF. |
1002 | * | | 1004 | * |
1003 | * XXX - this should really be checking for MSVC++, | | 1005 | * XXX - this should really be checking for MSVC++, |
1004 | * not _WIN32, if, for example, MinGW has its own | | 1006 | * not _WIN32, if, for example, MinGW has its own |
1005 | * C library that is more UNIX-compatible. | | 1007 | * C library that is more UNIX-compatible. |
1006 | */ | | 1008 | */ |
1007 | setvbuf(stdout, NULL, _IONBF, 0); | | 1009 | setvbuf(stdout, NULL, _IONBF, 0); |
1008 | #else /* _WIN32 */ | | 1010 | #else /* _WIN32 */ |
1009 | #ifdef HAVE_SETLINEBUF | | 1011 | #ifdef HAVE_SETLINEBUF |
1010 | setlinebuf(stdout); | | 1012 | setlinebuf(stdout); |
1011 | #else | | 1013 | #else |
1012 | setvbuf(stdout, NULL, _IOLBF, 0); | | 1014 | setvbuf(stdout, NULL, _IOLBF, 0); |
1013 | #endif | | 1015 | #endif |
1014 | #endif /* _WIN32 */ | | 1016 | #endif /* _WIN32 */ |
1015 | break; | | 1017 | break; |
1016 | | | 1018 | |
1017 | case 'K': | | 1019 | case 'K': |
1018 | ++ndo->ndo_Kflag; | | 1020 | ++ndo->ndo_Kflag; |
1019 | break; | | 1021 | break; |
1020 | | | 1022 | |
1021 | case 'm': | | 1023 | case 'm': |
1022 | #ifdef USE_LIBSMI | | 1024 | #ifdef USE_LIBSMI |
1023 | if (smiLoadModule(optarg) == 0) { | | 1025 | if (smiLoadModule(optarg) == 0) { |
1024 | error("could not load MIB module %s", optarg); | | 1026 | error("could not load MIB module %s", optarg); |
1025 | } | | 1027 | } |
1026 | ndo->ndo_mflag = 1; | | 1028 | ndo->ndo_mflag = 1; |
1027 | #else | | 1029 | #else |
1028 | (void)fprintf(stderr, "%s: ignoring option `-m %s' ", | | 1030 | (void)fprintf(stderr, "%s: ignoring option `-m %s' ", |
1029 | program_name, optarg); | | 1031 | program_name, optarg); |
1030 | (void)fprintf(stderr, "(no libsmi support)\n"); | | 1032 | (void)fprintf(stderr, "(no libsmi support)\n"); |
1031 | #endif | | 1033 | #endif |
1032 | break; | | 1034 | break; |
1033 | | | 1035 | |
1034 | case 'M': | | 1036 | case 'M': |
1035 | /* TCP-MD5 shared secret */ | | 1037 | /* TCP-MD5 shared secret */ |
1036 | #ifndef HAVE_LIBCRYPTO | | 1038 | #ifndef HAVE_LIBCRYPTO |
1037 | warning("crypto code not compiled in"); | | 1039 | warning("crypto code not compiled in"); |
1038 | #endif | | 1040 | #endif |
1039 | ndo->ndo_sigsecret = optarg; | | 1041 | ndo->ndo_sigsecret = optarg; |
1040 | break; | | 1042 | break; |
1041 | | | 1043 | |
1042 | case 'n': | | 1044 | case 'n': |
1043 | ++ndo->ndo_nflag; | | 1045 | ++ndo->ndo_nflag; |
1044 | break; | | 1046 | break; |
1045 | | | 1047 | |
1046 | case 'N': | | 1048 | case 'N': |
1047 | ++ndo->ndo_Nflag; | | 1049 | ++ndo->ndo_Nflag; |
1048 | break; | | 1050 | break; |
1049 | | | 1051 | |
1050 | case 'O': | | 1052 | case 'O': |
1051 | Oflag = 0; | | 1053 | Oflag = 0; |
1052 | break; | | 1054 | break; |
1053 | | | 1055 | |
1054 | case 'p': | | 1056 | case 'p': |
1055 | ++pflag; | | 1057 | ++pflag; |
1056 | break; | | 1058 | break; |
1057 | | | 1059 | |
1058 | case 'q': | | 1060 | case 'q': |
1059 | ++ndo->ndo_qflag; | | 1061 | ++ndo->ndo_qflag; |
1060 | ++ndo->ndo_suppress_default_print; | | 1062 | ++ndo->ndo_suppress_default_print; |
1061 | break; | | 1063 | break; |
1062 | | | 1064 | |
1063 | #ifdef HAVE_PCAP_SETDIRECTION | | 1065 | #ifdef HAVE_PCAP_SETDIRECTION |
1064 | case 'Q': | | 1066 | case 'Q': |
1065 | if (ascii_strcasecmp(optarg, "in") == 0) | | 1067 | if (ascii_strcasecmp(optarg, "in") == 0) |
1066 | Qflag = PCAP_D_IN; | | 1068 | Qflag = PCAP_D_IN; |
1067 | else if (ascii_strcasecmp(optarg, "out") == 0) | | 1069 | else if (ascii_strcasecmp(optarg, "out") == 0) |
1068 | Qflag = PCAP_D_OUT; | | 1070 | Qflag = PCAP_D_OUT; |
1069 | else if (ascii_strcasecmp(optarg, "inout") == 0) | | 1071 | else if (ascii_strcasecmp(optarg, "inout") == 0) |
1070 | Qflag = PCAP_D_INOUT; | | 1072 | Qflag = PCAP_D_INOUT; |
1071 | else | | 1073 | else |
1072 | error("unknown capture direction `%s'", optarg); | | 1074 | error("unknown capture direction `%s'", optarg); |
1073 | break; | | 1075 | break; |
1074 | #endif /* HAVE_PCAP_SETDIRECTION */ | | 1076 | #endif /* HAVE_PCAP_SETDIRECTION */ |
1075 | | | 1077 | |
1076 | case 'r': | | 1078 | case 'r': |
1077 | RFileName = optarg; | | 1079 | RFileName = optarg; |
1078 | break; | | 1080 | break; |
1079 | | | 1081 | |
1080 | case 's': | | 1082 | case 's': |
1081 | ndo->ndo_snaplen = strtol(optarg, &end, 0); | | 1083 | ndo->ndo_snaplen = strtol(optarg, &end, 0); |
1082 | if (optarg == end || *end != '\0' | | 1084 | if (optarg == end || *end != '\0' |
1083 | || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN) | | 1085 | || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN) |
1084 | error("invalid snaplen %s", optarg); | | 1086 | error("invalid snaplen %s", optarg); |
1085 | else if (ndo->ndo_snaplen == 0) | | 1087 | else if (ndo->ndo_snaplen == 0) |
1086 | ndo->ndo_snaplen = MAXIMUM_SNAPLEN; | | 1088 | ndo->ndo_snaplen = MAXIMUM_SNAPLEN; |
1087 | break; | | 1089 | break; |
1088 | | | 1090 | |
1089 | case 'S': | | 1091 | case 'S': |
1090 | ++ndo->ndo_Sflag; | | 1092 | ++ndo->ndo_Sflag; |
1091 | break; | | 1093 | break; |
1092 | | | 1094 | |
1093 | case 't': | | 1095 | case 't': |
1094 | ++ndo->ndo_tflag; | | 1096 | ++ndo->ndo_tflag; |
1095 | break; | | 1097 | break; |
1096 | | | 1098 | |
1097 | case 'T': | | 1099 | case 'T': |
1098 | if (ascii_strcasecmp(optarg, "vat") == 0) | | 1100 | if (ascii_strcasecmp(optarg, "vat") == 0) |
1099 | ndo->ndo_packettype = PT_VAT; | | 1101 | ndo->ndo_packettype = PT_VAT; |
1100 | else if (ascii_strcasecmp(optarg, "wb") == 0) | | 1102 | else if (ascii_strcasecmp(optarg, "wb") == 0) |
1101 | ndo->ndo_packettype = PT_WB; | | 1103 | ndo->ndo_packettype = PT_WB; |
1102 | else if (ascii_strcasecmp(optarg, "rpc") == 0) | | 1104 | else if (ascii_strcasecmp(optarg, "rpc") == 0) |
1103 | ndo->ndo_packettype = PT_RPC; | | 1105 | ndo->ndo_packettype = PT_RPC; |
1104 | else if (ascii_strcasecmp(optarg, "rtp") == 0) | | 1106 | else if (ascii_strcasecmp(optarg, "rtp") == 0) |
1105 | ndo->ndo_packettype = PT_RTP; | | 1107 | ndo->ndo_packettype = PT_RTP; |
1106 | else if (ascii_strcasecmp(optarg, "rtcp") == 0) | | 1108 | else if (ascii_strcasecmp(optarg, "rtcp") == 0) |
1107 | ndo->ndo_packettype = PT_RTCP; | | 1109 | ndo->ndo_packettype = PT_RTCP; |
1108 | else if (ascii_strcasecmp(optarg, "snmp") == 0) | | 1110 | else if (ascii_strcasecmp(optarg, "snmp") == 0) |
1109 | ndo->ndo_packettype = PT_SNMP; | | 1111 | ndo->ndo_packettype = PT_SNMP; |
1110 | else if (ascii_strcasecmp(optarg, "cnfp") == 0) | | 1112 | else if (ascii_strcasecmp(optarg, "cnfp") == 0) |
1111 | ndo->ndo_packettype = PT_CNFP; | | 1113 | ndo->ndo_packettype = PT_CNFP; |
1112 | else if (ascii_strcasecmp(optarg, "tftp") == 0) | | 1114 | else if (ascii_strcasecmp(optarg, "tftp") == 0) |
1113 | ndo->ndo_packettype = PT_TFTP; | | 1115 | ndo->ndo_packettype = PT_TFTP; |
1114 | else if (ascii_strcasecmp(optarg, "aodv") == 0) | | 1116 | else if (ascii_strcasecmp(optarg, "aodv") == 0) |
1115 | ndo->ndo_packettype = PT_AODV; | | 1117 | ndo->ndo_packettype = PT_AODV; |
1116 | else if (ascii_strcasecmp(optarg, "carp") == 0) | | 1118 | else if (ascii_strcasecmp(optarg, "carp") == 0) |
1117 | ndo->ndo_packettype = PT_CARP; | | 1119 | ndo->ndo_packettype = PT_CARP; |
1118 | else if (ascii_strcasecmp(optarg, "radius") == 0) | | 1120 | else if (ascii_strcasecmp(optarg, "radius") == 0) |
1119 | ndo->ndo_packettype = PT_RADIUS; | | 1121 | ndo->ndo_packettype = PT_RADIUS; |
1120 | else if (ascii_strcasecmp(optarg, "zmtp1") == 0) | | 1122 | else if (ascii_strcasecmp(optarg, "zmtp1") == 0) |
1121 | ndo->ndo_packettype = PT_ZMTP1; | | 1123 | ndo->ndo_packettype = PT_ZMTP1; |
1122 | else if (ascii_strcasecmp(optarg, "vxlan") == 0) | | 1124 | else if (ascii_strcasecmp(optarg, "vxlan") == 0) |
1123 | ndo->ndo_packettype = PT_VXLAN; | | 1125 | ndo->ndo_packettype = PT_VXLAN; |
1124 | else if (ascii_strcasecmp(optarg, "pgm") == 0) | | 1126 | else if (ascii_strcasecmp(optarg, "pgm") == 0) |
1125 | ndo->ndo_packettype = PT_PGM; | | 1127 | ndo->ndo_packettype = PT_PGM; |
1126 | else if (ascii_strcasecmp(optarg, "pgm_zmtp1") == 0) | | 1128 | else if (ascii_strcasecmp(optarg, "pgm_zmtp1") == 0) |
1127 | ndo->ndo_packettype = PT_PGM_ZMTP1; | | 1129 | ndo->ndo_packettype = PT_PGM_ZMTP1; |
1128 | else if (ascii_strcasecmp(optarg, "lmp") == 0) | | 1130 | else if (ascii_strcasecmp(optarg, "lmp") == 0) |
1129 | ndo->ndo_packettype = PT_LMP; | | 1131 | ndo->ndo_packettype = PT_LMP; |
1130 | else if (ascii_strcasecmp(optarg, "resp") == 0) | | 1132 | else if (ascii_strcasecmp(optarg, "resp") == 0) |
1131 | ndo->ndo_packettype = PT_RESP; | | 1133 | ndo->ndo_packettype = PT_RESP; |
1132 | else | | 1134 | else |
1133 | error("unknown packet type `%s'", optarg); | | 1135 | error("unknown packet type `%s'", optarg); |
1134 | break; | | 1136 | break; |
1135 | | | 1137 | |
1136 | case 'u': | | 1138 | case 'u': |
1137 | ++ndo->ndo_uflag; | | 1139 | ++ndo->ndo_uflag; |
1138 | break; | | 1140 | break; |
1139 | | | 1141 | |
1140 | #ifdef HAVE_PCAP_DUMP_FLUSH | | 1142 | #ifdef HAVE_PCAP_DUMP_FLUSH |
1141 | case 'U': | | 1143 | case 'U': |
1142 | ++Uflag; | | 1144 | ++Uflag; |
1143 | break; | | 1145 | break; |
1144 | #endif | | 1146 | #endif |
1145 | | | 1147 | |
1146 | case 'v': | | 1148 | case 'v': |
1147 | ++ndo->ndo_vflag; | | 1149 | ++ndo->ndo_vflag; |
1148 | break; | | 1150 | break; |
1149 | | | 1151 | |
1150 | case 'V': | | 1152 | case 'V': |
1151 | VFileName = optarg; | | 1153 | VFileName = optarg; |
1152 | break; | | 1154 | break; |
1153 | | | 1155 | |
1154 | case 'w': | | 1156 | case 'w': |
1155 | WFileName = optarg; | | 1157 | WFileName = optarg; |
1156 | break; | | 1158 | break; |
1157 | | | 1159 | |
1158 | case 'W': | | 1160 | case 'W': |
1159 | Wflag = atoi(optarg); | | 1161 | Wflag = atoi(optarg); |
1160 | if (Wflag <= 0) | | 1162 | if (Wflag <= 0) |
1161 | error("invalid number of output files %s", optarg); | | 1163 | error("invalid number of output files %s", optarg); |
1162 | WflagChars = getWflagChars(Wflag); | | 1164 | WflagChars = getWflagChars(Wflag); |
1163 | break; | | 1165 | break; |
1164 | | | 1166 | |
1165 | case 'x': | | 1167 | case 'x': |
1166 | ++ndo->ndo_xflag; | | 1168 | ++ndo->ndo_xflag; |
1167 | ++ndo->ndo_suppress_default_print; | | 1169 | ++ndo->ndo_suppress_default_print; |
1168 | break; | | 1170 | break; |
1169 | | | 1171 | |
1170 | case 'X': | | 1172 | case 'X': |
1171 | ++ndo->ndo_Xflag; | | 1173 | ++ndo->ndo_Xflag; |
1172 | ++ndo->ndo_suppress_default_print; | | 1174 | ++ndo->ndo_suppress_default_print; |
1173 | break; | | 1175 | break; |
1174 | | | 1176 | |
1175 | case 'y': | | 1177 | case 'y': |
1176 | yflag_dlt_name = optarg; | | 1178 | yflag_dlt_name = optarg; |
1177 | yflag_dlt = | | 1179 | yflag_dlt = |
1178 | pcap_datalink_name_to_val(yflag_dlt_name); | | 1180 | pcap_datalink_name_to_val(yflag_dlt_name); |
1179 | if (yflag_dlt < 0) | | 1181 | if (yflag_dlt < 0) |
1180 | error("invalid data link type %s", yflag_dlt_name); | | 1182 | error("invalid data link type %s", yflag_dlt_name); |
1181 | break; | | 1183 | break; |
1182 | | | 1184 | |
1183 | #ifdef HAVE_PCAP_SET_PARSER_DEBUG | | 1185 | #ifdef HAVE_PCAP_SET_PARSER_DEBUG |
1184 | case 'Y': | | 1186 | case 'Y': |
1185 | { | | 1187 | { |
1186 | /* Undocumented flag */ | | 1188 | /* Undocumented flag */ |
1187 | pcap_set_parser_debug(1); | | 1189 | pcap_set_parser_debug(1); |
1188 | } | | 1190 | } |
1189 | break; | | 1191 | break; |
1190 | #endif | | 1192 | #endif |
1191 | case 'z': | | 1193 | case 'z': |
1192 | zflag = optarg; | | 1194 | zflag = optarg; |
1193 | break; | | 1195 | break; |
1194 | | | 1196 | |
1195 | case 'Z': | | 1197 | case 'Z': |
1196 | username = optarg; | | 1198 | username = optarg; |
1197 | break; | | 1199 | break; |
1198 | | | 1200 | |
1199 | case '#': | | 1201 | case '#': |
1200 | ndo->ndo_packet_number = 1; | | 1202 | ndo->ndo_packet_number = 1; |
1201 | break; | | 1203 | break; |
1202 | | | 1204 | |
1203 | case OPTION_VERSION: | | 1205 | case OPTION_VERSION: |
1204 | print_version(); | | 1206 | print_version(); |
1205 | exit(0); | | 1207 | exit(0); |
1206 | break; | | 1208 | break; |