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 "simple_dialog.h"
86 #include <epan/prefs.h>
89 #include "capture-wpcap.h"
92 #include "wsutil/file_util.h"
95 typedef struct if_stat_cache_item_s {
98 } if_stat_cache_item_t;
100 struct if_stat_cache_s {
103 GList *cache_list; /* List of if_stat_chache_entry_t */
106 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
108 capture_callback_t cb_fct;
110 } capture_callback_data_t;
112 static GList *capture_callbacks = NULL;
115 capture_callback_invoke(int event, capture_options *capture_opts)
117 capture_callback_data_t *cb;
118 GList *cb_item = capture_callbacks;
120 /* there should be at least one interested */
121 g_assert(cb_item != NULL);
123 while(cb_item != NULL) {
125 cb->cb_fct(event, capture_opts, cb->user_data);
126 cb_item = g_list_next(cb_item);
132 capture_callback_add(capture_callback_t func, gpointer user_data)
134 capture_callback_data_t *cb;
136 cb = g_malloc(sizeof(capture_callback_data_t));
138 cb->user_data = user_data;
140 capture_callbacks = g_list_append(capture_callbacks, cb);
144 capture_callback_remove(capture_callback_t func)
146 capture_callback_data_t *cb;
147 GList *cb_item = capture_callbacks;
149 while(cb_item != NULL) {
151 if(cb->cb_fct == func) {
152 capture_callbacks = g_list_remove(capture_callbacks, cb);
156 cb_item = g_list_next(cb_item);
159 g_assert_not_reached();
165 * @return TRUE if the capture starts successfully, FALSE otherwise.
168 capture_start(capture_options *capture_opts)
173 /* close the currently loaded capture file */
174 cf_close(capture_opts->cf);
176 g_assert(capture_opts->state == CAPTURE_STOPPED);
177 capture_opts->state = CAPTURE_PREPARING;
179 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ...");
181 /* try to start the capture child process */
182 ret = sync_pipe_start(capture_opts);
184 if(capture_opts->save_file != NULL) {
185 g_free(capture_opts->save_file);
186 capture_opts->save_file = NULL;
189 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start failed!");
190 capture_opts->state = CAPTURE_STOPPED;
192 /* the capture child might not respond shortly after bringing it up */
193 /* (for example: it will block if no input arrives from an input capture pipe (e.g. mkfifo)) */
195 /* to prevent problems, bring the main GUI into "capture mode" right after a successful */
196 /* spawn/exec of the capture child, without waiting for any response from it */
197 capture_callback_invoke(capture_cb_capture_prepared, capture_opts);
199 if(capture_opts->show_info)
200 capture_info_open(capture_opts);
208 capture_stop(capture_options *capture_opts)
210 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Stop ...");
212 capture_callback_invoke(capture_cb_capture_stopping, capture_opts);
214 /* stop the capture child gracefully */
215 sync_pipe_stop(capture_opts);
220 capture_restart(capture_options *capture_opts)
222 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Restart");
224 capture_opts->restart = TRUE;
225 capture_stop(capture_opts);
230 capture_kill_child(capture_options *capture_opts)
232 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "Capture Kill");
234 /* kill the capture child */
235 sync_pipe_kill(capture_opts->fork_child);
240 /* We've succeeded in doing a (non real-time) capture; try to read it into a new capture file */
242 capture_input_read_all(capture_options *capture_opts, gboolean is_tempfile, gboolean drops_known,
248 /* Capture succeeded; attempt to open the capture file. */
249 if (cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err) != CF_OK) {
250 /* We're not doing a capture any more, so we don't have a save file. */
254 /* Set the read filter to NULL. */
255 /* XXX - this is odd here; try to put it somewhere where it fits better */
256 cf_set_rfcode(capture_opts->cf, NULL);
258 /* Get the packet-drop statistics.
260 XXX - there are currently no packet-drop statistics stored
261 in libpcap captures, and that's what we're reading.
263 At some point, we will add support in Wiretap to return
264 packet-drop statistics for capture file formats that store it,
265 and will make "cf_read()" get those statistics from Wiretap.
266 We clear the statistics (marking them as "not known") in
267 "cf_open()", and "cf_read()" will only fetch them and mark
268 them as known if Wiretap supplies them, so if we get the
269 statistics now, after calling "cf_open()" but before calling
270 "cf_read()", the values we store will be used by "cf_read()".
272 If a future libpcap capture file format stores the statistics,
273 we'll put them into the capture file that we write, and will
274 thus not have to set them here - "cf_read()" will get them from
275 the file and use them. */
277 cf_set_drops_known(capture_opts->cf, TRUE);
279 /* XXX - on some systems, libpcap doesn't bother filling in
280 "ps_ifdrop" - it doesn't even set it to zero - so we don't
281 bother looking at it.
283 Ideally, libpcap would have an interface that gave us
284 several statistics - perhaps including various interface
285 error statistics - and would tell us which of them it
286 supplies, allowing us to display only the ones it does. */
287 cf_set_drops(capture_opts->cf, drops);
290 /* read in the packet data */
291 switch (cf_read(capture_opts->cf)) {
295 /* Just because we got an error, that doesn't mean we were unable
296 to read any of the file; we handle what we could get from the
300 case CF_READ_ABORTED:
301 /* User wants to quit program. Exit by leaving the main loop,
302 so that any quit functions we registered get called. */
303 main_window_nested_quit();
307 /* if we didn't capture even a single packet, close the file again */
308 if(cf_get_packet_count(capture_opts->cf) == 0 && !capture_opts->restart) {
309 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
310 "%sNo packets captured!%s\n"
312 "As no data was captured, closing the %scapture file!\n"
315 "Help about capturing can be found at:\n"
317 " http://wiki.wireshark.org/CaptureSetup"
320 "Wireless (Wi-Fi/WLAN):\n"
321 "Try to switch off promiscuous mode in the Capture Options!"
324 simple_dialog_primary_start(), simple_dialog_primary_end(),
325 (cf_is_tempfile(capture_opts->cf)) ? "temporary " : "");
326 cf_close(capture_opts->cf);
332 /* capture child tells us we have a new (or the first) capture file */
334 capture_input_new_file(capture_options *capture_opts, gchar *new_file)
336 gboolean is_tempfile;
340 if(capture_opts->state == CAPTURE_PREPARING) {
341 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture started!");
343 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "File: \"%s\"", new_file);
345 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
347 /* free the old filename */
348 if(capture_opts->save_file != NULL) {
349 /* we start a new capture file, close the old one (if we had one before). */
350 /* (we can only have an open capture file in real_time_mode!) */
351 if( ((capture_file *) capture_opts->cf)->state != FILE_CLOSED) {
352 capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
353 cf_finish_tail(capture_opts->cf, &err);
354 cf_close(capture_opts->cf);
356 g_free(capture_opts->save_file);
358 cf_set_tempfile(capture_opts->cf, FALSE);
360 /* we didn't have a save_file before; must be a tempfile */
362 cf_set_tempfile(capture_opts->cf, TRUE);
365 /* save the new filename */
366 capture_opts->save_file = g_strdup(new_file);
368 /* if we are in real-time mode, open the new file now */
369 if(capture_opts->real_time_mode) {
370 /* Attempt to open the capture file and set up to read from it. */
371 switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
375 /* Don't unlink (delete) the save file - leave it around,
376 for debugging purposes. */
377 g_free(capture_opts->save_file);
378 capture_opts->save_file = NULL;
383 if(capture_opts->show_info) {
384 if (!capture_info_new_file(new_file))
388 if(capture_opts->real_time_mode) {
389 capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
391 capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
393 capture_opts->state = CAPTURE_RUNNING;
399 /* capture child tells us we have new packets to read */
401 capture_input_new_packets(capture_options *capture_opts, int to_read)
406 g_assert(capture_opts->save_file);
408 if(capture_opts->real_time_mode) {
409 /* Read from the capture file the number of records the child told us it added. */
410 switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
414 /* Just because we got an error, that doesn't mean we were unable
415 to read any of the file; we handle what we could get from the
418 XXX - abort on a read error? */
419 capture_callback_invoke(capture_cb_capture_update_continue, capture_opts);
422 case CF_READ_ABORTED:
423 /* Kill the child capture process; the user wants to exit, and we
424 shouldn't just leave it running. */
425 capture_kill_child(capture_opts);
429 /* increase the capture file packet counter by the number of incoming packets */
430 cf_set_packet_count(capture_opts->cf,
431 cf_get_packet_count(capture_opts->cf) + to_read);
433 capture_callback_invoke(capture_cb_capture_fixed_continue, capture_opts);
436 /* update the main window so we get events (e.g. from the stop toolbar button) */
437 main_window_update();
439 if(capture_opts->show_info)
440 capture_info_new_packets(to_read);
444 /* Capture child told us how many dropped packets it counted.
447 capture_input_drops(capture_options *capture_opts, guint32 dropped)
449 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%u packet%s dropped", dropped, plurality(dropped, "", "s"));
451 g_assert(capture_opts->state == CAPTURE_RUNNING);
453 cf_set_drops_known(capture_opts->cf, TRUE);
454 cf_set_drops(capture_opts->cf, dropped);
458 /* Capture child told us that an error has occurred while starting/running
460 The buffer we're handed has *two* null-terminated strings in it - a
461 primary message and a secondary message, one right after the other.
462 The secondary message might be a null string.
465 capture_input_error_message(capture_options *capture_opts, char *error_msg, char *secondary_error_msg)
467 gchar *safe_error_msg;
468 gchar *safe_secondary_error_msg;
470 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\", \"%s\"",
471 error_msg, secondary_error_msg);
473 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
475 safe_error_msg = simple_dialog_format_message(error_msg);
476 if (*secondary_error_msg != '\0') {
477 /* We have both primary and secondary messages. */
478 safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
479 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s\n\n%s",
480 simple_dialog_primary_start(), safe_error_msg,
481 simple_dialog_primary_end(), safe_secondary_error_msg);
482 g_free(safe_secondary_error_msg);
484 /* We have only a primary message. */
485 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s",
486 simple_dialog_primary_start(), safe_error_msg,
487 simple_dialog_primary_end());
489 g_free(safe_error_msg);
491 /* the capture child will close the sync_pipe if required, nothing to do for now */
496 /* Capture child told us that an error has occurred while parsing a
497 capture filter when starting/running the capture.
500 capture_input_cfilter_error_message(capture_options *capture_opts, char *error_message)
502 dfilter_t *rfcode = NULL;
503 gchar *safe_cfilter = simple_dialog_format_message(capture_opts->cfilter);
504 gchar *safe_cfilter_error_msg = simple_dialog_format_message(error_message);
506 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
508 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
510 /* Did the user try a display filter? */
511 if (dfilter_compile(capture_opts->cfilter, &rfcode) && rfcode != NULL) {
512 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
513 "%sInvalid capture filter: \"%s\"!%s\n"
515 "That string looks like a valid display filter; however, it isn't a valid\n"
516 "capture filter (%s).\n"
518 "Note that display filters and capture filters don't have the same syntax,\n"
519 "so you can't use most display filter expressions as capture filters.\n"
521 "See the User's Guide for a description of the capture filter syntax.",
522 simple_dialog_primary_start(), safe_cfilter,
523 simple_dialog_primary_end(), safe_cfilter_error_msg);
524 dfilter_free(rfcode);
526 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
527 "%sInvalid capture filter: \"%s\"!%s\n"
529 "That string isn't a valid capture filter (%s).\n"
530 "See the User's Guide for a description of the capture filter syntax.",
531 simple_dialog_primary_start(), safe_cfilter,
532 simple_dialog_primary_end(), safe_cfilter_error_msg);
534 g_free(safe_cfilter_error_msg);
535 g_free(safe_cfilter);
537 /* the capture child will close the sync_pipe if required, nothing to do for now */
541 /* capture child closed its side of the pipe, do the required cleanup */
543 capture_input_closed(capture_options *capture_opts)
546 int packet_count_save;
548 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
549 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
551 /* if we didn't start the capture, do a fake start. */
552 /* (happens if we got an error message - we won't get a filename then). */
553 if(capture_opts->state == CAPTURE_PREPARING) {
554 if(capture_opts->real_time_mode) {
555 capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
557 capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
561 if(capture_opts->real_time_mode) {
562 cf_read_status_t status;
564 /* Read what remains of the capture file. */
565 status = cf_finish_tail(capture_opts->cf, &err);
567 /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
568 packet_count_save = cf_get_packet_count(capture_opts->cf);
569 /* Tell the GUI we are not doing a capture any more.
570 Must be done after the cf_finish_tail(), so file lengths are
571 correctly displayed */
572 capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
574 /* Finish the capture. */
578 if ((packet_count_save == 0) && !capture_opts->restart) {
579 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
580 "%sNo packets captured!%s\n"
582 "As no data was captured, closing the %scapture file!\n"
585 "Help about capturing can be found at:\n"
587 " http://wiki.wireshark.org/CaptureSetup"
590 "Wireless (Wi-Fi/WLAN):\n"
591 "Try to switch off promiscuous mode in the Capture Options!"
594 simple_dialog_primary_start(), simple_dialog_primary_end(),
595 cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
596 cf_close(capture_opts->cf);
600 /* Just because we got an error, that doesn't mean we were unable
601 to read any of the file; we handle what we could get from the
605 case CF_READ_ABORTED:
606 /* Exit by leaving the main loop, so that any quit functions
607 we registered get called. */
612 /* first of all, we are not doing a capture any more */
613 capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts);
615 /* this is a normal mode capture and if no error happened, read in the capture file data */
616 if(capture_opts->save_file != NULL) {
617 capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
618 cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
622 if(capture_opts->show_info)
623 capture_info_close();
625 capture_opts->state = CAPTURE_STOPPED;
627 /* if we couldn't open a capture file, there's nothing more for us to do */
628 if(capture_opts->save_file == NULL) {
629 cf_close(capture_opts->cf);
633 /* does the user wants to restart the current capture? */
634 if(capture_opts->restart) {
635 capture_opts->restart = FALSE;
637 ws_unlink(capture_opts->save_file);
639 /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
640 if(cf_is_tempfile(capture_opts->cf)) {
641 g_free(capture_opts->save_file);
642 capture_opts->save_file = NULL;
645 /* ... and start the capture again */
646 capture_start(capture_opts);
648 /* We're not doing a capture any more, so we don't have a save file. */
649 g_free(capture_opts->save_file);
650 capture_opts->save_file = NULL;
655 * Fetch the interface list from a child process (dumpcap).
657 * @return A GList containing if_info_t structs if successful, NULL (with err and possibly err_str set) otherwise.
661 /* XXX - We parse simple text output to get our interface list. Should
662 * we use "real" data serialization instead, e.g. via XML? */
664 capture_interface_list(int *err, char **err_str)
666 GList *if_list = NULL;
669 gchar **raw_list, **if_parts, **addr_parts;
674 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
676 /* Try to get our interface list */
677 *err = sync_interface_list_open(&msg);
679 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
688 /* Split our lines */
690 raw_list = g_strsplit(msg, "\r\n", 0);
692 raw_list = g_strsplit(msg, "\n", 0);
696 for (i = 0; raw_list[i] != NULL; i++) {
697 if_parts = g_strsplit(raw_list[i], "\t", 4);
698 if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL ||
699 if_parts[3] == NULL) {
700 g_strfreev(if_parts);
704 /* Number followed by the name, e.g "1. eth0" */
705 name = strchr(if_parts[0], ' ');
709 g_strfreev(if_parts);
713 if_info = g_malloc0(sizeof(if_info_t));
714 if_info->name = g_strdup(name);
715 if (strlen(if_parts[1]) > 0)
716 if_info->description = g_strdup(if_parts[1]);
717 addr_parts = g_strsplit(if_parts[2], ",", 0);
718 for (j = 0; addr_parts[j] != NULL; j++) {
719 if_addr = g_malloc0(sizeof(if_addr_t));
720 if (inet_pton(AF_INET, addr_parts[j], &if_addr->ip_addr.ip4_addr)) {
721 if_addr->type = AT_IPv4;
722 } else if (inet_pton(AF_INET6, addr_parts[j],
723 &if_addr->ip_addr.ip6_addr)) {
724 if_addr->type = AT_IPv6;
730 if_info->ip_addr = g_slist_append(if_info->ip_addr, if_addr);
733 if (strcmp(if_parts[3], "loopback") == 0)
734 if_info->loopback = TRUE;
735 g_strfreev(if_parts);
736 g_strfreev(addr_parts);
737 if_list = g_list_append(if_list, if_info);
739 g_strfreev(raw_list);
741 /* Check to see if we built a list */
742 if (if_list == NULL) {
743 *err = NO_INTERFACES_FOUND;
745 *err_str = g_strdup("No interfaces found");
750 /* XXX - We parse simple text output to get our interface list. Should
751 * we use "real" data serialization instead, e.g. via XML? */
753 capture_pcap_linktype_list(const gchar *ifname, char **err_str)
755 GList *linktype_list = NULL;
758 gchar **raw_list, **lt_parts;
759 data_link_info_t *data_link_info;
761 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
763 /* Try to get our interface list */
764 err = sync_linktype_list_open(ifname, &msg);
766 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
775 /* Split our lines */
777 raw_list = g_strsplit(msg, "\r\n", 0);
779 raw_list = g_strsplit(msg, "\n", 0);
783 for (i = 0; raw_list[i] != NULL; i++) {
784 /* ...and what if the interface name has a tab in it, Mr. Clever Programmer? */
785 lt_parts = g_strsplit(raw_list[i], "\t", 3);
786 if (lt_parts[0] == NULL || lt_parts[1] == NULL || lt_parts[2] == NULL) {
787 g_strfreev(lt_parts);
791 data_link_info = g_malloc(sizeof (data_link_info_t));
792 data_link_info->dlt = (int) strtol(lt_parts[0], NULL, 10);
793 data_link_info->name = g_strdup(lt_parts[1]);
794 if (strcmp(lt_parts[2], "(not supported)") != 0)
795 data_link_info->description = g_strdup(lt_parts[2]);
797 data_link_info->description = NULL;
799 linktype_list = g_list_append(linktype_list, data_link_info);
801 g_strfreev(raw_list);
803 /* Check to see if we built a list */
804 if (linktype_list == NULL) {
808 return linktype_list;
812 capture_stat_start(GList *if_list) {
813 int stat_fd, fork_child;
815 if_stat_cache_t *sc = NULL;
818 if_stat_cache_item_t *sc_item;
820 /* Fire up dumpcap. */
822 * XXX - on systems with BPF, the number of BPF devices limits the
823 * number of devices on which you can capture simultaneously.
827 * 1) this might fail if you run out of BPF devices
831 * 2) opening every interface could leave too few BPF devices
832 * for *other* programs.
834 * It also means the system could end up getting a lot of traffic
835 * that it has to pass through the networking stack and capture
836 * mechanism, so opening all the devices and presenting packet
837 * counts might not always be a good idea.
839 if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
840 sc = g_malloc(sizeof(if_stat_cache_t));
841 sc->stat_fd = stat_fd;
842 sc->fork_child = fork_child;
843 sc->cache_list = NULL;
845 /* Initialize the cache */
846 for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
847 if_info = if_entry->data;
848 sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
849 sc_item->name = g_strdup(if_info->name);
850 sc->cache_list = g_list_append(sc->cache_list, sc_item);
856 #define MAX_STAT_LINE_LEN 500
859 capture_stat_cache_update(if_stat_cache_t *sc) {
860 gchar stat_line[MAX_STAT_LINE_LEN];
863 if_stat_cache_item_t *sc_item;
868 while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
869 g_strstrip(stat_line);
870 stat_parts = g_strsplit(stat_line, "\t", 3);
871 if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
872 stat_parts[2] == NULL) {
873 g_strfreev(stat_parts);
876 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
877 sc_item = sc_entry->data;
878 if (strcmp(sc_item->name, stat_parts[0]) == 0) {
879 sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
880 sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
883 g_strfreev(stat_parts);
888 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
890 if_stat_cache_item_t *sc_item;
892 if (!sc || !ifname || !ps) {
896 capture_stat_cache_update(sc);
897 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
898 sc_item = sc_entry->data;
899 if (strcmp(sc_item->name, ifname) == 0) {
900 memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
908 capture_stat_stop(if_stat_cache_t *sc) {
910 if_stat_cache_item_t *sc_item;
916 sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
918 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
919 sc_item = sc_entry->data;
920 g_free(sc_item->name);
926 #endif /* HAVE_LIBPCAP */