diff options
author | Guy Harris <guy@alum.mit.edu> | 2003-11-01 02:30:18 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2003-11-01 02:30:18 +0000 |
commit | 219b6cefa2380d726788967886907b9aa751dfdc (patch) | |
tree | 8cfd28761860f069df6b8e3ebe81a3dbee7dd825 | |
parent | 9ac0cce997ff284748ba351ab6abcfffce0eede4 (diff) |
Based on a patch from Brian Fundakowski Feldman, add support for setting
link-layer type when capturing, using the "pcap_set_datalink()" and
related APIs.
svn path=/trunk/; revision=8848
-rw-r--r-- | AUTHORS | 4 | ||||
-rw-r--r-- | acinclude.m4 | 4 | ||||
-rw-r--r-- | capture.c | 22 | ||||
-rw-r--r-- | capture.h | 4 | ||||
-rw-r--r-- | doc/ethereal.pod | 45 | ||||
-rw-r--r-- | doc/tethereal.pod | 11 | ||||
-rw-r--r-- | globals.h | 4 | ||||
-rw-r--r-- | gtk/capture_dlg.c | 135 | ||||
-rw-r--r-- | gtk/main.c | 170 | ||||
-rw-r--r-- | pcap-util.c | 127 | ||||
-rw-r--r-- | pcap-util.h | 27 | ||||
-rw-r--r-- | tethereal.c | 190 |
12 files changed, 622 insertions, 121 deletions
@@ -1904,6 +1904,10 @@ Scott Emberley <scotte [AT] netinst.com> { Support for reading Network Instruments version 9 capture files } +Brian Fundakowski Feldman <bfeldman [AT] fla.fujitsu.com> { + Support for setting link-layer type when capturing +} + And assorted fixes and enhancements by the people listed above and by: Pavel Roskin <proski [AT] gnu.org> diff --git a/acinclude.m4 b/acinclude.m4 index 4d603ce6bb..76109ff08f 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -2,7 +2,7 @@ dnl Macros that test for specific features. dnl This file is part of the Autoconf packaging for Ethereal. dnl Copyright (C) 1998-2000 by Gerald Combs. dnl -dnl $Id: acinclude.m4,v 1.61 2003/10/14 07:36:39 guy Exp $ +dnl $Id: acinclude.m4,v 1.62 2003/11/01 02:30:14 guy Exp $ dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by @@ -353,6 +353,8 @@ and did you also install that package?]])) AC_MSG_RESULT(no) fi AC_CHECK_FUNCS(pcap_findalldevs pcap_lib_version pcap_compile_nopcap) + AC_CHECK_FUNCS(pcap_datalink_val_to_name pcap_datalink_name_to_val) + AC_CHECK_FUNCS(pcap_list_datalinks pcap_set_datalink) LIBS="$ac_save_LIBS" ]) @@ -1,7 +1,7 @@ /* capture.c * Routines for packet capture windows * - * $Id: capture.c,v 1.212 2003/10/11 21:49:56 jmayer Exp $ + * $Id: capture.c,v 1.213 2003/11/01 02:30:14 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -395,6 +395,12 @@ do_capture(const char *save_file) argv = add_arg(argv, &argc, ssnap); } + if (capture_opts.linktype != -1) { + argv = add_arg(argv, &argc, "-y"); + sprintf(ssnap,"%d",capture_opts.linktype); + argv = add_arg(argv, &argc, ssnap); + } + if (capture_opts.has_autostop_filesize) { argv = add_arg(argv, &argc, "-a"); sprintf(sautostop_filesize,"filesize:%d",capture_opts.autostop_filesize); @@ -1387,6 +1393,7 @@ capture(gboolean *stats_known, struct pcap_stat *stats) gchar label_str[64]; bpf_u_int32 netnum, netmask; struct bpf_program fcode; + const char *set_linktype_err_str; time_t upd_time, cur_time; time_t start_time; int err, inpkts; @@ -1525,7 +1532,18 @@ capture(gboolean *stats_known, struct pcap_stat *stats) capture_opts.promisc_mode, CAP_READ_TIMEOUT, open_err_str); - if (pch == NULL) { + if (pch != NULL) { + /* setting the data link type only works on real interfaces */ + if (capture_opts.linktype != -1) { + set_linktype_err_str = set_pcap_linktype(pch, cfile.iface, + capture_opts.linktype); + if (set_linktype_err_str != NULL) { + snprintf(errmsg, sizeof errmsg, "Unable to set data link type (%s).", + set_linktype_err_str); + goto error; + } + } + } else { /* We couldn't open "cfile.iface" as a network device. */ #ifdef _WIN32 /* On Windows, we don't support capturing on pipes, so we give up. @@ -1,7 +1,7 @@ /* capture.h * Definitions for packet capture windows * - * $Id: capture.h,v 1.36 2003/09/15 23:15:31 guy Exp $ + * $Id: capture.h,v 1.37 2003/11/01 02:30:14 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -50,6 +50,8 @@ typedef struct { guint32 ringbuffer_num_files; /* Number of ring buffer files */ gboolean has_ring_duration; /* TRUE if ring duration specified */ gint32 ringbuffer_duration; /* Switch file after n seconds */ + int linktype; /* Data link type to use, or -1 for + "use default" */ } capture_options; extern capture_options capture_opts; diff --git a/doc/ethereal.pod b/doc/ethereal.pod index 0d44074f71..905bed4b15 100644 --- a/doc/ethereal.pod +++ b/doc/ethereal.pod @@ -15,6 +15,7 @@ S<[ B<-h> ]> S<[ B<-i> interface ]> S<[ B<-k> ]> S<[ B<-l> ]> +S<[ B<-L> ]> S<[ B<-m> font ]> S<[ B<-n> ]> S<[ B<-N> resolving flags ] > @@ -30,6 +31,7 @@ S<[ B<-T> tree view height ]> S<[ B<-t> time stamp format ]> S<[ B<-v> ]> S<[ B<-w> savefile]> +S<[ B<-y> link type ]> S<[ B<-z> statistics-string ]> S<[ infile ]> @@ -182,6 +184,10 @@ Turn on automatic scrolling if the packet display is being updated automatically as packets arrive during a capture (as specified by the B<-S> flag). +=item -L + +List the data link types supported by the interface and exit. + =item -m Set the name of the font used by B<Ethereal> for most text. @@ -276,6 +282,12 @@ Print the version and exit. Set the default capture file name. +=item -y + +If a capture is started from the command line with B<-k>, set the data +link type to use while capturing packets. The values reported by B<-L> +are the values that can be used. + =item -z Get B<Ethereal> to collect various types of statistics and display the result @@ -1266,13 +1278,31 @@ live packet data; these are used the first time a capture is started. The I<Interface:> combo box lets you specify the interface from which to capture packet data, or the name of a FIFO from which to get the packet -data. You can specify whether the interface is to be put in promiscuous -mode or not with the I<Capture packets in promiscuous mode> check box, -can specify that the display should be updated as packets are captured -with the I<Update list of packets in real time> check box, and can -specify whether in such a capture the packet list pane should scroll to -show the most recently captured packets with the I<Automatic scrolling -in live capture> check box. +data. + +The I<Data link type:> option menu lets you, for some interfaces, select +the data link header you want to see on the packets you capture. For +example, in some OSes and with some versions of libpcap, you can choose, +on an 802.11 interface, whether the packets should appear as Ethernet +packets (with a fake Ethernet header) or as 802.11 packets. + +The I<Limit each packet to ... bytes> check box lets you set the +snapshot length to use when capturing live data; turn on the check box, +and then set the number of bytes to use as the snapshot length. + +The I<Filter:> text entry lets you set a capture filter expression to be +used when capturing. + +The I<Capture packets in promiscuous mode> check box lets you specify +whether to put the interface in promiscuous mode when capturing. + +The I<Update list of packets in real time> check box lets you specify +that the display should be updated as packets are seen. + +The I<Automatic scrolling in live capture> check box lets you specify +whether, in an "Update list of packets in real time" capture, the packet +list pane should automatically scroll to show the most recently captured +packets. =item Protocol Preferences @@ -1951,6 +1981,7 @@ B<http://www.ethereal.com>. Loïc Minier <lool [AT] dooz.org> Marcel Holtmann <marcel [AT] holtmann.org> Scott Emberley <scotte [AT] netinst.com> + Brian Fundakowski Feldman <bfeldman [AT] fla.fujitsu.com> Pavel Roskin <proski [AT] gnu.org> Georgi Guninski <guninski [AT] guninski.com> Jason Copenhaver <jcopenha [AT] typedef.org> diff --git a/doc/tethereal.pod b/doc/tethereal.pod index 448121643d..0bd3988717 100644 --- a/doc/tethereal.pod +++ b/doc/tethereal.pod @@ -16,6 +16,7 @@ S<[ B<-F> file format ]> S<[ B<-h> ]> S<[ B<-i> interface ]> S<[ B<-l> ]> +S<[ B<-L> ]> S<[ B<-n> ]> S<[ B<-N> resolving flags ]> S<[ B<-o> preference setting ] ...> @@ -30,6 +31,7 @@ S<[ B<-v> ]> S<[ B<-V> ]> S<[ B<-w> savefile ]> S<[ B<-x> ]> +S<[ B<-y> link type ]> S<[ B<-z> statistics-string ]> S<[ filter expression ]> @@ -276,6 +278,10 @@ see the dissected data for a packet as soon as B<Tethereal> sees the packet and generates that output, rather than seeing it only when the standard output buffer containing that data fills up. +=item -L + +List the data link types supported by the interface and exit. + =item -n Disable network object name resolution (such as hostname, TCP and UDP port @@ -367,6 +373,11 @@ I<savefile> is "-". Cause B<Tethereal> to print a hex and ASCII dump of the packet data after printing the summary or protocol tree. +=item -y + +Set the data link type to use while capturing packets. The values +reported by B<-L> are the values that can be used. + =item -z Get B<Tethereal> to collect various types of statistics and display the result @@ -1,7 +1,7 @@ /* globals.h * Global defines, etc. * - * $Id: globals.h,v 1.31 2003/09/24 00:47:36 guy Exp $ + * $Id: globals.h,v 1.32 2003/11/01 02:30:14 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -28,8 +28,6 @@ #include "file.h" #include <epan/timestamp.h> -#define MIN_PACKET_SIZE 68 /* minimum amount of packet data we can read */ - extern capture_file cfile; extern gchar *ethereal_path; extern gchar *last_open_dir; diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c index 44680462bf..0f03de2acd 100644 --- a/gtk/capture_dlg.c +++ b/gtk/capture_dlg.c @@ -1,7 +1,7 @@ /* capture_dlg.c * Routines for packet capture windows * - * $Id: capture_dlg.c,v 1.84 2003/09/24 08:43:34 guy Exp $ + * $Id: capture_dlg.c,v 1.85 2003/11/01 02:30:17 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -56,6 +56,8 @@ /* Capture callback data keys */ #define E_CAP_IFACE_KEY "cap_iface" #define E_CAP_SNAP_CB_KEY "cap_snap_cb" +#define E_CAP_LT_OM_KEY "cap_lt_om" +#define E_CAP_LT_OM_LABEL_KEY "cap_lt_om_label" #define E_CAP_SNAP_SB_KEY "cap_snap_sb" #define E_CAP_PROMISC_KEY "cap_promisc" #define E_CAP_FILT_KEY "cap_filter_te" @@ -78,6 +80,8 @@ #define E_CAP_N_RESOLVE_KEY "cap_n_resolve" #define E_CAP_T_RESOLVE_KEY "cap_t_resolve" +#define E_CAP_OM_LT_VALUE_KEY "cap_om_lt_value" + #define E_FS_CALLER_PTR_KEY "fs_caller_ptr" #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr" @@ -85,6 +89,9 @@ static void capture_prep_file_cb(GtkWidget *w, gpointer te); static void +select_link_type_cb(GtkWidget *w, gpointer data); + +static void cap_prep_fs_ok_cb(GtkWidget *w, gpointer data); static void @@ -105,6 +112,9 @@ capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w); static void capture_prep_destroy_cb(GtkWidget *win, gpointer user_data); +static void +capture_prep_interface_changed_cb(GtkWidget *entry, gpointer parent_w); + void capture_stop_cb(GtkWidget *w _U_, gpointer d _U_) { @@ -119,12 +129,68 @@ capture_stop_cb(GtkWidget *w _U_, gpointer d _U_) */ static GtkWidget *cap_open_w; +static void +set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry) +{ + gchar *entry_text; + gchar *if_text; + gchar *if_name; + GList *lt_list; + char err_buf[PCAP_ERRBUF_SIZE]; + GtkWidget *lt_menu, *lt_menu_item; + GList *lt_entry; + data_link_info_t *data_link_info; + gchar *linktype_menu_label; + guint num_supported_link_types; + GtkWidget *linktype_lb = OBJECT_GET_DATA(linktype_om, E_CAP_LT_OM_LABEL_KEY); + + lt_menu = gtk_menu_new(); + entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); + if_text = g_strstrip(entry_text); + if_name = strrchr(if_text, ' '); + if (if_name == NULL) { + if_name = if_text; + } else { + if_name++; + } + + if (*if_name != '\0') + lt_list = get_pcap_linktype_list(if_name, err_buf); + else + lt_list = NULL; + g_free(entry_text); + num_supported_link_types = 0; + for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) { + data_link_info = lt_entry->data; + if (data_link_info->description != NULL) { + lt_menu_item = gtk_menu_item_new_with_label(data_link_info->description); + OBJECT_SET_DATA(lt_menu_item, E_CAP_LT_OM_KEY, linktype_om); + SIGNAL_CONNECT(lt_menu_item, "activate", select_link_type_cb, + GINT_TO_POINTER(data_link_info->dlt)); + num_supported_link_types++; + } else { + /* Not supported - tell them about it but don't let them select it. */ + linktype_menu_label = g_strdup_printf("%s (not supported)", + data_link_info->name); + lt_menu_item = gtk_menu_item_new_with_label(linktype_menu_label); + g_free(linktype_menu_label); + gtk_widget_set_sensitive(lt_menu_item, FALSE); + } + gtk_menu_append(GTK_MENU(lt_menu), lt_menu_item); + gtk_widget_show(lt_menu_item); + } + gtk_option_menu_set_menu(GTK_OPTION_MENU(linktype_om), lt_menu); + gtk_widget_set_sensitive(linktype_lb, num_supported_link_types != 0); + gtk_widget_set_sensitive(linktype_om, num_supported_link_types != 0); +} + void capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) { GtkWidget *main_vb, *capture_fr, *capture_vb, *if_hb, *if_cb, *if_lb, + *linktype_hb, *linktype_lb, *linktype_om, *snap_hb, *snap_cb, *snap_sb, *snap_lb, *promisc_cb, *filter_hb, *filter_bt, *filter_te, @@ -242,6 +308,25 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) gtk_box_pack_start(GTK_BOX(if_hb), if_cb, TRUE, TRUE, 6); gtk_widget_show(if_cb); + /* Linktype row */ + linktype_hb = gtk_hbox_new(FALSE, 3); + gtk_container_add(GTK_CONTAINER(capture_vb), linktype_hb); + gtk_widget_show(linktype_hb); + + linktype_lb = gtk_label_new("Data link type:"); + gtk_box_pack_start(GTK_BOX(linktype_hb), linktype_lb, FALSE, FALSE, 6); + gtk_widget_show(linktype_lb); + + linktype_om = gtk_option_menu_new(); + OBJECT_SET_DATA(linktype_om, E_CAP_LT_OM_LABEL_KEY, linktype_lb); + /* Default to "use the default" */ + OBJECT_SET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(-1)); + set_link_type_list(linktype_om, GTK_COMBO(if_cb)->entry); + gtk_box_pack_start (GTK_BOX(linktype_hb), linktype_om, FALSE, FALSE, 0); + gtk_widget_show(linktype_om); + SIGNAL_CONNECT(GTK_ENTRY(GTK_COMBO(if_cb)->entry), "changed", + capture_prep_interface_changed_cb, linktype_om); + /* Capture length row */ snap_hb = gtk_hbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(capture_vb), snap_hb); @@ -587,6 +672,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) OBJECT_SET_DATA(cap_open_w, E_CAP_IFACE_KEY, if_cb); OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_CB_KEY, snap_cb); OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_SB_KEY, snap_sb); + OBJECT_SET_DATA(cap_open_w, E_CAP_LT_OM_KEY, linktype_om); OBJECT_SET_DATA(cap_open_w, E_CAP_PROMISC_KEY, promisc_cb); OBJECT_SET_DATA(cap_open_w, E_CAP_FILT_KEY, filter_te); OBJECT_SET_DATA(cap_open_w, E_CAP_FILE_TE_KEY, file_te); @@ -651,6 +737,17 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) } static void +select_link_type_cb(GtkWidget *w, gpointer data) +{ + int new_linktype = GPOINTER_TO_INT(data); + GtkWidget *linktype_om = OBJECT_GET_DATA(w, E_CAP_LT_OM_KEY); + int old_linktype = GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY)); + + if (old_linktype != new_linktype) + OBJECT_SET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(new_linktype)); +} + +static void capture_prep_file_cb(GtkWidget *w, gpointer file_te) { GtkWidget *caller = gtk_widget_get_toplevel(w); @@ -756,12 +853,13 @@ static void capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) { GtkWidget *if_cb, *snap_cb, *snap_sb, *promisc_cb, *filter_te, *file_te, *ringbuffer_on_tb, *ringbuffer_nbf_sb, - *sync_cb, *auto_scroll_cb, + *linktype_om, *sync_cb, *auto_scroll_cb, *count_cb, *count_sb, *filesize_cb, *filesize_sb, *duration_cb, *duration_sb, *ring_duration_cb, *ring_duration_sb, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb; + gchar *entry_text; gchar *if_text; gchar *if_name; gchar *filter_text; @@ -772,6 +870,7 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) { if_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY); snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY); snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY); + linktype_om = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_OM_KEY); promisc_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_PROMISC_KEY); filter_te = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILT_KEY); file_te = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILE_TE_KEY); @@ -791,27 +890,32 @@ capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) { n_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_N_RESOLVE_KEY); t_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_T_RESOLVE_KEY); - if_text = + entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry))); - /* Remove interface description. Also, Windows combo entries have a - description followed by the interface name. These two cases are - OK as long as they're in front. */ + if_text = g_strstrip(entry_text); + /* Remove interface description; if it's present, it comes before + the interface name, and there's a space between them, and the + interface name is assumed to contain no space, so we look backwards + in the string for a space. */ if_name = strrchr(if_text, ' '); if (if_name == NULL) { if_name = if_text; } else { if_name++; } - if (if_name == NULL) { + if (*if_name == '\0') { simple_dialog(ESD_TYPE_CRIT, NULL, "You didn't specify an interface on which to capture packets."); - g_free(if_text); + g_free(entry_text); return; } if (cfile.iface) g_free(cfile.iface); cfile.iface = g_strdup(if_name); - g_free(if_text); + g_free(entry_text); + + capture_opts.linktype = + GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY)); capture_opts.has_snaplen = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)); @@ -951,6 +1055,14 @@ capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_) cap_open_w = NULL; } +static void +capture_prep_interface_changed_cb(GtkWidget *entry, gpointer argp) +{ + GtkWidget *linktype_om = argp; + + set_link_type_list(linktype_om, entry); +} + /* * Adjust the sensitivity of various widgets as per the current setting * of other widgets. @@ -958,7 +1070,8 @@ capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_) static void capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) { - GtkWidget *snap_cb, *snap_sb, + GtkWidget *if_cb, + *snap_cb, *snap_sb, *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb, *sync_cb, *auto_scroll_cb, *count_cb, *count_sb, @@ -966,6 +1079,7 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) *duration_cb, *duration_sb, *ring_duration_cb, *ring_duration_sb; + if_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY); snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY); snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY); ringbuffer_on_tb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY); @@ -1060,7 +1174,6 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) after N seconds" checkbox is on. */ gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_sb), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb))); - } #endif /* HAVE_LIBPCAP */ diff --git a/gtk/main.c b/gtk/main.c index 7d83dcd70d..95b2240816 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1,6 +1,6 @@ /* main.c * - * $Id: main.c,v 1.326 2003/10/20 22:28:22 guy Exp $ + * $Id: main.c,v 1.327 2003/11/01 02:30:18 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -165,6 +165,8 @@ static void console_log_handler(const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer user_data); #endif +static gboolean list_link_layer_types; + static void create_main_window(gint, gint, gint, e_prefs*); #define E_DFILTER_CM_KEY "display_filter_combo" @@ -1294,7 +1296,7 @@ print_usage(gboolean print_ver) { comp_info_str->str, runtime_info_str->str); } #ifdef HAVE_LIBPCAP - fprintf(stderr, "\n%s [ -vh ] [ -klnpQS ] [ -a <capture autostop condition> ] ...\n", + fprintf(stderr, "\n%s [ -vh ] [ -klLnpQS ] [ -a <capture autostop condition> ] ...\n", PACKAGE); fprintf(stderr, "\t[ -b <number of ringbuffer files>[:<duration>] ]\n"); fprintf(stderr, "\t[ -B <byte view height> ] [ -c <count> ] [ -f <capture filter> ]\n"); @@ -1302,7 +1304,7 @@ print_usage(gboolean print_ver) { fprintf(stderr, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n"); fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n"); fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n"); - fprintf(stderr, "\t[ -w <savefile> ] [ <infile> ]\n"); + fprintf(stderr, "\t[ -w <savefile> ] [ -y <link type> ] [ <infile> ]\n"); #else fprintf(stderr, "\n%s [ -vh ] [ -n ] [ -B <byte view height> ] [ -m <medium font> ]\n", PACKAGE); @@ -1572,6 +1574,8 @@ main(int argc, char *argv[]) gchar *save_file = NULL; GList *if_list; if_info_t *if_info; + GList *lt_list, *lt_entry; + data_link_info_t *data_link_info; gchar err_str[PCAP_ERRBUF_SIZE]; gboolean stats_known; struct pcap_stat stats; @@ -1591,7 +1595,7 @@ main(int argc, char *argv[]) ethereal_tap_list *tli = NULL; gchar *tap_opt = NULL; -#define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:vz:" +#define OPTSTRING_INIT "a:b:B:c:f:hi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:" #ifdef HAVE_LIBPCAP #ifdef WIN32 @@ -1735,6 +1739,7 @@ main(int argc, char *argv[]) capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES; capture_opts.has_ring_duration = FALSE; capture_opts.ringbuffer_duration = 1; + capture_opts.linktype = -1; /* If this is a capture child process, it should pay no attention to the "prefs.capture_prom_mode" setting in the preferences file; @@ -1872,6 +1877,15 @@ main(int argc, char *argv[]) arg_error = TRUE; #endif break; + case 'L': /* Print list of link-layer types and exit */ +#ifdef HAVE_LIBPCAP + list_link_layer_types = TRUE; + break; +#else + capture_option_specified = TRUE; + arg_error = TRUE; +#endif + break; case 'm': /* Fixed-width font for the display */ if (prefs->gui_font_name != NULL) g_free(prefs->gui_font_name); @@ -1988,6 +2002,24 @@ main(int argc, char *argv[]) arg_error = TRUE; #endif break; + case 'y': /* Set the pcap data link type */ +#ifdef HAVE_LIBPCAP +#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL + capture_opts.linktype = pcap_datalink_name_to_val(optarg); + if (capture_opts.linktype == -1) { + fprintf(stderr, "ethereal: The specified data link type \"%s\" is not valid\n", + optarg); + exit(1); + } +#else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */ + /* XXX - just treat it as a number */ + capture_opts.linktype = get_natural_int(optarg, "data link type"); +#endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */ +#else /* HAVE_LIBPCAP */ + capture_option_specified = TRUE; + arg_error = TRUE; +#endif /* HAVE_LIBPCAP */ + break; #ifdef HAVE_LIBPCAP /* This is a hidden option supporting Sync mode, so we don't set * the error flags for the user in the non-libpcap case. @@ -2066,59 +2098,71 @@ main(int argc, char *argv[]) fprintf(stderr, "Invalid argument: %s\n", argv[0]); arg_error = TRUE; } + +#ifndef HAVE_LIBPCAP + if (capture_option_specified) + fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n"); +#endif if (arg_error) { print_usage(FALSE); exit(1); } #ifdef HAVE_LIBPCAP - if (capture_opts.ringbuffer_on) { - /* Ring buffer works only under certain conditions: - a) ring buffer does not work with temporary files; - b) sync_mode and capture_opts.ringbuffer_on are mutually exclusive - - sync_mode takes precedence; - c) it makes no sense to enable the ring buffer if the maximum - file size is set to "infinite". */ - if (save_file == NULL) { - fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n"); - capture_opts.ringbuffer_on = FALSE; - } - if (capture_opts.sync_mode) { - fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n"); - capture_opts.ringbuffer_on = FALSE; - } - if (!capture_opts.has_autostop_filesize) { - fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n"); - capture_opts.ringbuffer_on = FALSE; - } - } -#endif - - /* Notify all registered modules that have had any of their preferences - changed either from one of the preferences file or from the command - line that their preferences have changed. */ - prefs_apply_all(); - - /* disabled protocols as per configuration file */ - if (dp_path == NULL) { - set_disabled_protos_list(); + if (start_capture && list_link_layer_types) { + /* Specifying *both* is bogus. */ + fprintf(stderr, "ethereal: You cannot specify both -L and a live capture.\n"); + exit(1); } -#ifndef HAVE_LIBPCAP - if (capture_option_specified) - fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n"); -#endif -#ifdef HAVE_LIBPCAP - if (start_capture) { + if (list_link_layer_types) { + /* We're supposed to list the link-layer types for an interface; + did the user also specify a capture file to be read? */ + if (cf_name) { + /* Yes - that's bogus. */ + fprintf(stderr, "ethereal: You cannot specify -L and a capture file to be read.\n"); + exit(1); + } + /* No - did they specify a ring buffer option? */ + if (capture_opts.ringbuffer_on) { + fprintf(stderr, "ethereal: Ring buffer requested, but a capture is not being done.\n"); + exit(1); + } + } else { /* We're supposed to do a live capture; did the user also specify a capture file to be read? */ if (cf_name) { /* Yes - that's bogus. */ fprintf(stderr, "ethereal: You cannot specify both a live capture and a capture file to be read.\n"); - exit(2); + exit(1); } - - /* No - did the user specify an interface to use? */ + + /* No - was the ring buffer option specified and, if so, does it make + sense? */ + if (capture_opts.ringbuffer_on) { + /* Ring buffer works only under certain conditions: + a) ring buffer does not work with temporary files; + b) sync_mode and capture_opts.ringbuffer_on are mutually exclusive - + sync_mode takes precedence; + c) it makes no sense to enable the ring buffer if the maximum + file size is set to "infinite". */ + if (save_file == NULL) { + fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n"); + capture_opts.ringbuffer_on = FALSE; + } + if (capture_opts.sync_mode) { + fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n"); + capture_opts.ringbuffer_on = FALSE; + } + if (!capture_opts.has_autostop_filesize) { + fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n"); + capture_opts.ringbuffer_on = FALSE; + } + } + } + + if (start_capture || list_link_layer_types) { + /* Did the user specify an interface to use? */ if (cfile.iface == NULL) { /* No - is a default specified in the preferences file? */ if (prefs->capture_device != NULL) { @@ -2147,16 +2191,54 @@ main(int argc, char *argv[]) } } } + if (capture_child) { if (cfile.save_file_fd == -1) { /* XXX - send this to the standard output as something our parent - should put in an error message box? */ + should put in an error message box? */ fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME); exit(1); } } + + if (list_link_layer_types) { + /* Get the list of link-layer types for the capture device. */ + lt_list = get_pcap_linktype_list(cfile.iface, err_str); + if (lt_list == NULL) { + if (err_str[0] != '\0') { + fprintf(stderr, "ethereal: The list of data link types for the capture device could not be obtained (%s).\n" + "Please check to make sure you have sufficient permissions, and that\n" + "you have the proper interface or pipe specified.\n", err_str); + } else + fprintf(stderr, "ethereal: The capture device has no data link types.\n"); + exit(2); + } + fprintf(stderr, "Data link types (use option -y to set):\n"); + for (lt_entry = lt_list; lt_entry != NULL; + lt_entry = g_list_next(lt_entry)) { + data_link_info = lt_entry->data; + fprintf(stderr, " %s", data_link_info->name); + if (data_link_info->description != NULL) + fprintf(stderr, " (%s)", data_link_info->description); + else + fprintf(stderr, " (not supported)"); + putchar('\n'); + } + free_pcap_linktype_list(lt_list); + exit(0); + } #endif + /* Notify all registered modules that have had any of their preferences + changed either from one of the preferences file or from the command + line that their preferences have changed. */ + prefs_apply_all(); + + /* disabled protocols as per configuration file */ + if (dp_path == NULL) { + set_disabled_protos_list(); + } + /* Build the column format array */ col_setup(&cfile.cinfo, prefs->num_cols); for (i = 0; i < cfile.cinfo.num_cols; i++) { diff --git a/pcap-util.c b/pcap-util.c index 2a2615b10f..064e8097a0 100644 --- a/pcap-util.c +++ b/pcap-util.c @@ -1,7 +1,7 @@ /* pcap-util.c * Utility routines for packet capture * - * $Id: pcap-util.c,v 1.18 2003/10/10 03:00:10 guy Exp $ + * $Id: pcap-util.c,v 1.19 2003/11/01 02:30:14 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -31,6 +31,7 @@ #include <glib.h> #include <stdlib.h> +#include <limits.h> #include <string.h> #ifdef HAVE_SYS_TYPES_H @@ -43,6 +44,9 @@ #include <pcap.h> +#include <wtap.h> +#include <wtap-capture.h> + #include "pcap-util.h" #include "pcap-util-int.h" @@ -231,4 +235,125 @@ free_interface_list(GList *if_list) g_list_free(if_list); } +/* + * Get the data-link types available for a libpcap device. + */ +static data_link_info_t * +create_data_link_info(int dlt) +{ + data_link_info_t *data_link_info; +#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME + const char *typename; +#endif + int wtap_encap; + + data_link_info = g_malloc(sizeof (data_link_info_t)); + data_link_info->dlt = dlt; +#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME + typename = pcap_datalink_val_to_name(dlt); + if (typename != NULL) + data_link_info->name = g_strdup(typename); + else +#endif + data_link_info->name = g_strdup_printf("DLT %d", dlt); + wtap_encap = wtap_pcap_encap_to_wtap_encap(dlt); + if (wtap_encap == WTAP_ENCAP_UNKNOWN) { + /* + * We don't support this in Wiretap. + * However, we should, so you can capture on it. + * Put in an entry for it, with no description. + */ + data_link_info->description = NULL; + } else { + /* + * If this is null, that's a bug in + * "wtap_pcap_encap_to_wtap_encap()" - it should always + * return a valid encapsulation type - so we assume it's + * not null. + */ + data_link_info->description = + g_strdup(wtap_encap_string(wtap_encap)); + } + return data_link_info; +} + +GList * +get_pcap_linktype_list(char *devname, char *err_buf) +{ + GList *linktype_list = NULL; + pcap_t *pch; + int deflt; +#ifdef HAVE_PCAP_SET_DATALINK + int *linktypes; + int i, nlt; +#endif + data_link_info_t *data_link_info; + + pch = pcap_open_live(devname, MIN_PACKET_SIZE, 0, 0, err_buf); + if (pch == NULL) + return NULL; + err_buf[0] = '\0'; /* an empty list doesn't mean an error */ + deflt = get_pcap_linktype(pch, devname); +#ifdef HAVE_PCAP_LIST_DATALINKS + nlt = pcap_list_datalinks(pch, &linktypes); + if (nlt == 0 || linktypes == NULL) + return NULL; + for (i = 0; i < nlt; i++) { + data_link_info = create_data_link_info(linktypes[i]); + + /* + * XXX - for 802.11, make the most detailed 802.11 + * version the default, rather than the one the + * device has as the default? + */ + if (linktypes[i] == deflt) + linktype_list = g_list_prepend(linktype_list, + data_link_info); + else + linktype_list = g_list_append(linktype_list, + data_link_info); + } + free(linktypes); +#else + data_link_info = create_data_link_info(deflt); + linktype_list = g_list_append(linktype_list, data_link_info); +#endif + + pcap_close(pch); + return linktype_list; +} + +static void +free_linktype_cb(gpointer data, gpointer user_data _U_) +{ + data_link_info_t *linktype_info = data; + + g_free(linktype_info->name); + if (linktype_info->description != NULL) + g_free(linktype_info->description); +} + +void +free_pcap_linktype_list(GList *linktype_list) +{ + g_list_foreach(linktype_list, free_linktype_cb, NULL); + g_list_free(linktype_list); +} + +/* Set the data link type on a pcap. */ +const char * +set_pcap_linktype(pcap_t *pch, char *devname, int dlt) +{ +#ifdef HAVE_PCAP_SET_DATALINK + if (pcap_set_datalink(pch, dlt) == 0) + return NULL; /* no error */ + return pcap_geterr(pch); +#else + /* Let them set it to the type it is; reject any other request. */ + if (get_pcap_linktype(pch, devname) == dlt) + return NULL; /* no error */ + return "That DLT is not one of the DLTs supported by this device"; +#endif +} + #endif /* HAVE_LIBPCAP */ diff --git a/pcap-util.h b/pcap-util.h index d110f3c0fc..638454840d 100644 --- a/pcap-util.h +++ b/pcap-util.h @@ -1,7 +1,7 @@ /* pcap-util.h * Utility definitions for packet capture * - * $Id: pcap-util.h,v 1.5 2003/10/10 06:05:48 guy Exp $ + * $Id: pcap-util.h,v 1.6 2003/11/01 02:30:14 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -31,7 +31,15 @@ extern "C" { #endif /* __cplusplus */ -int get_pcap_linktype(pcap_t *pch, char *devname); +/* + * XXX - this is also the traditional default snapshot size in + * tcpdump - but, if IPv6 is enabled, it defaults to 96, to get an + * IPv6 header + TCP + 22 extra bytes. + * + * Some libpcap versions for particular capture devices might happen + * to impose a minimum, but it's not always 68. + */ +#define MIN_PACKET_SIZE 68 /* minimum amount of packet data we can read */ #define MAX_WIN_IF_NAME_LEN 511 @@ -52,6 +60,21 @@ GList *get_interface_list(int *err, char *err_str); void free_interface_list(GList *if_list); +/* + * The list of data link types returned by "get_pcap_linktype_list()" is + * a list of these structures. + */ +typedef struct { + int dlt; + char *name; + char *description; +} data_link_info_t; + +int get_pcap_linktype(pcap_t *pch, char *devname); +GList *get_pcap_linktype_list(char *devname, char *err_buf); +void free_pcap_linktype_list(GList *linktype_list); +const char *set_pcap_linktype(pcap_t *pch, char *devname, int dlt); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/tethereal.c b/tethereal.c index d1dce1de74..d8409297c6 100644 --- a/tethereal.c +++ b/tethereal.c @@ -1,6 +1,6 @@ /* tethereal.c * - * $Id: tethereal.c,v 1.203 2003/10/30 19:56:47 guy Exp $ + * $Id: tethereal.c,v 1.204 2003/11/01 02:30:15 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -194,6 +194,8 @@ typedef struct { guint32 ringbuffer_num_files; /* Number of ring buffer files */ gboolean has_ring_duration; /* TRUE if ring duration specified */ gint32 ringbuffer_duration; /* Switch file after n seconds */ + int linktype; /* Data link type to use, or -1 for + "use default" */ } capture_options; static capture_options capture_opts = { @@ -212,9 +214,12 @@ static capture_options capture_opts = { RINGBUFFER_MIN_NUM_FILES, /* default number of ring buffer files */ FALSE, /* Switch ring file after some */ - 0 /* specified time is off by default */ + 0, /* specified time is off by default */ + -1 /* Default to not change link type */ }; +static gboolean list_link_layer_types; + #ifdef SIGINFO static gboolean infodelay; /* if TRUE, don't print capture info in SIGINFO handler */ static gboolean infoprint; /* if TRUE, print capture info after clearing infodelay */ @@ -231,14 +236,14 @@ print_usage(gboolean print_ver) comp_info_str->str, runtime_info_str->str); } #ifdef HAVE_LIBPCAP - fprintf(stderr, "\nt%s [ -vh ] [ -DlnpqSVx ] [ -a <capture autostop condition> ] ...\n", + fprintf(stderr, "\nt%s [ -vh ] [ -DlLnpqSVx ] [ -a <capture autostop condition> ] ...\n", PACKAGE); fprintf(stderr, "\t[ -b <number of ring buffer files>[:<duration>] ] [ -c <count> ]\n"); fprintf(stderr, "\t[ -d %s ] ...\n", decode_as_arg_template); fprintf(stderr, "\t[ -f <capture filter> ] [ -F <output file type> ] [ -i <interface> ]\n"); fprintf(stderr, "\t[ -N <resolving> ] [ -o <preference setting> ] ... [ -r <infile> ]\n"); fprintf(stderr, "\t[ -R <read filter> ] [ -s <snaplen> ] [ -t <time stamp format> ]\n"); - fprintf(stderr, "\t[ -w <savefile> ] [ -Z <statistics string> ]\n"); + fprintf(stderr, "\t[ -w <savefile> ] [ -y <link type> ] [ -Z <statistics string> ]\n"); #else fprintf(stderr, "\nt%s [ -vh ] [ -lnVx ]\n", PACKAGE); fprintf(stderr, "\t[ -d %s ] ...\n", decode_as_arg_template); @@ -793,6 +798,8 @@ main(int argc, char *argv[]) gchar *cf_name = NULL, *rfilter = NULL; #ifdef HAVE_LIBPCAP gchar *if_text; + GList *lt_list, *lt_entry; + data_link_info_t *data_link_info; #endif #ifdef HAVE_PCAP_COMPILE_NOPCAP struct bpf_program fcode; @@ -903,7 +910,7 @@ main(int argc, char *argv[]) get_runtime_version_info(runtime_info_str); /* Now get our args */ - while ((opt = getopt(argc, argv, "a:b:c:d:Df:F:hi:lnN:o:pqr:R:s:St:vw:Vxz:")) != -1) { + while ((opt = getopt(argc, argv, "a:b:c:d:Df:F:hi:lLnN:o:pqr:R:s:St:vw:Vxy:z:")) != -1) { switch (opt) { case 'a': /* autostop criteria */ #ifdef HAVE_LIBPCAP @@ -1057,7 +1064,9 @@ main(int argc, char *argv[]) /* This isn't line-buffering, strictly speaking, it's just flushing the standard output after the information for each packet is printed; however, that should be good - enough for all the purposes to which "-l" is put. + enough for all the purposes to which "-l" is put (and + is probably actually better for "-V", as it does fewer + writes). See the comment in "wtap_dispatch_cb_print()" for an explanation of why we do that, and why we don't just @@ -1067,6 +1076,15 @@ main(int argc, char *argv[]) when it fills up). */ line_buffered = TRUE; break; + case 'L': /* Print list of link-layer types and exit */ +#ifdef HAVE_LIBPCAP + list_link_layer_types = TRUE; + break; +#else + capture_option_specified = TRUE; + arg_error = TRUE; +#endif + break; case 'n': /* No name resolution */ g_resolv_flags = RESOLV_NONE; break; @@ -1155,6 +1173,24 @@ main(int argc, char *argv[]) case 'x': /* Print packet data in hex (and ASCII) */ print_hex = TRUE; break; + case 'y': /* Set the pcap data link type */ +#ifdef HAVE_LIBPCAP +#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL + capture_opts.linktype = pcap_datalink_name_to_val(optarg); + if (capture_opts.linktype == -1) { + fprintf(stderr, "tethereal: The specified data link type \"%s\" is not valid\n", + optarg); + exit(1); + } +#else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */ + /* XXX - just treat it as a number */ + capture_opts.linktype = get_natural_int(optarg, "data link type"); +#endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */ +#else + capture_option_specified = TRUE; + arg_error = TRUE; +#endif + break; case 'z': for(tli=tap_list;tli;tli=tli->next){ if(!strncmp(tli->cmd,optarg,strlen(tli->cmd))){ @@ -1241,42 +1277,66 @@ main(int argc, char *argv[]) #endif } -#ifdef HAVE_LIBPCAP - /* If they didn't specify a "-w" flag, but specified a maximum capture - file size, tell them that this doesn't work, and exit. */ - if (capture_opts.has_autostop_filesize && cfile.save_file == NULL) { - fprintf(stderr, "tethereal: Maximum capture file size specified, but " - "capture isn't being saved to a file.\n"); - exit(2); +#ifndef HAVE_LIBPCAP + if (capture_option_specified) + fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n"); +#endif + if (arg_error) { + print_usage(FALSE); + exit(1); } - if (capture_opts.ringbuffer_on) { - /* Ring buffer works only under certain conditions: - a) ring buffer does not work if you're not saving the capture to - a file; - b) ring buffer only works if you're saving in libpcap format; - c) it makes no sense to enable the ring buffer if the maximum - file size is set to "infinite"; - d) file must not be a pipe. */ - if (cfile.save_file == NULL) { - fprintf(stderr, "tethereal: Ring buffer requested, but " - "capture isn't being saved to a file.\n"); - exit(2); +#ifdef HAVE_LIBPCAP + if (list_link_layer_types) { + /* We're supposed to list the link-layer types for an interface; + did the user also specify a capture file to be read? */ + if (cf_name) { + /* Yes - that's bogus. */ + fprintf(stderr, "tethereal: You cannot specify -L and a capture file to be read.\n"); + exit(1); } - if (out_file_type != WTAP_FILE_PCAP) { - fprintf(stderr, "tethereal: Ring buffer requested, but " - "capture isn't being saved in libpcap format.\n"); - exit(2); + /* No - did they specify a ring buffer option? */ + if (capture_opts.ringbuffer_on) { + fprintf(stderr, "tethereal: Ring buffer requested, but a capture is not being done.\n"); + exit(1); } - if (!capture_opts.has_autostop_filesize) { - fprintf(stderr, "tethereal: Ring buffer requested, but " - "no maximum capture file size was specified.\n"); - exit(2); + } else { + /* If they didn't specify a "-w" flag, but specified a maximum capture + file size, tell them that this doesn't work, and exit. */ + if (capture_opts.has_autostop_filesize && cfile.save_file == NULL) { + fprintf(stderr, "tethereal: Maximum capture file size specified, but " + "capture isn't being saved to a file.\n"); + exit(1); } - if (ld.output_to_pipe) { - fprintf(stderr, "tethereal: Ring buffer requested, but " - "capture file is a pipe.\n"); - exit(2); + + if (capture_opts.ringbuffer_on) { + /* Ring buffer works only under certain conditions: + a) ring buffer does not work if you're not saving the capture to + a file; + b) ring buffer only works if you're saving in libpcap format; + c) it makes no sense to enable the ring buffer if the maximum + file size is set to "infinite"; + d) file must not be a pipe. */ + if (cfile.save_file == NULL) { + fprintf(stderr, "tethereal: Ring buffer requested, but " + "capture isn't being saved to a file.\n"); + exit(1); + } + if (out_file_type != WTAP_FILE_PCAP) { + fprintf(stderr, "tethereal: Ring buffer requested, but " + "capture isn't being saved in libpcap format.\n"); + exit(2); + } + if (!capture_opts.has_autostop_filesize) { + fprintf(stderr, "tethereal: Ring buffer requested, but " + "no maximum capture file size was specified.\n"); + exit(2); + } + if (ld.output_to_pipe) { + fprintf(stderr, "tethereal: Ring buffer requested, but " + "capture file is a pipe.\n"); + exit(2); + } } } #endif @@ -1296,15 +1356,6 @@ main(int argc, char *argv[]) set_disabled_protos_list(); } -#ifndef HAVE_LIBPCAP - if (capture_option_specified) - fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n"); -#endif - if (arg_error) { - print_usage(FALSE); - exit(1); - } - /* Build the column format array */ col_setup(&cfile.cinfo, prefs->num_cols); for (i = 0; i < cfile.cinfo.num_cols; i++) { @@ -1380,7 +1431,8 @@ main(int argc, char *argv[]) } cf_name[0] = '\0'; } else { - /* No capture file specified, so we're supposed to do a live capture; + /* No capture file specified, so we're supposed to do a live capture + (or get a list of link-layer types for a live capture device); do we have support for live captures? */ #ifdef HAVE_LIBPCAP @@ -1424,6 +1476,35 @@ main(int argc, char *argv[]) free_interface_list(if_list); } } + + if (list_link_layer_types) { + /* We were asked to list the link-layer types for an interface. + Get the list of link-layer types for the capture device. */ + lt_list = get_pcap_linktype_list(cfile.iface, err_str); + if (lt_list == NULL) { + if (err_str[0] != '\0') { + fprintf(stderr, "tethereal: The list of data link types for the capture device could not be obtained (%s).\n" + "Please check to make sure you have sufficient permissions, and that\n" + "you have the proper interface or pipe specified.\n", err_str); + } else + fprintf(stderr, "tethereal: The capture device has no data link types.\n"); + exit(2); + } + fprintf(stderr, "Data link types (use option -y to set):\n"); + for (lt_entry = lt_list; lt_entry != NULL; + lt_entry = g_list_next(lt_entry)) { + data_link_info = lt_entry->data; + fprintf(stderr, " %s", data_link_info->name); + if (data_link_info->description != NULL) + fprintf(stderr, " (%s)", data_link_info->description); + else + fprintf(stderr, " (not supported)"); + putchar('\n'); + } + free_pcap_linktype_list(lt_list); + exit(0); + } + capture(out_file_type); if (capture_opts.ringbuffer_on) { @@ -1457,6 +1538,7 @@ capture(int out_file_type) gchar lookup_net_err_str[PCAP_ERRBUF_SIZE]; bpf_u_int32 netnum, netmask; struct bpf_program fcode; + const char *set_linktype_err_str; void (*oldhandler)(int); int err = 0; int volatile volatile_err = 0; @@ -1478,7 +1560,6 @@ capture(int out_file_type) gboolean dump_ok; dfilter_t *rfcode = NULL; - /* Initialize all data structures used for dissection. */ init_dissection(); @@ -1493,7 +1574,18 @@ capture(int out_file_type) ld.pch = pcap_open_live(cfile.iface, capture_opts.snaplen, capture_opts.promisc_mode, 1000, open_err_str); - if (ld.pch == NULL) { + if (ld.pch != NULL) { + /* setting the data link type only works on real interfaces */ + if (capture_opts.linktype != -1) { + set_linktype_err_str = set_pcap_linktype(ld.pch, cfile.iface, + capture_opts.linktype); + if (set_linktype_err_str != NULL) { + snprintf(errmsg, sizeof errmsg, "Unable to set data link type (%s).", + set_linktype_err_str); + goto error; + } + } + } else { /* We couldn't open "cfile.iface" as a network device. */ #ifdef _WIN32 /* On Windows, we don't support capturing on pipes, so we give up. */ |