Removed some more "statement not reached" warnings.
[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     }
328   }
329
330   if(capture_opts->show_info) {
331     if (!capture_info_new_file(new_file))
332       return FALSE;
333   }
334
335   if(capture_opts->real_time_mode) {
336     cf_callback_invoke(cf_cb_live_capture_update_started, capture_opts);
337   } else {
338     cf_callback_invoke(cf_cb_live_capture_fixed_started, capture_opts);
339   }
340   capture_opts->state = CAPTURE_RUNNING;
341
342   return TRUE;
343 }
344
345
346 /* capture child tells us we have new packets to read */
347 void
348 capture_input_new_packets(capture_options *capture_opts, int to_read)
349 {
350   int  err;
351
352
353   g_assert(capture_opts->save_file);
354
355   if(capture_opts->real_time_mode) {
356     /* Read from the capture file the number of records the child told us it added. */
357     switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
358
359     case CF_READ_OK:
360     case CF_READ_ERROR:
361       /* Just because we got an error, that doesn't mean we were unable
362          to read any of the file; we handle what we could get from the
363          file.
364
365          XXX - abort on a read error? */
366          cf_callback_invoke(cf_cb_live_capture_update_continue, capture_opts->cf);
367       break;
368
369     case CF_READ_ABORTED:
370       /* Kill the child capture process; the user wants to exit, and we
371          shouldn't just leave it running. */
372       capture_kill_child(capture_opts);
373       break;
374     }
375   } else {
376     /* increase capture file packet counter by the number or incoming packets */
377     cf_set_packet_count(capture_opts->cf,
378         cf_get_packet_count(capture_opts->cf) + to_read);
379
380     cf_callback_invoke(cf_cb_live_capture_fixed_continue, capture_opts->cf);
381   }
382
383   /* update the main window, so we get events (e.g. from the stop toolbar button) */
384   main_window_update();
385
386   if(capture_opts->show_info)
387     capture_info_new_packets(to_read);
388 }
389
390
391 /* Capture child told us how many dropped packets it counted.
392  */
393 void
394 capture_input_drops(capture_options *capture_opts, int dropped)
395 {
396   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", dropped, plurality(dropped, "", "s"));
397
398   g_assert(capture_opts->state == CAPTURE_RUNNING);
399
400   cf_set_drops_known(capture_opts->cf, TRUE);
401   cf_set_drops(capture_opts->cf, dropped);
402 }
403
404
405 /* Capture child told us that an error has occurred while starting/running
406    the capture.
407    The buffer we're handed has *two* null-terminated strings in it - a
408    primary message and a secondary message, one right after the other.
409    The secondary message might be a null string.
410  */
411 void
412 capture_input_error_message(capture_options *capture_opts, char *error_msg, char *secondary_error_msg)
413 {
414   gchar *safe_error_msg;
415   gchar *safe_secondary_error_msg;
416
417   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\", \"%s\"",
418         error_msg, secondary_error_msg);
419
420   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
421
422   safe_error_msg = simple_dialog_format_message(error_msg);
423   if (*secondary_error_msg != '\0') {
424     /* We have both primary and secondary messages. */
425     safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
426     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s\n\n%s",
427                   simple_dialog_primary_start(), safe_error_msg,
428                   simple_dialog_primary_end(), safe_secondary_error_msg);
429     g_free(safe_secondary_error_msg);
430   } else {
431     /* We have only a primary message. */
432     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s%s%s",
433                   simple_dialog_primary_start(), safe_error_msg,
434                   simple_dialog_primary_end());
435   }
436   g_free(safe_error_msg);
437
438   /* the capture child will close the sync_pipe if required, nothing to do for now */
439 }
440
441
442
443 /* Capture child told us that an error has occurred while parsing a
444    capture filter when starting/running the capture.
445  */
446 void
447 capture_input_cfilter_error_message(capture_options *capture_opts, char *error_message)
448 {
449   dfilter_t   *rfcode = NULL;
450   gchar *safe_cfilter = simple_dialog_format_message(capture_opts->cfilter);
451   gchar *safe_cfilter_error_msg = simple_dialog_format_message(error_message);
452
453   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture filter error message from child: \"%s\"", error_message);
454
455   g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
456
457   /* Did the user try a display filter? */
458   if (dfilter_compile(capture_opts->cfilter, &rfcode) && rfcode != NULL) {
459     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
460       "%sInvalid capture filter: \"%s\"!%s\n"
461       "\n"
462       "That string looks like a valid display filter; however, it isn't a valid\n"
463       "capture filter (%s).\n"
464       "\n"
465       "Note that display filters and capture filters don't have the same syntax,\n"
466       "so you can't use most display filter expressions as capture filters.\n"
467       "\n"
468       "See the User's Guide for a description of the capture filter syntax.",
469       simple_dialog_primary_start(), safe_cfilter,
470       simple_dialog_primary_end(), safe_cfilter_error_msg);
471       dfilter_free(rfcode);
472   } else {
473     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
474       "%sInvalid capture filter: \"%s\"!%s\n"
475       "\n"
476       "That string isn't a valid capture filter (%s).\n"
477       "See the User's Guide for a description of the capture filter syntax.",
478       simple_dialog_primary_start(), safe_cfilter,
479       simple_dialog_primary_end(), safe_cfilter_error_msg);
480   }
481   g_free(safe_cfilter_error_msg);
482   g_free(safe_cfilter);
483
484   /* the capture child will close the sync_pipe if required, nothing to do for now */
485 }
486
487
488 /* capture child closed its side of the pipe, do the required cleanup */
489 void
490 capture_input_closed(capture_options *capture_opts)
491 {
492     int  err;
493     int  packet_count_save;
494
495     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!");
496     g_assert(capture_opts->state == CAPTURE_PREPARING || capture_opts->state == CAPTURE_RUNNING);
497
498     /* if we didn't started the capture, do a fake start */
499     /* (happens if we got an error message - we won't get a filename then) */
500     if(capture_opts->state == CAPTURE_PREPARING) {
501         if(capture_opts->real_time_mode) {
502             cf_callback_invoke(cf_cb_live_capture_update_started, capture_opts);
503         } else {
504             cf_callback_invoke(cf_cb_live_capture_fixed_started, capture_opts);
505         }
506     }
507
508     if(capture_opts->real_time_mode) {
509         cf_read_status_t status;
510
511         /* Read what remains of the capture file. */
512         status = cf_finish_tail(capture_opts->cf, &err);
513
514         /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */
515         packet_count_save = cf_get_packet_count(capture_opts->cf);
516         /* Tell the GUI, we are not doing a capture any more.
517                    Must be done after the cf_finish_tail(), so file lengths are displayed
518                    correct. */
519         cf_callback_invoke(cf_cb_live_capture_update_finished, capture_opts->cf);
520
521         /* Finish the capture. */
522         switch (status) {
523
524         case CF_READ_OK:
525             if ((packet_count_save == 0) && !capture_opts->restart) {
526                 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
527 "%sNo packets captured!%s\n"
528 "\n"
529 "As no data was captured, closing the %scapture file!\n"
530 "\n"
531 "\n"
532 "Help about capturing can be found at:\n"
533 "\n"
534 "       http://wiki.wireshark.org/CaptureSetup"
535 #ifdef _WIN32
536 "\n\n"
537 "Wireless (Wi-Fi/WLAN):\n"
538 "Try to switch off promiscuous mode in the Capture Options!"
539 #endif
540 "",
541               simple_dialog_primary_start(), simple_dialog_primary_end(),
542               cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
543               cf_close(capture_opts->cf);
544             }
545             break;
546         case CF_READ_ERROR:
547           /* Just because we got an error, that doesn't mean we were unable
548              to read any of the file; we handle what we could get from the
549              file. */
550           break;
551
552         case CF_READ_ABORTED:
553           /* Exit by leaving the main loop, so that any quit functions
554              we registered get called. */
555           main_window_quit();
556         }
557
558     } else {
559         /* first of all, we are not doing a capture any more */
560         cf_callback_invoke(cf_cb_live_capture_fixed_finished, capture_opts->cf);
561
562         /* this is a normal mode capture and if no error happened, read in the capture file data */
563         if(capture_opts->save_file != NULL) {
564             capture_input_read_all(capture_opts, cf_is_tempfile(capture_opts->cf),
565                 cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
566         }
567     }
568
569     if(capture_opts->show_info)
570       capture_info_close();
571
572     capture_opts->state = CAPTURE_STOPPED;
573
574     /* if we couldn't open a capture file, there's nothing more for us to do */
575     if(capture_opts->save_file == NULL) {
576         cf_close(capture_opts->cf);
577         return;
578     }
579
580     /* does the user wants to restart the current capture? */
581     if(capture_opts->restart) {
582         capture_opts->restart = FALSE;
583
584         eth_unlink(capture_opts->save_file);
585
586         /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */
587         if(cf_is_tempfile(capture_opts->cf)) {
588             g_free(capture_opts->save_file);
589             capture_opts->save_file = NULL;
590         }
591
592         /* ... and start the capture again */
593         capture_start(capture_opts);
594     } else {
595         /* We're not doing a capture any more, so we don't have a save file. */
596         g_free(capture_opts->save_file);
597         capture_opts->save_file = NULL;
598     }
599 }
600
601 /**
602  * Fetch the interface list from a child process (dumpcap).
603  *
604  * @return A GList containing if_info_t structs if successful, NULL otherwise.
605  */
606
607 /* XXX - We parse simple text output to get our interface list.  Should
608  * we use "real" data serialization instead, e.g. via XML? */
609 GList *
610 capture_interface_list(int *err, char **err_str)
611 {
612     GList     *if_list = NULL;
613     int        i, j;
614     gchar     *msg;
615     gchar    **raw_list, **if_parts, **addr_parts;
616     gchar     *name;
617     if_info_t *if_info;
618     if_addr_t *if_addr;
619
620     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
621
622     /* Try to get our interface list */
623     *err = sync_interface_list_open(&msg);
624     if (*err != 0) {
625         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
626         if (err_str) {
627             if (*err_str)
628                 *err_str = msg;
629             else
630                 g_free(msg);
631         } else {
632             g_free(msg);
633         }
634         return NULL;
635     }
636
637     /* Split our lines */
638     raw_list = g_strsplit(msg, "\n", 0);
639     g_free(msg);
640
641     for (i = 0; raw_list[i] != NULL; i++) {
642         if_parts = g_strsplit(raw_list[i], "\t", 4);
643         if (if_parts[0] == NULL || if_parts[1] == NULL || if_parts[2] == NULL ||
644                 if_parts[3] == NULL) {
645             g_strfreev(if_parts);
646             continue;
647         }
648
649         /* Number followed by the name, e.g "1. eth0" */
650         name = strchr(if_parts[0], ' ');
651         if (name) {
652             name++;
653         } else {
654             g_strfreev(if_parts);
655             continue;
656         }
657
658         if_info = g_malloc0(sizeof(if_info_t));
659         if_info->name = g_strdup(name);
660         if (strlen(if_parts[1]) > 0)
661             if_info->description = g_strdup(if_parts[1]);
662         addr_parts = g_strsplit(if_parts[2], ",", 0);
663         for (j = 0; addr_parts[j] != NULL; j++) {
664             if_addr = g_malloc0(sizeof(if_addr_t));
665             if (inet_pton(AF_INET, addr_parts[j], &if_addr->ip_addr.ip4_addr)) {
666                 if_addr->type = AT_IPv4;
667             } else if (inet_pton(AF_INET6, addr_parts[j],
668                     &if_addr->ip_addr.ip6_addr)) {
669                 if_addr->type = AT_IPv6;
670             } else {
671                 g_free(if_addr);
672                 if_addr = NULL;
673             }
674             if (if_addr) {
675                 if_info->ip_addr = g_slist_append(if_info->ip_addr, if_addr);
676             }
677         }
678         if (strcmp(if_parts[3], "loopback") == 0)
679             if_info->loopback = TRUE;
680         g_strfreev(if_parts);
681         g_strfreev(addr_parts);
682         if_list = g_list_append(if_list, if_info);
683     }
684     g_strfreev(raw_list);
685
686     /* Check to see if we built a list */
687     if (if_list == NULL) {
688         if (err_str && *err_str)
689             *err_str = g_strdup("No interfaces found");
690         *err = NO_INTERFACES_FOUND;
691     }
692     return if_list;
693 }
694
695 /* XXX - We parse simple text output to get our interface list.  Should
696  * we use "real" data serialization instead, e.g. via XML? */
697 GList *
698 capture_pcap_linktype_list(gchar *ifname, char **err_str)
699 {
700     GList     *linktype_list = NULL;
701     int        err, i;
702     gchar     *msg;
703     gchar    **raw_list, **lt_parts;
704     data_link_info_t *data_link_info;
705
706     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List ...");
707
708     /* Try to get our interface list */
709     err = sync_linktype_list_open(ifname, &msg);
710     if (err != 0) {
711         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Interface List failed!");
712         if (err_str) {
713             *err_str = msg;
714         } else {
715             g_free(msg);
716         }
717         return NULL;
718     }
719
720     /* Split our lines */
721     raw_list = g_strsplit(msg, "\n", 0);
722     g_free(msg);
723
724     for (i = 0; raw_list[i] != NULL; i++) {
725         /* ...and what if the interface name has a tab in it, Mr. Clever Programmer? */
726         lt_parts = g_strsplit(raw_list[i], "\t", 3);
727         if (lt_parts[0] == NULL || lt_parts[1] == NULL || lt_parts[2] == NULL) {
728             g_strfreev(lt_parts);
729             continue;
730         }
731
732         data_link_info = g_malloc(sizeof (data_link_info_t));
733         data_link_info->dlt = (int) strtol(lt_parts[0], NULL, 10);
734         data_link_info->name = g_strdup(lt_parts[1]);
735         if (strcmp(lt_parts[2], "(not supported)") != 0)
736             data_link_info->description = g_strdup(lt_parts[2]);
737         else
738             data_link_info->description = NULL;
739
740         linktype_list = g_list_append(linktype_list, data_link_info);
741     }
742     g_strfreev(raw_list);
743
744     /* Check to see if we built a list */
745     if (linktype_list == NULL) {
746         if (err_str)
747             *err_str = NULL;
748     }
749     return linktype_list;
750 }
751
752 if_stat_cache_t *
753 capture_stat_start(GList *if_list) {
754     int stat_fd, fork_child;
755     gchar *msg;
756     if_stat_cache_t *sc = NULL;
757     GList *if_entry;
758     if_info_t *if_info;
759     if_stat_cache_item_t *sc_item;
760
761     /* Fire up dumpcap. */
762     /*
763      * XXX - on systems with BPF, the number of BPF devices limits the
764      * number of devices on which you can capture simultaneously.
765      *
766      * This means that
767      *
768      *  1) this might fail if you run out of BPF devices
769      *
770      * and
771      *
772      *  2) opening every interface could leave too few BPF devices
773      *     for *other* programs.
774      *
775      * It also means the system could end up getting a lot of traffic
776      * that it has to pass through the networking stack and capture
777      * mechanism, so opening all the devices and presenting packet
778      * counts might not always be a good idea.
779      */
780      if (sync_interface_stats_open(&stat_fd, &fork_child, &msg) == 0) {
781         sc = g_malloc(sizeof(if_stat_cache_t));
782         sc->stat_fd = stat_fd;
783         sc->fork_child = fork_child;
784         sc->cache_list = NULL;
785
786         /* Initialize the cache */
787         for (if_entry = if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
788             if_info = if_entry->data;
789             sc_item = g_malloc0(sizeof(if_stat_cache_item_t));
790             sc_item->name = g_strdup(if_info->name);
791             sc->cache_list = g_list_append(sc->cache_list, sc_item);
792         }
793     }
794     return sc;
795 }
796
797 #define MAX_STAT_LINE_LEN 500
798
799 static void
800 capture_stat_cache_update(if_stat_cache_t *sc) {
801     gchar stat_line[MAX_STAT_LINE_LEN];
802     gchar **stat_parts;
803     GList *sc_entry;
804     if_stat_cache_item_t *sc_item;
805
806     if (!sc)
807         return;
808
809     while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
810         g_strstrip(stat_line);
811         stat_parts = g_strsplit(stat_line, "\t", 3);
812         if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
813             stat_parts[2] == NULL) {
814             g_strfreev(stat_parts);
815             continue;
816         }
817         for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
818             sc_item = sc_entry->data;
819             if (strcmp(sc_item->name, stat_parts[0]) == 0) {
820                 sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
821                 sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
822             }
823         }
824         g_strfreev(stat_parts);
825     }
826 }
827
828 gboolean
829 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps) {
830     GList *sc_entry;
831     if_stat_cache_item_t *sc_item;
832
833     if (!sc || !ifname || !ps) {
834         return FALSE;
835     }
836
837     capture_stat_cache_update(sc);
838     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
839         sc_item = sc_entry->data;
840         if (strcmp(sc_item->name, ifname) == 0) {
841             memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
842             return TRUE;
843         }
844     }
845     return FALSE;
846 }
847
848 void
849 capture_stat_stop(if_stat_cache_t *sc) {
850     GList *sc_entry;
851     if_stat_cache_item_t *sc_item;
852     gchar *msg;
853
854     if (!sc)
855         return;
856
857     sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
858
859     for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
860         sc_item = sc_entry->data;
861         g_free(sc_item->name);
862         g_free(sc_item);
863     }
864     g_free(sc);
865 }
866
867 #endif /* HAVE_LIBPCAP */