aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2010-07-13 23:26:07 +0000
committerGuy Harris <guy@alum.mit.edu>2010-07-13 23:26:07 +0000
commit4d6cb744df5d98d4da719fcaa0e43dbb3f765b82 (patch)
tree8274a0d9bd4cc30bdb4a1ed31097f6578583be67
parent3a5ba15b4d2ef710efc55bbab9331225f5e69a2e (diff)
Add a "-d" flag to dumpcap, to print out the generated code for the
capture filter in human-readable form. (Well, readable by humans who know BPF machine language, at least. :-)) svn path=/trunk/; revision=33509
-rw-r--r--acinclude.m42
-rw-r--r--doc/dumpcap.pod6
-rw-r--r--dumpcap.c400
3 files changed, 261 insertions, 147 deletions
diff --git a/acinclude.m4 b/acinclude.m4
index ca9703f603..05829bf382 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -614,7 +614,7 @@ install a newer version of the header file.])
AC_CHECK_FUNCS(pcap_datalink_val_to_description)
AC_CHECK_FUNCS(pcap_list_datalinks pcap_set_datalink pcap_lib_version)
AC_CHECK_FUNCS(pcap_get_selectable_fd pcap_free_datalinks)
- AC_CHECK_FUNCS(pcap_create)
+ AC_CHECK_FUNCS(pcap_create bpf_image)
fi
LIBS="$ac_save_LIBS"
])
diff --git a/doc/dumpcap.pod b/doc/dumpcap.pod
index 220d099728..107aebc98c 100644
--- a/doc/dumpcap.pod
+++ b/doc/dumpcap.pod
@@ -10,6 +10,7 @@ S<[ B<-a> E<lt>capture autostop conditionE<gt> ] ...>
S<[ B<-b> E<lt>capture ring buffer optionE<gt>] ...>
S<[ B<-B> E<lt>capture buffer sizeE<gt> ] >
S<[ B<-c> E<lt>capture packet countE<gt> ]>
+S<[ B<-d> ]>
S<[ B<-D> ]>
S<[ B<-f> E<lt>capture filterE<gt> ]>
S<[ B<-h> ]>
@@ -126,6 +127,11 @@ libpcap.
Set the maximum number of packets to read when capturing live
data.
+=item -d
+
+Dump the code generated for the capture filter in a human-readable form,
+and exit.
+
=item -D
Print a list of the interfaces on which B<Dumpcap> can capture, and
diff --git a/dumpcap.c b/dumpcap.c
index f01eca6960..345592386a 100644
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -319,6 +319,8 @@ static void report_packet_drops(guint32 drops);
static void report_capture_error(const char *error_msg, const char *secondary_error_msg);
static void report_cfilter_error(const char *cfilter, const char *errmsg);
+#define MSG_MAX_LENGTH 4096
+
static void
print_usage(gboolean print_ver) {
@@ -351,8 +353,11 @@ print_usage(gboolean print_ver) {
fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
fprintf(output, " -D print list of interfaces and exit\n");
fprintf(output, " -L print list of link-layer types of iface and exit\n");
+#ifdef HAVE_BPF_IMAGE
+ fprintf(output, " -d print generated BPF code for capture filter\n");
+#endif
fprintf(output, " -S print statistics for each interface once every second\n");
- fprintf(output, " -M for -D, -L, and -S produce machine-readable output\n");
+ fprintf(output, " -M for -D, -L, and -S, produce machine-readable output\n");
fprintf(output, "\n");
#ifdef HAVE_PCAP_REMOTE
fprintf(output, "\nRPCAP options:\n");
@@ -471,6 +476,215 @@ cmdarg_err_cont(const char *fmt, ...)
}
}
+static pcap_t *
+open_capture_device(capture_options *capture_opts, char *open_err_str,
+ size_t open_err_str_size)
+{
+ pcap_t *pcap_h;
+#ifdef HAVE_PCAP_CREATE
+ int err;
+#endif
+#ifdef HAVE_PCAP_REMOTE
+ struct pcap_rmtauth auth;
+#endif
+
+ /* Open the network interface to capture from it.
+ Some versions of libpcap may put warnings into the error buffer
+ if they succeed; to tell if that's happened, we have to clear
+ the error buffer, and check if it's still a null string. */
+ open_err_str[0] = '\0';
+#ifdef HAVE_PCAP_OPEN
+ /*
+ * If we're opening a remote device, use pcap_open(); that's currently
+ * the only open routine that supports remote devices.
+ */
+ if (strncmp (capture_opts->iface, "rpcap://", 8) == 0) {
+ auth.type = capture_opts->auth_type == CAPTURE_AUTH_PWD ?
+ RPCAP_RMTAUTH_PWD : RPCAP_RMTAUTH_NULL;
+ auth.username = capture_opts->auth_username;
+ auth.password = capture_opts->auth_password;
+
+ pcap_h = pcap_open(capture_opts->iface,
+ capture_opts->has_snaplen ? capture_opts->snaplen :
+ WTAP_MAX_PACKET_SIZE,
+ /* flags */
+ (capture_opts->promisc_mode ? PCAP_OPENFLAG_PROMISCUOUS : 0) |
+ (capture_opts->datatx_udp ? PCAP_OPENFLAG_DATATX_UDP : 0) |
+ (capture_opts->nocap_rpcap ? PCAP_OPENFLAG_NOCAPTURE_RPCAP : 0),
+ CAP_READ_TIMEOUT, &auth, open_err_str);
+ } else
+#endif /* HAVE_PCAP_OPEN */
+ {
+ /*
+ * If we're not opening a remote device, use pcap_create() and
+ * pcap_activate() if we have them, so that we can set the buffer
+ * size, otherwise use pcap_open_live().
+ */
+#ifdef HAVE_PCAP_CREATE
+ pcap_h = pcap_create(capture_opts->iface, open_err_str);
+ if (pcap_h != NULL) {
+ pcap_set_snaplen(pcap_h, capture_opts->has_snaplen ? capture_opts->snaplen : WTAP_MAX_PACKET_SIZE);
+ pcap_set_promisc(pcap_h, capture_opts->promisc_mode);
+ pcap_set_timeout(pcap_h, CAP_READ_TIMEOUT);
+
+ if (capture_opts->buffer_size > 1) {
+ pcap_set_buffer_size(pcap_h, capture_opts->buffer_size * 1024 * 1024);
+ }
+ if (capture_opts->monitor_mode)
+ pcap_set_rfmon(pcap_h, 1);
+ err = pcap_activate(pcap_h);
+ if (err < 0) {
+ /* Failed to activate, set to NULL */
+ if (err == PCAP_ERROR)
+ g_strlcpy(open_err_str, pcap_geterr(pcap_h), open_err_str_size);
+ else
+ g_strlcpy(open_err_str, pcap_statustostr(err), open_err_str_size);
+ pcap_close(pcap_h);
+ pcap_h = NULL;
+ }
+ }
+#else
+ pcap_h = pcap_open_live(capture_opts->iface,
+ capture_opts->has_snaplen ? capture_opts->snaplen :
+ WTAP_MAX_PACKET_SIZE,
+ capture_opts->promisc_mode, CAP_READ_TIMEOUT,
+ open_err_str);
+#endif
+ }
+
+ /* If not using libcap: we now can now set euid/egid to ruid/rgid */
+ /* to remove any suid privileges. */
+ /* If using libcap: we can now remove NET_RAW and NET_ADMIN capabilities */
+ /* (euid/egid have already previously been set to ruid/rgid. */
+ /* (See comment in main() for details) */
+#ifndef HAVE_LIBCAP
+ relinquish_special_privs_perm();
+#else
+ relinquish_all_capabilities();
+#endif
+
+ return pcap_h;
+}
+
+static void
+get_capture_device_open_failure_messages(const char *open_err_str,
+ char *errmsg, size_t errmsg_len,
+ char *secondary_errmsg,
+ size_t secondary_errmsg_len)
+{
+ const char *libpcap_warn;
+ static const char ppamsg[] = "can't find PPA for ";
+
+ /* If we got a "can't find PPA for X" message, warn the user (who
+ is running dumcap on HP-UX) that they don't have a version of
+ libpcap that properly handles HP-UX (libpcap 0.6.x and later
+ versions, which properly handle HP-UX, say "can't find /dev/dlpi
+ PPA for X" rather than "can't find PPA for X"). */
+ if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
+ libpcap_warn =
+ "\n\n"
+ "You are running (T)Wireshark with a version of the libpcap library\n"
+ "that doesn't handle HP-UX network devices well; this means that\n"
+ "(T)Wireshark may not be able to capture packets.\n"
+ "\n"
+ "To fix this, you should install libpcap 0.6.2, or a later version\n"
+ "of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n"
+ "packaged binary form from the Software Porting And Archive Centre\n"
+ "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
+ "at the URL lists a number of mirror sites.";
+ else
+ libpcap_warn = "";
+ g_snprintf(errmsg, (gulong) errmsg_len,
+ "The capture session could not be initiated (%s).", open_err_str);
+#ifndef _WIN32
+ g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len,
+"Please check to make sure you have sufficient permissions, and that you have "
+"the proper interface or pipe specified.%s", libpcap_warn);
+#else
+ g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len,
+"\n"
+"Please check that \"%s\" is the proper interface.\n"
+"\n"
+"\n"
+"Help can be found at:\n"
+"\n"
+" http://wiki.wireshark.org/WinPcap\n"
+" http://wiki.wireshark.org/CaptureSetup\n",
+ capture_opts->iface);
+#endif /* _WIN32 */
+}
+
+static gboolean
+compile_capture_filter(const char *iface, pcap_t *pcap_h,
+ struct bpf_program *fcode, const char *cfilter)
+{
+ bpf_u_int32 netnum, netmask;
+ gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
+
+ if (pcap_lookupnet(iface, &netnum, &netmask, lookup_net_err_str) < 0) {
+ /*
+ * Well, we can't get the netmask for this interface; it's used
+ * only for filters that check for broadcast IP addresses, so
+ * we just punt and use 0. It might be nice to warn the user,
+ * but that's a pain in a GUI application, as it'd involve popping
+ * up a message box, and it's not clear how often this would make
+ * a difference (only filters that check for IP broadcast addresses
+ * use the netmask).
+ */
+ /*cmdarg_err(
+ "Warning: Couldn't obtain netmask info (%s).", lookup_net_err_str);*/
+ netmask = 0;
+ }
+ if (pcap_compile(pcap_h, fcode, cfilter, 1, netmask) < 0)
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+show_filter_code(capture_options *capture_opts)
+{
+ pcap_t *pcap_h;
+ gchar open_err_str[PCAP_ERRBUF_SIZE];
+ char errmsg[MSG_MAX_LENGTH+1];
+ char secondary_errmsg[MSG_MAX_LENGTH+1];
+ struct bpf_program fcode;
+ struct bpf_insn *insn;
+ u_int i;
+
+ pcap_h = open_capture_device(capture_opts, open_err_str,
+ sizeof open_err_str);
+ if (pcap_h == NULL) {
+ /* Open failed; get messages */
+ get_capture_device_open_failure_messages(open_err_str,
+ errmsg, sizeof errmsg,
+ secondary_errmsg,
+ sizeof secondary_errmsg);
+ /* And report them */
+ report_capture_error(errmsg, secondary_errmsg);
+ return FALSE;
+ }
+
+ /* OK, try to compile the capture filter. */
+ if (!compile_capture_filter(capture_opts->iface, pcap_h, &fcode,
+ capture_opts->cfilter)) {
+ report_cfilter_error(capture_opts->cfilter, errmsg);
+ return FALSE;
+ }
+ pcap_close(pcap_h);
+
+ if (capture_child) {
+ /* Let our parent know we succeeded. */
+ pipe_write_block(2, SP_SUCCESS, NULL);
+ }
+
+ /* Now print the filter code. */
+ insn = fcode.bf_insns;
+
+ for (i = 0; i < fcode.bf_len; insn++, i++)
+ printf("%s\n", bpf_image(insn, i));
+ return TRUE;
+}
+
/*
* capture_interface_list() is expected to do the right thing to get
* a list of interfaces.
@@ -1873,21 +2087,13 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
{
gchar open_err_str[PCAP_ERRBUF_SIZE];
gchar *sync_msg_str;
- static const char ppamsg[] = "can't find PPA for ";
const char *set_linktype_err_str;
- const char *libpcap_warn;
-#if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
- int err;
-#endif
#ifdef _WIN32
+ int err;
gchar *sync_secondary_msg_str;
WORD wVersionRequested;
WSADATA wsaData;
#endif
-#ifdef HAVE_PCAP_REMOTE
- struct pcap_rmtauth auth;
-#endif
-
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_input : %s", capture_opts->iface);
@@ -1940,80 +2146,8 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
}
#endif
- /* Open the network interface to capture from it.
- Some versions of libpcap may put warnings into the error buffer
- if they succeed; to tell if that's happened, we have to clear
- the error buffer, and check if it's still a null string. */
- open_err_str[0] = '\0';
-#ifdef HAVE_PCAP_OPEN
- /*
- * If we're opening a remote device, use pcap_open(); that's currently
- * the only open routine that supports remote devices.
- */
- if (strncmp (capture_opts->iface, "rpcap://", 8) == 0) {
- auth.type = capture_opts->auth_type == CAPTURE_AUTH_PWD ?
- RPCAP_RMTAUTH_PWD : RPCAP_RMTAUTH_NULL;
- auth.username = capture_opts->auth_username;
- auth.password = capture_opts->auth_password;
-
- ld->pcap_h = pcap_open(capture_opts->iface,
- capture_opts->has_snaplen ? capture_opts->snaplen :
- WTAP_MAX_PACKET_SIZE,
- /* flags */
- (capture_opts->promisc_mode ? PCAP_OPENFLAG_PROMISCUOUS : 0) |
- (capture_opts->datatx_udp ? PCAP_OPENFLAG_DATATX_UDP : 0) |
- (capture_opts->nocap_rpcap ? PCAP_OPENFLAG_NOCAPTURE_RPCAP : 0),
- CAP_READ_TIMEOUT, &auth, open_err_str);
- } else
-#endif /* HAVE_PCAP_OPEN */
- {
- /*
- * If we're not opening a remote device, use pcap_create() and
- * pcap_activate() if we have them, so that we can set the buffer
- * size, otherwise use pcap_open_live().
- */
-#ifdef HAVE_PCAP_CREATE
- ld->pcap_h = pcap_create(capture_opts->iface, open_err_str);
- if (ld->pcap_h != NULL) {
- pcap_set_snaplen(ld->pcap_h, capture_opts->has_snaplen ? capture_opts->snaplen : WTAP_MAX_PACKET_SIZE);
- pcap_set_promisc(ld->pcap_h, capture_opts->promisc_mode);
- pcap_set_timeout(ld->pcap_h, CAP_READ_TIMEOUT);
-
- if (capture_opts->buffer_size > 1) {
- pcap_set_buffer_size(ld->pcap_h, capture_opts->buffer_size * 1024 * 1024);
- }
- if (capture_opts->monitor_mode)
- pcap_set_rfmon(ld->pcap_h, 1);
- err = pcap_activate(ld->pcap_h);
- if (err < 0) {
- /* Failed to activate, set to NULL */
- if (err == PCAP_ERROR)
- g_strlcpy(open_err_str, pcap_geterr(ld->pcap_h), sizeof open_err_str);
- else
- g_strlcpy(open_err_str, pcap_statustostr(err), sizeof open_err_str);
- pcap_close(ld->pcap_h);
- ld->pcap_h = NULL;
- }
- }
-#else
- ld->pcap_h = pcap_open_live(capture_opts->iface,
- capture_opts->has_snaplen ? capture_opts->snaplen :
- WTAP_MAX_PACKET_SIZE,
- capture_opts->promisc_mode, CAP_READ_TIMEOUT,
- open_err_str);
-#endif
- }
-
- /* If not using libcap: we now can now set euid/egid to ruid/rgid */
- /* to remove any suid privileges. */
- /* If using libcap: we can now remove NET_RAW and NET_ADMIN capabilities */
- /* (euid/egid have already previously been set to ruid/rgid. */
- /* (See comment in main() for details) */
-#ifndef HAVE_LIBCAP
- relinquish_special_privs_perm();
-#else
- relinquish_all_capabilities();
-#endif
+ ld->pcap_h = open_capture_device(capture_opts, open_err_str,
+ sizeof open_err_str);
if (ld->pcap_h != NULL) {
/* we've opened "iface" as a network device */
@@ -2096,44 +2230,10 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
if (ld->cap_pipe_err == PIPNEXIST) {
/* Pipe doesn't exist, so output message for interface */
-
- /* If we got a "can't find PPA for X" message, warn the user (who
- is running (T)Wireshark on HP-UX) that they don't have a version
- of libpcap that properly handles HP-UX (libpcap 0.6.x and later
- versions, which properly handle HP-UX, say "can't find /dev/dlpi
- PPA for X" rather than "can't find PPA for X"). */
- if (strncmp(open_err_str, ppamsg, sizeof ppamsg - 1) == 0)
- libpcap_warn =
- "\n\n"
- "You are running (T)Wireshark with a version of the libpcap library\n"
- "that doesn't handle HP-UX network devices well; this means that\n"
- "(T)Wireshark may not be able to capture packets.\n"
- "\n"
- "To fix this, you should install libpcap 0.6.2, or a later version\n"
- "of libpcap, rather than libpcap 0.4 or 0.5.x. It is available in\n"
- "packaged binary form from the Software Porting And Archive Centre\n"
- "for HP-UX; the Centre is at http://hpux.connect.org.uk/ - the page\n"
- "at the URL lists a number of mirror sites.";
- else
- libpcap_warn = "";
- g_snprintf(errmsg, (gulong) errmsg_len,
- "The capture session could not be initiated (%s).", open_err_str);
-#ifndef _WIN32
- g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len,
-"Please check to make sure you have sufficient permissions, and that you have "
-"the proper interface or pipe specified.%s", libpcap_warn);
-#else
- g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len,
-"\n"
-"Please check that \"%s\" is the proper interface.\n"
-"\n"
-"\n"
-"Help can be found at:\n"
-"\n"
-" http://wiki.wireshark.org/WinPcap\n"
-" http://wiki.wireshark.org/CaptureSetup\n",
- capture_opts->iface);
-#endif /* _WIN32 */
+ get_capture_device_open_failure_messages(open_err_str, errmsg,
+ errmsg_len,
+ secondary_errmsg,
+ secondary_errmsg_len);
}
/*
* Else pipe (or file) does exist and cap_pipe_open_live() has
@@ -2168,7 +2268,6 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
return TRUE;
}
-
/* close the capture input file (pcap or capture pipe) */
static void capture_loop_close_input(loop_data *ld) {
@@ -2207,32 +2306,17 @@ static void capture_loop_close_input(loop_data *ld) {
/* init the capture filter */
static initfilter_status_t
-capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, gchar * iface, gchar * cfilter) {
- bpf_u_int32 netnum, netmask;
- gchar lookup_net_err_str[PCAP_ERRBUF_SIZE];
+capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe,
+ gchar * iface, gchar * cfilter)
+{
struct bpf_program fcode;
-
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_filter: %s", cfilter);
/* capture filters only work on real interfaces */
if (cfilter && !from_cap_pipe) {
/* A capture filter was specified; set it up. */
- if (pcap_lookupnet(iface, &netnum, &netmask, lookup_net_err_str) < 0) {
- /*
- * Well, we can't get the netmask for this interface; it's used
- * only for filters that check for broadcast IP addresses, so
- * we just punt and use 0. It might be nice to warn the user,
- * but that's a pain in a GUI application, as it'd involve popping
- * up a message box, and it's not clear how often this would make
- * a difference (only filters that check for IP broadcast addresses
- * use the netmask).
- */
- /*cmdarg_err(
- "Warning: Couldn't obtain netmask info (%s).", lookup_net_err_str);*/
- netmask = 0;
- }
- if (pcap_compile(pcap_h, &fcode, cfilter, 1, netmask) < 0) {
+ if (!compile_capture_filter(iface, pcap_h, &fcode, cfilter)) {
/* Treat this specially - our caller might try to compile this
as a display filter and, if that succeeds, warn the user that
the display and capture filter syntaxes are different. */
@@ -2699,7 +2783,6 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
gboolean write_ok;
gboolean close_ok;
gboolean cfilter_error = FALSE;
-#define MSG_MAX_LENGTH 4096
char errmsg[MSG_MAX_LENGTH+1];
char secondary_errmsg[MSG_MAX_LENGTH+1];
@@ -3177,6 +3260,9 @@ main(int argc, char *argv[])
GLogLevelFlags log_flags;
gboolean list_interfaces = FALSE;
gboolean list_link_layer_types = FALSE;
+#ifdef HAVE_BPF_IMAGE
+ gboolean print_bpf_code = FALSE;
+#endif
gboolean machine_readable = FALSE;
gboolean print_statistics = FALSE;
int status, run_once_args = 0;
@@ -3213,7 +3299,13 @@ main(int argc, char *argv[])
#define OPTSTRING_I ""
#endif
-#define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:Df:hi:" OPTSTRING_I "L" OPTSTRING_m "Mnpq" OPTSTRING_r "Ss:" OPTSTRING_u "vw:y:Z:"
+#ifdef HAVE_BPF_IMAGE
+#define OPTSTRING_d "d"
+#else
+#define OPTSTRING_d ""
+#endif
+
+#define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:" OPTSTRING_d "Df:hi:" OPTSTRING_I "L" OPTSTRING_m "Mnpq" OPTSTRING_r "Ss:" OPTSTRING_u "vw:y:Z:"
#ifdef DEBUG_CHILD_DUMPCAP
if ((debug_log = ws_fopen("dumpcap_debug_log.tmp","w")) == NULL) {
@@ -3550,6 +3642,12 @@ main(int argc, char *argv[])
list_link_layer_types = TRUE;
run_once_args++;
break;
+#ifdef HAVE_BPF_IMAGE
+ case 'd': /* Print BPF code for capture filter and exit */
+ print_bpf_code = TRUE;
+ run_once_args++;
+ break;
+#endif
case 'S': /* Print interface statistics once a second */
print_statistics = TRUE;
run_once_args++;
@@ -3669,7 +3767,7 @@ main(int argc, char *argv[])
}
/*
- * "-L", and capturing, act on a particular interface, so we have to
+ * "-L", "-d", and capturing act on a particular interface, so we have to
* have an interface; if none was specified, pick a default.
*/
if (capture_opts_trim_iface(&global_capture_opts, NULL) == FALSE) {
@@ -3708,8 +3806,18 @@ main(int argc, char *argv[])
exit_main(0);
}
- /* We're supposed to do a capture. Process the remaining arguments. */
+ /* We're supposed to do a capture, or print the BPF code for a filter.
+ Process the snapshot length, as that affects the generated BPF code. */
capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
+
+#ifdef HAVE_BPF_IMAGE
+ if (print_bpf_code) {
+ show_filter_code(&global_capture_opts);
+ exit_main(0);
+ }
+#endif
+
+ /* We're supposed to do a capture. Process the ring buffer arguments. */
capture_opts_trim_ring_num_files(&global_capture_opts);
/* Now start the capture. */