2 * Routines for packet capture
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #ifdef HAVE_SYS_TYPES_H
44 #include <sys/types.h>
47 #ifdef HAVE_NETINET_IN_H
48 #include <netinet/in.h>
55 #ifdef HAVE_ARPA_INET_H
56 #include <arpa/inet.h>
59 #ifdef HAVE_SYS_SOCKET_H
60 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
63 #ifdef HAVE_WINSOCK2_H
64 #include <winsock2.h> /* needed to define AF_ values on Windows */
67 #ifdef NEED_INET_V6DEFS_H
68 # include "inet_v6defs.h"
76 #include <epan/packet.h>
77 #include <epan/dfilter/dfilter.h>
80 #include "capture_sync.h"
81 #include "capture_info.h"
82 #include "capture_ui_utils.h"
84 #include "capture-pcap-util.h"
85 #include "alert_box.h"
86 #include "simple_dialog.h"
87 #include <epan/prefs.h>
90 #include "capture-wpcap.h"
93 #include "wsutil/file_util.h"
96 typedef struct if_stat_cache_item_s {
99 } if_stat_cache_item_t;
101 struct if_stat_cache_s {
104 GList *cache_list; /* List of if_stat_chache_entry_t */
107 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
109 capture_callback_t cb_fct;
111 } capture_callback_data_t;
113 static GList *capture_callbacks = NULL;
116 capture_callback_invoke(int event, capture_options *capture_opts)
118 capture_callback_data_t *cb;
119 GList *cb_item = capture_callbacks;
121 /* there should be at least one interested */
122 g_assert(cb_item != NULL);
124 while(cb_item != NULL) {
126 cb->cb_fct(event, capture_opts, cb->user_data);
127 cb_item = g_list_next(cb_item);
133 capture_callback_add(capture_callback_t func, gpointer user_data)
135 capture_callback_data_t *cb;
137 cb = g_malloc(sizeof(capture_callback_data_t));
139 cb->user_data = user_data;
141 capture_callbacks = g_list_append(capture_callbacks, cb);
145 capture_callback_remove(capture_callback_t func)
147 capture_callback_data_t *cb;
148 GList *cb_item = capture_callbacks;
150 while(cb_item != NULL) {
152 if(cb->cb_fct == func) {
153 capture_callbacks = g_list_remove(capture_callbacks, cb);
157 cb_item = g_list_next(cb_item);
160 g_assert_not_reached();
166 * @return TRUE if the capture starts successfully, FALSE otherwise.
169 capture_start(capture_options *capture_opts)
174 /* close the currently loaded capture file */
175 cf_close(capture_opts->cf);
177 g_assert(capture_opts->state == CAPTURE_STOPPED);
178 capture_opts->state = CAPTURE_PREPARING;
180 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ...");
182 /* try to start the capture child process */
183 ret = sync_pipe_start(capture_opts);
185 if(capture_opts->save_file != NULL) {
186 g_free(capture_opts->save_file);
187 capture_opts->save_file = NULL;
190 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start failed!");
191 capture_opts->state = CAPTURE_STOPPED;
193 /* the capture child might not respond shortly after bringing it up */
194 /* (especially it will block, if no input coming from an input capture pipe (e.g. mkfifo) is coming in) */
196 /* to prevent problems, bring the main GUI into "capture mode" right after successfully */
197 /* spawn/exec the capture child, without waiting for any response from it */
198 capture_callback_invoke(capture_cb_capture_prepared, capture_opts);
200 if(capture_opts->show_info)
201 capture_info_open(capture_opts);
209 capture_stop(capture_options *capture_opts)
211 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Stop ...");
213 capture_callback_invoke(capture_cb_capture_stopping, capture_opts);
215 /* stop the capture child gracefully */
216 sync_pipe_stop(capture_opts);
221 capture_restart(capture_options *capture_opts)
223 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Restart");
225 capture_opts->restart = TRUE;
226 capture_stop(capture_opts);
231 capture_kill_child(capture_options *capture_opts)
233 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "Capture Kill");
235 /* kill the capture child */
236 sync_pipe_kill(capture_opts->fork_child);
241 /* We've succeeded a (non real-time) capture, try to read it into a new capture file */
243 capture_input_read_all(capture_options *capture_opts, gboolean is_tempfile, gboolean drops_known,
249 /* Capture succeeded; attempt to open the capture file. */
250 if (cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err) != CF_OK) {
251 /* We're not doing a capture any more, so we don't have a save
256 /* Set the read filter to NULL. */
257 /* XXX - this is odd here, try to put it somewhere, where it fits better */
258 cf_set_rfcode(capture_opts->cf, NULL);
260 /* Get the packet-drop statistics.
262 XXX - there are currently no packet-drop statistics stored
263 in libpcap captures, and that's what we're reading.
265 At some point, we will add support in Wiretap to return
266 packet-drop statistics for capture file formats that store it,
267 and will make "cf_read()" get those statistics from Wiretap.
268 We clear the statistics (marking them as "not known") in
269 "cf_open()", and "cf_read()" will only fetch them and mark
270 them as known if Wiretap supplies them, so if we get the
271 statistics now, after calling "cf_open()" but before calling
272 "cf_read()", the values we store will be used by "cf_read()".
274 If a future libpcap capture file format stores the statistics,
275 we'll put them into the capture file that we write, and will
276 thus not have to set them here - "cf_read()" will get them from
277 the file and use them. */
279 cf_set_drops_known(capture_opts->cf, TRUE);
281 /* XXX - on some systems, libpcap doesn't bother filling in
282 "ps_ifdrop" - it doesn't even set it to zero - so we don't
283 bother looking at it.
285 Ideally, libpcap would have an interface that gave us
286 several statistics - perhaps including various interface
287 error statistics - and would tell us which of them it
288 supplies, allowing us to display only the ones it does. */
289 cf_set_drops(capture_opts->cf, drops);
292 /* read in the packet data */
293 switch (cf_read(capture_opts->cf)) {
297 /* Just because we got an error, that doesn't mean we were unable
298 to read any of the file; we handle what we could get from the
302 case CF_READ_ABORTED:
303 /* User wants to quit program. Exit by leaving the main loop,
304 so that any quit functions we registered get called. */
305 main_window_nested_quit();
309 /* if we didn't captured even a single packet, close the file again */
310 if(cf_get_packet_count(capture_opts->cf) == 0 && !capture_opts->restart) {
311 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
312 "%sNo packets captured!%s\n"
314 "As no data was captured, closing the %scapture file!\n"
317 "Help about capturing can be found at:\n"
319 " http://wiki.wireshark.org/CaptureSetup"
322 "Wireless (Wi-Fi/WLAN):\n"
323 "Try to switch off promiscuous mode in the Capture Options!"
326 simple_dialog_primary_start(), simple_dialog_primary_end(),
327 (cf_is_tempfile(capture_opts->cf)) ? "temporary " : "");
328 cf_close(capture_opts->cf);
334 /* capture child tells us we have a new (or the first) capture file */
336 capture_input_new_file(capture_options *capture_opts, gchar *new_file)
338 gboolean is_tempfile;
342 if(capture_opts->state == CAPTURE_PREPARING) {
343 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture started!");
345 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "File: \"%s\"", new_file);
347 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
349 /* free the old filename */
350 if(capture_opts->save_file != NULL) {
351 /* we start a new capture file, close the old one (if we had one before) */
352 /* (we can only have an open capture file in real_time_mode!) */
353 if( ((capture_file *) capture_opts->cf)->state != FILE_CLOSED) {
354 capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
355 cf_finish_tail(capture_opts->cf, &err);
356 cf_close(capture_opts->cf);
358 g_free(capture_opts->save_file);
360 cf_set_tempfile(capture_opts->cf, FALSE);
362 /* we didn't had a save_file before, must be a tempfile */
364 cf_set_tempfile(capture_opts->cf, TRUE);
367 /* save the new filename */
368 capture_opts->save_file = g_strdup(new_file);
370 /* if we are in real-time mode, open the new file now */
371 if(capture_opts->real_time_mode) {
372 /* Attempt to open the capture file and set up to read from it. */
373 switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
377 /* Don't unlink (delete) the save file - leave it around,
378 for debugging purposes. */
379 g_free(capture_opts->save_file);
380 capture_opts->save_file = NULL;
385 if(capture_opts->show_info) {
386 if (!capture_info_new_file(new_file))
390 if(capture_opts->real_time_mode) {
391 capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
393 capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
395 capture_opts->state = CAPTURE_RUNNING;
401 /* capture child tells us we have new packets to read */
403 capture_input_new_packets(capture_options *capture_opts, int to_read)
408 g_assert(capture_opts->save_file);
410 if(capture_opts->real_time_mode) {
411 /* Read from the capture file the number of records the child told us it added. */
412 switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
416 /* Just because we got an error, that doesn't mean we were unable
417 to read any of the file; we handle what we could get from the
420 XXX - abort on a read error? */
421 capture_callback_invoke(capture_cb_capture_update_continue, capture_opts);
424 case CF_READ_ABORTED:
425 /* Kill the child capture process; the user wants to exit, and we
426 shouldn't just leave it running. */
427 capture_kill_child(capture_opts);
431 /* increase capture file packet counter by the number or incoming packets */
432 cf_set_packet_count(capture_opts->cf,
433 cf_get_packet_count(capture_opts->cf) + to_read);
435 capture_callback_invoke(capture_cb_capture_fixed_continue, capture_opts);
438 /* update the main window, so we get events (e.g. from the stop toolbar button) */
439 main_window_update();
441 if(capture_opts->show_info)
442 capture_info_new_packets(to_read);
446 /* Capture child told us how many dropped packets it counted.
449 capture_input_drops(capture_options *capture_opts, int dropped)
451 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", dropped, plurality(dropped, "", "s"));
453 g_assert(capture_opts->state == CAPTURE_RUNNING);
455 cf_set_drops_known(capture_opts->cf, TRUE);
456 cf_set_drops(capture_opts->cf, dropped);
460 /* Capture child told us that an error has occurred while starting/running
462 The buffer we're handed has *two* null-terminated strings in it - a
463 primary message and a secondary message, one right after the other.
464 The secondary message might be a null string.
467 capture_input_error_message(capture_options *capture_opts, char *error_msg, char *secondary_error_msg)
469 gchar *safe_error_msg;
470 gchar *safe_secondary_error_msg;
472 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\", \"%s\"",
473 error_msg, secondary_error_msg);
475 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
477 safe_error_msg = simple_dialog_format_message(error_msg);
478 if (*secondary_error_msg != '\0') {
479 /* We have both primary and secondary messages. */
480 safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
481 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s\n\n%s",
482 simple_dialog_primary_start(), safe_error_msg,
483 simple_dialog_primary_end(), safe_secondary_error_msg);
484 g_free(safe_secondary_error_msg);
486 /* We have only a primary message. */
487 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s",
488 simple_dialog_primary_start(), safe_error_msg,
489 simple_dialog_primary_end());
491 g_free(safe_error_msg);
493 /* the capture child will close the sync_pipe if required, nothing to do for now */
498 /* Capture child told us that an error has occurred while parsing a
499 capture filter when starting/running the capture.
502 capture_input_cfilter_error_message(capture_options *capture_opts, char *error_message)
504 dfilter_t *rfcode = NULL;
505 gchar *safe_cfilter = simple_dialog_format_message(capture_opts->cfilter);
506 gchar *safe_cfilter_error_msg = simple_dialog_format_message(error_message);
508 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
510 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
512 /* Did the user try a display filter? */
513 if (dfilter_compile(capture_opts->cfilter, &rfcode) && rfcode != NULL) {
514 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
515 "%sInvalid capture filter: \"%s\"!%s\n"
517 "That string looks like a valid display filter; however, it isn't a valid\n"
518 "capture filter (%s).\n"
520 "Note that display filters and capture filters don't have the same syntax,\n"
521 "so you can't use most display filter expressions as capture filters.\n"
523 "See the User's Guide for a description of the capture filter syntax.",
524 simple_dialog_primary_start(), safe_cfilter,
525 simple_dialog_primary_end(), safe_cfilter_error_msg);
526 dfilter_free(rfcode);
528 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
529 "%sInvalid capture filter: \"%s\"!%s\n"
531 "That string isn't a valid capture filter (%s).\n"
532 "See the User's Guide for a description of the capture filter syntax.",
533 simple_dialog_primary_start(), safe_cfilter,
534 simple_dialog_primary_end(), safe_cfilter_error_msg);
536 g_free(safe_cfilter_error_msg);
537 g_free(safe_cfilter);
539 /* the capture child will close the sync_pipe if required, nothing to do for now */
543 /* capture child closed its side of the pipe, do the required cleanup */
545 capture_input_closed(capture_options *capture_opts)
548 int packet_count_save;
550 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
551 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
553 /* if we didn't started the capture, do a fake start */
554 /* (happens if we got an error message - we won't get a filename then) */
555 if(capture_opts->state == CAPTURE_PREPARING) {
556 if(capture_opts->real_time_mode) {
557 capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
559 capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
563 if(capture_opts->real_time_mode) {
564 cf_read_status_t status;
566 /* Read what remains of the capture file. */
567 status = cf_finish_tail(capture_opts->cf, &err);
569 /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
570 packet_count_save = cf_get_packet_count(capture_opts->cf);
571 /* Tell the GUI, we are not doing a capture any more.
572 Must be done after the cf_finish_tail(), so file lengths are displayed
574 capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
576 /* Finish the capture. */
580 if ((packet_count_save == 0) && !capture_opts->restart) {
581 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
582 "%sNo packets captured!%s\n"
584 "As no data was captured, closing the %scapture file!\n"
587 "Help about capturing can be found at:\n"
589 " http://wiki.wireshark.org/CaptureSetup"
592 "Wireless (Wi-Fi/WLAN):\n"
593 "Try to switch off promiscuous mode in the Capture Options!"
596 simple_dialog_primary_start(), simple_dialog_primary_end(),
597 cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
598 cf_close(capture_opts->cf);
602 /* Just because we got an error, that doesn't mean we were unable
603 to read any of the file; we handle what we could get from the
607 case CF_READ_ABORTED:
608 /* Exit by leaving the main loop, so that any quit functions
609 we registered get called. */
614 /* first of all, we are not doing a capture any more */
615 capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts);
617 /* this is a normal mode capture and if no error happened, read in the capture file data */
618 if(capture_opts->save_file != NULL) {
619 capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
620 cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
624 if(capture_opts->show_info)
625 capture_info_close();
627 capture_opts->state = CAPTURE_STOPPED;
629 /* if we couldn't open a capture file, there's nothing more for us to do */
630 if(capture_opts->save_file == NULL) {
631 cf_close(capture_opts->cf);
635 /* does the user wants to restart the current capture? */
636 if(capture_opts->restart) {
637 capture_opts->restart = FALSE;
639 ws_unlink(capture_opts->save_file);
641 /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
642 if(cf_is_tempfile(capture_opts->cf)) {
643 g_free(capture_opts->save_file);
644 capture_opts->save_file = NULL;
647 /* ... and start the capture again */
648 capture_start(capture_opts);
650 /* We're not doing a capture any more, so we don't have a save file. */
651 g_free(capture_opts->save_file);
652 capture_opts->save_file = NULL;
657 * Fetch the interface list from a child process (dumpcap).
659 * @return A GList containing if_info_t structs if successful, NULL otherwise.
662 /* XXX - We parse simple text output to get our interface list. Should
663 * we use "real" data serialization instead, e.g. via XML? */
665 capture_interface_list(int *err, char **err_str)
667 GList *if_list = NULL;
670 gchar **raw_list, **if_parts, **addr_parts;
675 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
677 /* Try to get our interface list */
678 *err = sync_interface_list_open(&msg);
680 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
692 /* Split our lines */
694 raw_list = g_strsplit(msg, "\r\n", 0);
696 raw_list = g_strsplit(msg, "\n", 0);
700 for (i = 0; raw_list[i] != NULL; i++) {
701 if_parts = g_strsplit(raw_list[i], "\t", 4);
702 if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL ||
703 if_parts[3] == NULL) {
704 g_strfreev(if_parts);
708 /* Number followed by the name, e.g "1. eth0" */
709 name = strchr(if_parts[0], ' ');
713 g_strfreev(if_parts);
717 if_info = g_malloc0(sizeof(if_info_t));
718 if_info->name = g_strdup(name);
719 if (strlen(if_parts[1]) > 0)
720 if_info->description = g_strdup(if_parts[1]);
721 addr_parts = g_strsplit(if_parts[2], ",", 0);
722 for (j = 0; addr_parts[j] != NULL; j++) {
723 if_addr = g_malloc0(sizeof(if_addr_t));
724 if (inet_pton(AF_INET, addr_parts[j], &if_addr->ip_addr.ip4_addr)) {
725 if_addr->type = AT_IPv4;
726 } else if (inet_pton(AF_INET6, addr_parts[j],
727 &if_addr->ip_addr.ip6_addr)) {
728 if_addr->type = AT_IPv6;
734 if_info->ip_addr = g_slist_append(if_info->ip_addr, if_addr);
737 if (strcmp(if_parts[3], "loopback") == 0)
738 if_info->loopback = TRUE;
739 g_strfreev(if_parts);
740 g_strfreev(addr_parts);
741 if_list = g_list_append(if_list, if_info);
743 g_strfreev(raw_list);
745 /* Check to see if we built a list */
746 if (if_list == NULL) {
747 if (err_str && *err_str)
748 *err_str = g_strdup("No interfaces found");
749 *err = NO_INTERFACES_FOUND;
754 /* XXX - We parse simple text output to get our interface list. Should
755 * we use "real" data serialization instead, e.g. via XML? */
757 capture_pcap_linktype_list(const gchar *ifname, char **err_str)
759 GList *linktype_list = NULL;
762 gchar **raw_list, **lt_parts;
763 data_link_info_t *data_link_info;
765 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
767 /* Try to get our interface list */
768 err = sync_linktype_list_open(ifname, &msg);
770 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
779 /* Split our lines */
781 raw_list = g_strsplit(msg, "\r\n", 0);
783 raw_list = g_strsplit(msg, "\n", 0);
787 for (i = 0; raw_list[i] != NULL; i++) {
788 /* ...and what if the interface name has a tab in it, Mr. Clever Programmer? */
789 lt_parts = g_strsplit(raw_list[i], "\t", 3);
790 if (lt_parts[0] == NULL || lt_parts[1] == NULL || lt_parts[2] == NULL) {
791 g_strfreev(lt_parts);
795 data_link_info = g_malloc(sizeof (data_link_info_t));
796 data_link_info->dlt = (int) strtol(lt_parts[0], NULL, 10);
797 data_link_info->name = g_strdup(lt_parts[1]);
798 if (strcmp(lt_parts[2], "(not supported)") != 0)
799 data_link_info->description = g_strdup(lt_parts[2]);
801 data_link_info->description = NULL;
803 linktype_list = g_list_append(linktype_list, data_link_info);
805 g_strfreev(raw_list);
807 /* Check to see if we built a list */
808 if (linktype_list == NULL) {
812 return linktype_list;
816 capture_stat_start(GList *if_list) {
817 int stat_fd, fork_child;
819 if_stat_cache_t *sc = NULL;
822 if_stat_cache_item_t *sc_item;
824 /* Fire up dumpcap. */
826 * XXX - on systems with BPF, the number of BPF devices limits the
827 * number of devices on which you can capture simultaneously.
831 * 1) this might fail if you run out of BPF devices
835 * 2) opening every interface could leave too few BPF devices
836 * for *other* programs.
838 * It also means the system could end up getting a lot of traffic
839 * that it has to pass through the networking stack and capture
840 * mechanism, so opening all the devices and presenting packet
841 * counts might not always be a good idea.
843 if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
844 sc = g_malloc(sizeof(if_stat_cache_t));
845 sc->stat_fd = stat_fd;
846 sc->fork_child = fork_child;
847 sc->cache_list = NULL;
849 /* Initialize the cache */
850 for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
851 if_info = if_entry->data;
852 sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
853 sc_item->name = g_strdup(if_info->name);
854 sc->cache_list = g_list_append(sc->cache_list, sc_item);
860 #define MAX_STAT_LINE_LEN 500
863 capture_stat_cache_update(if_stat_cache_t *sc) {
864 gchar stat_line[MAX_STAT_LINE_LEN];
867 if_stat_cache_item_t *sc_item;
872 while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
873 g_strstrip(stat_line);
874 stat_parts = g_strsplit(stat_line, "\t", 3);
875 if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
876 stat_parts[2] == NULL) {
877 g_strfreev(stat_parts);
880 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
881 sc_item = sc_entry->data;
882 if (strcmp(sc_item->name, stat_parts[0]) == 0) {
883 sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
884 sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
887 g_strfreev(stat_parts);
892 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
894 if_stat_cache_item_t *sc_item;
896 if (!sc || !ifname || !ps) {
900 capture_stat_cache_update(sc);
901 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
902 sc_item = sc_entry->data;
903 if (strcmp(sc_item->name, ifname) == 0) {
904 memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
912 capture_stat_stop(if_stat_cache_t *sc) {
914 if_stat_cache_item_t *sc_item;
920 sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
922 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
923 sc_item = sc_entry->data;
924 g_free(sc_item->name);
930 #endif /* HAVE_LIBPCAP */