aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2003-11-01 02:30:18 +0000
committerGuy Harris <guy@alum.mit.edu>2003-11-01 02:30:18 +0000
commit219b6cefa2380d726788967886907b9aa751dfdc (patch)
tree8cfd28761860f069df6b8e3ebe81a3dbee7dd825
parent9ac0cce997ff284748ba351ab6abcfffce0eede4 (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--AUTHORS4
-rw-r--r--acinclude.m44
-rw-r--r--capture.c22
-rw-r--r--capture.h4
-rw-r--r--doc/ethereal.pod45
-rw-r--r--doc/tethereal.pod11
-rw-r--r--globals.h4
-rw-r--r--gtk/capture_dlg.c135
-rw-r--r--gtk/main.c170
-rw-r--r--pcap-util.c127
-rw-r--r--pcap-util.h27
-rw-r--r--tethereal.c190
12 files changed, 622 insertions, 121 deletions
diff --git a/AUTHORS b/AUTHORS
index a102dadcc1..f16489731a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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"
])
diff --git a/capture.c b/capture.c
index 2f411e0e22..66450c96ed 100644
--- a/capture.c
+++ b/capture.c
@@ -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.
diff --git a/capture.h b/capture.h
index b4ce1fb26a..609220dc62 100644
--- a/capture.h
+++ b/capture.h
@@ -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
diff --git a/globals.h b/globals.h
index eba68769aa..2632006bf9 100644
--- a/globals.h
+++ b/globals.h
@@ -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. */