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