Remove DISSECTOR_ASSERT since private_data isn't being used anymore to transport...
[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_session *cap_session)
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, cap_session, 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, capture_session *cap_session, void(*update_cb)(void))
134 {
135   gboolean ret;
136   guint i;
137   GString *source = g_string_new("");
138
139   cap_session->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 *)cap_session->cf, source->str);
169   g_string_free(source, TRUE);
170   /* try to start the capture child process */
171   ret = sync_pipe_start(capture_opts, cap_session, update_cb);
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       cap_session->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, cap_session);
187
188       if(capture_opts->show_info)
189         capture_info_open(cap_session);
190   }
191
192   return ret;
193 }
194
195
196 void
197 capture_stop(capture_session *cap_session)
198 {
199   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Stop ...");
200
201   capture_callback_invoke(capture_cb_capture_stopping, cap_session);
202
203   /* stop the capture child gracefully */
204   sync_pipe_stop(cap_session);
205 }
206
207
208 void
209 capture_restart(capture_session *cap_session)
210 {
211     capture_options *capture_opts = cap_session->capture_opts;
212
213     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Restart");
214
215     capture_opts->restart = TRUE;
216     capture_stop(cap_session);
217 }
218
219
220 void
221 capture_kill_child(capture_session *cap_session)
222 {
223   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "Capture Kill");
224
225   /* kill the capture child */
226   sync_pipe_kill(cap_session->fork_child);
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_session *cap_session, gboolean is_tempfile,
232                        gboolean drops_known, guint32 drops)
233 {
234   capture_options *capture_opts = cap_session->capture_opts;
235   int err;
236
237   /* Capture succeeded; attempt to open the capture file. */
238   if (cf_open((capture_file *)cap_session->cf, capture_opts->save_file, is_tempfile, &err) != CF_OK) {
239     /* We're not doing a capture any more, so we don't have a save file. */
240     return FALSE;
241   }
242
243   /* Set the read filter to NULL. */
244   /* XXX - this is odd here; try to put it somewhere where it fits better */
245   cf_set_rfcode((capture_file *)cap_session->cf, NULL);
246
247   /* Get the packet-drop statistics.
248
249      XXX - there are currently no packet-drop statistics stored
250      in libpcap captures, and that's what we're reading.
251
252      At some point, we will add support in Wiretap to return
253      packet-drop statistics for capture file formats that store it,
254      and will make "cf_read()" get those statistics from Wiretap.
255      We clear the statistics (marking them as "not known") in
256      "cf_open()", and "cf_read()" will only fetch them and mark
257      them as known if Wiretap supplies them, so if we get the
258      statistics now, after calling "cf_open()" but before calling
259      "cf_read()", the values we store will be used by "cf_read()".
260
261      If a future libpcap capture file format stores the statistics,
262      we'll put them into the capture file that we write, and will
263      thus not have to set them here - "cf_read()" will get them from
264      the file and use them. */
265   if (drops_known) {
266     cf_set_drops_known((capture_file *)cap_session->cf, TRUE);
267
268     /* XXX - on some systems, libpcap doesn't bother filling in
269        "ps_ifdrop" - it doesn't even set it to zero - so we don't
270        bother looking at it.
271
272        Ideally, libpcap would have an interface that gave us
273        several statistics - perhaps including various interface
274        error statistics - and would tell us which of them it
275        supplies, allowing us to display only the ones it does. */
276     cf_set_drops((capture_file *)cap_session->cf, drops);
277   }
278
279   /* read in the packet data */
280   switch (cf_read((capture_file *)cap_session->cf, FALSE)) {
281
282   case CF_READ_OK:
283   case CF_READ_ERROR:
284     /* Just because we got an error, that doesn't mean we were unable
285        to read any of the file; we handle what we could get from the
286        file. */
287     break;
288
289   case CF_READ_ABORTED:
290     /* User wants to quit program. Exit by leaving the main loop,
291        so that any quit functions we registered get called. */
292     main_window_nested_quit();
293     return FALSE;
294   }
295
296   /* if we didn't capture even a single packet, close the file again */
297   if(cf_get_packet_count((capture_file *)cap_session->cf) == 0 && !capture_opts->restart) {
298     simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
299 "%sNo packets captured!%s\n"
300 "\n"
301 "As no data was captured, closing the %scapture file!\n"
302 "\n"
303 "\n"
304 "Help about capturing can be found at:\n"
305 "\n"
306 "       http://wiki.wireshark.org/CaptureSetup"
307 #ifdef _WIN32
308 "\n\n"
309 "Wireless (Wi-Fi/WLAN):\n"
310 "Try to switch off promiscuous mode in the Capture Options!"
311 #endif
312 "",
313     simple_dialog_primary_start(), simple_dialog_primary_end(),
314     (cf_is_tempfile((capture_file *)cap_session->cf)) ? "temporary " : "");
315     cf_close((capture_file *)cap_session->cf);
316   }
317   return TRUE;
318 }
319
320
321 /* capture child tells us we have a new (or the first) capture file */
322 gboolean
323 capture_input_new_file(capture_session *cap_session, gchar *new_file)
324 {
325   capture_options *capture_opts = cap_session->capture_opts;
326   gboolean is_tempfile;
327   int  err;
328
329   if(cap_session->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(cap_session->state == CAPTURE_PREPARING || cap_session->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 *) cap_session->cf)->state != FILE_CLOSED) {
341         if(capture_opts->real_time_mode) {
342             capture_callback_invoke(capture_cb_capture_update_finished, cap_session);
343             cf_finish_tail((capture_file *)cap_session->cf, &err);
344             cf_close((capture_file *)cap_session->cf);
345         } else {
346             capture_callback_invoke(capture_cb_capture_fixed_finished, cap_session);
347         }
348     }
349     g_free(capture_opts->save_file);
350     is_tempfile = FALSE;
351     cf_set_tempfile((capture_file *)cap_session->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_file *)cap_session->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_open((capture_file *)cap_session->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, cap_session);
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, cap_session);
385   } else {
386     capture_callback_invoke(capture_cb_capture_fixed_started, cap_session);
387   }
388   cap_session->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_session *cap_session, int to_read)
397 {
398   capture_options *capture_opts = cap_session->capture_opts;
399   int  err;
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_file *)cap_session->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, cap_session);
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(cap_session);
421       break;
422     }
423   } else {
424     /* increase the capture file packet counter by the number of incoming packets */
425     cf_set_packet_count((capture_file *)cap_session->cf,
426         cf_get_packet_count((capture_file *)cap_session->cf) + to_read);
427     cf_fake_continue_tail((capture_file *)cap_session->cf);
428
429     capture_callback_invoke(capture_cb_capture_fixed_continue, cap_session);
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_session *cap_session, 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(cap_session->state == CAPTURE_RUNNING);
451
452   cf_set_drops_known((capture_file *)cap_session->cf, TRUE);
453   cf_set_drops((capture_file *)cap_session->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_session *cap_session, char *error_msg,
465                             char *secondary_error_msg)
466 {
467   gchar *safe_error_msg;
468   gchar *safe_secondary_error_msg;
469
470   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\", \"%s\"",
471         error_msg, secondary_error_msg);
472
473   g_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
474
475   safe_error_msg = simple_dialog_format_message(error_msg);
476   if (*secondary_error_msg != '\0') {
477     /* We have both primary and secondary messages. */
478     safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
479     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s\n\n%s",
480                   simple_dialog_primary_start(), safe_error_msg,
481                   simple_dialog_primary_end(), safe_secondary_error_msg);
482     g_free(safe_secondary_error_msg);
483   } else {
484     /* We have only a primary message. */
485     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s",
486                   simple_dialog_primary_start(), safe_error_msg,
487                   simple_dialog_primary_end());
488   }
489   g_free(safe_error_msg);
490
491   /* the capture child will close the sync_pipe if required, nothing to do for now */
492 }
493
494 /* Capture child told us that an error has occurred while parsing a
495    capture filter when starting/running the capture.
496  */
497 void
498 capture_input_cfilter_error_message(capture_session *cap_session, guint i,
499                                     char *error_message)
500 {
501   capture_options *capture_opts = cap_session->capture_opts;
502   dfilter_t *rfcode = NULL;
503   gchar *safe_cfilter;
504   gchar *safe_descr;
505   gchar *safe_cfilter_error_msg;
506   interface_options interface_opts;
507
508   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
509
510   g_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
511   g_assert(i < capture_opts->ifaces->len);
512
513   interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
514   safe_cfilter = simple_dialog_format_message(interface_opts.cfilter);
515   safe_descr = simple_dialog_format_message(interface_opts.descr);
516   safe_cfilter_error_msg = simple_dialog_format_message(error_message);
517   /* Did the user try a display filter? */
518   if (dfilter_compile(interface_opts.cfilter, &rfcode) && rfcode != NULL) {
519     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
520       "%sInvalid capture filter \"%s\" for interface %s!%s\n"
521       "\n"
522       "That string looks like a valid display filter; however, it isn't a valid\n"
523       "capture filter (%s).\n"
524       "\n"
525       "Note that display filters and capture filters don't have the same syntax,\n"
526       "so you can't use most display filter expressions as capture filters.\n"
527       "\n"
528       "See the User's Guide for a description of the capture filter syntax.",
529       simple_dialog_primary_start(), safe_cfilter, safe_descr,
530       simple_dialog_primary_end(), safe_cfilter_error_msg);
531       dfilter_free(rfcode);
532   } else {
533     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
534       "%sInvalid capture filter \"%s\" for interface %s!%s\n"
535       "\n"
536       "That string isn't a valid capture filter (%s).\n"
537       "See the User's Guide for a description of the capture filter syntax.",
538       simple_dialog_primary_start(), safe_cfilter, safe_descr,
539       simple_dialog_primary_end(), safe_cfilter_error_msg);
540   }
541   g_free(safe_cfilter_error_msg);
542   g_free(safe_descr);
543   g_free(safe_cfilter);
544
545   /* the capture child will close the sync_pipe if required, nothing to do for now */
546 }
547
548 /* capture child closed its side of the pipe, do the required cleanup */
549 void
550 capture_input_closed(capture_session *cap_session, gchar *msg)
551 {
552   capture_options *capture_opts = cap_session->capture_opts;
553   int  err;
554   int  packet_count_save;
555
556   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
557   g_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
558
559   if (msg != NULL)
560     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg);
561
562   if(cap_session->state == CAPTURE_PREPARING) {
563     /* We didn't start a capture; note that the attempt to start it
564        failed. */
565     capture_callback_invoke(capture_cb_capture_failed, cap_session);
566   } else {
567     /* We started a capture; process what's left of the capture file if
568        we were in "update list of packets in real time" mode, or process
569        all of it if we weren't. */
570     if(capture_opts->real_time_mode) {
571       cf_read_status_t status;
572
573       /* Read what remains of the capture file. */
574       status = cf_finish_tail((capture_file *)cap_session->cf, &err);
575
576       /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
577       packet_count_save = cf_get_packet_count((capture_file *)cap_session->cf);
578       /* Tell the GUI we are not doing a capture any more.
579          Must be done after the cf_finish_tail(), so file lengths are
580          correctly displayed */
581       capture_callback_invoke(capture_cb_capture_update_finished, cap_session);
582
583       /* Finish the capture. */
584       switch (status) {
585
586       case CF_READ_OK:
587         if ((packet_count_save == 0) && !capture_opts->restart) {
588           simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
589             "%sNo packets captured!%s\n"
590             "\n"
591             "As no data was captured, closing the %scapture file!\n"
592             "\n"
593             "\n"
594             "Help about capturing can be found at:\n"
595             "\n"
596             "       http://wiki.wireshark.org/CaptureSetup"
597 #ifdef _WIN32
598             "\n\n"
599             "Wireless (Wi-Fi/WLAN):\n"
600             "Try to switch off promiscuous mode in the Capture Options!"
601 #endif
602             "",
603             simple_dialog_primary_start(), simple_dialog_primary_end(),
604             cf_is_tempfile((capture_file *)cap_session->cf) ? "temporary " : "");
605           cf_close((capture_file *)cap_session->cf);
606         }
607         break;
608       case CF_READ_ERROR:
609         /* Just because we got an error, that doesn't mean we were unable
610            to read any of the file; we handle what we could get from the
611            file. */
612         break;
613
614       case CF_READ_ABORTED:
615         /* Exit by leaving the main loop, so that any quit functions
616            we registered get called. */
617         main_window_quit();
618         break;
619       }
620     } else {
621       /* first of all, we are not doing a capture any more */
622       capture_callback_invoke(capture_cb_capture_fixed_finished, cap_session);
623
624       /* this is a normal mode capture and if no error happened, read in the capture file data */
625       if(capture_opts->save_file != NULL) {
626         capture_input_read_all(cap_session, cf_is_tempfile((capture_file *)cap_session->cf),
627           cf_get_drops_known((capture_file *)cap_session->cf), cf_get_drops((capture_file *)cap_session->cf));
628       }
629     }
630   }
631
632   if(capture_opts->show_info)
633     capture_info_close();
634
635   cap_session->state = CAPTURE_STOPPED;
636
637   /* if we couldn't open a capture file, there's nothing more for us to do */
638   if(capture_opts->save_file == NULL) {
639     cf_close((capture_file *)cap_session->cf);
640     return;
641   }
642
643   /* does the user wants to restart the current capture? */
644   if(capture_opts->restart) {
645     capture_opts->restart = FALSE;
646
647     ws_unlink(capture_opts->save_file);
648
649     /* If we have a ring buffer, the original save file has been overwritten
650        with the "ring filename".  Restore it before starting again */
651     if ((capture_opts->multi_files_on) && (capture_opts->orig_save_file != NULL)) {
652       g_free(capture_opts->save_file);
653       capture_opts->save_file = g_strdup(capture_opts->orig_save_file);
654     }
655
656     /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
657     if(cf_is_tempfile((capture_file *)cap_session->cf)) {
658       g_free(capture_opts->save_file);
659       capture_opts->save_file = NULL;
660     }
661
662     /* ... and start the capture again */
663     if (capture_opts->ifaces->len == 0) {
664       collect_ifaces(capture_opts);
665     }
666
667     /* close the currently loaded capture file */
668     cf_close((capture_file *)cap_session->cf);
669
670     capture_start(capture_opts, cap_session,NULL); /*XXX is this NULL ok or we need an update_cb???*/
671   } else {
672     /* We're not doing a capture any more, so we don't have a save file. */
673     g_free(capture_opts->save_file);
674     capture_opts->save_file = NULL;
675   }
676 }
677
678 if_stat_cache_t *
679 capture_stat_start(capture_options *capture_opts) {
680   int stat_fd, fork_child;
681   gchar *msg;
682   if_stat_cache_t *sc = NULL;
683   if_stat_cache_item_t *sc_item;
684   guint i;
685   interface_t device;
686
687   /* Fire up dumpcap. */
688   /*
689    * XXX - on systems with BPF, the number of BPF devices limits the
690    * number of devices on which you can capture simultaneously.
691    *
692    * This means that
693    *
694    *    1) this might fail if you run out of BPF devices
695    *
696    * and
697    *
698    *    2) opening every interface could leave too few BPF devices
699    *       for *other* programs.
700    *
701    * It also means the system could end up getting a lot of traffic
702    * that it has to pass through the networking stack and capture
703    * mechanism, so opening all the devices and presenting packet
704    * counts might not always be a good idea.
705    */
706   if (sync_interface_stats_open(&stat_fd, &fork_child, &msg, NULL) == 0) {
707     sc = (if_stat_cache_t *)g_malloc(sizeof(if_stat_cache_t));
708     sc->stat_fd = stat_fd;
709     sc->fork_child = fork_child;
710     sc->cache_list = NULL;
711
712     /* Initialize the cache */
713     for (i = 0; i < capture_opts->all_ifaces->len; i++) {
714       device = g_array_index(capture_opts->all_ifaces, interface_t, i);
715       if (device.type != IF_PIPE && &(device.if_info)) {
716         sc_item = (if_stat_cache_item_t *)g_malloc0(sizeof(if_stat_cache_item_t));
717         sc_item->name = g_strdup(device.if_info.name);
718         sc->cache_list = g_list_append(sc->cache_list, sc_item);
719       }
720     }
721   }
722   return sc;
723 }
724
725 #define MAX_STAT_LINE_LEN 500
726
727 static void
728 capture_stat_cache_update(if_stat_cache_t *sc) {
729   gchar stat_line[MAX_STAT_LINE_LEN] = "";
730   gchar **stat_parts;
731   GList *sc_entry;
732   if_stat_cache_item_t *sc_item;
733
734   if (!sc)
735     return;
736
737   while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
738     g_strstrip(stat_line);
739     stat_parts = g_strsplit(stat_line, "\t", 3);
740     if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
741       stat_parts[2] == NULL) {
742       g_strfreev(stat_parts);
743       continue;
744     }
745     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
746       sc_item = (if_stat_cache_item_t *)sc_entry->data;
747       if (strcmp(sc_item->name, stat_parts[0]) == 0) {
748         sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
749         sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
750       }
751     }
752   g_strfreev(stat_parts);
753   }
754 }
755
756 gboolean
757 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
758   GList *sc_entry;
759   if_stat_cache_item_t *sc_item;
760
761   if (!sc || !ifname || !ps) {
762     return FALSE;
763   }
764
765   capture_stat_cache_update(sc);
766   for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
767     sc_item = (if_stat_cache_item_t *)sc_entry->data;
768     if (strcmp(sc_item->name, ifname) == 0) {
769       memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
770       return TRUE;
771     }
772   }
773   return FALSE;
774 }
775
776 void
777 capture_stat_stop(if_stat_cache_t *sc) {
778   GList *sc_entry;
779   if_stat_cache_item_t *sc_item;
780   int ret;
781   gchar *msg;
782
783   if (!sc)
784     return;
785
786   ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
787   if (ret == -1) {
788     /* XXX - report failure? */
789     g_free(msg);
790   }
791
792   for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
793     sc_item = (if_stat_cache_item_t *)sc_entry->data;
794     g_free(sc_item->name);
795     g_free(sc_item);
796   }
797   g_free(sc);
798 }
799
800 #endif /* HAVE_LIBPCAP */