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