static GMutex *cap_pipe_read_mtx;
#endif
+#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 */
+#endif /* SIGINFO */
+
/** Stop a low-level capture (stops the capture child). */
static void capture_loop_stop(void);
int err; /* if non-zero, error seen while capturing */
gint packet_count; /* Number of packets we have already captured */
gint packet_max; /* Number of packets we're supposed to capture - 0 means infinite */
+ gint inpkts_to_sync_pipe; /* Packets not already send out to the sync_pipe */
+#ifdef SIGINFO
+ gboolean report_packet_count; /* Set by SIGINFO handler; print packet count */
+#endif
/* pcap "input file" */
pcap_t *pcap_h; /* pcap handle */
} cap_pipe_state;
enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
- /* output file */
+ /* output file(s) */
FILE *pdh;
+ int save_file_fd;
int linktype;
int file_snaplen;
gint wtap_linktype;
long bytes_written;
-
+ guint32 autostop_files;
} loop_data;
/*
/* capture related options */
static capture_options global_capture_opts;
+static gboolean quiet;
static void capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
const u_char *pd);
fprintf(output, " -n use pcapng format instead of pcap\n");
/*fprintf(output, "\n");*/
fprintf(output, "Miscellaneous:\n");
+ fprintf(output, " -q don't report packet capture counts\n");
fprintf(output, " -v print version information and exit\n");
fprintf(output, " -h display this help and exit\n");
fprintf(output, "\n");
#endif
)
{
- int linktype;
+ int linktype;
#ifdef _AIX
- const char *ifacename;
+ const char *ifacename;
#endif
- linktype = pcap_datalink(pch);
+ linktype = pcap_datalink(pch);
#ifdef _AIX
- /*
- * The libpcap that comes with AIX 5.x uses RFC 1573 ifType values
- * rather than DLT_ values for link-layer types; the ifType values
- * for LAN devices are:
- *
- * Ethernet 6
- * 802.3 7
- * Token Ring 9
- * FDDI 15
- *
- * and the ifType value for a loopback device is 24.
- *
- * The AIX names for LAN devices begin with:
- *
- * Ethernet en
- * 802.3 et
- * Token Ring tr
- * FDDI fi
- *
- * and the AIX names for loopback devices begin with "lo".
- *
- * (The difference between "Ethernet" and "802.3" is presumably
- * whether packets have an Ethernet header, with a packet type,
- * or an 802.3 header, with a packet length, followed by an 802.2
- * header and possibly a SNAP header.)
- *
- * If the device name matches "linktype" interpreted as an ifType
- * value, rather than as a DLT_ value, we will assume this is AIX's
- * non-standard, incompatible libpcap, rather than a standard libpcap,
- * and will map the link-layer type to the standard DLT_ value for
- * that link-layer type, as that's what the rest of Wireshark expects.
- *
- * (This means the capture files won't be readable by a tcpdump
- * linked with AIX's non-standard libpcap, but so it goes. They
- * *will* be readable by standard versions of tcpdump, Wireshark,
- * and so on.)
- *
- * XXX - if we conclude we're using AIX libpcap, should we also
- * set a flag to cause us to assume the time stamps are in
- * seconds-and-nanoseconds form, and to convert them to
- * seconds-and-microseconds form before processing them and
- * writing them out?
- */
-
- /*
- * Find the last component of the device name, which is the
- * interface name.
- */
- ifacename = strchr(devname, '/');
- if (ifacename == NULL)
- ifacename = devname;
-
- /* See if it matches any of the LAN device names. */
- if (strncmp(ifacename, "en", 2) == 0) {
- if (linktype == 6) {
- /*
- * That's the RFC 1573 value for Ethernet; map it
- * to DLT_EN10MB.
- */
- linktype = 1;
- }
- } else if (strncmp(ifacename, "et", 2) == 0) {
- if (linktype == 7) {
- /*
- * That's the RFC 1573 value for 802.3; map it to
- * DLT_EN10MB.
- * (libpcap, tcpdump, Wireshark, etc. don't care if
- * it's Ethernet or 802.3.)
- */
- linktype = 1;
- }
- } else if (strncmp(ifacename, "tr", 2) == 0) {
- if (linktype == 9) {
- /*
- * That's the RFC 1573 value for 802.5 (Token Ring);
- * map it to DLT_IEEE802, which is what's used for
- * Token Ring.
- */
- linktype = 6;
- }
- } else if (strncmp(ifacename, "fi", 2) == 0) {
- if (linktype == 15) {
- /*
- * That's the RFC 1573 value for FDDI; map it to
- * DLT_FDDI.
- */
- linktype = 10;
- }
- } else if (strncmp(ifacename, "lo", 2) == 0) {
- if (linktype == 24) {
- /*
- * That's the RFC 1573 value for "software loopback"
- * devices; map it to DLT_NULL, which is what's used
- * for loopback devices on BSD.
- */
- linktype = 0;
- }
- }
-#endif
-
- return linktype;
+ /*
+ * The libpcap that comes with AIX 5.x uses RFC 1573 ifType values
+ * rather than DLT_ values for link-layer types; the ifType values
+ * for LAN devices are:
+ *
+ * Ethernet 6
+ * 802.3 7
+ * Token Ring 9
+ * FDDI 15
+ *
+ * and the ifType value for a loopback device is 24.
+ *
+ * The AIX names for LAN devices begin with:
+ *
+ * Ethernet en
+ * 802.3 et
+ * Token Ring tr
+ * FDDI fi
+ *
+ * and the AIX names for loopback devices begin with "lo".
+ *
+ * (The difference between "Ethernet" and "802.3" is presumably
+ * whether packets have an Ethernet header, with a packet type,
+ * or an 802.3 header, with a packet length, followed by an 802.2
+ * header and possibly a SNAP header.)
+ *
+ * If the device name matches "linktype" interpreted as an ifType
+ * value, rather than as a DLT_ value, we will assume this is AIX's
+ * non-standard, incompatible libpcap, rather than a standard libpcap,
+ * and will map the link-layer type to the standard DLT_ value for
+ * that link-layer type, as that's what the rest of Wireshark expects.
+ *
+ * (This means the capture files won't be readable by a tcpdump
+ * linked with AIX's non-standard libpcap, but so it goes. They
+ * *will* be readable by standard versions of tcpdump, Wireshark,
+ * and so on.)
+ *
+ * XXX - if we conclude we're using AIX libpcap, should we also
+ * set a flag to cause us to assume the time stamps are in
+ * seconds-and-nanoseconds form, and to convert them to
+ * seconds-and-microseconds form before processing them and
+ * writing them out?
+ */
+
+ /*
+ * Find the last component of the device name, which is the
+ * interface name.
+ */
+ ifacename = strchr(devname, '/');
+ if (ifacename == NULL)
+ ifacename = devname;
+
+ /* See if it matches any of the LAN device names. */
+ if (strncmp(ifacename, "en", 2) == 0) {
+ if (linktype == 6) {
+ /*
+ * That's the RFC 1573 value for Ethernet; map it to DLT_EN10MB.
+ */
+ linktype = 1;
+ }
+ } else if (strncmp(ifacename, "et", 2) == 0) {
+ if (linktype == 7) {
+ /*
+ * That's the RFC 1573 value for 802.3; map it to DLT_EN10MB.
+ * (libpcap, tcpdump, Wireshark, etc. don't care if it's Ethernet
+ * or 802.3.)
+ */
+ linktype = 1;
+ }
+ } else if (strncmp(ifacename, "tr", 2) == 0) {
+ if (linktype == 9) {
+ /*
+ * That's the RFC 1573 value for 802.5 (Token Ring); map it to
+ * DLT_IEEE802, which is what's used for Token Ring.
+ */
+ linktype = 6;
+ }
+ } else if (strncmp(ifacename, "fi", 2) == 0) {
+ if (linktype == 15) {
+ /*
+ * That's the RFC 1573 value for FDDI; map it to DLT_FDDI.
+ */
+ linktype = 10;
+ }
+ } else if (strncmp(ifacename, "lo", 2) == 0) {
+ if (linktype == 24) {
+ /*
+ * That's the RFC 1573 value for "software loopback" devices; map it
+ * to DLT_NULL, which is what's used for loopback devices on BSD.
+ */
+ linktype = 0;
+ }
+ }
+#endif
+
+ return linktype;
}
static data_link_info_t *
create_data_link_info(int dlt)
{
- data_link_info_t *data_link_info;
- const char *text;
-
- data_link_info = (data_link_info_t *)g_malloc(sizeof (data_link_info_t));
- data_link_info->dlt = dlt;
- text = pcap_datalink_val_to_name(dlt);
- if (text != NULL)
- data_link_info->name = g_strdup(text);
- else
- data_link_info->name = g_strdup_printf("DLT %d", dlt);
- text = pcap_datalink_val_to_description(dlt);
- if (text != NULL)
- data_link_info->description = g_strdup(text);
- else
- data_link_info->description = NULL;
- return data_link_info;
+ data_link_info_t *data_link_info;
+ const char *text;
+
+ data_link_info = (data_link_info_t *)g_malloc(sizeof (data_link_info_t));
+ data_link_info->dlt = dlt;
+ text = pcap_datalink_val_to_name(dlt);
+ if (text != NULL)
+ data_link_info->name = g_strdup(text);
+ else
+ data_link_info->name = g_strdup_printf("DLT %d", dlt);
+ text = pcap_datalink_val_to_description(dlt);
+ if (text != NULL)
+ data_link_info->description = g_strdup(text);
+ else
+ data_link_info->description = NULL;
+ return data_link_info;
}
/*
return NULL;
}
status = pcap_can_set_rfmon(pch);
- switch (status) {
-
- case 0:
- caps->can_set_rfmon = FALSE;
- break;
-
- case 1:
- caps->can_set_rfmon = TRUE;
- if (monitor_mode)
- pcap_set_rfmon(pch, 1);
- break;
-
- case PCAP_ERROR_NO_SUCH_DEVICE:
- if (err_str != NULL)
- *err_str = g_strdup_printf("There is no capture device named \"%s\"", devname);
- pcap_close(pch);
- g_free(caps);
- return NULL;
-
- case PCAP_ERROR:
- if (err_str != NULL)
- *err_str = g_strdup_printf("pcap_can_set_rfmon on \"%s\" failed: %s",
- devname, pcap_geterr(pch));
+ if (status < 0) {
+ /* Error. */
+ if (status == PCAP_ERROR)
+ *err_str = g_strdup_printf("pcap_can_set_rfmon() failed: %s",
+ pcap_geterr(pch));
+ else
+ *err_str = g_strdup(pcap_statustostr(status));
pcap_close(pch);
g_free(caps);
return NULL;
-
- default:
- if (err_str != NULL)
- *err_str = g_strdup_printf("pcap_can_set_rfmon on \"%s\" failed: %s",
- devname, pcap_statustostr(status));
+ }
+ if (status == 0)
+ caps->can_set_rfmon = FALSE;
+ else if (status == 1) {
+ caps->can_set_rfmon = TRUE;
+ if (monitor_mode)
+ pcap_set_rfmon(pch, 1);
+ } else {
+ if (err_str != NULL) {
+ *err_str = g_strdup_printf("pcap_can_set_rfmon() returned %d",
+ status);
+ }
pcap_close(pch);
g_free(caps);
return NULL;
if (status < 0) {
/* Error. We ignore warnings (status > 0). */
if (err_str != NULL) {
- if (status == PCAP_ERROR) {
- *err_str = g_strdup_printf("pcap_activate on %s failed: %s",
- devname, pcap_geterr(pch));
- } else {
- *err_str = g_strdup_printf("pcap_activate on %s failed: %s",
- devname, pcap_statustostr(status));
- }
+ if (status == PCAP_ERROR)
+ *err_str = g_strdup_printf("pcap_activate() failed: %s",
+ pcap_geterr(pch));
+ else
+ *err_str = g_strdup(pcap_statustostr(status));
}
pcap_close(pch);
g_free(caps);
}
#endif
+
+#ifdef SIGINFO
+static void
+report_counts(void)
+{
+ /* Don't print this if we're a capture child. */
+ if (!capture_child) {
+ if (quiet) {
+ /* Report the count only if we aren't printing a packet count
+ as packets arrive. */
+ fprintf(stderr, "%u packet%s captured\n", global_ld.packet_count,
+ plurality(global_ld.packet_count, "", "s"));
+ }
+ }
+ infoprint = FALSE; /* we just reported it */
+}
+
+static void
+report_counts_siginfo(int signum _U_)
+{
+ int sav_errno = errno;
+
+ /* If we've been told to delay printing, just set a flag asking
+ that we print counts (if we're supposed to), otherwise print
+ the count of packets captured (if we're supposed to). */
+ if (infodelay)
+ infoprint = TRUE;
+ else
+ report_counts();
+ errno = sav_errno;
+}
+#endif /* SIGINFO */
+
static void exit_main(int status)
{
#ifdef _WIN32
static const char *
set_pcap_linktype(pcap_t *pch, char *devname
#ifdef HAVE_PCAP_SET_DATALINK
- _U_
+ _U_
#endif
- , int dlt)
+ , int dlt)
{
#ifdef HAVE_PCAP_SET_DATALINK
- if (pcap_set_datalink(pch, dlt) == 0)
- return NULL; /* no error */
- return pcap_geterr(pch);
+ 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 isn't one of the DLTs supported by this device";
+ /* 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 isn't one of the DLTs supported by this device";
#endif
}
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
gchar *sync_secondary_msg_str;
WORD wVersionRequested;
/* set up to write to the already-opened capture output file/files */
static gboolean
-capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
+capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len) {
int err;
if (capture_opts->multi_files_on) {
ld->pdh = ringbuf_init_libpcap_fdopen(&err);
} else {
- ld->pdh = libpcap_fdopen(save_file_fd, &err);
+ ld->pdh = libpcap_fdopen(ld->save_file_fd, &err);
}
if (ld->pdh) {
gboolean successful;
#define TIME_GET() time(NULL)
#endif
+/* Do the work of handling either the file size or file duration capture
+ conditions being reached, and switching files or stopping. */
+static gboolean
+do_file_switch_or_stop(capture_options *capture_opts,
+ condition *cnd_autostop_files,
+ condition *cnd_autostop_size,
+ condition *cnd_file_duration)
+{
+ if (capture_opts->multi_files_on) {
+ if (cnd_autostop_files != NULL &&
+ cnd_eval(cnd_autostop_files, ++global_ld.autostop_files)) {
+ /* no files left: stop here */
+ global_ld.go = FALSE;
+ return FALSE;
+ }
+
+ /* Switch to the next ringbuffer file */
+ if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
+ &global_ld.save_file_fd, &global_ld.err)) {
+ gboolean successful;
+
+ /* File switch succeeded: reset the conditions */
+ global_ld.bytes_written = 0;
+ if (capture_opts->use_pcapng) {
+ char appname[100];
+
+ g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion);
+ successful = libpcap_write_session_header_block(global_ld.pdh, appname, &global_ld.bytes_written, &global_ld.err) &&
+ libpcap_write_interface_description_block(global_ld.pdh, capture_opts->iface, capture_opts->cfilter, global_ld.linktype, global_ld.file_snaplen, &global_ld.bytes_written, &global_ld.err);
+ } else {
+ successful = libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen,
+ &global_ld.bytes_written, &global_ld.err);
+ }
+ if (!successful) {
+ fclose(global_ld.pdh);
+ global_ld.pdh = NULL;
+ global_ld.go = FALSE;
+ return FALSE;
+ }
+ if(cnd_autostop_size)
+ cnd_reset(cnd_autostop_size);
+ if(cnd_file_duration)
+ cnd_reset(cnd_file_duration);
+ libpcap_dump_flush(global_ld.pdh, NULL);
+ if (!quiet)
+ report_packet_count(global_ld.inpkts_to_sync_pipe);
+ global_ld.inpkts_to_sync_pipe = 0;
+ report_new_capture_file(capture_opts->save_file);
+ } else {
+ /* File switch failed: stop here */
+ global_ld.go = FALSE;
+ return FALSE;
+ }
+ } else {
+ /* single file, stop now */
+ global_ld.go = FALSE;
+ return FALSE;
+ }
+ return TRUE;
+}
+
/* Do the low-level work of a capture.
Returns TRUE if it succeeds, FALSE otherwise. */
static gboolean
time_t start_time;
int err_close;
int inpkts;
- gint inpkts_to_sync_pipe = 0; /* packets not already send out to the sync_pipe */
condition *cnd_file_duration = NULL;
condition *cnd_autostop_files = NULL;
condition *cnd_autostop_size = NULL;
condition *cnd_autostop_duration = NULL;
- guint32 autostop_files = 0;
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];
- int save_file_fd = -1;
*errmsg = '\0';
*secondary_errmsg = '\0';
/* init the loop data */
- global_ld.go = TRUE;
- global_ld.packet_count = 0;
+ global_ld.go = TRUE;
+ global_ld.packet_count = 0;
+#ifdef SIGINFO
+ global_ld.report_packet_count = FALSE;
+#endif
if (capture_opts->has_autostop_packets)
- global_ld.packet_max = capture_opts->autostop_packets;
+ global_ld.packet_max = capture_opts->autostop_packets;
else
- global_ld.packet_max = 0; /* no limit */
- global_ld.err = 0; /* no error seen yet */
- global_ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
- global_ld.pcap_err = FALSE;
- global_ld.from_cap_pipe = FALSE;
- global_ld.pdh = NULL;
+ global_ld.packet_max = 0; /* no limit */
+ global_ld.inpkts_to_sync_pipe = 0;
+ global_ld.err = 0; /* no error seen yet */
+ global_ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
+ global_ld.pcap_err = FALSE;
+ global_ld.from_cap_pipe = FALSE;
+ global_ld.pdh = NULL;
#ifndef _WIN32
- global_ld.cap_pipe_fd = -1;
+ global_ld.cap_pipe_fd = -1;
#else
- global_ld.cap_pipe_h = INVALID_HANDLE_VALUE;
+ global_ld.cap_pipe_h = INVALID_HANDLE_VALUE;
#endif
#ifdef MUST_DO_SELECT
- global_ld.pcap_fd = 0;
+ global_ld.pcap_fd = 0;
#endif
+ global_ld.autostop_files = 0;
+ global_ld.save_file_fd = -1;
/* We haven't yet gotten the capture statistics. */
*stats_known = FALSE;
/* If we're supposed to write to a capture file, open it for output
(temporary/specified name/ringbuffer) */
if (capture_opts->saving_to_file) {
- if (!capture_loop_open_output(capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) {
+ if (!capture_loop_open_output(capture_opts, &global_ld.save_file_fd,
+ errmsg, sizeof(errmsg))) {
goto error;
}
/* set up to write to the already-opened capture output file/files */
- if (!capture_loop_init_output(capture_opts, save_file_fd, &global_ld,
- errmsg, sizeof(errmsg))) {
+ if (!capture_loop_init_output(capture_opts, &global_ld, errmsg,
+ sizeof(errmsg))) {
goto error;
}
inpkts = capture_loop_dispatch(capture_opts, &global_ld, errmsg,
sizeof(errmsg));
+#ifdef SIGINFO
+ /* Were we asked to print packet counts by the SIGINFO handler? */
+ if (global_ld.report_packet_count) {
+ fprintf(stderr, "%u packet%s captured\n", global_ld.packet_count,
+ plurality(global_ld.packet_count, "", "s"));
+ global_ld.report_packet_count = FALSE;
+ }
+#endif
+
#ifdef _WIN32
/* any news from our parent (signal pipe)? -> just stop the capture */
if (!signal_pipe_check_running()) {
#endif
if (inpkts > 0) {
- inpkts_to_sync_pipe += inpkts;
+ global_ld.inpkts_to_sync_pipe += inpkts;
/* check capture size condition */
if (cnd_autostop_size != NULL &&
- cnd_eval(cnd_autostop_size, (guint32)global_ld.bytes_written)){
+ cnd_eval(cnd_autostop_size, (guint32)global_ld.bytes_written)) {
/* Capture size limit reached, do we have another file? */
- if (capture_opts->multi_files_on) {
- if (cnd_autostop_files != NULL &&
- cnd_eval(cnd_autostop_files, ++autostop_files)) {
- /* no files left: stop here */
- global_ld.go = FALSE;
- continue;
- }
-
- /* Switch to the next ringbuffer file */
- if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
- &save_file_fd, &global_ld.err)) {
- gboolean successful;
-
- /* File switch succeeded: reset the conditions */
- global_ld.bytes_written = 0;
- if (capture_opts->use_pcapng) {
- char appname[100];
-
- g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion);
- successful = libpcap_write_session_header_block(global_ld.pdh, appname, &global_ld.bytes_written, &global_ld.err) &&
- libpcap_write_interface_description_block(global_ld.pdh, capture_opts->iface, capture_opts->cfilter, global_ld.linktype, global_ld.file_snaplen, &global_ld.bytes_written, &global_ld.err);
- } else {
- successful = libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen,
- &global_ld.bytes_written, &global_ld.err);
- }
- if (!successful) {
- fclose(global_ld.pdh);
- global_ld.pdh = NULL;
- global_ld.go = FALSE;
- continue;
- }
- cnd_reset(cnd_autostop_size);
- if (cnd_file_duration) {
- cnd_reset(cnd_file_duration);
- }
- libpcap_dump_flush(global_ld.pdh, NULL);
- report_packet_count(inpkts_to_sync_pipe);
- inpkts_to_sync_pipe = 0;
- report_new_capture_file(capture_opts->save_file);
- } else {
- /* File switch failed: stop here */
- global_ld.go = FALSE;
- continue;
- }
- } else {
- /* single file, stop now */
- global_ld.go = FALSE;
+ if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files,
+ cnd_autostop_size, cnd_file_duration))
continue;
- }
} /* cnd_autostop_size */
if (capture_opts->output_to_pipe) {
libpcap_dump_flush(global_ld.pdh, NULL);
}*/
/* Let the parent process know. */
- if (inpkts_to_sync_pipe) {
+ if (global_ld.inpkts_to_sync_pipe) {
/* do sync here */
libpcap_dump_flush(global_ld.pdh, NULL);
- /* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
- packets to the capture file. */
- report_packet_count(inpkts_to_sync_pipe);
+ /* Send our parent a message saying we've written out
+ "global_ld.inpkts_to_sync_pipe" packets to the capture file. */
+ if (!quiet)
+ report_packet_count(global_ld.inpkts_to_sync_pipe);
- inpkts_to_sync_pipe = 0;
+ global_ld.inpkts_to_sync_pipe = 0;
}
/* check capture duration condition */
/* check capture file duration condition */
if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
/* duration limit reached, do we have another file? */
- if (capture_opts->multi_files_on) {
- if (cnd_autostop_files != NULL &&
- cnd_eval(cnd_autostop_files, ++autostop_files)) {
- /* no files left: stop here */
- global_ld.go = FALSE;
- continue;
- }
-
- /* Switch to the next ringbuffer file */
- if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
- &save_file_fd, &global_ld.err)) {
- gboolean successful;
-
- /* file switch succeeded: reset the conditions */
- global_ld.bytes_written = 0;
- if (capture_opts->use_pcapng) {
- char appname[100];
-
- g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion);
- successful = libpcap_write_session_header_block(global_ld.pdh, appname, &global_ld.bytes_written, &global_ld.err) &&
- libpcap_write_interface_description_block(global_ld.pdh, capture_opts->iface, capture_opts->cfilter, global_ld.linktype, global_ld.file_snaplen, &global_ld.bytes_written, &global_ld.err);
- } else {
- successful = libpcap_write_file_header(global_ld.pdh, global_ld.linktype, global_ld.file_snaplen,
- &global_ld.bytes_written, &global_ld.err);
- }
- if (!successful) {
- fclose(global_ld.pdh);
- global_ld.pdh = NULL;
- global_ld.go = FALSE;
- continue;
- }
- cnd_reset(cnd_file_duration);
- if(cnd_autostop_size)
- cnd_reset(cnd_autostop_size);
- libpcap_dump_flush(global_ld.pdh, NULL);
- report_packet_count(inpkts_to_sync_pipe);
- inpkts_to_sync_pipe = 0;
- report_new_capture_file(capture_opts->save_file);
- } else {
- /* File switch failed: stop here */
- global_ld.go = FALSE;
- continue;
- }
- } else {
- /* single file, stop now */
- global_ld.go = FALSE;
+ if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files,
+ cnd_autostop_size, cnd_file_duration))
continue;
- }
} /* cnd_file_duration */
}
/* 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) {
- report_packet_count(inpkts_to_sync_pipe);
- inpkts_to_sync_pipe = 0;
+ if(global_ld.inpkts_to_sync_pipe) {
+ if (!quiet)
+ report_packet_count(global_ld.inpkts_to_sync_pipe);
+ global_ld.inpkts_to_sync_pipe = 0;
}
/* If we've displayed a message about a write error, there's no point
} else {
/* We can't use the save file, and we have no FILE * for the stream
to close in order to close it, so close the FD directly. */
- if(save_file_fd != -1) {
- ws_close(save_file_fd);
+ if(global_ld.save_file_fd != -1) {
+ ws_close(global_ld.save_file_fd);
}
/* We couldn't even start the capture, so get rid of the capture
gboolean stats_known;
struct pcap_stat stats;
GLogLevelFlags log_flags;
- gboolean print_version_info = FALSE;
gboolean list_interfaces = FALSE;
gboolean list_link_layer_types = FALSE;
gboolean machine_readable = FALSE;
#define OPTSTRING_I ""
#endif
-#define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:Df:hi:" OPTSTRING_I "L" OPTSTRING_m "Mnp" OPTSTRING_r "Ss:" OPTSTRING_u "vw:y:Z:"
+#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 DEBUG_CHILD_DUMPCAP
if ((debug_log = ws_fopen("dumpcap_debug_log.tmp","w")) == NULL) {
sigaction(SIGHUP, NULL, &oldaction);
if (oldaction.sa_handler == SIG_DFL)
sigaction(SIGHUP, &action, NULL);
+
+#ifdef SIGINFO
+ /* Catch SIGINFO and, if we get it and we're capturing in
+ quiet mode, report the number of packets we've captured. */
+ action.sa_handler = report_counts_siginfo;
+ action.sa_flags = SA_RESTART;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGINFO, &action, NULL);
+#endif /* SIGINFO */
#endif /* _WIN32 */
/* ----------------------------------------------------------------- */
exit_main(0);
break;
case 'v': /* Show version and exit */
- print_version_info = TRUE;
- run_once_args++;
+ {
+ GString *comp_info_str;
+ GString *runtime_info_str;
+ /* Assemble the compile-time version information string */
+ comp_info_str = g_string_new("Compiled ");
+ get_compiled_version_info(comp_info_str, NULL);
+
+ /* Assemble the run-time version information string */
+ runtime_info_str = g_string_new("Running ");
+ get_runtime_version_info(runtime_info_str, NULL);
+ show_version(comp_info_str, runtime_info_str);
+ g_string_free(comp_info_str, TRUE);
+ g_string_free(runtime_info_str, TRUE);
+ exit_main(0);
break;
+ }
/*** capture option specific ***/
case 'a': /* autostop criteria */
case 'b': /* Ringbuffer option */
#endif
break;
+ case 'q': /* Quiet */
+ quiet = TRUE;
+ break;
+
/*** all non capture option specific ***/
case 'D': /* Print a list of capture devices and exit */
list_interfaces = TRUE;
print_statistics = TRUE;
run_once_args++;
break;
- case 'M': /* For -D and -L, print machine-readable output */
+ case 'M': /* For -D, -L, and -S, print machine-readable output */
machine_readable = TRUE;
break;
default:
}
if (run_once_args > 1) {
- cmdarg_err("Only one of -v, -D, -L, or -S may be supplied.");
+ cmdarg_err("Only one of -D, -L, or -S may be supplied.");
exit_main(1);
} else if (run_once_args == 1) {
/* We're supposed to print some information, rather than
}
}
- if (print_version_info) {
- GString *comp_info_str;
- GString *runtime_info_str;
-
- if (machine_readable) {
- /* Print only the *pcap version information. */
- comp_info_str = g_string_new("");
- get_compiled_pcap_version(comp_info_str);
-
- runtime_info_str = g_string_new("");
- get_runtime_pcap_version(runtime_info_str);
-
- if (capture_child) {
- /* Let our parent know we succeeded. */
- pipe_write_block(2, SP_SUCCESS, NULL);
- }
-
- /* Print the two version strings on separate lines. */
- printf("%s\n", comp_info_str->str);
- printf("%s\n", runtime_info_str->str);
- } else {
- /* Assemble the compile-time version information string */
- comp_info_str = g_string_new("Compiled ");
- get_compiled_version_info(comp_info_str, NULL);
-
- /* Assemble the run-time version information string */
- runtime_info_str = g_string_new("Running ");
- get_runtime_version_info(runtime_info_str, NULL);
- show_version(comp_info_str, runtime_info_str);
- }
- g_string_free(comp_info_str, TRUE);
- g_string_free(runtime_info_str, TRUE);
- exit_main(0);
- }
-
+ /*
+ * "-D" requires no interface to be selected; it's supposed to list
+ * all interfaces.
+ */
if (list_interfaces) {
/* Get the list of interfaces */
GList *if_list;
}
/*
- * "-D" requires no interface to be selected; it's supposed to list
- * all interfaces.
- *
- * If -D wasn't specified, we have to have an interface; if none
- * was specified, pick a default.
+ * "-S" requires no interface to be selected; it gives statistics
+ * for all interfaces.
+ */
+ if (print_statistics) {
+ status = print_statistics_loop(machine_readable);
+ exit_main(status);
+ }
+
+ /*
+ * "-L", 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) {
/* cmdarg_err() already called .... */
exit_main(0);
}
- if (print_statistics) {
- status = print_statistics_loop(machine_readable);
- exit_main(status);
- }
-
/* We're supposed to do a capture. Process the remaining arguments. */
capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
capture_opts_trim_ring_num_files(&global_capture_opts);
/* indication report routines */
-void
+static void
report_packet_count(int packet_count)
{
char tmp[SP_DECISIZE+1+1];
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "File: %s", filename);
pipe_write_block(2, SP_FILE, filename);
} else {
+#ifdef SIGINFO
+ /*
+ * Prevent a SIGINFO handler from writing to the standard error
+ * while we're doing so; instead, have it just set a flag telling
+ * us to print that information when we're done.
+ */
+ infodelay = TRUE;
+#endif /* SIGINFO */
fprintf(stderr, "File: %s\n", filename);
/* stderr could be line buffered */
fflush(stderr);
+
+#ifdef SIGINFO
+ /*
+ * Allow SIGINFO handlers to write.
+ */
+ infodelay = FALSE;
+
+ /*
+ * If a SIGINFO handler asked us to write out capture counts, do so.
+ */
+ if (infoprint)
+ report_counts();
+#endif /* SIGINFO */
}
}