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