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 */
110 * @return TRUE if the capture starts successfully, FALSE otherwise.
113 capture_start(capture_options *capture_opts)
118 /* close the currently loaded capture file */
119 cf_close(capture_opts->cf);
121 g_assert(capture_opts->state == CAPTURE_STOPPED);
122 capture_opts->state = CAPTURE_PREPARING;
124 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ...");
126 /* try to start the capture child process */
127 ret = sync_pipe_start(capture_opts);
129 if(capture_opts->save_file != NULL) {
130 g_free(capture_opts->save_file);
131 capture_opts->save_file = NULL;
134 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start failed!");
135 capture_opts->state = CAPTURE_STOPPED;
137 /* the capture child might not respond shortly after bringing it up */
138 /* (especially it will block, if no input coming from an input capture pipe (e.g. mkfifo) is coming in) */
140 /* to prevent problems, bring the main GUI into "capture mode" right after successfully */
141 /* spawn/exec the capture child, without waiting for any response from it */
142 cf_callback_invoke(cf_cb_live_capture_prepared, capture_opts);
144 if(capture_opts->show_info)
145 capture_info_open(capture_opts->iface);
153 capture_stop(capture_options *capture_opts)
155 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Stop ...");
157 cf_callback_invoke(cf_cb_live_capture_stopping, capture_opts);
159 /* stop the capture child gracefully */
160 sync_pipe_stop(capture_opts);
165 capture_restart(capture_options *capture_opts)
167 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Restart");
169 capture_opts->restart = TRUE;
170 capture_stop(capture_opts);
175 capture_kill_child(capture_options *capture_opts)
177 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "Capture Kill");
179 /* kill the capture child */
180 sync_pipe_kill(capture_opts->fork_child);
185 /* We've succeeded a (non real-time) capture, try to read it into a new capture file */
187 capture_input_read_all(capture_options *capture_opts, gboolean is_tempfile, gboolean drops_known,
193 /* Capture succeeded; attempt to open the capture file. */
194 if (cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err) != CF_OK) {
195 /* We're not doing a capture any more, so we don't have a save
200 /* Set the read filter to NULL. */
201 /* XXX - this is odd here, try to put it somewhere, where it fits better */
202 cf_set_rfcode(capture_opts->cf, NULL);
204 /* Get the packet-drop statistics.
206 XXX - there are currently no packet-drop statistics stored
207 in libpcap captures, and that's what we're reading.
209 At some point, we will add support in Wiretap to return
210 packet-drop statistics for capture file formats that store it,
211 and will make "cf_read()" get those statistics from Wiretap.
212 We clear the statistics (marking them as "not known") in
213 "cf_open()", and "cf_read()" will only fetch them and mark
214 them as known if Wiretap supplies them, so if we get the
215 statistics now, after calling "cf_open()" but before calling
216 "cf_read()", the values we store will be used by "cf_read()".
218 If a future libpcap capture file format stores the statistics,
219 we'll put them into the capture file that we write, and will
220 thus not have to set them here - "cf_read()" will get them from
221 the file and use them. */
223 cf_set_drops_known(capture_opts->cf, TRUE);
225 /* XXX - on some systems, libpcap doesn't bother filling in
226 "ps_ifdrop" - it doesn't even set it to zero - so we don't
227 bother looking at it.
229 Ideally, libpcap would have an interface that gave us
230 several statistics - perhaps including various interface
231 error statistics - and would tell us which of them it
232 supplies, allowing us to display only the ones it does. */
233 cf_set_drops(capture_opts->cf, drops);
236 /* read in the packet data */
237 switch (cf_read(capture_opts->cf)) {
241 /* Just because we got an error, that doesn't mean we were unable
242 to read any of the file; we handle what we could get from the
246 case CF_READ_ABORTED:
247 /* User wants to quit program. Exit by leaving the main loop,
248 so that any quit functions we registered get called. */
249 main_window_nested_quit();
253 /* if we didn't captured even a single packet, close the file again */
254 if(cf_get_packet_count(capture_opts->cf) == 0 && !capture_opts->restart) {
255 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
256 "%sNo packets captured!%s\n"
258 "As no data was captured, closing the %scapture file!\n"
261 "Help about capturing can be found at:\n"
263 " http://wiki.wireshark.org/CaptureSetup"
266 "Wireless (Wi-Fi/WLAN):\n"
267 "Try to switch off promiscuous mode in the Capture Options!"
270 simple_dialog_primary_start(), simple_dialog_primary_end(),
271 (cf_is_tempfile(capture_opts->cf)) ? "temporary " : "");
272 cf_close(capture_opts->cf);
278 /* capture child tells us we have a new (or the first) capture file */
280 capture_input_new_file(capture_options *capture_opts, gchar *new_file)
282 gboolean is_tempfile;
286 if(capture_opts->state == CAPTURE_PREPARING) {
287 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture started!");
289 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "File: \"%s\"", new_file);
291 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
293 /* free the old filename */
294 if(capture_opts->save_file != NULL) {
295 /* we start a new capture file, close the old one (if we had one before) */
296 /* (we can only have an open capture file in real_time_mode!) */
297 if( ((capture_file *) capture_opts->cf)->state != FILE_CLOSED) {
298 cf_callback_invoke(cf_cb_live_capture_update_finished, capture_opts->cf);
299 cf_finish_tail(capture_opts->cf, &err);
300 cf_close(capture_opts->cf);
302 g_free(capture_opts->save_file);
304 cf_set_tempfile(capture_opts->cf, FALSE);
306 /* we didn't had a save_file before, must be a tempfile */
308 cf_set_tempfile(capture_opts->cf, TRUE);
311 /* save the new filename */
312 capture_opts->save_file = g_strdup(new_file);
314 /* if we are in real-time mode, open the new file now */
315 if(capture_opts->real_time_mode) {
316 /* Attempt to open the capture file and set up to read from it. */
317 switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
321 /* Don't unlink (delete) the save file - leave it around,
322 for debugging purposes. */
323 g_free(capture_opts->save_file);
324 capture_opts->save_file = NULL;
329 if(capture_opts->show_info) {
330 if (!capture_info_new_file(new_file))
334 if(capture_opts->real_time_mode) {
335 cf_callback_invoke(cf_cb_live_capture_update_started, capture_opts);
337 cf_callback_invoke(cf_cb_live_capture_fixed_started, capture_opts);
339 capture_opts->state = CAPTURE_RUNNING;
345 /* capture child tells us we have new packets to read */
347 capture_input_new_packets(capture_options *capture_opts, int to_read)
352 g_assert(capture_opts->save_file);
354 if(capture_opts->real_time_mode) {
355 /* Read from the capture file the number of records the child told us it added. */
356 switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
360 /* Just because we got an error, that doesn't mean we were unable
361 to read any of the file; we handle what we could get from the
364 XXX - abort on a read error? */
365 cf_callback_invoke(cf_cb_live_capture_update_continue, capture_opts->cf);
368 case CF_READ_ABORTED:
369 /* Kill the child capture process; the user wants to exit, and we
370 shouldn't just leave it running. */
371 capture_kill_child(capture_opts);
375 /* increase capture file packet counter by the number or incoming packets */
376 cf_set_packet_count(capture_opts->cf,
377 cf_get_packet_count(capture_opts->cf) + to_read);
379 cf_callback_invoke(cf_cb_live_capture_fixed_continue, capture_opts->cf);
382 /* update the main window, so we get events (e.g. from the stop toolbar button) */
383 main_window_update();
385 if(capture_opts->show_info)
386 capture_info_new_packets(to_read);
390 /* Capture child told us how many dropped packets it counted.
393 capture_input_drops(capture_options *capture_opts, int dropped)
395 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", dropped, plurality(dropped, "", "s"));
397 g_assert(capture_opts->state == CAPTURE_RUNNING);
399 cf_set_drops_known(capture_opts->cf, TRUE);
400 cf_set_drops(capture_opts->cf, dropped);
404 /* Capture child told us that an error has occurred while starting/running
406 The buffer we're handed has *two* null-terminated strings in it - a
407 primary message and a secondary message, one right after the other.
408 The secondary message might be a null string.
411 capture_input_error_message(capture_options *capture_opts, char *error_msg, char *secondary_error_msg)
413 gchar *safe_error_msg;
414 gchar *safe_secondary_error_msg;
416 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\", \"%s\"",
417 error_msg, secondary_error_msg);
419 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
421 safe_error_msg = simple_dialog_format_message(error_msg);
422 if (*secondary_error_msg != '\0') {
423 /* We have both primary and secondary messages. */
424 safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
425 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s\n\n%s",
426 simple_dialog_primary_start(), safe_error_msg,
427 simple_dialog_primary_end(), safe_secondary_error_msg);
428 g_free(safe_secondary_error_msg);
430 /* We have only a primary message. */
431 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s",
432 simple_dialog_primary_start(), safe_error_msg,
433 simple_dialog_primary_end());
435 g_free(safe_error_msg);
437 /* the capture child will close the sync_pipe if required, nothing to do for now */
442 /* Capture child told us that an error has occurred while parsing a
443 capture filter when starting/running the capture.
446 capture_input_cfilter_error_message(capture_options *capture_opts, char *error_message)
448 dfilter_t *rfcode = NULL;
449 gchar *safe_cfilter = simple_dialog_format_message(capture_opts->cfilter);
450 gchar *safe_cfilter_error_msg = simple_dialog_format_message(error_message);
452 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
454 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
456 /* Did the user try a display filter? */
457 if (dfilter_compile(capture_opts->cfilter, &rfcode) && rfcode != NULL) {
458 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
459 "%sInvalid capture filter: \"%s\"!%s\n"
461 "That string looks like a valid display filter; however, it isn't a valid\n"
462 "capture filter (%s).\n"
464 "Note that display filters and capture filters don't have the same syntax,\n"
465 "so you can't use most display filter expressions as capture filters.\n"
467 "See the User's Guide for a description of the capture filter syntax.",
468 simple_dialog_primary_start(), safe_cfilter,
469 simple_dialog_primary_end(), safe_cfilter_error_msg);
470 dfilter_free(rfcode);
472 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
473 "%sInvalid capture filter: \"%s\"!%s\n"
475 "That string isn't a valid capture filter (%s).\n"
476 "See the User's Guide for a description of the capture filter syntax.",
477 simple_dialog_primary_start(), safe_cfilter,
478 simple_dialog_primary_end(), safe_cfilter_error_msg);
480 g_free(safe_cfilter_error_msg);
481 g_free(safe_cfilter);
483 /* the capture child will close the sync_pipe if required, nothing to do for now */
487 /* capture child closed its side of the pipe, do the required cleanup */
489 capture_input_closed(capture_options *capture_opts)
492 int packet_count_save;
494 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
495 g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
497 /* if we didn't started the capture, do a fake start */
498 /* (happens if we got an error message - we won't get a filename then) */
499 if(capture_opts->state == CAPTURE_PREPARING) {
500 if(capture_opts->real_time_mode) {
501 cf_callback_invoke(cf_cb_live_capture_update_started, capture_opts);
503 cf_callback_invoke(cf_cb_live_capture_fixed_started, capture_opts);
507 if(capture_opts->real_time_mode) {
508 cf_read_status_t status;
510 /* Read what remains of the capture file. */
511 status = cf_finish_tail(capture_opts->cf, &err);
513 /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
514 packet_count_save = cf_get_packet_count(capture_opts->cf);
515 /* Tell the GUI, we are not doing a capture any more.
516 Must be done after the cf_finish_tail(), so file lengths are displayed
518 cf_callback_invoke(cf_cb_live_capture_update_finished, capture_opts->cf);
520 /* Finish the capture. */
524 if ((packet_count_save == 0) && !capture_opts->restart) {
525 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
526 "%sNo packets captured!%s\n"
528 "As no data was captured, closing the %scapture file!\n"
531 "Help about capturing can be found at:\n"
533 " http://wiki.wireshark.org/CaptureSetup"
536 "Wireless (Wi-Fi/WLAN):\n"
537 "Try to switch off promiscuous mode in the Capture Options!"
540 simple_dialog_primary_start(), simple_dialog_primary_end(),
541 cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
542 cf_close(capture_opts->cf);
546 /* Just because we got an error, that doesn't mean we were unable
547 to read any of the file; we handle what we could get from the
551 case CF_READ_ABORTED:
552 /* Exit by leaving the main loop, so that any quit functions
553 we registered get called. */
558 /* first of all, we are not doing a capture any more */
559 cf_callback_invoke(cf_cb_live_capture_fixed_finished, capture_opts->cf);
561 /* this is a normal mode capture and if no error happened, read in the capture file data */
562 if(capture_opts->save_file != NULL) {
563 capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
564 cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
568 if(capture_opts->show_info)
569 capture_info_close();
571 capture_opts->state = CAPTURE_STOPPED;
573 /* if we couldn't open a capture file, there's nothing more for us to do */
574 if(capture_opts->save_file == NULL) {
575 cf_close(capture_opts->cf);
579 /* does the user wants to restart the current capture? */
580 if(capture_opts->restart) {
581 capture_opts->restart = FALSE;
583 ws_unlink(capture_opts->save_file);
585 /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
586 if(cf_is_tempfile(capture_opts->cf)) {
587 g_free(capture_opts->save_file);
588 capture_opts->save_file = NULL;
591 /* ... and start the capture again */
592 capture_start(capture_opts);
594 /* We're not doing a capture any more, so we don't have a save file. */
595 g_free(capture_opts->save_file);
596 capture_opts->save_file = NULL;
601 * Fetch the interface list from a child process (dumpcap).
603 * @return A GList containing if_info_t structs if successful, NULL otherwise.
606 /* XXX - We parse simple text output to get our interface list. Should
607 * we use "real" data serialization instead, e.g. via XML? */
609 capture_interface_list(int *err, char **err_str)
611 GList *if_list = NULL;
614 gchar **raw_list, **if_parts, **addr_parts;
619 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
621 /* Try to get our interface list */
622 *err = sync_interface_list_open(&msg);
624 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
636 /* Split our lines */
638 raw_list = g_strsplit(msg, "\r\n", 0);
640 raw_list = g_strsplit(msg, "\n", 0);
644 for (i = 0; raw_list[i] != NULL; i++) {
645 if_parts = g_strsplit(raw_list[i], "\t", 4);
646 if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL ||
647 if_parts[3] == NULL) {
648 g_strfreev(if_parts);
652 /* Number followed by the name, e.g "1. eth0" */
653 name = strchr(if_parts[0], ' ');
657 g_strfreev(if_parts);
661 if_info = g_malloc0(sizeof(if_info_t));
662 if_info->name = g_strdup(name);
663 if (strlen(if_parts[1]) > 0)
664 if_info->description = g_strdup(if_parts[1]);
665 addr_parts = g_strsplit(if_parts[2], ",", 0);
666 for (j = 0; addr_parts[j] != NULL; j++) {
667 if_addr = g_malloc0(sizeof(if_addr_t));
668 if (inet_pton(AF_INET, addr_parts[j], &if_addr->ip_addr.ip4_addr)) {
669 if_addr->type = AT_IPv4;
670 } else if (inet_pton(AF_INET6, addr_parts[j],
671 &if_addr->ip_addr.ip6_addr)) {
672 if_addr->type = AT_IPv6;
678 if_info->ip_addr = g_slist_append(if_info->ip_addr, if_addr);
681 if (strcmp(if_parts[3], "loopback") == 0)
682 if_info->loopback = TRUE;
683 g_strfreev(if_parts);
684 g_strfreev(addr_parts);
685 if_list = g_list_append(if_list, if_info);
687 g_strfreev(raw_list);
689 /* Check to see if we built a list */
690 if (if_list == NULL) {
691 if (err_str && *err_str)
692 *err_str = g_strdup("No interfaces found");
693 *err = NO_INTERFACES_FOUND;
698 /* XXX - We parse simple text output to get our interface list. Should
699 * we use "real" data serialization instead, e.g. via XML? */
701 capture_pcap_linktype_list(const gchar *ifname, char **err_str)
703 GList *linktype_list = NULL;
706 gchar **raw_list, **lt_parts;
707 data_link_info_t *data_link_info;
709 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
711 /* Try to get our interface list */
712 err = sync_linktype_list_open(ifname, &msg);
714 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
723 /* Split our lines */
725 raw_list = g_strsplit(msg, "\r\n", 0);
727 raw_list = g_strsplit(msg, "\n", 0);
731 for (i = 0; raw_list[i] != NULL; i++) {
732 /* ...and what if the interface name has a tab in it, Mr. Clever Programmer? */
733 lt_parts = g_strsplit(raw_list[i], "\t", 3);
734 if (lt_parts[0] == NULL || lt_parts[1] == NULL || lt_parts[2] == NULL) {
735 g_strfreev(lt_parts);
739 data_link_info = g_malloc(sizeof (data_link_info_t));
740 data_link_info->dlt = (int) strtol(lt_parts[0], NULL, 10);
741 data_link_info->name = g_strdup(lt_parts[1]);
742 if (strcmp(lt_parts[2], "(not supported)") != 0)
743 data_link_info->description = g_strdup(lt_parts[2]);
745 data_link_info->description = NULL;
747 linktype_list = g_list_append(linktype_list, data_link_info);
749 g_strfreev(raw_list);
751 /* Check to see if we built a list */
752 if (linktype_list == NULL) {
756 return linktype_list;
760 capture_stat_start(GList *if_list) {
761 int stat_fd, fork_child;
763 if_stat_cache_t *sc = NULL;
766 if_stat_cache_item_t *sc_item;
768 /* Fire up dumpcap. */
770 * XXX - on systems with BPF, the number of BPF devices limits the
771 * number of devices on which you can capture simultaneously.
775 * 1) this might fail if you run out of BPF devices
779 * 2) opening every interface could leave too few BPF devices
780 * for *other* programs.
782 * It also means the system could end up getting a lot of traffic
783 * that it has to pass through the networking stack and capture
784 * mechanism, so opening all the devices and presenting packet
785 * counts might not always be a good idea.
787 if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
788 sc = g_malloc(sizeof(if_stat_cache_t));
789 sc->stat_fd = stat_fd;
790 sc->fork_child = fork_child;
791 sc->cache_list = NULL;
793 /* Initialize the cache */
794 for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
795 if_info = if_entry->data;
796 sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
797 sc_item->name = g_strdup(if_info->name);
798 sc->cache_list = g_list_append(sc->cache_list, sc_item);
804 #define MAX_STAT_LINE_LEN 500
807 capture_stat_cache_update(if_stat_cache_t *sc) {
808 gchar stat_line[MAX_STAT_LINE_LEN];
811 if_stat_cache_item_t *sc_item;
816 while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
817 g_strstrip(stat_line);
818 stat_parts = g_strsplit(stat_line, "\t", 3);
819 if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
820 stat_parts[2] == NULL) {
821 g_strfreev(stat_parts);
824 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
825 sc_item = sc_entry->data;
826 if (strcmp(sc_item->name, stat_parts[0]) == 0) {
827 sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
828 sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
831 g_strfreev(stat_parts);
836 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
838 if_stat_cache_item_t *sc_item;
840 if (!sc || !ifname || !ps) {
844 capture_stat_cache_update(sc);
845 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
846 sc_item = sc_entry->data;
847 if (strcmp(sc_item->name, ifname) == 0) {
848 memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
856 capture_stat_stop(if_stat_cache_t *sc) {
858 if_stat_cache_item_t *sc_item;
864 sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
866 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
867 sc_item = sc_entry->data;
868 g_free(sc_item->name);
874 #endif /* HAVE_LIBPCAP */