From Ryan Hoffman via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6122
[obnox/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, guint i, char *error_message)
497 {
498   dfilter_t *rfcode = NULL;
499   gchar *safe_cfilter;
500   gchar *safe_descr;
501   gchar *safe_cfilter_error_msg;
502   interface_options interface_opts;
503
504   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
505
506   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
507   g_assert(i < capture_opts->ifaces->len);
508
509   interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
510   safe_cfilter = simple_dialog_format_message(interface_opts.cfilter);
511   safe_descr = simple_dialog_format_message(interface_opts.descr);
512   safe_cfilter_error_msg = simple_dialog_format_message(error_message);
513   /* Did the user try a display filter? */
514   if (dfilter_compile(interface_opts.cfilter, &rfcode) && rfcode != NULL) {
515     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
516       "%sInvalid capture filter \"%s\" for interface %s!%s\n"
517       "\n"
518       "That string looks like a valid display filter; however, it isn't a valid\n"
519       "capture filter (%s).\n"
520       "\n"
521       "Note that display filters and capture filters don't have the same syntax,\n"
522       "so you can't use most display filter expressions as capture filters.\n"
523       "\n"
524       "See the User's Guide for a description of the capture filter syntax.",
525       simple_dialog_primary_start(), safe_cfilter, safe_descr,
526       simple_dialog_primary_end(), safe_cfilter_error_msg);
527       dfilter_free(rfcode);
528   } else {
529     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
530       "%sInvalid capture filter \"%s\" for interface %s!%s\n"
531       "\n"
532       "That string isn't a valid capture filter (%s).\n"
533       "See the User's Guide for a description of the capture filter syntax.",
534       simple_dialog_primary_start(), safe_cfilter, safe_descr,
535       simple_dialog_primary_end(), safe_cfilter_error_msg);
536   }
537   g_free(safe_cfilter_error_msg);
538   g_free(safe_descr);
539   g_free(safe_cfilter);
540
541   /* the capture child will close the sync_pipe if required, nothing to do for now */
542 }
543
544
545 /* capture child closed its side of the pipe, do the required cleanup */
546 void
547 capture_input_closed(capture_options *capture_opts, gchar *msg)
548 {
549     int  err;
550     int  packet_count_save;
551
552     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
553     g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
554
555     if (msg != NULL)
556         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg);
557
558     /* if we didn't start the capture, do a fake start. */
559     /* (happens if we got an error message - we won't get a filename then). */
560     if(capture_opts->state == CAPTURE_PREPARING) {
561         if(capture_opts->real_time_mode) {
562             capture_callback_invoke(capture_cb_capture_update_started, capture_opts);
563         } else {
564             capture_callback_invoke(capture_cb_capture_fixed_started, capture_opts);
565         }
566     }
567
568     if(capture_opts->real_time_mode) {
569         cf_read_status_t status;
570
571         /* Read what remains of the capture file. */
572         status = cf_finish_tail(capture_opts->cf, &err);
573
574         /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
575         packet_count_save = cf_get_packet_count(capture_opts->cf);
576         /* Tell the GUI we are not doing a capture any more.
577            Must be done after the cf_finish_tail(), so file lengths are 
578            correctly displayed */
579         capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
580
581         /* Finish the capture. */
582         switch (status) {
583
584         case CF_READ_OK:
585             if ((packet_count_save == 0) && !capture_opts->restart) {
586                 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
587 "%sNo packets captured!%s\n"
588 "\n"
589 "As no data was captured, closing the %scapture file!\n"
590 "\n"
591 "\n"
592 "Help about capturing can be found at:\n"
593 "\n"
594 "       http://wiki.wireshark.org/CaptureSetup"
595 #ifdef _WIN32
596 "\n\n"
597 "Wireless (Wi-Fi/WLAN):\n"
598 "Try to switch off promiscuous mode in the Capture Options!"
599 #endif
600 "",
601               simple_dialog_primary_start(), simple_dialog_primary_end(),
602               cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
603               cf_close(capture_opts->cf);
604             }
605             break;
606         case CF_READ_ERROR:
607           /* Just because we got an error, that doesn't mean we were unable
608              to read any of the file; we handle what we could get from the
609              file. */
610           break;
611
612         case CF_READ_ABORTED:
613           /* Exit by leaving the main loop, so that any quit functions
614              we registered get called. */
615           main_window_quit();
616           break;
617         }
618
619     } else {
620         /* first of all, we are not doing a capture any more */
621         capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts);
622
623         /* this is a normal mode capture and if no error happened, read in the capture file data */
624         if(capture_opts->save_file != NULL) {
625             capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
626                 cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
627         }
628     }
629
630     if(capture_opts->show_info)
631       capture_info_close();
632
633     capture_opts->state = CAPTURE_STOPPED;
634
635     /* if we couldn't open a capture file, there's nothing more for us to do */
636     if(capture_opts->save_file == NULL) {
637         cf_close(capture_opts->cf);
638         return;
639     }
640
641     /* does the user wants to restart the current capture? */
642     if(capture_opts->restart) {
643         capture_opts->restart = FALSE;
644
645         ws_unlink(capture_opts->save_file);
646
647         /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
648         if(cf_is_tempfile(capture_opts->cf)) {
649             g_free(capture_opts->save_file);
650             capture_opts->save_file = NULL;
651         }
652
653         /* ... and start the capture again */
654         capture_start(capture_opts);
655     } else {
656         /* We're not doing a capture any more, so we don't have a save file. */
657         g_free(capture_opts->save_file);
658         capture_opts->save_file = NULL;
659     }
660 }
661
662 if_stat_cache_t *
663 capture_stat_start(GList *if_list) {
664     int stat_fd, fork_child;
665     gchar *msg;
666     if_stat_cache_t *sc = NULL;
667     GList *if_entry;
668     if_info_t *if_info;
669     if_stat_cache_item_t *sc_item;
670
671     /* Fire up dumpcap. */
672     /*
673      * XXX - on systems with BPF, the number of BPF devices limits the
674      * number of devices on which you can capture simultaneously.
675      *
676      * This means that
677      *
678      *    1) this might fail if you run out of BPF devices
679      *
680      * and
681      *
682      *    2) opening every interface could leave too few BPF devices
683      *       for *other* programs.
684      *
685      * It also means the system could end up getting a lot of traffic
686      * that it has to pass through the networking stack and capture
687      * mechanism, so opening all the devices and presenting packet
688      * counts might not always be a good idea.
689      */
690      if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
691         sc = g_malloc(sizeof(if_stat_cache_t));
692         sc->stat_fd = stat_fd;
693         sc->fork_child = fork_child;
694         sc->cache_list = NULL;
695
696         /* Initialize the cache */
697         for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
698             if_info = if_entry->data;
699             if (if_info) {
700                 sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
701                 sc_item->name = g_strdup(if_info->name);
702                 sc->cache_list = g_list_append(sc->cache_list, sc_item);
703             }
704         }
705     }
706     return sc;
707 }
708
709 #define MAX_STAT_LINE_LEN 500
710
711 static void
712 capture_stat_cache_update(if_stat_cache_t *sc) {
713     gchar stat_line[MAX_STAT_LINE_LEN];
714     gchar **stat_parts;
715     GList *sc_entry;
716     if_stat_cache_item_t *sc_item;
717
718     if (!sc)
719         return;
720
721     while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
722         g_strstrip(stat_line);
723         stat_parts = g_strsplit(stat_line, "\t", 3);
724         if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
725             stat_parts[2] == NULL) {
726             g_strfreev(stat_parts);
727             continue;
728         }
729         for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
730             sc_item = sc_entry->data;
731             if (strcmp(sc_item->name, stat_parts[0]) == 0) {
732                 sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
733                 sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
734             }
735         }
736         g_strfreev(stat_parts);
737     }
738 }
739
740 gboolean
741 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
742     GList *sc_entry;
743     if_stat_cache_item_t *sc_item;
744
745     if (!sc || !ifname || !ps) {
746         return FALSE;
747     }
748
749     capture_stat_cache_update(sc);
750     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
751         sc_item = sc_entry->data;
752         if (strcmp(sc_item->name, ifname) == 0) {
753             memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
754             return TRUE;
755         }
756     }
757     return FALSE;
758 }
759
760 void
761 capture_stat_stop(if_stat_cache_t *sc) {
762     GList *sc_entry;
763     if_stat_cache_item_t *sc_item;
764     int ret;
765     gchar *msg;
766
767     if (!sc)
768         return;
769
770     ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
771     if (ret == -1) {
772         /* XXX - report failure? */
773         g_free(msg);
774     }
775
776     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
777         sc_item = sc_entry->data;
778         g_free(sc_item->name);
779         g_free(sc_item);
780     }
781     g_free(sc);
782 }
783
784 #endif /* HAVE_LIBPCAP */