Ethereal-dev: [Ethereal-dev] [PATCH] pcap_set_datalink()/BIOCSDLT support
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Brian Fundakowski Feldman <bfeldman@xxxxxxxxxxxxxxx>
Date: Fri, 31 Oct 2003 13:14:39 -0500
Since pcap(3) has recently grown the ability to select from multiple available data link types on some platforms, it's very useful for Ethereal to support switching to a non-default capture format. I've tested this on FreeBSD, which means that the HAVE_PCAP_DATALINK_VAL_TO_NAME part remains untested but present for a system which might have it. After you select an interface, you can check the "Change _data link type" box and then pull down to select a data link type or enter your own (in my case, they are all numbers corresponding to the DLT_ values in the system headers). The drop-down box isn't available (and the check box unchecks itself) if the current value of the interface entry can't be used to look up a set of data link types. The gtk_combo_set_value_in_list() should be removed if someone sees a need to be able to enter a DLT number manually when the list of named DLT constants is available on a platform with pcap_datalink_val_to_name()... not sure if that would be remotely useful though :) Does anyone have any thoughts? -- Brian Fundakowski Feldman | http://www.fla.fujitsu.com/ Software Specialist | Fujitsu Laboratories of America
--- aclocal.m4 Wed Jul 23 18:37:22 2003
+++ ../ethereal-0.9.12/aclocal.m4 Mon Oct 27 14:14:12 2003
@@ -339,6 +339,25 @@
AC_DEFINE(HAVE_LIBPCAP, 1, [Define to use libpcap library])
], [AC_MSG_ERROR(Library libpcap not found.)],
$SOCKET_LIBS $NSL_LIBS)
+
+ #
+ # Check to see if we find "pcap_set_datalink" in "-lpcap".
+ #
+ AC_CHECK_LIB(pcap, pcap_set_datalink,
+ [
+ AC_DEFINE(HAVE_PCAP_SET_DATALINK, 1, [Define to use pcap multiple data link types])
+ ], [AC_MSG_RESULT(Multiple data link types not required.)],
+ $SOCKET_LIBS $NSL_LIBS $PCAP_LIBS)
+
+ #
+ # Check to see if we find "pcap_datalink_val_to_name" in "-lpcap".
+ #
+ AC_CHECK_LIB(pcap, pcap_datalink_val_to_name,
+ [
+ AC_DEFINE(HAVE_PCAP_DATALINK_VAL_TO_NAME, 1, [Define to use pcap data link name/type translation])
+ ], [AC_MSG_RESULT(Data link name/type conversion not required.)],
+ $SOCKET_LIBS $NSL_LIBS $PCAP_LIBS)
+
AC_SUBST(PCAP_LIBS)
])
--- capture.c.orig Wed Jul 23 18:33:25 2003
+++ capture.c Wed Oct 29 12:41:09 2003
@@ -393,6 +393,11 @@
argv = add_arg(argv, &argc, ssnap);
}
+ if (capture_opts.linktype) {
+ argv = add_arg(argv, &argc, "-y");
+ argv = add_arg(argv, &argc, capture_opts.linktype);
+ }
+
if (capture_opts.has_autostop_filesize) {
argv = add_arg(argv, &argc, "-a");
sprintf(sautostop_filesize,"filesize:%d",capture_opts.autostop_filesize);
@@ -1578,6 +1583,15 @@
error message from pcap_open_live() */
open_err_str[0] = '\0';
#endif
+ }
+
+ /* setting the data link type only works on real interfaces */
+ if (capture_opts.linktype) {
+ if (set_pcap_linktype(pch, cfile.iface, capture_opts.linktype) != 0) {
+ snprintf(errmsg, sizeof errmsg, "Unable to set %s pcap link type (%s).",
+ capture_opts.linktype, strerror(errno));
+ goto error;
+ }
}
/* capture filters only work on real interfaces */
--- capture.h.orig Tue Oct 28 17:20:03 2003
+++ capture.h Tue Oct 28 17:19:58 2003
@@ -51,6 +51,7 @@
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 */
+ gchar *linktype; /* String of data link type to use */
} capture_options;
extern capture_options capture_opts;
--- gtk/capture_dlg.c.orig Sat May 17 12:33:02 2003
+++ gtk/capture_dlg.c Wed Oct 29 12:48:55 2003
@@ -55,6 +55,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_CB_KEY "cap_lt_cb"
+#define E_CAP_LT_SEL_KEY "cap_lt_sel"
#define E_CAP_SNAP_SB_KEY "cap_snap_sb"
#define E_CAP_PROMISC_KEY "cap_promisc"
#define E_CAP_FILT_KEY "cap_filter_te"
@@ -104,6 +106,9 @@
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_)
{
@@ -124,6 +129,7 @@
GtkWidget *main_vb,
*capture_fr, *capture_vb,
*if_hb, *if_cb, *if_lb,
+ *linktype_hb, *linktype_cb, *linktype_sel,
*snap_hb, *snap_cb, *snap_sb, *snap_lb,
*promisc_cb,
*filter_hb, *filter_bt, *filter_te,
@@ -238,6 +244,29 @@
free_interface_list(if_list);
+ /* Linktype row */
+ linktype_hb = gtk_hbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(capture_vb), linktype_hb);
+ gtk_widget_show(linktype_hb);
+
+#if GTK_MAJOR_VERSION < 2
+ linktype_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "Change _data link type", accel_group);
+#else
+ linktype_cb = gtk_check_button_new_with_mnemonic("Change _data link type");
+#endif
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(linktype_cb),
+ capture_opts.linktype != NULL);
+ SIGNAL_CONNECT(linktype_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
+ SIGNAL_CONNECT(GTK_ENTRY(GTK_COMBO(if_cb)->entry), "changed", capture_prep_interface_changed_cb, cap_open_w);
+ gtk_box_pack_start(GTK_BOX(linktype_hb), linktype_cb, FALSE, FALSE, 0);
+ gtk_widget_show(linktype_cb);
+
+ linktype_sel = gtk_combo_new();
+ gtk_combo_set_value_in_list(GTK_COMBO(linktype_sel), TRUE, TRUE);
+ gtk_box_pack_start (GTK_BOX(linktype_hb), linktype_sel, FALSE, FALSE, 0);
+ gtk_widget_show(linktype_sel);
+
/* Capture length row */
snap_hb = gtk_hbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(capture_vb), snap_hb);
@@ -583,6 +612,8 @@
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_CB_KEY, linktype_cb);
+ OBJECT_SET_DATA(cap_open_w, E_CAP_LT_SEL_KEY, linktype_sel);
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);
@@ -752,6 +783,7 @@
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,
+ *linktype_cb, *linktype_sel,
*sync_cb, *auto_scroll_cb,
*count_cb, *count_sb,
*filesize_cb, *filesize_sb,
@@ -768,6 +800,8 @@
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_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_CB_KEY);
+ linktype_sel = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_SEL_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);
@@ -807,6 +841,15 @@
cfile.iface = g_strdup(if_name);
g_free(if_text);
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linktype_cb))) {
+ g_free(capture_opts.linktype);
+ capture_opts.linktype = g_strdup(gtk_entry_get_text(
+ GTK_ENTRY(GTK_COMBO(linktype_sel)->entry)));
+ } else {
+ g_free(capture_opts.linktype);
+ capture_opts.linktype = NULL;
+ }
+
capture_opts.has_snaplen =
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb));
if (capture_opts.has_snaplen) {
@@ -943,6 +986,22 @@
cap_open_w = NULL;
}
+static void
+capture_prep_interface_changed_cb(GtkWidget *entry _U_, gpointer parent_w)
+{
+ GtkWidget *linktype_cb;
+
+ linktype_cb = OBJECT_GET_DATA(parent_w, E_CAP_LT_CB_KEY);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linktype_cb), FALSE);
+}
+
+static void
+do_g_free(gpointer tofree, gpointer dontfree _U_)
+{
+
+ g_free(tofree);
+}
+
/*
* Adjust the sensitivity of various widgets as per the current setting
* of other widgets.
@@ -950,14 +1009,17 @@
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,
*filesize_cb, *filesize_sb, *filesize_lb,
*duration_cb, *duration_sb,
- *ring_duration_cb, *ring_duration_sb;
+ *ring_duration_cb, *ring_duration_sb,
+ *linktype_cb, *linktype_sel;
+ 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);
@@ -974,6 +1036,39 @@
filesize_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_LB_KEY);
duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_CB_KEY);
duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_SB_KEY);
+ linktype_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_CB_KEY);
+ linktype_sel = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_SEL_KEY);
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linktype_cb))) {
+ gchar *curif;
+
+ curif = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry));
+ /* Windows uses /^.* ifname$/ */
+ if (strrchr(curif, ' ') != NULL)
+ curif = strrchr(curif, ' ') + 1;
+ if (curif != NULL) {
+ GList *lt_list;
+
+ lt_list = get_pcap_linktype_list(curif);
+ if (lt_list == NULL) {
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(linktype_cb), FALSE);
+ } else {
+ gtk_combo_set_popdown_strings(GTK_COMBO(linktype_sel), lt_list);
+ gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(linktype_sel)->entry),
+ g_list_nth_data(lt_list, 0));
+ g_list_foreach(lt_list, do_g_free, NULL);
+ g_list_free(lt_list);
+ }
+ } else {
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(linktype_cb), FALSE);
+ }
+ }
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linktype_cb))) {
+ gtk_widget_set_sensitive(GTK_WIDGET(linktype_sel), TRUE);
+ } else {
+ gtk_widget_set_sensitive(GTK_WIDGET(linktype_sel), FALSE);
+ gtk_list_clear_items(GTK_LIST(GTK_COMBO(linktype_sel)->list), 0, -1);
+ }
/* The snapshot length spinbox is sensitive iff the "Limit each packet
to" checkbox is on. */
--- gtk/main.c.orig Wed Oct 29 12:43:26 2003
+++ gtk/main.c Wed Oct 29 12:47:54 2003
@@ -1187,7 +1187,7 @@
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 <linktype> ] [ <infile> ]\n");
#else
fprintf(stderr, "\n%s [ -vh ] [ -n ] [ -B <byte view height> ] [ -m <medium font> ]\n",
PACKAGE);
@@ -1473,7 +1473,7 @@
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:klm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
#ifdef HAVE_LIBPCAP
#ifdef WIN32
@@ -1616,6 +1616,7 @@
capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
capture_opts.has_ring_duration = FALSE;
capture_opts.ringbuffer_duration = 1;
+ capture_opts.linktype = NULL;
/* If this is a capture child process, it should pay no attention
to the "prefs.capture_prom_mode" setting in the preferences file;
@@ -1866,6 +1867,14 @@
arg_error = TRUE;
#endif
break;
+ case 'y': /* Set the pcap data link type */
+#ifdef HAVE_LIBPCAP
+ capture_opts.linktype = g_strdup(optarg);
+#else
+ capture_option_specified = TRUE;
+ arg_error = TRUE;
+#endif
+ 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.
--- pcap-util.c Wed Jul 9 21:20:13 2003
+++ ../ethereal-0.9.12/pcap-util.c Tue Oct 28 16:16:20 2003
@@ -31,6 +31,7 @@
#include <glib.h>
#include <stdlib.h>
+#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
@@ -194,6 +195,87 @@
}
/*
+ * Get the data-link types available for a libpcap device.
+ */
+GList *
+get_pcap_linktype_list(char *devname)
+{
+ GList *linktype_list = NULL;
+ pcap_t *pch;
+ char err_buf[PCAP_ERRBUF_SIZE];
+#ifdef HAVE_PCAP_SET_DATALINK
+ int *linktypes;
+ int i, nlt, deflt;
+#endif
+
+ pch = pcap_open_live(devname, MIN_PACKET_SIZE, 0, 0, err_buf);
+ if (pch == NULL)
+ return NULL;
+ deflt = get_pcap_linktype(pch, devname);
+ /* TODO: Map link numbers to names (pcap_datalink_val_to_name). */
+#ifdef HAVE_PCAP_SET_DATALINK
+ nlt = pcap_list_datalinks(pch, &linktypes);
+ if (nlt > 0) {
+ for (i = 0; i < nlt; i++) {
+ char *typename;
+#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
+ typename = pcap_datalink_val_to_name(linktypes[i]);
+ if (typename != NULL)
+ typename = g_strdup(typename));
+ else
+#endif
+ typename = g_strdup_printf("%d", linktypes[i]);
+ if (linktypes[i] == deflt)
+ linktype_list = g_list_prepend(linktype_list,
+ typename);
+ else
+ linktype_list = g_list_append(linktype_list,
+ typename);
+ }
+ free(linktypes);
+ } else
+#endif
+ linktype_list = g_list_append(linktype_list,
+ g_strdup_printf("%d (not modifiable)",
+ get_pcap_linktype(pch, devname)));
+
+ pcap_close(pch);
+ return linktype_list;
+}
+
+/* Set the data link type on a pcap, including name/val translation. */
+int
+set_pcap_linktype(pcap_t *pch, char *devname, char *linktype)
+{
+ int val;
+
+#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
+ val = pcap_datalink_name_to_val(linktype);
+ if (val == -1) {
+#endif
+ long lval;
+ char *endptr;
+
+ lval = strtol(linktype, &endptr, 10);
+ if (*endptr != '\0' || lval < INT_MIN || lval > INT_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+ val = (int)lval;
+#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
+ }
+#endif
+#ifdef HAVE_PCAP_SET_DATALINK
+ return (pcap_set_datalink(pch, val));
+#else
+ if (get_pcap_linktype(pch, devname) == val)
+ return 0;
+ errno = EINVAL;
+ return -1;
+#endif
+}
+
+/*
* If the ability to capture packets is added to Wiretap, these
* routines should be moved to the Wiretap source (with
* "get_interface_list()" and "free_interface_list()" renamed to
--- pcap-util.h Wed Aug 28 20:40:05 2002
+++ ../ethereal-0.9.12/pcap-util.h Mon Oct 27 16:39:42 2003
@@ -32,6 +32,8 @@
#endif /* __cplusplus */
int get_pcap_linktype(pcap_t *pch, char *devname);
+GList *get_pcap_linktype_list(char *devname);
+int set_pcap_linktype(pcap_t *pch, char *devname, gchar *linktype);
GList *get_interface_list(int *err, char *err_str);
--- tethereal.c.orig Wed Oct 29 12:36:36 2003
+++ tethereal.c Wed Oct 29 13:03:07 2003
@@ -192,6 +192,7 @@
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 */
+ gchar *linktype; /* String of data link type to use */
} capture_options;
static capture_options capture_opts = {
@@ -210,7 +211,8 @@
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 */
+ NULL /* Default to not change link type */
};
#ifdef SIGINFO
@@ -236,7 +238,7 @@
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);
@@ -841,7 +843,7 @@
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:lnN:o:pqr:R:s:St:vw:Vxy:z:")) != -1) {
switch (opt) {
case 'a': /* autostop criteria */
#ifdef HAVE_LIBPCAP
@@ -1038,6 +1040,14 @@
break;
case 'x': /* Print packet data in hex (and ASCII) */
print_hex = TRUE;
+ break;
+ case 'y': /* Set the pcap data link type */
+#ifdef HAVE_LIBPCAP
+ capture_opts.linktype = g_strdup(optarg);
+#else
+ capture_option_specified = TRUE;
+ arg_error = TRUE;
+#endif
break;
case 'z':
for(tli=tap_list;tli;tli=tli->next){
- Follow-Ups:
- Re: [Ethereal-dev] [PATCH] pcap_set_datalink()/BIOCSDLT support
- From: Guy Harris
- Re: [Ethereal-dev] [PATCH] pcap_set_datalink()/BIOCSDLT support
- Prev by Date: Re: [Ethereal-dev] Lack of close button on Conversation windows
- Next by Date: Re: [Ethereal-dev] [PATCH] ACN pluging update
- Previous by thread: Re: [Ethereal-dev] H225 vendorIdentifier [PATCH]
- Next by thread: Re: [Ethereal-dev] [PATCH] pcap_set_datalink()/BIOCSDLT support
- Index(es):





