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