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