#endif
#ifdef _WIN32
-#include "epan/unicode-utils.h"
+#include <wsutil/unicode-utils.h>
#endif
-#include "epan/privileges.h"
+#include <wsutil/privileges.h>
#include "sync_pipe.h"
* This needs to be static, so that the SIGUSR1 handler can clear the "go"
* flag.
*/
-static loop_data ld;
+static loop_data global_ld;
/*
/* capture related options */
static capture_options global_capture_opts;
-static capture_options *capture_opts = &global_capture_opts;
static void capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
const u_char *pd);
static void report_new_capture_file(const char *filename);
static void report_packet_count(int packet_count);
-static void report_packet_drops(int drops);
+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);
pcap_t *pch;
char errbuf[PCAP_ERRBUF_SIZE];
struct pcap_stat ps;
+#ifndef _WIN32
+ struct sigaction act;
+#endif
if_list = get_interface_list(&err, &err_str);
if (if_list == NULL) {
"Dropped");
}
- ld.go = TRUE;
- while (ld.go) {
+#ifndef _WIN32
+ /* handle SIGPIPE signal to default action */
+ act.sa_handler = SIG_DFL;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_RESTART;
+ sigaction(SIGPIPE,&act,NULL);
+#endif
+
+ global_ld.go = TRUE;
+ while (global_ld.go) {
for (stat_entry = g_list_first(stat_list); stat_entry != NULL; stat_entry = g_list_next(stat_entry)) {
if_stat = stat_entry->data;
pcap_stats(if_stat->pch, &ps);
if (!machine_readable) {
- printf("%-15s %10d %10d\n", if_stat->name,
+ printf("%-15s %10u %10u\n", if_stat->name,
ps.ps_recv, ps.ps_drop);
} else {
- printf("%s\t%d\t%d\n", if_stat->name,
+ printf("%s\t%u\t%u\n", if_stat->name,
ps.ps_recv, ps.ps_drop);
fflush(stdout);
}
/* we've opened "iface" as a network device */
#ifdef _WIN32
/* try to set the capture buffer size */
- if (pcap_setbuff(ld->pcap_h, capture_opts->buffer_size * 1024 * 1024) != 0) {
+ if (capture_opts->buffer_size > 1 &&
+ pcap_setbuff(ld->pcap_h, capture_opts->buffer_size * 1024 * 1024) != 0) {
sync_secondary_msg_str = g_strdup_printf(
"The capture buffer size of %luMB seems to be too high for your machine,\n"
"the default of 1MB will be used.\n"
"\n"
"Help can be found at:\n"
"\n"
-" http://wiki.wireshark.org/CaptureSetup\n"
-"\n"
-"64-bit Windows:\n"
-"WinPcap does not support 64-bit Windows; you will have to use some other\n"
-"tool to capture traffic, such as netcap.\n"
-"For netcap details see: http://support.microsoft.com/?id=310875\n"
-"\n"
-"Modem (PPP/WAN):\n"
-"Note that version 3.0 of WinPcap, and earlier versions of WinPcap, don't\n"
-"support capturing on PPP/WAN interfaces on Windows NT 4.0 / 2000 / XP /\n"
-"Server 2003.\n"
-"WinPcap 3.1 has support for it on Windows 2000 / XP / Server 2003, but has no\n"
-"support for it on Windows NT 4.0 or Windows Vista (Beta 1).",
+" http://wiki.wireshark.org/WinPcap\n"
+" http://wiki.wireshark.org/CaptureSetup\n",
capture_opts->iface);
#endif /* _WIN32 */
}
char tmpname[128+1];
gchar *capfile_name;
gboolean is_tempfile;
-
+#ifndef _WIN32
+ int ret;
+#endif
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_output: %s",
(capture_opts->save_file) ? capture_opts->save_file : "");
/* capture_opts.save_file is "g_free"ed later, which is equivalent to
"g_free(capfile_name)". */
#ifndef _WIN32
- fchown(*save_file_fd, capture_opts->owner, capture_opts->group);
+ ret = fchown(*save_file_fd, capture_opts->owner, capture_opts->group);
#endif
return TRUE;
*secondary_errmsg = '\0';
/* init the loop data */
- ld.go = TRUE;
- ld.packet_count = 0;
+ global_ld.go = TRUE;
+ global_ld.packet_count = 0;
if (capture_opts->has_autostop_packets)
- ld.packet_max = capture_opts->autostop_packets;
+ global_ld.packet_max = capture_opts->autostop_packets;
else
- ld.packet_max = 0; /* no limit */
- ld.err = 0; /* no error seen yet */
- ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
- ld.pcap_err = FALSE;
- ld.from_cap_pipe = FALSE;
- ld.pdh = NULL;
- ld.cap_pipe_fd = -1;
+ 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.cap_pipe_fd = -1;
#ifdef MUST_DO_SELECT
- ld.pcap_fd = 0;
+ global_ld.pcap_fd = 0;
#endif
/* We haven't yet gotten the capture statistics. */
capture_opts_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, capture_opts);
/* open the "input file" from network interface or capture pipe */
- if (!capture_loop_open_input(capture_opts, &ld, errmsg, sizeof(errmsg),
+ if (!capture_loop_open_input(capture_opts, &global_ld, errmsg, sizeof(errmsg),
secondary_errmsg, sizeof(secondary_errmsg))) {
goto error;
}
/* init the input filter from the network interface (capture pipe will do nothing) */
- switch (capture_loop_init_filter(ld.pcap_h, ld.from_cap_pipe, capture_opts->iface, capture_opts->cfilter)) {
+ switch (capture_loop_init_filter(global_ld.pcap_h, global_ld.from_cap_pipe,
+ capture_opts->iface,
+ capture_opts->cfilter)) {
case INITFILTER_NO_ERROR:
break;
case INITFILTER_BAD_FILTER:
cfilter_error = TRUE;
- g_snprintf(errmsg, sizeof(errmsg), "%s", pcap_geterr(ld.pcap_h));
+ g_snprintf(errmsg, sizeof(errmsg), "%s", pcap_geterr(global_ld.pcap_h));
goto error;
case INITFILTER_OTHER_ERROR:
g_snprintf(errmsg, sizeof(errmsg), "Can't install filter (%s).",
- pcap_geterr(ld.pcap_h));
+ pcap_geterr(global_ld.pcap_h));
g_snprintf(secondary_errmsg, sizeof(secondary_errmsg), "%s", please_report);
goto error;
}
}
/* set up to write to the already-opened capture output file/files */
- if (!capture_loop_init_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
+ if (!capture_loop_init_output(capture_opts, save_file_fd, &global_ld,
+ errmsg, sizeof(errmsg))) {
goto error;
}
message to our parent so that they'll open the capture file and
update its windows to indicate that we have a live capture in
progress. */
- libpcap_dump_flush(ld.pdh, NULL);
+ libpcap_dump_flush(global_ld.pdh, NULL);
report_new_capture_file(capture_opts->save_file);
}
/* WOW, everything is prepared! */
/* please fasten your seat belts, we will enter now the actual capture loop */
- while (ld.go) {
+ while (global_ld.go) {
/* dispatch incoming packets */
- inpkts = capture_loop_dispatch(capture_opts, &ld, errmsg, sizeof(errmsg));
+ inpkts = capture_loop_dispatch(capture_opts, &global_ld, errmsg,
+ sizeof(errmsg));
#ifdef _WIN32
/* any news from our parent (signal pipe)? -> just stop the capture */
if (!signal_pipe_check_running()) {
- ld.go = FALSE;
+ global_ld.go = FALSE;
}
#endif
/* check capture size condition */
if (cnd_autostop_size != NULL &&
- cnd_eval(cnd_autostop_size, (guint32)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 */
- ld.go = FALSE;
+ global_ld.go = FALSE;
continue;
}
/* Switch to the next ringbuffer file */
- if (ringbuf_switch_file(&ld.pdh, &capture_opts->save_file,
- &save_file_fd, &ld.bytes_written, &ld.err)) {
+ if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
+ &save_file_fd, &global_ld.bytes_written, &global_ld.err)) {
/* File switch succeeded: reset the conditions */
cnd_reset(cnd_autostop_size);
if (cnd_file_duration) {
cnd_reset(cnd_file_duration);
}
- libpcap_dump_flush(ld.pdh, NULL);
+ 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 */
- ld.go = FALSE;
+ global_ld.go = FALSE;
continue;
}
} else {
/* single file, stop now */
- ld.go = FALSE;
+ global_ld.go = FALSE;
continue;
}
} /* cnd_autostop_size */
if (capture_opts->output_to_pipe) {
- libpcap_dump_flush(ld.pdh, NULL);
+ libpcap_dump_flush(global_ld.pdh, NULL);
}
} /* inpkts */
/* Let the parent process know. */
if (inpkts_to_sync_pipe) {
/* do sync here */
- libpcap_dump_flush(ld.pdh, NULL);
+ 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. */
/* check capture duration condition */
if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) {
/* The maximum capture time has elapsed; stop the capture. */
- ld.go = FALSE;
+ global_ld.go = FALSE;
continue;
}
if (cnd_autostop_files != NULL &&
cnd_eval(cnd_autostop_files, ++autostop_files)) {
/* no files left: stop here */
- ld.go = FALSE;
+ global_ld.go = FALSE;
continue;
}
/* Switch to the next ringbuffer file */
- if (ringbuf_switch_file(&ld.pdh, &capture_opts->save_file,
- &save_file_fd, &ld.bytes_written, &ld.err)) {
+ if (ringbuf_switch_file(&global_ld.pdh, &capture_opts->save_file,
+ &save_file_fd, &global_ld.bytes_written,
+ &global_ld.err)) {
/* file switch succeeded: reset the conditions */
cnd_reset(cnd_file_duration);
if(cnd_autostop_size)
cnd_reset(cnd_autostop_size);
- libpcap_dump_flush(ld.pdh, NULL);
+ 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 */
- ld.go = FALSE;
+ global_ld.go = FALSE;
continue;
}
} else {
/* single file, stop now */
- ld.go = FALSE;
+ global_ld.go = FALSE;
continue;
}
} /* cnd_file_duration */
}
- } /* while (ld.go) */
+ } /* while (global_ld.go) */
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopping ...");
cnd_delete(cnd_autostop_duration);
/* did we had a pcap (input) error? */
- if (ld.pcap_err) {
+ if (global_ld.pcap_err) {
/* On Linux, if an interface goes down while you're capturing on it,
you'll get a "recvfrom: Network is down" error (ENETDOWN).
(At least you will if strerror() doesn't show a local translation
These should *not* be reported to the Wireshark developers. */
char *cap_err_str;
- cap_err_str = pcap_geterr(ld.pcap_h);
+ cap_err_str = pcap_geterr(global_ld.pcap_h);
if (strcmp(cap_err_str, "recvfrom: Network is down") == 0 ||
strcmp(cap_err_str, "read: Device not configured") == 0 ||
strcmp(cap_err_str, "read: I/O error") == 0) {
report_capture_error(errmsg, please_report);
}
}
- else if (ld.from_cap_pipe && ld.cap_pipe_err == PIPERR)
+ else if (global_ld.from_cap_pipe && global_ld.cap_pipe_err == PIPERR)
report_capture_error(errmsg, "");
/* did we had an error while capturing? */
- if (ld.err == 0) {
+ if (global_ld.err == 0) {
write_ok = TRUE;
} else {
- capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, ld.err,
- FALSE);
+ capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file,
+ global_ld.err, FALSE);
report_capture_error(errmsg, please_report);
write_ok = FALSE;
}
if (capture_opts->saving_to_file) {
/* close the wiretap (output) file */
- close_ok = capture_loop_close_output(capture_opts, &ld, &err_close);
+ close_ok = capture_loop_close_output(capture_opts, &global_ld, &err_close);
} else
close_ok = TRUE;
*/
/* get packet drop statistics from pcap */
- if(ld.pcap_h != NULL) {
- g_assert(!ld.from_cap_pipe);
+ if(global_ld.pcap_h != NULL) {
+ g_assert(!global_ld.from_cap_pipe);
/* Get the capture statistics, so we know how many packets were
dropped. */
- if (pcap_stats(ld.pcap_h, stats) >= 0) {
+ if (pcap_stats(global_ld.pcap_h, stats) >= 0) {
*stats_known = TRUE;
/* Let the parent process know. */
report_packet_drops(stats->ps_drop);
} else {
g_snprintf(errmsg, sizeof(errmsg),
"Can't get packet-drop statistics: %s",
- pcap_geterr(ld.pcap_h));
+ pcap_geterr(global_ld.pcap_h));
report_capture_error(errmsg, please_report);
}
}
/* close the input file (pcap or capture pipe) */
- capture_loop_close_input(&ld);
+ capture_loop_close_input(&global_ld);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped!");
report_capture_error(errmsg, secondary_errmsg);
/* close the input file (pcap or cap_pipe) */
- capture_loop_close_input(&ld);
+ capture_loop_close_input(&global_ld);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped with error");
static void capture_loop_stop(void)
{
#ifdef HAVE_PCAP_BREAKLOOP
- if(ld.pcap_h != NULL)
- pcap_breakloop(ld.pcap_h);
+ if(global_ld.pcap_h != NULL)
+ pcap_breakloop(global_ld.pcap_h);
#endif
- ld.go = FALSE;
+ global_ld.go = FALSE;
}
relinquish_privs_except_capture();
#endif
- /* Set the initial values in the capture_opts. This might be overwritten
+ /* Set the initial values in the capture options. This might be overwritten
by the command line parameters. */
- capture_opts_init(capture_opts, NULL);
+ capture_opts_init(&global_capture_opts, NULL);
/* Default to capturing the entire packet. */
- capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
+ global_capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
/* We always save to a file - if no file was specified, we save to a
temporary file. */
- capture_opts->saving_to_file = TRUE;
- capture_opts->has_ring_num_files = TRUE;
+ global_capture_opts.saving_to_file = TRUE;
+ global_capture_opts.has_ring_num_files = TRUE;
/* Now get our args */
while ((opt = getopt(argc, argv, optstring)) != -1) {
#ifdef _WIN32
case 'B': /* Buffer size */
#endif /* _WIN32 */
- status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
+ status = capture_opts_add_opt(&global_capture_opts, opt, optarg, &start_capture);
if(status != 0) {
exit_main(status);
}
/* We're supposed to list the link-layer types for an interface;
did the user also specify a capture file to be read? */
/* No - did they specify a ring buffer option? */
- if (capture_opts->multi_files_on) {
+ if (global_capture_opts.multi_files_on) {
cmdarg_err("Ring buffer requested, but a capture isn't being done.");
exit_main(1);
}
} else {
/* No - was the ring buffer option specified and, if so, does it make
sense? */
- if (capture_opts->multi_files_on) {
+ if (global_capture_opts.multi_files_on) {
/* Ring buffer works only under certain conditions:
a) ring buffer does not work with temporary files;
b) it makes no sense to enable the ring buffer if the maximum
file size is set to "infinite". */
- if (capture_opts->save_file == NULL) {
+ if (global_capture_opts.save_file == NULL) {
cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
- capture_opts->multi_files_on = FALSE;
+ global_capture_opts.multi_files_on = FALSE;
}
- if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
+ if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
/* XXX - this must be redesigned as the conditions changed */
-/* capture_opts->multi_files_on = FALSE;*/
+/* global_capture_opts.multi_files_on = FALSE;*/
}
}
}
- if (capture_opts_trim_iface(capture_opts, NULL) == FALSE) {
+ if (capture_opts_trim_iface(&global_capture_opts, NULL) == FALSE) {
/* cmdarg_err() already called .... */
exit_main(1);
}
/* Let the user know what interface was chosen. */
/* get_interface_descriptive_name() is not available! */
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Interface: %s\n", capture_opts->iface);
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Interface: %s\n", global_capture_opts.iface);
if (list_interfaces) {
status = capture_opts_list_interfaces(machine_readable);
exit_main(status);
} else if (list_link_layer_types) {
- status = capture_opts_list_link_layer_types(capture_opts, machine_readable);
+ status = capture_opts_list_link_layer_types(&global_capture_opts, machine_readable);
exit_main(status);
} else if (print_statistics) {
status = print_statistics_loop(machine_readable);
exit_main(status);
}
- capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
- capture_opts_trim_ring_num_files(capture_opts);
+ capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
+ capture_opts_trim_ring_num_files(&global_capture_opts);
/* Now start the capture. */
- if(capture_loop_start(capture_opts, &stats_known, &stats) == TRUE) {
+ if(capture_loop_start(&global_capture_opts, &stats_known, &stats) == TRUE) {
/* capture ok */
exit_main(0);
} else {
}
void
-report_packet_drops(int drops)
+report_packet_drops(guint32 drops)
{
char tmp[SP_DECISIZE+1+1];
- g_snprintf(tmp, sizeof(tmp), "%d", drops);
+ g_snprintf(tmp, sizeof(tmp), "%u", drops);
if(capture_child) {
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Packets dropped: %s", tmp);