When capturing from multiple interfaces, indicate this in the window
[metze/wireshark/wip.git] / capture.c
1 /* capture.c
2  * Routines for packet capture
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include <glib.h>
39
40 #include <epan/packet.h>
41 #include <epan/dfilter/dfilter.h>
42 #include "file.h"
43 #include "capture.h"
44 #include "capture_ifinfo.h"
45 #include "capture_sync.h"
46 #include "capture_info.h"
47 #include "capture_ui_utils.h"
48 #include "util.h"
49 #include "capture-pcap-util.h"
50 #include "simple_dialog.h"
51 #include <epan/prefs.h>
52
53 #ifdef _WIN32
54 #include "capture-wpcap.h"
55 #endif
56 #include "ui_util.h"
57 #include "wsutil/file_util.h"
58 #include "log.h"
59
60 typedef struct if_stat_cache_item_s {
61     char *name;
62     struct pcap_stat ps;
63 } if_stat_cache_item_t;
64
65 struct if_stat_cache_s {
66     int stat_fd;
67     int fork_child;
68     GList *cache_list;  /* List of if_stat_chache_entry_t */
69 };
70
71 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
72 typedef struct {
73     capture_callback_t cb_fct;
74     gpointer user_data;
75 } capture_callback_data_t;
76
77 static GList *capture_callbacks = NULL;
78
79 static void
80 capture_callback_invoke(int event, capture_options *capture_opts)
81 {
82     capture_callback_data_t *cb;
83     GList *cb_item = capture_callbacks;
84
85     /* there should be at least one interested */
86     g_assert(cb_item != NULL);
87
88     while(cb_item != NULL) {
89         cb = cb_item->data;
90         cb->cb_fct(event, capture_opts, cb->user_data);
91         cb_item = g_list_next(cb_item);
92     }
93 }
94
95
96 void
97 capture_callback_add(capture_callback_t func, gpointer user_data)
98 {
99     capture_callback_data_t *cb;
100
101     cb = g_malloc(sizeof(capture_callback_data_t));
102     cb->cb_fct = func;
103     cb->user_data = user_data;
104
105     capture_callbacks = g_list_append(capture_callbacks, cb);
106 }
107
108 void
109 capture_callback_remove(capture_callback_t func)
110 {
111     capture_callback_data_t *cb;
112     GList *cb_item = capture_callbacks;
113
114     while(cb_item != NULL) {
115         cb = cb_item->data;
116         if(cb->cb_fct == func) {
117             capture_callbacks = g_list_remove(capture_callbacks, cb);
118             g_free(cb);
119             return;
120         }
121         cb_item = g_list_next(cb_item);
122     }
123
124     g_assert_not_reached();
125 }
126
127 /**
128  * Start a capture.
129  *
130  * @return TRUE if the capture starts successfully, FALSE otherwise.
131  */
132 gboolean
133 capture_start(capture_options *capture_opts)
134 {
135   gboolean ret;
136   guint i;
137   GString *source = g_string_new("");
138
139   if (capture_opts->state != CAPTURE_STOPPED)
140     return FALSE;
141   capture_opts->state = CAPTURE_PREPARING;
142
143   /* close the currently loaded capture file */
144   cf_close(capture_opts->cf);
145
146   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ...");
147
148 #ifdef _WIN32
149   if (capture_opts->ifaces->len < 2) {
150 #else
151   if (capture_opts->ifaces->len < 4) {
152 #endif
153     for (i = 0; i < capture_opts->ifaces->len; i++) {
154       interface_options interface_opts;
155
156       interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
157       if (i > 0) {
158           if (capture_opts->ifaces->len > 2) {
159               g_string_append_printf(source, ",");
160           }
161           g_string_append_printf(source, " ");
162           if (i == capture_opts->ifaces->len - 1) {
163               g_string_append_printf(source, "and ");
164           }
165       }
166       g_string_append_printf(source, "%s", get_iface_description_for_interface(capture_opts, i));
167       if ((interface_opts.cfilter != NULL) &&
168           (strlen(interface_opts.cfilter) > 0)) {
169         g_string_append_printf(source, " (%s)", interface_opts.cfilter);
170       }
171     }
172   } else {
173     g_string_append_printf(source, "%u interfaces", capture_opts->ifaces->len);
174   }
175   cf_set_tempfile_source(capture_opts->cf, source->str);
176   g_string_free(source, TRUE);
177
178   /* try to start the capture child process */
179   ret = sync_pipe_start(capture_opts);
180   if(!ret) {
181       if(capture_opts->save_file != NULL) {
182           g_free(capture_opts->save_file);
183           capture_opts->save_file = NULL;
184       }
185
186       g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start failed!");
187       capture_opts->state = CAPTURE_STOPPED;
188   } else {
189       /* the capture child might not respond shortly after bringing it up */
190       /* (for example: it will block if no input arrives from an input capture pipe (e.g. mkfifo)) */
191
192       /* to prevent problems, bring the main GUI into "capture mode" right after a successful */
193       /* spawn/exec of the capture child, without waiting for any response from it */
194       capture_callback_invoke(capture_cb_capture_prepared, capture_opts);
195
196       if(capture_opts->show_info)
197         capture_info_open(capture_opts);
198   }
199
200   return ret;
201 }
202
203
204 void
205 capture_stop(capture_options *capture_opts)
206 {
207   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Stop ...");
208
209   capture_callback_invoke(capture_cb_capture_stopping, capture_opts);
210
211   /* stop the capture child gracefully */
212   sync_pipe_stop(capture_opts);
213 }
214
215
216 void
217 capture_restart(capture_options *capture_opts)
218 {
219     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Restart");
220
221     capture_opts->restart = TRUE;
222     capture_stop(capture_opts);
223 }
224
225
226 void
227 capture_kill_child(capture_options *capture_opts)
228 {
229   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "Capture Kill");
230
231   /* kill the capture child */
232   sync_pipe_kill(capture_opts->fork_child);
233 }
234
235
236
237 /* We've succeeded in doing a (non real-time) capture; try to read it into a new capture file */
238 static gboolean
239 capture_input_read_all(capture_options *capture_opts, gboolean is_tempfile, gboolean drops_known,
240 guint32 drops)
241 {
242   int err;
243
244   /* Capture succeeded; attempt to open the capture file. */
245   if (cf_open(capture_opts->cf, capture_opts->save_file, is_tempfile, &err) != CF_OK) {
246     /* We're not doing a capture any more, so we don't have a save file. */
247     return FALSE;
248   }
249   
250   /* Set the read filter to NULL. */
251   /* XXX - this is odd here; try to put it somewhere where it fits better */
252   cf_set_rfcode(capture_opts->cf, NULL);
253
254   /* Get the packet-drop statistics.
255
256      XXX - there are currently no packet-drop statistics stored
257      in libpcap captures, and that's what we're reading.
258
259      At some point, we will add support in Wiretap to return
260      packet-drop statistics for capture file formats that store it,
261      and will make "cf_read()" get those statistics from Wiretap.
262      We clear the statistics (marking them as "not known") in
263      "cf_open()", and "cf_read()" will only fetch them and mark
264      them as known if Wiretap supplies them, so if we get the
265      statistics now, after calling "cf_open()" but before calling
266      "cf_read()", the values we store will be used by "cf_read()".
267
268      If a future libpcap capture file format stores the statistics,
269      we'll put them into the capture file that we write, and will
270      thus not have to set them here - "cf_read()" will get them from
271      the file and use them. */
272   if (drops_known) {
273     cf_set_drops_known(capture_opts->cf, TRUE);
274
275     /* XXX - on some systems, libpcap doesn't bother filling in
276        "ps_ifdrop" - it doesn't even set it to zero - so we don't
277        bother looking at it.
278
279        Ideally, libpcap would have an interface that gave us
280        several statistics - perhaps including various interface
281        error statistics - and would tell us which of them it
282        supplies, allowing us to display only the ones it does. */
283     cf_set_drops(capture_opts->cf, drops);
284   }
285
286   /* read in the packet data */
287   switch (cf_read(capture_opts->cf, FALSE)) {
288
289   case CF_READ_OK:
290   case CF_READ_ERROR:
291     /* Just because we got an error, that doesn't mean we were unable
292        to read any of the file; we handle what we could get from the
293        file. */
294     break;
295
296   case CF_READ_ABORTED:
297     /* User wants to quit program. Exit by leaving the main loop,
298        so that any quit functions we registered get called. */
299     main_window_nested_quit();
300     return FALSE;
301   }
302
303   /* if we didn't capture even a single packet, close the file again */
304   if(cf_get_packet_count(capture_opts->cf) == 0 && !capture_opts->restart) {
305     simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
306 "%sNo packets captured!%s\n"
307 "\n"
308 "As no data was captured, closing the %scapture file!\n"
309 "\n"
310 "\n"
311 "Help about capturing can be found at:\n"
312 "\n"
313 "       http://wiki.wireshark.org/CaptureSetup"
314 #ifdef _WIN32
315 "\n\n"
316 "Wireless (Wi-Fi/WLAN):\n"
317 "Try to switch off promiscuous mode in the Capture Options!"
318 #endif
319 "",
320     simple_dialog_primary_start(), simple_dialog_primary_end(),
321     (cf_is_tempfile(capture_opts->cf)) ? "temporary " : "");
322     cf_close(capture_opts->cf);
323   }
324   return TRUE;
325 }
326
327
328 /* capture child tells us we have a new (or the first) capture file */
329 gboolean
330 capture_input_new_file(capture_options *capture_opts, gchar *new_file)
331 {
332   gboolean is_tempfile;
333   int  err;
334
335   if(capture_opts->state == CAPTURE_PREPARING) {
336     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture started!");
337   }
338   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "File: \"%s\"", new_file);
339
340   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
341
342   /* free the old filename */
343   if(capture_opts->save_file != NULL) {
344     /* we start a new capture file, close the old one (if we had one before). */
345     /* (we can only have an open capture file in real_time_mode!) */
346     if( ((capture_file *) capture_opts->cf)->state != FILE_CLOSED) {
347         capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
348         cf_finish_tail(capture_opts->cf, &err);
349         cf_close(capture_opts->cf);
350     }
351     g_free(capture_opts->save_file);
352     is_tempfile = FALSE;
353     cf_set_tempfile(capture_opts->cf, FALSE);
354   } else {
355     /* we didn't have a save_file before; must be a tempfile */
356     is_tempfile = TRUE;
357     cf_set_tempfile(capture_opts->cf, TRUE);
358   }
359
360   /* save the new filename */
361   capture_opts->save_file = g_strdup(new_file);
362
363   /* if we are in real-time mode, open the new file now */
364   if(capture_opts->real_time_mode) {
365     /* Attempt to open the capture file and set up to read from it. */
366     switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
367     case CF_OK:
368       break;
369     case CF_ERROR:
370       /* Don't unlink (delete) the save file - leave it around,
371          for debugging purposes. */
372       g_free(capture_opts->save_file);
373       capture_opts->save_file = NULL;
374       return FALSE;
375     }
376   }
377
378   if(capture_opts->show_info) {
379     if (!capture_info_new_file(new_file))
380       return FALSE;
381   }
382
383   if(capture_opts->real_time_mode) {
384     capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
385   } else {
386     capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
387   }
388   capture_opts->state = CAPTURE_RUNNING;
389
390   return TRUE;
391 }
392
393
394 /* capture child tells us we have new packets to read */
395 void
396 capture_input_new_packets(capture_options *capture_opts, int to_read)
397 {
398   int  err;
399
400
401   g_assert(capture_opts->save_file);
402
403   if(capture_opts->real_time_mode) {
404     /* Read from the capture file the number of records the child told us it added. */
405     switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
406
407     case CF_READ_OK:
408     case CF_READ_ERROR:
409       /* Just because we got an error, that doesn't mean we were unable
410          to read any of the file; we handle what we could get from the
411          file.
412
413          XXX - abort on a read error? */
414          capture_callback_invoke(capture_cb_capture_update_continue, capture_opts);
415       break;
416
417     case CF_READ_ABORTED:
418       /* Kill the child capture process; the user wants to exit, and we
419          shouldn't just leave it running. */
420       capture_kill_child(capture_opts);
421       break;
422     }
423   } else {
424     /* increase the capture file packet counter by the number of incoming packets */
425     cf_set_packet_count(capture_opts->cf,
426         cf_get_packet_count(capture_opts->cf) + to_read);
427     cf_fake_continue_tail(capture_opts->cf);
428
429     capture_callback_invoke(capture_cb_capture_fixed_continue, capture_opts);
430   }
431
432   /* update the main window so we get events (e.g. from the stop toolbar button) */
433   main_window_update();
434
435   if(capture_opts->show_info)
436     capture_info_new_packets(to_read);
437 }
438
439
440 /* Capture child told us how many dropped packets it counted.
441  */
442 void
443 capture_input_drops(capture_options *capture_opts, guint32 dropped)
444 {
445   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%u packet%s dropped", dropped, plurality(dropped, "", "s"));
446
447   g_assert(capture_opts->state == CAPTURE_RUNNING);
448
449   cf_set_drops_known(capture_opts->cf, TRUE);
450   cf_set_drops(capture_opts->cf, dropped);
451 }
452
453
454 /* Capture child told us that an error has occurred while starting/running
455    the capture.
456    The buffer we're handed has *two* null-terminated strings in it - a
457    primary message and a secondary message, one right after the other.
458    The secondary message might be a null string.
459  */
460 void
461 capture_input_error_message(capture_options *capture_opts, char *error_msg, char *secondary_error_msg)
462 {
463   gchar *safe_error_msg;
464   gchar *safe_secondary_error_msg;
465
466   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\", \"%s\"",
467         error_msg, secondary_error_msg);
468
469   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
470
471   safe_error_msg = simple_dialog_format_message(error_msg);
472   if (*secondary_error_msg != '\0') {
473     /* We have both primary and secondary messages. */
474     safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
475     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s\n\n%s",
476                   simple_dialog_primary_start(), safe_error_msg,
477                   simple_dialog_primary_end(), safe_secondary_error_msg);
478     g_free(safe_secondary_error_msg);
479   } else {
480     /* We have only a primary message. */
481     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s",
482                   simple_dialog_primary_start(), safe_error_msg,
483                   simple_dialog_primary_end());
484   }
485   g_free(safe_error_msg);
486
487   /* the capture child will close the sync_pipe if required, nothing to do for now */
488 }
489
490
491
492 /* Capture child told us that an error has occurred while parsing a
493    capture filter when starting/running the capture.
494  */
495 void
496 capture_input_cfilter_error_message(capture_options *capture_opts, char *error_message)
497 {
498   dfilter_t   *rfcode = NULL;
499   gchar *safe_cfilter = simple_dialog_format_message(capture_opts->cfilter);
500   gchar *safe_cfilter_error_msg = simple_dialog_format_message(error_message);
501
502   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
503
504   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
505
506   /* Did the user try a display filter? */
507   if (dfilter_compile(capture_opts->cfilter, &rfcode) && rfcode != NULL) {
508     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
509       "%sInvalid capture filter: \"%s\"!%s\n"
510       "\n"
511       "That string looks like a valid display filter; however, it isn't a valid\n"
512       "capture filter (%s).\n"
513       "\n"
514       "Note that display filters and capture filters don't have the same syntax,\n"
515       "so you can't use most display filter expressions as capture filters.\n"
516       "\n"
517       "See the User's Guide for a description of the capture filter syntax.",
518       simple_dialog_primary_start(), safe_cfilter,
519       simple_dialog_primary_end(), safe_cfilter_error_msg);
520       dfilter_free(rfcode);
521   } else {
522     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
523       "%sInvalid capture filter: \"%s\"!%s\n"
524       "\n"
525       "That string isn't a valid capture filter (%s).\n"
526       "See the User's Guide for a description of the capture filter syntax.",
527       simple_dialog_primary_start(), safe_cfilter,
528       simple_dialog_primary_end(), safe_cfilter_error_msg);
529   }
530   g_free(safe_cfilter_error_msg);
531   g_free(safe_cfilter);
532
533   /* the capture child will close the sync_pipe if required, nothing to do for now */
534 }
535
536
537 /* capture child closed its side of the pipe, do the required cleanup */
538 void
539 capture_input_closed(capture_options *capture_opts, gchar *msg)
540 {
541     int  err;
542     int  packet_count_save;
543
544     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
545     g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
546
547     if (msg != NULL)
548         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg);
549
550     /* if we didn't start the capture, do a fake start. */
551     /* (happens if we got an error message - we won't get a filename then). */
552     if(capture_opts->state == CAPTURE_PREPARING) {
553         if(capture_opts->real_time_mode) {
554             capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
555         } else {
556             capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
557         }
558     }
559
560     if(capture_opts->real_time_mode) {
561         cf_read_status_t status;
562
563         /* Read what remains of the capture file. */
564         status = cf_finish_tail(capture_opts->cf, &err);
565
566         /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
567         packet_count_save = cf_get_packet_count(capture_opts->cf);
568         /* Tell the GUI we are not doing a capture any more.
569            Must be done after the cf_finish_tail(), so file lengths are 
570            correctly displayed */
571         capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
572
573         /* Finish the capture. */
574         switch (status) {
575
576         case CF_READ_OK:
577             if ((packet_count_save == 0) && !capture_opts->restart) {
578                 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
579 "%sNo packets captured!%s\n"
580 "\n"
581 "As no data was captured, closing the %scapture file!\n"
582 "\n"
583 "\n"
584 "Help about capturing can be found at:\n"
585 "\n"
586 "       http://wiki.wireshark.org/CaptureSetup"
587 #ifdef _WIN32
588 "\n\n"
589 "Wireless (Wi-Fi/WLAN):\n"
590 "Try to switch off promiscuous mode in the Capture Options!"
591 #endif
592 "",
593               simple_dialog_primary_start(), simple_dialog_primary_end(),
594               cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
595               cf_close(capture_opts->cf);
596             }
597             break;
598         case CF_READ_ERROR:
599           /* Just because we got an error, that doesn't mean we were unable
600              to read any of the file; we handle what we could get from the
601              file. */
602           break;
603
604         case CF_READ_ABORTED:
605           /* Exit by leaving the main loop, so that any quit functions
606              we registered get called. */
607           main_window_quit();
608           break;
609         }
610
611     } else {
612         /* first of all, we are not doing a capture any more */
613         capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts);
614
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));
619         }
620     }
621
622     if(capture_opts->show_info)
623       capture_info_close();
624
625     capture_opts->state = CAPTURE_STOPPED;
626
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);
630         return;
631     }
632
633     /* does the user wants to restart the current capture? */
634     if(capture_opts->restart) {
635         capture_opts->restart = FALSE;
636
637         ws_unlink(capture_opts->save_file);
638
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;
643         }
644
645         /* ... and start the capture again */
646         capture_start(capture_opts);
647     } else {
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;
651     }
652 }
653
654 if_stat_cache_t *
655 capture_stat_start(GList *if_list) {
656     int stat_fd, fork_child;
657     gchar *msg;
658     if_stat_cache_t *sc = NULL;
659     GList *if_entry;
660     if_info_t *if_info;
661     if_stat_cache_item_t *sc_item;
662
663     /* Fire up dumpcap. */
664     /*
665      * XXX - on systems with BPF, the number of BPF devices limits the
666      * number of devices on which you can capture simultaneously.
667      *
668      * This means that
669      *
670      *    1) this might fail if you run out of BPF devices
671      *
672      * and
673      *
674      *    2) opening every interface could leave too few BPF devices
675      *       for *other* programs.
676      *
677      * It also means the system could end up getting a lot of traffic
678      * that it has to pass through the networking stack and capture
679      * mechanism, so opening all the devices and presenting packet
680      * counts might not always be a good idea.
681      */
682      if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
683         sc = g_malloc(sizeof(if_stat_cache_t));
684         sc->stat_fd = stat_fd;
685         sc->fork_child = fork_child;
686         sc->cache_list = NULL;
687
688         /* Initialize the cache */
689         for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
690             if_info = if_entry->data;
691             sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
692             sc_item->name = g_strdup(if_info->name);
693             sc->cache_list = g_list_append(sc->cache_list, sc_item);
694         }
695     }
696     return sc;
697 }
698
699 #define MAX_STAT_LINE_LEN 500
700
701 static void
702 capture_stat_cache_update(if_stat_cache_t *sc) {
703     gchar stat_line[MAX_STAT_LINE_LEN];
704     gchar **stat_parts;
705     GList *sc_entry;
706     if_stat_cache_item_t *sc_item;
707
708     if (!sc)
709         return;
710
711     while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
712         g_strstrip(stat_line);
713         stat_parts = g_strsplit(stat_line, "\t", 3);
714         if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
715             stat_parts[2] == NULL) {
716             g_strfreev(stat_parts);
717             continue;
718         }
719         for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
720             sc_item = sc_entry->data;
721             if (strcmp(sc_item->name, stat_parts[0]) == 0) {
722                 sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
723                 sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
724             }
725         }
726         g_strfreev(stat_parts);
727     }
728 }
729
730 gboolean
731 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
732     GList *sc_entry;
733     if_stat_cache_item_t *sc_item;
734
735     if (!sc || !ifname || !ps) {
736         return FALSE;
737     }
738
739     capture_stat_cache_update(sc);
740     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
741         sc_item = sc_entry->data;
742         if (strcmp(sc_item->name, ifname) == 0) {
743             memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
744             return TRUE;
745         }
746     }
747     return FALSE;
748 }
749
750 void
751 capture_stat_stop(if_stat_cache_t *sc) {
752     GList *sc_entry;
753     if_stat_cache_item_t *sc_item;
754     int ret;
755     gchar *msg;
756
757     if (!sc)
758         return;
759
760     ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
761     if (ret == -1) {
762         /* XXX - report failure? */
763         g_free(msg);
764     }
765
766     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
767         sc_item = sc_entry->data;
768         g_free(sc_item->name);
769         g_free(sc_item);
770     }
771     g_free(sc);
772 }
773
774 #endif /* HAVE_LIBPCAP */