Put the low-level sync routines into a common file so they can be shared

by dumpcap and Ethereal (so that, on UN*X, the child process can report
a detailed "can't exec dumpcap" error).

Rename most of the "sync_pipe_XXX_to_parent()" routines, as they're also
in Tethereal, which doesn't have a sync pipe.

svn path=/trunk/; revision=17789
This commit is contained in:
Guy Harris 2006-04-03 01:56:53 +00:00
parent d5585760e7
commit d260003026
9 changed files with 278 additions and 172 deletions

View File

@ -151,6 +151,7 @@ ethereal_SOURCES = \
g711.c \
merge.c \
proto_hier_stats.c \
sync_pipe_write.c \
summary.c \
tempfile.c
@ -176,6 +177,7 @@ ethereal_INCLUDES = \
stat_menu.h \
statusbar.h \
summary.h \
sync_pipe.h \
tap_dfilter_dlg.h \
ui_util.h
@ -225,6 +227,7 @@ dumpcap_SOURCES = \
dumpcap.c \
pcapio.c \
ringbuffer.c \
sync_pipe_write.c \
tempfile.c \
version_info.c

View File

@ -528,7 +528,7 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
"\n"
"Nonetheless, the capture is started.\n",
capture_opts->buffer_size);
sync_pipe_errmsg_to_parent("Couldn't set the capture buffer size!",
report_capture_error("Couldn't set the capture buffer size!",
sync_secondary_msg_str);
g_free(sync_secondary_msg_str);
}
@ -643,7 +643,7 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
returned a warning; print it, but keep capturing. */
if (open_err_str[0] != '\0') {
sync_msg_str = g_strdup_printf("%s.", open_err_str);
sync_pipe_errmsg_to_parent(sync_msg_str, "");
report_capture_error(sync_msg_str, "");
g_free(sync_msg_str);
}
@ -825,7 +825,7 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
if (sel_ret < 0 && errno != EINTR) {
g_snprintf(errmsg, errmsg_len,
"Unexpected error from select: %s", strerror(errno));
sync_pipe_errmsg_to_parent(errmsg, please_report);
report_capture_error(errmsg, please_report);
ld->go = FALSE;
}
} else {
@ -904,7 +904,7 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
if (sel_ret < 0 && errno != EINTR) {
g_snprintf(errmsg, errmsg_len,
"Unexpected error from select: %s", strerror(errno));
sync_pipe_errmsg_to_parent(errmsg, please_report);
report_capture_error(errmsg, please_report);
ld->go = FALSE;
}
}
@ -1174,7 +1174,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
update its windows to indicate that we have a live capture in
progress. */
libpcap_dump_flush(ld.pdh, NULL);
sync_pipe_filename_to_parent(capture_opts->save_file);
report_new_capture_file(capture_opts->save_file);
}
/* initialize capture stop (and alike) conditions */
@ -1240,9 +1240,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
cnd_reset(cnd_file_duration);
}
libpcap_dump_flush(ld.pdh, NULL);
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
report_packet_count(inpkts_to_sync_pipe);
inpkts_to_sync_pipe = 0;
sync_pipe_filename_to_parent(capture_opts->save_file);
report_new_capture_file(capture_opts->save_file);
} else {
/* File switch failed: stop here */
ld.go = FALSE;
@ -1279,7 +1279,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
/* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
packets to the capture file. */
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
report_packet_count(inpkts_to_sync_pipe);
inpkts_to_sync_pipe = 0;
}
@ -1309,9 +1309,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if(cnd_autostop_size)
cnd_reset(cnd_autostop_size);
libpcap_dump_flush(ld.pdh, NULL);
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
report_packet_count(inpkts_to_sync_pipe);
inpkts_to_sync_pipe = 0;
sync_pipe_filename_to_parent(capture_opts->save_file);
report_new_capture_file(capture_opts->save_file);
} else {
/* File switch failed: stop here */
ld.go = FALSE;
@ -1343,11 +1343,11 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if (ld.pcap_err) {
g_snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s",
pcap_geterr(ld.pcap_h));
sync_pipe_errmsg_to_parent(errmsg, please_report);
report_capture_error(errmsg, please_report);
}
#ifndef _WIN32
else if (ld.from_cap_pipe && ld.cap_pipe_err == PIPERR)
sync_pipe_errmsg_to_parent(errmsg, "");
report_capture_error(errmsg, "");
#endif
/* did we had an error while capturing? */
@ -1356,7 +1356,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
} else {
capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, ld.err,
FALSE);
sync_pipe_errmsg_to_parent(errmsg, please_report);
report_capture_error(errmsg, please_report);
write_ok = FALSE;
}
@ -1369,7 +1369,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
/* there might be packets not yet notified to the parent */
/* (do this after closing the file, so all packets are already flushed) */
if(inpkts_to_sync_pipe) {
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
report_packet_count(inpkts_to_sync_pipe);
inpkts_to_sync_pipe = 0;
}
@ -1378,7 +1378,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if (!close_ok && write_ok) {
capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, err_close,
TRUE);
sync_pipe_errmsg_to_parent(errmsg, "");
report_capture_error(errmsg, "");
}
/*
@ -1398,12 +1398,12 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
if (pcap_stats(ld.pcap_h, stats) >= 0) {
*stats_known = TRUE;
/* Let the parent process know. */
sync_pipe_drops_to_parent(stats->ps_drop);
report_packet_drops(stats->ps_drop);
} else {
g_snprintf(errmsg, sizeof(errmsg),
"Can't get packet-drop statistics: %s",
pcap_geterr(ld.pcap_h));
sync_pipe_errmsg_to_parent(errmsg, please_report);
report_capture_error(errmsg, please_report);
}
}
@ -1435,9 +1435,9 @@ error:
}
capture_opts->save_file = NULL;
if (cfilter_error)
sync_pipe_cfilter_error_to_parent(capture_opts->cfilter, errmsg);
report_cfilter_error(capture_opts->cfilter, errmsg);
else
sync_pipe_errmsg_to_parent(errmsg, secondary_errmsg);
report_capture_error(errmsg, secondary_errmsg);
/* close the input file (pcap or cap_pipe) */
capture_loop_close_input(&ld);

View File

@ -159,4 +159,29 @@ capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_d
extern gboolean
capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close);
/*
* Routines called by the capture loop code to report things.
*/
/** Report a new capture file having been opened. */
extern void
report_new_capture_file(const char *filename);
/** Report a number of new packets captured. */
extern void
report_packet_count(int packet_count);
/** Report the packet drops once the capture finishes. */
extern void
report_packet_drops(int drops);
/** Report an error in the capture. */
extern void
report_capture_error(const char *error_msg, const char *secondary_error_msg);
/** Report an error with a capture filter. */
extern void
report_cfilter_error(const char *cfilter, const char *errmsg);
#endif /* capture_loop.h */

View File

@ -89,6 +89,8 @@
#include "capture_sync.h"
#include "simple_dialog.h"
#include "sync_pipe.h"
#ifdef _WIN32
#include "capture-wpcap.h"
#endif
@ -405,11 +407,12 @@ sync_pipe_start(capture_options *capture_opts) {
/* call dumpcap */
if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
g_warning("Couldn't open dumpcap (Error: %u): %s", GetLastError(), args->str);
capture_opts->fork_child = -1;
} else {
capture_opts->fork_child = (int) pi.hProcess;
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Couldn't run %s in child process: error %u",
args->str, GetLastError());
return FALSE;
}
capture_opts->fork_child = (int) pi.hProcess;
g_string_free(args, TRUE);
/* associate the operating system filehandle to a C run-time file handle */
@ -440,10 +443,9 @@ sync_pipe_start(capture_options *capture_opts) {
dup(sync_pipe[PIPE_WRITE]);
eth_close(sync_pipe[PIPE_READ]);
execv(exename, argv);
/* XXX - find a way to send this message to the parent in a clean way */
/*g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
exename, strerror(errno));
sync_pipe_errmsg_to_parent(errmsg, "");*/
sync_pipe_errmsg_to_parent(errmsg, "");
/* Exit with "_exit()", so that we don't close the connection
to the X server (and cause stuff buffered up by our parent but

View File

@ -35,36 +35,6 @@
#define __CAPTURE_SYNC_H__
/*
* Maximum length of sync pipe message data. Must be < 2^24, as the
* message length is 3 bytes.
* XXX - this must be large enough to handle a Really Big Filter
* Expression, as the error message for an incorrect filter expression
* is a bit larger than the filter expression.
*/
#define SP_MAX_MSG_LEN 4096
/* Size of buffer to hold decimal representation of
signed/unsigned 64-bit int */
#define SP_DECISIZE 20
/*
* Indications sent out on the sync pipe (from child to parent).
*/
#define SP_FILE 'F' /* the name of the recently opened file */
#define SP_ERROR_MSG 'E' /* error message */
#define SP_BAD_FILTER 'B' /* error message for bad capture filter */
#define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
#define SP_DROPS 'D' /* count of packets dropped in capture */
/*
* Win32 only: Indications sent out on the signal pipe (from parent to child)
* (UNIX-like sends signals for this)
*/
#define SP_QUIT 'Q' /* "gracefully" capture quit message (SIGUSR1) */
/**
* Start a new capture session.
* Create a capture child which is doing the real capture work.
@ -87,29 +57,6 @@ sync_pipe_stop(capture_options *capture_opts);
extern void
sync_pipe_kill(capture_options *capture_opts);
/** the child has opened a new capture file, notify the parent */
extern void
sync_pipe_filename_to_parent(const char *filename);
/** the child captured some new packets, notify the parent */
extern void
sync_pipe_packet_count_to_parent(int packet_count);
/** the child stopped capturing, notify the parent */
extern void
sync_pipe_drops_to_parent(int drops);
/** the child encountered an error with a capture filter, notify the parent */
extern void
sync_pipe_cfilter_error_to_parent(const char *cfilter, const char *errmsg);
/** the child encountered an error, notify the parent */
extern void
sync_pipe_errmsg_to_parent(const char *error_msg,
const char *secondary_error_msg);
/** does the parent signalled the child to stop */
#ifdef _WIN32
extern gboolean

View File

@ -54,6 +54,8 @@
#include "capture-wpcap.h"
#endif
#include "sync_pipe.h"
#include "capture.h"
#include "capture_loop.h"
#include "capture_sync.h"
@ -506,70 +508,11 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level,
/****************************************************************************************************************/
/* sync_pipe handling */
/* write a single message header to the recipient pipe */
static int
pipe_write_header(int pipe, char indicator, int length)
{
guchar header[1+3]; /* indicator + 3-byte len */
g_assert(length <= SP_MAX_MSG_LEN);
/* write header (indicator + 3-byte len) */
header[0] = indicator;
header[1] = (length >> 16) & 0xFF;
header[2] = (length >> 8) & 0xFF;
header[3] = (length >> 0) & 0xFF;
/* write header */
return write(pipe, header, sizeof header);
}
/* write a message to the recipient pipe in the standard format
(3 digit message length (excluding length and indicator field),
1 byte message indicator and the rest is the message).
If msg is NULL, the message has only a length and indicator. */
static void
pipe_write_block(int pipe, char indicator, const char *msg)
{
int ret;
size_t len;
/*g_warning("write %d enter", pipe);*/
if(msg != NULL) {
len = strlen(msg) + 1; /* including the terminating '\0'! */
} else {
len = 0;
}
/* write header (indicator + 3-byte len) */
ret = pipe_write_header(pipe, indicator, len);
if(ret == -1) {
return;
}
/* write value (if we have one) */
if(len) {
/*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
ret = write(pipe, msg, len);
if(ret == -1) {
return;
}
} else {
/*g_warning("write %d indicator: %c no value", pipe, indicator);*/
}
/*g_warning("write %d leave", pipe);*/
}
/* indication report routines */
void
sync_pipe_packet_count_to_parent(int packet_count)
report_packet_count(int packet_count)
{
char tmp[SP_DECISIZE+1+1];
static int count = 0;
@ -588,10 +531,10 @@ sync_pipe_packet_count_to_parent(int packet_count)
}
void
sync_pipe_filename_to_parent(const char *filename)
report_new_capture_file(const char *filename)
{
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "File: %s", filename);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "File: %s", filename);
if(capture_child) {
pipe_write_block(1, SP_FILE, filename);
@ -599,7 +542,7 @@ sync_pipe_filename_to_parent(const char *filename)
}
void
sync_pipe_cfilter_error_to_parent(const char *cfilter _U_, const char *errmsg)
report_cfilter_error(const char *cfilter _U_, const char *errmsg)
{
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Capture filter error: %s", errmsg);
@ -610,30 +553,27 @@ sync_pipe_cfilter_error_to_parent(const char *cfilter _U_, const char *errmsg)
}
void
sync_pipe_errmsg_to_parent(const char *error_msg, const char *secondary_error_msg)
report_capture_error(const char *error_msg, const char *secondary_error_msg)
{
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE,
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"Primary Error: %s", error_msg);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE,
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"Secondary Error: %s", secondary_error_msg);
if(capture_child) {
/* first write a "master header" with the length of the two messages plus their "slave headers" */
pipe_write_header(1, SP_ERROR_MSG, strlen(error_msg) + 1 + 4 + strlen(secondary_error_msg) + 1 + 4);
pipe_write_block(1, SP_ERROR_MSG, error_msg);
pipe_write_block(1, SP_ERROR_MSG, secondary_error_msg);
sync_pipe_errmsg_to_parent(error_msg, secondary_error_msg);
}
}
void
sync_pipe_drops_to_parent(int drops)
report_packet_drops(int drops)
{
char tmp[SP_DECISIZE+1+1];
g_snprintf(tmp, sizeof(tmp), "%d", drops);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_MESSAGE, "Packets dropped: %s", tmp);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets dropped: %s", tmp);
if(capture_child) {
pipe_write_block(1, SP_DROPS, tmp);

79
sync_pipe.h Normal file
View File

@ -0,0 +1,79 @@
/* sync_pipe.h
* Low-level synchronization pipe routines for use by Ethereal and dumpcap
*
* $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/** @file
*
* Low-level sync pipe interfaces.
*/
#ifndef __SYNC_PIPE_H__
#define __SYNC_PIPE_H__
/*
* Maximum length of sync pipe message data. Must be < 2^24, as the
* message length is 3 bytes.
* XXX - this must be large enough to handle a Really Big Filter
* Expression, as the error message for an incorrect filter expression
* is a bit larger than the filter expression.
*/
#define SP_MAX_MSG_LEN 4096
/* Size of buffer to hold decimal representation of
signed/unsigned 64-bit int */
#define SP_DECISIZE 20
/*
* Indications sent out on the sync pipe (from child to parent).
*/
#define SP_FILE 'F' /* the name of the recently opened file */
#define SP_ERROR_MSG 'E' /* error message */
#define SP_BAD_FILTER 'B' /* error message for bad capture filter */
#define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
#define SP_DROPS 'D' /* count of packets dropped in capture */
/*
* Win32 only: Indications sent out on the signal pipe (from parent to child)
* (UNIX-like sends signals for this)
*/
#define SP_QUIT 'Q' /* "gracefully" capture quit message (SIGUSR1) */
/* write a single message header to the recipient pipe */
extern int
pipe_write_header(int pipe, char indicator, int length);
/* write a message to the recipient pipe in the standard format
(3 digit message length (excluding length and indicator field),
1 byte message indicator and the rest is the message).
If msg is NULL, the message has only a length and indicator. */
extern void
pipe_write_block(int pipe, char indicator, const char *msg);
/** the child encountered an error, notify the parent */
extern void
sync_pipe_errmsg_to_parent(const char *error_msg,
const char *secondary_error_msg);
#endif /* sync_pipe.h */

110
sync_pipe_write.c Normal file
View File

@ -0,0 +1,110 @@
/* sync_pipe_write.c
*
* $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <glib.h>
#include "sync_pipe.h"
#include "log.h"
/****************************************************************************************************************/
/* sync_pipe handling */
/* write a single message header to the recipient pipe */
int
pipe_write_header(int pipe, char indicator, int length)
{
guchar header[1+3]; /* indicator + 3-byte len */
g_assert(length <= SP_MAX_MSG_LEN);
/* write header (indicator + 3-byte len) */
header[0] = indicator;
header[1] = (length >> 16) & 0xFF;
header[2] = (length >> 8) & 0xFF;
header[3] = (length >> 0) & 0xFF;
/* write header */
return write(pipe, header, sizeof header);
}
/* write a message to the recipient pipe in the standard format
(3 digit message length (excluding length and indicator field),
1 byte message indicator and the rest is the message).
If msg is NULL, the message has only a length and indicator. */
void
pipe_write_block(int pipe, char indicator, const char *msg)
{
int ret;
size_t len;
/*g_warning("write %d enter", pipe);*/
if(msg != NULL) {
len = strlen(msg) + 1; /* including the terminating '\0'! */
} else {
len = 0;
}
/* write header (indicator + 3-byte len) */
ret = pipe_write_header(pipe, indicator, len);
if(ret == -1) {
return;
}
/* write value (if we have one) */
if(len) {
/*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
ret = write(pipe, msg, len);
if(ret == -1) {
return;
}
} else {
/*g_warning("write %d indicator: %c no value", pipe, indicator);*/
}
/*g_warning("write %d leave", pipe);*/
}
void
sync_pipe_errmsg_to_parent(const char *error_msg, const char *secondary_error_msg)
{
/* first write a "master header" with the length of the two messages plus their "slave headers" */
pipe_write_header(1, SP_ERROR_MSG, strlen(error_msg) + 1 + 4 + strlen(secondary_error_msg) + 1 + 4);
pipe_write_block(1, SP_ERROR_MSG, error_msg);
pipe_write_block(1, SP_ERROR_MSG, secondary_error_msg);
}

View File

@ -2995,37 +2995,45 @@ cmdarg_err_cont(const char *fmt, ...)
/****************************************************************************************************************/
/* sync pipe "dummies", needed for capture_loop.c */
/* indication report "dummies", needed for capture_loop.c */
#ifdef HAVE_LIBPCAP
/** the child has opened a new capture file, notify the parent */
/** Report a new capture file having been opened. */
void
sync_pipe_filename_to_parent(const char *filename)
report_new_capture_file(const char *filename)
{
/* shouldn't happen */
g_assert(0);
g_assert_not_reached();
}
/** the child captured some new packets, notify the parent */
/** Report a number of new packets captured. */
void
sync_pipe_packet_count_to_parent(int packet_count)
report_packet_count(int packet_count)
{
/* shouldn't happen */
g_assert(0);
g_assert_not_reached();
}
/** the child stopped capturing, notify the parent */
/** Report the packet drops once the capture finishes. */
void
sync_pipe_drops_to_parent(int drops)
report_packet_drops(int drops)
{
/* shouldn't happen */
g_assert(0);
g_assert_not_reached();
}
/** the child encountered an error with a capture filter, notify the parent */
/** Report an error in the capture. */
void
report_capture_error(const char *errmsg, const char *secondary_error_msg)
{
cmdarg_err(errmsg);
cmdarg_err_cont(secondary_error_msg);
}
/** Report an error with a capture filter. */
void
sync_pipe_cfilter_error_to_parent(const char *cfilter, const char *errmsg)
report_cfilter_error(const char *cfilter, const char *errmsg)
{
cmdarg_err(
@ -3036,14 +3044,6 @@ sync_pipe_cfilter_error_to_parent(const char *cfilter, const char *errmsg)
cfilter, errmsg);
}
/** the child encountered an error, notify the parent */
void
sync_pipe_errmsg_to_parent(const char *errmsg, const char *secondary_error_msg)
{
cmdarg_err(errmsg);
cmdarg_err_cont(secondary_error_msg);
}
#endif /* HAVE_LIBPCAP */