5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@ethereal.com>
7 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #ifdef NEED_STRERROR_H
46 #ifdef _WIN32 /* Needed for console I/O */
51 #include <epan/packet.h>
52 #include <epan/strutil.h>
58 #include "simple_dialog.h"
59 #include "ringbuffer.h"
60 #include "../ui_util.h"
62 #include "clopts_common.h"
63 #include "cmdarg_err.h"
64 #include "version_info.h"
67 #include "pcap-util.h"
70 #include "capture-wpcap.h"
71 #include "capture_wpcap_packet.h"
75 #include "file_util.h"
80 GString *comp_info_str, *runtime_info_str;
81 gchar *ethereal_path = NULL;
84 static gboolean has_console = TRUE; /* TRUE if app has console */
85 static void create_console(void);
86 static void destroy_console(void);
89 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
90 const char *message, gpointer user_data _U_);
92 capture_options global_capture_opts;
93 capture_options *capture_opts = &global_capture_opts;
98 print_usage(gboolean print_ver) {
108 fprintf(output, "This is "PACKAGE " " VERSION "%s"
109 "\n (C) 1998-2005 Gerald Combs <gerald@ethereal.com>"
111 svnversion, comp_info_str->str, runtime_info_str->str);
115 fprintf(output, "\n%s [ -vh ] [ -klLnpQS ] [ -a <capture autostop condition> ] ...\n", PACKAGE);
116 fprintf(output, "\t[ -b <capture ring buffer option> ] ...\n");
118 fprintf(output, "\t[ -B <capture buffer size> ]\n");
120 fprintf(output, "\t[ -c <capture packet count> ] [ -f <capture filter> ]\n");
121 fprintf(output, "\t[ -g <packet number> ] [ -i <capture interface> ] [ -m <font> ]\n");
122 fprintf(output, "\t[ -N <name resolving flags> ] [ -o <preference/recent setting> ] ...\n");
123 fprintf(output, "\t[ -r <infile> ] [ -R <read (display) filter> ] [ -s <capture snaplen> ]\n");
124 fprintf(output, "\t[ -t <time stamp format> ] [ -w <savefile> ] [ -y <capture link type> ]\n");
125 fprintf(output, "\t[ -z <statistics> ] [ <infile> ]\n");
131 printf(PACKAGE " " VERSION "%s\n\n%s\n\n%s\n",
132 svnversion, comp_info_str->str, runtime_info_str->str);
136 * Report an error in command-line arguments.
137 * Creates a console on Windows.
138 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
139 * terminal isn't the standard error?
142 cmdarg_err(const char *fmt, ...)
150 fprintf(stderr, "dumpcap: ");
151 vfprintf(stderr, fmt, ap);
152 fprintf(stderr, "\n");
157 * Report additional information for an error in command-line arguments.
158 * Creates a console on Windows.
159 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
160 * terminal isn't the standard error?
163 cmdarg_err_cont(const char *fmt, ...)
171 vfprintf(stderr, fmt, ap);
172 fprintf(stderr, "\n");
178 BOOL WINAPI ConsoleCtrlHandlerRoutine(DWORD dwCtrlType)
180 //printf("Event: %u", dwCtrlType);
187 /* And now our feature presentation... [ fade to music ] */
189 main(int argc, char *argv[])
193 gboolean arg_error = FALSE;
200 gboolean start_capture = TRUE;
203 GList *lt_list, *lt_entry;
204 data_link_info_t *data_link_info;
205 gchar err_str[PCAP_ERRBUF_SIZE];
206 gchar *cant_get_if_list_errstr;
207 gboolean stats_known;
208 struct pcap_stat stats;
209 GLogLevelFlags log_flags;
210 gboolean list_link_layer_types = FALSE;
212 #define OPTSTRING_INIT "a:b:c:f:Hhi:kLpQSs:W:w:vy:"
215 #define OPTSTRING_WIN32 "B:Z:"
217 #define OPTSTRING_WIN32 ""
220 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
221 OPTSTRING_INIT OPTSTRING_WIN32;
223 /*** create the compile and runtime version strings ***/
225 /* Load wpcap if possible. Do this before collecting the run-time version information */
228 /* ... and also load the packet.dll from wpcap */
231 /* Start windows sockets */
232 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
236 SetConsoleCtrlHandler(&ConsoleCtrlHandlerRoutine, TRUE);
239 /* Assemble the compile-time version information string */
240 comp_info_str = g_string_new("Compiled ");
241 g_string_append(comp_info_str, "with ");
242 get_compiled_version_info(comp_info_str);
244 /* Assemble the run-time version information string */
245 runtime_info_str = g_string_new("Running ");
246 get_runtime_version_info(runtime_info_str);
248 ethereal_path = argv[0];
250 /* Arrange that if we have no console window, and a GLib message logging
251 routine is called to log a message, we pop up a console window.
253 We do that by inserting our own handler for all messages logged
254 to the default domain; that handler pops up a console if necessary,
255 and then calls the default handler. */
257 /* We might want to have component specific log levels later ... */
259 /* the default_log_handler will use stdout, which makes trouble with the */
260 /* capture child, as it uses stdout for it's sync_pipe */
261 /* so do the filtering in the console_log_handler and not here */
264 G_LOG_LEVEL_CRITICAL|
269 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
271 g_log_set_handler(NULL,
273 console_log_handler, NULL /* user_data */);
274 g_log_set_handler(LOG_DOMAIN_MAIN,
276 console_log_handler, NULL /* user_data */);
277 g_log_set_handler(LOG_DOMAIN_CAPTURE,
279 console_log_handler, NULL /* user_data */);
280 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
282 console_log_handler, NULL /* user_data */);
284 /* Set the initial values in the capture_opts. This might be overwritten
285 by preference settings and then again by the command line parameters. */
286 capture_opts_init(capture_opts, &cfile);
288 capture_opts->snaplen = MIN_PACKET_SIZE;
289 capture_opts->has_ring_num_files = TRUE;
291 init_cap_file(&cfile);
293 /* Now get our args */
294 while ((opt = getopt(argc, argv, optstring)) != -1) {
296 case 'h': /* Print help and exit */
300 case 'v': /* Show version and exit */
304 /*** capture option specific ***/
305 case 'a': /* autostop criteria */
306 case 'b': /* Ringbuffer option */
307 case 'c': /* Capture xxx packets */
308 case 'f': /* capture filter */
309 case 'k': /* Start capture immediately */
310 case 'H': /* Hide capture info dialog box */
311 case 'i': /* Use interface xxx */
312 case 'p': /* Don't capture in promiscuous mode */
313 case 'Q': /* Quit after capture (just capture to file) */
314 case 's': /* Set the snapshot (capture) length */
315 case 'S': /* "Sync" mode: used for following file ala tail -f */
316 case 'w': /* Write to capture file xxx */
317 case 'y': /* Set the pcap data link type */
319 case 'B': /* Buffer size */
320 /* Hidden option supporting Sync mode */
321 case 'Z': /* Write to pipe FD XXX */
323 capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
325 /* This is a hidden option supporting Sync mode, so we don't set
326 * the error flags for the user in the non-libpcap case.
328 case 'W': /* Write to capture file FD xxx */
329 capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
332 /*** all non capture option specific ***/
333 case 'L': /* Print list of link-layer types and exit */
334 list_link_layer_types = TRUE;
337 case '?': /* Bad flag - print usage message */
345 /* user speficied file name as regular command-line argument */
346 /* XXX - use it as the capture file name (or somthing else)? */
355 * Extra command line arguments were specified; complain.
357 cmdarg_err("Invalid argument: %s", argv[0]);
366 if (list_link_layer_types) {
367 /* We're supposed to list the link-layer types for an interface;
368 did the user also specify a capture file to be read? */
369 /* No - did they specify a ring buffer option? */
370 if (capture_opts->multi_files_on) {
371 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
375 /* No - was the ring buffer option specified and, if so, does it make
377 if (capture_opts->multi_files_on) {
378 /* Ring buffer works only under certain conditions:
379 a) ring buffer does not work with temporary files;
380 b) real_time_mode and multi_files_on are mutually exclusive -
381 real_time_mode takes precedence;
382 c) it makes no sense to enable the ring buffer if the maximum
383 file size is set to "infinite". */
384 if (capture_opts->save_file == NULL) {
385 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
386 capture_opts->multi_files_on = FALSE;
388 if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
389 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
390 /* XXX - this must be redesigned as the conditions changed */
391 /* capture_opts->multi_files_on = FALSE;*/
396 /* Did the user specify an interface to use? */
397 if (capture_opts->iface == NULL) {
398 /* No - pick the first one from the list of interfaces. */
399 if_list = get_interface_list(&err, err_str);
400 if (if_list == NULL) {
403 case CANT_GET_INTERFACE_LIST:
404 cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
405 cmdarg_err("%s", cant_get_if_list_errstr);
406 g_free(cant_get_if_list_errstr);
409 case NO_INTERFACES_FOUND:
410 cmdarg_err("There are no interfaces on which a capture can be done");
415 if_info = if_list->data; /* first interface */
416 capture_opts->iface = g_strdup(if_info->name);
417 free_interface_list(if_list);
420 if (list_link_layer_types) {
421 /* Get the list of link-layer types for the capture device. */
422 lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
423 if (lt_list == NULL) {
424 if (err_str[0] != '\0') {
425 cmdarg_err("The list of data link types for the capture device could not be obtained (%s)."
426 "Please check to make sure you have sufficient permissions, and that\n"
427 "you have the proper interface or pipe specified.\n", err_str);
429 cmdarg_err("The capture device has no data link types.");
432 g_warning("Data link types (use option -y to set):");
433 for (lt_entry = lt_list; lt_entry != NULL;
434 lt_entry = g_list_next(lt_entry)) {
435 data_link_info = lt_entry->data;
436 g_warning(" %s", data_link_info->name);
437 if (data_link_info->description != NULL)
438 g_warning(" (%s)", data_link_info->description);
440 g_warning(" (not supported)");
443 free_pcap_linktype_list(lt_list);
447 if (capture_opts->has_snaplen) {
448 if (capture_opts->snaplen < 1)
449 capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
450 else if (capture_opts->snaplen < MIN_PACKET_SIZE)
451 capture_opts->snaplen = MIN_PACKET_SIZE;
454 /* Check the value range of the ringbuffer_num_files parameter */
455 if (capture_opts->ring_num_files > RINGBUFFER_MAX_NUM_FILES)
456 capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES;
457 #if RINGBUFFER_MIN_NUM_FILES > 0
458 else if (capture_opts->num_files < RINGBUFFER_MIN_NUM_FILES)
459 capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
462 /* Now start the capture.
463 After the capture is done; there's nothing more for us to do. */
465 /* XXX - hand these stats to the parent process */
466 if(capture_loop_start(capture_opts, &stats_known, &stats) == TRUE) {
475 /* Shutdown windows sockets */
486 /* We build this as a GUI subsystem application on Win32, so
487 "WinMain()", not "main()", gets called.
489 Hack shamelessly stolen from the Win32 port of the GIMP. */
491 #define _stdcall __attribute__((stdcall))
495 WinMain (struct HINSTANCE__ *hInstance,
496 struct HINSTANCE__ *hPrevInstance,
501 return main (__argc, __argv);
505 * If this application has no console window to which its standard output
506 * would go, create one.
512 /* We have no console to which to print the version string, so
513 create one and make it the standard input, output, and error. */
515 return; /* couldn't create console */
516 eth_freopen("CONIN$", "r", stdin);
517 eth_freopen("CONOUT$", "w", stdout);
518 eth_freopen("CONOUT$", "w", stderr);
520 /* Well, we have a console now. */
523 /* Now register "destroy_console()" as a routine to be called just
524 before the application exits, so that we can destroy the console
525 after the user has typed a key (so that the console doesn't just
526 disappear out from under them, giving the user no chance to see
527 the message(s) we put in there). */
528 atexit(destroy_console);
530 SetConsoleTitle("Ethereal Capture Child Debug Console");
535 destroy_console(void)
538 printf("\n\nPress any key to exit\n");
546 /* This routine should not be necessary, at least as I read the GLib
547 source code, as it looks as if GLib is, on Win32, *supposed* to
548 create a console window into which to display its output.
550 That doesn't happen, however. I suspect there's something completely
551 broken about that code in GLib-for-Win32, and that it may be related
552 to the breakage that forces us to just call "printf()" on the message
553 rather than passing the message on to "g_log_default_handler()"
554 (which is the routine that does the aforementioned non-functional
555 console window creation). */
557 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
558 const char *message, gpointer user_data _U_)
565 /* ignore log message, if log_level isn't interesting */
566 if( !(log_level & G_LOG_LEVEL_MASK & ~G_LOG_LEVEL_DEBUG /*prefs.console_log_level*/)) {
570 /* create a "timestamp" */
572 today = localtime(&curr);
575 // if (prefs.gui_console_open != console_open_never) {
579 /* For some unknown reason, the above doesn't appear to actually cause
580 anything to be sent to the standard output, so we'll just splat the
581 message out directly, just to make sure it gets out. */
583 switch(log_level & G_LOG_LEVEL_MASK) {
584 case G_LOG_LEVEL_ERROR:
587 case G_LOG_LEVEL_CRITICAL:
590 case G_LOG_LEVEL_WARNING:
593 case G_LOG_LEVEL_MESSAGE:
596 case G_LOG_LEVEL_INFO:
599 case G_LOG_LEVEL_DEBUG:
603 fprintf(stderr, "unknown log_level %u\n", log_level);
605 g_assert_not_reached();
608 /* don't use printf (stdout), as the capture child uses stdout for it's sync_pipe */
609 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
610 today->tm_hour, today->tm_min, today->tm_sec,
611 log_domain != NULL ? log_domain : "",
615 g_log_default_handler(log_domain, log_level, message, user_data);
621 /* Size of buffer to hold decimal representation of
622 signed/unsigned 64-bit int */
623 #define SP_DECISIZE 20
626 * Indications sent out on the sync pipe.
628 #define SP_FILE 'F' /* the name of the recently opened file */
629 #define SP_ERROR_MSG 'E' /* error message */
630 #define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
631 #define SP_DROPS 'D' /* count of packets dropped in capture */
632 #define SP_QUIT 'Q' /* capture quit message (from parent to child) */
635 pipe_write_block(int pipe, char indicator, int len, const char *msg)
640 sync_pipe_packet_count_to_parent(int packet_count)
642 char tmp[SP_DECISIZE+1+1];
644 g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
646 //g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_packet_count_to_parent: %s", tmp);
648 pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
652 sync_pipe_filename_to_parent(const char *filename)
654 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "File: %s", filename);
656 pipe_write_block(1, SP_FILE, strlen(filename)+1, filename);
660 sync_pipe_errmsg_to_parent(const char *errmsg)
662 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
664 pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
668 sync_pipe_drops_to_parent(int drops)
670 char tmp[SP_DECISIZE+1+1];
673 g_snprintf(tmp, sizeof(tmp), "%d", drops);
675 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_drops_to_parent: %s", tmp);
677 pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
682 /****************************************************************************************************************/
685 void main_window_update(void) {}
687 /* exit the main window */
688 void main_window_exit(void)
693 /* quit a nested main window */
694 void main_window_nested_quit(void)
696 // if (gtk_main_level() > 0)
700 /* quit the main window */
701 void main_window_quit(void)
706 void pipe_input_set_handler(gint source, gpointer user_data, int *child_process, pipe_input_cb_t input_cb)
708 /* we don't use a pipe input for */
712 void capture_info_create(capture_info *cinfo, gchar *iface) {}
714 void capture_info_update(capture_info *cinfo) {
715 printf("Packets: %u\r", cinfo->counts->total);
718 void capture_info_destroy(capture_info *cinfo) {}
722 display_simple_dialog(gint type, gint btn_mask, char *message)
724 printf("%s", message);
729 char *simple_dialog_primary_start(void)
734 char *simple_dialog_primary_end(void)
739 /* Simple dialog function - Displays a dialog box with the supplied message
743 * type : One of ESD_TYPE_*.
744 * btn_mask : The value passed in determines which buttons are displayed.
745 * msg_format : Sprintf-style format of the text displayed in the dialog.
746 * ... : Argument list for msg_format
750 vsimple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, va_list ap)
755 #if GTK_MAJOR_VERSION >= 2
756 GdkWindowState state = 0;
759 /* Format the message. */
760 vmessage = g_strdup_vprintf(msg_format, ap);
762 #if GTK_MAJOR_VERSION >= 2
763 /* convert character encoding from locale to UTF8 (using iconv) */
764 message = g_locale_to_utf8(vmessage, -1, NULL, NULL, NULL);
770 win = display_simple_dialog(type, btn_mask, message);
778 simple_dialog(ESD_TYPE_E type, gint btn_mask, const gchar *msg_format, ...)
783 va_start(ap, msg_format);
784 ret = vsimple_dialog(type, btn_mask, msg_format, ap);
790 simple_dialog_format_message(const char *msg)
795 #if GTK_MAJOR_VERSION < 2
798 str = xml_escape(msg);
810 void fileset_file_opened(const char *fname) {}
811 void fileset_file_closed(void) {}
812 void fileset_dlg_add_file(fileset_entry *entry) {}
814 void packet_list_thaw(void) {}
815 void packet_list_clear(void) {}
816 void packet_list_freeze(void) {}
817 void packet_list_select_row(gint row) {}
818 void packet_list_moveto_end(void) {}
819 gint packet_list_find_row_from_data(gpointer data) { return 1; }
820 void packet_list_set_text(gint row, gint column, const gchar *text) {}
821 void packet_list_set_cls_time_width(gint column) {}
822 void packet_list_set_selected_row(gint row) {}
823 gint packet_list_append(const gchar *text[], gpointer data) { return 1; }
824 gint packet_list_get_sort_column(void) { return 1; }
825 gpointer packet_list_get_row_data(gint row) { return NULL; }
826 void packet_list_set_colors(gint row, color_t *fg, color_t *bg) {}
829 #include "progress_dlg.h"
831 void destroy_progress_dlg(progdlg_t *dlg) {}
832 void update_progress_dlg(progdlg_t *dlg, gfloat percentage, const gchar *status) {}
834 delayed_create_progress_dlg(const gchar *task_title, const gchar *item_title,
835 gboolean terminate_is_stop, gboolean *stop_flag,
836 const GTimeVal *start_time, gfloat progress) { return NULL; }
838 void tap_dfilter_dlg_update (void) {}
841 #include "color_filters.h"
843 color_filter_t * color_filters_colorize_packet(gint row, epan_dissect_t *edt) { return NULL; }
844 void color_filters_prime_edt(epan_dissect_t *edt) {}
845 gboolean color_filters_used(void) { return FALSE; }