Extend a comment.
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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         if(capture_opts->real_time_mode) {
342             capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
343             cf_finish_tail(capture_opts->cf, &err);
344             cf_close(capture_opts->cf);
345         } else {
346             capture_callback_invoke(capture_cb_capture_fixed_finished, capture_opts);
347         }
348     }
349     g_free(capture_opts->save_file);
350     is_tempfile = FALSE;
351     cf_set_tempfile(capture_opts->cf, FALSE);
352   } else {
353     /* we didn't have a save_file before; must be a tempfile */
354     is_tempfile = TRUE;
355     cf_set_tempfile(capture_opts->cf, TRUE);
356   }
357
358   /* save the new filename */
359   capture_opts->save_file = g_strdup(new_file);
360
361   /* if we are in real-time mode, open the new file now */
362   if(capture_opts->real_time_mode) {
363     /* Attempt to open the capture file and set up to read from it. */
364     switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
365     case CF_OK:
366       break;
367     case CF_ERROR:
368       /* Don't unlink (delete) the save file - leave it around,
369          for debugging purposes. */
370       g_free(capture_opts->save_file);
371       capture_opts->save_file = NULL;
372       return FALSE;
373     }
374   } else {
375     capture_callback_invoke(capture_cb_capture_prepared, capture_opts);
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   /* This causes a hang on Windows (see bug 7305). Do we need this on any platform? */
434 #ifndef _WIN32
435   main_window_update();
436 #endif
437
438   if(capture_opts->show_info)
439     capture_info_new_packets(to_read);
440 }
441
442
443 /* Capture child told us how many dropped packets it counted.
444  */
445 void
446 capture_input_drops(capture_options *capture_opts, guint32 dropped)
447 {
448   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%u packet%s dropped", dropped, plurality(dropped, "", "s"));
449
450   g_assert(capture_opts->state == CAPTURE_RUNNING);
451
452   cf_set_drops_known(capture_opts->cf, TRUE);
453   cf_set_drops(capture_opts->cf, dropped);
454 }
455
456
457 /* Capture child told us that an error has occurred while starting/running
458    the capture.
459    The buffer we're handed has *two* null-terminated strings in it - a
460    primary message and a secondary message, one right after the other.
461    The secondary message might be a null string.
462  */
463 void
464 capture_input_error_message(capture_options *capture_opts, char *error_msg, char *secondary_error_msg)
465 {
466   gchar *safe_error_msg;
467   gchar *safe_secondary_error_msg;
468
469   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\", \"%s\"",
470         error_msg, secondary_error_msg);
471
472   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
473
474   safe_error_msg = simple_dialog_format_message(error_msg);
475   if (*secondary_error_msg != '\0') {
476     /* We have both primary and secondary messages. */
477     safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
478     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s\n\n%s",
479                   simple_dialog_primary_start(), safe_error_msg,
480                   simple_dialog_primary_end(), safe_secondary_error_msg);
481     g_free(safe_secondary_error_msg);
482   } else {
483     /* We have only a primary message. */
484     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s",
485                   simple_dialog_primary_start(), safe_error_msg,
486                   simple_dialog_primary_end());
487   }
488   g_free(safe_error_msg);
489
490   /* the capture child will close the sync_pipe if required, nothing to do for now */
491 }
492
493
494
495 /* Capture child told us that an error has occurred while parsing a
496    capture filter when starting/running the capture.
497  */
498 void
499 capture_input_cfilter_error_message(capture_options *capture_opts, guint i, char *error_message)
500 {
501   dfilter_t *rfcode = NULL;
502   gchar *safe_cfilter;
503   gchar *safe_descr;
504   gchar *safe_cfilter_error_msg;
505   interface_options interface_opts;
506
507   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
508
509   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
510   g_assert(i < capture_opts->ifaces->len);
511
512   interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
513   safe_cfilter = simple_dialog_format_message(interface_opts.cfilter);
514   safe_descr = simple_dialog_format_message(interface_opts.descr);
515   safe_cfilter_error_msg = simple_dialog_format_message(error_message);
516   /* Did the user try a display filter? */
517   if (dfilter_compile(interface_opts.cfilter, &rfcode) && rfcode != NULL) {
518     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
519       "%sInvalid capture filter \"%s\" for interface %s!%s\n"
520       "\n"
521       "That string looks like a valid display filter; however, it isn't a valid\n"
522       "capture filter (%s).\n"
523       "\n"
524       "Note that display filters and capture filters don't have the same syntax,\n"
525       "so you can't use most display filter expressions as capture filters.\n"
526       "\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       dfilter_free(rfcode);
531   } else {
532     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
533       "%sInvalid capture filter \"%s\" for interface %s!%s\n"
534       "\n"
535       "That string isn't a valid capture filter (%s).\n"
536       "See the User's Guide for a description of the capture filter syntax.",
537       simple_dialog_primary_start(), safe_cfilter, safe_descr,
538       simple_dialog_primary_end(), safe_cfilter_error_msg);
539   }
540   g_free(safe_cfilter_error_msg);
541   g_free(safe_descr);
542   g_free(safe_cfilter);
543
544   /* the capture child will close the sync_pipe if required, nothing to do for now */
545 }
546
547
548 /* capture child closed its side of the pipe, do the required cleanup */
549 void
550 capture_input_closed(capture_options *capture_opts, gchar *msg)
551 {
552   int  err;
553   int  packet_count_save;
554
555   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
556   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
557
558   if (msg != NULL)
559     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg);
560
561   if(capture_opts->state == CAPTURE_PREPARING) {
562     /* We didn't start a capture; note that the attempt to start it
563        failed. */
564     capture_callback_invoke(capture_cb_capture_failed, capture_opts);
565   } else {
566     /* We started a capture; process what's left of the capture file if
567        we were in "update list of packets in real time" mode, or process
568        all of it if we weren't. */
569     if(capture_opts->real_time_mode) {
570       cf_read_status_t status;
571
572       /* Read what remains of the capture file. */
573       status = cf_finish_tail(capture_opts->cf, &err);
574
575       /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
576       packet_count_save = cf_get_packet_count(capture_opts->cf);
577       /* Tell the GUI we are not doing a capture any more.
578          Must be done after the cf_finish_tail(), so file lengths are
579          correctly displayed */
580       capture_callback_invoke(capture_cb_capture_update_finished, capture_opts);
581
582       /* Finish the capture. */
583       switch (status) {
584
585       case CF_READ_OK:
586         if ((packet_count_save == 0) && !capture_opts->restart) {
587           simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
588             "%sNo packets captured!%s\n"
589             "\n"
590             "As no data was captured, closing the %scapture file!\n"
591             "\n"
592             "\n"
593             "Help about capturing can be found at:\n"
594             "\n"
595             "       http://wiki.wireshark.org/CaptureSetup"
596 #ifdef _WIN32
597             "\n\n"
598             "Wireless (Wi-Fi/WLAN):\n"
599             "Try to switch off promiscuous mode in the Capture Options!"
600 #endif
601             "",
602             simple_dialog_primary_start(), simple_dialog_primary_end(),
603             cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
604           cf_close(capture_opts->cf);
605         }
606         break;
607       case CF_READ_ERROR:
608         /* Just because we got an error, that doesn't mean we were unable
609            to read any of the file; we handle what we could get from the
610            file. */
611         break;
612
613       case CF_READ_ABORTED:
614         /* Exit by leaving the main loop, so that any quit functions
615            we registered get called. */
616         main_window_quit();
617         break;
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
631   if(capture_opts->show_info)
632     capture_info_close();
633
634   capture_opts->state = CAPTURE_STOPPED;
635
636   /* if we couldn't open a capture file, there's nothing more for us to do */
637   if(capture_opts->save_file == NULL) {
638     cf_close(capture_opts->cf);
639     return;
640   }
641
642   /* does the user wants to restart the current capture? */
643   if(capture_opts->restart) {
644     capture_opts->restart = FALSE;
645
646     ws_unlink(capture_opts->save_file);
647
648     /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
649     if(cf_is_tempfile(capture_opts->cf)) {
650       g_free(capture_opts->save_file);
651       capture_opts->save_file = NULL;
652     }
653
654     /* ... and start the capture again */
655     if (capture_opts->ifaces->len == 0) {
656       collect_ifaces(capture_opts);
657     }
658
659     /* close the currently loaded capture file */
660     cf_close(capture_opts->cf);
661
662     capture_start(capture_opts);
663   } else {
664     /* We're not doing a capture any more, so we don't have a save file. */
665     g_free(capture_opts->save_file);
666     capture_opts->save_file = NULL;
667   }
668 }
669
670 if_stat_cache_t *
671 capture_stat_start(capture_options *capture_opts) {
672   int stat_fd, fork_child;
673   gchar *msg;
674   if_stat_cache_t *sc = NULL;
675   if_stat_cache_item_t *sc_item;
676   guint i;
677   interface_t device;
678
679   /* Fire up dumpcap. */
680   /*
681    * XXX - on systems with BPF, the number of BPF devices limits the
682    * number of devices on which you can capture simultaneously.
683    *
684    * This means that
685    *
686    *    1) this might fail if you run out of BPF devices
687    *
688    * and
689    *
690    *    2) opening every interface could leave too few BPF devices
691    *       for *other* programs.
692    *
693    * It also means the system could end up getting a lot of traffic
694    * that it has to pass through the networking stack and capture
695    * mechanism, so opening all the devices and presenting packet
696    * counts might not always be a good idea.
697    */
698   if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
699     sc = g_malloc(sizeof(if_stat_cache_t));
700     sc->stat_fd = stat_fd;
701     sc->fork_child = fork_child;
702     sc->cache_list = NULL;
703
704     /* Initialize the cache */
705     for (i = 0; i < capture_opts->all_ifaces->len; i++) {
706       device = g_array_index(capture_opts->all_ifaces, interface_t, i);
707       if (device.type != IF_PIPE && &(device.if_info)) {
708         sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
709         sc_item->name = g_strdup(device.if_info.name);
710         sc->cache_list = g_list_append(sc->cache_list, sc_item);
711       }
712     }
713   }
714   return sc;
715 }
716
717 #define MAX_STAT_LINE_LEN 500
718
719 static void
720 capture_stat_cache_update(if_stat_cache_t *sc) {
721   gchar stat_line[MAX_STAT_LINE_LEN] = "";
722   gchar **stat_parts;
723   GList *sc_entry;
724   if_stat_cache_item_t *sc_item;
725
726   if (!sc)
727     return;
728
729   while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
730     g_strstrip(stat_line);
731     stat_parts = g_strsplit(stat_line, "\t", 3);
732     if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
733       stat_parts[2] == NULL) {
734       g_strfreev(stat_parts);
735       continue;
736     }
737     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
738       sc_item = sc_entry->data;
739       if (strcmp(sc_item->name, stat_parts[0]) == 0) {
740         sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
741         sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
742       }
743     }
744   g_strfreev(stat_parts);
745   }
746 }
747
748 gboolean
749 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
750   GList *sc_entry;
751   if_stat_cache_item_t *sc_item;
752
753   if (!sc || !ifname || !ps) {
754     return FALSE;
755   }
756
757   capture_stat_cache_update(sc);
758   for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
759     sc_item = sc_entry->data;
760     if (strcmp(sc_item->name, ifname) == 0) {
761       memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
762       return TRUE;
763     }
764   }
765   return FALSE;
766 }
767
768 void
769 capture_stat_stop(if_stat_cache_t *sc) {
770   GList *sc_entry;
771   if_stat_cache_item_t *sc_item;
772   int ret;
773   gchar *msg;
774
775   if (!sc)
776     return;
777
778   ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
779   if (ret == -1) {
780     /* XXX - report failure? */
781     g_free(msg);
782   }
783
784   for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
785     sc_item = sc_entry->data;
786     g_free(sc_item->name);
787     g_free(sc_item);
788   }
789   g_free(sc);
790 }
791
792 #endif /* HAVE_LIBPCAP */