Fix a typo.
[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 "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   if (capture_opts->state != CAPTURE_STOPPED)
142     return FALSE;
143   capture_opts->state = CAPTURE_PREPARING;
144
145   /* close the currently loaded capture file */
146   cf_close(capture_opts->cf);
147   collect_ifaces(capture_opts);
148   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ...");
149 #ifdef _WIN32
150   if (capture_opts->ifaces->len < 2) {
151 #else
152   if (capture_opts->ifaces->len < 4) {
153 #endif
154     for (i = 0; i < capture_opts->ifaces->len; i++) {
155       interface_options interface_opts;
156
157       interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
158       if (i > 0) {
159           if (capture_opts->ifaces->len > 2) {
160               g_string_append_printf(source, ",");
161           }
162           g_string_append_printf(source, " ");
163           if (i == capture_opts->ifaces->len - 1) {
164               g_string_append_printf(source, "and ");
165           }
166       }
167       g_string_append_printf(source, "%s", get_iface_description_for_interface(capture_opts, i));
168       if ((interface_opts.cfilter != NULL) &&
169           (strlen(interface_opts.cfilter) > 0)) {
170         g_string_append_printf(source, " (%s)", interface_opts.cfilter);
171       }
172     }
173   } else {
174     g_string_append_printf(source, "%u interfaces", capture_opts->ifaces->len);
175   }
176   cf_set_tempfile_source(capture_opts->cf, source->str);
177   g_string_free(source, TRUE);
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     if (capture_opts->ifaces->len == 0) {
655       collect_ifaces(capture_opts);
656     }
657     capture_start(capture_opts);
658   } else {
659     /* We're not doing a capture any more, so we don't have a save file. */
660     g_free(capture_opts->save_file);
661     capture_opts->save_file = NULL;
662   }
663 }
664
665 if_stat_cache_t *
666 capture_stat_start(capture_options *capture_opts) {
667   int stat_fd, fork_child;
668   gchar *msg;
669   if_stat_cache_t *sc = NULL;
670   if_stat_cache_item_t *sc_item;
671   guint i;
672   interface_t device;
673
674   /* Fire up dumpcap. */
675   /*
676    * XXX - on systems with BPF, the number of BPF devices limits the
677    * number of devices on which you can capture simultaneously.
678    *
679    * This means that
680    *
681    *    1) this might fail if you run out of BPF devices
682    *
683    * and
684    *
685    *    2) opening every interface could leave too few BPF devices
686    *       for *other* programs.
687    *
688    * It also means the system could end up getting a lot of traffic
689    * that it has to pass through the networking stack and capture
690    * mechanism, so opening all the devices and presenting packet
691    * counts might not always be a good idea.
692    */
693   if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
694     sc = g_malloc(sizeof(if_stat_cache_t));
695     sc->stat_fd = stat_fd;
696     sc->fork_child = fork_child;
697     sc->cache_list = NULL;
698
699     /* Initialize the cache */
700     for (i = 0; i < capture_opts->all_ifaces->len; i++) {
701       device = g_array_index(capture_opts->all_ifaces, interface_t, i);
702       if (device.type != IF_PIPE && &(device.if_info)) {
703         sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
704         sc_item->name = g_strdup(device.if_info.name);
705         sc->cache_list = g_list_append(sc->cache_list, sc_item);
706       }
707     }
708   }
709   return sc;
710 }
711
712 #define MAX_STAT_LINE_LEN 500
713
714 static void
715 capture_stat_cache_update(if_stat_cache_t *sc) {
716   gchar stat_line[MAX_STAT_LINE_LEN];
717   gchar **stat_parts;
718   GList *sc_entry;
719   if_stat_cache_item_t *sc_item;
720
721   if (!sc)
722     return;
723
724   while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
725     g_strstrip(stat_line);
726     stat_parts = g_strsplit(stat_line, "\t", 3);
727     if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
728       stat_parts[2] == NULL) {
729       g_strfreev(stat_parts);
730       continue;
731     }
732     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
733       sc_item = sc_entry->data;
734       if (strcmp(sc_item->name, stat_parts[0]) == 0) {
735         sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
736         sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
737       }
738     }
739   g_strfreev(stat_parts);
740   }
741 }
742
743 gboolean
744 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
745   GList *sc_entry;
746   if_stat_cache_item_t *sc_item;
747
748   if (!sc || !ifname || !ps) {
749     return FALSE;
750   }
751
752   capture_stat_cache_update(sc);
753   for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
754     sc_item = sc_entry->data;
755     if (strcmp(sc_item->name, ifname) == 0) {
756       memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
757       return TRUE;
758     }
759   }
760   return FALSE;
761 }
762
763 void
764 capture_stat_stop(if_stat_cache_t *sc) {
765   GList *sc_entry;
766   if_stat_cache_item_t *sc_item;
767   int ret;
768   gchar *msg;
769
770   if (!sc)
771     return;
772
773   ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
774   if (ret == -1) {
775     /* XXX - report failure? */
776     g_free(msg);
777   }
778
779   for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
780     sc_item = sc_entry->data;
781     g_free(sc_item->name);
782     g_free(sc_item);
783   }
784   g_free(sc);
785 }
786
787 #endif /* HAVE_LIBPCAP */