5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@ethereal.com>
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.
45 #ifdef _WIN32 /* Needed for console I/O */
49 #include "ringbuffer.h"
50 #include "clopts_common.h"
51 #include "cmdarg_err.h"
52 #include "version_info.h"
55 #include "capture-pcap-util.h"
58 #include "capture-wpcap.h"
62 #include "capture_loop.h"
63 #include "capture_sync.h"
65 #include "simple_dialog.h"
68 #include "file_util.h"
72 gboolean capture_child; /* True if this is an Ethereal capture child */
74 /* Win32 console handling */
76 static gboolean has_console = FALSE; /* TRUE if app has console */
77 static void create_console(void);
78 static void destroy_console(void);
81 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
82 const char *message, gpointer user_data _U_);
84 /* capture related options */
85 capture_options global_capture_opts;
86 capture_options *capture_opts = &global_capture_opts;
89 void exit_main(int err) __attribute__ ((noreturn));
91 void exit_main(int err);
94 const char *get_basename(const char *path);
98 print_usage(gboolean print_ver) {
109 "Dumpcap " VERSION "%s\n"
110 "Capture network packets and dump them into a libpcap file.\n"
111 "See http://www.ethereal.com for more information.\n",
116 fprintf(output, "\nUsage: dumpcap [options] ...\n");
117 fprintf(output, "\n");
118 fprintf(output, "Capture interface:\n");
119 fprintf(output, " -i <interface> name or idx of interface (def: first none loopback)\n");
120 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
121 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
122 fprintf(output, " -p don't capture in promiscuous mode\n");
124 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
126 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
127 fprintf(output, " -D print list of interfaces and exit\n");
128 fprintf(output, " -L print list of link-layer types of iface and exit\n");
129 fprintf(output, "\n");
130 fprintf(output, "Stop conditions:\n");
131 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
132 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
133 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
134 fprintf(output, " files:NUM - stop after NUM files\n");
135 /*fprintf(output, "\n");*/
136 fprintf(output, "Output (files):\n");
137 fprintf(output, " -w <filename> name of file to save (def: tempfile)\n");
138 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
139 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
140 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
141 /*fprintf(output, "\n");*/
142 fprintf(output, "Miscellaneous:\n");
143 fprintf(output, " -v print version information and exit\n");
144 fprintf(output, " -h display this help and exit\n");
145 fprintf(output, "\n");
146 fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcap\n");
147 fprintf(output, "\"Capture network packets from interface eth0 until 60s passed into output.pcap\"\n");
148 fprintf(output, "\n");
149 fprintf(output, "Use Ctrl-C to stop capturing at any time.\n");
153 show_version(GString *comp_info_str, GString *runtime_info_str)
160 "Dumpcap " VERSION "%s\n"
165 "See http://www.ethereal.com for more information.\n",
166 svnversion, get_copyright_info() ,comp_info_str->str, runtime_info_str->str);
170 * Report an error in command-line arguments.
171 * Creates a console on Windows.
172 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
173 * terminal isn't the standard error?
176 cmdarg_err(const char *fmt, ...)
184 fprintf(stderr, "dumpcap: ");
185 vfprintf(stderr, fmt, ap);
186 fprintf(stderr, "\n");
191 * Report additional information for an error in command-line arguments.
192 * Creates a console on Windows.
193 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
194 * terminal isn't the standard error?
197 cmdarg_err_cont(const char *fmt, ...)
205 vfprintf(stderr, fmt, ap);
206 fprintf(stderr, "\n");
212 BOOL WINAPI ConsoleCtrlHandlerRoutine(DWORD dwCtrlType)
214 /*printf("Event: %u", dwCtrlType);*/
221 void exit_main(int err)
224 /* Shutdown windows sockets */
230 /* can be helpful for debugging */
236 /* And now our feature presentation... [ fade to music ] */
238 main(int argc, char *argv[])
242 gboolean arg_error = FALSE;
243 GString *comp_info_str;
244 GString *runtime_info_str;
250 gboolean start_capture = TRUE;
251 gboolean stats_known;
252 struct pcap_stat stats;
253 GLogLevelFlags log_flags;
254 gboolean list_link_layer_types = FALSE;
257 #define OPTSTRING_INIT "a:b:c:Df:hi:Lps:vw:y:"
260 #define OPTSTRING_WIN32 "B:Z:"
262 #define OPTSTRING_WIN32 ""
265 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
266 OPTSTRING_INIT OPTSTRING_WIN32;
269 capture_child = (strcmp(get_basename(argv[0]), CHILD_NAME) == 0);
272 /* Load wpcap if possible. Do this before collecting the run-time version information */
275 /* ... and also load the packet.dll from wpcap */
276 /* XXX - currently not required, may change later. */
277 /*wpcap_packet_load();*/
279 /* Start windows sockets */
280 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
282 /* Set handler for Ctrl+C key */
283 SetConsoleCtrlHandler(&ConsoleCtrlHandlerRoutine, TRUE);
286 /* Assemble the compile-time version information string */
287 comp_info_str = g_string_new("Compiled ");
288 g_string_append(comp_info_str, "with ");
289 get_compiled_version_info(comp_info_str);
291 /* Assemble the run-time version information string */
292 runtime_info_str = g_string_new("Running ");
293 get_runtime_version_info(runtime_info_str);
295 /* Arrange that if we have no console window, and a GLib message logging
296 routine is called to log a message, we pop up a console window.
298 We do that by inserting our own handler for all messages logged
299 to the default domain; that handler pops up a console if necessary,
300 and then calls the default handler. */
302 /* We might want to have component specific log levels later ... */
304 /* the default_log_handler will use stdout, which makes trouble with the */
305 /* capture child, as it uses stdout for it's sync_pipe */
306 /* so do the filtering in the console_log_handler and not here */
309 G_LOG_LEVEL_CRITICAL|
314 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
316 g_log_set_handler(NULL,
318 console_log_handler, NULL /* user_data */);
319 g_log_set_handler(LOG_DOMAIN_MAIN,
321 console_log_handler, NULL /* user_data */);
322 g_log_set_handler(LOG_DOMAIN_CAPTURE,
324 console_log_handler, NULL /* user_data */);
325 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
327 console_log_handler, NULL /* user_data */);
329 /* Set the initial values in the capture_opts. This might be overwritten
330 by the command line parameters. */
331 capture_opts_init(capture_opts, NULL);
333 capture_opts->snaplen = MIN_PACKET_SIZE;
334 capture_opts->has_ring_num_files = TRUE;
336 /* Now get our args */
337 while ((opt = getopt(argc, argv, optstring)) != -1) {
339 case 'h': /* Print help and exit */
343 case 'v': /* Show version and exit */
344 show_version(comp_info_str, runtime_info_str);
347 /*** capture option specific ***/
348 case 'a': /* autostop criteria */
349 case 'b': /* Ringbuffer option */
350 case 'c': /* Capture x packets */
351 case 'f': /* capture filter */
352 case 'i': /* Use interface x */
353 case 'p': /* Don't capture in promiscuous mode */
354 case 's': /* Set the snapshot (capture) length */
355 case 'w': /* Write to capture file x */
356 case 'y': /* Set the pcap data link type */
358 case 'B': /* Buffer size */
359 /* Hidden option supporting Sync mode */
360 case 'Z': /* Write to pipe FD x */
362 status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
368 /*** all non capture option specific ***/
369 case 'D': /* Print a list of capture devices and exit */
370 status = capture_opts_list_interfaces();
373 case 'L': /* Print list of link-layer types and exit */
374 list_link_layer_types = TRUE;
377 case '?': /* Bad flag - print usage message */
378 cmdarg_err("Invalid Option: %s", argv[optind-1]);
386 /* user specified file name as regular command-line argument */
387 /* XXX - use it as the capture file name (or something else)? */
394 * Extra command line arguments were specified; complain.
396 cmdarg_err("Invalid argument: %s", argv[0]);
405 if (list_link_layer_types) {
406 /* We're supposed to list the link-layer types for an interface;
407 did the user also specify a capture file to be read? */
408 /* No - did they specify a ring buffer option? */
409 if (capture_opts->multi_files_on) {
410 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
414 /* No - was the ring buffer option specified and, if so, does it make
416 if (capture_opts->multi_files_on) {
417 /* Ring buffer works only under certain conditions:
418 a) ring buffer does not work with temporary files;
419 b) it makes no sense to enable the ring buffer if the maximum
420 file size is set to "infinite". */
421 if (capture_opts->save_file == NULL) {
422 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
423 capture_opts->multi_files_on = FALSE;
425 if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
426 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
427 /* XXX - this must be redesigned as the conditions changed */
428 /* capture_opts->multi_files_on = FALSE;*/
433 if (capture_opts_trim_iface(capture_opts, NULL) == FALSE) {
434 cmdarg_err("No capture interfaces available (maybe lack of privileges?).");
438 /* Let the user know what interface was chosen. */
439 /* descr = get_interface_descriptive_name(capture_opts.iface);
440 fprintf(stderr, "Capturing on %s\n", descr);
444 fprintf(stderr, "Capturing on %s\n", capture_opts->iface);
447 if (list_link_layer_types) {
448 status = capture_opts_list_link_layer_types(capture_opts);
452 capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
453 capture_opts_trim_ring_num_files(capture_opts);
455 /* Now start the capture. */
457 /* XXX - hand the stats to the parent process */
458 if(capture_loop_start(capture_opts, &stats_known, &stats) == TRUE) {
469 /* We build this as a GUI subsystem application on Win32, so
470 "WinMain()", not "main()", gets called.
472 Hack shamelessly stolen from the Win32 port of the GIMP. */
474 #define _stdcall __attribute__((stdcall))
478 WinMain (struct HINSTANCE__ *hInstance,
479 struct HINSTANCE__ *hPrevInstance,
484 return main (__argc, __argv);
488 * If this application has no console window to which its standard output
489 * would go, create one.
495 /* We have no console to which to print the version string, so
496 create one and make it the standard input, output, and error. */
498 return; /* couldn't create console */
499 eth_freopen("CONIN$", "r", stdin);
500 eth_freopen("CONOUT$", "w", stdout);
501 eth_freopen("CONOUT$", "w", stderr);
503 /* Well, we have a console now. */
506 /* Now register "destroy_console()" as a routine to be called just
507 before the application exits, so that we can destroy the console
508 after the user has typed a key (so that the console doesn't just
509 disappear out from under them, giving the user no chance to see
510 the message(s) we put in there). */
511 atexit(destroy_console);
513 SetConsoleTitle("Dumpcap Console");
518 destroy_console(void)
521 /* XXX - doesn't make sense while we're linked as a console application */
522 /* printf("\n\nPress any key to exit\n");
530 /* This routine should not be necessary, at least as I read the GLib
531 source code, as it looks as if GLib is, on Win32, *supposed* to
532 create a console window into which to display its output.
534 That doesn't happen, however. I suspect there's something completely
535 broken about that code in GLib-for-Win32, and that it may be related
536 to the breakage that forces us to just call "printf()" on the message
537 rather than passing the message on to "g_log_default_handler()"
538 (which is the routine that does the aforementioned non-functional
539 console window creation). */
541 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
542 const char *message, gpointer user_data _U_)
549 /* ignore log message, if log_level isn't interesting */
550 if( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) {
554 /* create a "timestamp" */
556 today = localtime(&curr);
563 /* For some unknown reason, the above doesn't appear to actually cause
564 anything to be sent to the standard output, so we'll just splat the
565 message out directly, just to make sure it gets out. */
567 switch(log_level & G_LOG_LEVEL_MASK) {
568 case G_LOG_LEVEL_ERROR:
571 case G_LOG_LEVEL_CRITICAL:
574 case G_LOG_LEVEL_WARNING:
577 case G_LOG_LEVEL_MESSAGE:
580 case G_LOG_LEVEL_INFO:
583 case G_LOG_LEVEL_DEBUG:
587 fprintf(stderr, "unknown log_level %u\n", log_level);
589 g_assert_not_reached();
592 /* don't use printf (stdout), as the capture child uses stdout for it's sync_pipe */
593 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
594 today->tm_hour, today->tm_min, today->tm_sec,
595 log_domain != NULL ? log_domain : "",
599 g_log_default_handler(log_domain, log_level, message, user_data);
604 /****************************************************************************************************************/
605 /* sync_pipe stubs */
608 * Maximum length of sync pipe message data. Must be < 2^24, as the
609 * message length is 3 bytes.
610 * XXX - this must be large enough to handle a Really Big Filter
611 * Expression, as the error message for an incorrect filter expression
612 * is a bit larger than the filter expression.
614 #define SP_MAX_MSG_LEN 4096
617 /* write a message to the recipient pipe in the standard format
618 (3 digit message length (excluding length and indicator field),
619 1 byte message indicator and the rest is the message) */
621 pipe_write_block(int pipe, char indicator, int len, const char *msg)
623 guchar header[3+1]; /* indicator + 3-byte len */
626 /*g_warning("write %d enter", pipe);*/
628 /* if we're not a capture child, we don't have to tell our none existing parent anything */
632 g_assert(indicator < '0' || indicator > '9');
633 g_assert(len <= SP_MAX_MSG_LEN);
635 /* write header (indicator + 3-byte len) */
636 header[0] = indicator;
637 header[1] = (len >> 16) & 0xFF;
638 header[2] = (len >> 8) & 0xFF;
639 header[3] = (len >> 0) & 0xFF;
641 ret = write(pipe, header, sizeof header);
646 /* write value (if we have one) */
648 /*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
649 ret = write(pipe, msg, len);
654 /*g_warning("write %d indicator: %c no value", pipe, indicator);*/
657 /*g_warning("write %d leave", pipe);*/
662 sync_pipe_packet_count_to_parent(int packet_count)
664 char tmp[SP_DECISIZE+1+1];
665 static int count = 0;
669 count += packet_count;
670 fprintf(stderr, "\r%u", count);
671 /* stderr could be line buffered */
675 g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
677 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_packet_count_to_parent: %s", tmp);
679 pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
683 sync_pipe_filename_to_parent(const char *filename)
687 fprintf(stderr, "\nFile: %s\n", filename);
688 /* stderr could be line buffered */
692 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "File: %s", filename);
694 pipe_write_block(1, SP_FILE, strlen(filename)+1, filename);
698 sync_pipe_errmsg_to_parent(const char *errmsg)
700 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
702 pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
706 sync_pipe_drops_to_parent(int drops)
708 char tmp[SP_DECISIZE+1+1];
711 g_snprintf(tmp, sizeof(tmp), "%d", drops);
713 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_drops_to_parent: %s", tmp);
715 pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
720 /****************************************************************************************************************/
721 /* simple_dialog stubs */
724 char *simple_dialog_primary_start(void)
729 char *simple_dialog_primary_end(void)
735 simple_dialog_format_message(const char *msg)
740 #if GTK_MAJOR_VERSION < 2
743 str = xml_escape(msg);
751 /****************************************************************************************************************/
755 const char *netsnmp_get_version(void) { return ""; }
757 gboolean dfilter_compile(const gchar *text, dfilter_t **dfp) { (void)text; (void)dfp; return FALSE; }
759 void dfilter_free(dfilter_t *df) { (void)df; }
763 * Find out whether a hostname resolves to an ip or ipv6 address
764 * Return "ip6" if it is IPv6, "ip" otherwise (including the case
765 * that we don't know)
767 const char* host_ip_af(const char *host
768 #ifndef HAVE_GETHOSTBYNAME2
773 #ifdef HAVE_GETHOSTBYNAME2
775 return (h = gethostbyname2(host, AF_INET6)) && h->h_addrtype == AF_INET6 ? "ip6" : "ip";
782 /****************************************************************************************************************/
783 /* functions copied from epan */
786 * Given a pathname, return a pointer to the last pathname separator
787 * character in the pathname, or NULL if the pathname contains no
791 find_last_pathname_separator(const char *path)
799 * We have to scan for '\' or '/'.
800 * Get to the end of the string.
802 separator = strchr(path, '\0'); /* points to ending '\0' */
803 while (separator > path) {
805 if (c == '\\' || c == '/')
806 return separator; /* found it */
810 * OK, we didn't find any, so no directories - but there might
811 * be a drive letter....
813 return strchr(path, ':');
815 separator = strrchr(path, '/');
821 * Given a pathname, return the last component.
824 get_basename(const char *path)
826 const char *filename;
828 g_assert(path != NULL);
829 filename = find_last_pathname_separator(path);
830 if (filename == NULL) {
832 * There're no directories, drive letters, etc. in the
833 * name; the pathname *is* the file name.
838 * Skip past the pathname or drive letter separator.