nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* dumpcap.c |
2 | * |
||
3 | * Wireshark - Network traffic analyzer |
||
4 | * By Gerald Combs <gerald@wireshark.org> |
||
5 | * Copyright 1998 Gerald Combs |
||
6 | * |
||
7 | * This program is free software; you can redistribute it and/or |
||
8 | * modify it under the terms of the GNU General Public License |
||
9 | * as published by the Free Software Foundation; either version 2 |
||
10 | * of the License, or (at your option) any later version. |
||
11 | * |
||
12 | * This program is distributed in the hope that it will be useful, |
||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
15 | * GNU General Public License for more details. |
||
16 | * |
||
17 | * You should have received a copy of the GNU General Public License |
||
18 | * along with this program; if not, write to the Free Software |
||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
20 | */ |
||
21 | |||
22 | #include <config.h> |
||
23 | |||
24 | #include <stdio.h> |
||
25 | #include <stdlib.h> /* for exit() */ |
||
26 | #include <glib.h> |
||
27 | |||
28 | #include <string.h> |
||
29 | |||
30 | #ifdef HAVE_SYS_TYPES_H |
||
31 | # include <sys/types.h> |
||
32 | #endif |
||
33 | |||
34 | #ifdef HAVE_SYS_SOCKET_H |
||
35 | #include <sys/socket.h> |
||
36 | #endif |
||
37 | |||
38 | #ifdef HAVE_NETINET_IN_H |
||
39 | #include <netinet/in.h> |
||
40 | #endif |
||
41 | |||
42 | #ifdef HAVE_GETOPT_H |
||
43 | #include <getopt.h> |
||
44 | #endif |
||
45 | |||
46 | #ifdef HAVE_ARPA_INET_H |
||
47 | #include <arpa/inet.h> |
||
48 | #endif |
||
49 | |||
50 | #if defined(__APPLE__) && defined(__LP64__) |
||
51 | #include <sys/utsname.h> |
||
52 | #endif |
||
53 | |||
54 | #include <signal.h> |
||
55 | #include <errno.h> |
||
56 | |||
57 | #include <wsutil/cmdarg_err.h> |
||
58 | #include <wsutil/crash_info.h> |
||
59 | #include <ws_version_info.h> |
||
60 | |||
61 | #ifndef HAVE_GETOPT_LONG |
||
62 | #include "wsutil/wsgetopt.h" |
||
63 | #endif |
||
64 | |||
65 | #ifdef HAVE_NETDB_H |
||
66 | #include <netdb.h> |
||
67 | #endif |
||
68 | |||
69 | #ifdef HAVE_LIBCAP |
||
70 | # include <sys/prctl.h> |
||
71 | # include <sys/capability.h> |
||
72 | #endif |
||
73 | |||
74 | #include "ringbuffer.h" |
||
75 | |||
76 | #include "caputils/capture_ifinfo.h" |
||
77 | #include "caputils/capture-pcap-util.h" |
||
78 | #include "caputils/capture-pcap-util-int.h" |
||
79 | #ifdef _WIN32 |
||
80 | #include "caputils/capture-wpcap.h" |
||
81 | #endif /* _WIN32 */ |
||
82 | |||
83 | #include "writecap/pcapio.h" |
||
84 | |||
85 | #ifdef _WIN32 |
||
86 | #include <wsutil/unicode-utils.h> |
||
87 | #endif |
||
88 | |||
89 | #ifndef _WIN32 |
||
90 | #include <sys/un.h> |
||
91 | #endif |
||
92 | |||
93 | #include <wsutil/clopts_common.h> |
||
94 | #include <wsutil/privileges.h> |
||
95 | |||
96 | #include "sync_pipe.h" |
||
97 | |||
98 | #include "capture_opts.h" |
||
99 | #include <capchild/capture_session.h> |
||
100 | #include <capchild/capture_sync.h> |
||
101 | |||
102 | #include "conditions.h" |
||
103 | #include "capture_stop_conditions.h" |
||
104 | |||
105 | #include "wsutil/tempfile.h" |
||
106 | #include "log.h" |
||
107 | #include "wsutil/file_util.h" |
||
108 | #include "wsutil/os_version_info.h" |
||
109 | #include "wsutil/str_util.h" |
||
110 | #include "wsutil/inet_addr.h" |
||
111 | |||
112 | #include "caputils/ws80211_utils.h" |
||
113 | |||
114 | #ifdef HAVE_EXTCAP |
||
115 | #include "extcap.h" |
||
116 | #endif |
||
117 | |||
118 | /* |
||
119 | * Get information about libpcap format from "wiretap/libpcap.h". |
||
120 | * Get information about pcapng format from "wiretap/pcapng_module.h". |
||
121 | * XXX - can we just use pcap_open_offline() to read the pipe? |
||
122 | */ |
||
123 | #include "wiretap/libpcap.h" |
||
124 | #include "wiretap/pcapng_module.h" |
||
125 | |||
126 | /**#define DEBUG_DUMPCAP**/ |
||
127 | /**#define DEBUG_CHILD_DUMPCAP**/ |
||
128 | |||
129 | #ifdef _WIN32 |
||
130 | #ifdef DEBUG_DUMPCAP |
||
131 | #include <conio.h> /* _getch() */ |
||
132 | #endif |
||
133 | #endif |
||
134 | |||
135 | #ifdef DEBUG_CHILD_DUMPCAP |
||
136 | FILE *debug_log; /* for logging debug messages to */ |
||
137 | /* a file if DEBUG_CHILD_DUMPCAP */ |
||
138 | /* is defined */ |
||
139 | #endif |
||
140 | |||
141 | static GAsyncQueue *pcap_queue; |
||
142 | static gint64 pcap_queue_bytes; |
||
143 | static gint64 pcap_queue_packets; |
||
144 | static gint64 pcap_queue_byte_limit = 0; |
||
145 | static gint64 pcap_queue_packet_limit = 0; |
||
146 | |||
147 | static gboolean capture_child = FALSE; /* FALSE: standalone call, TRUE: this is an Wireshark capture child */ |
||
148 | #ifdef _WIN32 |
||
149 | static gchar *sig_pipe_name = NULL; |
||
150 | static HANDLE sig_pipe_handle = NULL; |
||
151 | static gboolean signal_pipe_check_running(void); |
||
152 | #endif |
||
153 | |||
154 | #ifdef SIGINFO |
||
155 | static gboolean infodelay; /* if TRUE, don't print capture info in SIGINFO handler */ |
||
156 | static gboolean infoprint; /* if TRUE, print capture info after clearing infodelay */ |
||
157 | #endif /* SIGINFO */ |
||
158 | |||
159 | /** Stop a low-level capture (stops the capture child). */ |
||
160 | static void capture_loop_stop(void); |
||
161 | /** Close a pipe, or socket if \a from_socket is TRUE */ |
||
162 | static void cap_pipe_close(int pipe_fd, gboolean from_socket _U_); |
||
163 | |||
164 | #ifdef __linux__ |
||
165 | /* |
||
166 | * Enable kernel BPF JIT compiler if available. |
||
167 | * If any calls fail, just drive on - the JIT compiler might not be |
||
168 | * enabled, but filtering will still work, and it's not clear what |
||
169 | * we could do if the calls fail; should we just report the error |
||
170 | * and not continue to capture, should we report it as a warning, or |
||
171 | * what? |
||
172 | */ |
||
173 | static void |
||
174 | enable_kernel_bpf_jit_compiler(void) |
||
175 | { |
||
176 | int fd; |
||
177 | ssize_t written _U_; |
||
178 | static const char file[] = "/proc/sys/net/core/bpf_jit_enable"; |
||
179 | |||
180 | fd = ws_open(file, O_WRONLY); |
||
181 | if (fd < 0) |
||
182 | return; |
||
183 | |||
184 | written = ws_write(fd, "1", strlen("1")); |
||
185 | |||
186 | ws_close(fd); |
||
187 | } |
||
188 | #endif |
||
189 | |||
190 | #if !defined (__linux__) |
||
191 | #ifndef HAVE_PCAP_BREAKLOOP |
||
192 | /* |
||
193 | * We don't have pcap_breakloop(), which is the only way to ensure that |
||
194 | * pcap_dispatch(), pcap_loop(), or even pcap_next() or pcap_next_ex() |
||
195 | * won't, if the call to read the next packet or batch of packets is |
||
196 | * is interrupted by a signal on UN*X, just go back and try again to |
||
197 | * read again. |
||
198 | * |
||
199 | * On UN*X, we catch SIGINT as a "stop capturing" signal, and, in |
||
200 | * the signal handler, set a flag to stop capturing; however, without |
||
201 | * a guarantee of that sort, we can't guarantee that we'll stop capturing |
||
202 | * if the read will be retried and won't time out if no packets arrive. |
||
203 | * |
||
204 | * Therefore, on at least some platforms, we work around the lack of |
||
205 | * pcap_breakloop() by doing a select() on the pcap_t's file descriptor |
||
206 | * to wait for packets to arrive, so that we're probably going to be |
||
207 | * blocked in the select() when the signal arrives, and can just bail |
||
208 | * out of the loop at that point. |
||
209 | * |
||
210 | * However, we don't want to do that on BSD (because "select()" doesn't work |
||
211 | * correctly on BPF devices on at least some releases of some flavors of |
||
212 | * BSD), and we don't want to do it on Windows (because "select()" is |
||
213 | * something for sockets, not for arbitrary handles). (Note that "Windows" |
||
214 | * here includes Cygwin; even in its pretend-it's-UNIX environment, we're |
||
215 | * using WinPcap, not a UNIX libpcap.) |
||
216 | * |
||
217 | * Fortunately, we don't need to do it on BSD, because the libpcap timeout |
||
218 | * on BSD times out even if no packets have arrived, so we'll eventually |
||
219 | * exit pcap_dispatch() with an indication that no packets have arrived, |
||
220 | * and will break out of the capture loop at that point. |
||
221 | * |
||
222 | * On Windows, we can't send a SIGINT to stop capturing, so none of this |
||
223 | * applies in any case. |
||
224 | * |
||
225 | * XXX - the various BSDs appear to define BSD in <sys/param.h>; we don't |
||
226 | * want to include it if it's not present on this platform, however. |
||
227 | */ |
||
228 | # if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && \ |
||
229 | !defined(__bsdi__) && !defined(__APPLE__) && !defined(_WIN32) && \ |
||
230 | !defined(__CYGWIN__) |
||
231 | # define MUST_DO_SELECT |
||
232 | # endif /* avoid select */ |
||
233 | #endif /* HAVE_PCAP_BREAKLOOP */ |
||
234 | #else /* linux */ |
||
235 | /* whatever the deal with pcap_breakloop, linux doesn't support timeouts |
||
236 | * in pcap_dispatch(); on the other hand, select() works just fine there. |
||
237 | * Hence we use a select for that come what may. |
||
238 | * |
||
239 | * XXX - with TPACKET_V1 and TPACKET_V2, it currently uses select() |
||
240 | * internally, and, with TPACKET_V3, once that's supported, it'll |
||
241 | * support timeouts, at least as I understand the way the code works. |
||
242 | */ |
||
243 | #define MUST_DO_SELECT |
||
244 | #endif |
||
245 | |||
246 | /** init the capture filter */ |
||
247 | typedef enum { |
||
248 | INITFILTER_NO_ERROR, |
||
249 | INITFILTER_BAD_FILTER, |
||
250 | INITFILTER_OTHER_ERROR |
||
251 | } initfilter_status_t; |
||
252 | |||
253 | typedef enum { |
||
254 | STATE_EXPECT_REC_HDR, |
||
255 | STATE_READ_REC_HDR, |
||
256 | STATE_EXPECT_DATA, |
||
257 | STATE_READ_DATA |
||
258 | } cap_pipe_state_t; |
||
259 | |||
260 | typedef enum { |
||
261 | PIPOK, |
||
262 | PIPEOF, |
||
263 | PIPERR, |
||
264 | PIPNEXIST |
||
265 | } cap_pipe_err_t; |
||
266 | |||
267 | typedef struct _pcap_options { |
||
268 | guint32 received; |
||
269 | guint32 dropped; |
||
270 | guint32 flushed; |
||
271 | pcap_t *pcap_h; |
||
272 | #ifdef MUST_DO_SELECT |
||
273 | int pcap_fd; /**< pcap file descriptor */ |
||
274 | #endif |
||
275 | gboolean pcap_err; |
||
276 | guint interface_id; |
||
277 | GThread *tid; |
||
278 | int snaplen; |
||
279 | int linktype; |
||
280 | gboolean ts_nsec; /**< TRUE if we're using nanosecond precision. */ |
||
281 | /**< capture pipe (unix only "input file") */ |
||
282 | gboolean from_cap_pipe; /**< TRUE if we are capturing data from a capture pipe */ |
||
283 | gboolean from_cap_socket; /**< TRUE if we're capturing from socket */ |
||
284 | struct pcap_hdr cap_pipe_hdr; /**< Pcap header when capturing from a pipe */ |
||
285 | struct pcaprec_modified_hdr cap_pipe_rechdr; /**< Pcap record header when capturing from a pipe */ |
||
286 | #ifdef _WIN32 |
||
287 | HANDLE cap_pipe_h; /**< The handle of the capture pipe */ |
||
288 | #endif |
||
289 | int cap_pipe_fd; /**< the file descriptor of the capture pipe */ |
||
290 | gboolean cap_pipe_modified; /**< TRUE if data in the pipe uses modified pcap headers */ |
||
291 | gboolean cap_pipe_byte_swapped; /**< TRUE if data in the pipe is byte swapped */ |
||
292 | #if defined(_WIN32) |
||
293 | char * cap_pipe_buf; /**< Pointer to the data buffer we read into */ |
||
294 | DWORD cap_pipe_bytes_to_read; /**< Used by cap_pipe_dispatch */ |
||
295 | DWORD cap_pipe_bytes_read; /**< Used by cap_pipe_dispatch */ |
||
296 | #else |
||
297 | size_t cap_pipe_bytes_to_read; /**< Used by cap_pipe_dispatch */ |
||
298 | size_t cap_pipe_bytes_read; /**< Used by cap_pipe_dispatch */ |
||
299 | #endif |
||
300 | cap_pipe_state_t cap_pipe_state; |
||
301 | cap_pipe_err_t cap_pipe_err; |
||
302 | |||
303 | #if defined(_WIN32) |
||
304 | GMutex *cap_pipe_read_mtx; |
||
305 | GAsyncQueue *cap_pipe_pending_q, *cap_pipe_done_q; |
||
306 | #endif |
||
307 | } pcap_options; |
||
308 | |||
309 | typedef struct _loop_data { |
||
310 | /* common */ |
||
311 | gboolean go; /**< TRUE as long as we're supposed to keep capturing */ |
||
312 | int err; /**< if non-zero, error seen while capturing */ |
||
313 | gint packet_count; /**< Number of packets we have already captured */ |
||
314 | gint packet_max; /**< Number of packets we're supposed to capture - 0 means infinite */ |
||
315 | guint inpkts_to_sync_pipe; /**< Packets not already send out to the sync_pipe */ |
||
316 | #ifdef SIGINFO |
||
317 | gboolean report_packet_count; /**< Set by SIGINFO handler; print packet count */ |
||
318 | #endif |
||
319 | GArray *pcaps; |
||
320 | /* output file(s) */ |
||
321 | FILE *pdh; |
||
322 | int save_file_fd; |
||
323 | guint64 bytes_written; |
||
324 | guint32 autostop_files; |
||
325 | } loop_data; |
||
326 | |||
327 | typedef struct _pcap_queue_element { |
||
328 | pcap_options *pcap_opts; |
||
329 | struct pcap_pkthdr phdr; |
||
330 | u_char *pd; |
||
331 | } pcap_queue_element; |
||
332 | |||
333 | /* |
||
334 | * Standard secondary message for unexpected errors. |
||
335 | */ |
||
336 | static const char please_report[] = |
||
337 | "Please report this to the Wireshark developers.\n" |
||
338 | "https://bugs.wireshark.org/\n" |
||
339 | "(This is not a crash; please do not report it as such.)"; |
||
340 | |||
341 | /* |
||
342 | * This needs to be static, so that the SIGINT handler can clear the "go" |
||
343 | * flag. |
||
344 | */ |
||
345 | static loop_data global_ld; |
||
346 | |||
347 | /* |
||
348 | * Timeout, in milliseconds, for reads from the stream of captured packets |
||
349 | * from a capture device. |
||
350 | * |
||
351 | * A bug in Mac OS X 10.6 and 10.6.1 causes calls to pcap_open_live(), in |
||
352 | * 64-bit applications, with sub-second timeouts not to work. The bug is |
||
353 | * fixed in 10.6.2, re-broken in 10.6.3, and again fixed in 10.6.5. |
||
354 | */ |
||
355 | #if defined(__APPLE__) && defined(__LP64__) |
||
356 | static gboolean need_timeout_workaround; |
||
357 | |||
358 | #define CAP_READ_TIMEOUT (need_timeout_workaround ? 1000 : 250) |
||
359 | #else |
||
360 | #define CAP_READ_TIMEOUT 250 |
||
361 | #endif |
||
362 | |||
363 | /* |
||
364 | * Timeout, in microseconds, for reads from the stream of captured packets |
||
365 | * from a pipe. Pipes don't have the same problem that BPF devices do |
||
366 | * in OS X 10.6, 10.6.1, 10.6.3, and 10.6.4, so we always use a timeout |
||
367 | * of 250ms, i.e. the same value as CAP_READ_TIMEOUT when not on one |
||
368 | * of the offending versions of Snow Leopard. |
||
369 | * |
||
370 | * On Windows this value is converted to milliseconds and passed to |
||
371 | * WaitForSingleObject. If it's less than 1000 WaitForSingleObject |
||
372 | * will return immediately. |
||
373 | */ |
||
374 | #if defined(_WIN32) |
||
375 | #define PIPE_READ_TIMEOUT 100000 |
||
376 | #else |
||
377 | #define PIPE_READ_TIMEOUT 250000 |
||
378 | #endif |
||
379 | |||
380 | #define WRITER_THREAD_TIMEOUT 100000 /* usecs */ |
||
381 | |||
382 | static void |
||
383 | console_log_handler(const char *log_domain, GLogLevelFlags log_level, |
||
384 | const char *message, gpointer user_data _U_); |
||
385 | |||
386 | /* capture related options */ |
||
387 | static capture_options global_capture_opts; |
||
388 | static gboolean quiet = FALSE; |
||
389 | static gboolean use_threads = FALSE; |
||
390 | static guint64 start_time; |
||
391 | |||
392 | static void capture_loop_write_packet_cb(u_char *pcap_opts_p, const struct pcap_pkthdr *phdr, |
||
393 | const u_char *pd); |
||
394 | static void capture_loop_queue_packet_cb(u_char *pcap_opts_p, const struct pcap_pkthdr *phdr, |
||
395 | const u_char *pd); |
||
396 | static void capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fname, |
||
397 | int err, gboolean is_close); |
||
398 | |||
399 | static void WS_NORETURN exit_main(int err); |
||
400 | |||
401 | static void report_new_capture_file(const char *filename); |
||
402 | static void report_packet_count(unsigned int packet_count); |
||
403 | static void report_packet_drops(guint32 received, guint32 pcap_drops, guint32 drops, guint32 flushed, guint32 ps_ifdrop, gchar *name); |
||
404 | static void report_capture_error(const char *error_msg, const char *secondary_error_msg); |
||
405 | static void report_cfilter_error(capture_options *capture_opts, guint i, const char *errmsg); |
||
406 | |||
407 | #define MSG_MAX_LENGTH 4096 |
||
408 | |||
409 | /* Copied from pcapio.c pcapng_write_interface_statistics_block()*/ |
||
410 | static guint64 |
||
411 | create_timestamp(void) { |
||
412 | guint64 timestamp; |
||
413 | #ifdef _WIN32 |
||
414 | FILETIME now; |
||
415 | #else |
||
416 | struct timeval now; |
||
417 | #endif |
||
418 | |||
419 | #ifdef _WIN32 |
||
420 | /* |
||
421 | * Current time, represented as 100-nanosecond intervals since |
||
422 | * January 1, 1601, 00:00:00 UTC. |
||
423 | * |
||
424 | * I think DWORD might be signed, so cast both parts of "now" |
||
425 | * to guint32 so that the sign bit doesn't get treated specially. |
||
426 | * |
||
427 | * Windows 8 provides GetSystemTimePreciseAsFileTime which we |
||
428 | * might want to use instead. |
||
429 | */ |
||
430 | GetSystemTimeAsFileTime(&now); |
||
431 | timestamp = (((guint64)(guint32)now.dwHighDateTime) << 32) + |
||
432 | (guint32)now.dwLowDateTime; |
||
433 | |||
434 | /* |
||
435 | * Convert to same thing but as 1-microsecond, i.e. 1000-nanosecond, |
||
436 | * intervals. |
||
437 | */ |
||
438 | timestamp /= 10; |
||
439 | |||
440 | /* |
||
441 | * Subtract difference, in microseconds, between January 1, 1601 |
||
442 | * 00:00:00 UTC and January 1, 1970, 00:00:00 UTC. |
||
443 | */ |
||
444 | timestamp -= G_GUINT64_CONSTANT(11644473600000000); |
||
445 | #else |
||
446 | /* |
||
447 | * Current time, represented as seconds and microseconds since |
||
448 | * January 1, 1970, 00:00:00 UTC. |
||
449 | */ |
||
450 | gettimeofday(&now, NULL); |
||
451 | |||
452 | /* |
||
453 | * Convert to delta in microseconds. |
||
454 | */ |
||
455 | timestamp = (guint64)(now.tv_sec) * 1000000 + |
||
456 | (guint64)(now.tv_usec); |
||
457 | #endif |
||
458 | return timestamp; |
||
459 | } |
||
460 | |||
461 | static void |
||
462 | print_usage(FILE *output) |
||
463 | { |
||
464 | fprintf(output, "\nUsage: dumpcap [options] ...\n"); |
||
465 | fprintf(output, "\n"); |
||
466 | fprintf(output, "Capture interface:\n"); |
||
467 | fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback),\n" |
||
468 | " or for remote capturing, use one of these formats:\n" |
||
469 | " rpcap://<host>/<interface>\n" |
||
470 | " TCP@<host>:<port>\n"); |
||
471 | fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n"); |
||
472 | fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n"); |
||
473 | fprintf(output, " -p don't capture in promiscuous mode\n"); |
||
474 | #ifdef HAVE_PCAP_CREATE |
||
475 | fprintf(output, " -I capture in monitor mode, if available\n"); |
||
476 | #endif |
||
477 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
478 | fprintf(output, " -B <buffer size> size of kernel buffer in MiB (def: %dMiB)\n", DEFAULT_CAPTURE_BUFFER_SIZE); |
||
479 | #endif |
||
480 | fprintf(output, " -y <link type> link layer type (def: first appropriate)\n"); |
||
481 | fprintf(output, " -D print list of interfaces and exit\n"); |
||
482 | fprintf(output, " -L print list of link-layer types of iface and exit\n"); |
||
483 | #ifdef HAVE_BPF_IMAGE |
||
484 | fprintf(output, " -d print generated BPF code for capture filter\n"); |
||
485 | #endif |
||
486 | fprintf(output, " -k set channel on wifi interface:\n" |
||
487 | " <freq>,[<type>],[<center_freq1>],[<center_freq2>]\n"); |
||
488 | fprintf(output, " -S print statistics for each interface once per second\n"); |
||
489 | fprintf(output, " -M for -D, -L, and -S, produce machine-readable output\n"); |
||
490 | fprintf(output, "\n"); |
||
491 | #ifdef HAVE_PCAP_REMOTE |
||
492 | fprintf(output, "RPCAP options:\n"); |
||
493 | fprintf(output, " -r don't ignore own RPCAP traffic in capture\n"); |
||
494 | fprintf(output, " -u use UDP for RPCAP data transfer\n"); |
||
495 | fprintf(output, " -A <user>:<password> use RPCAP password authentication\n"); |
||
496 | #ifdef HAVE_PCAP_SETSAMPLING |
||
497 | fprintf(output, " -m <sampling type> use packet sampling\n"); |
||
498 | fprintf(output, " count:NUM - capture one packet of every NUM\n"); |
||
499 | fprintf(output, " timer:NUM - capture no more than 1 packet in NUM ms\n"); |
||
500 | #endif |
||
501 | #endif |
||
502 | fprintf(output, "Stop conditions:\n"); |
||
503 | fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n"); |
||
504 | fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n"); |
||
505 | fprintf(output, " filesize:NUM - stop this file after NUM KB\n"); |
||
506 | fprintf(output, " files:NUM - stop after NUM files\n"); |
||
507 | /*fprintf(output, "\n");*/ |
||
508 | fprintf(output, "Output (files):\n"); |
||
509 | fprintf(output, " -w <filename> name of file to save (def: tempfile)\n"); |
||
510 | fprintf(output, " -g enable group read access on the output file(s)\n"); |
||
511 | fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n"); |
||
512 | fprintf(output, " filesize:NUM - switch to next file after NUM KB\n"); |
||
513 | fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n"); |
||
514 | fprintf(output, " -n use pcapng format instead of pcap (default)\n"); |
||
515 | fprintf(output, " -P use libpcap format instead of pcapng\n"); |
||
516 | fprintf(output, " --capture-comment <comment>\n"); |
||
517 | fprintf(output, " add a capture comment to the output file\n"); |
||
518 | fprintf(output, " (only for pcapng)\n"); |
||
519 | fprintf(output, "\n"); |
||
520 | fprintf(output, "Miscellaneous:\n"); |
||
521 | fprintf(output, " -N <packet_limit> maximum number of packets buffered within dumpcap\n"); |
||
522 | fprintf(output, " -C <byte_limit> maximum number of bytes used for buffering packets\n"); |
||
523 | fprintf(output, " within dumpcap\n"); |
||
524 | fprintf(output, " -t use a separate thread per interface\n"); |
||
525 | fprintf(output, " -q don't report packet capture counts\n"); |
||
526 | fprintf(output, " -v print version information and exit\n"); |
||
527 | fprintf(output, " -h display this help and exit\n"); |
||
528 | fprintf(output, "\n"); |
||
529 | #ifdef __linux__ |
||
530 | fprintf(output, "WARNING: dumpcap will enable kernel BPF JIT compiler if available.\n"); |
||
531 | fprintf(output, "You might want to reset it\n"); |
||
532 | fprintf(output, "By doing \"echo 0 > /proc/sys/net/core/bpf_jit_enable\"\n"); |
||
533 | fprintf(output, "\n"); |
||
534 | #endif |
||
535 | fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcapng\n"); |
||
536 | fprintf(output, "\"Capture packets from interface eth0 until 60s passed into output.pcapng\"\n"); |
||
537 | fprintf(output, "\n"); |
||
538 | fprintf(output, "Use Ctrl-C to stop capturing at any time.\n"); |
||
539 | } |
||
540 | |||
541 | /* |
||
542 | * Report an error in command-line arguments. |
||
543 | * If we're a capture child, send a message back to the parent, otherwise |
||
544 | * just print it. |
||
545 | */ |
||
546 | static void |
||
547 | dumpcap_cmdarg_err(const char *fmt, va_list ap) |
||
548 | { |
||
549 | if (capture_child) { |
||
550 | gchar *msg; |
||
551 | /* Generate a 'special format' message back to parent */ |
||
552 | msg = g_strdup_vprintf(fmt, ap); |
||
553 | sync_pipe_errmsg_to_parent(2, msg, ""); |
||
554 | g_free(msg); |
||
555 | } else { |
||
556 | fprintf(stderr, "dumpcap: "); |
||
557 | vfprintf(stderr, fmt, ap); |
||
558 | fprintf(stderr, "\n"); |
||
559 | } |
||
560 | } |
||
561 | |||
562 | /* |
||
563 | * Report additional information for an error in command-line arguments. |
||
564 | * If we're a capture child, send a message back to the parent, otherwise |
||
565 | * just print it. |
||
566 | */ |
||
567 | static void |
||
568 | dumpcap_cmdarg_err_cont(const char *fmt, va_list ap) |
||
569 | { |
||
570 | if (capture_child) { |
||
571 | gchar *msg; |
||
572 | msg = g_strdup_vprintf(fmt, ap); |
||
573 | sync_pipe_errmsg_to_parent(2, msg, ""); |
||
574 | g_free(msg); |
||
575 | } else { |
||
576 | vfprintf(stderr, fmt, ap); |
||
577 | fprintf(stderr, "\n"); |
||
578 | } |
||
579 | } |
||
580 | |||
581 | #ifdef HAVE_LIBCAP |
||
582 | static void |
||
583 | #if 0 /* Set to enable capability debugging */ |
||
584 | /* see 'man cap_to_text()' for explanation of output */ |
||
585 | /* '=' means 'all= ' ie: no capabilities */ |
||
586 | /* '=ip' means 'all=ip' ie: all capabilities are permissible and inheritable */ |
||
587 | /* .... */ |
||
588 | print_caps(const char *pfx) { |
||
589 | cap_t caps = cap_get_proc(); |
||
590 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, |
||
591 | "%s: EUID: %d Capabilities: %s", pfx, |
||
592 | geteuid(), cap_to_text(caps, NULL)); |
||
593 | cap_free(caps); |
||
594 | #else |
||
595 | print_caps(const char *pfx _U_) { |
||
596 | #endif |
||
597 | } |
||
598 | |||
599 | static void |
||
600 | relinquish_all_capabilities(void) |
||
601 | { |
||
602 | /* Drop any and all capabilities this process may have. */ |
||
603 | /* Allowed whether or not process has any privileges. */ |
||
604 | cap_t caps = cap_init(); /* all capabilities initialized to off */ |
||
605 | print_caps("Pre-clear"); |
||
606 | if (cap_set_proc(caps)) { |
||
607 | cmdarg_err("cap_set_proc() fail return: %s", g_strerror(errno)); |
||
608 | } |
||
609 | print_caps("Post-clear"); |
||
610 | cap_free(caps); |
||
611 | } |
||
612 | #endif |
||
613 | |||
614 | static void |
||
615 | get_capture_device_open_failure_messages(const char *open_err_str, |
||
616 | const char *iface, |
||
617 | char *errmsg, size_t errmsg_len, |
||
618 | char *secondary_errmsg, |
||
619 | size_t secondary_errmsg_len) |
||
620 | { |
||
621 | #ifndef _WIN32 |
||
622 | const char *libpcap_warn; |
||
623 | static const char ppamsg[] = "can't find PPA for "; |
||
624 | #endif |
||
625 | |||
626 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
627 | "The capture session could not be initiated on interface '%s' (%s).", |
||
628 | iface, open_err_str); |
||
629 | #ifdef _WIN32 |
||
630 | if (!has_wpcap) { |
||
631 | g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, |
||
632 | "\n" |
||
633 | "In order to capture packets, WinPcap must be installed; see\n" |
||
634 | "\n" |
||
635 | " https://www.winpcap.org/\n" |
||
636 | "\n" |
||
637 | "for a downloadable version of WinPcap and for instructions on how to install\n" |
||
638 | "WinPcap."); |
||
639 | } else { |
||
640 | g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, |
||
641 | "\n" |
||
642 | "Please check that \"%s\" is the proper interface.\n" |
||
643 | "\n" |
||
644 | "\n" |
||
645 | "Help can be found on the following pages:\n" |
||
646 | "\n" |
||
647 | " https://wiki.wireshark.org/WinPcap\n" |
||
648 | " https://wiki.wireshark.org/CaptureSetup\n", |
||
649 | iface); |
||
650 | } |
||
651 | #else |
||
652 | /* If we got a "can't find PPA for X" message, warn the user (who |
||
653 | is running dumpcap on HP-UX) that they don't have a version of |
||
654 | libpcap that properly handles HP-UX (libpcap 0.6.x and later |
||
655 | versions, which properly handle HP-UX, say "can't find /dev/dlpi |
||
656 | PPA for X" rather than "can't find PPA for X"). */ |
||
657 | if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0) |
||
658 | libpcap_warn = |
||
659 | "\n\n" |
||
660 | "You are running (T)Wireshark with a version of the libpcap library\n" |
||
661 | "that doesn't handle HP-UX network devices well; this means that\n" |
||
662 | "(T)Wireshark may not be able to capture packets.\n" |
||
663 | "\n" |
||
664 | "To fix this, you should install libpcap 0.6.2, or a later version\n" |
||
665 | "of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n" |
||
666 | "packaged binary form from the Software Porting And Archive Centre\n" |
||
667 | "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n" |
||
668 | "at the URL lists a number of mirror sites."; |
||
669 | else |
||
670 | libpcap_warn = ""; |
||
671 | |||
672 | g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, |
||
673 | "Please check to make sure you have sufficient permissions, and that you have " |
||
674 | "the proper interface or pipe specified.%s", libpcap_warn); |
||
675 | #endif /* _WIN32 */ |
||
676 | } |
||
677 | |||
678 | static gboolean |
||
679 | compile_capture_filter(const char *iface, pcap_t *pcap_h, |
||
680 | struct bpf_program *fcode, const char *cfilter) |
||
681 | { |
||
682 | bpf_u_int32 netnum, netmask; |
||
683 | gchar lookup_net_err_str[PCAP_ERRBUF_SIZE]; |
||
684 | |||
685 | if (pcap_lookupnet(iface, &netnum, &netmask, lookup_net_err_str) < 0) { |
||
686 | /* |
||
687 | * Well, we can't get the netmask for this interface; it's used |
||
688 | * only for filters that check for broadcast IP addresses, so |
||
689 | * we just punt and use 0. It might be nice to warn the user, |
||
690 | * but that's a pain in a GUI application, as it'd involve popping |
||
691 | * up a message box, and it's not clear how often this would make |
||
692 | * a difference (only filters that check for IP broadcast addresses |
||
693 | * use the netmask). |
||
694 | */ |
||
695 | /*cmdarg_err( |
||
696 | "Warning: Couldn't obtain netmask info (%s).", lookup_net_err_str);*/ |
||
697 | netmask = 0; |
||
698 | } |
||
699 | |||
700 | /* |
||
701 | * Sigh. Older versions of libpcap don't properly declare the |
||
702 | * third argument to pcap_compile() as a const pointer. Cast |
||
703 | * away the warning. |
||
704 | */ |
||
705 | DIAG_OFF(cast-qual) |
||
706 | if (pcap_compile(pcap_h, fcode, (char *)cfilter, 1, netmask) < 0) |
||
707 | return FALSE; |
||
708 | DIAG_ON(cast-qual) |
||
709 | return TRUE; |
||
710 | } |
||
711 | |||
712 | #ifdef HAVE_BPF_IMAGE |
||
713 | static gboolean |
||
714 | show_filter_code(capture_options *capture_opts) |
||
715 | { |
||
716 | interface_options interface_opts; |
||
717 | pcap_t *pcap_h; |
||
718 | gchar open_err_str[PCAP_ERRBUF_SIZE]; |
||
719 | char errmsg[MSG_MAX_LENGTH+1]; |
||
720 | char secondary_errmsg[MSG_MAX_LENGTH+1]; |
||
721 | struct bpf_program fcode; |
||
722 | struct bpf_insn *insn; |
||
723 | u_int i; |
||
724 | guint j; |
||
725 | |||
726 | for (j = 0; j < capture_opts->ifaces->len; j++) { |
||
727 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, j); |
||
728 | pcap_h = open_capture_device(capture_opts, &interface_opts, |
||
729 | CAP_READ_TIMEOUT, &open_err_str); |
||
730 | if (pcap_h == NULL) { |
||
731 | /* Open failed; get messages */ |
||
732 | get_capture_device_open_failure_messages(open_err_str, |
||
733 | interface_opts.name, |
||
734 | errmsg, sizeof errmsg, |
||
735 | secondary_errmsg, |
||
736 | sizeof secondary_errmsg); |
||
737 | /* And report them */ |
||
738 | report_capture_error(errmsg, secondary_errmsg); |
||
739 | return FALSE; |
||
740 | } |
||
741 | |||
742 | /* Set the link-layer type. */ |
||
743 | if (!set_pcap_datalink(pcap_h, interface_opts.linktype, interface_opts.name, |
||
744 | errmsg, sizeof errmsg, |
||
745 | secondary_errmsg, sizeof secondary_errmsg)) { |
||
746 | pcap_close(pcap_h); |
||
747 | report_capture_error(errmsg, secondary_errmsg); |
||
748 | return FALSE; |
||
749 | } |
||
750 | |||
751 | /* OK, try to compile the capture filter. */ |
||
752 | if (!compile_capture_filter(interface_opts.name, pcap_h, &fcode, |
||
753 | interface_opts.cfilter)) { |
||
754 | pcap_close(pcap_h); |
||
755 | report_cfilter_error(capture_opts, j, errmsg); |
||
756 | return FALSE; |
||
757 | } |
||
758 | pcap_close(pcap_h); |
||
759 | |||
760 | /* Now print the filter code. */ |
||
761 | insn = fcode.bf_insns; |
||
762 | |||
763 | for (i = 0; i < fcode.bf_len; insn++, i++) |
||
764 | printf("%s\n", bpf_image(insn, i)); |
||
765 | } |
||
766 | /* If not using libcap: we now can now set euid/egid to ruid/rgid */ |
||
767 | /* to remove any suid privileges. */ |
||
768 | /* If using libcap: we can now remove NET_RAW and NET_ADMIN capabilities */ |
||
769 | /* (euid/egid have already previously been set to ruid/rgid. */ |
||
770 | /* (See comment in main() for details) */ |
||
771 | #ifndef HAVE_LIBCAP |
||
772 | relinquish_special_privs_perm(); |
||
773 | #else |
||
774 | relinquish_all_capabilities(); |
||
775 | #endif |
||
776 | if (capture_child) { |
||
777 | /* Let our parent know we succeeded. */ |
||
778 | pipe_write_block(2, SP_SUCCESS, NULL); |
||
779 | } |
||
780 | return TRUE; |
||
781 | } |
||
782 | #endif |
||
783 | |||
784 | /* |
||
785 | * capture_interface_list() is expected to do the right thing to get |
||
786 | * a list of interfaces. |
||
787 | * |
||
788 | * In most of the programs in the Wireshark suite, "the right thing" |
||
789 | * is to run dumpcap and ask it for the list, because dumpcap may |
||
790 | * be the only program in the suite with enough privileges to get |
||
791 | * the list. |
||
792 | * |
||
793 | * In dumpcap itself, however, we obviously can't run dumpcap to |
||
794 | * ask for the list. Therefore, our capture_interface_list() should |
||
795 | * just call get_interface_list(). |
||
796 | */ |
||
797 | GList * |
||
798 | capture_interface_list(int *err, char **err_str, void(*update_cb)(void) _U_) |
||
799 | { |
||
800 | return get_interface_list(err, err_str); |
||
801 | } |
||
802 | |||
803 | #define ADDRSTRLEN 46 /* Covers IPv4 & IPv6 */ |
||
804 | /* |
||
805 | * Output a machine readable list of the interfaces |
||
806 | * This list is retrieved by the sync_interface_list_open() function |
||
807 | * The actual output of this function can be viewed with the command "dumpcap -D -Z none" |
||
808 | */ |
||
809 | static void |
||
810 | print_machine_readable_interfaces(GList *if_list) |
||
811 | { |
||
812 | int i; |
||
813 | GList *if_entry; |
||
814 | if_info_t *if_info; |
||
815 | GSList *addr; |
||
816 | if_addr_t *if_addr; |
||
817 | char addr_str[ADDRSTRLEN]; |
||
818 | |||
819 | if (capture_child) { |
||
820 | /* Let our parent know we succeeded. */ |
||
821 | pipe_write_block(2, SP_SUCCESS, NULL); |
||
822 | } |
||
823 | |||
824 | i = 1; /* Interface id number */ |
||
825 | for (if_entry = g_list_first(if_list); if_entry != NULL; |
||
826 | if_entry = g_list_next(if_entry)) { |
||
827 | if_info = (if_info_t *)if_entry->data; |
||
828 | printf("%d. %s\t", i++, if_info->name); |
||
829 | |||
830 | /* |
||
831 | * Print the contents of the if_entry struct in a parseable format. |
||
832 | * Each if_entry element is tab-separated. Addresses are comma- |
||
833 | * separated. |
||
834 | */ |
||
835 | /* XXX - Make sure our description doesn't contain a tab */ |
||
836 | if (if_info->vendor_description != NULL) |
||
837 | printf("%s\t", if_info->vendor_description); |
||
838 | else |
||
839 | printf("\t"); |
||
840 | |||
841 | /* XXX - Make sure our friendly name doesn't contain a tab */ |
||
842 | if (if_info->friendly_name != NULL) |
||
843 | printf("%s\t", if_info->friendly_name); |
||
844 | else |
||
845 | printf("\t"); |
||
846 | |||
847 | printf("%i\t", if_info->type); |
||
848 | |||
849 | for (addr = g_slist_nth(if_info->addrs, 0); addr != NULL; |
||
850 | addr = g_slist_next(addr)) { |
||
851 | if (addr != g_slist_nth(if_info->addrs, 0)) |
||
852 | printf(","); |
||
853 | |||
854 | if_addr = (if_addr_t *)addr->data; |
||
855 | switch(if_addr->ifat_type) { |
||
856 | case IF_AT_IPv4: |
||
857 | if (ws_inet_ntop4(&if_addr->addr.ip4_addr, addr_str, |
||
858 | ADDRSTRLEN)) { |
||
859 | printf("%s", addr_str); |
||
860 | } else { |
||
861 | printf("<unknown IPv4>"); |
||
862 | } |
||
863 | break; |
||
864 | case IF_AT_IPv6: |
||
865 | if (ws_inet_ntop6(&if_addr->addr.ip6_addr, |
||
866 | addr_str, ADDRSTRLEN)) { |
||
867 | printf("%s", addr_str); |
||
868 | } else { |
||
869 | printf("<unknown IPv6>"); |
||
870 | } |
||
871 | break; |
||
872 | default: |
||
873 | printf("<type unknown %i>", if_addr->ifat_type); |
||
874 | } |
||
875 | } |
||
876 | |||
877 | if (if_info->loopback) |
||
878 | printf("\tloopback"); |
||
879 | else |
||
880 | printf("\tnetwork"); |
||
881 | #ifdef HAVE_EXTCAP |
||
882 | printf("\t%s", if_info->extcap); |
||
883 | #endif |
||
884 | printf("\n"); |
||
885 | } |
||
886 | } |
||
887 | |||
888 | /* |
||
889 | * If you change the machine-readable output format of this function, |
||
890 | * you MUST update capture_ifinfo.c:capture_get_if_capabilities() accordingly! |
||
891 | */ |
||
892 | static void |
||
893 | print_machine_readable_if_capabilities(if_capabilities_t *caps) |
||
894 | { |
||
895 | GList *lt_entry; |
||
896 | data_link_info_t *data_link_info; |
||
897 | const gchar *desc_str; |
||
898 | |||
899 | if (capture_child) { |
||
900 | /* Let our parent know we succeeded. */ |
||
901 | pipe_write_block(2, SP_SUCCESS, NULL); |
||
902 | } |
||
903 | |||
904 | if (caps->can_set_rfmon) |
||
905 | printf("1\n"); |
||
906 | else |
||
907 | printf("0\n"); |
||
908 | for (lt_entry = caps->data_link_types; lt_entry != NULL; |
||
909 | lt_entry = g_list_next(lt_entry)) { |
||
910 | data_link_info = (data_link_info_t *)lt_entry->data; |
||
911 | if (data_link_info->description != NULL) |
||
912 | desc_str = data_link_info->description; |
||
913 | else |
||
914 | desc_str = "(not supported)"; |
||
915 | printf("%d\t%s\t%s\n", data_link_info->dlt, data_link_info->name, |
||
916 | desc_str); |
||
917 | } |
||
918 | } |
||
919 | |||
920 | typedef struct { |
||
921 | char *name; |
||
922 | pcap_t *pch; |
||
923 | } if_stat_t; |
||
924 | |||
925 | /* Print the number of packets captured for each interface until we're killed. */ |
||
926 | static int |
||
927 | print_statistics_loop(gboolean machine_readable) |
||
928 | { |
||
929 | GList *if_list, *if_entry, *stat_list = NULL, *stat_entry; |
||
930 | if_info_t *if_info; |
||
931 | if_stat_t *if_stat; |
||
932 | int err; |
||
933 | gchar *err_str; |
||
934 | pcap_t *pch; |
||
935 | char errbuf[PCAP_ERRBUF_SIZE]; |
||
936 | struct pcap_stat ps; |
||
937 | |||
938 | if_list = get_interface_list(&err, &err_str); |
||
939 | if (if_list == NULL) { |
||
940 | if (err == 0) |
||
941 | cmdarg_err("There are no interfaces on which a capture can be done"); |
||
942 | else { |
||
943 | cmdarg_err("%s", err_str); |
||
944 | g_free(err_str); |
||
945 | } |
||
946 | return err; |
||
947 | } |
||
948 | |||
949 | for (if_entry = g_list_first(if_list); if_entry != NULL; if_entry = g_list_next(if_entry)) { |
||
950 | if_info = (if_info_t *)if_entry->data; |
||
951 | |||
952 | #ifdef __linux__ |
||
953 | /* On Linux nf* interfaces don't collect stats properly and don't allows multiple |
||
954 | * connections. We avoid collecting stats on them. |
||
955 | */ |
||
956 | if (!strncmp(if_info->name, "nf", 2)) { |
||
957 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Skipping interface %s for stats", |
||
958 | if_info->name); |
||
959 | continue; |
||
960 | } |
||
961 | #endif |
||
962 | |||
963 | #ifdef HAVE_PCAP_OPEN |
||
964 | pch = pcap_open(if_info->name, MIN_PACKET_SIZE, 0, 0, NULL, errbuf); |
||
965 | #else |
||
966 | pch = pcap_open_live(if_info->name, MIN_PACKET_SIZE, 0, 0, errbuf); |
||
967 | #endif |
||
968 | |||
969 | if (pch) { |
||
970 | if_stat = (if_stat_t *)g_malloc(sizeof(if_stat_t)); |
||
971 | if_stat->name = g_strdup(if_info->name); |
||
972 | if_stat->pch = pch; |
||
973 | stat_list = g_list_append(stat_list, if_stat); |
||
974 | } |
||
975 | } |
||
976 | |||
977 | if (!stat_list) { |
||
978 | cmdarg_err("There are no interfaces on which a capture can be done"); |
||
979 | return 2; |
||
980 | } |
||
981 | |||
982 | if (capture_child) { |
||
983 | /* Let our parent know we succeeded. */ |
||
984 | pipe_write_block(2, SP_SUCCESS, NULL); |
||
985 | } |
||
986 | |||
987 | if (!machine_readable) { |
||
988 | printf("%-15s %10s %10s\n", "Interface", "Received", |
||
989 | "Dropped"); |
||
990 | } |
||
991 | |||
992 | global_ld.go = TRUE; |
||
993 | while (global_ld.go) { |
||
994 | for (stat_entry = g_list_first(stat_list); stat_entry != NULL; stat_entry = g_list_next(stat_entry)) { |
||
995 | if_stat = (if_stat_t *)stat_entry->data; |
||
996 | pcap_stats(if_stat->pch, &ps); |
||
997 | |||
998 | if (!machine_readable) { |
||
999 | printf("%-15s %10u %10u\n", if_stat->name, |
||
1000 | ps.ps_recv, ps.ps_drop); |
||
1001 | } else { |
||
1002 | printf("%s\t%u\t%u\n", if_stat->name, |
||
1003 | ps.ps_recv, ps.ps_drop); |
||
1004 | fflush(stdout); |
||
1005 | } |
||
1006 | } |
||
1007 | #ifdef _WIN32 |
||
1008 | /* If we have a dummy signal pipe check it */ |
||
1009 | if (!signal_pipe_check_running()) { |
||
1010 | global_ld.go = FALSE; |
||
1011 | } |
||
1012 | Sleep(1 * 1000); |
||
1013 | #else |
||
1014 | sleep(1); |
||
1015 | #endif |
||
1016 | } |
||
1017 | |||
1018 | /* XXX - Not reached. Should we look for 'q' in stdin? */ |
||
1019 | for (stat_entry = g_list_first(stat_list); stat_entry != NULL; stat_entry = g_list_next(stat_entry)) { |
||
1020 | if_stat = (if_stat_t *)stat_entry->data; |
||
1021 | pcap_close(if_stat->pch); |
||
1022 | g_free(if_stat->name); |
||
1023 | g_free(if_stat); |
||
1024 | } |
||
1025 | g_list_free(stat_list); |
||
1026 | free_interface_list(if_list); |
||
1027 | |||
1028 | return 0; |
||
1029 | } |
||
1030 | |||
1031 | |||
1032 | #ifdef _WIN32 |
||
1033 | static BOOL WINAPI |
||
1034 | capture_cleanup_handler(DWORD dwCtrlType) |
||
1035 | { |
||
1036 | /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to |
||
1037 | Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT |
||
1038 | is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of |
||
1039 | like SIGTERM at least when the machine's shutting down. |
||
1040 | |||
1041 | For now, if we're running as a command rather than a capture child, |
||
1042 | we handle all but CTRL_LOGOFF_EVENT as indications that we should |
||
1043 | clean up and quit, just as we handle SIGINT, SIGHUP, and SIGTERM |
||
1044 | in that way on UN*X. |
||
1045 | |||
1046 | If we're not running as a capture child, we might be running as |
||
1047 | a service; ignore CTRL_LOGOFF_EVENT, so we keep running after the |
||
1048 | user logs out. (XXX - can we explicitly check whether we're |
||
1049 | running as a service?) */ |
||
1050 | |||
1051 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
1052 | "Console: Control signal"); |
||
1053 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, |
||
1054 | "Console: Control signal, CtrlType: %u", dwCtrlType); |
||
1055 | |||
1056 | /* Keep capture running if we're a service and a user logs off */ |
||
1057 | if (capture_child || (dwCtrlType != CTRL_LOGOFF_EVENT)) { |
||
1058 | capture_loop_stop(); |
||
1059 | return TRUE; |
||
1060 | } else { |
||
1061 | return FALSE; |
||
1062 | } |
||
1063 | } |
||
1064 | #else |
||
1065 | static void |
||
1066 | capture_cleanup_handler(int signum _U_) |
||
1067 | { |
||
1068 | /* On UN*X, we cleanly shut down the capture on SIGINT, SIGHUP, and |
||
1069 | SIGTERM. We assume that if the user wanted it to keep running |
||
1070 | after they logged out, they'd have nohupped it. */ |
||
1071 | |||
1072 | /* Note: don't call g_log() in the signal handler: if we happened to be in |
||
1073 | * g_log() in process context when the signal came in, g_log will detect |
||
1074 | * the "recursion" and abort. |
||
1075 | */ |
||
1076 | |||
1077 | capture_loop_stop(); |
||
1078 | } |
||
1079 | #endif |
||
1080 | |||
1081 | |||
1082 | static void |
||
1083 | report_capture_count(gboolean reportit) |
||
1084 | { |
||
1085 | /* Don't print this if we're a capture child. */ |
||
1086 | if (!capture_child && reportit) { |
||
1087 | fprintf(stderr, "\rPackets captured: %d\n", global_ld.packet_count); |
||
1088 | /* stderr could be line buffered */ |
||
1089 | fflush(stderr); |
||
1090 | } |
||
1091 | } |
||
1092 | |||
1093 | |||
1094 | #ifdef SIGINFO |
||
1095 | static void |
||
1096 | report_counts_for_siginfo(void) |
||
1097 | { |
||
1098 | report_capture_count(quiet); |
||
1099 | infoprint = FALSE; /* we just reported it */ |
||
1100 | } |
||
1101 | |||
1102 | static void |
||
1103 | report_counts_siginfo(int signum _U_) |
||
1104 | { |
||
1105 | int sav_errno = errno; |
||
1106 | |||
1107 | /* If we've been told to delay printing, just set a flag asking |
||
1108 | that we print counts (if we're supposed to), otherwise print |
||
1109 | the count of packets captured (if we're supposed to). */ |
||
1110 | if (infodelay) |
||
1111 | infoprint = TRUE; |
||
1112 | else |
||
1113 | report_counts_for_siginfo(); |
||
1114 | errno = sav_errno; |
||
1115 | } |
||
1116 | #endif /* SIGINFO */ |
||
1117 | |||
1118 | static void |
||
1119 | exit_main(int status) |
||
1120 | { |
||
1121 | #ifdef _WIN32 |
||
1122 | /* Shutdown windows sockets */ |
||
1123 | WSACleanup(); |
||
1124 | |||
1125 | /* can be helpful for debugging */ |
||
1126 | #ifdef DEBUG_DUMPCAP |
||
1127 | printf("Press any key\n"); |
||
1128 | _getch(); |
||
1129 | #endif |
||
1130 | |||
1131 | #endif /* _WIN32 */ |
||
1132 | |||
1133 | exit(status); |
||
1134 | } |
||
1135 | |||
1136 | #ifdef HAVE_LIBCAP |
||
1137 | /* |
||
1138 | * If we were linked with libcap (not related to libpcap), make sure we have |
||
1139 | * CAP_NET_ADMIN and CAP_NET_RAW, then relinquish our permissions. |
||
1140 | * (See comment in main() for details) |
||
1141 | */ |
||
1142 | static void |
||
1143 | relinquish_privs_except_capture(void) |
||
1144 | { |
||
1145 | /* If 'started_with_special_privs' (ie: suid) then enable for |
||
1146 | * ourself the NET_ADMIN and NET_RAW capabilities and then |
||
1147 | * drop our suid privileges. |
||
1148 | * |
||
1149 | * CAP_NET_ADMIN: Promiscuous mode and a truckload of other |
||
1150 | * stuff we don't need (and shouldn't have). |
||
1151 | * CAP_NET_RAW: Packet capture (raw sockets). |
||
1152 | */ |
||
1153 | |||
1154 | if (started_with_special_privs()) { |
||
1155 | cap_value_t cap_list[2] = { CAP_NET_ADMIN, CAP_NET_RAW }; |
||
1156 | int cl_len = sizeof(cap_list) / sizeof(cap_value_t); |
||
1157 | |||
1158 | cap_t caps = cap_init(); /* all capabilities initialized to off */ |
||
1159 | |||
1160 | print_caps("Pre drop, pre set"); |
||
1161 | |||
1162 | if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) { |
||
1163 | cmdarg_err("prctl() fail return: %s", g_strerror(errno)); |
||
1164 | } |
||
1165 | |||
1166 | cap_set_flag(caps, CAP_PERMITTED, cl_len, cap_list, CAP_SET); |
||
1167 | cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, CAP_SET); |
||
1168 | |||
1169 | if (cap_set_proc(caps)) { |
||
1170 | cmdarg_err("cap_set_proc() fail return: %s", g_strerror(errno)); |
||
1171 | } |
||
1172 | print_caps("Pre drop, post set"); |
||
1173 | |||
1174 | relinquish_special_privs_perm(); |
||
1175 | |||
1176 | print_caps("Post drop, pre set"); |
||
1177 | cap_set_flag(caps, CAP_EFFECTIVE, cl_len, cap_list, CAP_SET); |
||
1178 | if (cap_set_proc(caps)) { |
||
1179 | cmdarg_err("cap_set_proc() fail return: %s", g_strerror(errno)); |
||
1180 | } |
||
1181 | print_caps("Post drop, post set"); |
||
1182 | |||
1183 | cap_free(caps); |
||
1184 | } |
||
1185 | } |
||
1186 | |||
1187 | #endif /* HAVE_LIBCAP */ |
||
1188 | |||
1189 | /* Take care of byte order in the libpcap headers read from pipes. |
||
1190 | * (function taken from wiretap/libpcap.c) */ |
||
1191 | static void |
||
1192 | cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr) |
||
1193 | { |
||
1194 | if (byte_swapped) { |
||
1195 | /* Byte-swap the record header fields. */ |
||
1196 | rechdr->ts_sec = GUINT32_SWAP_LE_BE(rechdr->ts_sec); |
||
1197 | rechdr->ts_usec = GUINT32_SWAP_LE_BE(rechdr->ts_usec); |
||
1198 | rechdr->incl_len = GUINT32_SWAP_LE_BE(rechdr->incl_len); |
||
1199 | rechdr->orig_len = GUINT32_SWAP_LE_BE(rechdr->orig_len); |
||
1200 | } |
||
1201 | |||
1202 | /* In file format version 2.3, the "incl_len" and "orig_len" fields were |
||
1203 | swapped, in order to match the BPF header layout. |
||
1204 | |||
1205 | Unfortunately, some files were, according to a comment in the "libpcap" |
||
1206 | source, written with version 2.3 in their headers but without the |
||
1207 | interchanged fields, so if "incl_len" is greater than "orig_len" - which |
||
1208 | would make no sense - we assume that we need to swap them. */ |
||
1209 | if (hdr->version_major == 2 && |
||
1210 | (hdr->version_minor < 3 || |
||
1211 | (hdr->version_minor == 3 && rechdr->incl_len > rechdr->orig_len))) { |
||
1212 | guint32 temp; |
||
1213 | |||
1214 | temp = rechdr->orig_len; |
||
1215 | rechdr->orig_len = rechdr->incl_len; |
||
1216 | rechdr->incl_len = temp; |
||
1217 | } |
||
1218 | } |
||
1219 | |||
1220 | /* Wrapper: distinguish between recv/read if we're reading on Windows, |
||
1221 | * or just read(). |
||
1222 | */ |
||
1223 | static ssize_t |
||
1224 | cap_pipe_read(int pipe_fd, char *buf, size_t sz, gboolean from_socket _U_) |
||
1225 | { |
||
1226 | #ifdef _WIN32 |
||
1227 | if (from_socket) { |
||
1228 | return recv(pipe_fd, buf, (int)sz, 0); |
||
1229 | } else { |
||
1230 | return -1; |
||
1231 | } |
||
1232 | #else |
||
1233 | return ws_read(pipe_fd, buf, sz); |
||
1234 | #endif |
||
1235 | } |
||
1236 | |||
1237 | #if defined(_WIN32) |
||
1238 | /* |
||
1239 | * Thread function that reads from a pipe and pushes the data |
||
1240 | * to the main application thread. |
||
1241 | */ |
||
1242 | /* |
||
1243 | * XXX Right now we use async queues for basic signaling. The main thread |
||
1244 | * sets cap_pipe_buf and cap_bytes_to_read, then pushes an item onto |
||
1245 | * cap_pipe_pending_q which triggers a read in the cap_pipe_read thread. |
||
1246 | * Iff the read is successful cap_pipe_read pushes an item onto |
||
1247 | * cap_pipe_done_q, otherwise an error is signaled. No data is passed in |
||
1248 | * the queues themselves (yet). |
||
1249 | * |
||
1250 | * We might want to move some of the cap_pipe_dispatch logic here so that |
||
1251 | * we can let cap_thread_read run independently, queuing up multiple reads |
||
1252 | * for the main thread (and possibly get rid of cap_pipe_read_mtx). |
||
1253 | */ |
||
1254 | static void *cap_thread_read(void *arg) |
||
1255 | { |
||
1256 | pcap_options *pcap_opts; |
||
1257 | #ifdef _WIN32 |
||
1258 | BOOL res; |
||
1259 | DWORD b, last_err, bytes_read; |
||
1260 | #else /* _WIN32 */ |
||
1261 | size_t bytes_read; |
||
1262 | int b; |
||
1263 | #endif /* _WIN32 */ |
||
1264 | |||
1265 | pcap_opts = (pcap_options *)arg; |
||
1266 | while (pcap_opts->cap_pipe_err == PIPOK) { |
||
1267 | g_async_queue_pop(pcap_opts->cap_pipe_pending_q); /* Wait for our cue (ahem) from the main thread */ |
||
1268 | g_mutex_lock(pcap_opts->cap_pipe_read_mtx); |
||
1269 | bytes_read = 0; |
||
1270 | while (bytes_read < pcap_opts->cap_pipe_bytes_to_read) { |
||
1271 | if ((pcap_opts->from_cap_socket) |
||
1272 | #ifndef _WIN32 |
||
1273 | || 1 |
||
1274 | #endif |
||
1275 | ) |
||
1276 | { |
||
1277 | b = cap_pipe_read(pcap_opts->cap_pipe_fd, pcap_opts->cap_pipe_buf+bytes_read, |
||
1278 | pcap_opts->cap_pipe_bytes_to_read - bytes_read, pcap_opts->from_cap_socket); |
||
1279 | if (b <= 0) { |
||
1280 | if (b == 0) { |
||
1281 | pcap_opts->cap_pipe_err = PIPEOF; |
||
1282 | bytes_read = 0; |
||
1283 | break; |
||
1284 | } else { |
||
1285 | pcap_opts->cap_pipe_err = PIPERR; |
||
1286 | bytes_read = -1; |
||
1287 | break; |
||
1288 | } |
||
1289 | } else { |
||
1290 | bytes_read += b; |
||
1291 | } |
||
1292 | } |
||
1293 | #ifdef _WIN32 |
||
1294 | else |
||
1295 | { |
||
1296 | /* If we try to use read() on a named pipe on Windows with partial |
||
1297 | * data it appears to return EOF. |
||
1298 | */ |
||
1299 | res = ReadFile(pcap_opts->cap_pipe_h, pcap_opts->cap_pipe_buf+bytes_read, |
||
1300 | pcap_opts->cap_pipe_bytes_to_read - bytes_read, |
||
1301 | &b, NULL); |
||
1302 | |||
1303 | bytes_read += b; |
||
1304 | if (!res) { |
||
1305 | last_err = GetLastError(); |
||
1306 | if (last_err == ERROR_MORE_DATA) { |
||
1307 | continue; |
||
1308 | } else if (last_err == ERROR_HANDLE_EOF || last_err == ERROR_BROKEN_PIPE || last_err == ERROR_PIPE_NOT_CONNECTED) { |
||
1309 | pcap_opts->cap_pipe_err = PIPEOF; |
||
1310 | bytes_read = 0; |
||
1311 | break; |
||
1312 | } |
||
1313 | pcap_opts->cap_pipe_err = PIPERR; |
||
1314 | bytes_read = -1; |
||
1315 | break; |
||
1316 | } else if (b == 0 && pcap_opts->cap_pipe_bytes_to_read > 0) { |
||
1317 | pcap_opts->cap_pipe_err = PIPEOF; |
||
1318 | bytes_read = 0; |
||
1319 | break; |
||
1320 | } |
||
1321 | } |
||
1322 | #endif /*_WIN32 */ |
||
1323 | } |
||
1324 | pcap_opts->cap_pipe_bytes_read = bytes_read; |
||
1325 | if (pcap_opts->cap_pipe_bytes_read >= pcap_opts->cap_pipe_bytes_to_read) { |
||
1326 | g_async_queue_push(pcap_opts->cap_pipe_done_q, pcap_opts->cap_pipe_buf); /* Any non-NULL value will do */ |
||
1327 | } |
||
1328 | g_mutex_unlock(pcap_opts->cap_pipe_read_mtx); |
||
1329 | } |
||
1330 | return NULL; |
||
1331 | } |
||
1332 | #endif |
||
1333 | |||
1334 | /* Provide select() functionality for a single file descriptor |
||
1335 | * on UNIX/POSIX. Windows uses cap_pipe_read via a thread. |
||
1336 | * |
||
1337 | * Returns the same values as select. |
||
1338 | */ |
||
1339 | static int |
||
1340 | cap_pipe_select(int pipe_fd) |
||
1341 | { |
||
1342 | fd_set rfds; |
||
1343 | struct timeval timeout; |
||
1344 | |||
1345 | FD_ZERO(&rfds); |
||
1346 | FD_SET(pipe_fd, &rfds); |
||
1347 | |||
1348 | timeout.tv_sec = PIPE_READ_TIMEOUT / 1000000; |
||
1349 | timeout.tv_usec = PIPE_READ_TIMEOUT % 1000000; |
||
1350 | |||
1351 | return select(pipe_fd+1, &rfds, NULL, NULL, &timeout); |
||
1352 | } |
||
1353 | |||
1354 | #define DEF_TCP_PORT 19000 |
||
1355 | |||
1356 | static int |
||
1357 | cap_open_socket(char *pipename, pcap_options *pcap_opts, char *errmsg, int errmsgl) |
||
1358 | { |
||
1359 | char *sockname = pipename + 4; |
||
1360 | struct sockaddr_in sa; |
||
1361 | char buf[16]; |
||
1362 | char *p; |
||
1363 | unsigned long port; |
||
1364 | size_t len; |
||
1365 | int fd; |
||
1366 | |||
1367 | memset(&sa, 0, sizeof(sa)); |
||
1368 | |||
1369 | p = strchr(sockname, ':'); |
||
1370 | if (p == NULL) { |
||
1371 | len = strlen(sockname); |
||
1372 | port = DEF_TCP_PORT; |
||
1373 | } |
||
1374 | else { |
||
1375 | len = p - sockname; |
||
1376 | port = strtoul(p + 1, &p, 10); |
||
1377 | if (*p || port > 65535) { |
||
1378 | goto fail_invalid; |
||
1379 | } |
||
1380 | } |
||
1381 | |||
1382 | if (len > 15) { |
||
1383 | goto fail_invalid; |
||
1384 | } |
||
1385 | |||
1386 | g_snprintf ( buf,(gulong)len + 1, "%s", sockname ); |
||
1387 | buf[len] = '\0'; |
||
1388 | if (!ws_inet_pton4(buf, (guint32 *)&sa.sin_addr)) { |
||
1389 | goto fail_invalid; |
||
1390 | } |
||
1391 | |||
1392 | sa.sin_family = AF_INET; |
||
1393 | sa.sin_port = g_htons((u_short)port); |
||
1394 | |||
1395 | if (((fd = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) || |
||
1396 | (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)) { |
||
1397 | #ifdef _WIN32 |
||
1398 | LPTSTR errorText = NULL; |
||
1399 | int lastError; |
||
1400 | |||
1401 | lastError = WSAGetLastError(); |
||
1402 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | |
||
1403 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
||
1404 | FORMAT_MESSAGE_IGNORE_INSERTS, |
||
1405 | NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
||
1406 | (LPTSTR)&errorText, 0, NULL); |
||
1407 | #endif |
||
1408 | g_snprintf(errmsg, errmsgl, |
||
1409 | "The capture session could not be initiated due to the socket error: \n" |
||
1410 | #ifdef _WIN32 |
||
1411 | " %d: %S", lastError, errorText ? (char *)errorText : "Unknown"); |
||
1412 | if (errorText) |
||
1413 | LocalFree(errorText); |
||
1414 | #else |
||
1415 | " %d: %s", errno, g_strerror(errno)); |
||
1416 | #endif |
||
1417 | pcap_opts->cap_pipe_err = PIPERR; |
||
1418 | |||
1419 | if (fd >= 0) |
||
1420 | cap_pipe_close(fd, TRUE); |
||
1421 | return -1; |
||
1422 | } |
||
1423 | |||
1424 | pcap_opts->from_cap_socket = TRUE; |
||
1425 | return fd; |
||
1426 | |||
1427 | fail_invalid: |
||
1428 | g_snprintf(errmsg, errmsgl, |
||
1429 | "The capture session could not be initiated because\n" |
||
1430 | "\"%s\" is not a valid socket specification", pipename); |
||
1431 | pcap_opts->cap_pipe_err = PIPERR; |
||
1432 | return -1; |
||
1433 | } |
||
1434 | |||
1435 | /* Wrapper: distinguish between closesocket on Windows; use ws_close |
||
1436 | * otherwise. |
||
1437 | */ |
||
1438 | static void |
||
1439 | cap_pipe_close(int pipe_fd, gboolean from_socket _U_) |
||
1440 | { |
||
1441 | #ifdef _WIN32 |
||
1442 | if (from_socket) { |
||
1443 | closesocket(pipe_fd); |
||
1444 | } |
||
1445 | #else |
||
1446 | ws_close(pipe_fd); |
||
1447 | #endif |
||
1448 | } |
||
1449 | |||
1450 | /* Mimic pcap_open_live() for pipe captures |
||
1451 | |||
1452 | * We check if "pipename" is "-" (stdin), a AF_UNIX socket, or a FIFO, |
||
1453 | * open it, and read the header. |
||
1454 | * |
||
1455 | * N.B. : we can't read the libpcap formats used in RedHat 6.1 or SuSE 6.3 |
||
1456 | * because we can't seek on pipes (see wiretap/libpcap.c for details) */ |
||
1457 | static void |
||
1458 | cap_pipe_open_live(char *pipename, |
||
1459 | pcap_options *pcap_opts, |
||
1460 | struct pcap_hdr *hdr, |
||
1461 | char *errmsg, int errmsgl) |
||
1462 | { |
||
1463 | #ifndef _WIN32 |
||
1464 | ws_statb64 pipe_stat; |
||
1465 | struct sockaddr_un sa; |
||
1466 | #else /* _WIN32 */ |
||
1467 | char *pncopy, *pos; |
||
1468 | wchar_t *err_str; |
||
1469 | #ifdef HAVE_EXTCAP |
||
1470 | char* extcap_pipe_name; |
||
1471 | #endif |
||
1472 | #endif |
||
1473 | #ifdef HAVE_EXTCAP |
||
1474 | gboolean extcap_pipe = FALSE; |
||
1475 | interface_options interface_opts; |
||
1476 | #endif |
||
1477 | ssize_t b; |
||
1478 | int fd = -1, sel_ret; |
||
1479 | size_t bytes_read; |
||
1480 | guint32 magic = 0; |
||
1481 | pcap_opts->cap_pipe_fd = -1; |
||
1482 | #ifdef _WIN32 |
||
1483 | pcap_opts->cap_pipe_h = INVALID_HANDLE_VALUE; |
||
1484 | #endif |
||
1485 | |||
1486 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: %s", pipename); |
||
1487 | |||
1488 | /* |
||
1489 | * XXX - this blocks until a pcap per-file header has been written to |
||
1490 | * the pipe, so it could block indefinitely. |
||
1491 | */ |
||
1492 | if (strcmp(pipename, "-") == 0) { |
||
1493 | #ifndef _WIN32 |
||
1494 | fd = 0; /* read from stdin */ |
||
1495 | #else /* _WIN32 */ |
||
1496 | pcap_opts->cap_pipe_h = GetStdHandle(STD_INPUT_HANDLE); |
||
1497 | #endif /* _WIN32 */ |
||
1498 | } else if (!strncmp(pipename, "TCP@", 4)) { |
||
1499 | if ((fd = cap_open_socket(pipename, pcap_opts, errmsg, errmsgl)) < 0) { |
||
1500 | return; |
||
1501 | } |
||
1502 | } else { |
||
1503 | |||
1504 | #ifdef HAVE_EXTCAP |
||
1505 | interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, 0); |
||
1506 | #endif |
||
1507 | |||
1508 | #ifndef _WIN32 |
||
1509 | #ifdef HAVE_EXTCAP |
||
1510 | if ( g_strrstr(interface_opts.name, EXTCAP_PIPE_PREFIX) != NULL ) |
||
1511 | extcap_pipe = TRUE; |
||
1512 | #endif |
||
1513 | |||
1514 | if (ws_stat64(pipename, &pipe_stat) < 0) { |
||
1515 | if (errno == ENOENT || errno == ENOTDIR) |
||
1516 | pcap_opts->cap_pipe_err = PIPNEXIST; |
||
1517 | else { |
||
1518 | g_snprintf(errmsg, errmsgl, |
||
1519 | "The capture session could not be initiated " |
||
1520 | "due to error getting information on pipe/socket: %s.", g_strerror(errno)); |
||
1521 | pcap_opts->cap_pipe_err = PIPERR; |
||
1522 | } |
||
1523 | return; |
||
1524 | } |
||
1525 | if (S_ISFIFO(pipe_stat.st_mode)) { |
||
1526 | fd = ws_open(pipename, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */); |
||
1527 | if (fd == -1) { |
||
1528 | g_snprintf(errmsg, errmsgl, |
||
1529 | "The capture session could not be initiated " |
||
1530 | "due to error on pipe open: %s.", g_strerror(errno)); |
||
1531 | pcap_opts->cap_pipe_err = PIPERR; |
||
1532 | return; |
||
1533 | } |
||
1534 | } else if (S_ISSOCK(pipe_stat.st_mode)) { |
||
1535 | fd = socket(AF_UNIX, SOCK_STREAM, 0); |
||
1536 | if (fd == -1) { |
||
1537 | g_snprintf(errmsg, errmsgl, |
||
1538 | "The capture session could not be initiated " |
||
1539 | "due to error on socket create: %s.", g_strerror(errno)); |
||
1540 | pcap_opts->cap_pipe_err = PIPERR; |
||
1541 | return; |
||
1542 | } |
||
1543 | sa.sun_family = AF_UNIX; |
||
1544 | /* |
||
1545 | * The Single UNIX Specification says: |
||
1546 | * |
||
1547 | * The size of sun_path has intentionally been left undefined. |
||
1548 | * This is because different implementations use different sizes. |
||
1549 | * For example, 4.3 BSD uses a size of 108, and 4.4 BSD uses a size |
||
1550 | * of 104. Since most implementations originate from BSD versions, |
||
1551 | * the size is typically in the range 92 to 108. |
||
1552 | * |
||
1553 | * Applications should not assume a particular length for sun_path |
||
1554 | * or assume that it can hold {_POSIX_PATH_MAX} bytes (256). |
||
1555 | * |
||
1556 | * It also says |
||
1557 | * |
||
1558 | * The <sys/un.h> header shall define the sockaddr_un structure, |
||
1559 | * which shall include at least the following members: |
||
1560 | * |
||
1561 | * sa_family_t sun_family Address family. |
||
1562 | * char sun_path[] Socket pathname. |
||
1563 | * |
||
1564 | * so we assume that it's an array, with a specified size, |
||
1565 | * and that the size reflects the maximum path length. |
||
1566 | */ |
||
1567 | if (g_strlcpy(sa.sun_path, pipename, sizeof sa.sun_path) > sizeof sa.sun_path) { |
||
1568 | /* Path name too long */ |
||
1569 | g_snprintf(errmsg, errmsgl, |
||
1570 | "The capture session coud not be initiated " |
||
1571 | "due to error on socket connect: Path name too long."); |
||
1572 | pcap_opts->cap_pipe_err = PIPERR; |
||
1573 | ws_close(fd); |
||
1574 | return; |
||
1575 | } |
||
1576 | b = connect(fd, (struct sockaddr *)&sa, sizeof sa); |
||
1577 | if (b == -1) { |
||
1578 | g_snprintf(errmsg, errmsgl, |
||
1579 | "The capture session coud not be initiated " |
||
1580 | "due to error on socket connect: %s.", g_strerror(errno)); |
||
1581 | pcap_opts->cap_pipe_err = PIPERR; |
||
1582 | ws_close(fd); |
||
1583 | return; |
||
1584 | } |
||
1585 | } else { |
||
1586 | if (S_ISCHR(pipe_stat.st_mode)) { |
||
1587 | /* |
||
1588 | * Assume the user specified an interface on a system where |
||
1589 | * interfaces are in /dev. Pretend we haven't seen it. |
||
1590 | */ |
||
1591 | pcap_opts->cap_pipe_err = PIPNEXIST; |
||
1592 | } else { |
||
1593 | g_snprintf(errmsg, errmsgl, |
||
1594 | "The capture session could not be initiated because\n" |
||
1595 | "\"%s\" is neither an interface nor a socket nor a pipe.", pipename); |
||
1596 | pcap_opts->cap_pipe_err = PIPERR; |
||
1597 | } |
||
1598 | return; |
||
1599 | } |
||
1600 | |||
1601 | #else /* _WIN32 */ |
||
1602 | #define PIPE_STR "\\pipe\\" |
||
1603 | /* Under Windows, named pipes _must_ have the form |
||
1604 | * "\\<server>\pipe\<pipename>". <server> may be "." for localhost. |
||
1605 | */ |
||
1606 | pncopy = g_strdup(pipename); |
||
1607 | if ( (pos=strstr(pncopy, "\\\\")) == pncopy) { |
||
1608 | pos = strchr(pncopy + 3, '\\'); |
||
1609 | if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0) |
||
1610 | pos = NULL; |
||
1611 | } |
||
1612 | |||
1613 | g_free(pncopy); |
||
1614 | |||
1615 | if (!pos) { |
||
1616 | g_snprintf(errmsg, errmsgl, |
||
1617 | "The capture session could not be initiated because\n" |
||
1618 | "\"%s\" is neither an interface nor a pipe.", pipename); |
||
1619 | pcap_opts->cap_pipe_err = PIPNEXIST; |
||
1620 | return; |
||
1621 | } |
||
1622 | #ifdef HAVE_EXTCAP |
||
1623 | extcap_pipe_name = g_strconcat("\\\\.\\pipe\\", EXTCAP_PIPE_PREFIX, NULL); |
||
1624 | extcap_pipe = strstr(interface_opts.name, extcap_pipe_name) ? TRUE : FALSE; |
||
1625 | g_free(extcap_pipe_name); |
||
1626 | #endif |
||
1627 | |||
1628 | /* Wait for the pipe to appear */ |
||
1629 | while (1) { |
||
1630 | |||
1631 | #ifdef HAVE_EXTCAP |
||
1632 | if(extcap_pipe) |
||
1633 | pcap_opts->cap_pipe_h = GetStdHandle(STD_INPUT_HANDLE); |
||
1634 | else |
||
1635 | #endif |
||
1636 | pcap_opts->cap_pipe_h = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL, |
||
1637 | OPEN_EXISTING, 0, NULL); |
||
1638 | |||
1639 | if (pcap_opts->cap_pipe_h != INVALID_HANDLE_VALUE) |
||
1640 | break; |
||
1641 | |||
1642 | if (GetLastError() != ERROR_PIPE_BUSY) { |
||
1643 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
||
1644 | NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); |
||
1645 | g_snprintf(errmsg, errmsgl, |
||
1646 | "The capture session on \"%s\" could not be started " |
||
1647 | "due to error on pipe open: %s (error %d).", |
||
1648 | pipename, utf_16to8(err_str), GetLastError()); |
||
1649 | LocalFree(err_str); |
||
1650 | pcap_opts->cap_pipe_err = PIPERR; |
||
1651 | return; |
||
1652 | } |
||
1653 | |||
1654 | if (!WaitNamedPipe(utf_8to16(pipename), 30 * 1000)) { |
||
1655 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
||
1656 | NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); |
||
1657 | g_snprintf(errmsg, errmsgl, |
||
1658 | "The capture session on \"%s\" timed out during " |
||
1659 | "pipe open: %s (error %d).", |
||
1660 | pipename, utf_16to8(err_str), GetLastError()); |
||
1661 | LocalFree(err_str); |
||
1662 | pcap_opts->cap_pipe_err = PIPERR; |
||
1663 | return; |
||
1664 | } |
||
1665 | } |
||
1666 | #endif /* _WIN32 */ |
||
1667 | } |
||
1668 | |||
1669 | pcap_opts->from_cap_pipe = TRUE; |
||
1670 | |||
1671 | #ifdef _WIN32 |
||
1672 | if (pcap_opts->from_cap_socket) |
||
1673 | #endif |
||
1674 | { |
||
1675 | /* read the pcap header */ |
||
1676 | bytes_read = 0; |
||
1677 | while (bytes_read < sizeof magic) { |
||
1678 | if (fd == -1) { |
||
1679 | g_snprintf(errmsg, errmsgl, "Invalid file descriptor."); |
||
1680 | goto error; |
||
1681 | } |
||
1682 | |||
1683 | sel_ret = cap_pipe_select(fd); |
||
1684 | if (sel_ret < 0) { |
||
1685 | g_snprintf(errmsg, errmsgl, |
||
1686 | "Unexpected error from select: %s.", g_strerror(errno)); |
||
1687 | goto error; |
||
1688 | } else if (sel_ret > 0) { |
||
1689 | b = cap_pipe_read(fd, ((char *)&magic)+bytes_read, |
||
1690 | sizeof magic-bytes_read, |
||
1691 | pcap_opts->from_cap_socket); |
||
1692 | #ifdef HAVE_EXTCAP |
||
1693 | /* jump messaging, if extcap had an error, stderr will provide the correct message */ |
||
1694 | if (extcap_pipe && b <= 0) |
||
1695 | goto error; |
||
1696 | #endif |
||
1697 | if (b <= 0) { |
||
1698 | if (b == 0) |
||
1699 | g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open."); |
||
1700 | else |
||
1701 | g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s.", |
||
1702 | g_strerror(errno)); |
||
1703 | goto error; |
||
1704 | } |
||
1705 | bytes_read += b; |
||
1706 | } |
||
1707 | } |
||
1708 | } |
||
1709 | #ifdef _WIN32 |
||
1710 | else { |
||
1711 | #if GLIB_CHECK_VERSION(2,31,0) |
||
1712 | g_thread_new("cap_pipe_open_live", &cap_thread_read, pcap_opts); |
||
1713 | #else |
||
1714 | g_thread_create(&cap_thread_read, pcap_opts, FALSE, NULL); |
||
1715 | #endif |
||
1716 | |||
1717 | pcap_opts->cap_pipe_buf = (char *) &magic; |
||
1718 | pcap_opts->cap_pipe_bytes_read = 0; |
||
1719 | pcap_opts->cap_pipe_bytes_to_read = sizeof(magic); |
||
1720 | /* We don't have to worry about cap_pipe_read_mtx here */ |
||
1721 | g_async_queue_push(pcap_opts->cap_pipe_pending_q, pcap_opts->cap_pipe_buf); |
||
1722 | g_async_queue_pop(pcap_opts->cap_pipe_done_q); |
||
1723 | /* jump messaging, if extcap had an error, stderr will provide the correct message */ |
||
1724 | if (pcap_opts->cap_pipe_bytes_read <= 0 && extcap_pipe) |
||
1725 | goto error; |
||
1726 | |||
1727 | if (pcap_opts->cap_pipe_bytes_read <= 0) { |
||
1728 | if (pcap_opts->cap_pipe_bytes_read == 0) |
||
1729 | g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open."); |
||
1730 | else |
||
1731 | g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s.", |
||
1732 | g_strerror(errno)); |
||
1733 | goto error; |
||
1734 | } |
||
1735 | } |
||
1736 | #endif |
||
1737 | |||
1738 | switch (magic) { |
||
1739 | case PCAP_MAGIC: |
||
1740 | case PCAP_NSEC_MAGIC: |
||
1741 | /* Host that wrote it has our byte order, and was running |
||
1742 | a program using either standard or ss990417 libpcap. */ |
||
1743 | pcap_opts->cap_pipe_byte_swapped = FALSE; |
||
1744 | pcap_opts->cap_pipe_modified = FALSE; |
||
1745 | pcap_opts->ts_nsec = magic == PCAP_NSEC_MAGIC; |
||
1746 | break; |
||
1747 | case PCAP_MODIFIED_MAGIC: |
||
1748 | /* Host that wrote it has our byte order, but was running |
||
1749 | a program using either ss990915 or ss991029 libpcap. */ |
||
1750 | pcap_opts->cap_pipe_byte_swapped = FALSE; |
||
1751 | pcap_opts->cap_pipe_modified = TRUE; |
||
1752 | break; |
||
1753 | case PCAP_SWAPPED_MAGIC: |
||
1754 | case PCAP_SWAPPED_NSEC_MAGIC: |
||
1755 | /* Host that wrote it has a byte order opposite to ours, |
||
1756 | and was running a program using either standard or |
||
1757 | ss990417 libpcap. */ |
||
1758 | pcap_opts->cap_pipe_byte_swapped = TRUE; |
||
1759 | pcap_opts->cap_pipe_modified = FALSE; |
||
1760 | pcap_opts->ts_nsec = magic == PCAP_SWAPPED_NSEC_MAGIC; |
||
1761 | break; |
||
1762 | case PCAP_SWAPPED_MODIFIED_MAGIC: |
||
1763 | /* Host that wrote it out has a byte order opposite to |
||
1764 | ours, and was running a program using either ss990915 |
||
1765 | or ss991029 libpcap. */ |
||
1766 | pcap_opts->cap_pipe_byte_swapped = TRUE; |
||
1767 | pcap_opts->cap_pipe_modified = TRUE; |
||
1768 | break; |
||
1769 | case BLOCK_TYPE_SHB: |
||
1770 | /* This isn't pcap, it's pcapng. We don't yet support |
||
1771 | reading it. */ |
||
1772 | g_snprintf(errmsg, errmsgl, "Capturing from a pipe doesn't support pcapng format."); |
||
1773 | goto error; |
||
1774 | default: |
||
1775 | /* Not a pcap type we know about, or not pcap at all. */ |
||
1776 | g_snprintf(errmsg, errmsgl, "Unrecognized libpcap format or not libpcap data."); |
||
1777 | goto error; |
||
1778 | } |
||
1779 | |||
1780 | #ifdef _WIN32 |
||
1781 | if (pcap_opts->from_cap_socket) |
||
1782 | #endif |
||
1783 | { |
||
1784 | /* Read the rest of the header */ |
||
1785 | bytes_read = 0; |
||
1786 | while (bytes_read < sizeof(struct pcap_hdr)) { |
||
1787 | sel_ret = cap_pipe_select(fd); |
||
1788 | if (sel_ret < 0) { |
||
1789 | g_snprintf(errmsg, errmsgl, |
||
1790 | "Unexpected error from select: %s.", g_strerror(errno)); |
||
1791 | goto error; |
||
1792 | } else if (sel_ret > 0) { |
||
1793 | b = cap_pipe_read(fd, ((char *)hdr)+bytes_read, |
||
1794 | sizeof(struct pcap_hdr) - bytes_read, |
||
1795 | pcap_opts->from_cap_socket); |
||
1796 | if (b <= 0) { |
||
1797 | if (b == 0) |
||
1798 | g_snprintf(errmsg, errmsgl, "End of file on pipe header during open."); |
||
1799 | else |
||
1800 | g_snprintf(errmsg, errmsgl, "Error on pipe header during open: %s.", |
||
1801 | g_strerror(errno)); |
||
1802 | goto error; |
||
1803 | } |
||
1804 | bytes_read += b; |
||
1805 | } |
||
1806 | } |
||
1807 | } |
||
1808 | #ifdef _WIN32 |
||
1809 | else { |
||
1810 | pcap_opts->cap_pipe_buf = (char *) hdr; |
||
1811 | pcap_opts->cap_pipe_bytes_read = 0; |
||
1812 | pcap_opts->cap_pipe_bytes_to_read = sizeof(struct pcap_hdr); |
||
1813 | g_async_queue_push(pcap_opts->cap_pipe_pending_q, pcap_opts->cap_pipe_buf); |
||
1814 | g_async_queue_pop(pcap_opts->cap_pipe_done_q); |
||
1815 | if (pcap_opts->cap_pipe_bytes_read <= 0) { |
||
1816 | if (pcap_opts->cap_pipe_bytes_read == 0) |
||
1817 | g_snprintf(errmsg, errmsgl, "End of file on pipe header during open."); |
||
1818 | else |
||
1819 | g_snprintf(errmsg, errmsgl, "Error on pipe header header during open: %s.", |
||
1820 | g_strerror(errno)); |
||
1821 | goto error; |
||
1822 | } |
||
1823 | } |
||
1824 | #endif |
||
1825 | |||
1826 | if (pcap_opts->cap_pipe_byte_swapped) { |
||
1827 | /* Byte-swap the header fields about which we care. */ |
||
1828 | hdr->version_major = GUINT16_SWAP_LE_BE(hdr->version_major); |
||
1829 | hdr->version_minor = GUINT16_SWAP_LE_BE(hdr->version_minor); |
||
1830 | hdr->snaplen = GUINT32_SWAP_LE_BE(hdr->snaplen); |
||
1831 | hdr->network = GUINT32_SWAP_LE_BE(hdr->network); |
||
1832 | } |
||
1833 | pcap_opts->linktype = hdr->network; |
||
1834 | |||
1835 | if (hdr->version_major < 2) { |
||
1836 | g_snprintf(errmsg, errmsgl, "Unable to read old libpcap format"); |
||
1837 | goto error; |
||
1838 | } |
||
1839 | |||
1840 | pcap_opts->cap_pipe_state = STATE_EXPECT_REC_HDR; |
||
1841 | pcap_opts->cap_pipe_err = PIPOK; |
||
1842 | pcap_opts->cap_pipe_fd = fd; |
||
1843 | return; |
||
1844 | |||
1845 | error: |
||
1846 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: error %s", errmsg); |
||
1847 | pcap_opts->cap_pipe_err = PIPERR; |
||
1848 | cap_pipe_close(fd, pcap_opts->from_cap_socket); |
||
1849 | pcap_opts->cap_pipe_fd = -1; |
||
1850 | } |
||
1851 | |||
1852 | |||
1853 | /* We read one record from the pipe, take care of byte order in the record |
||
1854 | * header, write the record to the capture file, and update capture statistics. */ |
||
1855 | static int |
||
1856 | cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *errmsg, int errmsgl) |
||
1857 | { |
||
1858 | struct pcap_pkthdr phdr; |
||
1859 | enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR, |
||
1860 | PD_ERR } result; |
||
1861 | #ifdef _WIN32 |
||
1862 | #if !GLIB_CHECK_VERSION(2,31,18) |
||
1863 | GTimeVal wait_time; |
||
1864 | #endif |
||
1865 | gpointer q_status; |
||
1866 | wchar_t *err_str; |
||
1867 | #endif |
||
1868 | ssize_t b; |
||
1869 | |||
1870 | #ifdef LOG_CAPTURE_VERBOSE |
||
1871 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_dispatch"); |
||
1872 | #endif |
||
1873 | |||
1874 | switch (pcap_opts->cap_pipe_state) { |
||
1875 | |||
1876 | case STATE_EXPECT_REC_HDR: |
||
1877 | #ifdef _WIN32 |
||
1878 | if (g_mutex_trylock(pcap_opts->cap_pipe_read_mtx)) { |
||
1879 | #endif |
||
1880 | |||
1881 | pcap_opts->cap_pipe_state = STATE_READ_REC_HDR; |
||
1882 | pcap_opts->cap_pipe_bytes_to_read = pcap_opts->cap_pipe_modified ? |
||
1883 | sizeof(struct pcaprec_modified_hdr) : sizeof(struct pcaprec_hdr); |
||
1884 | pcap_opts->cap_pipe_bytes_read = 0; |
||
1885 | |||
1886 | #ifdef _WIN32 |
||
1887 | pcap_opts->cap_pipe_buf = (char *) &pcap_opts->cap_pipe_rechdr; |
||
1888 | g_async_queue_push(pcap_opts->cap_pipe_pending_q, pcap_opts->cap_pipe_buf); |
||
1889 | g_mutex_unlock(pcap_opts->cap_pipe_read_mtx); |
||
1890 | } |
||
1891 | #endif |
||
1892 | /* Fall through */ |
||
1893 | |||
1894 | case STATE_READ_REC_HDR: |
||
1895 | #ifdef _WIN32 |
||
1896 | if (pcap_opts->from_cap_socket) |
||
1897 | #endif |
||
1898 | { |
||
1899 | b = cap_pipe_read(pcap_opts->cap_pipe_fd, ((char *)&pcap_opts->cap_pipe_rechdr)+pcap_opts->cap_pipe_bytes_read, |
||
1900 | pcap_opts->cap_pipe_bytes_to_read - pcap_opts->cap_pipe_bytes_read, pcap_opts->from_cap_socket); |
||
1901 | if (b <= 0) { |
||
1902 | if (b == 0) |
||
1903 | result = PD_PIPE_EOF; |
||
1904 | else |
||
1905 | result = PD_PIPE_ERR; |
||
1906 | break; |
||
1907 | } |
||
1908 | pcap_opts->cap_pipe_bytes_read += b; |
||
1909 | } |
||
1910 | #ifdef _WIN32 |
||
1911 | else { |
||
1912 | #if GLIB_CHECK_VERSION(2,31,18) |
||
1913 | q_status = g_async_queue_timeout_pop(pcap_opts->cap_pipe_done_q, PIPE_READ_TIMEOUT); |
||
1914 | #else |
||
1915 | g_get_current_time(&wait_time); |
||
1916 | g_time_val_add(&wait_time, PIPE_READ_TIMEOUT); |
||
1917 | q_status = g_async_queue_timed_pop(pcap_opts->cap_pipe_done_q, &wait_time); |
||
1918 | #endif |
||
1919 | if (pcap_opts->cap_pipe_err == PIPEOF) { |
||
1920 | result = PD_PIPE_EOF; |
||
1921 | break; |
||
1922 | } else if (pcap_opts->cap_pipe_err == PIPERR) { |
||
1923 | result = PD_PIPE_ERR; |
||
1924 | break; |
||
1925 | } |
||
1926 | if (!q_status) { |
||
1927 | return 0; |
||
1928 | } |
||
1929 | } |
||
1930 | #endif |
||
1931 | if (pcap_opts->cap_pipe_bytes_read < pcap_opts->cap_pipe_bytes_to_read) |
||
1932 | return 0; |
||
1933 | result = PD_REC_HDR_READ; |
||
1934 | break; |
||
1935 | |||
1936 | case STATE_EXPECT_DATA: |
||
1937 | #ifdef _WIN32 |
||
1938 | if (g_mutex_trylock(pcap_opts->cap_pipe_read_mtx)) { |
||
1939 | #endif |
||
1940 | |||
1941 | pcap_opts->cap_pipe_state = STATE_READ_DATA; |
||
1942 | pcap_opts->cap_pipe_bytes_to_read = pcap_opts->cap_pipe_rechdr.hdr.incl_len; |
||
1943 | pcap_opts->cap_pipe_bytes_read = 0; |
||
1944 | |||
1945 | #ifdef _WIN32 |
||
1946 | pcap_opts->cap_pipe_buf = (char *) data; |
||
1947 | g_async_queue_push(pcap_opts->cap_pipe_pending_q, pcap_opts->cap_pipe_buf); |
||
1948 | g_mutex_unlock(pcap_opts->cap_pipe_read_mtx); |
||
1949 | } |
||
1950 | #endif |
||
1951 | /* Fall through */ |
||
1952 | |||
1953 | case STATE_READ_DATA: |
||
1954 | #ifdef _WIN32 |
||
1955 | if (pcap_opts->from_cap_socket) |
||
1956 | #endif |
||
1957 | { |
||
1958 | b = cap_pipe_read(pcap_opts->cap_pipe_fd, |
||
1959 | data+pcap_opts->cap_pipe_bytes_read, |
||
1960 | pcap_opts->cap_pipe_bytes_to_read - pcap_opts->cap_pipe_bytes_read, |
||
1961 | pcap_opts->from_cap_socket); |
||
1962 | if (b <= 0) { |
||
1963 | if (b == 0) |
||
1964 | result = PD_PIPE_EOF; |
||
1965 | else |
||
1966 | result = PD_PIPE_ERR; |
||
1967 | break; |
||
1968 | } |
||
1969 | pcap_opts->cap_pipe_bytes_read += b; |
||
1970 | } |
||
1971 | #ifdef _WIN32 |
||
1972 | else { |
||
1973 | |||
1974 | #if GLIB_CHECK_VERSION(2,31,18) |
||
1975 | q_status = g_async_queue_timeout_pop(pcap_opts->cap_pipe_done_q, PIPE_READ_TIMEOUT); |
||
1976 | #else |
||
1977 | g_get_current_time(&wait_time); |
||
1978 | g_time_val_add(&wait_time, PIPE_READ_TIMEOUT); |
||
1979 | q_status = g_async_queue_timed_pop(pcap_opts->cap_pipe_done_q, &wait_time); |
||
1980 | #endif /* GLIB_CHECK_VERSION(2,31,18) */ |
||
1981 | if (pcap_opts->cap_pipe_err == PIPEOF) { |
||
1982 | result = PD_PIPE_EOF; |
||
1983 | break; |
||
1984 | } else if (pcap_opts->cap_pipe_err == PIPERR) { |
||
1985 | result = PD_PIPE_ERR; |
||
1986 | break; |
||
1987 | } |
||
1988 | if (!q_status) { |
||
1989 | return 0; |
||
1990 | } |
||
1991 | } |
||
1992 | #endif /* _WIN32 */ |
||
1993 | if (pcap_opts->cap_pipe_bytes_read < pcap_opts->cap_pipe_bytes_to_read) |
||
1994 | return 0; |
||
1995 | result = PD_DATA_READ; |
||
1996 | break; |
||
1997 | |||
1998 | default: |
||
1999 | g_snprintf(errmsg, errmsgl, "cap_pipe_dispatch: invalid state"); |
||
2000 | result = PD_ERR; |
||
2001 | |||
2002 | } /* switch (pcap_opts->cap_pipe_state) */ |
||
2003 | |||
2004 | /* |
||
2005 | * We've now read as much data as we were expecting, so process it. |
||
2006 | */ |
||
2007 | switch (result) { |
||
2008 | |||
2009 | case PD_REC_HDR_READ: |
||
2010 | /* We've read the header. Take care of byte order. */ |
||
2011 | cap_pipe_adjust_header(pcap_opts->cap_pipe_byte_swapped, &pcap_opts->cap_pipe_hdr, |
||
2012 | &pcap_opts->cap_pipe_rechdr.hdr); |
||
2013 | if (pcap_opts->cap_pipe_rechdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) { |
||
2014 | g_snprintf(errmsg, errmsgl, "Frame %u too long (%d bytes)", |
||
2015 | ld->packet_count+1, pcap_opts->cap_pipe_rechdr.hdr.incl_len); |
||
2016 | break; |
||
2017 | } |
||
2018 | |||
2019 | if (pcap_opts->cap_pipe_rechdr.hdr.incl_len) { |
||
2020 | pcap_opts->cap_pipe_state = STATE_EXPECT_DATA; |
||
2021 | return 0; |
||
2022 | } |
||
2023 | /* no data to read? fall through */ |
||
2024 | |||
2025 | case PD_DATA_READ: |
||
2026 | /* Fill in a "struct pcap_pkthdr", and process the packet. */ |
||
2027 | phdr.ts.tv_sec = pcap_opts->cap_pipe_rechdr.hdr.ts_sec; |
||
2028 | phdr.ts.tv_usec = pcap_opts->cap_pipe_rechdr.hdr.ts_usec; |
||
2029 | phdr.caplen = pcap_opts->cap_pipe_rechdr.hdr.incl_len; |
||
2030 | phdr.len = pcap_opts->cap_pipe_rechdr.hdr.orig_len; |
||
2031 | |||
2032 | if (use_threads) { |
||
2033 | capture_loop_queue_packet_cb((u_char *)pcap_opts, &phdr, data); |
||
2034 | } else { |
||
2035 | capture_loop_write_packet_cb((u_char *)pcap_opts, &phdr, data); |
||
2036 | } |
||
2037 | pcap_opts->cap_pipe_state = STATE_EXPECT_REC_HDR; |
||
2038 | return 1; |
||
2039 | |||
2040 | case PD_PIPE_EOF: |
||
2041 | pcap_opts->cap_pipe_err = PIPEOF; |
||
2042 | return -1; |
||
2043 | |||
2044 | case PD_PIPE_ERR: |
||
2045 | #ifdef _WIN32 |
||
2046 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, |
||
2047 | NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); |
||
2048 | g_snprintf(errmsg, errmsgl, |
||
2049 | "Error reading from pipe: %s (error %d)", |
||
2050 | utf_16to8(err_str), GetLastError()); |
||
2051 | LocalFree(err_str); |
||
2052 | #else |
||
2053 | g_snprintf(errmsg, errmsgl, "Error reading from pipe: %s", |
||
2054 | g_strerror(errno)); |
||
2055 | #endif |
||
2056 | /* Fall through */ |
||
2057 | case PD_ERR: |
||
2058 | break; |
||
2059 | } |
||
2060 | |||
2061 | pcap_opts->cap_pipe_err = PIPERR; |
||
2062 | /* Return here rather than inside the switch to prevent GCC warning */ |
||
2063 | return -1; |
||
2064 | } |
||
2065 | |||
2066 | |||
2067 | /** Open the capture input file (pcap or capture pipe). |
||
2068 | * Returns TRUE if it succeeds, FALSE otherwise. */ |
||
2069 | static gboolean |
||
2070 | capture_loop_open_input(capture_options *capture_opts, loop_data *ld, |
||
2071 | char *errmsg, size_t errmsg_len, |
||
2072 | char *secondary_errmsg, size_t secondary_errmsg_len) |
||
2073 | { |
||
2074 | gchar open_err_str[PCAP_ERRBUF_SIZE]; |
||
2075 | gchar *sync_msg_str; |
||
2076 | interface_options interface_opts; |
||
2077 | pcap_options *pcap_opts; |
||
2078 | guint i; |
||
2079 | #ifdef _WIN32 |
||
2080 | int err; |
||
2081 | WORD wVersionRequested; |
||
2082 | WSADATA wsaData; |
||
2083 | #endif |
||
2084 | |||
2085 | /* XXX - opening Winsock on tshark? */ |
||
2086 | |||
2087 | /* Initialize Windows Socket if we are in a Win32 OS |
||
2088 | This needs to be done before querying the interface for network/netmask */ |
||
2089 | #ifdef _WIN32 |
||
2090 | /* XXX - do we really require 1.1 or earlier? |
||
2091 | Are there any versions that support only 2.0 or higher? */ |
||
2092 | wVersionRequested = MAKEWORD(1, 1); |
||
2093 | err = WSAStartup(wVersionRequested, &wsaData); |
||
2094 | if (err != 0) { |
||
2095 | switch (err) { |
||
2096 | |||
2097 | case WSASYSNOTREADY: |
||
2098 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2099 | "Couldn't initialize Windows Sockets: Network system not ready for network communication"); |
||
2100 | break; |
||
2101 | |||
2102 | case WSAVERNOTSUPPORTED: |
||
2103 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2104 | "Couldn't initialize Windows Sockets: Windows Sockets version %u.%u not supported", |
||
2105 | LOBYTE(wVersionRequested), HIBYTE(wVersionRequested)); |
||
2106 | break; |
||
2107 | |||
2108 | case WSAEINPROGRESS: |
||
2109 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2110 | "Couldn't initialize Windows Sockets: Blocking operation is in progress"); |
||
2111 | break; |
||
2112 | |||
2113 | case WSAEPROCLIM: |
||
2114 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2115 | "Couldn't initialize Windows Sockets: Limit on the number of tasks supported by this WinSock implementation has been reached"); |
||
2116 | break; |
||
2117 | |||
2118 | case WSAEFAULT: |
||
2119 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2120 | "Couldn't initialize Windows Sockets: Bad pointer passed to WSAStartup"); |
||
2121 | break; |
||
2122 | |||
2123 | default: |
||
2124 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2125 | "Couldn't initialize Windows Sockets: error %d", err); |
||
2126 | break; |
||
2127 | } |
||
2128 | g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, please_report); |
||
2129 | return FALSE; |
||
2130 | } |
||
2131 | #endif |
||
2132 | if ((use_threads == FALSE) && |
||
2133 | (capture_opts->ifaces->len > 1)) { |
||
2134 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2135 | "Using threads is required for capturing on multiple interfaces."); |
||
2136 | return FALSE; |
||
2137 | } |
||
2138 | |||
2139 | for (i = 0; i < capture_opts->ifaces->len; i++) { |
||
2140 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); |
||
2141 | pcap_opts = (pcap_options *)g_malloc(sizeof (pcap_options)); |
||
2142 | if (pcap_opts == NULL) { |
||
2143 | g_snprintf(errmsg, (gulong) errmsg_len, |
||
2144 | "Could not allocate memory."); |
||
2145 | return FALSE; |
||
2146 | } |
||
2147 | pcap_opts->received = 0; |
||
2148 | pcap_opts->dropped = 0; |
||
2149 | pcap_opts->flushed = 0; |
||
2150 | pcap_opts->pcap_h = NULL; |
||
2151 | #ifdef MUST_DO_SELECT |
||
2152 | pcap_opts->pcap_fd = -1; |
||
2153 | #endif |
||
2154 | pcap_opts->pcap_err = FALSE; |
||
2155 | pcap_opts->interface_id = i; |
||
2156 | pcap_opts->tid = NULL; |
||
2157 | pcap_opts->snaplen = 0; |
||
2158 | pcap_opts->linktype = -1; |
||
2159 | pcap_opts->ts_nsec = FALSE; |
||
2160 | pcap_opts->from_cap_pipe = FALSE; |
||
2161 | pcap_opts->from_cap_socket = FALSE; |
||
2162 | memset(&pcap_opts->cap_pipe_hdr, 0, sizeof(struct pcap_hdr)); |
||
2163 | memset(&pcap_opts->cap_pipe_rechdr, 0, sizeof(struct pcaprec_modified_hdr)); |
||
2164 | #ifdef _WIN32 |
||
2165 | pcap_opts->cap_pipe_h = INVALID_HANDLE_VALUE; |
||
2166 | #endif |
||
2167 | pcap_opts->cap_pipe_fd = -1; |
||
2168 | pcap_opts->cap_pipe_modified = FALSE; |
||
2169 | pcap_opts->cap_pipe_byte_swapped = FALSE; |
||
2170 | #ifdef _WIN32 |
||
2171 | pcap_opts->cap_pipe_buf = NULL; |
||
2172 | #endif |
||
2173 | pcap_opts->cap_pipe_bytes_to_read = 0; |
||
2174 | pcap_opts->cap_pipe_bytes_read = 0; |
||
2175 | pcap_opts->cap_pipe_state = STATE_EXPECT_REC_HDR; |
||
2176 | pcap_opts->cap_pipe_err = PIPOK; |
||
2177 | #ifdef _WIN32 |
||
2178 | #if GLIB_CHECK_VERSION(2,31,0) |
||
2179 | pcap_opts->cap_pipe_read_mtx = g_malloc(sizeof(GMutex)); |
||
2180 | g_mutex_init(pcap_opts->cap_pipe_read_mtx); |
||
2181 | #else |
||
2182 | pcap_opts->cap_pipe_read_mtx = g_mutex_new(); |
||
2183 | #endif |
||
2184 | pcap_opts->cap_pipe_pending_q = g_async_queue_new(); |
||
2185 | pcap_opts->cap_pipe_done_q = g_async_queue_new(); |
||
2186 | #endif |
||
2187 | g_array_append_val(ld->pcaps, pcap_opts); |
||
2188 | |||
2189 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_input : %s", interface_opts.name); |
||
2190 | pcap_opts->pcap_h = open_capture_device(capture_opts, &interface_opts, |
||
2191 | CAP_READ_TIMEOUT, &open_err_str); |
||
2192 | |||
2193 | if (pcap_opts->pcap_h != NULL) { |
||
2194 | /* we've opened "iface" as a network device */ |
||
2195 | |||
2196 | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION |
||
2197 | /* Find out if we're getting nanosecond-precision time stamps */ |
||
2198 | pcap_opts->ts_nsec = have_high_resolution_timestamp(pcap_opts->pcap_h); |
||
2199 | #endif |
||
2200 | |||
2201 | #if defined(HAVE_PCAP_SETSAMPLING) |
||
2202 | if (interface_opts.sampling_method != CAPTURE_SAMP_NONE) { |
||
2203 | struct pcap_samp *samp; |
||
2204 | |||
2205 | if ((samp = pcap_setsampling(pcap_opts->pcap_h)) != NULL) { |
||
2206 | switch (interface_opts.sampling_method) { |
||
2207 | case CAPTURE_SAMP_BY_COUNT: |
||
2208 | samp->method = PCAP_SAMP_1_EVERY_N; |
||
2209 | break; |
||
2210 | |||
2211 | case CAPTURE_SAMP_BY_TIMER: |
||
2212 | samp->method = PCAP_SAMP_FIRST_AFTER_N_MS; |
||
2213 | break; |
||
2214 | |||
2215 | default: |
||
2216 | sync_msg_str = g_strdup_printf( |
||
2217 | "Unknown sampling method %d specified,\n" |
||
2218 | "continue without packet sampling", |
||
2219 | interface_opts.sampling_method); |
||
2220 | report_capture_error("Couldn't set the capture " |
||
2221 | "sampling", sync_msg_str); |
||
2222 | g_free(sync_msg_str); |
||
2223 | } |
||
2224 | samp->value = interface_opts.sampling_param; |
||
2225 | } else { |
||
2226 | report_capture_error("Couldn't set the capture sampling", |
||
2227 | "Cannot get packet sampling data structure"); |
||
2228 | } |
||
2229 | } |
||
2230 | #endif |
||
2231 | |||
2232 | /* setting the data link type only works on real interfaces */ |
||
2233 | if (!set_pcap_datalink(pcap_opts->pcap_h, interface_opts.linktype, |
||
2234 | interface_opts.name, |
||
2235 | errmsg, errmsg_len, |
||
2236 | secondary_errmsg, secondary_errmsg_len)) { |
||
2237 | return FALSE; |
||
2238 | } |
||
2239 | pcap_opts->linktype = get_pcap_datalink(pcap_opts->pcap_h, interface_opts.name); |
||
2240 | } else { |
||
2241 | /* We couldn't open "iface" as a network device. */ |
||
2242 | /* Try to open it as a pipe */ |
||
2243 | cap_pipe_open_live(interface_opts.name, pcap_opts, &pcap_opts->cap_pipe_hdr, errmsg, (int) errmsg_len); |
||
2244 | |||
2245 | #ifndef _WIN32 |
||
2246 | if (pcap_opts->cap_pipe_fd == -1) { |
||
2247 | #else |
||
2248 | if (pcap_opts->cap_pipe_h == INVALID_HANDLE_VALUE) { |
||
2249 | #endif |
||
2250 | if (pcap_opts->cap_pipe_err == PIPNEXIST) { |
||
2251 | /* |
||
2252 | * We tried opening as an interface, and that failed, |
||
2253 | * so we tried to open it as a pipe, but the pipe |
||
2254 | * doesn't exist. Report the error message for |
||
2255 | * the interface. |
||
2256 | */ |
||
2257 | get_capture_device_open_failure_messages(open_err_str, |
||
2258 | interface_opts.name, |
||
2259 | errmsg, |
||
2260 | errmsg_len, |
||
2261 | secondary_errmsg, |
||
2262 | secondary_errmsg_len); |
||
2263 | } |
||
2264 | /* |
||
2265 | * Else pipe (or file) does exist and cap_pipe_open_live() has |
||
2266 | * filled in errmsg |
||
2267 | */ |
||
2268 | return FALSE; |
||
2269 | } else { |
||
2270 | /* cap_pipe_open_live() succeeded; don't want |
||
2271 | error message from pcap_open_live() */ |
||
2272 | open_err_str[0] = '\0'; |
||
2273 | } |
||
2274 | } |
||
2275 | |||
2276 | /* XXX - will this work for tshark? */ |
||
2277 | #ifdef MUST_DO_SELECT |
||
2278 | if (!pcap_opts->from_cap_pipe) { |
||
2279 | #ifdef HAVE_PCAP_GET_SELECTABLE_FD |
||
2280 | pcap_opts->pcap_fd = pcap_get_selectable_fd(pcap_opts->pcap_h); |
||
2281 | #else |
||
2282 | pcap_opts->pcap_fd = pcap_fileno(pcap_opts->pcap_h); |
||
2283 | #endif |
||
2284 | } |
||
2285 | #endif |
||
2286 | |||
2287 | /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()" |
||
2288 | returned a warning; print it, but keep capturing. */ |
||
2289 | if (open_err_str[0] != '\0') { |
||
2290 | sync_msg_str = g_strdup_printf("%s.", open_err_str); |
||
2291 | report_capture_error(sync_msg_str, ""); |
||
2292 | g_free(sync_msg_str); |
||
2293 | } |
||
2294 | capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, i); |
||
2295 | g_array_insert_val(capture_opts->ifaces, i, interface_opts); |
||
2296 | } |
||
2297 | |||
2298 | /* If not using libcap: we now can now set euid/egid to ruid/rgid */ |
||
2299 | /* to remove any suid privileges. */ |
||
2300 | /* If using libcap: we can now remove NET_RAW and NET_ADMIN capabilities */ |
||
2301 | /* (euid/egid have already previously been set to ruid/rgid. */ |
||
2302 | /* (See comment in main() for details) */ |
||
2303 | #ifndef HAVE_LIBCAP |
||
2304 | relinquish_special_privs_perm(); |
||
2305 | #else |
||
2306 | relinquish_all_capabilities(); |
||
2307 | #endif |
||
2308 | return TRUE; |
||
2309 | } |
||
2310 | |||
2311 | /* close the capture input file (pcap or capture pipe) */ |
||
2312 | static void capture_loop_close_input(loop_data *ld) |
||
2313 | { |
||
2314 | guint i; |
||
2315 | pcap_options *pcap_opts; |
||
2316 | |||
2317 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input"); |
||
2318 | |||
2319 | for (i = 0; i < ld->pcaps->len; i++) { |
||
2320 | pcap_opts = g_array_index(ld->pcaps, pcap_options *, i); |
||
2321 | /* if open, close the capture pipe "input file" */ |
||
2322 | if (pcap_opts->cap_pipe_fd >= 0) { |
||
2323 | g_assert(pcap_opts->from_cap_pipe); |
||
2324 | cap_pipe_close(pcap_opts->cap_pipe_fd, pcap_opts->from_cap_socket); |
||
2325 | pcap_opts->cap_pipe_fd = -1; |
||
2326 | } |
||
2327 | #ifdef _WIN32 |
||
2328 | if (pcap_opts->cap_pipe_h != INVALID_HANDLE_VALUE) { |
||
2329 | CloseHandle(pcap_opts->cap_pipe_h); |
||
2330 | pcap_opts->cap_pipe_h = INVALID_HANDLE_VALUE; |
||
2331 | } |
||
2332 | #endif |
||
2333 | /* if open, close the pcap "input file" */ |
||
2334 | if (pcap_opts->pcap_h != NULL) { |
||
2335 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input: closing %p", (void *)pcap_opts->pcap_h); |
||
2336 | pcap_close(pcap_opts->pcap_h); |
||
2337 | pcap_opts->pcap_h = NULL; |
||
2338 | } |
||
2339 | } |
||
2340 | |||
2341 | ld->go = FALSE; |
||
2342 | |||
2343 | #ifdef _WIN32 |
||
2344 | /* Shut down windows sockets */ |
||
2345 | WSACleanup(); |
||
2346 | #endif |
||
2347 | } |
||
2348 | |||
2349 | |||
2350 | /* init the capture filter */ |
||
2351 | static initfilter_status_t |
||
2352 | capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, |
||
2353 | const gchar * name, const gchar * cfilter) |
||
2354 | { |
||
2355 | struct bpf_program fcode; |
||
2356 | |||
2357 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_filter: %s", cfilter); |
||
2358 | |||
2359 | /* capture filters only work on real interfaces */ |
||
2360 | if (cfilter && !from_cap_pipe) { |
||
2361 | /* A capture filter was specified; set it up. */ |
||
2362 | if (!compile_capture_filter(name, pcap_h, &fcode, cfilter)) { |
||
2363 | /* Treat this specially - our caller might try to compile this |
||
2364 | as a display filter and, if that succeeds, warn the user that |
||
2365 | the display and capture filter syntaxes are different. */ |
||
2366 | return INITFILTER_BAD_FILTER; |
||
2367 | } |
||
2368 | if (pcap_setfilter(pcap_h, &fcode) < 0) { |
||
2369 | #ifdef HAVE_PCAP_FREECODE |
||
2370 | pcap_freecode(&fcode); |
||
2371 | #endif |
||
2372 | return INITFILTER_OTHER_ERROR; |
||
2373 | } |
||
2374 | #ifdef HAVE_PCAP_FREECODE |
||
2375 | pcap_freecode(&fcode); |
||
2376 | #endif |
||
2377 | } |
||
2378 | |||
2379 | return INITFILTER_NO_ERROR; |
||
2380 | } |
||
2381 | |||
2382 | |||
2383 | /* set up to write to the already-opened capture output file/files */ |
||
2384 | static gboolean |
||
2385 | capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len) |
||
2386 | { |
||
2387 | int err; |
||
2388 | guint i; |
||
2389 | pcap_options *pcap_opts; |
||
2390 | interface_options interface_opts; |
||
2391 | gboolean successful; |
||
2392 | |||
2393 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_output"); |
||
2394 | |||
2395 | if ((capture_opts->use_pcapng == FALSE) && |
||
2396 | (capture_opts->ifaces->len > 1)) { |
||
2397 | g_snprintf(errmsg, errmsg_len, |
||
2398 | "Using PCAPNG is required for capturing on multiple interfaces. Use the -n option."); |
||
2399 | return FALSE; |
||
2400 | } |
||
2401 | |||
2402 | /* Set up to write to the capture file. */ |
||
2403 | if (capture_opts->multi_files_on) { |
||
2404 | ld->pdh = ringbuf_init_libpcap_fdopen(&err); |
||
2405 | } else { |
||
2406 | ld->pdh = ws_fdopen(ld->save_file_fd, "wb"); |
||
2407 | if (ld->pdh == NULL) { |
||
2408 | err = errno; |
||
2409 | } |
||
2410 | } |
||
2411 | if (ld->pdh) { |
||
2412 | if (capture_opts->use_pcapng) { |
||
2413 | char *appname; |
||
2414 | GString *os_info_str; |
||
2415 | |||
2416 | os_info_str = g_string_new(""); |
||
2417 | get_os_version_info(os_info_str); |
||
2418 | |||
2419 | appname = g_strdup_printf("Dumpcap (Wireshark) %s", get_ws_vcs_version_info()); |
||
2420 | successful = pcapng_write_session_header_block(ld->pdh, |
||
2421 | (const char *)capture_opts->capture_comment, /* Comment*/ |
||
2422 | NULL, /* HW*/ |
||
2423 | os_info_str->str, /* OS*/ |
||
2424 | appname, |
||
2425 | -1, /* section_length */ |
||
2426 | &ld->bytes_written, |
||
2427 | &err); |
||
2428 | g_free(appname); |
||
2429 | |||
2430 | for (i = 0; successful && (i < capture_opts->ifaces->len); i++) { |
||
2431 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); |
||
2432 | pcap_opts = g_array_index(ld->pcaps, pcap_options *, i); |
||
2433 | if (pcap_opts->from_cap_pipe) { |
||
2434 | pcap_opts->snaplen = pcap_opts->cap_pipe_hdr.snaplen; |
||
2435 | } else { |
||
2436 | pcap_opts->snaplen = pcap_snapshot(pcap_opts->pcap_h); |
||
2437 | } |
||
2438 | successful = pcapng_write_interface_description_block(global_ld.pdh, |
||
2439 | NULL, /* OPT_COMMENT 1 */ |
||
2440 | interface_opts.name, /* IDB_NAME 2 */ |
||
2441 | interface_opts.descr, /* IDB_DESCRIPTION 3 */ |
||
2442 | interface_opts.cfilter, /* IDB_FILTER 11 */ |
||
2443 | os_info_str->str, /* IDB_OS 12 */ |
||
2444 | pcap_opts->linktype, |
||
2445 | pcap_opts->snaplen, |
||
2446 | &(global_ld.bytes_written), |
||
2447 | 0, /* IDB_IF_SPEED 8 */ |
||
2448 | pcap_opts->ts_nsec ? 9 : 6, /* IDB_TSRESOL 9 */ |
||
2449 | &global_ld.err); |
||
2450 | } |
||
2451 | |||
2452 | g_string_free(os_info_str, TRUE); |
||
2453 | |||
2454 | } else { |
||
2455 | pcap_opts = g_array_index(ld->pcaps, pcap_options *, 0); |
||
2456 | if (pcap_opts->from_cap_pipe) { |
||
2457 | pcap_opts->snaplen = pcap_opts->cap_pipe_hdr.snaplen; |
||
2458 | } else { |
||
2459 | pcap_opts->snaplen = pcap_snapshot(pcap_opts->pcap_h); |
||
2460 | } |
||
2461 | successful = libpcap_write_file_header(ld->pdh, pcap_opts->linktype, pcap_opts->snaplen, |
||
2462 | pcap_opts->ts_nsec, &ld->bytes_written, &err); |
||
2463 | } |
||
2464 | if (!successful) { |
||
2465 | fclose(ld->pdh); |
||
2466 | ld->pdh = NULL; |
||
2467 | } |
||
2468 | } |
||
2469 | |||
2470 | if (ld->pdh == NULL) { |
||
2471 | /* We couldn't set up to write to the capture file. */ |
||
2472 | /* XXX - use cf_open_error_message from tshark instead? */ |
||
2473 | switch (err) { |
||
2474 | |||
2475 | default: |
||
2476 | if (err < 0) { |
||
2477 | g_snprintf(errmsg, errmsg_len, |
||
2478 | "The file to which the capture would be" |
||
2479 | " saved (\"%s\") could not be opened: Error %d.", |
||
2480 | capture_opts->save_file, err); |
||
2481 | } else { |
||
2482 | g_snprintf(errmsg, errmsg_len, |
||
2483 | "The file to which the capture would be" |
||
2484 | " saved (\"%s\") could not be opened: %s.", |
||
2485 | capture_opts->save_file, g_strerror(err)); |
||
2486 | } |
||
2487 | break; |
||
2488 | } |
||
2489 | |||
2490 | return FALSE; |
||
2491 | } |
||
2492 | |||
2493 | return TRUE; |
||
2494 | } |
||
2495 | |||
2496 | static gboolean |
||
2497 | capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close) |
||
2498 | { |
||
2499 | |||
2500 | unsigned int i; |
||
2501 | pcap_options *pcap_opts; |
||
2502 | guint64 end_time = create_timestamp(); |
||
2503 | |||
2504 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_output"); |
||
2505 | |||
2506 | if (capture_opts->multi_files_on) { |
||
2507 | return ringbuf_libpcap_dump_close(&capture_opts->save_file, err_close); |
||
2508 | } else { |
||
2509 | if (capture_opts->use_pcapng) { |
||
2510 | for (i = 0; i < global_ld.pcaps->len; i++) { |
||
2511 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
2512 | if (!pcap_opts->from_cap_pipe) { |
||
2513 | guint64 isb_ifrecv, isb_ifdrop; |
||
2514 | struct pcap_stat stats; |
||
2515 | |||
2516 | if (pcap_stats(pcap_opts->pcap_h, &stats) >= 0) { |
||
2517 | isb_ifrecv = pcap_opts->received; |
||
2518 | isb_ifdrop = stats.ps_drop + pcap_opts->dropped + pcap_opts->flushed; |
||
2519 | } else { |
||
2520 | isb_ifrecv = G_MAXUINT64; |
||
2521 | isb_ifdrop = G_MAXUINT64; |
||
2522 | } |
||
2523 | pcapng_write_interface_statistics_block(ld->pdh, |
||
2524 | i, |
||
2525 | &ld->bytes_written, |
||
2526 | "Counters provided by dumpcap", |
||
2527 | start_time, |
||
2528 | end_time, |
||
2529 | isb_ifrecv, |
||
2530 | isb_ifdrop, |
||
2531 | err_close); |
||
2532 | } |
||
2533 | } |
||
2534 | } |
||
2535 | if (fclose(ld->pdh) == EOF) { |
||
2536 | if (err_close != NULL) { |
||
2537 | *err_close = errno; |
||
2538 | } |
||
2539 | return (FALSE); |
||
2540 | } else { |
||
2541 | return (TRUE); |
||
2542 | } |
||
2543 | } |
||
2544 | } |
||
2545 | |||
2546 | /* dispatch incoming packets (pcap or capture pipe) |
||
2547 | * |
||
2548 | * Waits for incoming packets to be available, and calls pcap_dispatch() |
||
2549 | * to cause them to be processed. |
||
2550 | * |
||
2551 | * Returns the number of packets which were processed. |
||
2552 | * |
||
2553 | * Times out (returning zero) after CAP_READ_TIMEOUT ms; this ensures that the |
||
2554 | * packet-batching behaviour does not cause packets to get held back |
||
2555 | * indefinitely. |
||
2556 | */ |
||
2557 | static int |
||
2558 | capture_loop_dispatch(loop_data *ld, |
||
2559 | char *errmsg, int errmsg_len, pcap_options *pcap_opts) |
||
2560 | { |
||
2561 | int inpkts; |
||
2562 | gint packet_count_before; |
||
2563 | guchar pcap_data[WTAP_MAX_PACKET_SIZE]; |
||
2564 | #ifndef _WIN32 |
||
2565 | int sel_ret; |
||
2566 | #endif |
||
2567 | |||
2568 | packet_count_before = ld->packet_count; |
||
2569 | if (pcap_opts->from_cap_pipe) { |
||
2570 | /* dispatch from capture pipe */ |
||
2571 | #ifdef LOG_CAPTURE_VERBOSE |
||
2572 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from capture pipe"); |
||
2573 | #endif |
||
2574 | #ifndef _WIN32 |
||
2575 | sel_ret = cap_pipe_select(pcap_opts->cap_pipe_fd); |
||
2576 | if (sel_ret <= 0) { |
||
2577 | if (sel_ret < 0 && errno != EINTR) { |
||
2578 | g_snprintf(errmsg, errmsg_len, |
||
2579 | "Unexpected error from select: %s", g_strerror(errno)); |
||
2580 | report_capture_error(errmsg, please_report); |
||
2581 | ld->go = FALSE; |
||
2582 | } |
||
2583 | } else { |
||
2584 | /* |
||
2585 | * "select()" says we can read from the pipe without blocking |
||
2586 | */ |
||
2587 | #endif |
||
2588 | inpkts = cap_pipe_dispatch(ld, pcap_opts, pcap_data, errmsg, errmsg_len); |
||
2589 | if (inpkts < 0) { |
||
2590 | ld->go = FALSE; |
||
2591 | } |
||
2592 | #ifndef _WIN32 |
||
2593 | } |
||
2594 | #endif |
||
2595 | } |
||
2596 | else |
||
2597 | { |
||
2598 | /* dispatch from pcap */ |
||
2599 | #ifdef MUST_DO_SELECT |
||
2600 | /* |
||
2601 | * If we have "pcap_get_selectable_fd()", we use it to get the |
||
2602 | * descriptor on which to select; if that's -1, it means there |
||
2603 | * is no descriptor on which you can do a "select()" (perhaps |
||
2604 | * because you're capturing on a special device, and that device's |
||
2605 | * driver unfortunately doesn't support "select()", in which case |
||
2606 | * we don't do the select - which means it might not be possible |
||
2607 | * to stop a capture until a packet arrives. If that's unacceptable, |
||
2608 | * plead with whoever supplies the software for that device to add |
||
2609 | * "select()" support, or upgrade to libpcap 0.8.1 or later, and |
||
2610 | * rebuild Wireshark or get a version built with libpcap 0.8.1 or |
||
2611 | * later, so it can use pcap_breakloop(). |
||
2612 | */ |
||
2613 | #ifdef LOG_CAPTURE_VERBOSE |
||
2614 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch with select"); |
||
2615 | #endif |
||
2616 | if (pcap_opts->pcap_fd != -1) { |
||
2617 | sel_ret = cap_pipe_select(pcap_opts->pcap_fd); |
||
2618 | if (sel_ret > 0) { |
||
2619 | /* |
||
2620 | * "select()" says we can read from it without blocking; go for |
||
2621 | * it. |
||
2622 | * |
||
2623 | * We don't have pcap_breakloop(), so we only process one packet |
||
2624 | * per pcap_dispatch() call, to allow a signal to stop the |
||
2625 | * processing immediately, rather than processing all packets |
||
2626 | * in a batch before quitting. |
||
2627 | */ |
||
2628 | if (use_threads) { |
||
2629 | inpkts = pcap_dispatch(pcap_opts->pcap_h, 1, capture_loop_queue_packet_cb, (u_char *)pcap_opts); |
||
2630 | } else { |
||
2631 | inpkts = pcap_dispatch(pcap_opts->pcap_h, 1, capture_loop_write_packet_cb, (u_char *)pcap_opts); |
||
2632 | } |
||
2633 | if (inpkts < 0) { |
||
2634 | if (inpkts == -1) { |
||
2635 | /* Error, rather than pcap_breakloop(). */ |
||
2636 | pcap_opts->pcap_err = TRUE; |
||
2637 | } |
||
2638 | ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */ |
||
2639 | } |
||
2640 | } else { |
||
2641 | if (sel_ret < 0 && errno != EINTR) { |
||
2642 | g_snprintf(errmsg, errmsg_len, |
||
2643 | "Unexpected error from select: %s", g_strerror(errno)); |
||
2644 | report_capture_error(errmsg, please_report); |
||
2645 | ld->go = FALSE; |
||
2646 | } |
||
2647 | } |
||
2648 | } |
||
2649 | else |
||
2650 | #endif /* MUST_DO_SELECT */ |
||
2651 | { |
||
2652 | /* dispatch from pcap without select */ |
||
2653 | #if 1 |
||
2654 | #ifdef LOG_CAPTURE_VERBOSE |
||
2655 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch"); |
||
2656 | #endif |
||
2657 | #ifdef _WIN32 |
||
2658 | /* |
||
2659 | * On Windows, we don't support asynchronously telling a process to |
||
2660 | * stop capturing; instead, we check for an indication on a pipe |
||
2661 | * after processing packets. We therefore process only one packet |
||
2662 | * at a time, so that we can check the pipe after every packet. |
||
2663 | */ |
||
2664 | if (use_threads) { |
||
2665 | inpkts = pcap_dispatch(pcap_opts->pcap_h, 1, capture_loop_queue_packet_cb, (u_char *)pcap_opts); |
||
2666 | } else { |
||
2667 | inpkts = pcap_dispatch(pcap_opts->pcap_h, 1, capture_loop_write_packet_cb, (u_char *)pcap_opts); |
||
2668 | } |
||
2669 | #else |
||
2670 | if (use_threads) { |
||
2671 | inpkts = pcap_dispatch(pcap_opts->pcap_h, -1, capture_loop_queue_packet_cb, (u_char *)pcap_opts); |
||
2672 | } else { |
||
2673 | inpkts = pcap_dispatch(pcap_opts->pcap_h, -1, capture_loop_write_packet_cb, (u_char *)pcap_opts); |
||
2674 | } |
||
2675 | #endif |
||
2676 | if (inpkts < 0) { |
||
2677 | if (inpkts == -1) { |
||
2678 | /* Error, rather than pcap_breakloop(). */ |
||
2679 | pcap_opts->pcap_err = TRUE; |
||
2680 | } |
||
2681 | ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */ |
||
2682 | } |
||
2683 | #else /* pcap_next_ex */ |
||
2684 | #ifdef LOG_CAPTURE_VERBOSE |
||
2685 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_next_ex"); |
||
2686 | #endif |
||
2687 | /* XXX - this is currently unused, as there is some confusion with pcap_next_ex() vs. pcap_dispatch() */ |
||
2688 | |||
2689 | /* |
||
2690 | * WinPcap's remote capturing feature doesn't work with pcap_dispatch(), |
||
2691 | * see https://wiki.wireshark.org/CaptureSetup_2fWinPcapRemote |
||
2692 | * This should be fixed in the WinPcap 4.0 alpha release. |
||
2693 | * |
||
2694 | * For reference, an example remote interface: |
||
2695 | * rpcap://[1.2.3.4]/\Device\NPF_{39993D68-7C9B-4439-A329-F2D888DA7C5C} |
||
2696 | */ |
||
2697 | |||
2698 | /* emulate dispatch from pcap */ |
||
2699 | { |
||
2700 | int in; |
||
2701 | struct pcap_pkthdr *pkt_header; |
||
2702 | u_char *pkt_data; |
||
2703 | |||
2704 | in = 0; |
||
2705 | while(ld->go && |
||
2706 | (in = pcap_next_ex(pcap_opts->pcap_h, &pkt_header, &pkt_data)) == 1) { |
||
2707 | if (use_threads) { |
||
2708 | capture_loop_queue_packet_cb((u_char *)pcap_opts, pkt_header, pkt_data); |
||
2709 | } else { |
||
2710 | capture_loop_write_packet_cb((u_char *)pcap_opts, pkt_header, pkt_data); |
||
2711 | } |
||
2712 | } |
||
2713 | |||
2714 | if (in < 0) { |
||
2715 | pcap_opts->pcap_err = TRUE; |
||
2716 | ld->go = FALSE; |
||
2717 | } |
||
2718 | } |
||
2719 | #endif /* pcap_next_ex */ |
||
2720 | } |
||
2721 | } |
||
2722 | |||
2723 | #ifdef LOG_CAPTURE_VERBOSE |
||
2724 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: %d new packet%s", inpkts, plurality(inpkts, "", "s")); |
||
2725 | #endif |
||
2726 | |||
2727 | return ld->packet_count - packet_count_before; |
||
2728 | } |
||
2729 | |||
2730 | #ifdef _WIN32 |
||
2731 | /* Isolate the Universally Unique Identifier from the interface. Basically, we |
||
2732 | * want to grab only the characters between the '{' and '}' delimiters. |
||
2733 | * |
||
2734 | * Returns a GString that must be freed with g_string_free(). */ |
||
2735 | static GString * |
||
2736 | isolate_uuid(const char *iface) |
||
2737 | { |
||
2738 | gchar *ptr; |
||
2739 | GString *gstr; |
||
2740 | |||
2741 | ptr = strchr(iface, '{'); |
||
2742 | if (ptr == NULL) |
||
2743 | return g_string_new(iface); |
||
2744 | gstr = g_string_new(ptr + 1); |
||
2745 | |||
2746 | ptr = strchr(gstr->str, '}'); |
||
2747 | if (ptr == NULL) |
||
2748 | return gstr; |
||
2749 | |||
2750 | gstr = g_string_truncate(gstr, ptr - gstr->str); |
||
2751 | return gstr; |
||
2752 | } |
||
2753 | #endif |
||
2754 | |||
2755 | /* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */ |
||
2756 | /* Returns TRUE if the file opened successfully, FALSE otherwise. */ |
||
2757 | static gboolean |
||
2758 | capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, |
||
2759 | char *errmsg, int errmsg_len) |
||
2760 | { |
||
2761 | char *tmpname; |
||
2762 | gchar *capfile_name; |
||
2763 | gchar *prefix, *suffix; |
||
2764 | gboolean is_tempfile; |
||
2765 | |||
2766 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_output: %s", |
||
2767 | (capture_opts->save_file) ? capture_opts->save_file : "(not specified)"); |
||
2768 | |||
2769 | if (capture_opts->save_file != NULL) { |
||
2770 | /* We return to the caller while the capture is in progress. |
||
2771 | * Therefore we need to take a copy of save_file in |
||
2772 | * case the caller destroys it after we return. |
||
2773 | */ |
||
2774 | capfile_name = g_strdup(capture_opts->save_file); |
||
2775 | |||
2776 | if (capture_opts->output_to_pipe == TRUE) { /* either "-" or named pipe */ |
||
2777 | if (capture_opts->multi_files_on) { |
||
2778 | /* ringbuffer is enabled; that doesn't work with standard output or a named pipe */ |
||
2779 | g_snprintf(errmsg, errmsg_len, |
||
2780 | "Ring buffer requested, but capture is being written to standard output or to a named pipe."); |
||
2781 | g_free(capfile_name); |
||
2782 | return FALSE; |
||
2783 | } |
||
2784 | if (strcmp(capfile_name, "-") == 0) { |
||
2785 | /* write to stdout */ |
||
2786 | *save_file_fd = 1; |
||
2787 | #ifdef _WIN32 |
||
2788 | /* set output pipe to binary mode to avoid Windows text-mode processing (eg: for CR/LF) */ |
||
2789 | _setmode(1, O_BINARY); |
||
2790 | #endif |
||
2791 | } |
||
2792 | } /* if (...output_to_pipe ... */ |
||
2793 | |||
2794 | else { |
||
2795 | if (capture_opts->multi_files_on) { |
||
2796 | /* ringbuffer is enabled */ |
||
2797 | *save_file_fd = ringbuf_init(capfile_name, |
||
2798 | (capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0, |
||
2799 | capture_opts->group_read_access); |
||
2800 | |||
2801 | /* we need the ringbuf name */ |
||
2802 | if (*save_file_fd != -1) { |
||
2803 | g_free(capfile_name); |
||
2804 | capfile_name = g_strdup(ringbuf_current_filename()); |
||
2805 | } |
||
2806 | } else { |
||
2807 | /* Try to open/create the specified file for use as a capture buffer. */ |
||
2808 | *save_file_fd = ws_open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, |
||
2809 | (capture_opts->group_read_access) ? 0640 : 0600); |
||
2810 | } |
||
2811 | } |
||
2812 | is_tempfile = FALSE; |
||
2813 | } else { |
||
2814 | /* Choose a random name for the temporary capture buffer */ |
||
2815 | if (global_capture_opts.ifaces->len > 1) { |
||
2816 | prefix = g_strdup_printf("wireshark_%d_interfaces", global_capture_opts.ifaces->len); |
||
2817 | if (capture_opts->use_pcapng) { |
||
2818 | suffix = ".pcapng"; |
||
2819 | }else{ |
||
2820 | suffix = ".pcap"; |
||
2821 | } |
||
2822 | } else { |
||
2823 | gchar *basename; |
||
2824 | basename = g_path_get_basename(g_array_index(global_capture_opts.ifaces, interface_options, 0).console_display_name); |
||
2825 | #ifdef _WIN32 |
||
2826 | /* use the generic portion of the interface guid to form the basis of the filename */ |
||
2827 | if (strncmp("NPF_{", basename, 5)==0) |
||
2828 | { |
||
2829 | /* we have a windows guid style device name, extract the guid digits as the basis of the filename */ |
||
2830 | GString *iface; |
||
2831 | iface = isolate_uuid(basename); |
||
2832 | g_free(basename); |
||
2833 | basename = g_strdup(iface->str); |
||
2834 | g_string_free(iface, TRUE); |
||
2835 | } |
||
2836 | #endif |
||
2837 | /* generate the temp file name prefix and suffix */ |
||
2838 | if (capture_opts->use_pcapng) { |
||
2839 | prefix = g_strconcat("wireshark_", basename, NULL); |
||
2840 | suffix = ".pcapng"; |
||
2841 | }else{ |
||
2842 | prefix = g_strconcat("wireshark_", basename, NULL); |
||
2843 | suffix = ".pcap"; |
||
2844 | } |
||
2845 | g_free(basename); |
||
2846 | } |
||
2847 | *save_file_fd = create_tempfile(&tmpname, prefix, suffix); |
||
2848 | g_free(prefix); |
||
2849 | capfile_name = g_strdup(tmpname); |
||
2850 | is_tempfile = TRUE; |
||
2851 | } |
||
2852 | |||
2853 | /* did we fail to open the output file? */ |
||
2854 | if (*save_file_fd == -1) { |
||
2855 | if (is_tempfile) { |
||
2856 | g_snprintf(errmsg, errmsg_len, |
||
2857 | "The temporary file to which the capture would be saved (\"%s\") " |
||
2858 | "could not be opened: %s.", capfile_name, g_strerror(errno)); |
||
2859 | } else { |
||
2860 | if (capture_opts->multi_files_on) { |
||
2861 | ringbuf_error_cleanup(); |
||
2862 | } |
||
2863 | |||
2864 | g_snprintf(errmsg, errmsg_len, |
||
2865 | "The file to which the capture would be saved (\"%s\") " |
||
2866 | "could not be opened: %s.", capfile_name, |
||
2867 | g_strerror(errno)); |
||
2868 | } |
||
2869 | g_free(capfile_name); |
||
2870 | return FALSE; |
||
2871 | } |
||
2872 | |||
2873 | if (capture_opts->save_file != NULL) { |
||
2874 | g_free(capture_opts->save_file); |
||
2875 | } |
||
2876 | capture_opts->save_file = capfile_name; |
||
2877 | /* capture_opts.save_file is "g_free"ed later, which is equivalent to |
||
2878 | "g_free(capfile_name)". */ |
||
2879 | |||
2880 | return TRUE; |
||
2881 | } |
||
2882 | |||
2883 | |||
2884 | /* Do the work of handling either the file size or file duration capture |
||
2885 | conditions being reached, and switching files or stopping. */ |
||
2886 | static gboolean |
||
2887 | do_file_switch_or_stop(capture_options *capture_opts, |
||
2888 | condition *cnd_autostop_files, |
||
2889 | condition *cnd_autostop_size, |
||
2890 | condition *cnd_file_duration) |
||
2891 | { |
||
2892 | guint i; |
||
2893 | pcap_options *pcap_opts; |
||
2894 | interface_options interface_opts; |
||
2895 | gboolean successful; |
||
2896 | |||
2897 | if (capture_opts->multi_files_on) { |
||
2898 | if (cnd_autostop_files != NULL && |
||
2899 | cnd_eval(cnd_autostop_files, (guint64)++global_ld.autostop_files)) { |
||
2900 | /* no files left: stop here */ |
||
2901 | global_ld.go = FALSE; |
||
2902 | return FALSE; |
||
2903 | } |
||
2904 | |||
2905 | /* Switch to the next ringbuffer file */ |
||
2906 | if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file, |
||
2907 | &global_ld.save_file_fd, &global_ld.err)) { |
||
2908 | |||
2909 | /* File switch succeeded: reset the conditions */ |
||
2910 | global_ld.bytes_written = 0; |
||
2911 | if (capture_opts->use_pcapng) { |
||
2912 | char *appname; |
||
2913 | GString *os_info_str; |
||
2914 | |||
2915 | os_info_str = g_string_new(""); |
||
2916 | get_os_version_info(os_info_str); |
||
2917 | |||
2918 | appname = g_strdup_printf("Dumpcap (Wireshark) %s", get_ws_vcs_version_info()); |
||
2919 | successful = pcapng_write_session_header_block(global_ld.pdh, |
||
2920 | NULL, /* Comment */ |
||
2921 | NULL, /* HW */ |
||
2922 | os_info_str->str, /* OS */ |
||
2923 | appname, |
||
2924 | -1, /* section_length */ |
||
2925 | &(global_ld.bytes_written), |
||
2926 | &global_ld.err); |
||
2927 | g_free(appname); |
||
2928 | |||
2929 | for (i = 0; successful && (i < capture_opts->ifaces->len); i++) { |
||
2930 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); |
||
2931 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
2932 | successful = pcapng_write_interface_description_block(global_ld.pdh, |
||
2933 | NULL, /* OPT_COMMENT 1 */ |
||
2934 | interface_opts.name, /* IDB_NAME 2 */ |
||
2935 | interface_opts.descr, /* IDB_DESCRIPTION 3 */ |
||
2936 | interface_opts.cfilter, /* IDB_FILTER 11 */ |
||
2937 | os_info_str->str, /* IDB_OS 12 */ |
||
2938 | pcap_opts->linktype, |
||
2939 | pcap_opts->snaplen, |
||
2940 | &(global_ld.bytes_written), |
||
2941 | 0, /* IDB_IF_SPEED 8 */ |
||
2942 | pcap_opts->ts_nsec ? 9 : 6, /* IDB_TSRESOL 9 */ |
||
2943 | &global_ld.err); |
||
2944 | } |
||
2945 | |||
2946 | g_string_free(os_info_str, TRUE); |
||
2947 | |||
2948 | } else { |
||
2949 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, 0); |
||
2950 | successful = libpcap_write_file_header(global_ld.pdh, pcap_opts->linktype, pcap_opts->snaplen, |
||
2951 | pcap_opts->ts_nsec, &global_ld.bytes_written, &global_ld.err); |
||
2952 | } |
||
2953 | if (!successful) { |
||
2954 | fclose(global_ld.pdh); |
||
2955 | global_ld.pdh = NULL; |
||
2956 | global_ld.go = FALSE; |
||
2957 | return FALSE; |
||
2958 | } |
||
2959 | if (cnd_autostop_size) |
||
2960 | cnd_reset(cnd_autostop_size); |
||
2961 | if (cnd_file_duration) |
||
2962 | cnd_reset(cnd_file_duration); |
||
2963 | fflush(global_ld.pdh); |
||
2964 | if (!quiet) |
||
2965 | report_packet_count(global_ld.inpkts_to_sync_pipe); |
||
2966 | global_ld.inpkts_to_sync_pipe = 0; |
||
2967 | report_new_capture_file(capture_opts->save_file); |
||
2968 | } else { |
||
2969 | /* File switch failed: stop here */ |
||
2970 | global_ld.go = FALSE; |
||
2971 | return FALSE; |
||
2972 | } |
||
2973 | } else { |
||
2974 | /* single file, stop now */ |
||
2975 | global_ld.go = FALSE; |
||
2976 | return FALSE; |
||
2977 | } |
||
2978 | return TRUE; |
||
2979 | } |
||
2980 | |||
2981 | static void * |
||
2982 | pcap_read_handler(void* arg) |
||
2983 | { |
||
2984 | pcap_options *pcap_opts; |
||
2985 | char errmsg[MSG_MAX_LENGTH+1]; |
||
2986 | |||
2987 | pcap_opts = (pcap_options *)arg; |
||
2988 | |||
2989 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Started thread for interface %d.", |
||
2990 | pcap_opts->interface_id); |
||
2991 | |||
2992 | while (global_ld.go) { |
||
2993 | /* dispatch incoming packets */ |
||
2994 | capture_loop_dispatch(&global_ld, errmsg, sizeof(errmsg), pcap_opts); |
||
2995 | } |
||
2996 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Stopped thread for interface %d.", |
||
2997 | pcap_opts->interface_id); |
||
2998 | g_thread_exit(NULL); |
||
2999 | return (NULL); |
||
3000 | } |
||
3001 | |||
3002 | /* Do the low-level work of a capture. |
||
3003 | Returns TRUE if it succeeds, FALSE otherwise. */ |
||
3004 | static gboolean |
||
3005 | capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats) |
||
3006 | { |
||
3007 | #ifdef _WIN32 |
||
3008 | DWORD upd_time, cur_time; /* GetTickCount() returns a "DWORD" (which is 'unsigned long') */ |
||
3009 | #else |
||
3010 | struct timeval upd_time, cur_time; |
||
3011 | #endif |
||
3012 | int err_close; |
||
3013 | int inpkts; |
||
3014 | condition *cnd_file_duration = NULL; |
||
3015 | condition *cnd_autostop_files = NULL; |
||
3016 | condition *cnd_autostop_size = NULL; |
||
3017 | condition *cnd_autostop_duration = NULL; |
||
3018 | gboolean write_ok; |
||
3019 | gboolean close_ok; |
||
3020 | gboolean cfilter_error = FALSE; |
||
3021 | char errmsg[MSG_MAX_LENGTH+1]; |
||
3022 | char secondary_errmsg[MSG_MAX_LENGTH+1]; |
||
3023 | pcap_options *pcap_opts; |
||
3024 | interface_options interface_opts; |
||
3025 | guint i, error_index = 0; |
||
3026 | |||
3027 | *errmsg = '\0'; |
||
3028 | *secondary_errmsg = '\0'; |
||
3029 | |||
3030 | /* init the loop data */ |
||
3031 | global_ld.go = TRUE; |
||
3032 | global_ld.packet_count = 0; |
||
3033 | #ifdef SIGINFO |
||
3034 | global_ld.report_packet_count = FALSE; |
||
3035 | #endif |
||
3036 | if (capture_opts->has_autostop_packets) |
||
3037 | global_ld.packet_max = capture_opts->autostop_packets; |
||
3038 | else |
||
3039 | global_ld.packet_max = 0; /* no limit */ |
||
3040 | global_ld.inpkts_to_sync_pipe = 0; |
||
3041 | global_ld.err = 0; /* no error seen yet */ |
||
3042 | global_ld.pdh = NULL; |
||
3043 | global_ld.autostop_files = 0; |
||
3044 | global_ld.save_file_fd = -1; |
||
3045 | |||
3046 | /* We haven't yet gotten the capture statistics. */ |
||
3047 | *stats_known = FALSE; |
||
3048 | |||
3049 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop starting ..."); |
||
3050 | capture_opts_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, capture_opts); |
||
3051 | |||
3052 | /* open the "input file" from network interface or capture pipe */ |
||
3053 | if (!capture_loop_open_input(capture_opts, &global_ld, errmsg, sizeof(errmsg), |
||
3054 | secondary_errmsg, sizeof(secondary_errmsg))) { |
||
3055 | goto error; |
||
3056 | } |
||
3057 | for (i = 0; i < capture_opts->ifaces->len; i++) { |
||
3058 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
3059 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); |
||
3060 | /* init the input filter from the network interface (capture pipe will do nothing) */ |
||
3061 | /* |
||
3062 | * When remote capturing WinPCap crashes when the capture filter |
||
3063 | * is NULL. This might be a bug in WPCap. Therefore we provide an empty |
||
3064 | * string. |
||
3065 | */ |
||
3066 | switch (capture_loop_init_filter(pcap_opts->pcap_h, pcap_opts->from_cap_pipe, |
||
3067 | interface_opts.name, |
||
3068 | interface_opts.cfilter?interface_opts.cfilter:"")) { |
||
3069 | |||
3070 | case INITFILTER_NO_ERROR: |
||
3071 | break; |
||
3072 | |||
3073 | case INITFILTER_BAD_FILTER: |
||
3074 | cfilter_error = TRUE; |
||
3075 | error_index = i; |
||
3076 | g_snprintf(errmsg, sizeof(errmsg), "%s", pcap_geterr(pcap_opts->pcap_h)); |
||
3077 | goto error; |
||
3078 | |||
3079 | case INITFILTER_OTHER_ERROR: |
||
3080 | g_snprintf(errmsg, sizeof(errmsg), "Can't install filter (%s).", |
||
3081 | pcap_geterr(pcap_opts->pcap_h)); |
||
3082 | g_snprintf(secondary_errmsg, sizeof(secondary_errmsg), "%s", please_report); |
||
3083 | goto error; |
||
3084 | } |
||
3085 | } |
||
3086 | |||
3087 | /* If we're supposed to write to a capture file, open it for output |
||
3088 | (temporary/specified name/ringbuffer) */ |
||
3089 | if (capture_opts->saving_to_file) { |
||
3090 | if (!capture_loop_open_output(capture_opts, &global_ld.save_file_fd, |
||
3091 | errmsg, sizeof(errmsg))) { |
||
3092 | goto error; |
||
3093 | } |
||
3094 | |||
3095 | /* set up to write to the already-opened capture output file/files */ |
||
3096 | if (!capture_loop_init_output(capture_opts, &global_ld, errmsg, |
||
3097 | sizeof(errmsg))) { |
||
3098 | goto error; |
||
3099 | } |
||
3100 | |||
3101 | /* XXX - capture SIGTERM and close the capture, in case we're on a |
||
3102 | Linux 2.0[.x] system and you have to explicitly close the capture |
||
3103 | stream in order to turn promiscuous mode off? We need to do that |
||
3104 | in other places as well - and I don't think that works all the |
||
3105 | time in any case, due to libpcap bugs. */ |
||
3106 | |||
3107 | /* Well, we should be able to start capturing. |
||
3108 | |||
3109 | Sync out the capture file, so the header makes it to the file system, |
||
3110 | and send a "capture started successfully and capture file created" |
||
3111 | message to our parent so that they'll open the capture file and |
||
3112 | update its windows to indicate that we have a live capture in |
||
3113 | progress. */ |
||
3114 | fflush(global_ld.pdh); |
||
3115 | report_new_capture_file(capture_opts->save_file); |
||
3116 | } |
||
3117 | |||
3118 | /* initialize capture stop (and alike) conditions */ |
||
3119 | init_capture_stop_conditions(); |
||
3120 | /* create stop conditions */ |
||
3121 | if (capture_opts->has_autostop_filesize) { |
||
3122 | if (capture_opts->autostop_filesize > (((guint32)INT_MAX + 1) / 1000)) { |
||
3123 | capture_opts->autostop_filesize = ((guint32)INT_MAX + 1) / 1000; |
||
3124 | } |
||
3125 | cnd_autostop_size = |
||
3126 | cnd_new(CND_CLASS_CAPTURESIZE, (guint64)capture_opts->autostop_filesize * 1000); |
||
3127 | } |
||
3128 | if (capture_opts->has_autostop_duration) |
||
3129 | cnd_autostop_duration = |
||
3130 | cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts->autostop_duration); |
||
3131 | |||
3132 | if (capture_opts->multi_files_on) { |
||
3133 | if (capture_opts->has_file_duration) |
||
3134 | cnd_file_duration = |
||
3135 | cnd_new(CND_CLASS_TIMEOUT, capture_opts->file_duration); |
||
3136 | |||
3137 | if (capture_opts->has_autostop_files) |
||
3138 | cnd_autostop_files = |
||
3139 | cnd_new(CND_CLASS_CAPTURESIZE, (guint64)capture_opts->autostop_files); |
||
3140 | } |
||
3141 | |||
3142 | /* init the time values */ |
||
3143 | #ifdef _WIN32 |
||
3144 | upd_time = GetTickCount(); |
||
3145 | #else |
||
3146 | gettimeofday(&upd_time, NULL); |
||
3147 | #endif |
||
3148 | start_time = create_timestamp(); |
||
3149 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop running."); |
||
3150 | |||
3151 | /* WOW, everything is prepared! */ |
||
3152 | /* please fasten your seat belts, we will enter now the actual capture loop */ |
||
3153 | if (use_threads) { |
||
3154 | pcap_queue = g_async_queue_new(); |
||
3155 | pcap_queue_bytes = 0; |
||
3156 | pcap_queue_packets = 0; |
||
3157 | for (i = 0; i < global_ld.pcaps->len; i++) { |
||
3158 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
3159 | #if GLIB_CHECK_VERSION(2,31,0) |
||
3160 | /* XXX - Add an interface name here? */ |
||
3161 | pcap_opts->tid = g_thread_new("Capture read", pcap_read_handler, pcap_opts); |
||
3162 | #else |
||
3163 | pcap_opts->tid = g_thread_create(pcap_read_handler, pcap_opts, TRUE, NULL); |
||
3164 | #endif |
||
3165 | } |
||
3166 | } |
||
3167 | while (global_ld.go) { |
||
3168 | /* dispatch incoming packets */ |
||
3169 | if (use_threads) { |
||
3170 | pcap_queue_element *queue_element; |
||
3171 | #if GLIB_CHECK_VERSION(2,31,18) |
||
3172 | |||
3173 | g_async_queue_lock(pcap_queue); |
||
3174 | queue_element = (pcap_queue_element *)g_async_queue_timeout_pop_unlocked(pcap_queue, WRITER_THREAD_TIMEOUT); |
||
3175 | #else |
||
3176 | GTimeVal write_thread_time; |
||
3177 | |||
3178 | g_get_current_time(&write_thread_time); |
||
3179 | g_time_val_add(&write_thread_time, WRITER_THREAD_TIMEOUT); |
||
3180 | g_async_queue_lock(pcap_queue); |
||
3181 | queue_element = (pcap_queue_element *)g_async_queue_timed_pop_unlocked(pcap_queue, &write_thread_time); |
||
3182 | #endif |
||
3183 | if (queue_element) { |
||
3184 | pcap_queue_bytes -= queue_element->phdr.caplen; |
||
3185 | pcap_queue_packets -= 1; |
||
3186 | } |
||
3187 | g_async_queue_unlock(pcap_queue); |
||
3188 | if (queue_element) { |
||
3189 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
3190 | "Dequeued a packet of length %d captured on interface %d.", |
||
3191 | queue_element->phdr.caplen, queue_element->pcap_opts->interface_id); |
||
3192 | |||
3193 | capture_loop_write_packet_cb((u_char *) queue_element->pcap_opts, |
||
3194 | &queue_element->phdr, |
||
3195 | queue_element->pd); |
||
3196 | g_free(queue_element->pd); |
||
3197 | g_free(queue_element); |
||
3198 | inpkts = 1; |
||
3199 | } else { |
||
3200 | inpkts = 0; |
||
3201 | } |
||
3202 | } else { |
||
3203 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, 0); |
||
3204 | inpkts = capture_loop_dispatch(&global_ld, errmsg, |
||
3205 | sizeof(errmsg), pcap_opts); |
||
3206 | } |
||
3207 | #ifdef SIGINFO |
||
3208 | /* Were we asked to print packet counts by the SIGINFO handler? */ |
||
3209 | if (global_ld.report_packet_count) { |
||
3210 | fprintf(stderr, "%u packet%s captured\n", global_ld.packet_count, |
||
3211 | plurality(global_ld.packet_count, "", "s")); |
||
3212 | global_ld.report_packet_count = FALSE; |
||
3213 | } |
||
3214 | #endif |
||
3215 | |||
3216 | #ifdef _WIN32 |
||
3217 | /* any news from our parent (signal pipe)? -> just stop the capture */ |
||
3218 | if (!signal_pipe_check_running()) { |
||
3219 | global_ld.go = FALSE; |
||
3220 | } |
||
3221 | #endif |
||
3222 | |||
3223 | if (inpkts > 0) { |
||
3224 | global_ld.inpkts_to_sync_pipe += inpkts; |
||
3225 | |||
3226 | /* check capture size condition */ |
||
3227 | if (cnd_autostop_size != NULL && |
||
3228 | cnd_eval(cnd_autostop_size, global_ld.bytes_written)) { |
||
3229 | /* Capture size limit reached, do we have another file? */ |
||
3230 | if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files, |
||
3231 | cnd_autostop_size, cnd_file_duration)) |
||
3232 | continue; |
||
3233 | } /* cnd_autostop_size */ |
||
3234 | if (capture_opts->output_to_pipe) { |
||
3235 | fflush(global_ld.pdh); |
||
3236 | } |
||
3237 | } /* inpkts */ |
||
3238 | |||
3239 | /* Only update once every 500ms so as not to overload slow displays. |
||
3240 | * This also prevents too much context-switching between the dumpcap |
||
3241 | * and wireshark processes. |
||
3242 | */ |
||
3243 | #define DUMPCAP_UPD_TIME 500 |
||
3244 | |||
3245 | #ifdef _WIN32 |
||
3246 | cur_time = GetTickCount(); /* Note: wraps to 0 if sys runs for 49.7 days */ |
||
3247 | if ((cur_time - upd_time) > DUMPCAP_UPD_TIME) { /* wrap just causes an extra update */ |
||
3248 | #else |
||
3249 | gettimeofday(&cur_time, NULL); |
||
3250 | if (((guint64)cur_time.tv_sec * 1000000 + cur_time.tv_usec) > |
||
3251 | ((guint64)upd_time.tv_sec * 1000000 + upd_time.tv_usec + DUMPCAP_UPD_TIME*1000)) { |
||
3252 | #endif |
||
3253 | |||
3254 | upd_time = cur_time; |
||
3255 | |||
3256 | #if 0 |
||
3257 | if (pcap_stats(pch, stats) >= 0) { |
||
3258 | *stats_known = TRUE; |
||
3259 | } |
||
3260 | #endif |
||
3261 | /* Let the parent process know. */ |
||
3262 | if (global_ld.inpkts_to_sync_pipe) { |
||
3263 | /* do sync here */ |
||
3264 | fflush(global_ld.pdh); |
||
3265 | |||
3266 | /* Send our parent a message saying we've written out |
||
3267 | "global_ld.inpkts_to_sync_pipe" packets to the capture file. */ |
||
3268 | if (!quiet) |
||
3269 | report_packet_count(global_ld.inpkts_to_sync_pipe); |
||
3270 | |||
3271 | global_ld.inpkts_to_sync_pipe = 0; |
||
3272 | } |
||
3273 | |||
3274 | /* check capture duration condition */ |
||
3275 | if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) { |
||
3276 | /* The maximum capture time has elapsed; stop the capture. */ |
||
3277 | global_ld.go = FALSE; |
||
3278 | continue; |
||
3279 | } |
||
3280 | |||
3281 | /* check capture file duration condition */ |
||
3282 | if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) { |
||
3283 | /* duration limit reached, do we have another file? */ |
||
3284 | if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files, |
||
3285 | cnd_autostop_size, cnd_file_duration)) |
||
3286 | continue; |
||
3287 | } /* cnd_file_duration */ |
||
3288 | } |
||
3289 | } |
||
3290 | |||
3291 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopping ..."); |
||
3292 | if (use_threads) { |
||
3293 | pcap_queue_element *queue_element; |
||
3294 | |||
3295 | for (i = 0; i < global_ld.pcaps->len; i++) { |
||
3296 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
3297 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Waiting for thread of interface %u...", |
||
3298 | pcap_opts->interface_id); |
||
3299 | g_thread_join(pcap_opts->tid); |
||
3300 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Thread of interface %u terminated.", |
||
3301 | pcap_opts->interface_id); |
||
3302 | } |
||
3303 | while (1) { |
||
3304 | g_async_queue_lock(pcap_queue); |
||
3305 | queue_element = (pcap_queue_element *)g_async_queue_try_pop_unlocked(pcap_queue); |
||
3306 | if (queue_element) { |
||
3307 | pcap_queue_bytes -= queue_element->phdr.caplen; |
||
3308 | pcap_queue_packets -= 1; |
||
3309 | } |
||
3310 | g_async_queue_unlock(pcap_queue); |
||
3311 | if (queue_element == NULL) { |
||
3312 | break; |
||
3313 | } |
||
3314 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
3315 | "Dequeued a packet of length %d captured on interface %d.", |
||
3316 | queue_element->phdr.caplen, queue_element->pcap_opts->interface_id); |
||
3317 | capture_loop_write_packet_cb((u_char *)queue_element->pcap_opts, |
||
3318 | &queue_element->phdr, |
||
3319 | queue_element->pd); |
||
3320 | g_free(queue_element->pd); |
||
3321 | g_free(queue_element); |
||
3322 | global_ld.inpkts_to_sync_pipe += 1; |
||
3323 | if (capture_opts->output_to_pipe) { |
||
3324 | fflush(global_ld.pdh); |
||
3325 | } |
||
3326 | } |
||
3327 | } |
||
3328 | |||
3329 | |||
3330 | /* delete stop conditions */ |
||
3331 | if (cnd_file_duration != NULL) |
||
3332 | cnd_delete(cnd_file_duration); |
||
3333 | if (cnd_autostop_files != NULL) |
||
3334 | cnd_delete(cnd_autostop_files); |
||
3335 | if (cnd_autostop_size != NULL) |
||
3336 | cnd_delete(cnd_autostop_size); |
||
3337 | if (cnd_autostop_duration != NULL) |
||
3338 | cnd_delete(cnd_autostop_duration); |
||
3339 | |||
3340 | /* did we have a pcap (input) error? */ |
||
3341 | for (i = 0; i < capture_opts->ifaces->len; i++) { |
||
3342 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
3343 | if (pcap_opts->pcap_err) { |
||
3344 | /* On Linux, if an interface goes down while you're capturing on it, |
||
3345 | you'll get a "recvfrom: Network is down" or |
||
3346 | "The interface went down" error (ENETDOWN). |
||
3347 | (At least you will if g_strerror() doesn't show a local translation |
||
3348 | of the error.) |
||
3349 | |||
3350 | On FreeBSD and OS X, if a network adapter disappears while |
||
3351 | you're capturing on it, you'll get a "read: Device not configured" |
||
3352 | error (ENXIO). (See previous parenthetical note.) |
||
3353 | |||
3354 | On OpenBSD, you get "read: I/O error" (EIO) in the same case. |
||
3355 | |||
3356 | These should *not* be reported to the Wireshark developers. */ |
||
3357 | char *cap_err_str; |
||
3358 | |||
3359 | cap_err_str = pcap_geterr(pcap_opts->pcap_h); |
||
3360 | if (strcmp(cap_err_str, "recvfrom: Network is down") == 0 || |
||
3361 | strcmp(cap_err_str, "The interface went down") == 0 || |
||
3362 | strcmp(cap_err_str, "read: Device not configured") == 0 || |
||
3363 | strcmp(cap_err_str, "read: I/O error") == 0 || |
||
3364 | strcmp(cap_err_str, "read error: PacketReceivePacket failed") == 0) { |
||
3365 | report_capture_error("The network adapter on which the capture was being done " |
||
3366 | "is no longer running; the capture has stopped.", |
||
3367 | ""); |
||
3368 | } else { |
||
3369 | g_snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s", |
||
3370 | cap_err_str); |
||
3371 | report_capture_error(errmsg, please_report); |
||
3372 | } |
||
3373 | break; |
||
3374 | } else if (pcap_opts->from_cap_pipe && pcap_opts->cap_pipe_err == PIPERR) { |
||
3375 | report_capture_error(errmsg, ""); |
||
3376 | break; |
||
3377 | } |
||
3378 | } |
||
3379 | /* did we have an output error while capturing? */ |
||
3380 | if (global_ld.err == 0) { |
||
3381 | write_ok = TRUE; |
||
3382 | } else { |
||
3383 | capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, |
||
3384 | global_ld.err, FALSE); |
||
3385 | report_capture_error(errmsg, please_report); |
||
3386 | write_ok = FALSE; |
||
3387 | } |
||
3388 | |||
3389 | if (capture_opts->saving_to_file) { |
||
3390 | /* close the output file */ |
||
3391 | close_ok = capture_loop_close_output(capture_opts, &global_ld, &err_close); |
||
3392 | } else |
||
3393 | close_ok = TRUE; |
||
3394 | |||
3395 | /* there might be packets not yet notified to the parent */ |
||
3396 | /* (do this after closing the file, so all packets are already flushed) */ |
||
3397 | if (global_ld.inpkts_to_sync_pipe) { |
||
3398 | if (!quiet) |
||
3399 | report_packet_count(global_ld.inpkts_to_sync_pipe); |
||
3400 | global_ld.inpkts_to_sync_pipe = 0; |
||
3401 | } |
||
3402 | |||
3403 | /* If we've displayed a message about a write error, there's no point |
||
3404 | in displaying another message about an error on close. */ |
||
3405 | if (!close_ok && write_ok) { |
||
3406 | capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, err_close, |
||
3407 | TRUE); |
||
3408 | report_capture_error(errmsg, ""); |
||
3409 | } |
||
3410 | |||
3411 | /* |
||
3412 | * XXX We exhibit different behaviour between normal mode and sync mode |
||
3413 | * when the pipe is stdin and not already at EOF. If we're a child, the |
||
3414 | * parent's stdin isn't closed, so if the user starts another capture, |
||
3415 | * cap_pipe_open_live() will very likely not see the expected magic bytes and |
||
3416 | * will say "Unrecognized libpcap format". On the other hand, in normal |
||
3417 | * mode, cap_pipe_open_live() will say "End of file on pipe during open". |
||
3418 | */ |
||
3419 | |||
3420 | report_capture_count(TRUE); |
||
3421 | |||
3422 | /* get packet drop statistics from pcap */ |
||
3423 | for (i = 0; i < capture_opts->ifaces->len; i++) { |
||
3424 | guint32 received; |
||
3425 | guint32 pcap_dropped = 0; |
||
3426 | |||
3427 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
3428 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); |
||
3429 | received = pcap_opts->received; |
||
3430 | if (pcap_opts->pcap_h != NULL) { |
||
3431 | g_assert(!pcap_opts->from_cap_pipe); |
||
3432 | /* Get the capture statistics, so we know how many packets were dropped. */ |
||
3433 | /* |
||
3434 | * Older versions of libpcap didn't set ps_ifdrop on some |
||
3435 | * platforms; initialize it to 0 to handle that. |
||
3436 | */ |
||
3437 | stats->ps_ifdrop = 0; |
||
3438 | if (pcap_stats(pcap_opts->pcap_h, stats) >= 0) { |
||
3439 | *stats_known = TRUE; |
||
3440 | /* Let the parent process know. */ |
||
3441 | pcap_dropped += stats->ps_drop; |
||
3442 | } else { |
||
3443 | g_snprintf(errmsg, sizeof(errmsg), |
||
3444 | "Can't get packet-drop statistics: %s", |
||
3445 | pcap_geterr(pcap_opts->pcap_h)); |
||
3446 | report_capture_error(errmsg, please_report); |
||
3447 | } |
||
3448 | } |
||
3449 | report_packet_drops(received, pcap_dropped, pcap_opts->dropped, pcap_opts->flushed, stats->ps_ifdrop, interface_opts.console_display_name); |
||
3450 | } |
||
3451 | |||
3452 | /* close the input file (pcap or capture pipe) */ |
||
3453 | capture_loop_close_input(&global_ld); |
||
3454 | |||
3455 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped."); |
||
3456 | |||
3457 | /* ok, if the write and the close were successful. */ |
||
3458 | return write_ok && close_ok; |
||
3459 | |||
3460 | error: |
||
3461 | if (capture_opts->multi_files_on) { |
||
3462 | /* cleanup ringbuffer */ |
||
3463 | ringbuf_error_cleanup(); |
||
3464 | } else { |
||
3465 | /* We can't use the save file, and we have no FILE * for the stream |
||
3466 | to close in order to close it, so close the FD directly. */ |
||
3467 | if (global_ld.save_file_fd != -1) { |
||
3468 | ws_close(global_ld.save_file_fd); |
||
3469 | } |
||
3470 | |||
3471 | /* We couldn't even start the capture, so get rid of the capture |
||
3472 | file. */ |
||
3473 | if (capture_opts->save_file != NULL) { |
||
3474 | ws_unlink(capture_opts->save_file); |
||
3475 | g_free(capture_opts->save_file); |
||
3476 | } |
||
3477 | } |
||
3478 | capture_opts->save_file = NULL; |
||
3479 | if (cfilter_error) |
||
3480 | report_cfilter_error(capture_opts, error_index, errmsg); |
||
3481 | else |
||
3482 | report_capture_error(errmsg, secondary_errmsg); |
||
3483 | |||
3484 | /* close the input file (pcap or cap_pipe) */ |
||
3485 | capture_loop_close_input(&global_ld); |
||
3486 | |||
3487 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped with error"); |
||
3488 | |||
3489 | return FALSE; |
||
3490 | } |
||
3491 | |||
3492 | |||
3493 | static void |
||
3494 | capture_loop_stop(void) |
||
3495 | { |
||
3496 | #ifdef HAVE_PCAP_BREAKLOOP |
||
3497 | guint i; |
||
3498 | pcap_options *pcap_opts; |
||
3499 | |||
3500 | for (i = 0; i < global_ld.pcaps->len; i++) { |
||
3501 | pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i); |
||
3502 | if (pcap_opts->pcap_h != NULL) |
||
3503 | pcap_breakloop(pcap_opts->pcap_h); |
||
3504 | } |
||
3505 | #endif |
||
3506 | global_ld.go = FALSE; |
||
3507 | } |
||
3508 | |||
3509 | |||
3510 | static void |
||
3511 | capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fname, |
||
3512 | int err, gboolean is_close) |
||
3513 | { |
||
3514 | switch (err) { |
||
3515 | |||
3516 | case ENOSPC: |
||
3517 | g_snprintf(errmsg, errmsglen, |
||
3518 | "Not all the packets could be written to the file" |
||
3519 | " to which the capture was being saved\n" |
||
3520 | "(\"%s\") because there is no space left on the file system\n" |
||
3521 | "on which that file resides.", |
||
3522 | fname); |
||
3523 | break; |
||
3524 | |||
3525 | #ifdef EDQUOT |
||
3526 | case EDQUOT: |
||
3527 | g_snprintf(errmsg, errmsglen, |
||
3528 | "Not all the packets could be written to the file" |
||
3529 | " to which the capture was being saved\n" |
||
3530 | "(\"%s\") because you are too close to, or over," |
||
3531 | " your disk quota\n" |
||
3532 | "on the file system on which that file resides.", |
||
3533 | fname); |
||
3534 | break; |
||
3535 | #endif |
||
3536 | |||
3537 | default: |
||
3538 | if (is_close) { |
||
3539 | g_snprintf(errmsg, errmsglen, |
||
3540 | "The file to which the capture was being saved\n" |
||
3541 | "(\"%s\") could not be closed: %s.", |
||
3542 | fname, g_strerror(err)); |
||
3543 | } else { |
||
3544 | g_snprintf(errmsg, errmsglen, |
||
3545 | "An error occurred while writing to the file" |
||
3546 | " to which the capture was being saved\n" |
||
3547 | "(\"%s\"): %s.", |
||
3548 | fname, g_strerror(err)); |
||
3549 | } |
||
3550 | break; |
||
3551 | } |
||
3552 | } |
||
3553 | |||
3554 | |||
3555 | /* one packet was captured, process it */ |
||
3556 | static void |
||
3557 | capture_loop_write_packet_cb(u_char *pcap_opts_p, const struct pcap_pkthdr *phdr, |
||
3558 | const u_char *pd) |
||
3559 | { |
||
3560 | pcap_options *pcap_opts = (pcap_options *) (void *) pcap_opts_p; |
||
3561 | int err; |
||
3562 | guint ts_mul = pcap_opts->ts_nsec ? 1000000000 : 1000000; |
||
3563 | |||
3564 | /* We may be called multiple times from pcap_dispatch(); if we've set |
||
3565 | the "stop capturing" flag, ignore this packet, as we're not |
||
3566 | supposed to be saving any more packets. */ |
||
3567 | if (!global_ld.go) { |
||
3568 | pcap_opts->flushed++; |
||
3569 | return; |
||
3570 | } |
||
3571 | |||
3572 | if (global_ld.pdh) { |
||
3573 | gboolean successful; |
||
3574 | |||
3575 | /* We're supposed to write the packet to a file; do so. |
||
3576 | If this fails, set "ld->go" to FALSE, to stop the capture, and set |
||
3577 | "ld->err" to the error. */ |
||
3578 | if (global_capture_opts.use_pcapng) { |
||
3579 | successful = pcapng_write_enhanced_packet_block(global_ld.pdh, |
||
3580 | NULL, |
||
3581 | phdr->ts.tv_sec, (gint32)phdr->ts.tv_usec, |
||
3582 | phdr->caplen, phdr->len, |
||
3583 | pcap_opts->interface_id, |
||
3584 | ts_mul, |
||
3585 | pd, 0, |
||
3586 | &global_ld.bytes_written, &err); |
||
3587 | } else { |
||
3588 | successful = libpcap_write_packet(global_ld.pdh, |
||
3589 | phdr->ts.tv_sec, (gint32)phdr->ts.tv_usec, |
||
3590 | phdr->caplen, phdr->len, |
||
3591 | pd, |
||
3592 | &global_ld.bytes_written, &err); |
||
3593 | } |
||
3594 | if (!successful) { |
||
3595 | global_ld.go = FALSE; |
||
3596 | global_ld.err = err; |
||
3597 | pcap_opts->dropped++; |
||
3598 | } else { |
||
3599 | #if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP) |
||
3600 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
3601 | "Wrote a packet of length %d captured on interface %u.", |
||
3602 | phdr->caplen, pcap_opts->interface_id); |
||
3603 | #endif |
||
3604 | global_ld.packet_count++; |
||
3605 | pcap_opts->received++; |
||
3606 | /* if the user told us to stop after x packets, do we already have enough? */ |
||
3607 | if ((global_ld.packet_max > 0) && (global_ld.packet_count >= global_ld.packet_max)) { |
||
3608 | global_ld.go = FALSE; |
||
3609 | } |
||
3610 | } |
||
3611 | } |
||
3612 | } |
||
3613 | |||
3614 | /* one packet was captured, queue it */ |
||
3615 | static void |
||
3616 | capture_loop_queue_packet_cb(u_char *pcap_opts_p, const struct pcap_pkthdr *phdr, |
||
3617 | const u_char *pd) |
||
3618 | { |
||
3619 | pcap_options *pcap_opts = (pcap_options *) (void *) pcap_opts_p; |
||
3620 | pcap_queue_element *queue_element; |
||
3621 | gboolean limit_reached; |
||
3622 | |||
3623 | /* We may be called multiple times from pcap_dispatch(); if we've set |
||
3624 | the "stop capturing" flag, ignore this packet, as we're not |
||
3625 | supposed to be saving any more packets. */ |
||
3626 | if (!global_ld.go) { |
||
3627 | pcap_opts->flushed++; |
||
3628 | return; |
||
3629 | } |
||
3630 | |||
3631 | queue_element = (pcap_queue_element *)g_malloc(sizeof(pcap_queue_element)); |
||
3632 | if (queue_element == NULL) { |
||
3633 | pcap_opts->dropped++; |
||
3634 | return; |
||
3635 | } |
||
3636 | queue_element->pcap_opts = pcap_opts; |
||
3637 | queue_element->phdr = *phdr; |
||
3638 | queue_element->pd = (u_char *)g_malloc(phdr->caplen); |
||
3639 | if (queue_element->pd == NULL) { |
||
3640 | pcap_opts->dropped++; |
||
3641 | g_free(queue_element); |
||
3642 | return; |
||
3643 | } |
||
3644 | memcpy(queue_element->pd, pd, phdr->caplen); |
||
3645 | g_async_queue_lock(pcap_queue); |
||
3646 | if (((pcap_queue_byte_limit == 0) || (pcap_queue_bytes < pcap_queue_byte_limit)) && |
||
3647 | ((pcap_queue_packet_limit == 0) || (pcap_queue_packets < pcap_queue_packet_limit))) { |
||
3648 | limit_reached = FALSE; |
||
3649 | g_async_queue_push_unlocked(pcap_queue, queue_element); |
||
3650 | pcap_queue_bytes += phdr->caplen; |
||
3651 | pcap_queue_packets += 1; |
||
3652 | } else { |
||
3653 | limit_reached = TRUE; |
||
3654 | } |
||
3655 | g_async_queue_unlock(pcap_queue); |
||
3656 | if (limit_reached) { |
||
3657 | pcap_opts->dropped++; |
||
3658 | g_free(queue_element->pd); |
||
3659 | g_free(queue_element); |
||
3660 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
3661 | "Dropped a packet of length %d captured on interface %u.", |
||
3662 | phdr->caplen, pcap_opts->interface_id); |
||
3663 | } else { |
||
3664 | pcap_opts->received++; |
||
3665 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
3666 | "Queued a packet of length %d captured on interface %u.", |
||
3667 | phdr->caplen, pcap_opts->interface_id); |
||
3668 | } |
||
3669 | /* I don't want to hold the mutex over the debug output. So the |
||
3670 | output may be wrong */ |
||
3671 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
3672 | "Queue size is now %" G_GINT64_MODIFIER "d bytes (%" G_GINT64_MODIFIER "d packets)", |
||
3673 | pcap_queue_bytes, pcap_queue_packets); |
||
3674 | } |
||
3675 | |||
3676 | static int |
||
3677 | set_80211_channel(const char *iface, const char *opt) |
||
3678 | { |
||
3679 | int freq = 0; |
||
3680 | int type = -1; |
||
3681 | int center_freq1 = -1; |
||
3682 | int center_freq2 = -1; |
||
3683 | int args; |
||
3684 | int ret; |
||
3685 | gchar **options = NULL; |
||
3686 | |||
3687 | options = g_strsplit_set(opt, ",", 4); |
||
3688 | for (args = 0; options[args]; args++); |
||
3689 | |||
3690 | if (options[0]) |
||
3691 | freq = atoi(options[0]); |
||
3692 | |||
3693 | if (args >= 1 && options[1]) { |
||
3694 | type = ws80211_str_to_chan_type(options[1]); |
||
3695 | if (type == -1) { |
||
3696 | ret = EINVAL; |
||
3697 | goto out; |
||
3698 | } |
||
3699 | } |
||
3700 | |||
3701 | if (args >= 2 && options[2]) |
||
3702 | center_freq1 = atoi(options[2]); |
||
3703 | |||
3704 | if (args >= 3 && options[3]) |
||
3705 | center_freq2 = atoi(options[3]); |
||
3706 | |||
3707 | ret = ws80211_init(); |
||
3708 | if (ret) { |
||
3709 | cmdarg_err("%d: Failed to init ws80211: %s\n", abs(ret), g_strerror(abs(ret))); |
||
3710 | ret = 2; |
||
3711 | goto out; |
||
3712 | } |
||
3713 | ret = ws80211_set_freq(iface, freq, type, center_freq1, center_freq2); |
||
3714 | |||
3715 | if (ret) { |
||
3716 | cmdarg_err("%d: Failed to set channel: %s\n", abs(ret), g_strerror(abs(ret))); |
||
3717 | ret = 2; |
||
3718 | goto out; |
||
3719 | } |
||
3720 | |||
3721 | if (capture_child) |
||
3722 | pipe_write_block(2, SP_SUCCESS, NULL); |
||
3723 | ret = 0; |
||
3724 | |||
3725 | out: |
||
3726 | g_strfreev(options); |
||
3727 | return ret; |
||
3728 | } |
||
3729 | |||
3730 | static void |
||
3731 | get_dumpcap_compiled_info(GString *str) |
||
3732 | { |
||
3733 | /* Capture libraries */ |
||
3734 | g_string_append(str, ", "); |
||
3735 | get_compiled_caplibs_version(str); |
||
3736 | } |
||
3737 | |||
3738 | static void |
||
3739 | get_dumpcap_runtime_info(GString *str) |
||
3740 | { |
||
3741 | /* Capture libraries */ |
||
3742 | g_string_append(str, ", "); |
||
3743 | get_runtime_caplibs_version(str); |
||
3744 | } |
||
3745 | |||
3746 | /* And now our feature presentation... [ fade to music ] */ |
||
3747 | int |
||
3748 | main(int argc, char *argv[]) |
||
3749 | { |
||
3750 | GString *comp_info_str; |
||
3751 | GString *runtime_info_str; |
||
3752 | int opt; |
||
3753 | static const struct option long_options[] = { |
||
3754 | {"help", no_argument, NULL, 'h'}, |
||
3755 | {"version", no_argument, NULL, 'v'}, |
||
3756 | LONGOPT_CAPTURE_COMMON |
||
3757 | {0, 0, 0, 0 } |
||
3758 | }; |
||
3759 | |||
3760 | gboolean arg_error = FALSE; |
||
3761 | |||
3762 | #ifdef _WIN32 |
||
3763 | WSADATA wsaData; |
||
3764 | #else |
||
3765 | struct sigaction action, oldaction; |
||
3766 | #endif |
||
3767 | |||
3768 | gboolean start_capture = TRUE; |
||
3769 | gboolean stats_known; |
||
3770 | struct pcap_stat stats; |
||
3771 | GLogLevelFlags log_flags; |
||
3772 | gboolean list_interfaces = FALSE; |
||
3773 | gboolean list_link_layer_types = FALSE; |
||
3774 | #ifdef HAVE_BPF_IMAGE |
||
3775 | gboolean print_bpf_code = FALSE; |
||
3776 | #endif |
||
3777 | gboolean set_chan = FALSE; |
||
3778 | gchar *set_chan_arg = NULL; |
||
3779 | gboolean machine_readable = FALSE; |
||
3780 | gboolean print_statistics = FALSE; |
||
3781 | int status, run_once_args = 0; |
||
3782 | gint i; |
||
3783 | guint j; |
||
3784 | #if defined(__APPLE__) && defined(__LP64__) |
||
3785 | struct utsname osinfo; |
||
3786 | #endif |
||
3787 | GString *str; |
||
3788 | |||
3789 | cmdarg_err_init(dumpcap_cmdarg_err, dumpcap_cmdarg_err_cont); |
||
3790 | |||
3791 | /* Get the compile-time version information string */ |
||
3792 | comp_info_str = get_compiled_version_info(NULL, get_dumpcap_compiled_info); |
||
3793 | |||
3794 | /* Get the run-time version information string */ |
||
3795 | runtime_info_str = get_runtime_version_info(get_dumpcap_runtime_info); |
||
3796 | |||
3797 | /* Add it to the information to be reported on a crash. */ |
||
3798 | ws_add_crash_info("Dumpcap (Wireshark) %s\n" |
||
3799 | "\n" |
||
3800 | "%s" |
||
3801 | "\n" |
||
3802 | "%s", |
||
3803 | get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str); |
||
3804 | g_string_free(comp_info_str, TRUE); |
||
3805 | g_string_free(runtime_info_str, TRUE); |
||
3806 | |||
3807 | #ifdef _WIN32 |
||
3808 | arg_list_utf_16to8(argc, argv); |
||
3809 | create_app_running_mutex(); |
||
3810 | |||
3811 | /* |
||
3812 | * Initialize our DLL search path. MUST be called before LoadLibrary |
||
3813 | * or g_module_open. |
||
3814 | */ |
||
3815 | ws_init_dll_search_path(); |
||
3816 | #endif |
||
3817 | |||
3818 | #ifdef HAVE_BPF_IMAGE |
||
3819 | #define OPTSTRING_d "d" |
||
3820 | #else |
||
3821 | #define OPTSTRING_d "" |
||
3822 | #endif |
||
3823 | |||
3824 | #ifdef HAVE_PCAP_REMOTE |
||
3825 | #define OPTSTRING_r "r" |
||
3826 | #define OPTSTRING_u "u" |
||
3827 | #else |
||
3828 | #define OPTSTRING_r "" |
||
3829 | #define OPTSTRING_u "" |
||
3830 | #endif |
||
3831 | |||
3832 | #ifdef HAVE_PCAP_SETSAMPLING |
||
3833 | #define OPTSTRING_m "m:" |
||
3834 | #else |
||
3835 | #define OPTSTRING_m "" |
||
3836 | #endif |
||
3837 | |||
3838 | #define OPTSTRING OPTSTRING_CAPTURE_COMMON "C:" OPTSTRING_d "gh" "k:" OPTSTRING_m "MN:nPq" OPTSTRING_r "St" OPTSTRING_u "vw:Z:" |
||
3839 | |||
3840 | #ifdef DEBUG_CHILD_DUMPCAP |
||
3841 | if ((debug_log = ws_fopen("dumpcap_debug_log.tmp","w")) == NULL) { |
||
3842 | fprintf (stderr, "Unable to open debug log file .\n"); |
||
3843 | exit (1); |
||
3844 | } |
||
3845 | #endif |
||
3846 | |||
3847 | #if defined(__APPLE__) && defined(__LP64__) |
||
3848 | /* |
||
3849 | * Is this Mac OS X 10.6.0, 10.6.1, 10.6.3, or 10.6.4? If so, we need |
||
3850 | * a bug workaround - timeouts less than 1 second don't work with libpcap |
||
3851 | * in 64-bit code. (The bug was introduced in 10.6, fixed in 10.6.2, |
||
3852 | * re-introduced in 10.6.3, not fixed in 10.6.4, and fixed in 10.6.5. |
||
3853 | * The problem is extremely unlikely to be reintroduced in a future |
||
3854 | * release.) |
||
3855 | */ |
||
3856 | if (uname(&osinfo) == 0) { |
||
3857 | /* |
||
3858 | * Mac OS X 10.x uses Darwin {x+4}.0.0. Mac OS X 10.x.y uses Darwin |
||
3859 | * {x+4}.y.0 (except that 10.6.1 appears to have a uname version |
||
3860 | * number of 10.0.0, not 10.1.0 - go figure). |
||
3861 | */ |
||
3862 | if (strcmp(osinfo.release, "10.0.0") == 0 || /* 10.6, 10.6.1 */ |
||
3863 | strcmp(osinfo.release, "10.3.0") == 0 || /* 10.6.3 */ |
||
3864 | strcmp(osinfo.release, "10.4.0") == 0) /* 10.6.4 */ |
||
3865 | need_timeout_workaround = TRUE; |
||
3866 | } |
||
3867 | #endif |
||
3868 | |||
3869 | /* |
||
3870 | * Determine if dumpcap is being requested to run in a special |
||
3871 | * capture_child mode by going thru the command line args to see if |
||
3872 | * a -Z is present. (-Z is a hidden option). |
||
3873 | * |
||
3874 | * The primary result of running in capture_child mode is that |
||
3875 | * all messages sent out on stderr are in a special type/len/string |
||
3876 | * format to allow message processing by type. These messages include |
||
3877 | * error messages if dumpcap fails to start the operation it was |
||
3878 | * requested to do, as well as various "status" messages which are sent |
||
3879 | * when an actual capture is in progress, and a "success" message sent |
||
3880 | * if dumpcap was requested to perform an operation other than a |
||
3881 | * capture. |
||
3882 | * |
||
3883 | * Capture_child mode would normally be requested by a parent process |
||
3884 | * which invokes dumpcap and obtains dumpcap stderr output via a pipe |
||
3885 | * to which dumpcap stderr has been redirected. It might also have |
||
3886 | * another pipe to obtain dumpcap stdout output; for operations other |
||
3887 | * than a capture, that information is formatted specially for easier |
||
3888 | * parsing by the parent process. |
||
3889 | * |
||
3890 | * Capture_child mode needs to be determined immediately upon |
||
3891 | * startup so that any messages generated by dumpcap in this mode |
||
3892 | * (eg: during initialization) will be formatted properly. |
||
3893 | */ |
||
3894 | |||
3895 | for (i=1; i<argc; i++) { |
||
3896 | if (strcmp("-Z", argv[i]) == 0) { |
||
3897 | capture_child = TRUE; |
||
3898 | machine_readable = TRUE; /* request machine-readable output */ |
||
3899 | #ifdef _WIN32 |
||
3900 | /* set output pipe to binary mode, to avoid ugly text conversions */ |
||
3901 | _setmode(2, O_BINARY); |
||
3902 | #endif |
||
3903 | } |
||
3904 | } |
||
3905 | |||
3906 | /* The default_log_handler will use stdout, which makes trouble in */ |
||
3907 | /* capture child mode, as it uses stdout for its sync_pipe. */ |
||
3908 | /* So: the filtering is done in the console_log_handler and not here.*/ |
||
3909 | /* We set the log handlers right up front to make sure that any log */ |
||
3910 | /* messages when running as child will be sent back to the parent */ |
||
3911 | /* with the correct format. */ |
||
3912 | |||
3913 | log_flags = |
||
3914 | (GLogLevelFlags)( |
||
3915 | G_LOG_LEVEL_ERROR| |
||
3916 | G_LOG_LEVEL_CRITICAL| |
||
3917 | G_LOG_LEVEL_WARNING| |
||
3918 | G_LOG_LEVEL_MESSAGE| |
||
3919 | G_LOG_LEVEL_INFO| |
||
3920 | G_LOG_LEVEL_DEBUG| |
||
3921 | G_LOG_FLAG_FATAL| |
||
3922 | G_LOG_FLAG_RECURSION); |
||
3923 | |||
3924 | g_log_set_handler(NULL, |
||
3925 | log_flags, |
||
3926 | console_log_handler, NULL /* user_data */); |
||
3927 | g_log_set_handler(LOG_DOMAIN_MAIN, |
||
3928 | log_flags, |
||
3929 | console_log_handler, NULL /* user_data */); |
||
3930 | g_log_set_handler(LOG_DOMAIN_CAPTURE, |
||
3931 | log_flags, |
||
3932 | console_log_handler, NULL /* user_data */); |
||
3933 | g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD, |
||
3934 | log_flags, |
||
3935 | console_log_handler, NULL /* user_data */); |
||
3936 | |||
3937 | /* Initialize the pcaps list */ |
||
3938 | global_ld.pcaps = g_array_new(FALSE, FALSE, sizeof(pcap_options *)); |
||
3939 | |||
3940 | #if !GLIB_CHECK_VERSION(2,31,0) |
||
3941 | /* Initialize the thread system */ |
||
3942 | g_thread_init(NULL); |
||
3943 | #endif |
||
3944 | |||
3945 | #ifdef _WIN32 |
||
3946 | /* Load wpcap if possible. Do this before collecting the run-time version information */ |
||
3947 | load_wpcap(); |
||
3948 | |||
3949 | /* ... and also load the packet.dll from wpcap */ |
||
3950 | /* XXX - currently not required, may change later. */ |
||
3951 | /*wpcap_packet_load();*/ |
||
3952 | |||
3953 | /* Start windows sockets */ |
||
3954 | WSAStartup( MAKEWORD( 1, 1 ), &wsaData ); |
||
3955 | |||
3956 | /* Set handler for Ctrl+C key */ |
||
3957 | SetConsoleCtrlHandler(capture_cleanup_handler, TRUE); |
||
3958 | #else |
||
3959 | /* Catch SIGINT and SIGTERM and, if we get either of them, clean up |
||
3960 | and exit. Do the same with SIGPIPE, in case, for example, |
||
3961 | we're writing to our standard output and it's a pipe. |
||
3962 | Do the same with SIGHUP if it's not being ignored (if we're |
||
3963 | being run under nohup, it might be ignored, in which case we |
||
3964 | should leave it ignored). |
||
3965 | |||
3966 | XXX - apparently, Coverity complained that part of action |
||
3967 | wasn't initialized. Perhaps it's running on Linux, where |
||
3968 | struct sigaction has an ignored "sa_restorer" element and |
||
3969 | where "sa_handler" and "sa_sigaction" might not be two |
||
3970 | members of a union. */ |
||
3971 | memset(&action, 0, sizeof(action)); |
||
3972 | action.sa_handler = capture_cleanup_handler; |
||
3973 | /* |
||
3974 | * Arrange that system calls not get restarted, because when |
||
3975 | * our signal handler returns we don't want to restart |
||
3976 | * a call that was waiting for packets to arrive. |
||
3977 | */ |
||
3978 | action.sa_flags = 0; |
||
3979 | sigemptyset(&action.sa_mask); |
||
3980 | sigaction(SIGTERM, &action, NULL); |
||
3981 | sigaction(SIGINT, &action, NULL); |
||
3982 | sigaction(SIGPIPE, &action, NULL); |
||
3983 | sigaction(SIGHUP, NULL, &oldaction); |
||
3984 | if (oldaction.sa_handler == SIG_DFL) |
||
3985 | sigaction(SIGHUP, &action, NULL); |
||
3986 | |||
3987 | #ifdef SIGINFO |
||
3988 | /* Catch SIGINFO and, if we get it and we're capturing in |
||
3989 | quiet mode, report the number of packets we've captured. */ |
||
3990 | action.sa_handler = report_counts_siginfo; |
||
3991 | action.sa_flags = SA_RESTART; |
||
3992 | sigemptyset(&action.sa_mask); |
||
3993 | sigaction(SIGINFO, &action, NULL); |
||
3994 | #endif /* SIGINFO */ |
||
3995 | #endif /* _WIN32 */ |
||
3996 | |||
3997 | #ifdef __linux__ |
||
3998 | enable_kernel_bpf_jit_compiler(); |
||
3999 | #endif |
||
4000 | |||
4001 | /* ----------------------------------------------------------------- */ |
||
4002 | /* Privilege and capability handling */ |
||
4003 | /* Cases: */ |
||
4004 | /* 1. Running not as root or suid root; no special capabilities. */ |
||
4005 | /* Action: none */ |
||
4006 | /* */ |
||
4007 | /* 2. Running logged in as root (euid=0; ruid=0); Not using libcap. */ |
||
4008 | /* Action: none */ |
||
4009 | /* */ |
||
4010 | /* 3. Running logged in as root (euid=0; ruid=0). Using libcap. */ |
||
4011 | /* Action: */ |
||
4012 | /* - Near start of program: Enable NET_RAW and NET_ADMIN */ |
||
4013 | /* capabilities; Drop all other capabilities; */ |
||
4014 | /* - If not -w (ie: doing -S or -D, etc) run to completion; */ |
||
4015 | /* else: after pcap_open_live() in capture_loop_open_input() */ |
||
4016 | /* drop all capabilities (NET_RAW and NET_ADMIN); */ |
||
4017 | /* (Note: this means that the process, although logged in */ |
||
4018 | /* as root, does not have various permissions such as the */ |
||
4019 | /* ability to bypass file access permissions). */ |
||
4020 | /* XXX: Should we just leave capabilities alone in this case */ |
||
4021 | /* so that user gets expected effect that root can do */ |
||
4022 | /* anything ?? */ |
||
4023 | /* */ |
||
4024 | /* 4. Running as suid root (euid=0, ruid=n); Not using libcap. */ |
||
4025 | /* Action: */ |
||
4026 | /* - If not -w (ie: doing -S or -D, etc) run to completion; */ |
||
4027 | /* else: after pcap_open_live() in capture_loop_open_input() */ |
||
4028 | /* drop suid root (set euid=ruid).(ie: keep suid until after */ |
||
4029 | /* pcap_open_live). */ |
||
4030 | /* */ |
||
4031 | /* 5. Running as suid root (euid=0, ruid=n); Using libcap. */ |
||
4032 | /* Action: */ |
||
4033 | /* - Near start of program: Enable NET_RAW and NET_ADMIN */ |
||
4034 | /* capabilities; Drop all other capabilities; */ |
||
4035 | /* Drop suid privileges (euid=ruid); */ |
||
4036 | /* - If not -w (ie: doing -S or -D, etc) run to completion; */ |
||
4037 | /* else: after pcap_open_live() in capture_loop_open_input() */ |
||
4038 | /* drop all capabilities (NET_RAW and NET_ADMIN). */ |
||
4039 | /* */ |
||
4040 | /* XXX: For some Linux versions/distros with capabilities */ |
||
4041 | /* a 'normal' process with any capabilities cannot be */ |
||
4042 | /* 'killed' (signaled) from another (same uid) non-privileged */ |
||
4043 | /* process. */ |
||
4044 | /* For example: If (non-suid) Wireshark forks a */ |
||
4045 | /* child suid dumpcap which acts as described here (case 5), */ |
||
4046 | /* Wireshark will be unable to kill (signal) the child */ |
||
4047 | /* dumpcap process until the capabilities have been dropped */ |
||
4048 | /* (after pcap_open_live()). */ |
||
4049 | /* This behaviour will apparently be changed in the kernel */ |
||
4050 | /* to allow the kill (signal) in this case. */ |
||
4051 | /* See the following for details: */ |
||
4052 | /* https://www.mail-archive.com/ [wrapped] */ |
||
4053 | /* linux-security-module@vger.kernel.org/msg02913.html */ |
||
4054 | /* */ |
||
4055 | /* It is therefore conceivable that if dumpcap somehow hangs */ |
||
4056 | /* in pcap_open_live or before that wireshark will not */ |
||
4057 | /* be able to stop dumpcap using a signal (INT, TERM, etc). */ |
||
4058 | /* In this case, exiting wireshark will kill the child */ |
||
4059 | /* dumpcap process. */ |
||
4060 | /* */ |
||
4061 | /* 6. Not root or suid root; Running with NET_RAW & NET_ADMIN */ |
||
4062 | /* capabilities; Using libcap. Note: capset cmd (which see) */ |
||
4063 | /* used to assign capabilities to file. */ |
||
4064 | /* Action: */ |
||
4065 | /* - If not -w (ie: doing -S or -D, etc) run to completion; */ |
||
4066 | /* else: after pcap_open_live() in capture_loop_open_input() */ |
||
4067 | /* drop all capabilities (NET_RAW and NET_ADMIN) */ |
||
4068 | /* */ |
||
4069 | /* ToDo: -S (stats) should drop privileges/capabilities when no */ |
||
4070 | /* longer required (similar to capture). */ |
||
4071 | /* */ |
||
4072 | /* ----------------------------------------------------------------- */ |
||
4073 | |||
4074 | init_process_policies(); |
||
4075 | |||
4076 | #ifdef HAVE_LIBCAP |
||
4077 | /* If 'started with special privileges' (and using libcap) */ |
||
4078 | /* Set to keep only NET_RAW and NET_ADMIN capabilities; */ |
||
4079 | /* Set euid/egid = ruid/rgid to remove suid privileges */ |
||
4080 | relinquish_privs_except_capture(); |
||
4081 | #endif |
||
4082 | |||
4083 | /* Set the initial values in the capture options. This might be overwritten |
||
4084 | by the command line parameters. */ |
||
4085 | capture_opts_init(&global_capture_opts); |
||
4086 | /* We always save to a file - if no file was specified, we save to a |
||
4087 | temporary file. */ |
||
4088 | global_capture_opts.saving_to_file = TRUE; |
||
4089 | global_capture_opts.has_ring_num_files = TRUE; |
||
4090 | |||
4091 | /* Pass on capture_child mode for capture_opts */ |
||
4092 | global_capture_opts.capture_child = capture_child; |
||
4093 | |||
4094 | /* Now get our args */ |
||
4095 | while ((opt = getopt_long(argc, argv, OPTSTRING, long_options, NULL)) != -1) { |
||
4096 | switch (opt) { |
||
4097 | case 'h': /* Print help and exit */ |
||
4098 | printf("Dumpcap (Wireshark) %s\n" |
||
4099 | "Capture network packets and dump them into a pcapng or pcap file.\n" |
||
4100 | "See https://www.wireshark.org for more information.\n", |
||
4101 | get_ws_vcs_version_info()); |
||
4102 | print_usage(stdout); |
||
4103 | exit_main(0); |
||
4104 | break; |
||
4105 | case 'v': /* Show version and exit */ |
||
4106 | comp_info_str = get_compiled_version_info(NULL, get_dumpcap_compiled_info); |
||
4107 | runtime_info_str = get_runtime_version_info(get_dumpcap_runtime_info); |
||
4108 | show_version("Dumpcap (Wireshark)", comp_info_str, runtime_info_str); |
||
4109 | g_string_free(comp_info_str, TRUE); |
||
4110 | g_string_free(runtime_info_str, TRUE); |
||
4111 | exit_main(0); |
||
4112 | break; |
||
4113 | /*** capture option specific ***/ |
||
4114 | case 'a': /* autostop criteria */ |
||
4115 | case 'b': /* Ringbuffer option */ |
||
4116 | case 'c': /* Capture x packets */ |
||
4117 | case 'f': /* capture filter */ |
||
4118 | case 'g': /* enable group read access on file(s) */ |
||
4119 | case 'i': /* Use interface x */ |
||
4120 | case 'n': /* Use pcapng format */ |
||
4121 | case 'p': /* Don't capture in promiscuous mode */ |
||
4122 | case 'P': /* Use pcap format */ |
||
4123 | case 's': /* Set the snapshot (capture) length */ |
||
4124 | case 'w': /* Write to capture file x */ |
||
4125 | case 'y': /* Set the pcap data link type */ |
||
4126 | case LONGOPT_NUM_CAP_COMMENT: /* add a capture comment */ |
||
4127 | #ifdef HAVE_PCAP_REMOTE |
||
4128 | case 'u': /* Use UDP for data transfer */ |
||
4129 | case 'r': /* Capture own RPCAP traffic too */ |
||
4130 | case 'A': /* Authentication */ |
||
4131 | #endif |
||
4132 | #ifdef HAVE_PCAP_SETSAMPLING |
||
4133 | case 'm': /* Sampling */ |
||
4134 | #endif |
||
4135 | #ifdef CAN_SET_CAPTURE_BUFFER_SIZE |
||
4136 | case 'B': /* Buffer size */ |
||
4137 | #endif |
||
4138 | #ifdef HAVE_PCAP_CREATE |
||
4139 | case 'I': /* Monitor mode */ |
||
4140 | #endif |
||
4141 | status = capture_opts_add_opt(&global_capture_opts, opt, optarg, &start_capture); |
||
4142 | if (status != 0) { |
||
4143 | exit_main(status); |
||
4144 | } |
||
4145 | break; |
||
4146 | /*** hidden option: Wireshark child mode (using binary output messages) ***/ |
||
4147 | case 'Z': |
||
4148 | capture_child = TRUE; |
||
4149 | #ifdef _WIN32 |
||
4150 | /* set output pipe to binary mode, to avoid ugly text conversions */ |
||
4151 | _setmode(2, O_BINARY); |
||
4152 | /* |
||
4153 | * optarg = the control ID, aka the PPID, currently used for the |
||
4154 | * signal pipe name. |
||
4155 | */ |
||
4156 | if (strcmp(optarg, SIGNAL_PIPE_CTRL_ID_NONE) != 0) { |
||
4157 | sig_pipe_name = g_strdup_printf(SIGNAL_PIPE_FORMAT, optarg); |
||
4158 | sig_pipe_handle = CreateFile(utf_8to16(sig_pipe_name), |
||
4159 | GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); |
||
4160 | |||
4161 | if (sig_pipe_handle == INVALID_HANDLE_VALUE) { |
||
4162 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
4163 | "Signal pipe: Unable to open %s. Dead parent?", |
||
4164 | sig_pipe_name); |
||
4165 | exit_main(1); |
||
4166 | } |
||
4167 | } |
||
4168 | #endif |
||
4169 | break; |
||
4170 | |||
4171 | case 'q': /* Quiet */ |
||
4172 | quiet = TRUE; |
||
4173 | break; |
||
4174 | case 't': |
||
4175 | use_threads = TRUE; |
||
4176 | break; |
||
4177 | /*** all non capture option specific ***/ |
||
4178 | case 'D': /* Print a list of capture devices and exit */ |
||
4179 | if (!list_interfaces) { |
||
4180 | list_interfaces = TRUE; |
||
4181 | run_once_args++; |
||
4182 | } |
||
4183 | break; |
||
4184 | case 'L': /* Print list of link-layer types and exit */ |
||
4185 | if (!list_link_layer_types) { |
||
4186 | list_link_layer_types = TRUE; |
||
4187 | run_once_args++; |
||
4188 | } |
||
4189 | break; |
||
4190 | #ifdef HAVE_BPF_IMAGE |
||
4191 | case 'd': /* Print BPF code for capture filter and exit */ |
||
4192 | if (!print_bpf_code) { |
||
4193 | print_bpf_code = TRUE; |
||
4194 | run_once_args++; |
||
4195 | } |
||
4196 | break; |
||
4197 | #endif |
||
4198 | case 'S': /* Print interface statistics once a second */ |
||
4199 | if (!print_statistics) { |
||
4200 | print_statistics = TRUE; |
||
4201 | run_once_args++; |
||
4202 | } |
||
4203 | break; |
||
4204 | case 'k': /* Set wireless channel */ |
||
4205 | if (!set_chan) { |
||
4206 | set_chan = TRUE; |
||
4207 | set_chan_arg = optarg; |
||
4208 | run_once_args++; |
||
4209 | } else { |
||
4210 | cmdarg_err("Only one -k flag may be specified"); |
||
4211 | arg_error = TRUE; |
||
4212 | } |
||
4213 | break; |
||
4214 | case 'M': /* For -D, -L, and -S, print machine-readable output */ |
||
4215 | machine_readable = TRUE; |
||
4216 | break; |
||
4217 | case 'C': |
||
4218 | pcap_queue_byte_limit = get_positive_int(optarg, "byte_limit"); |
||
4219 | break; |
||
4220 | case 'N': |
||
4221 | pcap_queue_packet_limit = get_positive_int(optarg, "packet_limit"); |
||
4222 | break; |
||
4223 | default: |
||
4224 | cmdarg_err("Invalid Option: %s", argv[optind-1]); |
||
4225 | /* FALLTHROUGH */ |
||
4226 | case '?': /* Bad flag - print usage message */ |
||
4227 | arg_error = TRUE; |
||
4228 | break; |
||
4229 | } |
||
4230 | } |
||
4231 | if (!arg_error) { |
||
4232 | argc -= optind; |
||
4233 | argv += optind; |
||
4234 | if (argc >= 1) { |
||
4235 | /* user specified file name as regular command-line argument */ |
||
4236 | /* XXX - use it as the capture file name (or something else)? */ |
||
4237 | argc--; |
||
4238 | argv++; |
||
4239 | } |
||
4240 | if (argc != 0) { |
||
4241 | /* |
||
4242 | * Extra command line arguments were specified; complain. |
||
4243 | * XXX - interpret as capture filter, as tcpdump and tshark do? |
||
4244 | */ |
||
4245 | cmdarg_err("Invalid argument: %s", argv[0]); |
||
4246 | arg_error = TRUE; |
||
4247 | } |
||
4248 | } |
||
4249 | |||
4250 | if ((pcap_queue_byte_limit > 0) || (pcap_queue_packet_limit > 0)) { |
||
4251 | use_threads = TRUE; |
||
4252 | } |
||
4253 | if ((pcap_queue_byte_limit == 0) && (pcap_queue_packet_limit == 0)) { |
||
4254 | /* Use some default if the user hasn't specified some */ |
||
4255 | /* XXX: Are these defaults good enough? */ |
||
4256 | pcap_queue_byte_limit = 1000 * 1000; |
||
4257 | pcap_queue_packet_limit = 1000; |
||
4258 | } |
||
4259 | if (arg_error) { |
||
4260 | print_usage(stderr); |
||
4261 | exit_main(1); |
||
4262 | } |
||
4263 | |||
4264 | if (run_once_args > 1) { |
||
4265 | #ifdef HAVE_BPF_IMAGE |
||
4266 | cmdarg_err("Only one of -D, -L, -d, -k, or -S may be supplied."); |
||
4267 | #else |
||
4268 | cmdarg_err("Only one of -D, -L, -k, or -S may be supplied."); |
||
4269 | #endif |
||
4270 | exit_main(1); |
||
4271 | } else if (run_once_args == 1) { |
||
4272 | /* We're supposed to print some information, rather than |
||
4273 | to capture traffic; did they specify a ring buffer option? */ |
||
4274 | if (global_capture_opts.multi_files_on) { |
||
4275 | cmdarg_err("Ring buffer requested, but a capture isn't being done."); |
||
4276 | exit_main(1); |
||
4277 | } |
||
4278 | } else { |
||
4279 | /* We're supposed to capture traffic; */ |
||
4280 | |||
4281 | /* Are we capturing on multiple interface? If so, use threads and pcapng. */ |
||
4282 | if (global_capture_opts.ifaces->len > 1) { |
||
4283 | use_threads = TRUE; |
||
4284 | global_capture_opts.use_pcapng = TRUE; |
||
4285 | } |
||
4286 | |||
4287 | if (global_capture_opts.capture_comment && |
||
4288 | (!global_capture_opts.use_pcapng || global_capture_opts.multi_files_on)) { |
||
4289 | /* XXX - for ringbuffer, should we apply the comment to each file? */ |
||
4290 | cmdarg_err("A capture comment can only be set if we capture into a single pcapng file."); |
||
4291 | exit_main(1); |
||
4292 | } |
||
4293 | |||
4294 | /* Was the ring buffer option specified and, if so, does it make sense? */ |
||
4295 | if (global_capture_opts.multi_files_on) { |
||
4296 | /* Ring buffer works only under certain conditions: |
||
4297 | a) ring buffer does not work with temporary files; |
||
4298 | b) it makes no sense to enable the ring buffer if the maximum |
||
4299 | file size is set to "infinite". */ |
||
4300 | if (global_capture_opts.save_file == NULL) { |
||
4301 | cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file."); |
||
4302 | global_capture_opts.multi_files_on = FALSE; |
||
4303 | } |
||
4304 | if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) { |
||
4305 | cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified."); |
||
4306 | #if 0 |
||
4307 | /* XXX - this must be redesigned as the conditions changed */ |
||
4308 | global_capture_opts.multi_files_on = FALSE; |
||
4309 | #endif |
||
4310 | } |
||
4311 | } |
||
4312 | } |
||
4313 | |||
4314 | /* |
||
4315 | * "-D" requires no interface to be selected; it's supposed to list |
||
4316 | * all interfaces. |
||
4317 | */ |
||
4318 | if (list_interfaces) { |
||
4319 | /* Get the list of interfaces */ |
||
4320 | GList *if_list; |
||
4321 | int err; |
||
4322 | gchar *err_str; |
||
4323 | |||
4324 | if_list = capture_interface_list(&err, &err_str,NULL); |
||
4325 | if (if_list == NULL) { |
||
4326 | if (err == 0) { |
||
4327 | /* |
||
4328 | * If we're being run by another program, just give them |
||
4329 | * an empty list of interfaces, don't report this as |
||
4330 | * an error; that lets them decide whether to report |
||
4331 | * this as an error or not. |
||
4332 | */ |
||
4333 | if (!machine_readable) { |
||
4334 | cmdarg_err("There are no interfaces on which a capture can be done"); |
||
4335 | exit_main(2); |
||
4336 | } |
||
4337 | } else { |
||
4338 | cmdarg_err("%s", err_str); |
||
4339 | g_free(err_str); |
||
4340 | exit_main(2); |
||
4341 | } |
||
4342 | } |
||
4343 | |||
4344 | if (machine_readable) /* tab-separated values to stdout */ |
||
4345 | print_machine_readable_interfaces(if_list); |
||
4346 | else |
||
4347 | capture_opts_print_interfaces(if_list); |
||
4348 | free_interface_list(if_list); |
||
4349 | exit_main(0); |
||
4350 | } |
||
4351 | |||
4352 | /* |
||
4353 | * "-S" requires no interface to be selected; it gives statistics |
||
4354 | * for all interfaces. |
||
4355 | */ |
||
4356 | if (print_statistics) { |
||
4357 | status = print_statistics_loop(machine_readable); |
||
4358 | exit_main(status); |
||
4359 | } |
||
4360 | |||
4361 | if (set_chan) { |
||
4362 | interface_options interface_opts; |
||
4363 | |||
4364 | if (global_capture_opts.ifaces->len != 1) { |
||
4365 | cmdarg_err("Need one interface"); |
||
4366 | exit_main(2); |
||
4367 | } |
||
4368 | |||
4369 | interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, 0); |
||
4370 | status = set_80211_channel(interface_opts.name, set_chan_arg); |
||
4371 | exit_main(status); |
||
4372 | } |
||
4373 | |||
4374 | /* |
||
4375 | * "-L", "-d", and capturing act on a particular interface, so we have to |
||
4376 | * have an interface; if none was specified, pick a default. |
||
4377 | */ |
||
4378 | status = capture_opts_default_iface_if_necessary(&global_capture_opts, NULL); |
||
4379 | if (status != 0) { |
||
4380 | /* cmdarg_err() already called .... */ |
||
4381 | exit_main(status); |
||
4382 | } |
||
4383 | |||
4384 | if (list_link_layer_types) { |
||
4385 | /* Get the list of link-layer types for the capture device. */ |
||
4386 | if_capabilities_t *caps; |
||
4387 | gchar *err_str; |
||
4388 | guint ii; |
||
4389 | |||
4390 | for (ii = 0; ii < global_capture_opts.ifaces->len; ii++) { |
||
4391 | interface_options interface_opts; |
||
4392 | |||
4393 | interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, ii); |
||
4394 | |||
4395 | caps = get_if_capabilities(&interface_opts, &err_str); |
||
4396 | if (caps == NULL) { |
||
4397 | cmdarg_err("The capabilities of the capture device \"%s\" could not be obtained (%s).\n" |
||
4398 | "Please check to make sure you have sufficient permissions, and that\n" |
||
4399 | "you have the proper interface or pipe specified.", interface_opts.name, err_str); |
||
4400 | g_free(err_str); |
||
4401 | exit_main(2); |
||
4402 | } |
||
4403 | if (caps->data_link_types == NULL) { |
||
4404 | cmdarg_err("The capture device \"%s\" has no data link types.", interface_opts.name); |
||
4405 | exit_main(2); |
||
4406 | } |
||
4407 | if (machine_readable) /* tab-separated values to stdout */ |
||
4408 | /* XXX: We need to change the format and adopt consumers */ |
||
4409 | print_machine_readable_if_capabilities(caps); |
||
4410 | else |
||
4411 | /* XXX: We might want to print also the interface name */ |
||
4412 | capture_opts_print_if_capabilities(caps, interface_opts.name, |
||
4413 | interface_opts.monitor_mode); |
||
4414 | free_if_capabilities(caps); |
||
4415 | } |
||
4416 | exit_main(0); |
||
4417 | } |
||
4418 | |||
4419 | /* We're supposed to do a capture, or print the BPF code for a filter. */ |
||
4420 | |||
4421 | /* Let the user know what interfaces were chosen. */ |
||
4422 | if (capture_child) { |
||
4423 | for (j = 0; j < global_capture_opts.ifaces->len; j++) { |
||
4424 | interface_options interface_opts; |
||
4425 | |||
4426 | interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j); |
||
4427 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Interface: %s\n", |
||
4428 | interface_opts.name); |
||
4429 | } |
||
4430 | } else { |
||
4431 | str = g_string_new(""); |
||
4432 | #ifdef _WIN32 |
||
4433 | if (global_capture_opts.ifaces->len < 2) |
||
4434 | #else |
||
4435 | if (global_capture_opts.ifaces->len < 4) |
||
4436 | #endif |
||
4437 | { |
||
4438 | for (j = 0; j < global_capture_opts.ifaces->len; j++) { |
||
4439 | interface_options interface_opts; |
||
4440 | |||
4441 | interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j); |
||
4442 | if (j > 0) { |
||
4443 | if (global_capture_opts.ifaces->len > 2) { |
||
4444 | g_string_append_printf(str, ","); |
||
4445 | } |
||
4446 | g_string_append_printf(str, " "); |
||
4447 | if (j == global_capture_opts.ifaces->len - 1) { |
||
4448 | g_string_append_printf(str, "and "); |
||
4449 | } |
||
4450 | } |
||
4451 | g_string_append_printf(str, "'%s'", interface_opts.console_display_name); |
||
4452 | } |
||
4453 | } else { |
||
4454 | g_string_append_printf(str, "%u interfaces", global_capture_opts.ifaces->len); |
||
4455 | } |
||
4456 | fprintf(stderr, "Capturing on %s\n", str->str); |
||
4457 | g_string_free(str, TRUE); |
||
4458 | } |
||
4459 | |||
4460 | /* Process the snapshot length, as that affects the generated BPF code. */ |
||
4461 | capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE); |
||
4462 | |||
4463 | #ifdef HAVE_BPF_IMAGE |
||
4464 | if (print_bpf_code) { |
||
4465 | show_filter_code(&global_capture_opts); |
||
4466 | exit_main(0); |
||
4467 | } |
||
4468 | #endif |
||
4469 | |||
4470 | /* We're supposed to do a capture. Process the ring buffer arguments. */ |
||
4471 | capture_opts_trim_ring_num_files(&global_capture_opts); |
||
4472 | |||
4473 | /* flush stderr prior to starting the main capture loop */ |
||
4474 | fflush(stderr); |
||
4475 | |||
4476 | /* Now start the capture. */ |
||
4477 | if (capture_loop_start(&global_capture_opts, &stats_known, &stats) == TRUE) { |
||
4478 | /* capture ok */ |
||
4479 | exit_main(0); |
||
4480 | } else { |
||
4481 | /* capture failed */ |
||
4482 | exit_main(1); |
||
4483 | } |
||
4484 | return 0; /* never here, make compiler happy */ |
||
4485 | } |
||
4486 | |||
4487 | |||
4488 | static void |
||
4489 | console_log_handler(const char *log_domain, GLogLevelFlags log_level, |
||
4490 | const char *message, gpointer user_data _U_) |
||
4491 | { |
||
4492 | time_t curr; |
||
4493 | struct tm *today; |
||
4494 | const char *level; |
||
4495 | gchar *msg; |
||
4496 | |||
4497 | /* ignore log message, if log_level isn't interesting */ |
||
4498 | if ( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) { |
||
4499 | #if !defined(DEBUG_DUMPCAP) && !defined(DEBUG_CHILD_DUMPCAP) |
||
4500 | return; |
||
4501 | #endif |
||
4502 | } |
||
4503 | |||
4504 | switch(log_level & G_LOG_LEVEL_MASK) { |
||
4505 | case G_LOG_LEVEL_ERROR: |
||
4506 | level = "Err "; |
||
4507 | break; |
||
4508 | case G_LOG_LEVEL_CRITICAL: |
||
4509 | level = "Crit"; |
||
4510 | break; |
||
4511 | case G_LOG_LEVEL_WARNING: |
||
4512 | level = "Warn"; |
||
4513 | break; |
||
4514 | case G_LOG_LEVEL_MESSAGE: |
||
4515 | level = "Msg "; |
||
4516 | break; |
||
4517 | case G_LOG_LEVEL_INFO: |
||
4518 | level = "Info"; |
||
4519 | break; |
||
4520 | case G_LOG_LEVEL_DEBUG: |
||
4521 | level = "Dbg "; |
||
4522 | break; |
||
4523 | default: |
||
4524 | fprintf(stderr, "unknown log_level %d\n", log_level); |
||
4525 | level = NULL; |
||
4526 | g_assert_not_reached(); |
||
4527 | } |
||
4528 | |||
4529 | /* Generate the output message */ |
||
4530 | if (log_level & G_LOG_LEVEL_MESSAGE) { |
||
4531 | /* normal user messages without additional infos */ |
||
4532 | msg = g_strdup_printf("%s\n", message); |
||
4533 | } else { |
||
4534 | /* create a "timestamp" */ |
||
4535 | time(&curr); |
||
4536 | today = localtime(&curr); |
||
4537 | |||
4538 | /* info/debug messages with additional infos */ |
||
4539 | if (today != NULL) |
||
4540 | msg = g_strdup_printf("%02u:%02u:%02u %8s %s %s\n", |
||
4541 | today->tm_hour, today->tm_min, today->tm_sec, |
||
4542 | log_domain != NULL ? log_domain : "", |
||
4543 | level, message); |
||
4544 | else |
||
4545 | msg = g_strdup_printf("Time not representable %8s %s %s\n", |
||
4546 | log_domain != NULL ? log_domain : "", |
||
4547 | level, message); |
||
4548 | } |
||
4549 | |||
4550 | /* DEBUG & INFO msgs (if we're debugging today) */ |
||
4551 | #if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP) |
||
4552 | if ( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) { |
||
4553 | #ifdef DEBUG_DUMPCAP |
||
4554 | fprintf(stderr, "%s", msg); |
||
4555 | fflush(stderr); |
||
4556 | #endif |
||
4557 | #ifdef DEBUG_CHILD_DUMPCAP |
||
4558 | fprintf(debug_log, "%s", msg); |
||
4559 | fflush(debug_log); |
||
4560 | #endif |
||
4561 | g_free(msg); |
||
4562 | return; |
||
4563 | } |
||
4564 | #endif |
||
4565 | |||
4566 | /* ERROR, CRITICAL, WARNING, MESSAGE messages goto stderr or */ |
||
4567 | /* to parent especially formatted if dumpcap running as child. */ |
||
4568 | if (capture_child) { |
||
4569 | sync_pipe_errmsg_to_parent(2, msg, ""); |
||
4570 | } else { |
||
4571 | fprintf(stderr, "%s", msg); |
||
4572 | fflush(stderr); |
||
4573 | } |
||
4574 | g_free(msg); |
||
4575 | } |
||
4576 | |||
4577 | |||
4578 | /****************************************************************************************************************/ |
||
4579 | /* indication report routines */ |
||
4580 | |||
4581 | |||
4582 | static void |
||
4583 | report_packet_count(unsigned int packet_count) |
||
4584 | { |
||
4585 | char tmp[SP_DECISIZE+1+1]; |
||
4586 | static unsigned int count = 0; |
||
4587 | |||
4588 | if (capture_child) { |
||
4589 | g_snprintf(tmp, sizeof(tmp), "%u", packet_count); |
||
4590 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets: %s", tmp); |
||
4591 | pipe_write_block(2, SP_PACKET_COUNT, tmp); |
||
4592 | } else { |
||
4593 | count += packet_count; |
||
4594 | fprintf(stderr, "\rPackets: %u ", count); |
||
4595 | /* stderr could be line buffered */ |
||
4596 | fflush(stderr); |
||
4597 | } |
||
4598 | } |
||
4599 | |||
4600 | static void |
||
4601 | report_new_capture_file(const char *filename) |
||
4602 | { |
||
4603 | if (capture_child) { |
||
4604 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "File: %s", filename); |
||
4605 | pipe_write_block(2, SP_FILE, filename); |
||
4606 | } else { |
||
4607 | #ifdef SIGINFO |
||
4608 | /* |
||
4609 | * Prevent a SIGINFO handler from writing to the standard error |
||
4610 | * while we're doing so; instead, have it just set a flag telling |
||
4611 | * us to print that information when we're done. |
||
4612 | */ |
||
4613 | infodelay = TRUE; |
||
4614 | #endif /* SIGINFO */ |
||
4615 | fprintf(stderr, "File: %s\n", filename); |
||
4616 | /* stderr could be line buffered */ |
||
4617 | fflush(stderr); |
||
4618 | |||
4619 | #ifdef SIGINFO |
||
4620 | /* |
||
4621 | * Allow SIGINFO handlers to write. |
||
4622 | */ |
||
4623 | infodelay = FALSE; |
||
4624 | |||
4625 | /* |
||
4626 | * If a SIGINFO handler asked us to write out capture counts, do so. |
||
4627 | */ |
||
4628 | if (infoprint) |
||
4629 | report_counts_for_siginfo(); |
||
4630 | #endif /* SIGINFO */ |
||
4631 | } |
||
4632 | } |
||
4633 | |||
4634 | static void |
||
4635 | report_cfilter_error(capture_options *capture_opts, guint i, const char *errmsg) |
||
4636 | { |
||
4637 | interface_options interface_opts; |
||
4638 | char tmp[MSG_MAX_LENGTH+1+6]; |
||
4639 | |||
4640 | if (i < capture_opts->ifaces->len) { |
||
4641 | if (capture_child) { |
||
4642 | g_snprintf(tmp, sizeof(tmp), "%u:%s", i, errmsg); |
||
4643 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Capture filter error: %s", errmsg); |
||
4644 | pipe_write_block(2, SP_BAD_FILTER, tmp); |
||
4645 | } else { |
||
4646 | /* |
||
4647 | * clopts_step_invalid_capfilter in test/suite-clopts.sh MUST match |
||
4648 | * the error message below. |
||
4649 | */ |
||
4650 | interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); |
||
4651 | cmdarg_err( |
||
4652 | "Invalid capture filter \"%s\" for interface '%s'.\n" |
||
4653 | "\n" |
||
4654 | "That string isn't a valid capture filter (%s).\n" |
||
4655 | "See the User's Guide for a description of the capture filter syntax.", |
||
4656 | interface_opts.cfilter, interface_opts.name, errmsg); |
||
4657 | } |
||
4658 | } |
||
4659 | } |
||
4660 | |||
4661 | static void |
||
4662 | report_capture_error(const char *error_msg, const char *secondary_error_msg) |
||
4663 | { |
||
4664 | if (capture_child) { |
||
4665 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, |
||
4666 | "Primary Error: %s", error_msg); |
||
4667 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, |
||
4668 | "Secondary Error: %s", secondary_error_msg); |
||
4669 | sync_pipe_errmsg_to_parent(2, error_msg, secondary_error_msg); |
||
4670 | } else { |
||
4671 | cmdarg_err("%s", error_msg); |
||
4672 | if (secondary_error_msg[0] != '\0') |
||
4673 | cmdarg_err_cont("%s", secondary_error_msg); |
||
4674 | } |
||
4675 | } |
||
4676 | |||
4677 | static void |
||
4678 | report_packet_drops(guint32 received, guint32 pcap_drops, guint32 drops, guint32 flushed, guint32 ps_ifdrop, gchar *name) |
||
4679 | { |
||
4680 | char tmp[SP_DECISIZE+1+1]; |
||
4681 | guint32 total_drops = pcap_drops + drops + flushed; |
||
4682 | |||
4683 | g_snprintf(tmp, sizeof(tmp), "%u", total_drops); |
||
4684 | |||
4685 | if (capture_child) { |
||
4686 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, |
||
4687 | "Packets received/dropped on interface '%s': %u/%u (pcap:%u/dumpcap:%u/flushed:%u/ps_ifdrop:%u)", |
||
4688 | name, received, total_drops, pcap_drops, drops, flushed, ps_ifdrop); |
||
4689 | /* XXX: Need to provide interface id, changes to consumers required. */ |
||
4690 | pipe_write_block(2, SP_DROPS, tmp); |
||
4691 | } else { |
||
4692 | fprintf(stderr, |
||
4693 | "Packets received/dropped on interface '%s': %u/%u (pcap:%u/dumpcap:%u/flushed:%u/ps_ifdrop:%u) (%.1f%%)\n", |
||
4694 | name, received, total_drops, pcap_drops, drops, flushed, ps_ifdrop, |
||
4695 | received ? 100.0 * received / (received + total_drops) : 0.0); |
||
4696 | /* stderr could be line buffered */ |
||
4697 | fflush(stderr); |
||
4698 | } |
||
4699 | } |
||
4700 | |||
4701 | |||
4702 | /************************************************************************************************/ |
||
4703 | /* signal_pipe handling */ |
||
4704 | |||
4705 | |||
4706 | #ifdef _WIN32 |
||
4707 | static gboolean |
||
4708 | signal_pipe_check_running(void) |
||
4709 | { |
||
4710 | /* any news from our parent? -> just stop the capture */ |
||
4711 | DWORD avail = 0; |
||
4712 | gboolean result; |
||
4713 | |||
4714 | /* if we are running standalone, no check required */ |
||
4715 | if (!capture_child) { |
||
4716 | return TRUE; |
||
4717 | } |
||
4718 | |||
4719 | if (!sig_pipe_name || !sig_pipe_handle) { |
||
4720 | /* This shouldn't happen */ |
||
4721 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
4722 | "Signal pipe: No name or handle"); |
||
4723 | return FALSE; |
||
4724 | } |
||
4725 | |||
4726 | /* |
||
4727 | * XXX - We should have the process ID of the parent (from the "-Z" flag) |
||
4728 | * at this point. Should we check to see if the parent is still alive, |
||
4729 | * e.g. by using OpenProcess? |
||
4730 | */ |
||
4731 | |||
4732 | result = PeekNamedPipe(sig_pipe_handle, NULL, 0, NULL, &avail, NULL); |
||
4733 | |||
4734 | if (!result || avail > 0) { |
||
4735 | /* peek failed or some bytes really available */ |
||
4736 | /* (if not piping from stdin this would fail) */ |
||
4737 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, |
||
4738 | "Signal pipe: Stop capture: %s", sig_pipe_name); |
||
4739 | g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, |
||
4740 | "Signal pipe: %s (%p) result: %u avail: %u", sig_pipe_name, |
||
4741 | sig_pipe_handle, result, avail); |
||
4742 | return FALSE; |
||
4743 | } else { |
||
4744 | /* pipe ok and no bytes available */ |
||
4745 | return TRUE; |
||
4746 | } |
||
4747 | } |
||
4748 | #endif |
||
4749 | |||
4750 | /* |
||
4751 | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
||
4752 | * |
||
4753 | * Local variables: |
||
4754 | * c-basic-offset: 4 |
||
4755 | * tab-width: 8 |
||
4756 | * indent-tabs-mode: nil |
||
4757 | * End: |
||
4758 | * |
||
4759 | * vi: set shiftwidth=4 tabstop=8 expandtab: |
||
4760 | * :indentSize=4:tabSize=8:noTabs=true: |
||
4761 | */ |