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