From 08bbd29c71b8068e419f95a7a8cb7332ef0a3a3d Mon Sep 17 00:00:00 2001 From: Tomas Kukosa Date: Tue, 4 Dec 2007 11:19:29 +0000 Subject: [PATCH] Support for RPCAP features in GUI (from Boris Misenov, see Bug 1366) - retrieving the list of remote PCAP interfaces - password authentication support - UDP data fransfer - packet sampling (available in WinPcap 4.x) etc. fix problem if non-default rpcap port is used svn path=/trunk/; revision=23750 --- Makefile.nmake | 7 + acinclude.m4 | 17 + capture-pcap-util-int.h | 11 + capture-pcap-util-unix.c | 39 +++ capture-pcap-util.c | 15 + capture-pcap-util.h | 5 + capture-wpcap.c | 103 +++++++ capture_loop.c | 56 ++++ capture_opts.c | 129 ++++++++ capture_opts.h | 45 +++ capture_sync.c | 33 ++ capture_ui_utils.c | 8 +- config.h.win32 | 7 + config.nmake | 22 ++ configure.in | 22 ++ dumpcap.c | 23 ++ epan/dissectors/packet-ldap.c | 2 +- epan/dissectors/packet-ldap.h | 2 +- gtk/capture_dlg.c | 563 ++++++++++++++++++++++++++++++++++ 19 files changed, 1104 insertions(+), 5 deletions(-) diff --git a/Makefile.nmake b/Makefile.nmake index 4f38e2bfcf..12e2b6cb82 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -305,6 +305,12 @@ config.h : config.h.win32 config.nmake -e "s/@HAVE_PCAP_DATALINK_NAME_TO_VAL@/$(PCAP_DATALINK_NAME_TO_VAL_CONFIG)/" \ -e "s/@HAVE_PCAP_DATALINK_VAL_TO_NAME@/$(PCAP_DATALINK_VAL_TO_NAME_CONFIG)/" \ -e "s/@HAVE_PCAP_BREAKLOOP@/$(PCAP_BREAKLOOP_CONFIG)/" \ + -e "s/@HAVE_REMOTE@/$(PCAP_HAVE_REMOTE_CONFIG)/" \ + -e "s/@HAVE_PCAP_REMOTE@/$(PCAP_REMOTE_CONFIG)/" \ + -e "s/@HAVE_PCAP_OPEN@/$(PCAP_OPEN_CONFIG)/" \ + -e "s/@HAVE_PCAP_FINDALLDEVS_EX@/$(PCAP_FINDALLDEVS_EX_CONFIG)/" \ + -e "s/@HAVE_PCAP_CREATESRCSTR@/$(PCAP_CREATESRCSTR_CONFIG)/" \ + -e "s/@HAVE_PCAP_SETSAMPLING@/$(PCAP_SETSAMPLING_CONFIG)/" \ -e "s/@HAVE_LIBWIRESHARKDLL@/$(LIBWIRESHARK_CONFIG)/" \ -e "s/@WPCAP_CONSTIFIED@/$(WPCAP_CONSTIFIED_CONFIG)/" \ -e "s/@HAVE_LIBGNUTLS@/$(GNUTLS_CONFIG)/" \ @@ -1067,3 +1073,4 @@ clean-deps2: clean-deps: clean-deps1 clean-deps2 + diff --git a/acinclude.m4 b/acinclude.m4 index ff9c31fba9..d711fe8361 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -557,6 +557,23 @@ and did you also install that package?]])) LIBS="$ac_save_LIBS" ]) +AC_DEFUN([AC_WIRESHARK_PCAP_REMOTE_CHECK], +[ + ac_save_LIBS="$LIBS" + LIBS="$PCAP_LIBS $SOCKET_LIBS $NSL_LIBS $LIBS" + AC_DEFINE(HAVE_REMOTE, 1, [Define to 1 to enable remote + capturing feature in WinPcap library]) + AC_CHECK_FUNCS(pcap_open pcap_findalldevs_ex pcap_createsrcstr) + if test $ac_cv_func_pcap_open = "yes" -a \ + $ac_cv_func_pcap_findalldevs_ex = "yes" -a \ + $ac_cv_func_pcap_createsrcstr = "yes" ; then + AC_DEFINE(HAVE_PCAP_REMOTE, 1, + [Define to 1 if you have WinPcap remote capturing support and prefer to use these new API features.]) + fi + AC_CHECK_FUNCS(pcap_setsampling) + LIBS="$ac_save_LIBS" +]) + # # AC_WIRESHARK_ZLIB_CHECK # diff --git a/capture-pcap-util-int.h b/capture-pcap-util-int.h index 3ab330aedd..ccdd54dfdb 100644 --- a/capture-pcap-util-int.h +++ b/capture-pcap-util-int.h @@ -26,12 +26,23 @@ #define __PCAP_UTIL_INT_H__ #ifdef HAVE_LIBPCAP +#ifdef HAVE_PCAP_REMOTE +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#endif extern if_info_t *if_info_new(char *name, char *description); extern void if_info_add_address(if_info_t *if_info, struct sockaddr *addr); #ifdef HAVE_PCAP_FINDALLDEVS +#ifdef HAVE_PCAP_REMOTE +extern GList *get_interface_list_findalldevs_ex(const char *source, + struct pcap_rmtauth *auth, int *err, char **err_str); +#else extern GList *get_interface_list_findalldevs(int *err, char **err_str); #endif +#endif /* * Get an error message string for a CANT_GET_INTERFACE_LIST error from diff --git a/capture-pcap-util-unix.c b/capture-pcap-util-unix.c index ea8968b7d0..d707cc695a 100644 --- a/capture-pcap-util-unix.c +++ b/capture-pcap-util-unix.c @@ -73,11 +73,50 @@ static void search_for_if_cb(gpointer data, gpointer user_data); #endif +#ifdef HAVE_PCAP_REMOTE +GList * +get_remote_interface_list(const char *hostname, const char *port, + int auth_type, const char *username, + const char *passwd, int *err, char **err_str) +{ + struct pcap_rmtauth auth; + char source[PCAP_BUF_SIZE]; + char errbuf[PCAP_ERRBUF_SIZE]; + + auth.type = auth_type; + auth.username = username; + auth.password = passwd; + + if (pcap_createsrcstr(source, PCAP_SRC_IFREMOTE, hostname, port, + NULL, errbuf) == -1) { + *err = CANT_GET_INTERFACE_LIST; + if (err_str != NULL) + *err_str = cant_get_if_list_error_message(errbuf); + return NULL; + } + return get_interface_list_findalldevs_ex(source, &auth, err, err_str); +} +#endif + GList * get_interface_list(int *err, char **err_str) { #ifdef HAVE_PCAP_FINDALLDEVS +#ifdef HAVE_PCAP_REMOTE + char source[PCAP_BUF_SIZE]; + char errbuf[PCAP_ERRBUF_SIZE]; + + if (pcap_createsrcstr(source, PCAP_SRC_IFLOCAL, + NULL, NULL, NULL, errbuf) == -1) { + *err = CANT_GET_INTERFACE_LIST; + if (err_str != NULL) + *err_str = cant_get_if_list_error_message(errbuf); + return NULL; + } + return get_interface_list_findalldevs_ex(source, NULL, err, err_str); +#else return get_interface_list_findalldevs(err, err_str); +#endif #else GList *il = NULL; gint nonloopback_pos = 0; diff --git a/capture-pcap-util.c b/capture-pcap-util.c index 1c24afd485..4cf7f4995d 100644 --- a/capture-pcap-util.c +++ b/capture-pcap-util.c @@ -249,15 +249,26 @@ if_info_ip(if_info_t *if_info, pcap_if_t *d) } } +#ifdef HAVE_PCAP_REMOTE +GList * +get_interface_list_findalldevs_ex(const char *source, + struct pcap_rmtauth *auth, + int *err, char **err_str) +#else GList * get_interface_list_findalldevs(int *err, char **err_str) +#endif { GList *il = NULL; pcap_if_t *alldevs, *dev; if_info_t *if_info; char errbuf[PCAP_ERRBUF_SIZE]; +#ifdef HAVE_PCAP_REMOTE + if (pcap_findalldevs_ex((char *)source, auth, &alldevs, errbuf) == -1) { +#else if (pcap_findalldevs(&alldevs, errbuf) == -1) { +#endif *err = CANT_GET_INTERFACE_LIST; if (err_str != NULL) *err_str = cant_get_if_list_error_message(errbuf); @@ -367,7 +378,11 @@ get_pcap_linktype_list(char *devname, char **err_str) #endif data_link_info_t *data_link_info; +#ifdef HAVE_PCAP_OPEN + pch = pcap_open(devname, MIN_PACKET_SIZE, 0, 0, NULL, errbuf); +#else pch = pcap_open_live(devname, MIN_PACKET_SIZE, 0, 0, errbuf); +#endif if (pch == NULL) { if (err_str != NULL) *err_str = g_strdup(errbuf); diff --git a/capture-pcap-util.h b/capture-pcap-util.h index 6de58441a9..259a8ed48c 100644 --- a/capture-pcap-util.h +++ b/capture-pcap-util.h @@ -68,6 +68,11 @@ typedef struct { } if_addr_t; GList *get_interface_list(int *err, char **err_str); +#ifdef HAVE_PCAP_REMOTE +GList *get_remote_interface_list(const char *hostname, const char *port, + int auth_type, const char *username, + const char *passwd, int *err, char **err_str); +#endif /* Error values from "get_interface_list()/capture_interface_list()". */ #define CANT_GET_INTERFACE_LIST 1 /* error getting list */ diff --git a/capture-wpcap.c b/capture-wpcap.c index 81d06abecb..04ebe5e322 100644 --- a/capture-wpcap.c +++ b/capture-wpcap.c @@ -96,6 +96,17 @@ static void (*p_pcap_breakloop) (pcap_t *); static const char *(*p_pcap_lib_version) (void); static int (*p_pcap_setbuff) (pcap_t *, int dim); static int (*p_pcap_next_ex) (pcap_t *, struct pcap_pkthdr **pkt_header, const u_char **pkt_data); +#ifdef HAVE_PCAP_REMOTE +static pcap_t* (*p_pcap_open) (const char *, int, int, int, + struct pcap_rmtauth *, char *); +static int (*p_pcap_findalldevs_ex) (char *, struct pcap_rmtauth *, + pcap_if_t **, char *); +static int (*p_pcap_createsrcstr) (char *, int, const char *, const char *, + const char *, char *); +#endif +#ifdef HAVE_PCAP_SETSAMPLING +static struct pcap_samp* (*p_pcap_setsampling)(pcap_t *); +#endif typedef struct { const char *name; @@ -121,7 +132,16 @@ load_wpcap(void) SYM(pcap_geterr, FALSE), SYM(pcap_compile, FALSE), SYM(pcap_lookupnet, FALSE), +#ifdef HAVE_PCAP_REMOTE + SYM(pcap_open, FALSE), + SYM(pcap_findalldevs_ex, FALSE), + SYM(pcap_createsrcstr, FALSE), +#else SYM(pcap_open_live, FALSE), +#endif +#ifdef HAVE_PCAP_SETSAMPLING + SYM(pcap_setsampling, TRUE), +#endif SYM(pcap_loop, FALSE), SYM(pcap_freecode, TRUE), #ifdef HAVE_PCAP_FINDALLDEVS @@ -266,6 +286,42 @@ pcap_open_live(char *a, int b, int c, int d, char *e) return p_pcap_open_live(a, b, c, d, e); } +#ifdef HAVE_PCAP_REMOTE +pcap_t* +pcap_open(const char *a, int b, int c, int d, struct pcap_rmtauth *e, char *f) +{ + g_assert(has_wpcap); + return p_pcap_open(a, b, c, d, e, f); +} + +int +pcap_findalldevs_ex(char *a, struct pcap_rmtauth *b, pcap_if_t **c, char *d) +{ + g_assert(has_wpcap); + return p_pcap_findalldevs_ex(a, b, c, d); +} + +int +pcap_createsrcstr(char *a, int b, const char *c, const char *d, const char *e, + char *f) +{ + g_assert(has_wpcap); + return p_pcap_createsrcstr(a, b, c, d, e, f); +} +#endif + +#ifdef HAVE_PCAP_SETSAMPLING +struct pcap_samp * +pcap_setsampling(pcap_t *a) +{ + g_assert(has_wpcap); + if (p_pcap_setsampling != NULL) { + return p_pcap_setsampling(a); + } + return NULL; +} +#endif + int pcap_loop(pcap_t *a, int b, pcap_handler c, guchar *d) { @@ -465,6 +521,37 @@ int pcap_next_ex (pcap_t *a, struct pcap_pkthdr **b, const u_char **c) return p_pcap_next_ex(a, b, c); } +#ifdef HAVE_PCAP_REMOTE +GList * +get_remote_interface_list(const char *hostname, const char *port, + int auth_type, const char *username, + const char *passwd, int *err, char **err_str) +{ + struct pcap_rmtauth auth; + char source[PCAP_BUF_SIZE]; + char errbuf[PCAP_ERRBUF_SIZE]; + GList *result; + + if (pcap_createsrcstr(source, PCAP_SRC_IFREMOTE, hostname, port, + NULL, errbuf) == -1) { + *err = CANT_GET_INTERFACE_LIST; + if (err_str != NULL) + *err_str = cant_get_if_list_error_message(errbuf); + return NULL; + } + + auth.type = auth_type; + auth.username = g_strdup(username); + auth.password = g_strdup(passwd); + + result = get_interface_list_findalldevs_ex(source, &auth, err, err_str); + g_free(auth.username); + g_free(auth.password); + + return result; +} +#endif + /* * This will use "pcap_findalldevs()" if we have it, otherwise it'll * fall back on "pcap_lookupdev()". @@ -472,14 +559,29 @@ int pcap_next_ex (pcap_t *a, struct pcap_pkthdr **b, const u_char **c) GList * get_interface_list(int *err, char **err_str) { +#ifdef HAVE_PCAP_REMOTE + char source[PCAP_BUF_SIZE]; +#else GList *il = NULL; wchar_t *names; char *win95names; char ascii_name[MAX_WIN_IF_NAME_LEN + 1]; char ascii_desc[MAX_WIN_IF_NAME_LEN + 1]; int i, j; +#endif char errbuf[PCAP_ERRBUF_SIZE]; +#ifdef HAVE_PCAP_REMOTE + if (p_pcap_createsrcstr(source, PCAP_SRC_IFLOCAL, NULL, NULL, + NULL, errbuf) == -1) { + *err = CANT_GET_INTERFACE_LIST; + if (err_str != NULL) + *err_str = cant_get_if_list_error_message(errbuf); + return NULL; + } + return get_interface_list_findalldevs_ex(source, NULL, err, err_str); +#else + #ifdef HAVE_PCAP_FINDALLDEVS if (p_pcap_findalldevs != NULL) return get_interface_list_findalldevs(err, err_str); @@ -620,6 +722,7 @@ get_interface_list(int *err, char **err_str) } return il; +#endif /* HAVE_PCAP_REMOTE */ } /* diff --git a/capture_loop.c b/capture_loop.c index 822a95f079..8c602a4a16 100644 --- a/capture_loop.c +++ b/capture_loop.c @@ -639,6 +639,9 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld, WORD wVersionRequested; WSADATA wsaData; #endif +#ifdef HAVE_PCAP_REMOTE + struct pcap_rmtauth auth; +#endif g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_open_input : %s", capture_opts->iface); @@ -697,11 +700,27 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld, 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 + auth.type = capture_opts->auth_type == CAPTURE_AUTH_PWD ? + RPCAP_RMTAUTH_PWD : RPCAP_RMTAUTH_NULL; + auth.username = capture_opts->auth_username; + auth.password = capture_opts->auth_password; + + ld->pcap_h = pcap_open(capture_opts->iface, + capture_opts->has_snaplen ? capture_opts->snaplen : + WTAP_MAX_PACKET_SIZE, + /* flags */ + (capture_opts->promisc_mode ? PCAP_OPENFLAG_PROMISCUOUS : 0) | + (capture_opts->datatx_udp ? PCAP_OPENFLAG_DATATX_UDP : 0) | + (capture_opts->nocap_rpcap ? PCAP_OPENFLAG_NOCAPTURE_RPCAP : 0), + CAP_READ_TIMEOUT, &auth, open_err_str); +#else ld->pcap_h = pcap_open_live(capture_opts->iface, capture_opts->has_snaplen ? capture_opts->snaplen : WTAP_MAX_PACKET_SIZE, capture_opts->promisc_mode, CAP_READ_TIMEOUT, open_err_str); +#endif if (ld->pcap_h != NULL) { /* we've opened "iface" as a network device */ @@ -720,6 +739,43 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld, } #endif +#if defined(HAVE_PCAP_REMOTE) && defined(HAVE_PCAP_SETSAMPLING) + if (capture_opts->sampling_method != CAPTURE_SAMP_NONE) + { + 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; + + case CAPTURE_SAMP_BY_TIMER: + samp->method = PCAP_SAMP_FIRST_AFTER_N_MS; + break; + + default: + sync_msg_str = g_strdup_printf( + "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); + 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"); + } + + } +#endif + /* setting the data link type only works on real interfaces */ if (capture_opts->linktype != -1) { set_linktype_err_str = set_pcap_linktype(ld->pcap_h, capture_opts->iface, diff --git a/capture_opts.c b/capture_opts.c index 6e9b63152c..a72f6c88f0 100644 --- a/capture_opts.c +++ b/capture_opts.c @@ -86,6 +86,21 @@ capture_opts_init(capture_options *capture_opts, void *cfile) capture_opts->cfilter = g_strdup(""); /* No capture filter string specified */ capture_opts->iface = NULL; /* Default is "pick the first interface" */ capture_opts->iface_descr = NULL; +#ifdef HAVE_PCAP_REMOTE + capture_opts->src_type = CAPTURE_IFLOCAL; + capture_opts->remote_host = NULL; + capture_opts->remote_port = NULL; + capture_opts->auth_type = CAPTURE_AUTH_NULL; + capture_opts->auth_username = NULL; + capture_opts->auth_password = NULL; + capture_opts->datatx_udp = FALSE; + capture_opts->nocap_rpcap = TRUE; + capture_opts->nocap_local = FALSE; +#ifdef HAVE_PCAP_SETSAMPLING + capture_opts->sampling_method = CAPTURE_SAMP_NONE; + capture_opts->sampling_param = 0; +#endif +#endif #ifdef _WIN32 capture_opts->buffer_size = 1; /* 1 MB */ #endif @@ -140,6 +155,27 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio /* iface_descr may not been filled in and some C Libraries hate a null ptr for %s */ g_log(log_domain, log_level, "Interface Descr : %s", capture_opts->iface_descr ? capture_opts->iface_descr : ""); +#ifdef HAVE_PCAP_REMOTE + g_log(log_domain, log_level, "Capture source : %s", + capture_opts->src_type == CAPTURE_IFLOCAL ? "Local interface" : + capture_opts->src_type == CAPTURE_IFREMOTE ? "Remote interface" : + "Unknown"); + if (capture_opts->src_type == CAPTURE_IFREMOTE) { + g_log(log_domain, log_level, "Remote host : %s", capture_opts->remote_host); + g_log(log_domain, log_level, "Remote port : %u", capture_opts->remote_port); + } + g_log(log_domain, log_level, "Authentication : %s", + capture_opts->auth_type == CAPTURE_AUTH_NULL ? "Null" : + capture_opts->auth_type == CAPTURE_AUTH_PWD ? "By username/password" : + "Unknown"); + if (capture_opts->auth_type == CAPTURE_AUTH_PWD) { + g_log(log_domain, log_level, "Auth username : %s", capture_opts->auth_password); + g_log(log_domain, log_level, "Auth password : "); + } + g_log(log_domain, log_level, "UDP data transfer : %u", capture_opts->datatx_udp); + g_log(log_domain, log_level, "No capture RPCAP : %u", capture_opts->nocap_rpcap); + g_log(log_domain, log_level, "No capture local : %u", capture_opts->nocap_local); +#endif #ifdef _WIN32 g_log(log_domain, log_level, "BufferSize : %u (MB)", capture_opts->buffer_size); #endif @@ -268,6 +304,73 @@ get_ring_arguments(capture_options *capture_opts, const char *arg) return TRUE; } +#ifdef HAVE_PCAP_SETSAMPLING +/* + * Given a string of the form ":", as might appear + * as an argument to a "-m" option, parse it and set the arguments in + * question. Return an indication of whether it succeeded or failed + * in some fashion. + */ +static gboolean +get_sampling_arguments(capture_options *capture_opts, const char *arg) +{ + gchar *p = NULL, *colonp; + + colonp = strchr(arg, ':'); + if (colonp == NULL) + return FALSE; + + p = colonp; + *p++ = '\0'; + + while (isspace((guchar)*p)) + p++; + if (*p == '\0') { + *colonp = ':'; + return FALSE; + } + + if (strcmp(arg, "count") == 0) { + capture_opts->sampling_method = CAPTURE_SAMP_BY_COUNT; + capture_opts->sampling_param = get_positive_int(p, "sampling count"); + } else if (strcmp(arg, "timer") == 0) { + capture_opts->sampling_method = CAPTURE_SAMP_BY_TIMER; + capture_opts->sampling_param = get_positive_int(p, "sampling timer"); + } + *colonp = ':'; + return TRUE; +} +#endif + +#ifdef HAVE_PCAP_REMOTE +/* + * Given a string of the form ":", as might appear + * as an argument to a "-A" option, parse it and set the arguments in + * question. Return an indication of whether it succeeded or failed + * in some fashion. + */ +static gboolean +get_auth_arguments(capture_options *capture_opts, const char *arg) +{ + gchar *p = NULL, *colonp; + + colonp = strchr(arg, ':'); + if (colonp == NULL) + return FALSE; + + p = colonp; + *p++ = '\0'; + + while (isspace((guchar)*p)) + p++; + + capture_opts->auth_type = CAPTURE_AUTH_PWD; + capture_opts->auth_username = g_strdup(arg); + capture_opts->auth_password = g_strdup(p); + *colonp = ':'; + return TRUE; +} +#endif static int capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg) @@ -348,6 +451,14 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, return 1; } break; +#ifdef HAVE_PCAP_REMOTE + case 'A': + if (get_auth_arguments(capture_opts, optarg) == FALSE) { + cmdarg_err("Invalid or unknown -A arg \"%s\"", optarg); + return 1; + } + break; +#endif case 'b': /* Ringbuffer option */ capture_opts->multi_files_on = TRUE; if (get_ring_arguments(capture_opts, optarg) == FALSE) { @@ -386,6 +497,14 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, *start_capture = TRUE; break; /*case 'l':*/ /* Automatic scrolling in live capture mode */ +#ifdef HAVE_PCAP_SETSAMPLING + case 'm': + if (get_sampling_arguments(capture_opts, optarg) == FALSE) { + cmdarg_err("Invalid or unknown -m arg \"%s\"", optarg); + return 1; + } + break; +#endif case 'p': /* Don't capture in promiscuous mode */ capture_opts->promisc_mode = FALSE; break; @@ -393,6 +512,11 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, capture_opts->quit_after_cap = TRUE; *start_capture = TRUE; /*** -Q implies -k !! ***/ break; +#ifdef HAVE_PCAP_REMOTE + case 'r': + capture_opts->nocap_rpcap = FALSE; + break; +#endif case 's': /* Set the snapshot (capture) length */ capture_opts->has_snaplen = TRUE; capture_opts->snaplen = get_positive_int(optarg, "snapshot length"); @@ -400,6 +524,11 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, case 'S': /* "Real-Time" mode: used for following file ala tail -f */ capture_opts->real_time_mode = TRUE; break; +#ifdef HAVE_PCAP_REMOTE + case 'u': + capture_opts->datatx_udp = TRUE; + break; +#endif case 'w': /* Write to capture file x */ capture_opts->saving_to_file = TRUE; g_free(capture_opts->save_file); diff --git a/capture_opts.h b/capture_opts.h index c47519329d..7b91c09473 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -40,6 +40,34 @@ typedef enum { CAPTURE_RUNNING /**< capture child signalled ok, capture is running now */ } capture_state; +#ifdef HAVE_PCAP_REMOTE +/* Type of capture source */ +typedef enum { + CAPTURE_IFLOCAL, /**< Local network interface */ + CAPTURE_IFREMOTE /**< Remote network interface */ +} capture_source; + +/* Type of RPCAPD Authentication */ +typedef enum { + CAPTURE_AUTH_NULL, /**< No authentication */ + CAPTURE_AUTH_PWD /**< User/password authentication */ +} capture_auth; + +#ifdef HAVE_PCAP_SETSAMPLING +/** + * Method of packet sampling (dropping some captured packets), + * may require additional integer parameter, marked here as N + */ +typedef enum { + CAPTURE_SAMP_NONE, /**< No sampling - capture all packets */ + CAPTURE_SAMP_BY_COUNT, /**< Counter-based sampling - + capture 1 packet from every N */ + CAPTURE_SAMP_BY_TIMER /**< Timer-based sampling - + capture no more than 1 packet + in N milliseconds */ +} capture_sampling; +#endif +#endif /** Capture options coming from user interface */ typedef struct capture_options_tag { @@ -55,7 +83,24 @@ typedef struct capture_options_tag { *< Readers of this field should use *< get_iface_description() from *< "capture_ui_utils.h" to access it. */ +#ifdef HAVE_PCAP_REMOTE + capture_source src_type; /**< Capturing on remote interface */ + gchar *remote_host; /**< Host name or network address + *< for remote capturing */ + gchar *remote_port; /**< TCP port of remote RPCAP server */ + capture_auth auth_type; + gchar *auth_username; + gchar *auth_password; /**< Remote authentication parameters */ + + gboolean datatx_udp; /**< Whether to use UDP for data transfer */ + gboolean nocap_rpcap; /**< Whether to capture RPCAP own traffic */ + gboolean nocap_local; /**< TODO: Whether to capture local traffic */ +#ifdef HAVE_PCAP_SETSAMPLING + capture_sampling sampling_method; /**< PCAP packet sampling method */ + int sampling_param; /**< PCAP packet sampling parameter */ +#endif +#endif #ifdef _WIN32 int buffer_size; /**< the capture buffer size (MB) */ #endif diff --git a/capture_sync.c b/capture_sync.c index d07f8a6151..b2cc825dd5 100644 --- a/capture_sync.c +++ b/capture_sync.c @@ -251,6 +251,12 @@ sync_pipe_start(capture_options *capture_opts) { char sautostop_files[ARGV_NUMBER_LEN]; char sautostop_filesize[ARGV_NUMBER_LEN]; char sautostop_duration[ARGV_NUMBER_LEN]; +#ifdef HAVE_PCAP_REMOTE + char sauth[256]; +#endif +#ifdef HAVE_PCAP_SETSAMPLING + char ssampling[ARGV_NUMBER_LEN]; +#endif #ifdef _WIN32 char buffer_size[ARGV_NUMBER_LEN]; HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */ @@ -352,6 +358,33 @@ sync_pipe_start(capture_options *capture_opts) { if (!capture_opts->promisc_mode) argv = sync_pipe_add_arg(argv, &argc, "-p"); +#ifdef HAVE_PCAP_REMOTE + if (capture_opts->datatx_udp) + argv = sync_pipe_add_arg(argv, &argc, "-u"); + + if (!capture_opts->nocap_rpcap) + argv = sync_pipe_add_arg(argv, &argc, "-r"); + + if (capture_opts->auth_type == CAPTURE_AUTH_PWD) + { + argv = sync_pipe_add_arg(argv, &argc, "-A"); + g_snprintf(sauth, sizeof(sauth), "%s:%s", capture_opts->auth_username, + capture_opts->auth_password); + argv = sync_pipe_add_arg(argv, &argc, sauth); + } +#endif +#ifdef HAVE_PCAP_SETSAMPLING + if (capture_opts->sampling_method != CAPTURE_SAMP_NONE) + { + argv = sync_pipe_add_arg(argv, &argc, "-m"); + g_snprintf(ssampling, ARGV_NUMBER_LEN, "%s:%d", + capture_opts->sampling_method == CAPTURE_SAMP_BY_COUNT ? "count" : + capture_opts->sampling_method == CAPTURE_SAMP_BY_TIMER ? "timer" : + "undef", + capture_opts->sampling_param); + argv = sync_pipe_add_arg(argv, &argc, ssampling); + } +#endif /* dumpcap should be running in capture child mode (hidden feature) */ #ifndef DEBUG_CHILD diff --git a/capture_ui_utils.c b/capture_ui_utils.c index 1d4b523dc6..aaa20eeb79 100644 --- a/capture_ui_utils.c +++ b/capture_ui_utils.c @@ -319,11 +319,13 @@ get_if_name(const char *if_text) * it'll be followed by a blank if it separates the description * and the interface name. (We don't wire in "rpcap", in case we * support other protocols in the same syntax.) + * Unfortunately, another colon can be used in "rpcap://host:port/" + * before port. Check if colon is followed by digit. */ - if (strncmp(if_name, "://", 3) != 0) { + if ((strncmp(if_name, "://", 3) != 0) && !isdigit(if_name[1])) { /* - * OK, we've found a colon not followed by "//". Skip blanks - * following it. + * OK, we've found a colon followed neither by "//" nor by digit. + * Skip blanks following it. */ if_name++; while (*if_name == ' ') diff --git a/config.h.win32 b/config.h.win32 index 617ada715e..1e4e1e583f 100644 --- a/config.h.win32 +++ b/config.h.win32 @@ -61,6 +61,13 @@ @WPCAP_CONSTIFIED@ @HAVE_LIBWIRESHARKDLL@ +@HAVE_REMOTE@ +@HAVE_PCAP_REMOTE@ +@HAVE_PCAP_OPEN@ +@HAVE_PCAP_FINDALLDEVS_EX@ +@HAVE_PCAP_CREATESRCSTR@ +@HAVE_PCAP_SETSAMPLING@ + @HAVE_AIRPCAP@ @HAVE_AIRPDCAP@ diff --git a/config.nmake b/config.nmake index 9dae3f36d8..af4abd9958 100644 --- a/config.nmake +++ b/config.nmake @@ -166,6 +166,12 @@ GTK_WIMP_DIR=$(WIRESHARK_LIBS)\gtk-wimp\gtk-wimp-0.7.0-bin # PCAP_DIR=$(WIRESHARK_LIBS)\WPdpack +# +# Optional: WinPcap remote capture support and new API +# (pcap_open(), pcap_findalldevs_ex(), etc.) +# +#PCAP_REMOTE=1 + # # Optional: The ZLib enables unzipping of gzip compressed capture files # "on the fly". @@ -690,6 +696,22 @@ PCAP_BREAKLOOP_CONFIG= WPCAP_CONSTIFIED= !ENDIF +!IF DEFINED(PCAP_DIR) && DEFINED(PCAP_REMOTE) +PCAP_HAVE_REMOTE_CONFIG=^#define HAVE_REMOTE 1 +PCAP_REMOTE_CONFIG=^#define HAVE_PCAP_REMOTE 1 +PCAP_OPEN_CONFIG=^#define HAVE_PCAP_OPEN 1 +PCAP_FINDALLDEVS_EX_CONFIG=^#define HAVE_PCAP_FINDALLDEVS_EX 1 +PCAP_CREATESRCSTR_CONFIG=^#define HAVE_PCAP_CREATESRCSTR 1 +PCAP_SETSAMPLING_CONFIG=^#define HAVE_PCAP_SETSAMPLING 1 +!ELSE +PCAP_HAVE_REMOTE_CONFIG= +PCAP_REMOTE_CONFIG= +PCAP_OPEN_CONFIG= +PCAP_FINDALLDEVS_EX_CONFIG= +PCAP_CREATESRCSTR_CONFIG= +PCAP_SETSAMPLING_CONFIG= +!ENDIF + !IFDEF ZLIB_DIR ZLIB_PATH=$(ZLIB_DIR) ZLIB_CFLAGS=/I$(ZLIB_DIR)\include diff --git a/configure.in b/configure.in index b4d50f1594..72c67e6cda 100644 --- a/configure.in +++ b/configure.in @@ -884,6 +884,28 @@ fi AC_SUBST(dumpcap_bin) AC_SUBST(dumpcap_man) +dnl pcap remote check +AC_MSG_CHECKING(whether to use libpcap remote capturing feature) + +AC_ARG_WITH(pcap-remote, +[ --with-pcap-remote use libpcap remote capturing (requires libpcap)], +[ + if test $withval = no + then + want_pcap_remote=no + else + want_pcap_remote=yes + fi +],[ + want_pcap_remote=no +]) +if test "x$want_pcap_remote" = "xno" -o "x$want_pcap" = "xno" ; then + AC_MSG_RESULT(no) +else + AC_MSG_RESULT(yes) + AC_WIRESHARK_PCAP_REMOTE_CHECK +fi + dnl zlib check AC_MSG_CHECKING(whether to use zlib for reading compressed capture files) diff --git a/dumpcap.c b/dumpcap.c index ed4f5fa81e..97a5dfbc30 100644 --- a/dumpcap.c +++ b/dumpcap.c @@ -138,6 +138,17 @@ print_usage(gboolean print_ver) { 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"); +#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"); +#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"); @@ -363,7 +374,11 @@ main(int argc, char *argv[]) gboolean print_statistics = FALSE; int status, run_once_args = 0; +#ifdef HAVE_PCAP_REMOTE +#define OPTSTRING_INIT "a:A:b:c:Df:hi:Lm:MprSs:uvw:y:Z:" +#else #define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z:" +#endif #ifdef _WIN32 #define OPTSTRING_WIN32 "B:" @@ -476,6 +491,14 @@ main(int argc, char *argv[]) case 's': /* Set the snapshot (capture) length */ case 'w': /* Write to capture file x */ case 'y': /* Set the pcap data link type */ +#ifdef HAVE_PCAP_REMOTE + case 'u': /* Use UDP for data transfer */ + case 'r': /* Capture own RPCAP traffic too */ + case 'A': /* Authentication */ +#endif +#ifdef HAVE_PCAP_SETSAMPLING + case 'm': /* Sampling */ +#endif #ifdef _WIN32 case 'B': /* Buffer size */ #endif /* _WIN32 */ diff --git a/epan/dissectors/packet-ldap.c b/epan/dissectors/packet-ldap.c index 96c8c84821..01204f4708 100644 --- a/epan/dissectors/packet-ldap.c +++ b/epan/dissectors/packet-ldap.c @@ -1,7 +1,7 @@ /* Do not modify this file. */ /* It is created automatically by the ASN.1 to Wireshark dissector compiler */ /* packet-ldap.c */ -/* ../../tools/asn2wrs.py -b -X -T -p ldap -c ./ldap.cnf -s ./packet-ldap-template -D . Lightweight-Directory-Access-Protocol-V3.asn */ +/* ../../tools/asn2wrs.py -b -X -T -p ldap -c ldap.cnf -s packet-ldap-template Lightweight-Directory-Access-Protocol-V3.asn */ /* Input file: packet-ldap-template.c */ diff --git a/epan/dissectors/packet-ldap.h b/epan/dissectors/packet-ldap.h index e100495869..60a3664a4d 100644 --- a/epan/dissectors/packet-ldap.h +++ b/epan/dissectors/packet-ldap.h @@ -1,7 +1,7 @@ /* Do not modify this file. */ /* It is created automatically by the ASN.1 to Wireshark dissector compiler */ /* packet-ldap.h */ -/* ../../tools/asn2wrs.py -b -X -T -p ldap -c ./ldap.cnf -s ./packet-ldap-template -D . Lightweight-Directory-Access-Protocol-V3.asn */ +/* ../../tools/asn2wrs.py -b -X -T -p ldap -c ldap.cnf -s packet-ldap-template Lightweight-Directory-Access-Protocol-V3.asn */ /* Input file: packet-ldap-template.h */ diff --git a/gtk/capture_dlg.c b/gtk/capture_dlg.c index 42e1ebd662..ebe1f9c010 100644 --- a/gtk/capture_dlg.c +++ b/gtk/capture_dlg.c @@ -115,6 +115,30 @@ #define E_CAP_N_RESOLVE_KEY "cap_n_resolve" #define E_CAP_T_RESOLVE_KEY "cap_t_resolve" +#ifdef HAVE_PCAP_REMOTE +#define E_CAP_IFTYPE_OM_KEY "cap_iftype_om" +#define E_CAP_DATATX_UDP_CB_KEY "cap_datatx_udp_cb" +#define E_CAP_NOCAP_RPCAP_CB_KEY "cap_nocap_rpcap_cb" +#define E_CAP_REMOTE_DIALOG_PTR_KEY "cap_remote_dialog" +#define E_CAP_REMOTE_CALLER_PTR_KEY "cap_remote_caller" +#define E_REMOTE_HOST_TE_KEY "cap_remote_host" +#define E_REMOTE_PORT_TE_KEY "cap_remote_port" +#define E_REMOTE_AUTH_NULL_KEY "cap_remote_auth_null" +#define E_REMOTE_AUTH_PASSWD_KEY "cap_remote_auth_passwd" +#define E_REMOTE_USERNAME_LB_KEY "cap_remote_username_lb" +#define E_REMOTE_USERNAME_TE_KEY "cap_remote_username_te" +#define E_REMOTE_PASSWD_LB_KEY "cap_remote_passwd_lb" +#define E_REMOTE_PASSWD_TE_KEY "cap_remote_passwd_te" +#define E_CAP_OM_IFTYPE_VALUE_KEY "cap_om_iftype_value" +#endif +#ifdef HAVE_PCAP_SETSAMPLING +#define E_CAP_SAMP_NONE_RB_KEY "cap_samp_none_rb" +#define E_CAP_SAMP_COUNT_RB_KEY "cap_samp_count_rb" +#define E_CAP_SAMP_COUNT_SB_KEY "cap_samp_count_sb" +#define E_CAP_SAMP_TIMER_RB_KEY "cap_samp_timer_rb" +#define E_CAP_SAMP_TIMER_SB_KEY "cap_samp_timer_sb" +#endif + #define E_CAP_OM_LT_VALUE_KEY "cap_om_lt_value" @@ -134,6 +158,14 @@ capture_prep_file_cb(GtkWidget *file_bt, GtkWidget *file_te); static void select_link_type_cb(GtkWidget *w, gpointer data); +#ifdef HAVE_PCAP_REMOTE +static void +select_if_type_cb(GtkWidget *w, gpointer data); + +static void +capture_remote_cb(GtkWidget *w, gpointer data); +#endif + static void capture_prep_adjust_sensitivity(GtkWidget *tb, gpointer parent_w); @@ -551,6 +583,314 @@ display_airpcap_advanced_cb(w,d); } #endif +#ifdef HAVE_PCAP_REMOTE +/* PCAP interface type menu item */ +struct iftype_info { + capture_source id; + const char *name; +}; + +/* List of available types of PCAP interface */ +static struct iftype_info iftype[] = { + { CAPTURE_IFLOCAL, "Local" }, + { CAPTURE_IFREMOTE, "Remote" } +}; + +/* Fill the menu of available types of interfaces */ +static GtkWidget * +iftype_option_menu_new(capture_source value) +{ + GtkWidget *iftype_om, *menu, *menu_item; + unsigned int i, active = 0; + + iftype_om = gtk_option_menu_new(); + menu = gtk_menu_new(); + + for (i = 0; i < sizeof(iftype) / sizeof(iftype[0]); i++) + { + menu_item = gtk_menu_item_new_with_label(iftype[i].name); + OBJECT_SET_DATA(menu_item, E_CAP_IFTYPE_OM_KEY, iftype_om); + SIGNAL_CONNECT(menu_item, "activate", select_if_type_cb, + GINT_TO_POINTER((int)iftype[i].id)); + gtk_menu_append(GTK_MENU(menu), menu_item); + if (value == iftype[i].id) + active = i; + } + + gtk_menu_set_active(GTK_MENU(menu), active); + gtk_option_menu_set_menu(GTK_OPTION_MENU(iftype_om), menu); + + return iftype_om; +} + +/* Retrieve the list of local or remote interfaces according to selected + * options and re-fill inteface name combobox */ +static void +update_interface_list() +{ + GtkWidget *if_cb; + GList *if_list, *combo_list; + int err; + gchar *err_str; + + if (cap_open_w == NULL) + return; + + if_cb = (GtkWidget *)OBJECT_GET_DATA(cap_open_w, E_CAP_IFACE_KEY); + + if (capture_opts->src_type == CAPTURE_IFREMOTE) + if_list = get_remote_interface_list(capture_opts->remote_host, + capture_opts->remote_port, + capture_opts->auth_type, + capture_opts->auth_username, + capture_opts->auth_password, + &err, &err_str); + else + if_list = get_interface_list(&err, &err_str); + + if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); + g_free(err_str); + + gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), NULL); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), ""); + } + combo_list = build_capture_combo_list(if_list, TRUE); + if (combo_list != NULL) + gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), combo_list); + + free_capture_combo_list(combo_list); + free_interface_list(if_list); +} + +/* User changed an interface entry of "Remote interface" dialog */ +static void +capture_remote_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) +{ + GtkWidget *auth_passwd_rb, + *username_lb, *username_te, + *passwd_lb, *passwd_te; + gboolean state; + + auth_passwd_rb = (GtkWidget *)OBJECT_GET_DATA(parent_w, + E_REMOTE_AUTH_PASSWD_KEY); + username_lb = (GtkWidget *)OBJECT_GET_DATA(parent_w, + E_REMOTE_USERNAME_LB_KEY); + username_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, + E_REMOTE_USERNAME_TE_KEY); + passwd_lb = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_REMOTE_PASSWD_LB_KEY); + passwd_te = (GtkWidget *)OBJECT_GET_DATA(parent_w, E_REMOTE_PASSWD_TE_KEY); + + state = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auth_passwd_rb)); + gtk_widget_set_sensitive(GTK_WIDGET(username_lb), state); + gtk_widget_set_sensitive(GTK_WIDGET(username_te), state); + gtk_widget_set_sensitive(GTK_WIDGET(passwd_lb), state); + gtk_widget_set_sensitive(GTK_WIDGET(passwd_te), state); +} + +/* user requested to destroy the dialog */ +static void +capture_remote_destroy_cb(GtkWidget *win, gpointer user_data _U_) +{ + GtkWidget *caller; + + caller = OBJECT_GET_DATA(win, E_CAP_REMOTE_CALLER_PTR_KEY); + OBJECT_SET_DATA(caller, E_CAP_REMOTE_DIALOG_PTR_KEY, NULL); +} + +/* user requested to accept remote interface options */ +static void +capture_remote_ok_cb(GtkWidget *win _U_, GtkWidget *remote_w) +{ + GtkWidget *host_te, *port_te, *auth_pwd_rb, *username_te, *passwd_te, + *auth_null_rb, *auth_passwd_rb; + + if (remote_w == NULL) + return; + + host_te = (GtkWidget *)OBJECT_GET_DATA(remote_w, E_REMOTE_HOST_TE_KEY); + port_te = (GtkWidget *)OBJECT_GET_DATA(remote_w, E_REMOTE_PORT_TE_KEY); + auth_pwd_rb = (GtkWidget *)OBJECT_GET_DATA(remote_w, + E_REMOTE_AUTH_PASSWD_KEY); + username_te = (GtkWidget *)OBJECT_GET_DATA(remote_w, + E_REMOTE_USERNAME_TE_KEY); + passwd_te = (GtkWidget *)OBJECT_GET_DATA(remote_w, E_REMOTE_PASSWD_TE_KEY); + auth_null_rb = (GtkWidget *) OBJECT_GET_DATA(remote_w, E_REMOTE_AUTH_NULL_KEY); + auth_passwd_rb = (GtkWidget *) OBJECT_GET_DATA(remote_w, E_REMOTE_AUTH_PASSWD_KEY); + + g_free(capture_opts->remote_host); + capture_opts->remote_host = g_strdup(gtk_entry_get_text(GTK_ENTRY(host_te))); + g_free(capture_opts->remote_port); + capture_opts->remote_port = g_strdup(gtk_entry_get_text(GTK_ENTRY(port_te))); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auth_passwd_rb))) + capture_opts->auth_type = CAPTURE_AUTH_PWD; + else + capture_opts->auth_type = CAPTURE_AUTH_NULL; + + g_free(capture_opts->auth_username); + capture_opts->auth_username = + g_strdup(gtk_entry_get_text(GTK_ENTRY(username_te))); + + g_free(capture_opts->auth_password); + capture_opts->auth_password = + g_strdup(gtk_entry_get_text(GTK_ENTRY(passwd_te))); + + capture_opts->src_type = CAPTURE_IFREMOTE; + + window_destroy(GTK_WIDGET(remote_w)); + update_interface_list(); +} + +/* Show remote capture interface parameters dialog */ +static void +capture_remote_cb(GtkWidget *w _U_, gpointer d _U_) +{ + GtkWidget *caller, *remote_w, + *main_vb, *host_tb, + *host_lb, *host_te, *port_lb, *port_te, + *auth_fr, *auth_vb, + *auth_null_rb, *auth_passwd_rb, *auth_passwd_tb, + *user_lb, *user_te, *passwd_lb, *passwd_te, + *bbox, *ok_bt, *cancel_bt; + gchar *title; + GtkTooltips *tooltips; + GSList *auth_group; + + caller = gtk_widget_get_toplevel(w); + remote_w = OBJECT_GET_DATA(caller, E_CAP_REMOTE_DIALOG_PTR_KEY); + if (remote_w != NULL) + { + reactivate_window(remote_w); + return; + } + + title = create_user_window_title("Wireshark: Remote Interface"); + remote_w = dlg_window_new(title); + OBJECT_SET_DATA(remote_w, E_CAP_REMOTE_CALLER_PTR_KEY, caller); + OBJECT_SET_DATA(caller, E_CAP_REMOTE_DIALOG_PTR_KEY, remote_w); + g_free(title); + + tooltips = gtk_tooltips_new(); + + main_vb = gtk_vbox_new(FALSE, 0); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(remote_w), main_vb); + + /* Host/port table */ + host_tb = gtk_table_new(2, 2, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(host_tb), 3); + gtk_table_set_col_spacings(GTK_TABLE(host_tb), 3); + gtk_box_pack_start(GTK_BOX(main_vb), host_tb, FALSE, FALSE, 0); + + /* Host row */ + host_lb = gtk_label_new("Host:"); + gtk_table_attach_defaults(GTK_TABLE(host_tb), host_lb, 0, 1, 0, 1); + + host_te = gtk_entry_new(); + gtk_tooltips_set_tip(tooltips, host_te, + "Enter the hostname or host IP address to be used as a source " + "for remote capture.", NULL); + gtk_table_attach_defaults(GTK_TABLE(host_tb), host_te, 1, 2, 0, 1); + if (capture_opts->remote_host != NULL) + gtk_entry_set_text(GTK_ENTRY(host_te), capture_opts->remote_host); + + /* Port row */ + port_lb = gtk_label_new("Port:"); + gtk_table_attach_defaults(GTK_TABLE(host_tb), port_lb, 0, 1, 1, 2); + + port_te = gtk_entry_new(); + gtk_tooltips_set_tip(tooltips, port_te, + "Enter the TCP port number used by RPCAP server at remote host " + "(leave it empty for default port number).", NULL); + gtk_table_attach_defaults(GTK_TABLE(host_tb), port_te, 1, 2, 1, 2); + if (capture_opts->remote_port != NULL) + gtk_entry_set_text(GTK_ENTRY(port_te), capture_opts->remote_port); + + /* Authentication options frame */ + auth_fr = gtk_frame_new("Authentication"); + gtk_container_add(GTK_CONTAINER(main_vb), auth_fr); + + auth_vb = gtk_vbox_new(FALSE, 3); + gtk_container_border_width(GTK_CONTAINER(auth_vb), 5); + gtk_container_add(GTK_CONTAINER(auth_fr), auth_vb); + + auth_null_rb = gtk_radio_button_new_with_label(NULL, + "Null authentication"); + gtk_box_pack_start(GTK_BOX(auth_vb), auth_null_rb, TRUE, TRUE, 0); + +#if GTK_MAJOR_VERSION >= 2 + auth_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(auth_null_rb)); +#else + auth_group = gtk_radio_button_group(GTK_RADIO_BUTTON(auth_null_rb)); +#endif + auth_passwd_rb = gtk_radio_button_new_with_label(auth_group, + "Password authentication"); + gtk_box_pack_start(GTK_BOX(auth_vb), auth_passwd_rb, TRUE, TRUE, 0); + SIGNAL_CONNECT(auth_passwd_rb, "toggled", capture_remote_adjust_sensitivity, + remote_w); + + auth_passwd_tb = gtk_table_new(2, 2, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(auth_passwd_tb), 3); + gtk_table_set_col_spacings(GTK_TABLE(auth_passwd_tb), 3); + gtk_box_pack_start(GTK_BOX(auth_vb), auth_passwd_tb, FALSE, FALSE, 0); + + user_lb = gtk_label_new("Username:"); + gtk_table_attach_defaults(GTK_TABLE(auth_passwd_tb), user_lb, 0, 1, 0, 1); + + user_te = gtk_entry_new(); + gtk_table_attach_defaults(GTK_TABLE(auth_passwd_tb), user_te, 1, 2, 0, 1); + if (capture_opts->auth_username != NULL) + gtk_entry_set_text(GTK_ENTRY(user_te), capture_opts->auth_username); + + passwd_lb = gtk_label_new("Password:"); + gtk_table_attach_defaults(GTK_TABLE(auth_passwd_tb), passwd_lb, 0, 1, 1, 2); + + passwd_te = gtk_entry_new(); + gtk_entry_set_visibility(GTK_ENTRY(passwd_te), FALSE); + gtk_table_attach_defaults(GTK_TABLE(auth_passwd_tb), passwd_te, 1, 2, 1, 2); + if (capture_opts->auth_password != NULL) + gtk_entry_set_text(GTK_ENTRY(passwd_te), capture_opts->auth_password); + + /* Button row: "Start" and "Cancel" buttons */ + bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL); + gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5); + + ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK); + SIGNAL_CONNECT(ok_bt, "clicked", capture_remote_ok_cb, remote_w); + gtk_tooltips_set_tip(tooltips, ok_bt, + "Accept remote host parameters and lookup " + "remote interfaces.", NULL); + + cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL); + gtk_tooltips_set_tip(tooltips, cancel_bt, + "Cancel and exit dialog.", NULL); + window_set_cancel_button(remote_w, cancel_bt, window_cancel_button_cb); + + gtk_widget_grab_default(ok_bt); + + SIGNAL_CONNECT(remote_w, "delete_event", window_delete_event_cb, NULL); + SIGNAL_CONNECT(remote_w, "destroy", capture_remote_destroy_cb, NULL); + + OBJECT_SET_DATA(remote_w, E_REMOTE_HOST_TE_KEY, host_te); + OBJECT_SET_DATA(remote_w, E_REMOTE_PORT_TE_KEY, port_te); + OBJECT_SET_DATA(remote_w, E_REMOTE_AUTH_NULL_KEY, auth_null_rb); + OBJECT_SET_DATA(remote_w, E_REMOTE_AUTH_PASSWD_KEY, auth_passwd_rb); + OBJECT_SET_DATA(remote_w, E_REMOTE_USERNAME_LB_KEY, user_lb); + OBJECT_SET_DATA(remote_w, E_REMOTE_USERNAME_TE_KEY, user_te); + OBJECT_SET_DATA(remote_w, E_REMOTE_PASSWD_LB_KEY, passwd_lb); + OBJECT_SET_DATA(remote_w, E_REMOTE_PASSWD_TE_KEY, passwd_te); + + if (capture_opts->auth_type == CAPTURE_AUTH_PWD) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(auth_passwd_rb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(auth_null_rb), TRUE); + capture_remote_adjust_sensitivity(NULL, remote_w); + + gtk_widget_show_all(remote_w); + window_present(remote_w); +} +#endif + /* show capture prepare (options) dialog */ void capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) @@ -591,6 +931,16 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) GtkWidget *advanced_hb, *advanced_bt; #endif #endif +#ifdef HAVE_PCAP_REMOTE + GtkWidget *iftype_om, *nocap_rpcap_cb, *datatx_udp_cb; +#ifdef HAVE_PCAP_SETSAMPLING + GtkWidget *sampling_fr, *sampling_vb, *sampling_tb, *sampling_lb, + *samp_none_rb, *samp_count_rb, *samp_timer_rb, + *samp_count_sb, *samp_timer_sb; + GtkAdjustment *samp_count_adj, *samp_timer_adj; + GSList *samp_group; +#endif +#endif #if GTK_MAJOR_VERSION < 2 GtkAccelGroup *accel_group; #endif @@ -631,7 +981,19 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) } #endif +#ifdef HAVE_PCAP_REMOTE + if (capture_opts->src_type == CAPTURE_IFREMOTE) + if_list = get_remote_interface_list(capture_opts->remote_host, + capture_opts->remote_port, + capture_opts->auth_type, + capture_opts->auth_username, + capture_opts->auth_password, + &err, &err_str); + else + if_list = get_interface_list(&err, &err_str); +#else if_list = capture_interface_list(&err, &err_str); +#endif if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) { simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str); g_free(err_str); @@ -690,6 +1052,11 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) if_lb = gtk_label_new("Interface:"); gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 6); +#ifdef HAVE_PCAP_REMOTE + iftype_om = iftype_option_menu_new(capture_opts->src_type); + gtk_box_pack_start(GTK_BOX(if_hb), iftype_om, FALSE, FALSE, 0); +#endif + if_cb = gtk_combo_new(); combo_list = build_capture_combo_list(if_list, TRUE); if (combo_list != NULL) @@ -806,6 +1173,21 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) "See the FAQ for some more details of capturing packets from a switched network.", NULL); gtk_container_add(GTK_CONTAINER(capture_vb), promisc_cb); +#ifdef HAVE_PCAP_REMOTE + /* RPCAP-related flags */ + nocap_rpcap_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC( + "Do not capture RPCAP own traffic", accel_group); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(nocap_rpcap_cb), + capture_opts->nocap_rpcap); + gtk_container_add(GTK_CONTAINER(capture_vb), nocap_rpcap_cb); + + datatx_udp_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC( + "Use UDP for RPCAP data transfer", accel_group); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(datatx_udp_cb), + capture_opts->datatx_udp); + gtk_container_add(GTK_CONTAINER(capture_vb), datatx_udp_cb); +#endif + /* Capture length row */ snap_hb = gtk_hbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(capture_vb), snap_hb); @@ -1145,6 +1527,77 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) gtk_adjustment_set_value(stop_duration_adj, (gfloat) value); row++; +#ifdef HAVE_PCAP_SETSAMPLING + /* Sampling options */ + sampling_fr = gtk_frame_new("Sampling Options"); + gtk_container_add(GTK_CONTAINER(right_vb), sampling_fr); + + sampling_vb = gtk_vbox_new(FALSE, 0); + gtk_container_border_width(GTK_CONTAINER(sampling_vb), 5); + gtk_container_add(GTK_CONTAINER(sampling_fr), sampling_vb); + + sampling_tb = gtk_table_new(3, 3, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(sampling_tb), 1); + gtk_table_set_col_spacings(GTK_TABLE(sampling_tb), 3); + gtk_box_pack_start(GTK_BOX(sampling_vb), sampling_tb, FALSE, FALSE, 0); + + /* "No sampling" row */ + samp_none_rb = gtk_radio_button_new_with_label(NULL, "None"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_none_rb), + (capture_opts->sampling_method == CAPTURE_SAMP_NONE)); + SIGNAL_CONNECT(samp_none_rb, "toggled", + capture_prep_adjust_sensitivity, cap_open_w); + gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_none_rb, 0, 1, 0, 1); + + /* "Sampling by counter" row */ +#if GTK_MAJOR_VERSION >= 2 + samp_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(samp_none_rb)); +#else + samp_group = gtk_radio_button_group(GTK_RADIO_BUTTON(samp_none_rb)); +#endif + samp_count_rb = gtk_radio_button_new_with_label(samp_group, "1 of"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_none_rb), + (capture_opts->sampling_method == CAPTURE_SAMP_BY_COUNT)); + SIGNAL_CONNECT(samp_count_rb, "toggled", + capture_prep_adjust_sensitivity, cap_open_w); + gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_count_rb, 0, 1, 1, 2); + + samp_count_adj = (GtkAdjustment *) gtk_adjustment_new( + (gfloat)capture_opts->sampling_param, + 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0); + samp_count_sb = gtk_spin_button_new(samp_count_adj, 0, 0); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(samp_count_sb), TRUE); + gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_count_sb, 1, 2, 1, 2); + + sampling_lb = gtk_label_new("packets"); + gtk_misc_set_alignment(GTK_MISC(sampling_lb), 0, 0.5); + gtk_table_attach_defaults(GTK_TABLE(sampling_tb), sampling_lb, 2, 3, 1, 2); + + /* "Sampling by timer" row */ +#if GTK_MAJOR_VERSION >= 2 + samp_group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(samp_count_rb)); +#else + samp_group = gtk_radio_button_group(GTK_RADIO_BUTTON(samp_count_rb)); +#endif + samp_timer_rb = gtk_radio_button_new_with_label(samp_group, "1 every"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(samp_none_rb), + (capture_opts->sampling_method == CAPTURE_SAMP_BY_TIMER)); + SIGNAL_CONNECT(samp_timer_rb, "toggled", + capture_prep_adjust_sensitivity, cap_open_w); + gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_timer_rb, 0, 1, 2, 3); + + samp_timer_adj = (GtkAdjustment *) gtk_adjustment_new( + (gfloat)capture_opts->sampling_param, + 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0); + samp_timer_sb = gtk_spin_button_new(samp_timer_adj, 0, 0); + gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(samp_timer_sb), TRUE); + gtk_table_attach_defaults(GTK_TABLE(sampling_tb), samp_timer_sb, 1, 2, 2, 3); + + sampling_lb = gtk_label_new("milliseconds"); + gtk_misc_set_alignment(GTK_MISC(sampling_lb), 0, 0.5); + gtk_table_attach_defaults(GTK_TABLE(sampling_tb), sampling_lb, 2, 3, 2, 3); +#endif + /* Display-related options frame */ display_fr = gtk_frame_new("Display Options"); gtk_container_add(GTK_CONTAINER(right_vb), display_fr); @@ -1236,6 +1689,12 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) /* Attach pointers to needed widgets to the capture prefs window/object */ OBJECT_SET_DATA(cap_open_w, E_CAP_IFACE_KEY, if_cb); +#ifdef HAVE_PCAP_REMOTE + OBJECT_SET_DATA(cap_open_w, E_CAP_IFTYPE_OM_KEY, iftype_om); + OBJECT_SET_DATA(cap_open_w, E_CAP_REMOTE_DIALOG_PTR_KEY, NULL); + OBJECT_SET_DATA(cap_open_w, E_CAP_NOCAP_RPCAP_CB_KEY, nocap_rpcap_cb); + OBJECT_SET_DATA(cap_open_w, E_CAP_DATATX_UDP_CB_KEY, datatx_udp_cb); +#endif OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_CB_KEY, snap_cb); OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_SB_KEY, snap_sb); OBJECT_SET_DATA(cap_open_w, E_CAP_LT_OM_KEY, linktype_om); @@ -1273,6 +1732,13 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) OBJECT_SET_DATA(cap_open_w, E_CAP_M_RESOLVE_KEY, m_resolv_cb); OBJECT_SET_DATA(cap_open_w, E_CAP_N_RESOLVE_KEY, n_resolv_cb); OBJECT_SET_DATA(cap_open_w, E_CAP_T_RESOLVE_KEY, t_resolv_cb); +#ifdef HAVE_PCAP_SETSAMPLING + OBJECT_SET_DATA(cap_open_w, E_CAP_SAMP_NONE_RB_KEY, samp_none_rb); + OBJECT_SET_DATA(cap_open_w, E_CAP_SAMP_COUNT_RB_KEY, samp_count_rb); + OBJECT_SET_DATA(cap_open_w, E_CAP_SAMP_COUNT_SB_KEY, samp_count_sb); + OBJECT_SET_DATA(cap_open_w, E_CAP_SAMP_TIMER_RB_KEY, samp_timer_rb); + OBJECT_SET_DATA(cap_open_w, E_CAP_SAMP_TIMER_SB_KEY, samp_timer_sb); +#endif /* Set the sensitivity of various widgets as per the settings of other widgets. */ @@ -1441,6 +1907,33 @@ select_link_type_cb(GtkWidget *w, gpointer data) } } +#ifdef HAVE_PCAP_REMOTE +/* user selected an interface type (local/remote), convert to internal value) */ +static void +select_if_type_cb(GtkWidget *w, gpointer data) +{ + int new_iftype = GPOINTER_TO_INT(data); + GtkWidget *iftype_om = OBJECT_GET_DATA(w, E_CAP_IFTYPE_OM_KEY); + int old_iftype = GPOINTER_TO_INT(OBJECT_GET_DATA(iftype_om, + E_CAP_OM_IFTYPE_VALUE_KEY)); + + if (old_iftype != new_iftype) + { + OBJECT_SET_DATA(iftype_om, E_CAP_OM_IFTYPE_VALUE_KEY, + GINT_TO_POINTER(new_iftype)); + } + if (new_iftype == CAPTURE_IFREMOTE) + { + capture_remote_cb(iftype_om, NULL); + } + else if (new_iftype != old_iftype) + { + capture_opts->src_type = CAPTURE_IFLOCAL; + update_interface_list(); + } +} +#endif + /* user pressed "File" button */ static void capture_prep_file_cb(GtkWidget *file_bt, GtkWidget *file_te) @@ -1462,6 +1955,13 @@ capture_dlg_prep(gpointer parent_w) { *file_duration_cb, *file_duration_sb, *file_duration_om, *stop_files_cb, *stop_files_sb, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb; +#ifdef HAVE_PCAP_REMOTE + GtkWidget *iftype_om, *datatx_udp_cb, *nocap_rpcap_cb; +#endif +#ifdef HAVE_PCAP_SETSAMPLING + GtkWidget *samp_none_rb, *samp_count_rb, *samp_timer_rb, + *samp_count_sb, *samp_timer_sb; +#endif #ifdef _WIN32 GtkWidget *buffer_size_sb; #endif @@ -1475,6 +1975,11 @@ capture_dlg_prep(gpointer parent_w) { gint32 tmp; if_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY); +#ifdef HAVE_PCAP_REMOTE + iftype_om = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFTYPE_OM_KEY); + datatx_udp_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DATATX_UDP_CB_KEY); + nocap_rpcap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_NOCAP_RPCAP_CB_KEY); +#endif snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY); snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY); linktype_om = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_OM_KEY); @@ -1510,6 +2015,13 @@ capture_dlg_prep(gpointer parent_w) { m_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_M_RESOLVE_KEY); n_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_N_RESOLVE_KEY); t_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_T_RESOLVE_KEY); +#ifdef HAVE_PCAP_SETSAMPLING + samp_none_rb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_NONE_RB_KEY); + samp_count_rb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_COUNT_RB_KEY); + samp_timer_rb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_TIMER_RB_KEY); + samp_count_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_COUNT_SB_KEY); + samp_timer_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_TIMER_SB_KEY); +#endif entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry))); @@ -1533,6 +2045,31 @@ capture_dlg_prep(gpointer parent_w) { /* capture_opts->linktype = GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY)); */ +#ifdef HAVE_PCAP_REMOTE + capture_opts->src_type = (capture_source) + GPOINTER_TO_INT(OBJECT_GET_DATA(iftype_om, E_CAP_OM_IFTYPE_VALUE_KEY)); + capture_opts->datatx_udp = + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(datatx_udp_cb)); + capture_opts->nocap_rpcap = + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(nocap_rpcap_cb)); +#endif +#ifdef HAVE_PCAP_SETSAMPLING + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_none_rb))) + capture_opts->sampling_method = CAPTURE_SAMP_NONE; + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_count_rb))) + { + capture_opts->sampling_method = CAPTURE_SAMP_BY_COUNT; + capture_opts->sampling_param = gtk_spin_button_get_value_as_int( + GTK_SPIN_BUTTON(samp_count_sb)); + } + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_timer_rb))) + { + capture_opts->sampling_method = CAPTURE_SAMP_BY_TIMER; + capture_opts->sampling_param = gtk_spin_button_get_value_as_int( + GTK_SPIN_BUTTON(samp_timer_sb)); + } +#endif + #ifdef _WIN32 capture_opts->buffer_size = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(buffer_size_sb)); @@ -1703,6 +2240,9 @@ static void capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_) { GtkWidget *fs; +#ifdef HAVE_PCAP_REMOTE + GtkWidget *remote_w; +#endif /* Is there a file selection dialog associated with this Capture Options dialog? */ @@ -1720,6 +2260,12 @@ capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_) /* update airpcap toolbar */ airpcap_set_toolbar_stop_capture(airpcap_if_active); #endif + +#ifdef HAVE_PCAP_REMOTE + remote_w = OBJECT_GET_DATA(win, E_CAP_REMOTE_DIALOG_PTR_KEY); + if (remote_w != NULL) + window_destroy(remote_w); +#endif } /* user changed the interface entry */ @@ -1751,6 +2297,10 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) *stop_filesize_cb, *stop_filesize_sb, *stop_filesize_om, *stop_duration_cb, *stop_duration_sb, *stop_duration_om, *stop_files_cb, *stop_files_sb, *stop_files_lb; +#ifdef HAVE_PCAP_SETSAMPLING + GtkWidget *samp_count_rb, *samp_timer_rb, + *samp_count_sb, *samp_timer_sb; +#endif if_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY); @@ -1781,6 +2331,12 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) stop_files_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_STOP_FILES_CB_KEY); stop_files_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_STOP_FILES_SB_KEY); stop_files_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_STOP_FILES_LB_KEY); +#ifdef HAVE_PCAP_SETSAMPLING + samp_count_rb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_COUNT_RB_KEY); + samp_timer_rb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_TIMER_RB_KEY); + samp_count_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_COUNT_SB_KEY); + samp_timer_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SAMP_TIMER_SB_KEY); +#endif /* The snapshot length spinbox is sensitive if the "Limit each packet to" checkbox is on. */ @@ -1895,6 +2451,13 @@ capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(stop_duration_cb))); gtk_widget_set_sensitive(GTK_WIDGET(stop_duration_om), gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(stop_duration_cb))); + +#ifdef HAVE_PCAP_SETSAMPLING + gtk_widget_set_sensitive(GTK_WIDGET(samp_count_sb), + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_count_rb))); + gtk_widget_set_sensitive(GTK_WIDGET(samp_timer_sb), + gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(samp_timer_rb))); +#endif } #endif /* HAVE_LIBPCAP */