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 none 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 fprintf(output, "Stop conditions:\n");
142 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
143 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
144 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
145 fprintf(output, " files:NUM - stop after NUM files\n");
146 /*fprintf(output, "\n");*/
147 fprintf(output, "Output (files):\n");
148 fprintf(output, " -w <filename> name of file to save (def: tempfile)\n");
149 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
150 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
151 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
152 /*fprintf(output, "\n");*/
153 fprintf(output, "Miscellaneous:\n");
154 fprintf(output, " -v print version information and exit\n");
155 fprintf(output, " -h display this help and exit\n");
156 fprintf(output, "\n");
157 fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcap\n");
158 fprintf(output, "\"Capture network packets from interface eth0 until 60s passed into output.pcap\"\n");
159 fprintf(output, "\n");
160 fprintf(output, "Use Ctrl-C to stop capturing at any time.\n");
164 show_version(GString *comp_info_str, GString *runtime_info_str)
168 "Dumpcap " VERSION "%s\n"
173 "See http://www.wireshark.org for more information.\n",
174 wireshark_svnversion, get_copyright_info() ,comp_info_str->str, runtime_info_str->str);
178 * Report an error in command-line arguments.
181 cmdarg_err(const char *fmt, ...)
186 /* Print a bare error */
188 vfprintf(stderr, fmt, ap);
192 fprintf(stderr, "dumpcap: ");
193 vfprintf(stderr, fmt, ap);
194 fprintf(stderr, "\n");
200 * Report additional information for an error in command-line arguments.
203 cmdarg_err_cont(const char *fmt, ...)
208 /* XXX - convert to g_log */
211 vfprintf(stderr, fmt, ap);
212 fprintf(stderr, "\n");
220 capture_cleanup(DWORD dwCtrlType)
222 /* CTRL_C_EVENT is sort of like SIGINT, CTRL_BREAK_EVENT is unique to
223 Windows, CTRL_CLOSE_EVENT is sort of like SIGHUP, CTRL_LOGOFF_EVENT
224 is also sort of like SIGHUP, and CTRL_SHUTDOWN_EVENT is sort of
225 like SIGTERM at least when the machine's shutting down.
227 For now, if we're running as a command rather than a capture child,
228 we handle all but CTRL_LOGOFF_EVENT as indications that we should
229 clean up and quit, just as we handle SIGINT, SIGHUP, and SIGTERM
232 If we're not running as a capture child, we might be running as
233 a service; ignore CTRL_LOGOFF_EVENT, so we keep running after the
234 user logs out. (XXX - can we explicitly check whether we're
235 running as a service?) */
237 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
238 "Console: Control signal");
239 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
240 "Console: Control signal, CtrlType: %u", dwCtrlType);
242 /* Keep capture running if we're a service and a user logs off */
243 if (capture_child || (dwCtrlType != CTRL_LOGOFF_EVENT)) {
252 capture_cleanup(int signum)
254 /* On UN*X, we cleanly shut down the capture on SIGINT, SIGHUP, and
255 SIGTERM. We assume that if the user wanted it to keep running
256 after they logged out, they'd have nohupped it. */
258 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
260 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
261 "Console: Signal, signal value: %u", signum);
267 void exit_main(int status)
270 /* Shutdown windows sockets */
273 /* can be helpful for debugging */
275 printf("Press any key\n");
286 * If we were linked with libcap (not libpcap), make sure we have
287 * CAP_NET_ADMIN and CAP_NET_RAW, then relinquish our permissions.
291 #if 0 /* Set to enable capability debugging */
292 print_caps(char *pfx) {
293 cap_t caps = cap_get_proc();
294 fprintf(stderr, "%s: EUID: %d Capabilities: %s\n", pfx,
295 geteuid(), cap_to_text(caps, NULL));
298 print_caps(char *pfx _U_) {
303 relinquish_privs_except_capture(void)
305 /* CAP_NET_ADMIN: Promiscuous mode and a truckload of other
306 * stuff we don't need (and shouldn't have).
307 * CAP_NET_RAW: Packet capture (raw sockets).
309 cap_value_t cap_list[2] = { CAP_NET_ADMIN, CAP_NET_RAW };
310 cap_t caps = cap_init();
311 int cl_len = sizeof(cap_list) / sizeof(cap_value_t);
313 if (started_with_special_privs()) {
314 print_caps("Pre drop, pre set");
315 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
319 cap_set_flag(caps, CAP_PERMITTED, cl_len, cap_list, CAP_SET);
320 cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, CAP_SET);
322 if (cap_set_proc(caps)) {
325 print_caps("Pre drop, post set");
328 relinquish_special_privs_perm();
330 print_caps("Post drop, pre set");
331 cap_set_flag(caps, CAP_EFFECTIVE, cl_len, cap_list, CAP_SET);
332 if (cap_set_proc(caps)) {
335 print_caps("Post drop, post set");
338 #endif /* HAVE_LIBCAP */
341 /* And now our feature presentation... [ fade to music ] */
343 main(int argc, char *argv[])
347 gboolean arg_error = FALSE;
353 struct sigaction action, oldaction;
356 gboolean start_capture = TRUE;
357 gboolean stats_known;
358 struct pcap_stat stats;
359 GLogLevelFlags log_flags;
360 gboolean list_interfaces = FALSE;
361 gboolean list_link_layer_types = FALSE;
362 gboolean machine_readable = FALSE;
363 gboolean print_statistics = FALSE;
364 int status, run_once_args = 0;
366 #define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z:"
369 #define OPTSTRING_WIN32 "B:"
371 #define OPTSTRING_WIN32 ""
374 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
375 OPTSTRING_INIT OPTSTRING_WIN32;
378 /* Load wpcap if possible. Do this before collecting the run-time version information */
381 /* ... and also load the packet.dll from wpcap */
382 /* XXX - currently not required, may change later. */
383 /*wpcap_packet_load();*/
385 /* Start windows sockets */
386 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
388 /* Set handler for Ctrl+C key */
389 SetConsoleCtrlHandler(capture_cleanup, TRUE);
391 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
393 action.sa_handler = capture_cleanup;
395 sigemptyset(&action.sa_mask);
396 sigaction(SIGTERM, &action, NULL);
397 sigaction(SIGINT, &action, NULL);
398 sigaction(SIGHUP, NULL, &oldaction);
399 if (oldaction.sa_handler == SIG_DFL)
400 sigaction(SIGHUP, &action, NULL);
404 get_credential_info();
405 relinquish_privs_except_capture();
408 /* the default_log_handler will use stdout, which makes trouble in */
409 /* capture child mode, as it uses stdout for it's sync_pipe */
410 /* so do the filtering in the console_log_handler and not here */
413 G_LOG_LEVEL_CRITICAL|
418 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
420 g_log_set_handler(NULL,
422 console_log_handler, NULL /* user_data */);
423 g_log_set_handler(LOG_DOMAIN_MAIN,
425 console_log_handler, NULL /* user_data */);
426 g_log_set_handler(LOG_DOMAIN_CAPTURE,
428 console_log_handler, NULL /* user_data */);
429 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
431 console_log_handler, NULL /* user_data */);
433 /* Set the initial values in the capture_opts. This might be overwritten
434 by the command line parameters. */
435 capture_opts_init(capture_opts, NULL);
437 /* Default to capturing the entire packet. */
438 capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
440 /* We always save to a file - if no file was specified, we save to a
442 capture_opts->saving_to_file = TRUE;
443 capture_opts->has_ring_num_files = TRUE;
445 /* Now get our args */
446 while ((opt = getopt(argc, argv, optstring)) != -1) {
448 case 'h': /* Print help and exit */
452 case 'v': /* Show version and exit */
454 GString *comp_info_str;
455 GString *runtime_info_str;
456 /* Assemble the compile-time version information string */
457 comp_info_str = g_string_new("Compiled ");
458 get_compiled_version_info(comp_info_str, NULL);
460 /* Assemble the run-time version information string */
461 runtime_info_str = g_string_new("Running ");
462 get_runtime_version_info(runtime_info_str, NULL);
463 show_version(comp_info_str, runtime_info_str);
464 g_string_free(comp_info_str, TRUE);
465 g_string_free(runtime_info_str, TRUE);
469 /*** capture option specific ***/
470 case 'a': /* autostop criteria */
471 case 'b': /* Ringbuffer option */
472 case 'c': /* Capture x packets */
473 case 'f': /* capture filter */
474 case 'i': /* Use interface x */
475 case 'p': /* Don't capture in promiscuous mode */
476 case 's': /* Set the snapshot (capture) length */
477 case 'w': /* Write to capture file x */
478 case 'y': /* Set the pcap data link type */
480 case 'B': /* Buffer size */
482 status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
487 /*** hidden option: Wireshark child mode (using binary output messages) ***/
489 capture_child = TRUE;
491 /* set output pipe to binary mode, to avoid ugly text conversions */
492 _setmode(2, O_BINARY);
494 * optarg = the control ID, aka the PPID, currently used for the
497 if (strcmp(optarg, SIGNAL_PIPE_CTRL_ID_NONE) != 0) {
498 sig_pipe_name = g_strdup_printf(SIGNAL_PIPE_FORMAT,
500 sig_pipe_handle = CreateFile(utf_8to16(sig_pipe_name),
501 GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
503 if (sig_pipe_handle == INVALID_HANDLE_VALUE) {
504 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
505 "Signal pipe: Unable to open %s. Dead parent?",
513 /*** all non capture option specific ***/
514 case 'D': /* Print a list of capture devices and exit */
515 list_interfaces = TRUE;
518 case 'L': /* Print list of link-layer types and exit */
519 list_link_layer_types = TRUE;
522 case 'S': /* Print interface statistics once a second */
523 print_statistics = TRUE;
526 case 'M': /* For -D and -L, print machine-readable output */
527 machine_readable = TRUE;
530 case '?': /* Bad flag - print usage message */
531 cmdarg_err("Invalid Option: %s", argv[optind-1]);
539 /* user specified file name as regular command-line argument */
540 /* XXX - use it as the capture file name (or something else)? */
547 * Extra command line arguments were specified; complain.
548 * XXX - interpret as capture filter, as tcpdump and tshark do?
550 cmdarg_err("Invalid argument: %s", argv[0]);
559 if (run_once_args > 1) {
560 cmdarg_err("Only one of -D, -L, or -S may be supplied.");
562 } else if (list_link_layer_types) {
563 /* We're supposed to list the link-layer types for an interface;
564 did the user also specify a capture file to be read? */
565 /* No - did they specify a ring buffer option? */
566 if (capture_opts->multi_files_on) {
567 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
571 /* No - was the ring buffer option specified and, if so, does it make
573 if (capture_opts->multi_files_on) {
574 /* Ring buffer works only under certain conditions:
575 a) ring buffer does not work with temporary files;
576 b) it makes no sense to enable the ring buffer if the maximum
577 file size is set to "infinite". */
578 if (capture_opts->save_file == NULL) {
579 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
580 capture_opts->multi_files_on = FALSE;
582 if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
583 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
584 /* XXX - this must be redesigned as the conditions changed */
585 /* capture_opts->multi_files_on = FALSE;*/
590 if (capture_opts_trim_iface(capture_opts, NULL) == FALSE) {
591 cmdarg_err("No capture interfaces available (maybe lack of privileges?).");
595 /* Let the user know what interface was chosen. */
596 /* get_interface_descriptive_name() is not available! */
597 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Interface: %s\n", capture_opts->iface);
599 if (list_interfaces) {
600 status = capture_opts_list_interfaces(machine_readable);
602 } else if (list_link_layer_types) {
603 status = capture_opts_list_link_layer_types(capture_opts, machine_readable);
605 } else if (print_statistics) {
606 status = capture_opts_print_statistics(machine_readable);
610 capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
611 capture_opts_trim_ring_num_files(capture_opts);
613 /* Now start the capture. */
615 if(capture_loop_start(capture_opts, &stats_known, &stats) == TRUE) {
626 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
627 const char *message, gpointer user_data _U_)
634 /* ignore log message, if log_level isn't interesting */
635 if( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) {
636 #ifndef DEBUG_DUMPCAP
641 /* create a "timestamp" */
643 today = localtime(&curr);
645 switch(log_level & G_LOG_LEVEL_MASK) {
646 case G_LOG_LEVEL_ERROR:
649 case G_LOG_LEVEL_CRITICAL:
652 case G_LOG_LEVEL_WARNING:
655 case G_LOG_LEVEL_MESSAGE:
658 case G_LOG_LEVEL_INFO:
661 case G_LOG_LEVEL_DEBUG:
665 fprintf(stderr, "unknown log_level %u\n", log_level);
667 g_assert_not_reached();
670 /* don't use printf (stdout), in child mode we're using stdout for the sync_pipe */
671 if(log_level & G_LOG_LEVEL_MESSAGE) {
672 /* normal user messages without additional infos */
673 fprintf(stderr, "%s\n", message);
676 /* info/debug messages with additional infos */
677 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
678 today->tm_hour, today->tm_min, today->tm_sec,
679 log_domain != NULL ? log_domain : "",
686 /****************************************************************************************************************/
687 /* indication report routines */
691 report_packet_count(int packet_count)
693 char tmp[SP_DECISIZE+1+1];
694 static int count = 0;
697 g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
698 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets: %s", tmp);
699 pipe_write_block(2, SP_PACKET_COUNT, tmp);
701 count += packet_count;
702 fprintf(stderr, "\rPackets: %u ", count);
703 /* stderr could be line buffered */
709 report_new_capture_file(const char *filename)
712 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "File: %s", filename);
713 pipe_write_block(2, SP_FILE, filename);
715 fprintf(stderr, "File: %s\n", filename);
716 /* stderr could be line buffered */
722 report_cfilter_error(const char *cfilter, const char *errmsg)
725 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Capture filter error: %s", errmsg);
726 pipe_write_block(2, SP_BAD_FILTER, errmsg);
729 "Invalid capture filter: \"%s\"!\n"
731 "That string isn't a valid capture filter (%s).\n"
732 "See the User's Guide for a description of the capture filter syntax.\n",
738 report_capture_error(const char *error_msg, const char *secondary_error_msg)
741 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
742 "Primary Error: %s", error_msg);
743 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
744 "Secondary Error: %s", secondary_error_msg);
745 sync_pipe_errmsg_to_parent(2, error_msg, secondary_error_msg);
747 fprintf(stderr, "%s\n%s\n", error_msg, secondary_error_msg);
752 report_packet_drops(int drops)
754 char tmp[SP_DECISIZE+1+1];
756 g_snprintf(tmp, sizeof(tmp), "%d", drops);
759 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets dropped: %s", tmp);
760 pipe_write_block(2, SP_DROPS, tmp);
762 fprintf(stderr, "Packets dropped: %s\n", tmp);
763 /* stderr could be line buffered */
769 /****************************************************************************************************************/
770 /* signal_pipe handling */
775 signal_pipe_check_running(void)
777 /* any news from our parent? -> just stop the capture */
781 /* if we are running standalone, no check required */
786 if(!sig_pipe_name || !sig_pipe_handle) {
787 /* This shouldn't happen */
788 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
789 "Signal pipe: No name or handle");
794 * XXX - We should have the process ID of the parent (from the "-Z" flag)
795 * at this point. Should we check to see if the parent is still alive,
796 * e.g. by using OpenProcess?
799 result = PeekNamedPipe(sig_pipe_handle, NULL, 0, NULL, &avail, NULL);
801 if(!result || avail > 0) {
802 /* peek failed or some bytes really available */
803 /* (if not piping from stdin this would fail) */
804 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
805 "Signal pipe: Stop capture: %s", sig_pipe_name);
806 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
807 "Signal pipe: %s (%p) result: %u avail: %u", sig_pipe_name,
808 sig_pipe_handle, result, avail);
811 /* pipe ok and no bytes available */