5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include <stdlib.h> /* for exit() */
49 # include <sys/prctl.h>
50 # include <sys/capability.h>
54 #include "ringbuffer.h"
55 #include "clopts_common.h"
56 #include "cmdarg_err.h"
57 #include "version_info.h"
60 #include "capture-pcap-util.h"
63 #include "capture-wpcap.h"
67 #include "epan/unicode-utils.h"
71 #include "epan/privileges.h"
74 #include "sync_pipe.h"
77 #include "capture_loop.h"
78 #include "capture_sync.h"
80 #include "simple_dialog.h"
83 #include "file_util.h"
86 /*#define DEBUG_DUMPCAP*/
88 gboolean capture_child = FALSE; /* FALSE: standalone call, TRUE: this is an Wireshark capture child */
90 gchar *sig_pipe_name = NULL;
91 HANDLE sig_pipe_handle = NULL;
95 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
96 const char *message, gpointer user_data _U_);
98 /* capture related options */
99 capture_options global_capture_opts;
100 capture_options *capture_opts = &global_capture_opts;
103 void exit_main(int err) __attribute__ ((noreturn));
105 void exit_main(int err);
110 print_usage(gboolean print_ver) {
118 "Dumpcap " VERSION "%s\n"
119 "Capture network packets and dump them into a libpcap file.\n"
120 "See http://www.wireshark.org for more information.\n",
121 wireshark_svnversion);
125 fprintf(output, "\nUsage: dumpcap [options] ...\n");
126 fprintf(output, "\n");
127 fprintf(output, "Capture interface:\n");
128 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
129 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
130 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
131 fprintf(output, " -p don't capture in promiscuous mode\n");
133 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
135 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
136 fprintf(output, " -D print list of interfaces and exit\n");
137 fprintf(output, " -L print list of link-layer types of iface and exit\n");
138 fprintf(output, " -S print statistics for each interface once every second\n");
139 fprintf(output, " -M for -D, -L, and -S produce machine-readable output\n");
140 fprintf(output, "\n");
141 #ifdef HAVE_PCAP_REMOTE
142 fprintf(output, "\nRPCAP options:\n");
143 fprintf(output, " -r don't ignore own RPCAP traffic in capture\n");
144 fprintf(output, " -u use UDP for RPCAP data transfer\n");
145 fprintf(output, " -A <user>:<password> use RPCAP password authentication\n");
146 #ifdef HAVE_PCAP_SETSAMPLING
147 fprintf(output, " -m <sampling type> use packet sampling\n");
148 fprintf(output, " count:NUM - capture one packet of every NUM\n");
149 fprintf(output, " timer:NUM - capture no more than 1 packet in NUM ms\n");
152 fprintf(output, "Stop conditions:\n");
153 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
154 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
155 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
156 fprintf(output, " files:NUM - stop after NUM files\n");
157 /*fprintf(output, "\n");*/
158 fprintf(output, "Output (files):\n");
159 fprintf(output, " -w <filename> name of file to save (def: tempfile)\n");
160 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
161 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
162 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
163 /*fprintf(output, "\n");*/
164 fprintf(output, "Miscellaneous:\n");
165 fprintf(output, " -v print version information and exit\n");
166 fprintf(output, " -h display this help and exit\n");
167 fprintf(output, "\n");
168 fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcap\n");
169 fprintf(output, "\"Capture network packets from interface eth0 until 60s passed into output.pcap\"\n");
170 fprintf(output, "\n");
171 fprintf(output, "Use Ctrl-C to stop capturing at any time.\n");
175 show_version(GString *comp_info_str, GString *runtime_info_str)
179 "Dumpcap " VERSION "%s\n"
184 "See http://www.wireshark.org for more information.\n",
185 wireshark_svnversion, get_copyright_info() ,comp_info_str->str, runtime_info_str->str);
189 * Report an error in command-line arguments.
192 cmdarg_err(const char *fmt, ...)
197 /* Print a bare error */
199 vfprintf(stderr, fmt, ap);
203 fprintf(stderr, "dumpcap: ");
204 vfprintf(stderr, fmt, ap);
205 fprintf(stderr, "\n");
211 * Report additional information for an error in command-line arguments.
214 cmdarg_err_cont(const char *fmt, ...)
219 /* XXX - convert to g_log */
222 vfprintf(stderr, fmt, ap);
223 fprintf(stderr, "\n");
231 capture_cleanup(DWORD dwCtrlType)
233 /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to
234 Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT
235 is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of
236 like SIGTERM at least when the machine's shutting down.
238 For now, if we're running as a command rather than a capture child,
239 we handle all but CTRL_LOGOFF_EVENT as indications that we should
240 clean up and quit, just as we handle SIGINT, SIGHUP, and SIGTERM
243 If we're not running as a capture child, we might be running as
244 a service; ignore CTRL_LOGOFF_EVENT, so we keep running after the
245 user logs out. (XXX - can we explicitly check whether we're
246 running as a service?) */
248 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
249 "Console: Control signal");
250 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
251 "Console: Control signal, CtrlType: %u", dwCtrlType);
253 /* Keep capture running if we're a service and a user logs off */
254 if (capture_child || (dwCtrlType != CTRL_LOGOFF_EVENT)) {
263 capture_cleanup(int signum)
265 /* On UN*X, we cleanly shut down the capture on SIGINT, SIGHUP, and
266 SIGTERM. We assume that if the user wanted it to keep running
267 after they logged out, they'd have nohupped it. */
269 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
271 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
272 "Console: Signal, signal value: %u", signum);
278 void exit_main(int status)
281 /* Shutdown windows sockets */
284 /* can be helpful for debugging */
286 printf("Press any key\n");
297 * If we were linked with libcap (not libpcap), make sure we have
298 * CAP_NET_ADMIN and CAP_NET_RAW, then relinquish our permissions.
302 #if 0 /* Set to enable capability debugging */
303 print_caps(char *pfx) {
304 cap_t caps = cap_get_proc();
305 fprintf(stderr, "%s: EUID: %d Capabilities: %s\n", pfx,
306 geteuid(), cap_to_text(caps, NULL));
309 print_caps(char *pfx _U_) {
314 relinquish_privs_except_capture(void)
316 /* CAP_NET_ADMIN: Promiscuous mode and a truckload of other
317 * stuff we don't need (and shouldn't have).
318 * CAP_NET_RAW: Packet capture (raw sockets).
320 cap_value_t cap_list[2] = { CAP_NET_ADMIN, CAP_NET_RAW };
321 cap_t caps = cap_init();
322 int cl_len = sizeof(cap_list) / sizeof(cap_value_t);
324 if (started_with_special_privs()) {
325 print_caps("Pre drop, pre set");
326 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
330 cap_set_flag(caps, CAP_PERMITTED, cl_len, cap_list, CAP_SET);
331 cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, CAP_SET);
333 if (cap_set_proc(caps)) {
336 print_caps("Pre drop, post set");
339 relinquish_special_privs_perm();
341 print_caps("Post drop, pre set");
342 cap_set_flag(caps, CAP_EFFECTIVE, cl_len, cap_list, CAP_SET);
343 if (cap_set_proc(caps)) {
346 print_caps("Post drop, post set");
349 #endif /* HAVE_LIBCAP */
352 /* And now our feature presentation... [ fade to music ] */
354 main(int argc, char *argv[])
358 gboolean arg_error = FALSE;
364 struct sigaction action, oldaction;
367 gboolean start_capture = TRUE;
368 gboolean stats_known;
369 struct pcap_stat stats;
370 GLogLevelFlags log_flags;
371 gboolean list_interfaces = FALSE;
372 gboolean list_link_layer_types = FALSE;
373 gboolean machine_readable = FALSE;
374 gboolean print_statistics = FALSE;
375 int status, run_once_args = 0;
377 #ifdef HAVE_PCAP_REMOTE
378 #define OPTSTRING_INIT "a:A:b:c:Df:hi:Lm:MprSs:uvw:y:Z:"
380 #define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z:"
384 #define OPTSTRING_WIN32 "B:"
386 #define OPTSTRING_WIN32 ""
389 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
390 OPTSTRING_INIT OPTSTRING_WIN32;
393 /* Load wpcap if possible. Do this before collecting the run-time version information */
396 /* ... and also load the packet.dll from wpcap */
397 /* XXX - currently not required, may change later. */
398 /*wpcap_packet_load();*/
400 /* Start windows sockets */
401 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
403 /* Set handler for Ctrl+C key */
404 SetConsoleCtrlHandler(capture_cleanup, TRUE);
406 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
408 action.sa_handler = capture_cleanup;
410 sigemptyset(&action.sa_mask);
411 sigaction(SIGTERM, &action, NULL);
412 sigaction(SIGINT, &action, NULL);
413 sigaction(SIGHUP, NULL, &oldaction);
414 if (oldaction.sa_handler == SIG_DFL)
415 sigaction(SIGHUP, &action, NULL);
419 get_credential_info();
420 relinquish_privs_except_capture();
423 /* the default_log_handler will use stdout, which makes trouble in */
424 /* capture child mode, as it uses stdout for it's sync_pipe */
425 /* so do the filtering in the console_log_handler and not here */
428 G_LOG_LEVEL_CRITICAL|
433 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
435 g_log_set_handler(NULL,
437 console_log_handler, NULL /* user_data */);
438 g_log_set_handler(LOG_DOMAIN_MAIN,
440 console_log_handler, NULL /* user_data */);
441 g_log_set_handler(LOG_DOMAIN_CAPTURE,
443 console_log_handler, NULL /* user_data */);
444 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
446 console_log_handler, NULL /* user_data */);
448 /* Set the initial values in the capture_opts. This might be overwritten
449 by the command line parameters. */
450 capture_opts_init(capture_opts, NULL);
452 /* Default to capturing the entire packet. */
453 capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
455 /* We always save to a file - if no file was specified, we save to a
457 capture_opts->saving_to_file = TRUE;
458 capture_opts->has_ring_num_files = TRUE;
460 /* Now get our args */
461 while ((opt = getopt(argc, argv, optstring)) != -1) {
463 case 'h': /* Print help and exit */
467 case 'v': /* Show version and exit */
469 GString *comp_info_str;
470 GString *runtime_info_str;
471 /* Assemble the compile-time version information string */
472 comp_info_str = g_string_new("Compiled ");
473 get_compiled_version_info(comp_info_str, NULL);
475 /* Assemble the run-time version information string */
476 runtime_info_str = g_string_new("Running ");
477 get_runtime_version_info(runtime_info_str, NULL);
478 show_version(comp_info_str, runtime_info_str);
479 g_string_free(comp_info_str, TRUE);
480 g_string_free(runtime_info_str, TRUE);
484 /*** capture option specific ***/
485 case 'a': /* autostop criteria */
486 case 'b': /* Ringbuffer option */
487 case 'c': /* Capture x packets */
488 case 'f': /* capture filter */
489 case 'i': /* Use interface x */
490 case 'p': /* Don't capture in promiscuous mode */
491 case 's': /* Set the snapshot (capture) length */
492 case 'w': /* Write to capture file x */
493 case 'y': /* Set the pcap data link type */
494 #ifdef HAVE_PCAP_REMOTE
495 case 'u': /* Use UDP for data transfer */
496 case 'r': /* Capture own RPCAP traffic too */
497 case 'A': /* Authentication */
499 #ifdef HAVE_PCAP_SETSAMPLING
500 case 'm': /* Sampling */
503 case 'B': /* Buffer size */
505 status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
510 /*** hidden option: Wireshark child mode (using binary output messages) ***/
512 capture_child = TRUE;
514 /* set output pipe to binary mode, to avoid ugly text conversions */
515 _setmode(2, O_BINARY);
517 * optarg = the control ID, aka the PPID, currently used for the
520 if (strcmp(optarg, SIGNAL_PIPE_CTRL_ID_NONE) != 0) {
521 sig_pipe_name = g_strdup_printf(SIGNAL_PIPE_FORMAT,
523 sig_pipe_handle = CreateFile(utf_8to16(sig_pipe_name),
524 GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
526 if (sig_pipe_handle == INVALID_HANDLE_VALUE) {
527 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
528 "Signal pipe: Unable to open %s. Dead parent?",
536 /*** all non capture option specific ***/
537 case 'D': /* Print a list of capture devices and exit */
538 list_interfaces = TRUE;
541 case 'L': /* Print list of link-layer types and exit */
542 list_link_layer_types = TRUE;
545 case 'S': /* Print interface statistics once a second */
546 print_statistics = TRUE;
549 case 'M': /* For -D and -L, print machine-readable output */
550 machine_readable = TRUE;
553 case '?': /* Bad flag - print usage message */
554 cmdarg_err("Invalid Option: %s", argv[optind-1]);
562 /* user specified file name as regular command-line argument */
563 /* XXX - use it as the capture file name (or something else)? */
570 * Extra command line arguments were specified; complain.
571 * XXX - interpret as capture filter, as tcpdump and tshark do?
573 cmdarg_err("Invalid argument: %s", argv[0]);
582 if (run_once_args > 1) {
583 cmdarg_err("Only one of -D, -L, or -S may be supplied.");
585 } else if (list_link_layer_types) {
586 /* We're supposed to list the link-layer types for an interface;
587 did the user also specify a capture file to be read? */
588 /* No - did they specify a ring buffer option? */
589 if (capture_opts->multi_files_on) {
590 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
594 /* No - was the ring buffer option specified and, if so, does it make
596 if (capture_opts->multi_files_on) {
597 /* Ring buffer works only under certain conditions:
598 a) ring buffer does not work with temporary files;
599 b) it makes no sense to enable the ring buffer if the maximum
600 file size is set to "infinite". */
601 if (capture_opts->save_file == NULL) {
602 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
603 capture_opts->multi_files_on = FALSE;
605 if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
606 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
607 /* XXX - this must be redesigned as the conditions changed */
608 /* capture_opts->multi_files_on = FALSE;*/
613 if (capture_opts_trim_iface(capture_opts, NULL) == FALSE) {
614 cmdarg_err("No capture interfaces available (maybe lack of privileges?).");
618 /* Let the user know what interface was chosen. */
619 /* get_interface_descriptive_name() is not available! */
620 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Interface: %s\n", capture_opts->iface);
622 if (list_interfaces) {
623 status = capture_opts_list_interfaces(machine_readable);
625 } else if (list_link_layer_types) {
626 status = capture_opts_list_link_layer_types(capture_opts, machine_readable);
628 } else if (print_statistics) {
629 status = capture_opts_print_statistics(machine_readable);
633 capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
634 capture_opts_trim_ring_num_files(capture_opts);
636 /* Now start the capture. */
638 if(capture_loop_start(capture_opts, &stats_known, &stats) == TRUE) {
649 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
650 const char *message, gpointer user_data _U_)
657 /* ignore log message, if log_level isn't interesting */
658 if( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) {
659 #ifndef DEBUG_DUMPCAP
664 /* create a "timestamp" */
666 today = localtime(&curr);
668 switch(log_level & G_LOG_LEVEL_MASK) {
669 case G_LOG_LEVEL_ERROR:
672 case G_LOG_LEVEL_CRITICAL:
675 case G_LOG_LEVEL_WARNING:
678 case G_LOG_LEVEL_MESSAGE:
681 case G_LOG_LEVEL_INFO:
684 case G_LOG_LEVEL_DEBUG:
688 fprintf(stderr, "unknown log_level %u\n", log_level);
690 g_assert_not_reached();
693 /* don't use printf (stdout), in child mode we're using stdout for the sync_pipe */
694 if(log_level & G_LOG_LEVEL_MESSAGE) {
695 /* normal user messages without additional infos */
696 fprintf(stderr, "%s\n", message);
699 /* info/debug messages with additional infos */
700 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
701 today->tm_hour, today->tm_min, today->tm_sec,
702 log_domain != NULL ? log_domain : "",
709 /****************************************************************************************************************/
710 /* indication report routines */
714 report_packet_count(int packet_count)
716 char tmp[SP_DECISIZE+1+1];
717 static int count = 0;
720 g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
721 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets: %s", tmp);
722 pipe_write_block(2, SP_PACKET_COUNT, tmp);
724 count += packet_count;
725 fprintf(stderr, "\rPackets: %u ", count);
726 /* stderr could be line buffered */
732 report_new_capture_file(const char *filename)
735 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "File: %s", filename);
736 pipe_write_block(2, SP_FILE, filename);
738 fprintf(stderr, "File: %s\n", filename);
739 /* stderr could be line buffered */
745 report_cfilter_error(const char *cfilter, const char *errmsg)
748 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Capture filter error: %s", errmsg);
749 pipe_write_block(2, SP_BAD_FILTER, errmsg);
752 "Invalid capture filter: \"%s\"!\n"
754 "That string isn't a valid capture filter (%s).\n"
755 "See the User's Guide for a description of the capture filter syntax.\n",
761 report_capture_error(const char *error_msg, const char *secondary_error_msg)
764 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
765 "Primary Error: %s", error_msg);
766 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
767 "Secondary Error: %s", secondary_error_msg);
768 sync_pipe_errmsg_to_parent(2, error_msg, secondary_error_msg);
770 fprintf(stderr, "%s\n%s\n", error_msg, secondary_error_msg);
775 report_packet_drops(int drops)
777 char tmp[SP_DECISIZE+1+1];
779 g_snprintf(tmp, sizeof(tmp), "%d", drops);
782 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets dropped: %s", tmp);
783 pipe_write_block(2, SP_DROPS, tmp);
785 fprintf(stderr, "Packets dropped: %s\n", tmp);
786 /* stderr could be line buffered */
792 /****************************************************************************************************************/
793 /* signal_pipe handling */
798 signal_pipe_check_running(void)
800 /* any news from our parent? -> just stop the capture */
804 /* if we are running standalone, no check required */
809 if(!sig_pipe_name || !sig_pipe_handle) {
810 /* This shouldn't happen */
811 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
812 "Signal pipe: No name or handle");
817 * XXX - We should have the process ID of the parent (from the "-Z" flag)
818 * at this point. Should we check to see if the parent is still alive,
819 * e.g. by using OpenProcess?
822 result = PeekNamedPipe(sig_pipe_handle, NULL, 0, NULL, &avail, NULL);
824 if(!result || avail > 0) {
825 /* peek failed or some bytes really available */
826 /* (if not piping from stdin this would fail) */
827 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
828 "Signal pipe: Stop capture: %s", sig_pipe_name);
829 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
830 "Signal pipe: %s (%p) result: %u avail: %u", sig_pipe_name,
831 sig_pipe_handle, result, avail);
834 /* pipe ok and no bytes available */