forked from osmocom/wireshark
Add a "-S" flag to dumpcap, which prints out interface statistics. Use
this in the GUI rather than calling pcap_stats() directly. This gets rid of the last pcap_open_live() call in the GUI code. Update README.packaging. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@22443 f5534014-38df-0310-8fa8-9805f1628bb7
This commit is contained in:
parent
5f3cf2a8f2
commit
e5997f6643
|
@ -72,7 +72,7 @@ GList *get_interface_list(int *err, char **err_str);
|
||||||
/* Error values from "get_interface_list()/capture_interface_list()". */
|
/* Error values from "get_interface_list()/capture_interface_list()". */
|
||||||
#define CANT_GET_INTERFACE_LIST 1 /* error getting list */
|
#define CANT_GET_INTERFACE_LIST 1 /* error getting list */
|
||||||
#define NO_INTERFACES_FOUND 2 /* list is empty */
|
#define NO_INTERFACES_FOUND 2 /* list is empty */
|
||||||
#define CANT_RUN_DUMPCAP 3 /* problem running 'dumpcap -I l' */
|
#define CANT_RUN_DUMPCAP 3 /* problem running dumpcap */
|
||||||
|
|
||||||
void free_interface_list(GList *if_list);
|
void free_interface_list(GList *if_list);
|
||||||
|
|
||||||
|
|
139
capture.c
139
capture.c
|
@ -44,14 +44,18 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h> /* needed to define AF_ values on UNIX */
|
#include <sys/socket.h> /* needed to define AF_ values on UNIX */
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,7 +96,16 @@
|
||||||
#include "file_util.h"
|
#include "file_util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
typedef struct if_stat_cache_item_s {
|
||||||
|
char *name;
|
||||||
|
struct pcap_stat ps;
|
||||||
|
} if_stat_cache_item_t;
|
||||||
|
|
||||||
|
struct if_stat_cache_s {
|
||||||
|
int stat_fd;
|
||||||
|
int fork_child;
|
||||||
|
GList *cache_list; /* List of if_stat_chache_entry_t */
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a capture.
|
* Start a capture.
|
||||||
|
@ -675,7 +688,7 @@ capture_interface_list(int *err, char **err_str)
|
||||||
|
|
||||||
/* Check to see if we built a list */
|
/* Check to see if we built a list */
|
||||||
if (if_list == NULL) {
|
if (if_list == NULL) {
|
||||||
if (*err_str)
|
if (err_str && *err_str)
|
||||||
*err_str = g_strdup("No interfaces found");
|
*err_str = g_strdup("No interfaces found");
|
||||||
*err = NO_INTERFACES_FOUND;
|
*err = NO_INTERFACES_FOUND;
|
||||||
}
|
}
|
||||||
|
@ -722,7 +735,7 @@ capture_pcap_linktype_list(gchar *ifname, char **err_str)
|
||||||
data_link_info = g_malloc(sizeof (data_link_info_t));
|
data_link_info = g_malloc(sizeof (data_link_info_t));
|
||||||
data_link_info->dlt = (int) strtol(lt_parts[0], NULL, 10);
|
data_link_info->dlt = (int) strtol(lt_parts[0], NULL, 10);
|
||||||
data_link_info->name = g_strdup(lt_parts[1]);
|
data_link_info->name = g_strdup(lt_parts[1]);
|
||||||
if (strcmp(lt_parts[2], "(not supported)") != NULL)
|
if (strcmp(lt_parts[2], "(not supported)") != 0)
|
||||||
data_link_info->description = g_strdup(lt_parts[2]);
|
data_link_info->description = g_strdup(lt_parts[2]);
|
||||||
else
|
else
|
||||||
data_link_info->description = NULL;
|
data_link_info->description = NULL;
|
||||||
|
@ -739,5 +752,119 @@ capture_pcap_linktype_list(gchar *ifname, char **err_str)
|
||||||
return linktype_list;
|
return linktype_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if_stat_cache_t *
|
||||||
|
capture_stat_start(GList *if_list) {
|
||||||
|
int stat_fd, fork_child;
|
||||||
|
gchar *msg;
|
||||||
|
if_stat_cache_t *sc = NULL;
|
||||||
|
GList *if_entry;
|
||||||
|
if_info_t *if_info;
|
||||||
|
if_stat_cache_item_t *sc_item;
|
||||||
|
|
||||||
|
/* Fire up dumpcap. */
|
||||||
|
/*
|
||||||
|
* XXX - on systems with BPF, the number of BPF devices limits the
|
||||||
|
* number of devices on which you can capture simultaneously.
|
||||||
|
*
|
||||||
|
* This means that
|
||||||
|
*
|
||||||
|
* 1) this might fail if you run out of BPF devices
|
||||||
|
*
|
||||||
|
* and
|
||||||
|
*
|
||||||
|
* 2) opening every interface could leave too few BPF devices
|
||||||
|
* for *other* programs.
|
||||||
|
*
|
||||||
|
* It also means the system could end up getting a lot of traffic
|
||||||
|
* that it has to pass through the networking stack and capture
|
||||||
|
* mechanism, so opening all the devices and presenting packet
|
||||||
|
* counts might not always be a good idea.
|
||||||
|
*/
|
||||||
|
if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
|
||||||
|
sc = g_malloc(sizeof(if_stat_cache_t));
|
||||||
|
sc->stat_fd = stat_fd;
|
||||||
|
sc->fork_child = fork_child;
|
||||||
|
sc->cache_list = NULL;
|
||||||
|
|
||||||
|
/* Initialize the cache */
|
||||||
|
for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
|
||||||
|
if_info = if_entry->data;
|
||||||
|
sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
|
||||||
|
sc_item->name = g_strdup(if_info->name);
|
||||||
|
sc->cache_list = g_list_append(sc->cache_list, sc_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_STAT_LINE_LEN 500
|
||||||
|
|
||||||
|
static void
|
||||||
|
capture_stat_cache_update(if_stat_cache_t *sc) {
|
||||||
|
gchar stat_line[MAX_STAT_LINE_LEN];
|
||||||
|
gchar **stat_parts;
|
||||||
|
GList *sc_entry;
|
||||||
|
if_stat_cache_item_t *sc_item;
|
||||||
|
|
||||||
|
if (!sc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
|
||||||
|
g_strstrip(stat_line);
|
||||||
|
stat_parts = g_strsplit(stat_line, "\t", 3);
|
||||||
|
if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
|
||||||
|
stat_parts[2] == NULL) {
|
||||||
|
g_strfreev(stat_parts);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
|
||||||
|
sc_item = sc_entry->data;
|
||||||
|
if (strcmp(sc_item->name, stat_parts[0]) == 0) {
|
||||||
|
sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
|
||||||
|
sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_strfreev(stat_parts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
|
||||||
|
GList *sc_entry;
|
||||||
|
if_stat_cache_item_t *sc_item;
|
||||||
|
|
||||||
|
if (!sc || !ifname || !ps) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
capture_stat_cache_update(sc);
|
||||||
|
for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
|
||||||
|
sc_item = sc_entry->data;
|
||||||
|
if (strcmp(sc_item->name, ifname) == 0) {
|
||||||
|
memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
capture_stat_stop(if_stat_cache_t *sc) {
|
||||||
|
GList *sc_entry;
|
||||||
|
if_stat_cache_item_t *sc_item;
|
||||||
|
gchar *msg;
|
||||||
|
|
||||||
|
if (!sc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
|
||||||
|
|
||||||
|
for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
|
||||||
|
sc_item = sc_entry->data;
|
||||||
|
g_free(sc_item->name);
|
||||||
|
g_free(sc_item);
|
||||||
|
}
|
||||||
|
g_free(sc);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HAVE_LIBPCAP */
|
#endif /* HAVE_LIBPCAP */
|
||||||
|
|
23
capture.h
23
capture.h
|
@ -81,6 +81,7 @@ extern void capture_input_cfilter_error_message(capture_options *capture_opts, c
|
||||||
*/
|
*/
|
||||||
extern void capture_input_closed(capture_options *capture_opts);
|
extern void capture_input_closed(capture_options *capture_opts);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBPCAP
|
||||||
/**
|
/**
|
||||||
* Fetch the interface list from a child process.
|
* Fetch the interface list from a child process.
|
||||||
*/
|
*/
|
||||||
|
@ -92,4 +93,26 @@ extern GList *capture_interface_list(int *err, char **err_str);
|
||||||
extern GList *capture_pcap_linktype_list(char *devname, char **err_str);
|
extern GList *capture_pcap_linktype_list(char *devname, char **err_str);
|
||||||
|
|
||||||
|
|
||||||
|
struct if_stat_cache_s;
|
||||||
|
typedef struct if_stat_cache_s if_stat_cache_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start gathering capture statistics for the interfaces specified.
|
||||||
|
* @param A GList of if_info_t items
|
||||||
|
* @return A pointer to the statistics state data.
|
||||||
|
*/
|
||||||
|
extern if_stat_cache_t * capture_stat_start(GList *if_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch capture statistics, similar to pcap_stats().
|
||||||
|
*/
|
||||||
|
struct pcap_stat; /* Stub in case we don't or haven't yet included pcap.h */
|
||||||
|
extern gboolean capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop gathering capture statistics.
|
||||||
|
*/
|
||||||
|
void capture_stat_stop(if_stat_cache_t *sc);
|
||||||
|
#endif /* HAVE_LIBPCAP */
|
||||||
|
|
||||||
#endif /* capture.h */
|
#endif /* capture.h */
|
||||||
|
|
|
@ -31,6 +31,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,6 +72,10 @@
|
||||||
#include "capture-pcap-util.h"
|
#include "capture-pcap-util.h"
|
||||||
#include <wiretap/file_util.h>
|
#include <wiretap/file_util.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *name;
|
||||||
|
pcap_t *pch;
|
||||||
|
} if_stat_t;
|
||||||
|
|
||||||
static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe);
|
static gboolean capture_opts_output_to_pipe(const char *save_file, gboolean *is_pipe);
|
||||||
|
|
||||||
|
@ -558,6 +566,90 @@ capture_opts_list_interfaces(gboolean machine_readable)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print the number of packets captured for each interface until we're killed. */
|
||||||
|
int
|
||||||
|
capture_opts_print_statistics(gboolean machine_readable)
|
||||||
|
{
|
||||||
|
GList *if_list, *if_entry, *stat_list = NULL, *stat_entry;
|
||||||
|
if_info_t *if_info;
|
||||||
|
if_stat_t *if_stat;
|
||||||
|
int err;
|
||||||
|
gchar *err_str;
|
||||||
|
pcap_t *pch;
|
||||||
|
char errbuf[PCAP_ERRBUF_SIZE];
|
||||||
|
struct pcap_stat ps;
|
||||||
|
|
||||||
|
if_list = get_interface_list(&err, &err_str);
|
||||||
|
if (if_list == NULL) {
|
||||||
|
switch (err) {
|
||||||
|
case CANT_GET_INTERFACE_LIST:
|
||||||
|
cmdarg_err("%s", err_str);
|
||||||
|
g_free(err_str);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NO_INTERFACES_FOUND:
|
||||||
|
cmdarg_err("There are no interfaces on which a capture can be done");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (if_entry = g_list_first(if_list); if_entry != NULL; if_entry = g_list_next(if_entry)) {
|
||||||
|
if_info = if_entry->data;
|
||||||
|
pch = pcap_open_live(if_info->name, MIN_PACKET_SIZE, 0, 0, errbuf);
|
||||||
|
|
||||||
|
if (pch) {
|
||||||
|
if_stat = g_malloc(sizeof(if_stat_t));
|
||||||
|
if_stat->name = g_strdup(if_info->name);
|
||||||
|
if_stat->pch = pch;
|
||||||
|
stat_list = g_list_append(stat_list, if_stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stat_list) {
|
||||||
|
cmdarg_err("There are no interfaces on which a capture can be done");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!machine_readable) {
|
||||||
|
printf("%-15s %10s %10s\n", "Interface", "Received",
|
||||||
|
"Dropped");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) { /* XXX - Add signal handling? */
|
||||||
|
for (stat_entry = g_list_first(stat_list); stat_entry != NULL; stat_entry = g_list_next(stat_entry)) {
|
||||||
|
if_stat = stat_entry->data;
|
||||||
|
pcap_stats(if_stat->pch, &ps);
|
||||||
|
|
||||||
|
if (!machine_readable) {
|
||||||
|
printf("%-15s %10d %10d\n", if_stat->name,
|
||||||
|
ps.ps_recv, ps.ps_drop);
|
||||||
|
} else {
|
||||||
|
printf("%s\t%d\t%d\n", if_stat->name,
|
||||||
|
ps.ps_recv, ps.ps_drop);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
Sleep(1 * 1000);
|
||||||
|
#else
|
||||||
|
sleep(1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX - Not reached. Should we look for 'q' in stdin? */
|
||||||
|
for (stat_entry = g_list_first(stat_list); stat_entry != NULL; stat_entry = g_list_next(stat_entry)) {
|
||||||
|
if_stat = stat_entry->data;
|
||||||
|
pcap_close(if_stat->pch);
|
||||||
|
g_free(if_stat->name);
|
||||||
|
g_free(if_stat);
|
||||||
|
}
|
||||||
|
g_list_free(stat_list);
|
||||||
|
free_interface_list(if_list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min)
|
void capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min)
|
||||||
{
|
{
|
||||||
|
|
|
@ -120,6 +120,10 @@ capture_opts_list_link_layer_types(capture_options *capture_opts, gboolean machi
|
||||||
extern int
|
extern int
|
||||||
capture_opts_list_interfaces(gboolean machine_readable);
|
capture_opts_list_interfaces(gboolean machine_readable);
|
||||||
|
|
||||||
|
/* print interface statistics */
|
||||||
|
extern int
|
||||||
|
capture_opts_print_statistics(gboolean machine_readable);
|
||||||
|
|
||||||
/* trim the snaplen entry */
|
/* trim the snaplen entry */
|
||||||
extern void
|
extern void
|
||||||
capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min);
|
capture_opts_trim_snaplen(capture_options *capture_opts, int snaplen_min);
|
||||||
|
|
212
capture_sync.c
212
capture_sync.c
|
@ -37,10 +37,13 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <fcntl.h>
|
|
||||||
#include "epan/unicode-utils.h"
|
#include "epan/unicode-utils.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -523,15 +526,17 @@ sync_pipe_start(capture_options *capture_opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Run dumpcap with the supplied arguments. On success, msg points to
|
* Open dumpcap with the supplied arguments. On success, msg points to
|
||||||
* a buffer containing the dumpcap output and returns 0. On failure, msg
|
* a buffer containing the dumpcap output and returns 0. read_fd and
|
||||||
* points to the error message returned by dumpcap, and returns dumpcap's
|
* fork_child point to the pipe's file descriptor and child PID/handle,
|
||||||
* exit value. In either case, msg must be freed with g_free().
|
* respectively. On failure, msg points to the error message returned by
|
||||||
|
* dumpcap, and returns dumpcap's exit value. In either case, msg must be
|
||||||
|
* freed with g_free().
|
||||||
*/
|
*/
|
||||||
/* XXX - This duplicates a lot of code in sync_pipe_start() */
|
/* XXX - This duplicates a lot of code in sync_pipe_start() */
|
||||||
#define PIPE_BUF_SIZE 5120
|
#define PIPE_BUF_SIZE 5120
|
||||||
static int
|
static int
|
||||||
sync_pipe_run_command(const char** argv, gchar **msg) {
|
sync_pipe_open_command(const char** argv, int *read_fd, int *fork_child, gchar **msg) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */
|
HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */
|
||||||
HANDLE sync_pipe_write; /* pipe used to send messages from parent to child */
|
HANDLE sync_pipe_write; /* pipe used to send messages from parent to child */
|
||||||
|
@ -545,12 +550,9 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
int sync_pipe[2]; /* pipe used to send messages from child to parent */
|
int sync_pipe[2]; /* pipe used to send messages from child to parent */
|
||||||
enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
|
enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
|
||||||
#endif
|
#endif
|
||||||
int fork_child = -1, fork_child_status;
|
|
||||||
int sync_pipe_read_fd = -1;
|
|
||||||
GString *msg_buf = NULL;
|
|
||||||
gchar buf[PIPE_BUF_SIZE+1];
|
|
||||||
int count;
|
|
||||||
|
|
||||||
|
*fork_child = -1;
|
||||||
|
*read_fd = -1;
|
||||||
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_run_command");
|
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_run_command");
|
||||||
|
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
|
@ -613,12 +615,12 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
g_free( (gpointer) argv);
|
g_free( (gpointer) argv);
|
||||||
return CANT_RUN_DUMPCAP;
|
return CANT_RUN_DUMPCAP;
|
||||||
}
|
}
|
||||||
fork_child = (int) pi.hProcess;
|
*fork_child = (int) pi.hProcess;
|
||||||
g_string_free(args, TRUE);
|
g_string_free(args, TRUE);
|
||||||
|
|
||||||
/* associate the operating system filehandle to a C run-time file handle */
|
/* associate the operating system filehandle to a C run-time file handle */
|
||||||
/* (good file handle infos at: http://www.flounder.com/handles.htm) */
|
/* (good file handle infos at: http://www.flounder.com/handles.htm) */
|
||||||
sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
|
*read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
|
||||||
|
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
if (pipe(sync_pipe) < 0) {
|
if (pipe(sync_pipe) < 0) {
|
||||||
|
@ -629,7 +631,7 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
return CANT_RUN_DUMPCAP;
|
return CANT_RUN_DUMPCAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fork_child = fork()) == 0) {
|
if ((*fork_child = fork()) == 0) {
|
||||||
/*
|
/*
|
||||||
* Child process - run dumpcap with the right arguments to make
|
* Child process - run dumpcap with the right arguments to make
|
||||||
* it just capture with the specified capture parameters
|
* it just capture with the specified capture parameters
|
||||||
|
@ -643,7 +645,7 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
return CANT_RUN_DUMPCAP;
|
return CANT_RUN_DUMPCAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_pipe_read_fd = sync_pipe[PIPE_READ];
|
*read_fd = sync_pipe[PIPE_READ];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
g_free( (gpointer) argv[0]); /* exename */
|
g_free( (gpointer) argv[0]); /* exename */
|
||||||
|
@ -662,31 +664,34 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
eth_close(sync_pipe[PIPE_WRITE]);
|
eth_close(sync_pipe[PIPE_WRITE]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fork_child == -1) {
|
if (*fork_child == -1) {
|
||||||
/* We couldn't even create the child process. */
|
/* We couldn't even create the child process. */
|
||||||
*msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
|
*msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
|
||||||
eth_close(sync_pipe_read_fd);
|
eth_close(*read_fd);
|
||||||
return CANT_RUN_DUMPCAP;
|
return CANT_RUN_DUMPCAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we might wait for a moment till child is ready, so update screen now */
|
/* we might wait for a moment till child is ready, so update screen now */
|
||||||
main_window_update();
|
main_window_update();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* We were able to set up to read dumpcap's output. Do so and
|
static int
|
||||||
return its exit value. */
|
#ifdef _WIN32
|
||||||
msg_buf = g_string_new("");
|
sync_pipe_close_command(int *read_fd, int *fork_child, gchar **msg) {
|
||||||
while ((count = eth_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
|
#else
|
||||||
buf[count] = '\0';
|
sync_pipe_close_command(int *read_fd, gchar **msg) {
|
||||||
g_string_append(msg_buf, buf);
|
#endif
|
||||||
}
|
int fork_child_status;
|
||||||
|
|
||||||
eth_close(sync_pipe_read_fd);
|
eth_close(*read_fd);
|
||||||
|
|
||||||
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open: wait till child closed");
|
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open: wait till child closed");
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (_cwait(&fork_child_status, fork_child, _WAIT_CHILD) == -1) {
|
/* XXX - Should we signal the child somehow? */
|
||||||
g_string_free(msg_buf, TRUE);
|
sync_pipe_kill(*fork_child);
|
||||||
|
if (_cwait(&fork_child_status, *fork_child, _WAIT_CHILD) == -1) {
|
||||||
*msg = g_strdup_printf("Child capture process stopped unexpectedly "
|
*msg = g_strdup_printf("Child capture process stopped unexpectedly "
|
||||||
"(errno:%u)", errno);
|
"(errno:%u)", errno);
|
||||||
return CANT_RUN_DUMPCAP;
|
return CANT_RUN_DUMPCAP;
|
||||||
|
@ -697,7 +702,6 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
/* The child exited. */
|
/* The child exited. */
|
||||||
fork_child_status = WEXITSTATUS(fork_child_status);
|
fork_child_status = WEXITSTATUS(fork_child_status);
|
||||||
} else {
|
} else {
|
||||||
g_string_free(msg_buf, TRUE);
|
|
||||||
if (WIFSTOPPED(fork_child_status)) {
|
if (WIFSTOPPED(fork_child_status)) {
|
||||||
/* It stopped, rather than exiting. "Should not happen." */
|
/* It stopped, rather than exiting. "Should not happen." */
|
||||||
*msg = g_strdup_printf("Child capture process stopped: %s",
|
*msg = g_strdup_printf("Child capture process stopped: %s",
|
||||||
|
@ -716,16 +720,56 @@ sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
return CANT_RUN_DUMPCAP;
|
return CANT_RUN_DUMPCAP;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g_string_free(msg_buf, TRUE);
|
|
||||||
*msg = g_strdup_printf("Child capture process stopped unexpectedly "
|
*msg = g_strdup_printf("Child capture process stopped unexpectedly "
|
||||||
"(errno:%u)", errno);
|
"(errno:%u)", errno);
|
||||||
return CANT_RUN_DUMPCAP;
|
return CANT_RUN_DUMPCAP;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Run dumpcap with the supplied arguments. On success, msg points to
|
||||||
|
* a buffer containing the dumpcap output and returns 0. On failure, msg
|
||||||
|
* points to the error message returned by dumpcap, and returns dumpcap's
|
||||||
|
* exit value. In either case, msg must be freed with g_free().
|
||||||
|
*/
|
||||||
|
/* XXX - This duplicates a lot of code in sync_pipe_start() */
|
||||||
|
#define PIPE_BUF_SIZE 5120
|
||||||
|
static int
|
||||||
|
sync_pipe_run_command(const char** argv, gchar **msg) {
|
||||||
|
int sync_pipe_read_fd, fork_child, ret;
|
||||||
|
gchar buf[PIPE_BUF_SIZE+1];
|
||||||
|
GString *msg_buf = NULL;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
ret = sync_pipe_open_command(argv, &sync_pipe_read_fd, &fork_child, msg);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* We were able to set up to read dumpcap's output. Do so and
|
||||||
|
return its exit value. */
|
||||||
|
msg_buf = g_string_new("");
|
||||||
|
while ((count = eth_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
|
||||||
|
buf[count] = '\0';
|
||||||
|
g_string_append(msg_buf, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
ret = sync_pipe_close_command(&sync_pipe_read_fd, &fork_child, msg);
|
||||||
|
#else
|
||||||
|
ret = sync_pipe_close_command(&sync_pipe_read_fd, msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
g_string_free(msg_buf, TRUE);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
*msg = msg_buf->str;
|
*msg = msg_buf->str;
|
||||||
g_string_free(msg_buf, FALSE);
|
g_string_free(msg_buf, FALSE);
|
||||||
return fork_child_status;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -804,6 +848,52 @@ sync_linktype_list_open(gchar *ifname, gchar **msg) {
|
||||||
return sync_pipe_run_command(argv, msg);
|
return sync_pipe_run_command(argv, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start getting interface statistics using dumpcap. On success, read_fd
|
||||||
|
* contains the file descriptor for the pipe's stdout, msg is unchanged,
|
||||||
|
* and zero is returned. On failure, msg will point to an error message
|
||||||
|
* that must be g_free()d and a nonzero error value will be returned.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg) {
|
||||||
|
int argc;
|
||||||
|
const char **argv;
|
||||||
|
|
||||||
|
if (!msg) {
|
||||||
|
/* We can't return anything */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_linktype_list_open");
|
||||||
|
|
||||||
|
argv = init_pipe_args(&argc);
|
||||||
|
|
||||||
|
if (!argv) {
|
||||||
|
*msg = g_strdup_printf("We don't know where to find dumpcap.");
|
||||||
|
return CANT_RUN_DUMPCAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ask for the linktype list */
|
||||||
|
argv = sync_pipe_add_arg(argv, &argc, "-S");
|
||||||
|
argv = sync_pipe_add_arg(argv, &argc, "-M");
|
||||||
|
|
||||||
|
/* dumpcap should be running in capture child mode (hidden feature) */
|
||||||
|
#ifndef DEBUG_CHILD
|
||||||
|
argv = sync_pipe_add_arg(argv, &argc, "-Z");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return sync_pipe_open_command(argv, read_fd, fork_child, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close down the stats process */
|
||||||
|
int
|
||||||
|
sync_interface_stats_close(int *read_fd, int *fork_child, gchar **msg) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return sync_pipe_close_command(read_fd, fork_child, msg);
|
||||||
|
#else
|
||||||
|
return sync_pipe_close_command(read_fd, msg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* read a number of bytes from a pipe */
|
/* read a number of bytes from a pipe */
|
||||||
/* (blocks until enough bytes read or an error occurs) */
|
/* (blocks until enough bytes read or an error occurs) */
|
||||||
|
@ -812,7 +902,6 @@ pipe_read_bytes(int pipe, char *bytes, int required) {
|
||||||
int newly;
|
int newly;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
|
|
||||||
while(required) {
|
while(required) {
|
||||||
newly = read(pipe, &bytes[offset], required);
|
newly = read(pipe, &bytes[offset], required);
|
||||||
if (newly == 0) {
|
if (newly == 0) {
|
||||||
|
@ -835,6 +924,67 @@ pipe_read_bytes(int pipe, char *bytes, int required) {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean pipe_data_available(int pipe) {
|
||||||
|
#ifdef _WIN32 /* PeekNamedPipe */
|
||||||
|
HANDLE hPipe = (HANDLE) _get_osfhandle(pipe);
|
||||||
|
DWORD bytes_avail;
|
||||||
|
|
||||||
|
if (hPipe == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (! PeekNamedPipe(hPipe, NULL, 0, NULL, &bytes_avail, NULL))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (bytes_avail > 0)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
#else /* select */
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(pipe, &rfds);
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
if (select(pipe+1, &rfds, NULL, NULL, &timeout) > 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a line from a pipe, similar to fgets */
|
||||||
|
int
|
||||||
|
sync_pipe_gets_nonblock(int pipe, char *bytes, int max) {
|
||||||
|
int newly;
|
||||||
|
int offset = -1;
|
||||||
|
|
||||||
|
while(offset < max - 1) {
|
||||||
|
offset++;
|
||||||
|
if (! pipe_data_available(pipe))
|
||||||
|
break;
|
||||||
|
newly = read(pipe, &bytes[offset], 1);
|
||||||
|
if (newly == 0) {
|
||||||
|
/* EOF - not necessarily an error */
|
||||||
|
break;
|
||||||
|
} else if (newly < 0) {
|
||||||
|
/* error */
|
||||||
|
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
|
||||||
|
"read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
|
||||||
|
return newly;
|
||||||
|
} else if (bytes[offset] == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset >= 0)
|
||||||
|
bytes[offset] = '\0';
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* convert header values (indicator and 4-byte length) */
|
/* convert header values (indicator and 4-byte length) */
|
||||||
static void
|
static void
|
||||||
pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
|
pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
|
||||||
|
|
|
@ -71,4 +71,17 @@ sync_interface_list_open(gchar **msg);
|
||||||
extern int
|
extern int
|
||||||
sync_linktype_list_open(gchar *ifname, gchar **msg);
|
sync_linktype_list_open(gchar *ifname, gchar **msg);
|
||||||
|
|
||||||
|
/** Start getting interface statistics using dumpcap. */
|
||||||
|
extern int
|
||||||
|
sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg);
|
||||||
|
|
||||||
|
/** Stop gathering statistics. */
|
||||||
|
extern int
|
||||||
|
sync_interface_stats_close(int *read_fd, int *fork_child, gchar **msg);
|
||||||
|
|
||||||
|
/** Read a line from a pipe, similar to fgets. Non-blocking. */
|
||||||
|
extern int
|
||||||
|
sync_pipe_gets_nonblock(int pipe, char *bytes, int max);
|
||||||
|
|
||||||
|
|
||||||
#endif /* capture_sync.h */
|
#endif /* capture_sync.h */
|
||||||
|
|
|
@ -1,37 +1,66 @@
|
||||||
Here's a brief list of information that might be useful to anyone
|
The following guidelines should be followed by anyone distributing a software
|
||||||
distributing a software package containing Wireshark:
|
package containing Wireshark:
|
||||||
|
|
||||||
1. The canonical location for every Wireshark source release is
|
1. URLs.
|
||||||
|
|
||||||
|
1.1. Wireshark web site.
|
||||||
|
|
||||||
|
The Wireshark web site URL is http://www.wireshark.org/ .
|
||||||
|
|
||||||
|
1.2. Wireshark releases.
|
||||||
|
|
||||||
|
The canonical location for every Wireshark source release is
|
||||||
|
|
||||||
http://www.wireshark.org/download/src/all-versions/, e.g.
|
http://www.wireshark.org/download/src/all-versions/, e.g.
|
||||||
|
|
||||||
http://www.wireshark.org/download/src/all-versions/wireshark-0.99.55.tar.bz2
|
http://www.wireshark.org/download/src/all-versions/wireshark-0.99.55.tar.bz2
|
||||||
|
|
||||||
If your packaging system downloads a copy of the Wireshark sources,
|
If your packaging system downloads a copy of the Wireshark sources, use
|
||||||
use this location. Don't use http://www.wireshark.org/download/src.
|
this location. Don't use http://www.wireshark.org/download/src.
|
||||||
|
|
||||||
2. The Wireshark web site URL is http://www.wireshark.org/ .
|
1.3. Artwork.
|
||||||
|
|
||||||
3. Wireshark is released under the GNU General Public License. Make sure
|
Logo and icon artwork can be found in the "image" directory in the
|
||||||
your package complies with this license, or we send in the marmots.
|
distribution. This is available online at
|
||||||
|
|
||||||
4. Wireshark and the "fin" logo are registered trademarks of Gerald
|
http://anonsvn.wireshark.org/wireshark/trunk/image/
|
||||||
Combs.
|
|
||||||
|
|
||||||
5. Custom version information can be added by creating a file called
|
2. Licensing.
|
||||||
"version.conf". See make-version.pl for details. If your package
|
|
||||||
contains significant changes we recommend that you use this to
|
|
||||||
differentiate it from official Wireshark releases.
|
|
||||||
|
|
||||||
6. The SVN version corresponding to each release is in svnversion.h.
|
Wireshark is released under the GNU General Public License. Make sure
|
||||||
It's defined as a string. If you need a numeric definition, let
|
your package complies with this license, or we send in the marmots.
|
||||||
us know.
|
|
||||||
|
|
||||||
7. Wireshark icons, logos, and other artwork can be found in the
|
3. Privileges.
|
||||||
"image" directory of the Wireshark sources.
|
|
||||||
|
In versions up to and including 0.99.6, it was necessary to run
|
||||||
|
Wireshark with elevated privileges in order to be able to capture
|
||||||
|
traffic. With version 0.99.7, all function calls that require elevated
|
||||||
|
privliges have been moved out of the GUI.
|
||||||
|
|
||||||
|
WIRESHARK CONTAINS OVER ONE POINT FIVE MILLION LINES OF SOURCE CODE. DO
|
||||||
|
NOT RUN THEM AS ROOT.
|
||||||
|
|
||||||
|
4. Customization.
|
||||||
|
|
||||||
|
Custom version information can be added by creating a file called
|
||||||
|
"version.conf". See make-version.pl for details. If your package
|
||||||
|
contains significant changes we recommend that you use this to
|
||||||
|
differentiate it from official Wireshark releases.
|
||||||
|
|
||||||
|
4.1. Source-level version detection.
|
||||||
|
|
||||||
|
The SVN version corresponding to each release is in svnversion.h. It's
|
||||||
|
defined as a string. If you need a numeric definition, let us know.
|
||||||
|
|
||||||
|
5. Trademarks.
|
||||||
|
|
||||||
|
Wireshark and the "fin" logo are registered trademarks of Gerald Combs.
|
||||||
|
|
||||||
|
6. Spelling.
|
||||||
|
|
||||||
|
Wireshark is spelled with a capital "W", and with everything else lower
|
||||||
|
case. E.g., "WireShark" is incorrect.
|
||||||
|
|
||||||
8. Wireshark is spelled with a capital "W", and with everything else
|
|
||||||
lower case. E.g., "WireShark" is incorrect.
|
|
||||||
|
|
||||||
If you have a question not addressed here, send it to
|
If you have a question not addressed here, send it to
|
||||||
wireshark-dev@wireshark.org.
|
wireshark-dev@wireshark.org.
|
||||||
|
|
21
dumpcap.c
21
dumpcap.c
|
@ -115,7 +115,8 @@ print_usage(gboolean print_ver) {
|
||||||
fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
|
fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
|
||||||
fprintf(output, " -D print list of interfaces and exit\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, " -L print list of link-layer types of iface and exit\n");
|
||||||
fprintf(output, " -M for -D and -L, produce machine-readable 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");
|
fprintf(output, "\n");
|
||||||
fprintf(output, "Stop conditions:\n");
|
fprintf(output, "Stop conditions:\n");
|
||||||
fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
|
fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
|
||||||
|
@ -249,9 +250,10 @@ main(int argc, char *argv[])
|
||||||
gboolean list_interfaces = FALSE;
|
gboolean list_interfaces = FALSE;
|
||||||
gboolean list_link_layer_types = FALSE;
|
gboolean list_link_layer_types = FALSE;
|
||||||
gboolean machine_readable = FALSE;
|
gboolean machine_readable = FALSE;
|
||||||
int status;
|
gboolean print_statistics = FALSE;
|
||||||
|
int status, run_once_args = 0;
|
||||||
|
|
||||||
#define OPTSTRING_INIT "a:b:c:Df:hi:LMps:vw:y:Z"
|
#define OPTSTRING_INIT "a:b:c:Df:hi:LMpSs:vw:y:Z"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define OPTSTRING_WIN32 "B:"
|
#define OPTSTRING_WIN32 "B:"
|
||||||
|
@ -369,9 +371,15 @@ main(int argc, char *argv[])
|
||||||
/*** all non capture option specific ***/
|
/*** all non capture option specific ***/
|
||||||
case 'D': /* Print a list of capture devices and exit */
|
case 'D': /* Print a list of capture devices and exit */
|
||||||
list_interfaces = TRUE;
|
list_interfaces = TRUE;
|
||||||
|
run_once_args++;
|
||||||
break;
|
break;
|
||||||
case 'L': /* Print list of link-layer types and exit */
|
case 'L': /* Print list of link-layer types and exit */
|
||||||
list_link_layer_types = TRUE;
|
list_link_layer_types = TRUE;
|
||||||
|
run_once_args++;
|
||||||
|
break;
|
||||||
|
case 'S': /* Print interface statistics once a second */
|
||||||
|
print_statistics = TRUE;
|
||||||
|
run_once_args++;
|
||||||
break;
|
break;
|
||||||
case 'M': /* For -D and -L, print machine-readable output */
|
case 'M': /* For -D and -L, print machine-readable output */
|
||||||
machine_readable = TRUE;
|
machine_readable = TRUE;
|
||||||
|
@ -406,8 +414,8 @@ main(int argc, char *argv[])
|
||||||
exit_main(1);
|
exit_main(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list_interfaces && list_link_layer_types) {
|
if (run_once_args > 1) {
|
||||||
cmdarg_err("Only one of -D or -L may be supplied.");
|
cmdarg_err("Only one of -D, -L, or -S may be supplied.");
|
||||||
exit_main(1);
|
exit_main(1);
|
||||||
} else if (list_link_layer_types) {
|
} else if (list_link_layer_types) {
|
||||||
/* We're supposed to list the link-layer types for an interface;
|
/* We're supposed to list the link-layer types for an interface;
|
||||||
|
@ -452,6 +460,9 @@ main(int argc, char *argv[])
|
||||||
} else if (list_link_layer_types) {
|
} else if (list_link_layer_types) {
|
||||||
status = capture_opts_list_link_layer_types(capture_opts, machine_readable);
|
status = capture_opts_list_link_layer_types(capture_opts, machine_readable);
|
||||||
exit_main(status);
|
exit_main(status);
|
||||||
|
} else if (print_statistics) {
|
||||||
|
status = capture_opts_print_statistics(machine_readable);
|
||||||
|
exit_main(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
|
capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
|
||||||
|
|
|
@ -107,7 +107,6 @@ GList *if_list;
|
||||||
|
|
||||||
/* the "runtime" data of one interface */
|
/* the "runtime" data of one interface */
|
||||||
typedef struct if_dlg_data_s {
|
typedef struct if_dlg_data_s {
|
||||||
pcap_t *pch;
|
|
||||||
GtkWidget *device_lb;
|
GtkWidget *device_lb;
|
||||||
GtkWidget *descr_lb;
|
GtkWidget *descr_lb;
|
||||||
GtkWidget *ip_lb;
|
GtkWidget *ip_lb;
|
||||||
|
@ -123,8 +122,6 @@ typedef struct if_dlg_data_s {
|
||||||
if_info_t if_info;
|
if_info_t if_info;
|
||||||
} if_dlg_data_t;
|
} if_dlg_data_t;
|
||||||
|
|
||||||
void update_if(if_dlg_data_t *if_dlg_data);
|
|
||||||
|
|
||||||
|
|
||||||
/* start capture button was pressed */
|
/* start capture button was pressed */
|
||||||
static void
|
static void
|
||||||
|
@ -185,48 +182,9 @@ capture_details_cb(GtkWidget *details_bt _U_, gpointer if_data)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* open a single interface */
|
|
||||||
static void
|
|
||||||
open_if(gchar *name, if_dlg_data_t *if_dlg_data)
|
|
||||||
{
|
|
||||||
gchar open_err_str[PCAP_ERRBUF_SIZE];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX - on systems with BPF, the number of BPF devices limits the
|
|
||||||
* number of devices on which you can capture simultaneously.
|
|
||||||
*
|
|
||||||
* This means that
|
|
||||||
*
|
|
||||||
* 1) this might fail if you run out of BPF devices
|
|
||||||
*
|
|
||||||
* and
|
|
||||||
*
|
|
||||||
* 2) opening every interface could leave too few BPF devices
|
|
||||||
* for *other* programs.
|
|
||||||
*
|
|
||||||
* It also means the system could end up getting a lot of traffic
|
|
||||||
* that it has to pass through the networking stack and capture
|
|
||||||
* mechanism, so opening all the devices and presenting packet
|
|
||||||
* counts might not always be a good idea.
|
|
||||||
*/
|
|
||||||
if_dlg_data->pch = pcap_open_live(name,
|
|
||||||
MIN_PACKET_SIZE,
|
|
||||||
capture_opts->promisc_mode, CAP_READ_TIMEOUT,
|
|
||||||
open_err_str);
|
|
||||||
|
|
||||||
if (if_dlg_data->pch != NULL) {
|
|
||||||
update_if(if_dlg_data);
|
|
||||||
} else {
|
|
||||||
printf("open_if: %s\n", open_err_str);
|
|
||||||
gtk_label_set_text(GTK_LABEL(if_dlg_data->curr_lb), "error");
|
|
||||||
gtk_label_set_text(GTK_LABEL(if_dlg_data->last_lb), "error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update a single interface */
|
/* update a single interface */
|
||||||
void
|
void
|
||||||
update_if(if_dlg_data_t *if_dlg_data)
|
update_if(if_dlg_data_t *if_dlg_data, if_stat_cache_t *sc)
|
||||||
{
|
{
|
||||||
struct pcap_stat stats;
|
struct pcap_stat stats;
|
||||||
gchar *str;
|
gchar *str;
|
||||||
|
@ -243,8 +201,8 @@ update_if(if_dlg_data_t *if_dlg_data)
|
||||||
* (Note also that some versions of libpcap, on some versions of UN*X,
|
* (Note also that some versions of libpcap, on some versions of UN*X,
|
||||||
* have the same bug.)
|
* have the same bug.)
|
||||||
*/
|
*/
|
||||||
if (if_dlg_data->pch) {
|
if (sc) {
|
||||||
if(pcap_stats(if_dlg_data->pch, &stats) >= 0) {
|
if(capture_stats(sc, if_dlg_data->device, &stats)) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
diff = stats.ps_recv - if_dlg_data->last_packets;
|
diff = stats.ps_recv - if_dlg_data->last_packets;
|
||||||
if_dlg_data->last_packets = stats.ps_recv;
|
if_dlg_data->last_packets = stats.ps_recv;
|
||||||
|
@ -269,31 +227,20 @@ update_if(if_dlg_data_t *if_dlg_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* close a single interface */
|
|
||||||
static void
|
|
||||||
close_if(if_dlg_data_t *if_dlg_data)
|
|
||||||
{
|
|
||||||
if(if_dlg_data->pch)
|
|
||||||
pcap_close(if_dlg_data->pch);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* update all interfaces */
|
/* update all interfaces */
|
||||||
static gboolean
|
static gboolean
|
||||||
update_all(gpointer data)
|
update_all(gpointer data)
|
||||||
{
|
{
|
||||||
GList *curr;
|
GList *curr;
|
||||||
int ifs;
|
int ifs;
|
||||||
|
if_stat_cache_t *sc = data;
|
||||||
|
|
||||||
if(!cap_if_w) {
|
if(!cap_if_w) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(ifs = 0; (curr = g_list_nth(data, ifs)); ifs++) {
|
for(ifs = 0; (curr = g_list_nth(if_data, ifs)); ifs++) {
|
||||||
update_if(curr->data);
|
update_if(curr->data, sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -322,17 +269,15 @@ set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress)
|
||||||
|
|
||||||
/* the window was closed, cleanup things */
|
/* the window was closed, cleanup things */
|
||||||
static void
|
static void
|
||||||
capture_if_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
|
capture_if_destroy_cb(GtkWidget *win _U_, gpointer user_data)
|
||||||
{
|
{
|
||||||
GList *curr;
|
GList *curr;
|
||||||
int ifs;
|
int ifs;
|
||||||
|
if_stat_cache_t *sc = user_data;
|
||||||
|
|
||||||
gtk_timeout_remove(timer_id);
|
gtk_timeout_remove(timer_id);
|
||||||
|
|
||||||
for(ifs = 0; (curr = g_list_nth(if_data, ifs)); ifs++) {
|
for(ifs = 0; (curr = g_list_nth(if_data, ifs)); ifs++) {
|
||||||
if_dlg_data_t *if_dlg_data = curr->data;
|
|
||||||
|
|
||||||
close_if(if_dlg_data);
|
|
||||||
g_free(curr->data);
|
g_free(curr->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,8 +288,10 @@ capture_if_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
|
||||||
/* Note that we no longer have a "Capture Options" dialog box. */
|
/* Note that we no longer have a "Capture Options" dialog box. */
|
||||||
cap_if_w = NULL;
|
cap_if_w = NULL;
|
||||||
|
|
||||||
|
capture_stat_stop(sc);
|
||||||
|
|
||||||
#ifdef HAVE_AIRPCAP
|
#ifdef HAVE_AIRPCAP
|
||||||
airpcap_set_toolbar_stop_capture(airpcap_if_active);
|
airpcap_set_toolbar_stop_capture(airpcap_if_active);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,6 +385,7 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
|
||||||
if_addr_t *ip_addr;
|
if_addr_t *ip_addr;
|
||||||
GString *if_tool_str = g_string_new("");
|
GString *if_tool_str = g_string_new("");
|
||||||
gchar *tmp_str;
|
gchar *tmp_str;
|
||||||
|
if_stat_cache_t *sc;
|
||||||
|
|
||||||
if (cap_if_w != NULL) {
|
if (cap_if_w != NULL) {
|
||||||
/* There's already a "Capture Interfaces" dialog box; reactivate it. */
|
/* There's already a "Capture Interfaces" dialog box; reactivate it. */
|
||||||
|
@ -567,6 +515,10 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
|
||||||
gtk_widget_size_request(stop_bt, &requisition);
|
gtk_widget_size_request(stop_bt, &requisition);
|
||||||
height += requisition.height + 15;
|
height += requisition.height + 15;
|
||||||
|
|
||||||
|
/* Start gathering statistics (using dumpcap) */
|
||||||
|
sc = capture_stat_start(if_list);
|
||||||
|
|
||||||
|
/* List the interfaces */
|
||||||
for(ifs = 0; (curr = g_list_nth(if_list, ifs)); ifs++) {
|
for(ifs = 0; (curr = g_list_nth(if_list, ifs)); ifs++) {
|
||||||
g_string_assign(if_tool_str, "");
|
g_string_assign(if_tool_str, "");
|
||||||
if_info = curr->data;
|
if_info = curr->data;
|
||||||
|
@ -674,8 +626,6 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
|
||||||
gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->details_bt, 8, 9, row, row+1);
|
gtk_table_attach_defaults(GTK_TABLE(if_tb), if_dlg_data->details_bt, 8, 9, row, row+1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
open_if(if_info->name, if_dlg_data);
|
|
||||||
|
|
||||||
if_data = g_list_append(if_data, if_dlg_data);
|
if_data = g_list_append(if_data, if_dlg_data);
|
||||||
|
|
||||||
row++;
|
row++;
|
||||||
|
@ -713,7 +663,7 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
|
||||||
gtk_widget_grab_default(close_bt);
|
gtk_widget_grab_default(close_bt);
|
||||||
|
|
||||||
SIGNAL_CONNECT(cap_if_w, "delete_event", window_delete_event_cb, NULL);
|
SIGNAL_CONNECT(cap_if_w, "delete_event", window_delete_event_cb, NULL);
|
||||||
SIGNAL_CONNECT(cap_if_w, "destroy", capture_if_destroy_cb, NULL);
|
SIGNAL_CONNECT(cap_if_w, "destroy", capture_if_destroy_cb, sc);
|
||||||
|
|
||||||
gtk_widget_show_all(cap_if_w);
|
gtk_widget_show_all(cap_if_w);
|
||||||
window_present(cap_if_w);
|
window_present(cap_if_w);
|
||||||
|
@ -721,7 +671,7 @@ capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
|
||||||
set_capture_if_dialog_for_capture_in_progress(is_capture_in_progress());
|
set_capture_if_dialog_for_capture_in_progress(is_capture_in_progress());
|
||||||
|
|
||||||
/* update the interface list every 1000ms */
|
/* update the interface list every 1000ms */
|
||||||
timer_id = gtk_timeout_add(1000, update_all, if_data);
|
timer_id = gtk_timeout_add(1000, update_all, sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue