From f09b320711ab393385d0ba1cd5101f14022eb2bf Mon Sep 17 00:00:00 2001 From: Bill Meier Date: Mon, 21 Mar 2011 16:57:11 +0000 Subject: [PATCH] Fix a comment; Use consistent indentatation & formatting. svn path=/trunk/; revision=36225 --- dumpcap.c | 4655 +++++++++++++++++++++++++++-------------------------- 1 file changed, 2331 insertions(+), 2324 deletions(-) diff --git a/dumpcap.c b/dumpcap.c index 2ab7e70adf..fd949d4684 100644 --- a/dumpcap.c +++ b/dumpcap.c @@ -146,8 +146,8 @@ 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 */ +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). */ @@ -207,60 +207,60 @@ static void capture_loop_stop(void); /** init the capture filter */ typedef enum { - INITFILTER_NO_ERROR, - INITFILTER_BAD_FILTER, - INITFILTER_OTHER_ERROR + INITFILTER_NO_ERROR, + INITFILTER_BAD_FILTER, + INITFILTER_OTHER_ERROR } initfilter_status_t; typedef struct _loop_data { - /* common */ - gboolean go; /* TRUE as long as we're supposed to keep capturing */ - 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 */ + /* common */ + gboolean go; /* TRUE as long as we're supposed to keep capturing */ + 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 */ + gboolean report_packet_count; /* Set by SIGINFO handler; print packet count */ #endif - /* pcap "input file" */ - pcap_t *pcap_h; /* pcap handle */ - gboolean pcap_err; /* TRUE if error from pcap */ + /* pcap "input file" */ + pcap_t *pcap_h; /* pcap handle */ + gboolean pcap_err; /* TRUE if error from pcap */ #ifdef MUST_DO_SELECT - int pcap_fd; /* pcap file descriptor */ + int pcap_fd; /* pcap file descriptor */ #endif - /* capture pipe (unix only "input file") */ - gboolean from_cap_pipe; /* TRUE if we are capturing data from a capture pipe */ - struct pcap_hdr cap_pipe_hdr; /* Pcap header when capturing from a pipe */ - struct pcaprec_modified_hdr cap_pipe_rechdr; /* Pcap record header when capturing from a pipe */ + /* capture pipe (unix only "input file") */ + gboolean from_cap_pipe; /* TRUE if we are capturing data from a capture pipe */ + struct pcap_hdr cap_pipe_hdr; /* Pcap header when capturing from a pipe */ + struct pcaprec_modified_hdr cap_pipe_rechdr; /* Pcap record header when capturing from a pipe */ #ifdef _WIN32 - HANDLE cap_pipe_h; /* The handle of the capture pipe */ + HANDLE cap_pipe_h; /* The handle of the capture pipe */ #else - int cap_pipe_fd; /* the file descriptor of the capture pipe */ + int cap_pipe_fd; /* the file descriptor of the capture pipe */ #endif - gboolean cap_pipe_modified; /* TRUE if data in the pipe uses modified pcap headers */ - gboolean cap_pipe_byte_swapped; /* TRUE if data in the pipe is byte swapped */ + gboolean cap_pipe_modified; /* TRUE if data in the pipe uses modified pcap headers */ + gboolean cap_pipe_byte_swapped; /* TRUE if data in the pipe is byte swapped */ #ifdef USE_THREADS - char * cap_pipe_buf; /* Pointer to the data buffer we read into */ + char * cap_pipe_buf; /* Pointer to the data buffer we read into */ #endif /* USE_THREADS */ - int cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */ - int cap_pipe_bytes_read; /* Used by cap_pipe_dispatch */ - enum { - STATE_EXPECT_REC_HDR, - STATE_READ_REC_HDR, - STATE_EXPECT_DATA, - STATE_READ_DATA - } cap_pipe_state; - enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err; + int cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */ + int cap_pipe_bytes_read; /* Used by cap_pipe_dispatch */ + enum { + STATE_EXPECT_REC_HDR, + STATE_READ_REC_HDR, + STATE_EXPECT_DATA, + STATE_READ_DATA + } cap_pipe_state; + enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err; - /* output file(s) */ - FILE *pdh; - int save_file_fd; - int linktype; - int file_snaplen; - long bytes_written; - guint32 autostop_files; + /* output file(s) */ + FILE *pdh; + int save_file_fd; + int linktype; + int file_snaplen; + long bytes_written; + guint32 autostop_files; } loop_data; /* @@ -288,9 +288,9 @@ static loop_data global_ld; #if defined(__APPLE__) && defined(__LP64__) static gboolean need_timeout_workaround; -#define CAP_READ_TIMEOUT (need_timeout_workaround ? 1000 : 250) +#define CAP_READ_TIMEOUT (need_timeout_workaround ? 1000 : 250) #else -#define CAP_READ_TIMEOUT 250 +#define CAP_READ_TIMEOUT 250 #endif /* @@ -313,16 +313,16 @@ static const char *cap_pipe_err_str; static void console_log_handler(const char *log_domain, GLogLevelFlags log_level, - const char *message, gpointer user_data _U_); + const char *message, gpointer user_data _U_); /* capture related options */ static capture_options global_capture_opts; static gboolean quiet = FALSE; static void capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr, - const u_char *pd); + const u_char *pd); static void capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fname, - int err, gboolean is_close); + int err, gboolean is_close); static void WS_MSVC_NORETURN exit_main(int err) G_GNUC_NORETURN; @@ -335,84 +335,82 @@ static void report_cfilter_error(const char *cfilter, const char *errmsg); #define MSG_MAX_LENGTH 4096 static void -print_usage(gboolean print_ver) { +print_usage(gboolean print_ver) +{ + FILE *output; - FILE *output; - - - if (print_ver) { - output = stdout; - fprintf(output, - "Dumpcap " VERSION "%s\n" - "Capture network packets and dump them into a libpcap file.\n" - "See http://www.wireshark.org for more information.\n", - wireshark_svnversion); - } else { - output = stderr; - } - fprintf(output, "\nUsage: dumpcap [options] ...\n"); - fprintf(output, "\n"); - fprintf(output, "Capture interface:\n"); - fprintf(output, " -i name or idx of interface (def: first non-loopback)\n"); - fprintf(output, " -f packet filter in libpcap filter syntax\n"); - fprintf(output, " -s packet snapshot length (def: 65535)\n"); - fprintf(output, " -p don't capture in promiscuous mode\n"); + if (print_ver) { + output = stdout; + fprintf(output, + "Dumpcap " VERSION "%s\n" + "Capture network packets and dump them into a libpcap file.\n" + "See http://www.wireshark.org for more information.\n", + wireshark_svnversion); + } else { + output = stderr; + } + fprintf(output, "\nUsage: dumpcap [options] ...\n"); + fprintf(output, "\n"); + fprintf(output, "Capture interface:\n"); + fprintf(output, " -i name or idx of interface (def: first non-loopback)\n"); + fprintf(output, " -f packet filter in libpcap filter syntax\n"); + fprintf(output, " -s packet snapshot length (def: 65535)\n"); + fprintf(output, " -p don't capture in promiscuous mode\n"); #ifdef HAVE_PCAP_CREATE - fprintf(output, " -I capture in monitor mode, if available\n"); + fprintf(output, " -I capture in monitor mode, if available\n"); #endif #if defined(_WIN32) || defined(HAVE_PCAP_CREATE) - fprintf(output, " -B size of kernel buffer (def: 1MB)\n"); + fprintf(output, " -B size of kernel buffer (def: 1MB)\n"); #endif - fprintf(output, " -y 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"); + fprintf(output, " -y 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"); + 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, "\n"); + 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, "\n"); #ifdef HAVE_PCAP_REMOTE - fprintf(output, "\nRPCAP options:\n"); - fprintf(output, " -r don't ignore own RPCAP traffic in capture\n"); - fprintf(output, " -u use UDP for RPCAP data transfer\n"); - fprintf(output, " -A : use RPCAP password authentication\n"); + fprintf(output, "\nRPCAP options:\n"); + fprintf(output, " -r don't ignore own RPCAP traffic in capture\n"); + fprintf(output, " -u use UDP for RPCAP data transfer\n"); + fprintf(output, " -A : use RPCAP password authentication\n"); #ifdef HAVE_PCAP_SETSAMPLING - fprintf(output, " -m use packet sampling\n"); - fprintf(output, " count:NUM - capture one packet of every NUM\n"); - fprintf(output, " timer:NUM - capture no more than 1 packet in NUM ms\n"); + fprintf(output, " -m use packet sampling\n"); + fprintf(output, " count:NUM - capture one packet of every NUM\n"); + fprintf(output, " timer:NUM - capture no more than 1 packet in NUM ms\n"); #endif #endif - fprintf(output, "Stop conditions:\n"); - fprintf(output, " -c stop after n packets (def: infinite)\n"); - fprintf(output, " -a ... duration:NUM - stop after NUM seconds\n"); - fprintf(output, " filesize:NUM - stop this file after NUM KB\n"); - fprintf(output, " files:NUM - stop after NUM files\n"); - /*fprintf(output, "\n");*/ - fprintf(output, "Output (files):\n"); - fprintf(output, " -w name of file to save (def: tempfile)\n"); - fprintf(output, " -g enable group read access on the output file(s)\n"); - fprintf(output, " -b ... duration:NUM - switch to next file after NUM secs\n"); - fprintf(output, " filesize:NUM - switch to next file after NUM KB\n"); - fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n"); - 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"); - fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcap\n"); - fprintf(output, "\"Capture network packets from interface eth0 until 60s passed into output.pcap\"\n"); - fprintf(output, "\n"); - fprintf(output, "Use Ctrl-C to stop capturing at any time.\n"); + fprintf(output, "Stop conditions:\n"); + fprintf(output, " -c stop after n packets (def: infinite)\n"); + fprintf(output, " -a ... duration:NUM - stop after NUM seconds\n"); + fprintf(output, " filesize:NUM - stop this file after NUM KB\n"); + fprintf(output, " files:NUM - stop after NUM files\n"); + /*fprintf(output, "\n");*/ + fprintf(output, "Output (files):\n"); + fprintf(output, " -w name of file to save (def: tempfile)\n"); + fprintf(output, " -g enable group read access on the output file(s)\n"); + fprintf(output, " -b ... duration:NUM - switch to next file after NUM secs\n"); + fprintf(output, " filesize:NUM - switch to next file after NUM KB\n"); + fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n"); + 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"); + fprintf(output, "Example: dumpcap -i eth0 -a duration:60 -w output.pcap\n"); + fprintf(output, "\"Capture network packets from interface eth0 until 60s passed into output.pcap\"\n"); + fprintf(output, "\n"); + fprintf(output, "Use Ctrl-C to stop capturing at any time.\n"); } static void show_version(GString *comp_info_str, GString *runtime_info_str) { - - printf( + printf( "Dumpcap " VERSION "%s\n" "\n" "%s\n" @@ -429,17 +427,17 @@ show_version(GString *comp_info_str, GString *runtime_info_str) void vfprintf_stderr(const char *fmt, va_list ap) { - vfprintf(stderr, fmt, ap); + vfprintf(stderr, fmt, ap); } void fprintf_stderr(const char *fmt, ...) { - va_list ap; + va_list ap; - va_start(ap, fmt); - vfprintf_stderr(fmt, ap); - va_end(ap); + va_start(ap, fmt); + vfprintf_stderr(fmt, ap); + va_end(ap); } /* @@ -448,23 +446,23 @@ fprintf_stderr(const char *fmt, ...) void cmdarg_err(const char *fmt, ...) { - va_list ap; + va_list ap; - if(capture_child) { - gchar *msg; - /* Generate a 'special format' message back to parent */ - va_start(ap, fmt); - msg = g_strdup_vprintf(fmt, ap); - sync_pipe_errmsg_to_parent(2, msg, ""); - g_free(msg); - va_end(ap); - } else { - va_start(ap, fmt); - fprintf(stderr, "dumpcap: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - } + if(capture_child) { + gchar *msg; + /* Generate a 'special format' message back to parent */ + va_start(ap, fmt); + msg = g_strdup_vprintf(fmt, ap); + sync_pipe_errmsg_to_parent(2, msg, ""); + g_free(msg); + va_end(ap); + } else { + va_start(ap, fmt); + fprintf(stderr, "dumpcap: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + } } /* @@ -473,21 +471,21 @@ cmdarg_err(const char *fmt, ...) void cmdarg_err_cont(const char *fmt, ...) { - va_list ap; + va_list ap; - if(capture_child) { - gchar *msg; - va_start(ap, fmt); - msg = g_strdup_vprintf(fmt, ap); - sync_pipe_errmsg_to_parent(2, msg, ""); - g_free(msg); - va_end(ap); - } else { - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - } + if(capture_child) { + gchar *msg; + va_start(ap, fmt); + msg = g_strdup_vprintf(fmt, ap); + sync_pipe_errmsg_to_parent(2, msg, ""); + g_free(msg); + va_end(ap); + } else { + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + } } #ifdef HAVE_LIBCAP @@ -527,90 +525,90 @@ static pcap_t * open_capture_device(capture_options *capture_opts, char (*open_err_str)[PCAP_ERRBUF_SIZE]) { - pcap_t *pcap_h; + pcap_t *pcap_h; #ifdef HAVE_PCAP_CREATE - int err; + int err; #endif #ifdef HAVE_PCAP_REMOTE - struct pcap_rmtauth auth; + 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'; + /* 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(). + * 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); + 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), sizeof *open_err_str); - else - g_strlcpy(*open_err_str, pcap_statustostr(err), sizeof *open_err_str); - pcap_close(pcap_h); - pcap_h = NULL; - } + 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), sizeof *open_err_str); + else + g_strlcpy(*open_err_str, pcap_statustostr(err), sizeof *open_err_str); + 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 } -#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) */ + /* 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(); + relinquish_special_privs_perm(); #else - relinquish_all_capabilities(); + relinquish_all_capabilities(); #endif - return pcap_h; + return pcap_h; } static void @@ -624,45 +622,45 @@ get_capture_device_open_failure_messages(const char *open_err_str, char *secondary_errmsg, size_t secondary_errmsg_len) { - const char *libpcap_warn; - static const char ppamsg[] = "can't find PPA for "; + 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); + /* 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); + 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", - iface); + 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", + iface); #endif /* _WIN32 */ } @@ -672,113 +670,113 @@ set_pcap_linktype(pcap_t *pcap_h, capture_options *capture_opts, char *errmsg, size_t errmsg_len, char *secondary_errmsg, size_t secondary_errmsg_len) { - char *set_linktype_err_str; + char *set_linktype_err_str; - if (capture_opts->linktype == -1) - return TRUE; /* just use the default */ + if (capture_opts->linktype == -1) + return TRUE; /* just use the default */ #ifdef HAVE_PCAP_SET_DATALINK - if (pcap_set_datalink(pcap_h, capture_opts->linktype) == 0) - return TRUE; /* no error */ - set_linktype_err_str = pcap_geterr(pcap_h); + if (pcap_set_datalink(pcap_h, capture_opts->linktype) == 0) + return TRUE; /* no error */ + set_linktype_err_str = pcap_geterr(pcap_h); #else - /* Let them set it to the type it is; reject any other request. */ - if (get_pcap_linktype(pcap_h, capture_opts->iface) == capture_opts->linktype) - return TRUE; /* no error */ - set_linktype_err_str = - "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(pcap_h, capture_opts->iface) == capture_opts->linktype) + return TRUE; /* no error */ + set_linktype_err_str = + "That DLT isn't one of the DLTs supported by this device"; #endif - g_snprintf(errmsg, (gulong) errmsg_len, "Unable to set data link type (%s).", - set_linktype_err_str); - /* - * If the error isn't "XXX is not one of the DLTs supported by this device", - * tell the user to tell the Wireshark developers about it. - */ - if (strstr(set_linktype_err_str, "is not one of the DLTs supported by this device") == NULL) - g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, please_report); - else - secondary_errmsg[0] = '\0'; - return FALSE; + g_snprintf(errmsg, (gulong) errmsg_len, "Unable to set data link type (%s).", + set_linktype_err_str); + /* + * If the error isn't "XXX is not one of the DLTs supported by this device", + * tell the user to tell the Wireshark developers about it. + */ + if (strstr(set_linktype_err_str, "is not one of the DLTs supported by this device") == NULL) + g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, please_report); + else + secondary_errmsg[0] = '\0'; + return FALSE; } static gboolean compile_capture_filter(const char *iface, pcap_t *pcap_h, struct bpf_program *fcode, char *cfilter) { - bpf_u_int32 netnum, netmask; - gchar lookup_net_err_str[PCAP_ERRBUF_SIZE]; + 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; + 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; } #ifdef HAVE_BPF_IMAGE 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_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); - if (pcap_h == NULL) { - /* Open failed; get messages */ - get_capture_device_open_failure_messages(open_err_str, - capture_opts->iface, - errmsg, sizeof errmsg, - secondary_errmsg, - sizeof secondary_errmsg); - /* And report them */ - report_capture_error(errmsg, secondary_errmsg); - return FALSE; - } + pcap_h = open_capture_device(capture_opts, &open_err_str); + if (pcap_h == NULL) { + /* Open failed; get messages */ + get_capture_device_open_failure_messages(open_err_str, + capture_opts->iface, + errmsg, sizeof errmsg, + secondary_errmsg, + sizeof secondary_errmsg); + /* And report them */ + report_capture_error(errmsg, secondary_errmsg); + return FALSE; + } - /* Set the link-layer type. */ - if (!set_pcap_linktype(pcap_h, capture_opts, errmsg, sizeof errmsg, - secondary_errmsg, sizeof secondary_errmsg)) { + /* Set the link-layer type. */ + if (!set_pcap_linktype(pcap_h, capture_opts, errmsg, sizeof errmsg, + secondary_errmsg, sizeof secondary_errmsg)) { + pcap_close(pcap_h); + 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)) { + pcap_close(pcap_h); + report_cfilter_error(capture_opts->cfilter, errmsg); + return FALSE; + } pcap_close(pcap_h); - 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)) { - pcap_close(pcap_h); - 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); + } - 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; - /* 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; + for (i = 0; i < fcode.bf_len; insn++, i++) + printf("%s\n", bpf_image(insn, i)); + return TRUE; } #endif @@ -798,7 +796,7 @@ show_filter_code(capture_options *capture_opts) GList * capture_interface_list(int *err, char **err_str) { - return get_interface_list(err, err_str); + return get_interface_list(err, err_str); } /* @@ -809,135 +807,135 @@ capture_interface_list(int *err, char **err_str) static int get_pcap_linktype(pcap_t *pch, const char *devname #ifndef _AIX - _U_ + _U_ #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? - */ + /* + * 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; + /* + * 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; + /* 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; + } } - } 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; + 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_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 = (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; } /* @@ -946,7 +944,7 @@ create_data_link_info(int dlt) static if_capabilities_t * get_if_capabilities(const char *devname, gboolean monitor_mode #ifndef HAVE_PCAP_CREATE - _U_ + _U_ #endif , char **err_str) { @@ -1357,16 +1355,16 @@ capture_cleanup_handler(int signum _U_) static void report_capture_count(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, "Packets captured: %u\n", global_ld.packet_count); - /* stderr could be line buffered */ - fflush(stderr); + /* 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, "Packets captured: %u\n", global_ld.packet_count); + /* stderr could be line buffered */ + fflush(stderr); + } } - } } @@ -1374,41 +1372,42 @@ report_capture_count(void) static void report_counts_for_siginfo(void) { - report_capture_count(); - infoprint = FALSE; /* we just reported it */ + report_capture_count(); + infoprint = FALSE; /* we just reported it */ } static void report_counts_siginfo(int signum _U_) { - int sav_errno = errno; + 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_for_siginfo(); - errno = sav_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_for_siginfo(); + errno = sav_errno; } #endif /* SIGINFO */ -static void exit_main(int status) +static void +exit_main(int status) { #ifdef _WIN32 - /* Shutdown windows sockets */ - WSACleanup(); + /* Shutdown windows sockets */ + WSACleanup(); - /* can be helpful for debugging */ + /* can be helpful for debugging */ #ifdef DEBUG_DUMPCAP - printf("Press any key\n"); - _getch(); + printf("Press any key\n"); + _getch(); #endif #endif /* _WIN32 */ - exit(status); + exit(status); } #ifdef HAVE_LIBCAP @@ -1469,30 +1468,30 @@ relinquish_privs_except_capture(void) static void cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcaprec_hdr *rechdr) { - if (byte_swapped) { - /* Byte-swap the record header fields. */ - rechdr->ts_sec = BSWAP32(rechdr->ts_sec); - rechdr->ts_usec = BSWAP32(rechdr->ts_usec); - rechdr->incl_len = BSWAP32(rechdr->incl_len); - rechdr->orig_len = BSWAP32(rechdr->orig_len); - } + if (byte_swapped) { + /* Byte-swap the record header fields. */ + rechdr->ts_sec = BSWAP32(rechdr->ts_sec); + rechdr->ts_usec = BSWAP32(rechdr->ts_usec); + rechdr->incl_len = BSWAP32(rechdr->incl_len); + rechdr->orig_len = BSWAP32(rechdr->orig_len); + } - /* In file format version 2.3, the "incl_len" and "orig_len" fields were - swapped, in order to match the BPF header layout. + /* In file format version 2.3, the "incl_len" and "orig_len" fields were + swapped, in order to match the BPF header layout. - Unfortunately, some files were, according to a comment in the "libpcap" - source, written with version 2.3 in their headers but without the - interchanged fields, so if "incl_len" is greater than "orig_len" - which - would make no sense - we assume that we need to swap them. */ - if (hdr->version_major == 2 && - (hdr->version_minor < 3 || - (hdr->version_minor == 3 && rechdr->incl_len > rechdr->orig_len))) { - guint32 temp; + Unfortunately, some files were, according to a comment in the "libpcap" + source, written with version 2.3 in their headers but without the + interchanged fields, so if "incl_len" is greater than "orig_len" - which + would make no sense - we assume that we need to swap them. */ + if (hdr->version_major == 2 && + (hdr->version_minor < 3 || + (hdr->version_minor == 3 && rechdr->incl_len > rechdr->orig_len))) { + guint32 temp; - temp = rechdr->orig_len; - rechdr->orig_len = rechdr->incl_len; - rechdr->incl_len = temp; - } + temp = rechdr->orig_len; + rechdr->orig_len = rechdr->incl_len; + rechdr->incl_len = temp; + } } #ifdef USE_THREADS @@ -1512,7 +1511,8 @@ cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcapr * we can let cap_pipe_read run independently, queuing up multiple reads * for the main thread (and possibly get rid of cap_pipe_read_mtx). */ -static void *cap_pipe_read(void *ld_ptr) { +static void *cap_pipe_read(void *ld_ptr) +{ loop_data *ld = (loop_data *)ld_ptr; int bytes_read; #ifdef _WIN32 @@ -1588,23 +1588,24 @@ static void *cap_pipe_read(void *ld_ptr) { * the string cap_pipe_err_str should be used instead of errno. */ static int -cap_pipe_select(int pipe_fd) { - fd_set rfds; - struct timeval timeout; - int sel_ret; +cap_pipe_select(int pipe_fd) +{ + fd_set rfds; + struct timeval timeout; + int sel_ret; - cap_pipe_err_str = "Unknown error"; + cap_pipe_err_str = "Unknown error"; - FD_ZERO(&rfds); - FD_SET(pipe_fd, &rfds); + FD_ZERO(&rfds); + FD_SET(pipe_fd, &rfds); - timeout.tv_sec = PIPE_READ_TIMEOUT / 1000000; - timeout.tv_usec = PIPE_READ_TIMEOUT % 1000000; + timeout.tv_sec = PIPE_READ_TIMEOUT / 1000000; + timeout.tv_usec = PIPE_READ_TIMEOUT % 1000000; - sel_ret = select(pipe_fd+1, &rfds, NULL, NULL, &timeout); - if (sel_ret < 0) - cap_pipe_err_str = strerror(errno); - return sel_ret; + sel_ret = select(pipe_fd+1, &rfds, NULL, NULL, &timeout); + if (sel_ret < 0) + cap_pipe_err_str = strerror(errno); + return sel_ret; } @@ -1620,326 +1621,326 @@ cap_pipe_open_live(char *pipename, struct pcap_hdr *hdr, loop_data *ld, char *errmsg, int errmsgl) { #ifndef _WIN32 - struct stat pipe_stat; - struct sockaddr_un sa; - int sel_ret; - int b; - unsigned int bytes_read; - int fd; + struct stat pipe_stat; + struct sockaddr_un sa; + int sel_ret; + int b; + unsigned int bytes_read; + int fd; #else /* _WIN32 */ #if 1 - char *pncopy, *pos; - wchar_t *err_str; + char *pncopy, *pos; + wchar_t *err_str; #endif #endif - guint32 magic = 0; + guint32 magic = 0; #ifndef _WIN32 - ld->cap_pipe_fd = -1; + ld->cap_pipe_fd = -1; #else - ld->cap_pipe_h = INVALID_HANDLE_VALUE; + ld->cap_pipe_h = INVALID_HANDLE_VALUE; #endif - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: %s", pipename); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: %s", pipename); - /* - * XXX - this blocks until a pcap per-file header has been written to - * the pipe, so it could block indefinitely. - */ - if (strcmp(pipename, "-") == 0) { + /* + * XXX - this blocks until a pcap per-file header has been written to + * the pipe, so it could block indefinitely. + */ + if (strcmp(pipename, "-") == 0) { #ifndef _WIN32 - fd = 0; /* read from stdin */ + fd = 0; /* read from stdin */ #else /* _WIN32 */ - ld->cap_pipe_h = GetStdHandle(STD_INPUT_HANDLE); + ld->cap_pipe_h = GetStdHandle(STD_INPUT_HANDLE); #endif /* _WIN32 */ - } else { -#ifndef _WIN32 - if (ws_stat(pipename, &pipe_stat) < 0) { - if (errno == ENOENT || errno == ENOTDIR) - ld->cap_pipe_err = PIPNEXIST; - else { - g_snprintf(errmsg, errmsgl, - "The capture session could not be initiated " - "due to error getting information on pipe/socket: %s", strerror(errno)); - ld->cap_pipe_err = PIPERR; - } - return; - } - if (S_ISFIFO(pipe_stat.st_mode)) { - fd = ws_open(pipename, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */); - if (fd == -1) { - g_snprintf(errmsg, errmsgl, - "The capture session could not be initiated " - "due to error on pipe open: %s", strerror(errno)); - ld->cap_pipe_err = PIPERR; - return; - } - } else if (S_ISSOCK(pipe_stat.st_mode)) { - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) { - g_snprintf(errmsg, errmsgl, - "The capture session could not be initiated " - "due to error on socket create: %s", strerror(errno)); - ld->cap_pipe_err = PIPERR; - return; - } - sa.sun_family = AF_UNIX; - /* - * The Single UNIX Specification says: - * - * The size of sun_path has intentionally been left undefined. - * This is because different implementations use different sizes. - * For example, 4.3 BSD uses a size of 108, and 4.4 BSD uses a size - * of 104. Since most implementations originate from BSD versions, - * the size is typically in the range 92 to 108. - * - * Applications should not assume a particular length for sun_path - * or assume that it can hold {_POSIX_PATH_MAX} bytes (256). - * - * It also says - * - * The header shall define the sockaddr_un structure, - * which shall include at least the following members: - * - * sa_family_t sun_family Address family. - * char sun_path[] Socket pathname. - * - * so we assume that it's an array, with a specified size, - * and that the size reflects the maximum path length. - */ - if (g_strlcpy(sa.sun_path, pipename, sizeof sa.sun_path) > sizeof sa.sun_path) { - /* Path name too long */ - g_snprintf(errmsg, errmsgl, - "The capture session coud not be initiated " - "due to error on socket connect: Path name too long"); - ld->cap_pipe_err = PIPERR; - return; - } - b = connect(fd, (struct sockaddr *)&sa, sizeof sa); - if (b == -1) { - g_snprintf(errmsg, errmsgl, - "The capture session coud not be initiated " - "due to error on socket connect: %s", strerror(errno)); - ld->cap_pipe_err = PIPERR; - return; - } } else { - if (S_ISCHR(pipe_stat.st_mode)) { - /* - * Assume the user specified an interface on a system where - * interfaces are in /dev. Pretend we haven't seen it. - */ - ld->cap_pipe_err = PIPNEXIST; - } else - { - g_snprintf(errmsg, errmsgl, - "The capture session could not be initiated because\n" - "\"%s\" is neither an interface nor a socket nor a pipe", pipename); - ld->cap_pipe_err = PIPERR; - } - return; - } +#ifndef _WIN32 + if (ws_stat(pipename, &pipe_stat) < 0) { + if (errno == ENOENT || errno == ENOTDIR) + ld->cap_pipe_err = PIPNEXIST; + else { + g_snprintf(errmsg, errmsgl, + "The capture session could not be initiated " + "due to error getting information on pipe/socket: %s", strerror(errno)); + ld->cap_pipe_err = PIPERR; + } + return; + } + if (S_ISFIFO(pipe_stat.st_mode)) { + fd = ws_open(pipename, O_RDONLY | O_NONBLOCK, 0000 /* no creation so don't matter */); + if (fd == -1) { + g_snprintf(errmsg, errmsgl, + "The capture session could not be initiated " + "due to error on pipe open: %s", strerror(errno)); + ld->cap_pipe_err = PIPERR; + return; + } + } else if (S_ISSOCK(pipe_stat.st_mode)) { + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) { + g_snprintf(errmsg, errmsgl, + "The capture session could not be initiated " + "due to error on socket create: %s", strerror(errno)); + ld->cap_pipe_err = PIPERR; + return; + } + sa.sun_family = AF_UNIX; + /* + * The Single UNIX Specification says: + * + * The size of sun_path has intentionally been left undefined. + * This is because different implementations use different sizes. + * For example, 4.3 BSD uses a size of 108, and 4.4 BSD uses a size + * of 104. Since most implementations originate from BSD versions, + * the size is typically in the range 92 to 108. + * + * Applications should not assume a particular length for sun_path + * or assume that it can hold {_POSIX_PATH_MAX} bytes (256). + * + * It also says + * + * The header shall define the sockaddr_un structure, + * which shall include at least the following members: + * + * sa_family_t sun_family Address family. + * char sun_path[] Socket pathname. + * + * so we assume that it's an array, with a specified size, + * and that the size reflects the maximum path length. + */ + if (g_strlcpy(sa.sun_path, pipename, sizeof sa.sun_path) > sizeof sa.sun_path) { + /* Path name too long */ + g_snprintf(errmsg, errmsgl, + "The capture session coud not be initiated " + "due to error on socket connect: Path name too long"); + ld->cap_pipe_err = PIPERR; + return; + } + b = connect(fd, (struct sockaddr *)&sa, sizeof sa); + if (b == -1) { + g_snprintf(errmsg, errmsgl, + "The capture session coud not be initiated " + "due to error on socket connect: %s", strerror(errno)); + ld->cap_pipe_err = PIPERR; + return; + } + } else { + if (S_ISCHR(pipe_stat.st_mode)) { + /* + * Assume the user specified an interface on a system where + * interfaces are in /dev. Pretend we haven't seen it. + */ + ld->cap_pipe_err = PIPNEXIST; + } else + { + g_snprintf(errmsg, errmsgl, + "The capture session could not be initiated because\n" + "\"%s\" is neither an interface nor a socket nor a pipe", pipename); + ld->cap_pipe_err = PIPERR; + } + return; + } #else /* _WIN32 */ #define PIPE_STR "\\pipe\\" - /* Under Windows, named pipes _must_ have the form - * "\\\pipe\". may be "." for localhost. - */ - pncopy = g_strdup(pipename); - if ( (pos=strstr(pncopy, "\\\\")) == pncopy) { - pos = strchr(pncopy + 3, '\\'); - if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0) - pos = NULL; - } + /* Under Windows, named pipes _must_ have the form + * "\\\pipe\". may be "." for localhost. + */ + pncopy = g_strdup(pipename); + if ( (pos=strstr(pncopy, "\\\\")) == pncopy) { + pos = strchr(pncopy + 3, '\\'); + if (pos && g_ascii_strncasecmp(pos, PIPE_STR, strlen(PIPE_STR)) != 0) + pos = NULL; + } - g_free(pncopy); + g_free(pncopy); - if (!pos) { - g_snprintf(errmsg, errmsgl, - "The capture session could not be initiated because\n" - "\"%s\" is neither an interface nor a pipe", pipename); - ld->cap_pipe_err = PIPNEXIST; - return; - } + if (!pos) { + g_snprintf(errmsg, errmsgl, + "The capture session could not be initiated because\n" + "\"%s\" is neither an interface nor a pipe", pipename); + ld->cap_pipe_err = PIPNEXIST; + return; + } - /* Wait for the pipe to appear */ - while (1) { - ld->cap_pipe_h = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL, - OPEN_EXISTING, 0, NULL); + /* Wait for the pipe to appear */ + while (1) { + ld->cap_pipe_h = CreateFile(utf_8to16(pipename), GENERIC_READ, 0, NULL, + OPEN_EXISTING, 0, NULL); - if (ld->cap_pipe_h != INVALID_HANDLE_VALUE) - break; + if (ld->cap_pipe_h != INVALID_HANDLE_VALUE) + break; - if (GetLastError() != ERROR_PIPE_BUSY) { - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); - g_snprintf(errmsg, errmsgl, - "The capture session on \"%s\" could not be started " - "due to error on pipe open: %s (error %d)", - pipename, utf_16to8(err_str), GetLastError()); - LocalFree(err_str); - ld->cap_pipe_err = PIPERR; - return; - } + if (GetLastError() != ERROR_PIPE_BUSY) { + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); + g_snprintf(errmsg, errmsgl, + "The capture session on \"%s\" could not be started " + "due to error on pipe open: %s (error %d)", + pipename, utf_16to8(err_str), GetLastError()); + LocalFree(err_str); + ld->cap_pipe_err = PIPERR; + return; + } - if (!WaitNamedPipe(utf_8to16(pipename), 30 * 1000)) { - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); - g_snprintf(errmsg, errmsgl, - "The capture session on \"%s\" timed out during " - "pipe open: %s (error %d)", - pipename, utf_16to8(err_str), GetLastError()); - LocalFree(err_str); - ld->cap_pipe_err = PIPERR; - return; - } - } + if (!WaitNamedPipe(utf_8to16(pipename), 30 * 1000)) { + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); + g_snprintf(errmsg, errmsgl, + "The capture session on \"%s\" timed out during " + "pipe open: %s (error %d)", + pipename, utf_16to8(err_str), GetLastError()); + LocalFree(err_str); + ld->cap_pipe_err = PIPERR; + return; + } + } #endif /* _WIN32 */ - } + } - ld->from_cap_pipe = TRUE; + ld->from_cap_pipe = TRUE; #ifndef USE_THREADS - /* read the pcap header */ - bytes_read = 0; - while (bytes_read < sizeof magic) { - sel_ret = cap_pipe_select(fd); - if (sel_ret < 0) { - g_snprintf(errmsg, errmsgl, - "Unexpected error from select: %s", strerror(errno)); - goto error; - } else if (sel_ret > 0) { - b = read(fd, ((char *)&magic)+bytes_read, sizeof magic-bytes_read); - if (b <= 0) { - if (b == 0) - g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open"); - else - g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s", - strerror(errno)); - goto error; - } - bytes_read += b; + /* read the pcap header */ + bytes_read = 0; + while (bytes_read < sizeof magic) { + sel_ret = cap_pipe_select(fd); + if (sel_ret < 0) { + g_snprintf(errmsg, errmsgl, + "Unexpected error from select: %s", strerror(errno)); + goto error; + } else if (sel_ret > 0) { + b = read(fd, ((char *)&magic)+bytes_read, sizeof magic-bytes_read); + if (b <= 0) { + if (b == 0) + g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open"); + else + g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s", + strerror(errno)); + goto error; + } + bytes_read += b; + } } - } #else /* USE_THREADS */ - g_thread_create(&cap_pipe_read, ld, FALSE, NULL); + g_thread_create(&cap_pipe_read, ld, FALSE, NULL); - ld->cap_pipe_buf = (char *) &magic; - ld->cap_pipe_bytes_read = 0; - ld->cap_pipe_bytes_to_read = sizeof(magic); - /* We don't have to worry about cap_pipe_read_mtx here */ - g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); - g_async_queue_pop(cap_pipe_done_q); - if (ld->cap_pipe_bytes_read <= 0) { - if (ld->cap_pipe_bytes_read == 0) - g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open"); - else - g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s", - strerror(errno)); - goto error; - } + ld->cap_pipe_buf = (char *) &magic; + ld->cap_pipe_bytes_read = 0; + ld->cap_pipe_bytes_to_read = sizeof(magic); + /* We don't have to worry about cap_pipe_read_mtx here */ + g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); + g_async_queue_pop(cap_pipe_done_q); + if (ld->cap_pipe_bytes_read <= 0) { + if (ld->cap_pipe_bytes_read == 0) + g_snprintf(errmsg, errmsgl, "End of file on pipe magic during open"); + else + g_snprintf(errmsg, errmsgl, "Error on pipe magic during open: %s", + strerror(errno)); + goto error; + } #endif /* USE_THREADS */ - switch (magic) { - case PCAP_MAGIC: - /* Host that wrote it has our byte order, and was running - a program using either standard or ss990417 libpcap. */ - ld->cap_pipe_byte_swapped = FALSE; - ld->cap_pipe_modified = FALSE; - break; - case PCAP_MODIFIED_MAGIC: - /* Host that wrote it has our byte order, but was running - a program using either ss990915 or ss991029 libpcap. */ - ld->cap_pipe_byte_swapped = FALSE; - ld->cap_pipe_modified = TRUE; - break; - case PCAP_SWAPPED_MAGIC: - /* Host that wrote it has a byte order opposite to ours, - and was running a program using either standard or - ss990417 libpcap. */ - ld->cap_pipe_byte_swapped = TRUE; - ld->cap_pipe_modified = FALSE; - break; - case PCAP_SWAPPED_MODIFIED_MAGIC: - /* Host that wrote it out has a byte order opposite to - ours, and was running a program using either ss990915 - or ss991029 libpcap. */ - ld->cap_pipe_byte_swapped = TRUE; - ld->cap_pipe_modified = TRUE; - break; - default: - /* Not a "libpcap" type we know about. */ - g_snprintf(errmsg, errmsgl, "Unrecognized libpcap format"); - goto error; - } + switch (magic) { + case PCAP_MAGIC: + /* Host that wrote it has our byte order, and was running + a program using either standard or ss990417 libpcap. */ + ld->cap_pipe_byte_swapped = FALSE; + ld->cap_pipe_modified = FALSE; + break; + case PCAP_MODIFIED_MAGIC: + /* Host that wrote it has our byte order, but was running + a program using either ss990915 or ss991029 libpcap. */ + ld->cap_pipe_byte_swapped = FALSE; + ld->cap_pipe_modified = TRUE; + break; + case PCAP_SWAPPED_MAGIC: + /* Host that wrote it has a byte order opposite to ours, + and was running a program using either standard or + ss990417 libpcap. */ + ld->cap_pipe_byte_swapped = TRUE; + ld->cap_pipe_modified = FALSE; + break; + case PCAP_SWAPPED_MODIFIED_MAGIC: + /* Host that wrote it out has a byte order opposite to + ours, and was running a program using either ss990915 + or ss991029 libpcap. */ + ld->cap_pipe_byte_swapped = TRUE; + ld->cap_pipe_modified = TRUE; + break; + default: + /* Not a "libpcap" type we know about. */ + g_snprintf(errmsg, errmsgl, "Unrecognized libpcap format"); + goto error; + } #ifndef USE_THREADS - /* Read the rest of the header */ - bytes_read = 0; - while (bytes_read < sizeof(struct pcap_hdr)) { - sel_ret = cap_pipe_select(fd); - if (sel_ret < 0) { - g_snprintf(errmsg, errmsgl, - "Unexpected error from select: %s", strerror(errno)); - goto error; - } else if (sel_ret > 0) { - b = read(fd, ((char *)hdr)+bytes_read, - sizeof(struct pcap_hdr) - bytes_read); - if (b <= 0) { - if (b == 0) - g_snprintf(errmsg, errmsgl, "End of file on pipe header during open"); - else - g_snprintf(errmsg, errmsgl, "Error on pipe header during open: %s", - strerror(errno)); - goto error; - } - bytes_read += b; + /* Read the rest of the header */ + bytes_read = 0; + while (bytes_read < sizeof(struct pcap_hdr)) { + sel_ret = cap_pipe_select(fd); + if (sel_ret < 0) { + g_snprintf(errmsg, errmsgl, + "Unexpected error from select: %s", strerror(errno)); + goto error; + } else if (sel_ret > 0) { + b = read(fd, ((char *)hdr)+bytes_read, + sizeof(struct pcap_hdr) - bytes_read); + if (b <= 0) { + if (b == 0) + g_snprintf(errmsg, errmsgl, "End of file on pipe header during open"); + else + g_snprintf(errmsg, errmsgl, "Error on pipe header during open: %s", + strerror(errno)); + goto error; + } + bytes_read += b; + } } - } #else /* USE_THREADS */ - ld->cap_pipe_buf = (char *) hdr; - ld->cap_pipe_bytes_read = 0; - ld->cap_pipe_bytes_to_read = sizeof(struct pcap_hdr); - g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); - g_async_queue_pop(cap_pipe_done_q); - if (ld->cap_pipe_bytes_read <= 0) { - if (ld->cap_pipe_bytes_read == 0) - g_snprintf(errmsg, errmsgl, "End of file on pipe header during open"); - else - g_snprintf(errmsg, errmsgl, "Error on pipe header header during open: %s", - strerror(errno)); - goto error; - } + ld->cap_pipe_buf = (char *) hdr; + ld->cap_pipe_bytes_read = 0; + ld->cap_pipe_bytes_to_read = sizeof(struct pcap_hdr); + g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); + g_async_queue_pop(cap_pipe_done_q); + if (ld->cap_pipe_bytes_read <= 0) { + if (ld->cap_pipe_bytes_read == 0) + g_snprintf(errmsg, errmsgl, "End of file on pipe header during open"); + else + g_snprintf(errmsg, errmsgl, "Error on pipe header header during open: %s", + strerror(errno)); + goto error; + } #endif /* USE_THREADS */ - if (ld->cap_pipe_byte_swapped) { - /* Byte-swap the header fields about which we care. */ - hdr->version_major = BSWAP16(hdr->version_major); - hdr->version_minor = BSWAP16(hdr->version_minor); - hdr->snaplen = BSWAP32(hdr->snaplen); - hdr->network = BSWAP32(hdr->network); - } - ld->linktype = hdr->network; + if (ld->cap_pipe_byte_swapped) { + /* Byte-swap the header fields about which we care. */ + hdr->version_major = BSWAP16(hdr->version_major); + hdr->version_minor = BSWAP16(hdr->version_minor); + hdr->snaplen = BSWAP32(hdr->snaplen); + hdr->network = BSWAP32(hdr->network); + } + ld->linktype = hdr->network; - if (hdr->version_major < 2) { - g_snprintf(errmsg, errmsgl, "Unable to read old libpcap format"); - goto error; - } + if (hdr->version_major < 2) { + g_snprintf(errmsg, errmsgl, "Unable to read old libpcap format"); + goto error; + } - ld->cap_pipe_state = STATE_EXPECT_REC_HDR; - ld->cap_pipe_err = PIPOK; + ld->cap_pipe_state = STATE_EXPECT_REC_HDR; + ld->cap_pipe_err = PIPOK; #ifndef _WIN32 - ld->cap_pipe_fd = fd; + ld->cap_pipe_fd = fd; #endif - return; + return; error: - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: error %s", errmsg); - ld->cap_pipe_err = PIPERR; + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_open_live: error %s", errmsg); + ld->cap_pipe_err = PIPERR; #ifndef _WIN32 - ws_close(fd); - ld->cap_pipe_fd = -1; + ws_close(fd); + ld->cap_pipe_fd = -1; #endif - return; + return; } @@ -1949,183 +1950,183 @@ error: static int cap_pipe_dispatch(loop_data *ld, guchar *data, char *errmsg, int errmsgl) { - struct pcap_pkthdr phdr; - enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR, - PD_ERR } result; + struct pcap_pkthdr phdr; + enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR, + PD_ERR } result; #ifdef USE_THREADS - GTimeVal wait_time; - gpointer q_status; + GTimeVal wait_time; + gpointer q_status; #else - int b; + int b; #endif #ifdef _WIN32 - wchar_t *err_str; + wchar_t *err_str; #endif #ifdef LOG_CAPTURE_VERBOSE - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_dispatch"); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_dispatch"); #endif - switch (ld->cap_pipe_state) { + switch (ld->cap_pipe_state) { - case STATE_EXPECT_REC_HDR: + case STATE_EXPECT_REC_HDR: #ifdef USE_THREADS - if (g_mutex_trylock(cap_pipe_read_mtx)) { + if (g_mutex_trylock(cap_pipe_read_mtx)) { #endif - ld->cap_pipe_state = STATE_READ_REC_HDR; - ld->cap_pipe_bytes_to_read = ld->cap_pipe_modified ? - sizeof(struct pcaprec_modified_hdr) : sizeof(struct pcaprec_hdr); - ld->cap_pipe_bytes_read = 0; + ld->cap_pipe_state = STATE_READ_REC_HDR; + ld->cap_pipe_bytes_to_read = ld->cap_pipe_modified ? + sizeof(struct pcaprec_modified_hdr) : sizeof(struct pcaprec_hdr); + ld->cap_pipe_bytes_read = 0; #ifdef USE_THREADS - ld->cap_pipe_buf = (char *) &ld->cap_pipe_rechdr; - g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); - g_mutex_unlock(cap_pipe_read_mtx); - } + ld->cap_pipe_buf = (char *) &ld->cap_pipe_rechdr; + g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); + g_mutex_unlock(cap_pipe_read_mtx); + } #endif - /* Fall through */ + /* Fall through */ - case STATE_READ_REC_HDR: + case STATE_READ_REC_HDR: #ifndef USE_THREADS - b = read(ld->cap_pipe_fd, ((char *)&ld->cap_pipe_rechdr)+ld->cap_pipe_bytes_read, - ld->cap_pipe_bytes_to_read - ld->cap_pipe_bytes_read); - if (b <= 0) { - if (b == 0) - result = PD_PIPE_EOF; - else - result = PD_PIPE_ERR; - break; - } - ld->cap_pipe_bytes_read += b; + b = read(ld->cap_pipe_fd, ((char *)&ld->cap_pipe_rechdr)+ld->cap_pipe_bytes_read, + ld->cap_pipe_bytes_to_read - ld->cap_pipe_bytes_read); + if (b <= 0) { + if (b == 0) + result = PD_PIPE_EOF; + else + result = PD_PIPE_ERR; + break; + } + ld->cap_pipe_bytes_read += b; #else /* USE_THREADS */ - g_get_current_time(&wait_time); - g_time_val_add(&wait_time, PIPE_READ_TIMEOUT); - q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time); - if (ld->cap_pipe_err == PIPEOF) { - result = PD_PIPE_EOF; - break; - } else if (ld->cap_pipe_err == PIPERR) { - result = PD_PIPE_ERR; - break; - } - if (!q_status) { - return 0; - } + g_get_current_time(&wait_time); + g_time_val_add(&wait_time, PIPE_READ_TIMEOUT); + q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time); + if (ld->cap_pipe_err == PIPEOF) { + result = PD_PIPE_EOF; + break; + } else if (ld->cap_pipe_err == PIPERR) { + result = PD_PIPE_ERR; + break; + } + if (!q_status) { + return 0; + } #endif /* USE_THREADS */ - if ((ld->cap_pipe_bytes_read) < ld->cap_pipe_bytes_to_read) - return 0; - result = PD_REC_HDR_READ; - break; + if ((ld->cap_pipe_bytes_read) < ld->cap_pipe_bytes_to_read) + return 0; + result = PD_REC_HDR_READ; + break; - case STATE_EXPECT_DATA: + case STATE_EXPECT_DATA: #ifdef USE_THREADS - if (g_mutex_trylock(cap_pipe_read_mtx)) { + if (g_mutex_trylock(cap_pipe_read_mtx)) { #endif - ld->cap_pipe_state = STATE_READ_DATA; - ld->cap_pipe_bytes_to_read = ld->cap_pipe_rechdr.hdr.incl_len; - ld->cap_pipe_bytes_read = 0; + ld->cap_pipe_state = STATE_READ_DATA; + ld->cap_pipe_bytes_to_read = ld->cap_pipe_rechdr.hdr.incl_len; + ld->cap_pipe_bytes_read = 0; #ifdef USE_THREADS - ld->cap_pipe_buf = (char *) data; - g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); - g_mutex_unlock(cap_pipe_read_mtx); - } + ld->cap_pipe_buf = (char *) data; + g_async_queue_push(cap_pipe_pending_q, ld->cap_pipe_buf); + g_mutex_unlock(cap_pipe_read_mtx); + } #endif - /* Fall through */ + /* Fall through */ - case STATE_READ_DATA: + case STATE_READ_DATA: #ifndef USE_THREADS - b = read(ld->cap_pipe_fd, data+ld->cap_pipe_bytes_read, - ld->cap_pipe_bytes_to_read - ld->cap_pipe_bytes_read); - if (b <= 0) { - if (b == 0) - result = PD_PIPE_EOF; - else - result = PD_PIPE_ERR; - break; - } - ld->cap_pipe_bytes_read += b; + b = read(ld->cap_pipe_fd, data+ld->cap_pipe_bytes_read, + ld->cap_pipe_bytes_to_read - ld->cap_pipe_bytes_read); + if (b <= 0) { + if (b == 0) + result = PD_PIPE_EOF; + else + result = PD_PIPE_ERR; + break; + } + ld->cap_pipe_bytes_read += b; #else /* USE_THREADS */ - g_get_current_time(&wait_time); - g_time_val_add(&wait_time, PIPE_READ_TIMEOUT); - q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time); - if (ld->cap_pipe_err == PIPEOF) { - result = PD_PIPE_EOF; - break; - } else if (ld->cap_pipe_err == PIPERR) { - result = PD_PIPE_ERR; - break; - } - if (!q_status) { - return 0; - } + g_get_current_time(&wait_time); + g_time_val_add(&wait_time, PIPE_READ_TIMEOUT); + q_status = g_async_queue_timed_pop(cap_pipe_done_q, &wait_time); + if (ld->cap_pipe_err == PIPEOF) { + result = PD_PIPE_EOF; + break; + } else if (ld->cap_pipe_err == PIPERR) { + result = PD_PIPE_ERR; + break; + } + if (!q_status) { + return 0; + } #endif /* USE_THREADS */ - if ((ld->cap_pipe_bytes_read) < ld->cap_pipe_bytes_to_read) + if ((ld->cap_pipe_bytes_read) < ld->cap_pipe_bytes_to_read) + return 0; + result = PD_DATA_READ; + break; + + default: + g_snprintf(errmsg, errmsgl, "cap_pipe_dispatch: invalid state"); + result = PD_ERR; + + } /* switch (ld->cap_pipe_state) */ + + /* + * We've now read as much data as we were expecting, so process it. + */ + switch (result) { + + case PD_REC_HDR_READ: + /* We've read the header. Take care of byte order. */ + cap_pipe_adjust_header(ld->cap_pipe_byte_swapped, &ld->cap_pipe_hdr, + &ld->cap_pipe_rechdr.hdr); + if (ld->cap_pipe_rechdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) { + g_snprintf(errmsg, errmsgl, "Frame %u too long (%d bytes)", + ld->packet_count+1, ld->cap_pipe_rechdr.hdr.incl_len); + break; + } + ld->cap_pipe_state = STATE_EXPECT_DATA; return 0; - result = PD_DATA_READ; - break; - default: - g_snprintf(errmsg, errmsgl, "cap_pipe_dispatch: invalid state"); - result = PD_ERR; + case PD_DATA_READ: + /* Fill in a "struct pcap_pkthdr", and process the packet. */ + phdr.ts.tv_sec = ld->cap_pipe_rechdr.hdr.ts_sec; + phdr.ts.tv_usec = ld->cap_pipe_rechdr.hdr.ts_usec; + phdr.caplen = ld->cap_pipe_rechdr.hdr.incl_len; + phdr.len = ld->cap_pipe_rechdr.hdr.orig_len; - } /* switch (ld->cap_pipe_state) */ + capture_loop_packet_cb((u_char *)ld, &phdr, data); - /* - * We've now read as much data as we were expecting, so process it. - */ - switch (result) { + ld->cap_pipe_state = STATE_EXPECT_REC_HDR; + return 1; - case PD_REC_HDR_READ: - /* We've read the header. Take care of byte order. */ - cap_pipe_adjust_header(ld->cap_pipe_byte_swapped, &ld->cap_pipe_hdr, - &ld->cap_pipe_rechdr.hdr); - if (ld->cap_pipe_rechdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) { - g_snprintf(errmsg, errmsgl, "Frame %u too long (%d bytes)", - ld->packet_count+1, ld->cap_pipe_rechdr.hdr.incl_len); - break; - } - ld->cap_pipe_state = STATE_EXPECT_DATA; - return 0; + case PD_PIPE_EOF: + ld->cap_pipe_err = PIPEOF; + return -1; - case PD_DATA_READ: - /* Fill in a "struct pcap_pkthdr", and process the packet. */ - phdr.ts.tv_sec = ld->cap_pipe_rechdr.hdr.ts_sec; - phdr.ts.tv_usec = ld->cap_pipe_rechdr.hdr.ts_usec; - phdr.caplen = ld->cap_pipe_rechdr.hdr.incl_len; - phdr.len = ld->cap_pipe_rechdr.hdr.orig_len; - - capture_loop_packet_cb((u_char *)ld, &phdr, data); - - ld->cap_pipe_state = STATE_EXPECT_REC_HDR; - return 1; - - case PD_PIPE_EOF: - ld->cap_pipe_err = PIPEOF; - return -1; - - case PD_PIPE_ERR: + case PD_PIPE_ERR: #ifdef _WIN32 - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, - NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); - g_snprintf(errmsg, errmsgl, - "Error reading from pipe: %s (error %d)", - utf_16to8(err_str), GetLastError()); - LocalFree(err_str); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, GetLastError(), 0, (LPTSTR) &err_str, 0, NULL); + g_snprintf(errmsg, errmsgl, + "Error reading from pipe: %s (error %d)", + utf_16to8(err_str), GetLastError()); + LocalFree(err_str); #else - g_snprintf(errmsg, errmsgl, "Error reading from pipe: %s", - strerror(errno)); + g_snprintf(errmsg, errmsgl, "Error reading from pipe: %s", + strerror(errno)); #endif - /* Fall through */ - case PD_ERR: - break; - } + /* Fall through */ + case PD_ERR: + break; + } - ld->cap_pipe_err = PIPERR; - /* Return here rather than inside the switch to prevent GCC warning */ - return -1; + ld->cap_pipe_err = PIPERR; + /* Return here rather than inside the switch to prevent GCC warning */ + return -1; } @@ -2136,96 +2137,96 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld, char *errmsg, size_t errmsg_len, char *secondary_errmsg, size_t secondary_errmsg_len) { - gchar open_err_str[PCAP_ERRBUF_SIZE]; - gchar *sync_msg_str; + gchar open_err_str[PCAP_ERRBUF_SIZE]; + gchar *sync_msg_str; #ifdef _WIN32 - int err; - gchar *sync_secondary_msg_str; - WORD wVersionRequested; - WSADATA wsaData; + int err; + gchar *sync_secondary_msg_str; + WORD wVersionRequested; + WSADATA wsaData; #endif - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_input : %s", capture_opts->iface); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_input : %s", capture_opts->iface); /* XXX - opening Winsock on tshark? */ - /* Initialize Windows Socket if we are in a WIN32 OS - This needs to be done before querying the interface for network/netmask */ + /* Initialize Windows Socket if we are in a WIN32 OS + This needs to be done before querying the interface for network/netmask */ #ifdef _WIN32 - /* XXX - do we really require 1.1 or earlier? - Are there any versions that support only 2.0 or higher? */ - wVersionRequested = MAKEWORD(1, 1); - err = WSAStartup(wVersionRequested, &wsaData); - if (err != 0) { - switch (err) { + /* XXX - do we really require 1.1 or earlier? + Are there any versions that support only 2.0 or higher? */ + wVersionRequested = MAKEWORD(1, 1); + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + switch (err) { - case WSASYSNOTREADY: - g_snprintf(errmsg, (gulong) errmsg_len, - "Couldn't initialize Windows Sockets: Network system not ready for network communication"); - break; + case WSASYSNOTREADY: + g_snprintf(errmsg, (gulong) errmsg_len, + "Couldn't initialize Windows Sockets: Network system not ready for network communication"); + break; - case WSAVERNOTSUPPORTED: - g_snprintf(errmsg, (gulong) errmsg_len, - "Couldn't initialize Windows Sockets: Windows Sockets version %u.%u not supported", - LOBYTE(wVersionRequested), HIBYTE(wVersionRequested)); - break; + case WSAVERNOTSUPPORTED: + g_snprintf(errmsg, (gulong) errmsg_len, + "Couldn't initialize Windows Sockets: Windows Sockets version %u.%u not supported", + LOBYTE(wVersionRequested), HIBYTE(wVersionRequested)); + break; - case WSAEINPROGRESS: - g_snprintf(errmsg, (gulong) errmsg_len, - "Couldn't initialize Windows Sockets: Blocking operation is in progress"); - break; + case WSAEINPROGRESS: + g_snprintf(errmsg, (gulong) errmsg_len, + "Couldn't initialize Windows Sockets: Blocking operation is in progress"); + break; - case WSAEPROCLIM: - g_snprintf(errmsg, (gulong) errmsg_len, - "Couldn't initialize Windows Sockets: Limit on the number of tasks supported by this WinSock implementation has been reached"); - break; + case WSAEPROCLIM: + g_snprintf(errmsg, (gulong) errmsg_len, + "Couldn't initialize Windows Sockets: Limit on the number of tasks supported by this WinSock implementation has been reached"); + break; - case WSAEFAULT: - g_snprintf(errmsg, (gulong) errmsg_len, - "Couldn't initialize Windows Sockets: Bad pointer passed to WSAStartup"); - break; + case WSAEFAULT: + g_snprintf(errmsg, (gulong) errmsg_len, + "Couldn't initialize Windows Sockets: Bad pointer passed to WSAStartup"); + break; - default: - g_snprintf(errmsg, (gulong) errmsg_len, - "Couldn't initialize Windows Sockets: error %d", err); - break; + default: + g_snprintf(errmsg, (gulong) errmsg_len, + "Couldn't initialize Windows Sockets: error %d", err); + break; + } + g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, please_report); + return FALSE; } - g_snprintf(secondary_errmsg, (gulong) secondary_errmsg_len, please_report); - return FALSE; - } #endif - ld->pcap_h = open_capture_device(capture_opts, &open_err_str); + ld->pcap_h = open_capture_device(capture_opts, &open_err_str); - if (ld->pcap_h != NULL) { - /* we've opened "iface" as a network device */ + if (ld->pcap_h != NULL) { + /* we've opened "iface" as a network device */ #ifdef _WIN32 - /* try to set the capture buffer size */ - 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 %dMB seems to be too high for your machine,\n" - "the default of 1MB will be used.\n" - "\n" - "Nonetheless, the capture is started.\n", - capture_opts->buffer_size); - report_capture_error("Couldn't set the capture buffer size!", - sync_secondary_msg_str); - g_free(sync_secondary_msg_str); - } + /* try to set the capture buffer size */ + 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 %dMB seems to be too high for your machine,\n" + "the default of 1MB will be used.\n" + "\n" + "Nonetheless, the capture is started.\n", + capture_opts->buffer_size); + report_capture_error("Couldn't set the capture buffer size!", + sync_secondary_msg_str); + g_free(sync_secondary_msg_str); + } #endif #if defined(HAVE_PCAP_REMOTE) && defined(HAVE_PCAP_SETSAMPLING) - if ((capture_opts->sampling_method != CAPTURE_SAMP_NONE) && - (strncmp (capture_opts->iface, "rpcap://", 8) == 0)) - { - struct pcap_samp *samp; - - if ((samp = pcap_setsampling(ld->pcap_h)) != NULL) + if ((capture_opts->sampling_method != CAPTURE_SAMP_NONE) && + (strncmp (capture_opts->iface, "rpcap://", 8) == 0)) { - switch (capture_opts->sampling_method) + struct pcap_samp *samp; + + if ((samp = pcap_setsampling(ld->pcap_h)) != NULL) { + switch (capture_opts->sampling_method) + { case CAPTURE_SAMP_BY_COUNT: samp->method = PCAP_SAMP_1_EVERY_N; break; @@ -2236,114 +2237,114 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld, default: sync_msg_str = g_strdup_printf( - "Unknown sampling method %d specified,\n" - "continue without packet sampling", - capture_opts->sampling_method); + "Unknown sampling method %d specified,\n" + "continue without packet sampling", + capture_opts->sampling_method); report_capture_error("Couldn't set the capture " - "sampling", sync_msg_str); + "sampling", sync_msg_str); g_free(sync_msg_str); + } + samp->value = capture_opts->sampling_param; + } + else + { + report_capture_error("Couldn't set the capture sampling", + "Cannot get packet sampling data structure"); } - samp->value = capture_opts->sampling_param; - } - else - { - report_capture_error("Couldn't set the capture sampling", - "Cannot get packet sampling data structure"); - } - } + } #endif - /* setting the data link type only works on real interfaces */ - if (!set_pcap_linktype(ld->pcap_h, capture_opts, errmsg, errmsg_len, - secondary_errmsg, secondary_errmsg_len)) - return FALSE; - ld->linktype = get_pcap_linktype(ld->pcap_h, capture_opts->iface); - } else { - /* We couldn't open "iface" as a network device. */ - /* Try to open it as a pipe */ - cap_pipe_open_live(capture_opts->iface, &ld->cap_pipe_hdr, ld, errmsg, (int) errmsg_len); + /* setting the data link type only works on real interfaces */ + if (!set_pcap_linktype(ld->pcap_h, capture_opts, errmsg, errmsg_len, + secondary_errmsg, secondary_errmsg_len)) + return FALSE; + ld->linktype = get_pcap_linktype(ld->pcap_h, capture_opts->iface); + } else { + /* We couldn't open "iface" as a network device. */ + /* Try to open it as a pipe */ + cap_pipe_open_live(capture_opts->iface, &ld->cap_pipe_hdr, ld, errmsg, (int) errmsg_len); #ifndef _WIN32 - if (ld->cap_pipe_fd == -1) { + if (ld->cap_pipe_fd == -1) #else - if (ld->cap_pipe_h == INVALID_HANDLE_VALUE) { + if (ld->cap_pipe_h == INVALID_HANDLE_VALUE) #endif - - if (ld->cap_pipe_err == PIPNEXIST) { - /* Pipe doesn't exist, so output message for interface */ - get_capture_device_open_failure_messages(open_err_str, - capture_opts->iface, - errmsg, - errmsg_len, - secondary_errmsg, - secondary_errmsg_len); - } - /* - * Else pipe (or file) does exist and cap_pipe_open_live() has - * filled in errmsg - */ - return FALSE; - } else - /* cap_pipe_open_live() succeeded; don't want - error message from pcap_open_live() */ - open_err_str[0] = '\0'; - } + { + if (ld->cap_pipe_err == PIPNEXIST) { + /* Pipe doesn't exist, so output message for interface */ + get_capture_device_open_failure_messages(open_err_str, + capture_opts->iface, + errmsg, + errmsg_len, + secondary_errmsg, + secondary_errmsg_len); + } + /* + * Else pipe (or file) does exist and cap_pipe_open_live() has + * filled in errmsg + */ + return FALSE; + } else + /* cap_pipe_open_live() succeeded; don't want + error message from pcap_open_live() */ + open_err_str[0] = '\0'; + } /* XXX - will this work for tshark? */ #ifdef MUST_DO_SELECT - if (!ld->from_cap_pipe) { + if (!ld->from_cap_pipe) { #ifdef HAVE_PCAP_GET_SELECTABLE_FD - ld->pcap_fd = pcap_get_selectable_fd(ld->pcap_h); + ld->pcap_fd = pcap_get_selectable_fd(ld->pcap_h); #else - ld->pcap_fd = pcap_fileno(ld->pcap_h); + ld->pcap_fd = pcap_fileno(ld->pcap_h); #endif - } + } #endif - /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()" - returned a warning; print it, but keep capturing. */ - if (open_err_str[0] != '\0') { - sync_msg_str = g_strdup_printf("%s.", open_err_str); - report_capture_error(sync_msg_str, ""); - g_free(sync_msg_str); - } + /* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()" + returned a warning; print it, but keep capturing. */ + if (open_err_str[0] != '\0') { + sync_msg_str = g_strdup_printf("%s.", open_err_str); + report_capture_error(sync_msg_str, ""); + g_free(sync_msg_str); + } - return TRUE; + return TRUE; } /* close the capture input file (pcap or capture pipe) */ -static void capture_loop_close_input(loop_data *ld) { +static void capture_loop_close_input(loop_data *ld) +{ + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input"); - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input"); - - /* if open, close the capture pipe "input file" */ + /* if open, close the capture pipe "input file" */ #ifndef _WIN32 - if (ld->cap_pipe_fd >= 0) { - g_assert(ld->from_cap_pipe); - ws_close(ld->cap_pipe_fd); - ld->cap_pipe_fd = 0; - } + if (ld->cap_pipe_fd >= 0) { + g_assert(ld->from_cap_pipe); + ws_close(ld->cap_pipe_fd); + ld->cap_pipe_fd = 0; + } #else - if (ld->cap_pipe_h != INVALID_HANDLE_VALUE) { - CloseHandle(ld->cap_pipe_h); - ld->cap_pipe_h = INVALID_HANDLE_VALUE; - } + if (ld->cap_pipe_h != INVALID_HANDLE_VALUE) { + CloseHandle(ld->cap_pipe_h); + ld->cap_pipe_h = INVALID_HANDLE_VALUE; + } #endif - /* if open, close the pcap "input file" */ - if(ld->pcap_h != NULL) { - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input: closing %p", (void *)ld->pcap_h); - g_assert(!ld->from_cap_pipe); - pcap_close(ld->pcap_h); - ld->pcap_h = NULL; - } + /* if open, close the pcap "input file" */ + if(ld->pcap_h != NULL) { + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input: closing %p", (void *)ld->pcap_h); + g_assert(!ld->from_cap_pipe); + pcap_close(ld->pcap_h); + ld->pcap_h = NULL; + } - ld->go = FALSE; + ld->go = FALSE; #ifdef _WIN32 - /* Shut down windows sockets */ - WSACleanup(); + /* Shut down windows sockets */ + WSACleanup(); #endif } @@ -2353,115 +2354,116 @@ static initfilter_status_t capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, gchar * iface, gchar * cfilter) { - struct bpf_program fcode; + struct bpf_program fcode; - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_filter: %s", cfilter); + 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 (!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. */ - return INITFILTER_BAD_FILTER; - } - if (pcap_setfilter(pcap_h, &fcode) < 0) { + /* capture filters only work on real interfaces */ + if (cfilter && !from_cap_pipe) { + /* A capture filter was specified; set it up. */ + 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. */ + return INITFILTER_BAD_FILTER; + } + if (pcap_setfilter(pcap_h, &fcode) < 0) { #ifdef HAVE_PCAP_FREECODE - pcap_freecode(&fcode); + pcap_freecode(&fcode); #endif - return INITFILTER_OTHER_ERROR; - } + return INITFILTER_OTHER_ERROR; + } #ifdef HAVE_PCAP_FREECODE - pcap_freecode(&fcode); + pcap_freecode(&fcode); #endif - } + } - return INITFILTER_NO_ERROR; + return INITFILTER_NO_ERROR; } /* set up to write to the already-opened capture output file/files */ static gboolean -capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len) { - int err; +capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *errmsg, int errmsg_len) +{ + int err; + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_output"); - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_output"); + /* get snaplen */ + if (ld->from_cap_pipe) { + ld->file_snaplen = ld->cap_pipe_hdr.snaplen; + } else + { + ld->file_snaplen = pcap_snapshot(ld->pcap_h); + } - /* get snaplen */ - if (ld->from_cap_pipe) { - ld->file_snaplen = ld->cap_pipe_hdr.snaplen; - } else - { - ld->file_snaplen = pcap_snapshot(ld->pcap_h); - } - - /* Set up to write to the capture file. */ - if (capture_opts->multi_files_on) { - ld->pdh = ringbuf_init_libpcap_fdopen(&err); - } else { - ld->pdh = libpcap_fdopen(ld->save_file_fd, &err); - } - if (ld->pdh) { - gboolean successful; - - 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(ld->pdh, appname, &ld->bytes_written, &err) && - libpcap_write_interface_description_block(ld->pdh, capture_opts->iface, capture_opts->cfilter, ld->linktype, ld->file_snaplen, &ld->bytes_written, &err); + /* Set up to write to the capture file. */ + if (capture_opts->multi_files_on) { + ld->pdh = ringbuf_init_libpcap_fdopen(&err); } else { - successful = libpcap_write_file_header(ld->pdh, ld->linktype, ld->file_snaplen, - &ld->bytes_written, &err); + ld->pdh = libpcap_fdopen(ld->save_file_fd, &err); } - if (!successful) { - fclose(ld->pdh); - ld->pdh = NULL; - } - } + if (ld->pdh) { + gboolean successful; - if (ld->pdh == NULL) { - /* We couldn't set up to write to the capture file. */ - /* XXX - use cf_open_error_message from tshark instead? */ - switch (err) { + ld->bytes_written = 0; + if (capture_opts->use_pcapng) { + char appname[100]; - default: - if (err < 0) { - g_snprintf(errmsg, errmsg_len, - "The file to which the capture would be" - " saved (\"%s\") could not be opened: Error %d.", - capture_opts->save_file, err); - } else { - g_snprintf(errmsg, errmsg_len, - "The file to which the capture would be" - " saved (\"%s\") could not be opened: %s.", - capture_opts->save_file, strerror(err)); - } - break; + g_snprintf(appname, sizeof(appname), "Dumpcap " VERSION "%s", wireshark_svnversion); + successful = libpcap_write_session_header_block(ld->pdh, appname, &ld->bytes_written, &err) && + libpcap_write_interface_description_block(ld->pdh, capture_opts->iface, capture_opts->cfilter, ld->linktype, ld->file_snaplen, &ld->bytes_written, &err); + } else { + successful = libpcap_write_file_header(ld->pdh, ld->linktype, ld->file_snaplen, + &ld->bytes_written, &err); + } + if (!successful) { + fclose(ld->pdh); + ld->pdh = NULL; + } } - return FALSE; - } + if (ld->pdh == NULL) { + /* We couldn't set up to write to the capture file. */ + /* XXX - use cf_open_error_message from tshark instead? */ + switch (err) { - return TRUE; + default: + if (err < 0) { + g_snprintf(errmsg, errmsg_len, + "The file to which the capture would be" + " saved (\"%s\") could not be opened: Error %d.", + capture_opts->save_file, err); + } else { + g_snprintf(errmsg, errmsg_len, + "The file to which the capture would be" + " saved (\"%s\") could not be opened: %s.", + capture_opts->save_file, strerror(err)); + } + break; + } + + return FALSE; + } + + return TRUE; } static gboolean -capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close) { +capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close) +{ - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_output"); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_output"); - if (capture_opts->multi_files_on) { - return ringbuf_libpcap_dump_close(&capture_opts->save_file, err_close); - } else { - if (capture_opts->use_pcapng) { - libpcap_write_interface_statistics_block(ld->pdh, 0, ld->pcap_h, &ld->bytes_written, err_close); + if (capture_opts->multi_files_on) { + return ringbuf_libpcap_dump_close(&capture_opts->save_file, err_close); + } else { + if (capture_opts->use_pcapng) { + libpcap_write_interface_statistics_block(ld->pdh, 0, ld->pcap_h, &ld->bytes_written, err_close); + } + return libpcap_dump_close(ld->pdh, err_close); } - return libpcap_dump_close(ld->pdh, err_close); - } } /* dispatch incoming packets (pcap or capture pipe) @@ -2477,159 +2479,159 @@ capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err */ static int capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld, - char *errmsg, int errmsg_len) + char *errmsg, int errmsg_len) { - int inpkts; - gint packet_count_before; - guchar pcap_data[WTAP_MAX_PACKET_SIZE]; + int inpkts; + gint packet_count_before; + guchar pcap_data[WTAP_MAX_PACKET_SIZE]; #ifndef USE_THREADS - int sel_ret; + int sel_ret; #endif - packet_count_before = ld->packet_count; - if (ld->from_cap_pipe) { - /* dispatch from capture pipe */ + packet_count_before = ld->packet_count; + if (ld->from_cap_pipe) { + /* dispatch from capture pipe */ #ifdef LOG_CAPTURE_VERBOSE - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from capture pipe"); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from capture pipe"); #endif #ifndef USE_THREADS - sel_ret = cap_pipe_select(ld->cap_pipe_fd); - if (sel_ret <= 0) { - if (sel_ret < 0 && errno != EINTR) { - g_snprintf(errmsg, errmsg_len, - "Unexpected error from select: %s", strerror(errno)); - report_capture_error(errmsg, please_report); - ld->go = FALSE; - } - } else { - /* - * "select()" says we can read from the pipe without blocking - */ -#endif /* USE_THREADS */ - inpkts = cap_pipe_dispatch(ld, pcap_data, errmsg, errmsg_len); - if (inpkts < 0) { - ld->go = FALSE; - } -#ifndef USE_THREADS - } -#endif - } - else - { - /* dispatch from pcap */ -#ifdef MUST_DO_SELECT - /* - * If we have "pcap_get_selectable_fd()", we use it to get the - * descriptor on which to select; if that's -1, it means there - * is no descriptor on which you can do a "select()" (perhaps - * because you're capturing on a special device, and that device's - * driver unfortunately doesn't support "select()", in which case - * we don't do the select - which means it might not be possible - * to stop a capture until a packet arrives. If that's unacceptable, - * plead with whoever supplies the software for that device to add - * "select()" support, or upgrade to libpcap 0.8.1 or later, and - * rebuild Wireshark or get a version built with libpcap 0.8.1 or - * later, so it can use pcap_breakloop(). - */ -#ifdef LOG_CAPTURE_VERBOSE - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch with select"); -#endif - if (ld->pcap_fd != -1) { - sel_ret = cap_pipe_select(ld->pcap_fd); - if (sel_ret > 0) { - /* - * "select()" says we can read from it without blocking; go for - * it. - * - * We don't have pcap_breakloop(), so we only process one packet - * per pcap_dispatch() call, to allow a signal to stop the - * processing immediately, rather than processing all packets - * in a batch before quitting. - */ - inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, - (u_char *)ld); - if (inpkts < 0) { - if (inpkts == -1) { - /* Error, rather than pcap_breakloop(). */ - ld->pcap_err = TRUE; + sel_ret = cap_pipe_select(ld->cap_pipe_fd); + if (sel_ret <= 0) { + if (sel_ret < 0 && errno != EINTR) { + g_snprintf(errmsg, errmsg_len, + "Unexpected error from select: %s", strerror(errno)); + report_capture_error(errmsg, please_report); + ld->go = FALSE; } - ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */ + } else { + /* + * "select()" says we can read from the pipe without blocking + */ +#endif /* USE_THREADS */ + inpkts = cap_pipe_dispatch(ld, pcap_data, errmsg, errmsg_len); + if (inpkts < 0) { + ld->go = FALSE; + } +#ifndef USE_THREADS } - } else { - if (sel_ret < 0 && errno != EINTR) { - g_snprintf(errmsg, errmsg_len, - "Unexpected error from select: %s", strerror(errno)); - report_capture_error(errmsg, please_report); - ld->go = FALSE; - } - } +#endif } else -#endif /* MUST_DO_SELECT */ { - /* dispatch from pcap without select */ + /* dispatch from pcap */ +#ifdef MUST_DO_SELECT + /* + * If we have "pcap_get_selectable_fd()", we use it to get the + * descriptor on which to select; if that's -1, it means there + * is no descriptor on which you can do a "select()" (perhaps + * because you're capturing on a special device, and that device's + * driver unfortunately doesn't support "select()", in which case + * we don't do the select - which means it might not be possible + * to stop a capture until a packet arrives. If that's unacceptable, + * plead with whoever supplies the software for that device to add + * "select()" support, or upgrade to libpcap 0.8.1 or later, and + * rebuild Wireshark or get a version built with libpcap 0.8.1 or + * later, so it can use pcap_breakloop(). + */ +#ifdef LOG_CAPTURE_VERBOSE + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch with select"); +#endif + if (ld->pcap_fd != -1) { + sel_ret = cap_pipe_select(ld->pcap_fd); + if (sel_ret > 0) { + /* + * "select()" says we can read from it without blocking; go for + * it. + * + * We don't have pcap_breakloop(), so we only process one packet + * per pcap_dispatch() call, to allow a signal to stop the + * processing immediately, rather than processing all packets + * in a batch before quitting. + */ + inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, + (u_char *)ld); + if (inpkts < 0) { + if (inpkts == -1) { + /* Error, rather than pcap_breakloop(). */ + ld->pcap_err = TRUE; + } + ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */ + } + } else { + if (sel_ret < 0 && errno != EINTR) { + g_snprintf(errmsg, errmsg_len, + "Unexpected error from select: %s", strerror(errno)); + report_capture_error(errmsg, please_report); + ld->go = FALSE; + } + } + } + else +#endif /* MUST_DO_SELECT */ + { + /* dispatch from pcap without select */ #if 1 #ifdef LOG_CAPTURE_VERBOSE - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch"); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch"); #endif #ifdef _WIN32 - /* - * On Windows, we don't support asynchronously telling a process to - * stop capturing; instead, we check for an indication on a pipe - * after processing packets. We therefore process only one packet - * at a time, so that we can check the pipe after every packet. - */ - inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, (u_char *) ld); + /* + * On Windows, we don't support asynchronously telling a process to + * stop capturing; instead, we check for an indication on a pipe + * after processing packets. We therefore process only one packet + * at a time, so that we can check the pipe after every packet. + */ + inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, (u_char *) ld); #else - inpkts = pcap_dispatch(ld->pcap_h, -1, capture_loop_packet_cb, (u_char *) ld); + inpkts = pcap_dispatch(ld->pcap_h, -1, capture_loop_packet_cb, (u_char *) ld); #endif - if (inpkts < 0) { - if (inpkts == -1) { - /* Error, rather than pcap_breakloop(). */ - ld->pcap_err = TRUE; - } - ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */ - } + if (inpkts < 0) { + if (inpkts == -1) { + /* Error, rather than pcap_breakloop(). */ + ld->pcap_err = TRUE; + } + ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */ + } #else /* pcap_next_ex */ #ifdef LOG_CAPTURE_VERBOSE - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_next_ex"); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_next_ex"); #endif - /* XXX - this is currently unused, as there is some confusion with pcap_next_ex() vs. pcap_dispatch() */ + /* XXX - this is currently unused, as there is some confusion with pcap_next_ex() vs. pcap_dispatch() */ - /* - * WinPcap's remote capturing feature doesn't work with pcap_dispatch(), - * see http://wiki.wireshark.org/CaptureSetup_2fWinPcapRemote - * This should be fixed in the WinPcap 4.0 alpha release. - * - * For reference, an example remote interface: - * rpcap://[1.2.3.4]/\Device\NPF_{39993D68-7C9B-4439-A329-F2D888DA7C5C} - */ + /* + * WinPcap's remote capturing feature doesn't work with pcap_dispatch(), + * see http://wiki.wireshark.org/CaptureSetup_2fWinPcapRemote + * This should be fixed in the WinPcap 4.0 alpha release. + * + * For reference, an example remote interface: + * rpcap://[1.2.3.4]/\Device\NPF_{39993D68-7C9B-4439-A329-F2D888DA7C5C} + */ - /* emulate dispatch from pcap */ - { - int in; - struct pcap_pkthdr *pkt_header; - u_char *pkt_data; + /* emulate dispatch from pcap */ + { + int in; + struct pcap_pkthdr *pkt_header; + u_char *pkt_data; - in = 0; - while(ld->go && - (in = pcap_next_ex(ld->pcap_h, &pkt_header, &pkt_data)) == 1) - capture_loop_packet_cb( (u_char *) ld, pkt_header, pkt_data); + in = 0; + while(ld->go && + (in = pcap_next_ex(ld->pcap_h, &pkt_header, &pkt_data)) == 1) + capture_loop_packet_cb( (u_char *) ld, pkt_header, pkt_data); - if(in < 0) { - ld->pcap_err = TRUE; - ld->go = FALSE; - } - } + if(in < 0) { + ld->pcap_err = TRUE; + ld->go = FALSE; + } + } #endif /* pcap_next_ex */ + } } - } #ifdef LOG_CAPTURE_VERBOSE - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: %d new packet%s", inpkts, plurality(inpkts, "", "s")); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: %d new packet%s", inpkts, plurality(inpkts, "", "s")); #endif - return ld->packet_count - packet_count_before; + return ld->packet_count - packet_count_before; } #ifdef _WIN32 @@ -2637,7 +2639,8 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld, * want to grab only the characters between the '{' and '}' delimiters. * * Returns a GString that must be freed with g_string_free(). */ -static GString *isolate_uuid(const char *iface) +static GString * +isolate_uuid(const char *iface) { gchar *ptr; GString *gstr; @@ -2660,105 +2663,105 @@ static GString *isolate_uuid(const char *iface) /* Returns TRUE if the file opened successfully, FALSE otherwise. */ static gboolean capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, - char *errmsg, int errmsg_len) { + char *errmsg, int errmsg_len) +{ + char *tmpname; + gchar *capfile_name; + gchar *prefix; + gboolean is_tempfile; - char *tmpname; - gchar *capfile_name; - gchar *prefix; - gboolean is_tempfile; + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_output: %s", + (capture_opts->save_file) ? capture_opts->save_file : ""); - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_output: %s", - (capture_opts->save_file) ? capture_opts->save_file : ""); + if (capture_opts->save_file != NULL) { + /* We return to the caller while the capture is in progress. + * Therefore we need to take a copy of save_file in + * case the caller destroys it after we return. + */ + capfile_name = g_strdup(capture_opts->save_file); - if (capture_opts->save_file != NULL) { - /* We return to the caller while the capture is in progress. - * Therefore we need to take a copy of save_file in - * case the caller destroys it after we return. - */ - capfile_name = g_strdup(capture_opts->save_file); + if (capture_opts->output_to_pipe == TRUE) { /* either "-" or named pipe */ + if (capture_opts->multi_files_on) { + /* ringbuffer is enabled; that doesn't work with standard output or a named pipe */ + g_snprintf(errmsg, errmsg_len, + "Ring buffer requested, but capture is being written to standard output or to a named pipe."); + g_free(capfile_name); + return FALSE; + } + if (strcmp(capfile_name, "-") == 0) { + /* write to stdout */ + *save_file_fd = 1; +#ifdef _WIN32 + /* set output pipe to binary mode to avoid Windows text-mode processing (eg: for CR/LF) */ + _setmode(1, O_BINARY); +#endif + } + } /* if (...output_to_pipe ... */ - if (capture_opts->output_to_pipe == TRUE) { /* either "-" or named pipe */ - if (capture_opts->multi_files_on) { - /* ringbuffer is enabled; that doesn't work with standard output or a named pipe */ - g_snprintf(errmsg, errmsg_len, - "Ring buffer requested, but capture is being written to standard output or to a named pipe."); + else { + if (capture_opts->multi_files_on) { + /* ringbuffer is enabled */ + *save_file_fd = ringbuf_init(capfile_name, + (capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0, + capture_opts->group_read_access); + + /* we need the ringbuf name */ + if(*save_file_fd != -1) { + g_free(capfile_name); + capfile_name = g_strdup(ringbuf_current_filename()); + } + } else { + /* Try to open/create the specified file for use as a capture buffer. */ + *save_file_fd = ws_open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, + (capture_opts->group_read_access) ? 0640 : 0600); + } + } + is_tempfile = FALSE; + } else { + /* Choose a random name for the temporary capture buffer */ +#ifdef _WIN32 + GString *iface; + + iface = isolate_uuid(capture_opts->iface); + prefix = g_strconcat("wireshark_", g_basename(iface->str), NULL); + g_string_free(iface, TRUE); +#else + prefix = g_strconcat("wireshark_", g_basename(capture_opts->iface), NULL); +#endif + *save_file_fd = create_tempfile(&tmpname, prefix); + g_free(prefix); + capfile_name = g_strdup(tmpname); + is_tempfile = TRUE; + } + + /* did we fail to open the output file? */ + if (*save_file_fd == -1) { + if (is_tempfile) { + g_snprintf(errmsg, errmsg_len, + "The temporary file to which the capture would be saved (\"%s\") " + "could not be opened: %s.", capfile_name, strerror(errno)); + } else { + if (capture_opts->multi_files_on) { + ringbuf_error_cleanup(); + } + + g_snprintf(errmsg, errmsg_len, + "The file to which the capture would be saved (\"%s\") " + "could not be opened: %s.", capfile_name, + strerror(errno)); + } g_free(capfile_name); return FALSE; - } - if (strcmp(capfile_name, "-") == 0) { - /* write to stdout */ - *save_file_fd = 1; -#ifdef _WIN32 - /* set output pipe to binary mode to avoid Windows text-mode processing (eg: for CR/LF) */ - _setmode(1, O_BINARY); -#endif - } - } /* if (...output_to_pipe ... */ - - else { - if (capture_opts->multi_files_on) { - /* ringbuffer is enabled */ - *save_file_fd = ringbuf_init(capfile_name, - (capture_opts->has_ring_num_files) ? capture_opts->ring_num_files : 0, - capture_opts->group_read_access); - - /* we need the ringbuf name */ - if(*save_file_fd != -1) { - g_free(capfile_name); - capfile_name = g_strdup(ringbuf_current_filename()); - } - } else { - /* Try to open/create the specified file for use as a capture buffer. */ - *save_file_fd = ws_open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT, - (capture_opts->group_read_access) ? 0640 : 0600); - } } - is_tempfile = FALSE; - } else { - /* Choose a random name for the temporary capture buffer */ -#ifdef _WIN32 - GString *iface; - iface = isolate_uuid(capture_opts->iface); - prefix = g_strconcat("wireshark_", g_basename(iface->str), NULL); - g_string_free(iface, TRUE); -#else - prefix = g_strconcat("wireshark_", g_basename(capture_opts->iface), NULL); -#endif - *save_file_fd = create_tempfile(&tmpname, prefix); - g_free(prefix); - capfile_name = g_strdup(tmpname); - is_tempfile = TRUE; - } - - /* did we fail to open the output file? */ - if (*save_file_fd == -1) { - if (is_tempfile) { - g_snprintf(errmsg, errmsg_len, - "The temporary file to which the capture would be saved (\"%s\") " - "could not be opened: %s.", capfile_name, strerror(errno)); - } else { - if (capture_opts->multi_files_on) { - ringbuf_error_cleanup(); - } - - g_snprintf(errmsg, errmsg_len, - "The file to which the capture would be saved (\"%s\") " - "could not be opened: %s.", capfile_name, - strerror(errno)); + if(capture_opts->save_file != NULL) { + g_free(capture_opts->save_file); } - g_free(capfile_name); - return FALSE; - } + capture_opts->save_file = capfile_name; + /* capture_opts.save_file is "g_free"ed later, which is equivalent to + "g_free(capfile_name)". */ - if(capture_opts->save_file != NULL) { - g_free(capture_opts->save_file); - } - capture_opts->save_file = capfile_name; - /* capture_opts.save_file is "g_free"ed later, which is equivalent to - "g_free(capfile_name)". */ - - return TRUE; + return TRUE; } @@ -2776,57 +2779,57 @@ do_file_switch_or_stop(capture_options *capture_opts, 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; - } + 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; + /* 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]; + /* 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; + 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; - } - 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; + return TRUE; } /* Do the low-level work of a capture. @@ -2834,460 +2837,462 @@ do_file_switch_or_stop(capture_options *capture_opts, static gboolean capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats) { - time_t upd_time, cur_time; - int err_close; - int inpkts; - condition *cnd_file_duration = NULL; - condition *cnd_autostop_files = NULL; - condition *cnd_autostop_size = NULL; - condition *cnd_autostop_duration = NULL; - gboolean write_ok; - gboolean close_ok; - gboolean cfilter_error = FALSE; - char errmsg[MSG_MAX_LENGTH+1]; - char secondary_errmsg[MSG_MAX_LENGTH+1]; + time_t upd_time, cur_time; + int err_close; + int inpkts; + condition *cnd_file_duration = NULL; + condition *cnd_autostop_files = NULL; + condition *cnd_autostop_size = NULL; + condition *cnd_autostop_duration = NULL; + gboolean write_ok; + gboolean close_ok; + gboolean cfilter_error = FALSE; + char errmsg[MSG_MAX_LENGTH+1]; + char secondary_errmsg[MSG_MAX_LENGTH+1]; - *errmsg = '\0'; - *secondary_errmsg = '\0'; + *errmsg = '\0'; + *secondary_errmsg = '\0'; - /* init the loop data */ - global_ld.go = TRUE; - global_ld.packet_count = 0; + /* init the loop data */ + global_ld.go = TRUE; + global_ld.packet_count = 0; #ifdef SIGINFO - global_ld.report_packet_count = FALSE; + global_ld.report_packet_count = FALSE; #endif - if (capture_opts->has_autostop_packets) - global_ld.packet_max = capture_opts->autostop_packets; - else - global_ld.packet_max = 0; /* no limit */ - global_ld.inpkts_to_sync_pipe = 0; - global_ld.err = 0; /* no error seen yet */ - global_ld.pcap_err = FALSE; - global_ld.from_cap_pipe = FALSE; - global_ld.pdh = NULL; + if (capture_opts->has_autostop_packets) + global_ld.packet_max = capture_opts->autostop_packets; + else + global_ld.packet_max = 0; /* no limit */ + global_ld.inpkts_to_sync_pipe = 0; + global_ld.err = 0; /* no error seen yet */ + 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; + global_ld.autostop_files = 0; + global_ld.save_file_fd = -1; - /* We haven't yet gotten the capture statistics. */ - *stats_known = FALSE; + /* We haven't yet gotten the capture statistics. */ + *stats_known = FALSE; - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop starting ..."); - capture_opts_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, capture_opts); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop starting ..."); + 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, &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(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(global_ld.pcap_h)); - goto error; - - case INITFILTER_OTHER_ERROR: - g_snprintf(errmsg, sizeof(errmsg), "Can't install filter (%s).", - pcap_geterr(global_ld.pcap_h)); - g_snprintf(secondary_errmsg, sizeof(secondary_errmsg), "%s", please_report); - goto error; - } - - /* 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, &global_ld.save_file_fd, - errmsg, sizeof(errmsg))) { - goto error; + /* open the "input file" from network interface or capture pipe */ + if (!capture_loop_open_input(capture_opts, &global_ld, errmsg, sizeof(errmsg), + secondary_errmsg, sizeof(secondary_errmsg))) { + goto error; } - /* set up to write to the already-opened capture output file/files */ - if (!capture_loop_init_output(capture_opts, &global_ld, errmsg, - sizeof(errmsg))) { - goto error; + /* init the input filter from the network interface (capture pipe will do nothing) */ + 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(global_ld.pcap_h)); + goto error; + + case INITFILTER_OTHER_ERROR: + g_snprintf(errmsg, sizeof(errmsg), "Can't install filter (%s).", + pcap_geterr(global_ld.pcap_h)); + g_snprintf(secondary_errmsg, sizeof(secondary_errmsg), "%s", please_report); + goto error; } - /* XXX - capture SIGTERM and close the capture, in case we're on a - Linux 2.0[.x] system and you have to explicitly close the capture - stream in order to turn promiscuous mode off? We need to do that - in other places as well - and I don't think that works all the - time in any case, due to libpcap bugs. */ + /* 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, &global_ld.save_file_fd, + errmsg, sizeof(errmsg))) { + goto error; + } - /* Well, we should be able to start capturing. + /* set up to write to the already-opened capture output file/files */ + if (!capture_loop_init_output(capture_opts, &global_ld, errmsg, + sizeof(errmsg))) { + goto error; + } - Sync out the capture file, so the header makes it to the file system, - and send a "capture started successfully and capture file created" - 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(global_ld.pdh, NULL); - report_new_capture_file(capture_opts->save_file); - } + /* XXX - capture SIGTERM and close the capture, in case we're on a + Linux 2.0[.x] system and you have to explicitly close the capture + stream in order to turn promiscuous mode off? We need to do that + in other places as well - and I don't think that works all the + time in any case, due to libpcap bugs. */ - /* initialize capture stop (and alike) conditions */ - init_capture_stop_conditions(); - /* create stop conditions */ - if (capture_opts->has_autostop_filesize) - cnd_autostop_size = - cnd_new(CND_CLASS_CAPTURESIZE,(long)capture_opts->autostop_filesize * 1024); - if (capture_opts->has_autostop_duration) - cnd_autostop_duration = - cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts->autostop_duration); + /* Well, we should be able to start capturing. - if (capture_opts->multi_files_on) { - if (capture_opts->has_file_duration) - cnd_file_duration = - cnd_new(CND_CLASS_TIMEOUT, capture_opts->file_duration); + Sync out the capture file, so the header makes it to the file system, + and send a "capture started successfully and capture file created" + 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(global_ld.pdh, NULL); + report_new_capture_file(capture_opts->save_file); + } - if (capture_opts->has_autostop_files) - cnd_autostop_files = - cnd_new(CND_CLASS_CAPTURESIZE, capture_opts->autostop_files); - } + /* initialize capture stop (and alike) conditions */ + init_capture_stop_conditions(); + /* create stop conditions */ + if (capture_opts->has_autostop_filesize) + cnd_autostop_size = + cnd_new(CND_CLASS_CAPTURESIZE,(long)capture_opts->autostop_filesize * 1024); + if (capture_opts->has_autostop_duration) + cnd_autostop_duration = + cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts->autostop_duration); - /* init the time values */ - upd_time = TIME_GET(); + if (capture_opts->multi_files_on) { + if (capture_opts->has_file_duration) + cnd_file_duration = + cnd_new(CND_CLASS_TIMEOUT, capture_opts->file_duration); - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop running!"); + if (capture_opts->has_autostop_files) + cnd_autostop_files = + cnd_new(CND_CLASS_CAPTURESIZE, capture_opts->autostop_files); + } - /* WOW, everything is prepared! */ - /* please fasten your seat belts, we will enter now the actual capture loop */ - while (global_ld.go) { - /* dispatch incoming packets */ - inpkts = capture_loop_dispatch(capture_opts, &global_ld, errmsg, - sizeof(errmsg)); + /* init the time values */ + upd_time = TIME_GET(); + + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop running!"); + + /* WOW, everything is prepared! */ + /* please fasten your seat belts, we will enter now the actual capture loop */ + while (global_ld.go) { + /* dispatch incoming packets */ + 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; - } + /* 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()) { - global_ld.go = FALSE; - } + /* any news from our parent (signal pipe)? -> just stop the capture */ + if (!signal_pipe_check_running()) { + global_ld.go = FALSE; + } #endif - if (inpkts > 0) { - global_ld.inpkts_to_sync_pipe += inpkts; + if (inpkts > 0) { + 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)) { - /* Capture size limit reached, do we have another file? */ - 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); - } - } /* inpkts */ + /* check capture size condition */ + if (cnd_autostop_size != NULL && + cnd_eval(cnd_autostop_size, (guint32)global_ld.bytes_written)) { + /* Capture size limit reached, do we have another file? */ + 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); + } + } /* inpkts */ - /* Only update once a second (Win32: 500ms) so as not to overload slow - * displays. This also prevents too much context-switching between the - * dumpcap and wireshark processes */ - cur_time = TIME_GET(); + /* Only update once a second (Win32: 500ms) so as not to overload slow + * displays. This also prevents too much context-switching between the + * dumpcap and wireshark processes */ #ifdef _WIN32 - if ( (cur_time - upd_time) > 500) { +#define DUMPCAP_UPD_TIME 500 #else - if (cur_time - upd_time > 0) { +#define DUMPCAP_UPD_TIME 0 #endif - upd_time = cur_time; + cur_time = TIME_GET(); + if ( (cur_time - upd_time) > DUMPCAP_UPD_TIME) { + upd_time = cur_time; - /*if (pcap_stats(pch, stats) >= 0) { - *stats_known = TRUE; - }*/ +#if 0 + if (pcap_stats(pch, stats) >= 0) { + *stats_known = TRUE; + } +#endif + /* Let the parent process know. */ + if (global_ld.inpkts_to_sync_pipe) { + /* do sync here */ + libpcap_dump_flush(global_ld.pdh, NULL); - /* Let the parent process know. */ - 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 + "global_ld.inpkts_to_sync_pipe" packets to the capture file. */ + if (!quiet) + report_packet_count(global_ld.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. */ + global_ld.inpkts_to_sync_pipe = 0; + } + + /* check capture duration condition */ + if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) { + /* The maximum capture time has elapsed; stop the capture. */ + global_ld.go = FALSE; + continue; + } + + /* check capture file duration condition */ + if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) { + /* duration limit reached, do we have another file? */ + if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files, + cnd_autostop_size, cnd_file_duration)) + continue; + } /* cnd_file_duration */ + } + + } /* while (global_ld.go) */ + + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopping ..."); + + /* delete stop conditions */ + if (cnd_file_duration != NULL) + cnd_delete(cnd_file_duration); + if (cnd_autostop_files != NULL) + cnd_delete(cnd_autostop_files); + if (cnd_autostop_size != NULL) + cnd_delete(cnd_autostop_size); + if (cnd_autostop_duration != NULL) + cnd_delete(cnd_autostop_duration); + + /* did we had a pcap (input) error? */ + 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" or + "The interface went down" error (ENETDOWN). + (At least you will if strerror() doesn't show a local translation + of the error.) + + On FreeBSD and OS X, if a network adapter disappears while + you're capturing on it, you'll get a "read: Device not configured" + error (ENXIO). (See previous parenthetical note.) + + On OpenBSD, you get "read: I/O error" (EIO) in the same case. + + These should *not* be reported to the Wireshark developers. */ + char *cap_err_str; + + cap_err_str = pcap_geterr(global_ld.pcap_h); + if (strcmp(cap_err_str, "recvfrom: Network is down") == 0 || + strcmp(cap_err_str, "The interface went down") == 0 || + strcmp(cap_err_str, "read: Device not configured") == 0 || + strcmp(cap_err_str, "read: I/O error") == 0 || + strcmp(cap_err_str, "read error: PacketReceivePacket failed") == 0) { + report_capture_error("The network adapter on which the capture was being done " + "is no longer running; the capture has stopped.", + ""); + } else { + g_snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s", + cap_err_str); + report_capture_error(errmsg, please_report); + } + } + else if (global_ld.from_cap_pipe && global_ld.cap_pipe_err == PIPERR) + report_capture_error(errmsg, ""); + + /* did we have an output error while capturing? */ + if (global_ld.err == 0) { + write_ok = TRUE; + } else { + 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 output file */ + close_ok = capture_loop_close_output(capture_opts, &global_ld, &err_close); + } else + close_ok = TRUE; + + /* there might be packets not yet notified to the parent */ + /* (do this after closing the file, so all packets are already flushed) */ + if(global_ld.inpkts_to_sync_pipe) { if (!quiet) - report_packet_count(global_ld.inpkts_to_sync_pipe); - + report_packet_count(global_ld.inpkts_to_sync_pipe); global_ld.inpkts_to_sync_pipe = 0; - } - - /* check capture duration condition */ - if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) { - /* The maximum capture time has elapsed; stop the capture. */ - global_ld.go = FALSE; - continue; - } - - /* check capture file duration condition */ - if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) { - /* duration limit reached, do we have another file? */ - if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files, - cnd_autostop_size, cnd_file_duration)) - continue; - } /* cnd_file_duration */ } - } /* while (global_ld.go) */ - - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopping ..."); - - /* delete stop conditions */ - if (cnd_file_duration != NULL) - cnd_delete(cnd_file_duration); - if (cnd_autostop_files != NULL) - cnd_delete(cnd_autostop_files); - if (cnd_autostop_size != NULL) - cnd_delete(cnd_autostop_size); - if (cnd_autostop_duration != NULL) - cnd_delete(cnd_autostop_duration); - - /* did we had a pcap (input) error? */ - 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" or - "The interface went down" error (ENETDOWN). - (At least you will if strerror() doesn't show a local translation - of the error.) - - On FreeBSD and OS X, if a network adapter disappears while - you're capturing on it, you'll get a "read: Device not configured" - error (ENXIO). (See previous parenthetical note.) - - On OpenBSD, you get "read: I/O error" (EIO) in the same case. - - These should *not* be reported to the Wireshark developers. */ - char *cap_err_str; - - cap_err_str = pcap_geterr(global_ld.pcap_h); - if (strcmp(cap_err_str, "recvfrom: Network is down") == 0 || - strcmp(cap_err_str, "The interface went down") == 0 || - strcmp(cap_err_str, "read: Device not configured") == 0 || - strcmp(cap_err_str, "read: I/O error") == 0 || - strcmp(cap_err_str, "read error: PacketReceivePacket failed") == 0) { - report_capture_error("The network adapter on which the capture was being done " - "is no longer running; the capture has stopped.", - ""); - } else { - g_snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s", - cap_err_str); - report_capture_error(errmsg, please_report); + /* If we've displayed a message about a write error, there's no point + in displaying another message about an error on close. */ + if (!close_ok && write_ok) { + capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, err_close, + TRUE); + report_capture_error(errmsg, ""); } - } - 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 (global_ld.err == 0) { - write_ok = TRUE; - } else { - capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, - global_ld.err, FALSE); - report_capture_error(errmsg, please_report); - write_ok = FALSE; - } + /* + * XXX We exhibit different behaviour between normal mode and sync mode + * when the pipe is stdin and not already at EOF. If we're a child, the + * parent's stdin isn't closed, so if the user starts another capture, + * cap_pipe_open_live() will very likely not see the expected magic bytes and + * will say "Unrecognized libpcap format". On the other hand, in normal + * mode, cap_pipe_open_live() will say "End of file on pipe during open". + */ - if (capture_opts->saving_to_file) { - /* close the output file */ - close_ok = capture_loop_close_output(capture_opts, &global_ld, &err_close); - } else - close_ok = TRUE; + report_capture_count(); /* print final capture count only if (quiet && !capture_child) */ - /* there might be packets not yet notified to the parent */ - /* (do this after closing the file, so all packets are already flushed) */ - 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 - in displaying another message about an error on close. */ - if (!close_ok && write_ok) { - capture_loop_get_errmsg(errmsg, sizeof(errmsg), capture_opts->save_file, err_close, - TRUE); - report_capture_error(errmsg, ""); - } - - /* - * XXX We exhibit different behaviour between normal mode and sync mode - * when the pipe is stdin and not already at EOF. If we're a child, the - * parent's stdin isn't closed, so if the user starts another capture, - * cap_pipe_open_live() will very likely not see the expected magic bytes and - * will say "Unrecognized libpcap format". On the other hand, in normal - * mode, cap_pipe_open_live() will say "End of file on pipe during open". - */ - - report_capture_count(); /* print final capture count only if (quiet && !capture_child) */ - - /* get packet drop statistics from pcap */ - 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(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(global_ld.pcap_h)); - report_capture_error(errmsg, please_report); + /* get packet drop statistics from pcap */ + 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(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(global_ld.pcap_h)); + report_capture_error(errmsg, please_report); + } } - } - /* close the input file (pcap or capture pipe) */ - capture_loop_close_input(&global_ld); + /* close the input file (pcap or capture pipe) */ + capture_loop_close_input(&global_ld); - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped!"); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped!"); - /* ok, if the write and the close were successful. */ - return write_ok && close_ok; + /* ok, if the write and the close were successful. */ + return write_ok && close_ok; error: - if (capture_opts->multi_files_on) { - /* cleanup ringbuffer */ - ringbuf_error_cleanup(); - } 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(global_ld.save_file_fd != -1) { - ws_close(global_ld.save_file_fd); + if (capture_opts->multi_files_on) { + /* cleanup ringbuffer */ + ringbuf_error_cleanup(); + } 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(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 + file. */ + if(capture_opts->save_file != NULL) { + ws_unlink(capture_opts->save_file); + g_free(capture_opts->save_file); + } } + capture_opts->save_file = NULL; + if (cfilter_error) + report_cfilter_error(capture_opts->cfilter, errmsg); + else + report_capture_error(errmsg, secondary_errmsg); - /* We couldn't even start the capture, so get rid of the capture - file. */ - if(capture_opts->save_file != NULL) { - ws_unlink(capture_opts->save_file); - g_free(capture_opts->save_file); - } - } - capture_opts->save_file = NULL; - if (cfilter_error) - report_cfilter_error(capture_opts->cfilter, errmsg); - else - report_capture_error(errmsg, secondary_errmsg); + /* close the input file (pcap or cap_pipe) */ + capture_loop_close_input(&global_ld); - /* close the input file (pcap or cap_pipe) */ - capture_loop_close_input(&global_ld); + g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped with error"); - g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop stopped with error"); - - return FALSE; + return FALSE; } static void capture_loop_stop(void) { #ifdef HAVE_PCAP_BREAKLOOP - if(global_ld.pcap_h != NULL) - pcap_breakloop(global_ld.pcap_h); + if(global_ld.pcap_h != NULL) + pcap_breakloop(global_ld.pcap_h); #endif - global_ld.go = FALSE; + global_ld.go = FALSE; } static void capture_loop_get_errmsg(char *errmsg, int errmsglen, const char *fname, - int err, gboolean is_close) + int err, gboolean is_close) { - switch (err) { + switch (err) { - case ENOSPC: - g_snprintf(errmsg, errmsglen, - "Not all the packets could be written to the file" - " to which the capture was being saved\n" - "(\"%s\") because there is no space left on the file system\n" - "on which that file resides.", - fname); - break; + case ENOSPC: + g_snprintf(errmsg, errmsglen, + "Not all the packets could be written to the file" + " to which the capture was being saved\n" + "(\"%s\") because there is no space left on the file system\n" + "on which that file resides.", + fname); + break; #ifdef EDQUOT - case EDQUOT: - g_snprintf(errmsg, errmsglen, - "Not all the packets could be written to the file" - " to which the capture was being saved\n" - "(\"%s\") because you are too close to, or over," - " your disk quota\n" - "on the file system on which that file resides.", - fname); - break; + case EDQUOT: + g_snprintf(errmsg, errmsglen, + "Not all the packets could be written to the file" + " to which the capture was being saved\n" + "(\"%s\") because you are too close to, or over," + " your disk quota\n" + "on the file system on which that file resides.", + fname); + break; #endif - default: - if (is_close) { - g_snprintf(errmsg, errmsglen, - "The file to which the capture was being saved\n" - "(\"%s\") could not be closed: %s.", - fname, strerror(err)); - } else { - g_snprintf(errmsg, errmsglen, - "An error occurred while writing to the file" - " to which the capture was being saved\n" - "(\"%s\"): %s.", - fname, strerror(err)); + default: + if (is_close) { + g_snprintf(errmsg, errmsglen, + "The file to which the capture was being saved\n" + "(\"%s\") could not be closed: %s.", + fname, strerror(err)); + } else { + g_snprintf(errmsg, errmsglen, + "An error occurred while writing to the file" + " to which the capture was being saved\n" + "(\"%s\"): %s.", + fname, strerror(err)); + } + break; } - break; - } } /* one packet was captured, process it */ static void capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr, - const u_char *pd) + const u_char *pd) { - loop_data *ld = (loop_data *) (void *) user; - int err; + loop_data *ld = (loop_data *) (void *) user; + int err; - /* We may be called multiple times from pcap_dispatch(); if we've set - the "stop capturing" flag, ignore this packet, as we're not - supposed to be saving any more packets. */ - if (!ld->go) - return; + /* We may be called multiple times from pcap_dispatch(); if we've set + the "stop capturing" flag, ignore this packet, as we're not + supposed to be saving any more packets. */ + if (!ld->go) + return; - if (ld->pdh) { - gboolean successful; - /* We're supposed to write the packet to a file; do so. - If this fails, set "ld->go" to FALSE, to stop the capture, and set - "ld->err" to the error. */ - if (global_capture_opts.use_pcapng) { - successful = libpcap_write_enhanced_packet_block(ld->pdh, phdr, 0, pd, &ld->bytes_written, &err); - } else { - successful = libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err); + if (ld->pdh) { + gboolean successful; + /* We're supposed to write the packet to a file; do so. + If this fails, set "ld->go" to FALSE, to stop the capture, and set + "ld->err" to the error. */ + if (global_capture_opts.use_pcapng) { + successful = libpcap_write_enhanced_packet_block(ld->pdh, phdr, 0, pd, &ld->bytes_written, &err); + } else { + successful = libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err); + } + if (!successful) { + ld->go = FALSE; + ld->err = err; + } else { + ld->packet_count++; + /* if the user told us to stop after x packets, do we already have enough? */ + if ((ld->packet_max > 0) && (ld->packet_count >= ld->packet_max)) + { + ld->go = FALSE; + } + } } - if (!successful) { - ld->go = FALSE; - ld->err = err; - } else { - ld->packet_count++; - /* if the user told us to stop after x packets, do we already have enough? */ - if ((ld->packet_max > 0) && (ld->packet_count >= ld->packet_max)) - { - ld->go = FALSE; - } - } - } } @@ -3295,50 +3300,50 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr, int main(int argc, char *argv[]) { - int opt; - gboolean arg_error = FALSE; + int opt; + gboolean arg_error = FALSE; #ifdef _WIN32 - WSADATA wsaData; - LPWSTR *wc_argv; - int wc_argc; + WSADATA wsaData; + LPWSTR *wc_argv; + int wc_argc; #else - struct sigaction action, oldaction; + struct sigaction action, oldaction; #endif - gboolean start_capture = TRUE; - gboolean stats_known; - struct pcap_stat stats; - GLogLevelFlags log_flags; - gboolean list_interfaces = FALSE; - gboolean list_link_layer_types = FALSE; + gboolean start_capture = TRUE; + gboolean stats_known; + struct pcap_stat stats; + GLogLevelFlags log_flags; + gboolean list_interfaces = FALSE; + gboolean list_link_layer_types = FALSE; #ifdef HAVE_BPF_IMAGE - gboolean print_bpf_code = FALSE; + gboolean print_bpf_code = FALSE; #endif - gboolean machine_readable = FALSE; - gboolean print_statistics = FALSE; - int status, run_once_args = 0; - gint i; + gboolean machine_readable = FALSE; + gboolean print_statistics = FALSE; + int status, run_once_args = 0; + gint i; #if defined(__APPLE__) && defined(__LP64__) - struct utsname osinfo; + struct utsname osinfo; #endif #ifdef _WIN32 - /* Convert our arg list to UTF-8. */ - wc_argv = CommandLineToArgvW(GetCommandLineW(), &wc_argc); - if (wc_argv && wc_argc == argc) { - for (i = 0; i < argc; i++) { - argv[i] = g_utf16_to_utf8(wc_argv[i], -1, NULL, NULL, NULL); - } - } /* XXX else bail because something is horribly, horribly wrong? */ + /* Convert our arg list to UTF-8. */ + wc_argv = CommandLineToArgvW(GetCommandLineW(), &wc_argc); + if (wc_argv && wc_argc == argc) { + for (i = 0; i < argc; i++) { + argv[i] = g_utf16_to_utf8(wc_argv[i], -1, NULL, NULL, NULL); + } + } /* XXX else bail because something is horribly, horribly wrong? */ #endif /* _WIN32 */ #ifdef _WIN32 - /* - * Initialize our DLL search path. MUST be called before LoadLibrary - * or g_module_open. - */ - ws_init_dll_search_path(); + /* + * Initialize our DLL search path. MUST be called before LoadLibrary + * or g_module_open. + */ + ws_init_dll_search_path(); #endif #ifdef HAVE_PCAP_REMOTE @@ -3378,608 +3383,610 @@ main(int argc, char *argv[]) #define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:" OPTSTRING_d "Df:ghi:" 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) { - fprintf (stderr, "Unable to open debug log file !\n"); - exit (1); - } + if ((debug_log = ws_fopen("dumpcap_debug_log.tmp","w")) == NULL) { + fprintf (stderr, "Unable to open debug log file !\n"); + exit (1); + } #endif #if defined(__APPLE__) && defined(__LP64__) - /* - * Is this Mac OS X 10.6.0, 10.6.1, 10.6.3, or 10.6.4? If so, we need - * a bug workaround - timeouts less than 1 second don't work with libpcap - * in 64-bit code. (The bug was introduced in 10.6, fixed in 10.6.2, - * re-introduced in 10.6.3, not fixed in 10.6.4, and fixed in 10.6.5. - * The problem is extremely unlikely to be reintroduced in a future - * release.) - */ - if (uname(&osinfo) == 0) { /* - * Mac OS X 10.x uses Darwin {x+4}.0.0. Mac OS X 10.x.y uses Darwin - * {x+4}.y.0 (except that 10.6.1 appears to have a uname version - * number of 10.0.0, not 10.1.0 - go figure). + * Is this Mac OS X 10.6.0, 10.6.1, 10.6.3, or 10.6.4? If so, we need + * a bug workaround - timeouts less than 1 second don't work with libpcap + * in 64-bit code. (The bug was introduced in 10.6, fixed in 10.6.2, + * re-introduced in 10.6.3, not fixed in 10.6.4, and fixed in 10.6.5. + * The problem is extremely unlikely to be reintroduced in a future + * release.) */ - if (strcmp(osinfo.release, "10.0.0") == 0 || /* 10.6, 10.6.1 */ - strcmp(osinfo.release, "10.3.0") == 0 || /* 10.6.3 */ - strcmp(osinfo.release, "10.4.0") == 0) /* 10.6.4 */ - need_timeout_workaround = TRUE; - } -#endif - - /* - * Determine if dumpcap is being requested to run in a special - * capture_child mode by going thru the command line args to see if - * a -Z is present. (-Z is a hidden option). - * - * The primary result of running in capture_child mode is that - * all messages sent out on stderr are in a special type/len/string - * format to allow message processing by type. These messages include - * error messages if dumpcap fails to start the operation it was - * requested to do, as well as various "status" messages which are sent - * when an actual capture is in progress, and a "success" message sent - * if dumpcap was requested to perform an operation other than a - * capture. - * - * Capture_child mode would normally be requested by a parent process - * which invokes dumpcap and obtains dumpcap stderr output via a pipe - * to which dumpcap stderr has been redirected. It might also have - * another pipe to obtain dumpcap stdout output; for operations other - * than a capture, that information is formatted specially for easier - * parsing by the parent process. - * - * Capture_child mode needs to be determined immediately upon - * startup so that any messages generated by dumpcap in this mode - * (eg: during initialization) will be formatted properly. - */ - - for (i=1; i