LATER... ei_kerberos_kdc_session_key ...
[wireshark-sm.git] / ui / capture.c
blob56621d06ce3331ae50652ffb871d1d11bf633078
1 /* capture.c
2 * Routines for packet capture
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
12 #define WS_LOG_DOMAIN LOG_DOMAIN_CAPTURE
14 #ifdef HAVE_LIBPCAP
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
20 #include <glib.h>
22 #include <ws_exit_codes.h>
24 #include <epan/packet.h>
25 #include <epan/dfilter/dfilter.h>
26 #include "extcap.h"
27 #include "file.h"
28 #include "ui/capture.h"
29 #include "capture/capture_ifinfo.h"
30 #include <capture/capture_sync.h>
31 #include "capture/iface_monitor.h"
32 #include "ui/capture_info.h"
33 #include "ui/capture_ui_utils.h"
34 #include "ui/iface_lists.h"
35 #include "ui/util.h"
36 #include "ui/urls.h"
37 #include "capture/capture-pcap-util.h"
39 #ifdef _WIN32
40 #include "capture/capture-wpcap.h"
41 #endif
43 #include "ui/simple_dialog.h"
44 #include "ui/ws_ui_util.h"
46 #include "wsutil/file_util.h"
47 #include "wsutil/str_util.h"
48 #include <wsutil/filesystem.h>
49 #include <wsutil/wslog.h>
50 #include <wsutil/ws_assert.h>
52 typedef struct if_stat_cache_item_s {
53 char *name;
54 struct pcap_stat ps;
55 } if_stat_cache_item_t;
57 struct if_stat_cache_s {
58 int stat_fd;
59 ws_process_id fork_child;
60 GList *cache_list; /* List of if_stat_chache_entry_t */
63 /* this callback mechanism should possibly be replaced by the g_signal_...() stuff (if I only would know how :-) */
64 typedef struct {
65 capture_callback_t cb_fct;
66 void *user_data;
67 } capture_callback_data_t;
69 static GList *capture_callbacks;
71 static void
72 capture_callback_invoke(int event, capture_session *cap_session)
74 capture_callback_data_t *cb;
75 GList *cb_item = capture_callbacks;
77 /* there should be at least one interested */
78 ws_assert(cb_item != NULL);
80 while(cb_item != NULL) {
81 cb = (capture_callback_data_t *)cb_item->data;
82 cb->cb_fct(event, cap_session, cb->user_data);
83 cb_item = g_list_next(cb_item);
88 void
89 capture_callback_add(capture_callback_t func, void *user_data)
91 capture_callback_data_t *cb;
93 cb = g_new(capture_callback_data_t, 1);
94 cb->cb_fct = func;
95 cb->user_data = user_data;
97 capture_callbacks = g_list_prepend(capture_callbacks, cb);
100 void
101 capture_callback_remove(capture_callback_t func, void *user_data)
103 capture_callback_data_t *cb;
104 GList *cb_item = capture_callbacks;
106 while(cb_item != NULL) {
107 cb = (capture_callback_data_t *)cb_item->data;
108 if(cb->cb_fct == func && cb->user_data == user_data) {
109 capture_callbacks = g_list_remove(capture_callbacks, cb);
110 g_free(cb);
111 return;
113 cb_item = g_list_next(cb_item);
116 ws_assert_not_reached();
120 * Start a capture.
122 * @return true if the capture starts successfully, false otherwise.
124 bool
125 capture_start(capture_options *capture_opts, GPtrArray *capture_comments,
126 capture_session *cap_session, info_data_t* cap_data,
127 void(*update_cb)(void))
129 GString *source;
131 cap_session->state = CAPTURE_PREPARING;
132 cap_session->count = 0;
133 ws_message("Capture Start ...");
134 source = get_iface_list_string(capture_opts, IFLIST_SHOW_FILTER);
135 cf_set_tempfile_source((capture_file *)cap_session->cf, source->str);
136 g_string_free(source, TRUE);
137 iface_mon_enable(false);
138 /* try to start the capture child process */
139 if (!sync_pipe_start(capture_opts, capture_comments, cap_session,
140 cap_data, update_cb)) {
141 iface_mon_enable(true);
142 /* We failed to start the capture child. */
143 if(capture_opts->save_file != NULL) {
144 g_free(capture_opts->save_file);
145 capture_opts->save_file = NULL;
148 ws_message("Capture Start failed.");
149 cap_session->state = CAPTURE_STOPPED;
150 return false;
153 // Do we need data structures for ignoring duplicate frames?
154 if (prefs.ignore_dup_frames && capture_opts->real_time_mode) {
155 fifo_string_cache_init(&cap_session->frame_dup_cache,
156 prefs.ignore_dup_frames_cache_entries, g_free);
157 cap_session->frame_cksum = g_checksum_new(G_CHECKSUM_SHA256);
160 /* the capture child might not respond shortly after bringing it up */
161 /* (for example: it will block if no input arrives from an input capture pipe (e.g. mkfifo)) */
163 /* to prevent problems, bring the main GUI into "capture mode" right after a successful */
164 /* spawn/exec of the capture child, without waiting for any response from it */
165 capture_callback_invoke(capture_cb_capture_prepared, cap_session);
167 wtap_rec_init(&cap_session->rec);
168 ws_buffer_init(&cap_session->buf, 1514);
170 cap_session->wtap = NULL;
172 if (capture_opts->show_info) {
173 if (cap_data->counts.counts_hash != NULL)
175 /* Clean up any previous lists of packet counts */
176 g_hash_table_destroy(cap_data->counts.counts_hash);
179 cap_data->counts.counts_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
180 cap_data->counts.other = 0;
181 cap_data->counts.total = 0;
183 cap_data->ui.counts = &cap_data->counts;
185 capture_info_ui_create(&cap_data->ui, cap_session);
188 return true;
192 void
193 capture_stop(capture_session *cap_session)
195 ws_message("Capture Stop ...");
197 capture_callback_invoke(capture_cb_capture_stopping, cap_session);
199 if (!extcap_session_stop(cap_session)) {
200 extcap_request_stop(cap_session);
201 cap_session->capture_opts->stop_after_extcaps = true;
202 } else {
203 /* stop the capture child gracefully */
204 sync_pipe_stop(cap_session);
209 void
210 capture_kill_child(capture_session *cap_session)
212 ws_info("Capture Kill");
214 /* kill the capture child */
215 sync_pipe_kill(cap_session->fork_child);
218 #ifdef _WIN32
219 #define NO_PACKETS_CAPTURED_PLATFORM_HELP \
220 "\n\n" \
221 "Wireless (Wi-Fi/WLAN):\n" \
222 "Try to switch off promiscuous mode in the Capture Options."
223 #else
224 #define NO_PACKETS_CAPTURED_PLATFORM_HELP
225 #endif
227 static void
228 capture_input_no_packets(capture_session *cap_session)
230 simple_message_box(ESD_TYPE_INFO, NULL,
231 "Help about capturing can be found at "
232 WS_WIKI_URL("CaptureSetup")
233 NO_PACKETS_CAPTURED_PLATFORM_HELP,
234 "No packets captured. "
235 "As no data was captured, closing the %scapture file.",
236 (cf_is_tempfile((capture_file *)cap_session->cf)) ? "temporary " : "");
237 cf_close((capture_file *)cap_session->cf);
240 /* We've succeeded in doing a (non real-time) capture; try to read it into a new capture file */
241 static bool
242 capture_input_read_all(capture_session *cap_session, bool is_tempfile,
243 bool drops_known, uint32_t drops)
245 capture_options *capture_opts = cap_session->capture_opts;
246 int err;
248 /* Capture succeeded; attempt to open the capture file. */
249 if (cf_open((capture_file *)cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, is_tempfile, &err) != CF_OK) {
250 /* We're not doing a capture any more, so we don't have a save file. */
251 return false;
254 /* Set the read filter to NULL. */
255 /* XXX - this is odd here; try to put it somewhere where it fits better */
256 cf_set_rfcode((capture_file *)cap_session->cf, NULL);
258 /* Get the packet-drop statistics.
260 XXX - there are currently no packet-drop statistics stored
261 in libpcap captures, and that's what we're reading.
263 At some point, we will add support in Wiretap to return
264 packet-drop statistics for capture file formats that store it,
265 and will make "cf_read()" get those statistics from Wiretap.
266 We clear the statistics (marking them as "not known") in
267 "cf_open()", and "cf_read()" will only fetch them and mark
268 them as known if Wiretap supplies them, so if we get the
269 statistics now, after calling "cf_open()" but before calling
270 "cf_read()", the values we store will be used by "cf_read()".
272 If a future libpcap capture file format stores the statistics,
273 we'll put them into the capture file that we write, and will
274 thus not have to set them here - "cf_read()" will get them from
275 the file and use them. */
276 if (drops_known) {
277 cf_set_drops_known((capture_file *)cap_session->cf, true);
279 /* XXX - on some systems, libpcap doesn't bother filling in
280 "ps_ifdrop" - it doesn't even set it to zero - so we don't
281 bother looking at it.
283 Ideally, libpcap would have an interface that gave us
284 several statistics - perhaps including various interface
285 error statistics - and would tell us which of them it
286 supplies, allowing us to display only the ones it does. */
287 cf_set_drops((capture_file *)cap_session->cf, drops);
290 /* read in the packet data */
291 switch (cf_read((capture_file *)cap_session->cf, /*reloading=*/false)) {
293 case CF_READ_OK:
294 case CF_READ_ERROR:
295 /* Just because we got an error, that doesn't mean we were unable
296 to read any of the file; we handle what we could get from the
297 file. */
298 break;
300 case CF_READ_ABORTED:
301 /* The user asked to abort the read, but that might be to
302 restart the capture, so let the caller decide whether
303 to exit. */
304 //exit_application(0);
305 return false;
308 /* if we didn't capture even a single packet, report that and
309 close the file again */
310 if(cap_session->count == 0 && !capture_opts->restart) {
311 capture_input_no_packets(cap_session);
313 return true;
316 static const char *
317 cf_open_error_message(int err, char *err_info)
319 const char *errmsg;
320 static char errmsg_errno[1024 + 1];
322 if (err < 0) {
323 /* Wiretap error. */
324 switch (err) {
326 case WTAP_ERR_NOT_REGULAR_FILE:
327 errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
328 break;
330 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
331 /* Seen only when opening a capture file for reading. */
332 errmsg = "The file \"%s\" isn't a capture file in a format Wireshark understands.";
333 break;
335 case WTAP_ERR_UNSUPPORTED:
336 snprintf(errmsg_errno, sizeof(errmsg_errno),
337 "The file \"%%s\" contains record data that Wireshark doesn't support.\n"
338 "(%s)", err_info != NULL ? err_info : "no information supplied");
339 g_free(err_info);
340 errmsg = errmsg_errno;
341 break;
343 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
344 errmsg = "The file \"%s\" is a capture for a network type that Wireshark doesn't support.";
345 break;
347 case WTAP_ERR_BAD_FILE:
348 snprintf(errmsg_errno, sizeof(errmsg_errno),
349 "The file \"%%s\" appears to be damaged or corrupt.\n"
350 "(%s)", err_info != NULL ? err_info : "no information supplied");
351 g_free(err_info);
352 errmsg = errmsg_errno;
353 break;
355 case WTAP_ERR_CANT_OPEN:
356 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
357 break;
359 case WTAP_ERR_SHORT_READ:
360 errmsg = "The file \"%s\" appears to have been cut short"
361 " in the middle of a packet or other data.";
362 break;
364 case WTAP_ERR_DECOMPRESS:
365 snprintf(errmsg_errno, sizeof(errmsg_errno),
366 "The file \"%%s\" cannot be decompressed; it may be damaged or corrupt.\n"
367 "(%s)", err_info != NULL ? err_info : "no information supplied");
368 g_free(err_info);
369 errmsg = errmsg_errno;
370 break;
372 case WTAP_ERR_INTERNAL:
373 snprintf(errmsg_errno, sizeof(errmsg_errno),
374 "An internal error occurred opening the file \"%%s\".\n"
375 "(%s)", err_info != NULL ? err_info : "no information supplied");
376 g_free(err_info);
377 errmsg = errmsg_errno;
378 break;
380 case WTAP_ERR_DECOMPRESSION_NOT_SUPPORTED:
381 snprintf(errmsg_errno, sizeof(errmsg_errno),
382 "The file \"%%s\" cannot be decompressed; it is compressed in a way that We don't support.\n"
383 "(%s)", err_info != NULL ? err_info : "no information supplied");
384 g_free(err_info);
385 errmsg = errmsg_errno;
386 break;
388 default:
389 snprintf(errmsg_errno, sizeof(errmsg_errno),
390 "The file \"%%s\" could not be opened: %s.",
391 wtap_strerror(err));
392 errmsg = errmsg_errno;
393 break;
396 else
397 errmsg = file_open_error_message(err, false);
398 return errmsg;
401 /* capture child tells us we have a new (or the first) capture file */
402 static bool
403 capture_input_new_file(capture_session *cap_session, char *new_file)
405 capture_options *capture_opts = cap_session->capture_opts;
406 bool is_tempfile;
407 int err;
408 char *err_info;
409 char *err_msg;
411 if(cap_session->state == CAPTURE_PREPARING) {
412 ws_message("Capture started");
414 ws_message("File: \"%s\"", new_file);
416 ws_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
418 /* free the old filename */
419 if(capture_opts->save_file != NULL) {
420 /* we start a new capture file, close the old one (if we had one before). */
421 /* (we can only have an open capture file in real_time_mode!) */
422 if (((capture_file*)cap_session->cf)->state == FILE_READ_PENDING) {
423 capture_callback_invoke(capture_cb_capture_fixed_finished, cap_session);
424 } else if (((capture_file*)cap_session->cf)->state != FILE_CLOSED) {
425 cap_session->session_will_restart = true;
426 capture_callback_invoke(capture_cb_capture_update_finished, cap_session);
427 cf_finish_tail((capture_file *)cap_session->cf,
428 &cap_session->rec, &cap_session->buf, &err,
429 &cap_session->frame_dup_cache, cap_session->frame_cksum);
430 cf_close((capture_file *)cap_session->cf);
432 g_free(capture_opts->save_file);
433 is_tempfile = false;
434 cf_set_tempfile((capture_file *)cap_session->cf, false);
435 } else {
436 /* we didn't have a save_file before; must be a tempfile */
437 is_tempfile = true;
438 cf_set_tempfile((capture_file *)cap_session->cf, true);
441 /* save the new filename */
442 capture_opts->save_file = g_strdup(new_file);
444 /* if we are in real-time mode, open the new file now */
445 if(capture_opts->real_time_mode) {
446 /* Attempt to open the capture file and set up to read from it. */
447 switch(cf_open((capture_file *)cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, is_tempfile, &err)) {
448 case CF_OK:
449 break;
450 case CF_ERROR:
451 /* Don't unlink (delete) the save file - leave it around,
452 for debugging purposes. */
453 g_free(capture_opts->save_file);
454 capture_opts->save_file = NULL;
455 return false;
457 } else {
458 capture_callback_invoke(capture_cb_capture_prepared, cap_session);
461 if(capture_opts->show_info) {
462 if (cap_session->wtap != NULL) {
463 wtap_close(cap_session->wtap);
466 cap_session->wtap = wtap_open_offline(new_file, WTAP_TYPE_AUTO, &err, &err_info, false);
467 if (!cap_session->wtap) {
468 err_msg = ws_strdup_printf(cf_open_error_message(err, err_info),
469 new_file);
470 ws_warning("capture_input_new_file: %d (%s)", err, err_msg);
471 g_free(err_msg);
472 return false;
476 if(capture_opts->real_time_mode) {
477 capture_callback_invoke(capture_cb_capture_update_started, cap_session);
478 } else {
479 capture_callback_invoke(capture_cb_capture_fixed_started, cap_session);
481 cap_session->state = CAPTURE_RUNNING;
483 return true;
486 static void
487 capture_info_packet(info_data_t* cap_info, int wtap_linktype, const unsigned char *pd, uint32_t caplen, union wtap_pseudo_header *pseudo_header)
489 capture_packet_info_t cpinfo;
491 /* Setup the capture packet structure */
492 cpinfo.counts = cap_info->counts.counts_hash;
494 cap_info->counts.total++;
495 if (!try_capture_dissector("wtap_encap", wtap_linktype, pd, 0, caplen, &cpinfo, pseudo_header))
496 cap_info->counts.other++;
499 /* new packets arrived */
500 static void
501 capture_info_new_packets(int to_read, wtap *wth, info_data_t* cap_info)
503 int err;
504 char *err_info;
505 int64_t data_offset;
506 wtap_rec rec;
507 Buffer buf;
508 union wtap_pseudo_header *pseudo_header;
509 int wtap_linktype;
511 cap_info->ui.new_packets = to_read;
513 /*ws_warning("new packets: %u", to_read);*/
515 wtap_rec_init(&rec);
516 ws_buffer_init(&buf, 1514);
517 while (to_read > 0) {
518 wtap_cleareof(wth);
519 if (wtap_read(wth, &rec, &buf, &err, &err_info, &data_offset)) {
520 if (rec.rec_type == REC_TYPE_PACKET) {
521 pseudo_header = &rec.rec_header.packet_header.pseudo_header;
522 wtap_linktype = rec.rec_header.packet_header.pkt_encap;
524 capture_info_packet(cap_info, wtap_linktype,
525 ws_buffer_start_ptr(&buf),
526 rec.rec_header.packet_header.caplen,
527 pseudo_header);
529 /*ws_warning("new packet");*/
530 to_read--;
532 wtap_rec_reset(&rec);
535 wtap_rec_cleanup(&rec);
536 ws_buffer_free(&buf);
538 capture_info_ui_update(&cap_info->ui);
541 /* capture child tells us we have new packets to read */
542 static void
543 capture_input_new_packets(capture_session *cap_session, int to_read)
545 capture_options *capture_opts = cap_session->capture_opts;
546 int err;
548 ws_assert(capture_opts->save_file);
550 if(capture_opts->real_time_mode) {
551 if (((capture_file*)cap_session->cf)->state == FILE_READ_PENDING) {
552 /* Attempt to open the capture file and set up to read from it. */
553 switch (cf_open((capture_file*)cap_session->cf, capture_opts->save_file, WTAP_TYPE_AUTO, cf_is_tempfile((capture_file*)cap_session->cf), &err)) {
554 case CF_OK:
555 break;
556 case CF_ERROR:
557 /* Don't unlink (delete) the save file - leave it around,
558 for debugging purposes. */
559 g_free(capture_opts->save_file);
560 capture_opts->save_file = NULL;
561 capture_kill_child(cap_session);
563 capture_callback_invoke(capture_cb_capture_update_started, cap_session);
565 /* Read from the capture file the number of records the child told us it added. */
566 to_read += cap_session->count_pending;
567 cap_session->count_pending = 0;
568 switch (cf_continue_tail((capture_file *)cap_session->cf, to_read,
569 &cap_session->rec, &cap_session->buf, &err,
570 &cap_session->frame_dup_cache, cap_session->frame_cksum)) {
572 case CF_READ_OK:
573 case CF_READ_ERROR:
574 /* Just because we got an error, that doesn't mean we were unable
575 to read any of the file; we handle what we could get from the
576 file.
578 XXX - abort on a read error? */
579 capture_callback_invoke(capture_cb_capture_update_continue, cap_session);
580 break;
582 case CF_READ_ABORTED:
583 /* Kill the child capture process; the user wants to exit, and we
584 shouldn't just leave it running. */
585 capture_kill_child(cap_session);
586 break;
588 } else {
589 cf_fake_continue_tail((capture_file *)cap_session->cf);
590 cap_session->count_pending += to_read;
592 capture_callback_invoke(capture_cb_capture_fixed_continue, cap_session);
595 if(cap_session->wtap)
596 capture_info_new_packets(to_read, cap_session->wtap, cap_session->cap_data_info);
600 /* Capture child told us how many dropped packets it counted.
602 static void
603 capture_input_drops(capture_session *cap_session, uint32_t dropped, const char* interface_name)
605 if (interface_name != NULL) {
606 ws_info("%u packet%s dropped from %s", dropped, plurality(dropped, "", "s"), interface_name);
607 } else {
608 ws_info("%u packet%s dropped", dropped, plurality(dropped, "", "s"));
611 ws_assert(cap_session->state == CAPTURE_RUNNING);
613 cf_set_drops_known((capture_file *)cap_session->cf, true);
614 cf_set_drops((capture_file *)cap_session->cf, dropped);
618 /* Capture child told us that an error has occurred while starting/running
619 the capture.
620 The buffer we're handed has *two* null-terminated strings in it - a
621 primary message and a secondary message, one right after the other.
622 The secondary message might be a null string.
624 static void
625 capture_input_error(capture_session *cap_session _U_, char *error_msg,
626 char *secondary_error_msg)
628 char *safe_error_msg;
629 char *safe_secondary_error_msg;
631 /* The primary message might be an empty string, e.g. when the error was
632 * from extcap. (The extcap stderr is gathered when the session closes
633 * and printed in capture_input_closed below.) */
634 if (*error_msg != '\0') {
635 ws_message("Error message from child: \"%s\", \"%s\"", error_msg, secondary_error_msg);
638 ws_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
640 safe_error_msg = simple_dialog_format_message(error_msg);
641 if (secondary_error_msg != NULL && *secondary_error_msg != '\0') {
642 /* We have both primary and secondary messages. */
643 safe_secondary_error_msg = simple_dialog_format_message(secondary_error_msg);
644 simple_message_box(ESD_TYPE_ERROR, NULL, safe_secondary_error_msg,
645 "%s", safe_error_msg);
646 g_free(safe_secondary_error_msg);
647 } else {
648 /* We have only a primary message. */
649 simple_message_box(ESD_TYPE_ERROR, NULL, NULL, "%s", safe_error_msg);
651 g_free(safe_error_msg);
653 /* the capture child will close the sync_pipe if required, nothing to do for now */
656 /* Capture child told us that an error has occurred while parsing a
657 capture filter when starting/running the capture.
659 static void
660 capture_input_cfilter_error(capture_session *cap_session, unsigned i,
661 const char *error_message)
663 capture_options *capture_opts = cap_session->capture_opts;
664 dfilter_t *rfcode = NULL;
665 char *safe_cfilter;
666 char *safe_descr;
667 char *safe_cfilter_error_msg;
668 const char *secondary_error_msg;
669 interface_options *interface_opts;
671 ws_message("Capture filter error message from child: \"%s\"", error_message);
673 ws_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
674 ws_assert(i < capture_opts->ifaces->len);
676 interface_opts = &g_array_index(capture_opts->ifaces, interface_options, i);
677 safe_cfilter = simple_dialog_format_message(interface_opts->cfilter);
678 safe_descr = simple_dialog_format_message(interface_opts->descr);
679 safe_cfilter_error_msg = simple_dialog_format_message(error_message);
680 /* Did the user try a display filter? */
681 if (dfilter_compile(interface_opts->cfilter, &rfcode, NULL) && rfcode != NULL) {
682 secondary_error_msg =
683 "That string looks like a valid display filter.\n"
684 "\n"
685 "Note that display filters and capture filters don't have the same syntax,\n"
686 "so you can't use most display filter expressions as capture filters.\n"
687 "\n"
688 "See the User's Guide for a description of the capture filter syntax.";
689 } else {
690 secondary_error_msg =
691 "See the User's Guide for a description of the capture filter syntax.";
693 simple_message_box(ESD_TYPE_ERROR, NULL,
694 secondary_error_msg,
695 "\"%s\" is not a valid capture filter for interface \"%s\" (%s).",
696 safe_cfilter, safe_descr, safe_cfilter_error_msg);
697 g_free(safe_cfilter_error_msg);
698 g_free(safe_descr);
699 g_free(safe_cfilter);
701 /* the capture child will close the sync_pipe if required, nothing to do for now */
704 /* capture child closed its side of the pipe, do the required cleanup */
705 static void
706 capture_input_closed(capture_session *cap_session, char *msg)
708 capture_options *capture_opts = cap_session->capture_opts;
709 int err;
711 ws_message("Capture stopped.");
712 ws_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING);
714 if (msg != NULL && msg[0] != '\0') {
715 ESD_TYPE_E dlg_type = ESD_TYPE_ERROR;
716 if (strstr(msg, " WARNING] ")) {
717 dlg_type = ESD_TYPE_WARN;
720 * ws_log prefixes log messages with a timestamp delimited by " -- " and possibly
721 * a function name delimited by "(): ". Log it to sterr, but omit it in the UI.
723 char **msg_lines = g_strsplit(msg, "\n", 0);
724 GString* gui_msg = g_string_new(NULL);
726 for (char **line = msg_lines; *line != NULL; line++) {
727 if (gui_msg->len > 0) {
728 g_string_append(gui_msg, "\n");
730 char *plain_msg = strstr(*line, "(): ");
731 if (plain_msg != NULL) {
732 plain_msg += strlen("(): ");
733 } else if ((plain_msg = strstr(*line, " -- ")) != NULL) {
734 plain_msg += strlen(" -- ");
735 } else {
736 plain_msg = *line;
738 g_string_append(gui_msg, plain_msg);
740 ws_warning("%s", msg);
741 simple_dialog(dlg_type, ESD_BTN_OK, "%s", gui_msg->str);
742 g_string_free(gui_msg, TRUE);
743 g_strfreev(msg_lines);
746 wtap_rec_cleanup(&cap_session->rec);
747 ws_buffer_free(&cap_session->buf);
748 if(cap_session->state == CAPTURE_PREPARING) {
749 /* We started the capture child, but we didn't manage to start
750 the capture process; note that the attempt to start it
751 failed. */
752 capture_callback_invoke(capture_cb_capture_failed, cap_session);
753 } else {
754 /* We started a capture; process what's left of the capture file if
755 we were in "update list of packets in real time" mode, or process
756 all of it if we weren't. */
757 if(((capture_file*)cap_session->cf)->state == FILE_READ_IN_PROGRESS) {
758 cf_read_status_t status;
760 /* Read what remains of the capture file. */
761 status = cf_finish_tail((capture_file *)cap_session->cf,
762 &cap_session->rec, &cap_session->buf, &err,
763 &cap_session->frame_dup_cache, cap_session->frame_cksum);
765 // The real-time reading of the pcap is done. Now we can clear the
766 // dup-frame cache, if present. But check that we actually have
767 // data structures to clear (by checking frame-checksum); the user
768 // could have changed the preference *during* the live capture.
769 if (cap_session->frame_cksum != NULL) {
770 fifo_string_cache_free(&cap_session->frame_dup_cache);
771 g_checksum_free(cap_session->frame_cksum);
772 cap_session->frame_cksum = NULL;
775 /* Tell the GUI we are not doing a capture any more.
776 Must be done after the cf_finish_tail(), so file lengths are
777 correctly displayed */
778 cap_session->session_will_restart = false;
779 capture_callback_invoke(capture_cb_capture_update_finished, cap_session);
781 /* Finish the capture. */
782 switch (status) {
784 case CF_READ_OK:
785 if (cap_session->count == 0 && !capture_opts->restart) {
786 capture_input_no_packets(cap_session);
788 break;
789 case CF_READ_ERROR:
790 /* Just because we got an error, that doesn't mean we were unable
791 to read any of the file; we handle what we could get from the
792 file. */
793 break;
795 case CF_READ_ABORTED:
796 /* The user asked to abort the read, but that might be to
797 restart the capture, so let the caller decide whether
798 to exit. */
799 //exit_application(0);
800 break;
802 } else if (((capture_file*)cap_session->cf)->state == FILE_READ_PENDING) {
803 /* first of all, we are not doing a capture any more */
804 capture_callback_invoke(capture_cb_capture_fixed_finished, cap_session);
806 /* this is a normal mode capture and if no error happened, read in the capture file data */
807 if(capture_opts->save_file != NULL) {
808 capture_input_read_all(cap_session, cf_is_tempfile((capture_file *)cap_session->cf),
809 cf_get_drops_known((capture_file *)cap_session->cf), cf_get_drops((capture_file *)cap_session->cf));
811 } else {
812 /* First, tell the GUI we are not capturing nor stopping a capture
813 anymore. We need to do this if we're aborting the capture but
814 not quitting the program (e.g., restarting the capture.) */
815 capture_callback_invoke(capture_cb_capture_update_finished, cap_session);
817 if (cap_session->frame_cksum != NULL) {
818 fifo_string_cache_free(&cap_session->frame_dup_cache);
819 g_checksum_free(cap_session->frame_cksum);
820 cap_session->frame_cksum = NULL;
823 cf_close((capture_file *)cap_session->cf);
827 capture_info_ui_destroy(&cap_session->cap_data_info->ui);
828 if(cap_session->wtap) {
829 wtap_close(cap_session->wtap);
830 cap_session->wtap = NULL;
833 cap_session->state = CAPTURE_STOPPED;
835 /* if we couldn't open a capture file, there's nothing more for us to do */
836 if(capture_opts->save_file == NULL) {
837 cf_close((capture_file *)cap_session->cf);
838 return;
841 /* does the user wants to restart the current capture? */
842 if(capture_opts->restart) {
843 capture_opts->restart = false;
845 /* If we have a ring buffer, the original save file has been overwritten
846 with the "ring filename". Restore it before starting again */
847 if ((capture_opts->multi_files_on) && (capture_opts->orig_save_file != NULL)) {
848 g_free(capture_opts->save_file);
849 capture_opts->save_file = g_strdup(capture_opts->orig_save_file);
852 /* If it was a tempfile, throw away the old filename (so it will become a tempfile again) */
853 if (cf_is_tempfile((capture_file *)cap_session->cf)) {
854 g_free(capture_opts->save_file);
855 capture_opts->save_file = NULL;
857 } else {
859 /* If we're in multiple file mode, restore the original save file
860 name (template), so that it will be used if a new capture is started
861 without opening the Capture Options dialog. Any files we just wrote
862 won't get overwritten. If we set it to NULL, a tempfile name would
863 be used, but that doesn't work in multiple file mode - we could turn
864 off multiple file mode instead, but that would change the behavior
865 if the Capture Options dialog is re-opened. */
866 if ((capture_opts->multi_files_on) && (capture_opts->orig_save_file != NULL)) {
867 g_free(capture_opts->save_file);
868 capture_opts->save_file = g_strdup(capture_opts->orig_save_file);
869 } else {
870 /* We're not doing a capture any more, so we don't have a save file.
871 If a new capture is started without opening the Capture Options
872 dialog (Start button or double-clicking on an interface from
873 the welcome screen), we'll use a tempfile. Thus if our current
874 capture is to a permanent file, we won't overwrite it. */
875 g_free(capture_opts->save_file);
876 capture_opts->save_file = NULL;
881 if_stat_cache_t *
882 capture_stat_start(capture_options *capture_opts)
884 int stat_fd;
885 ws_process_id fork_child;
886 char *msg;
887 if_stat_cache_t *sc = g_new0(if_stat_cache_t, 1);
888 if_stat_cache_item_t *sc_item;
889 unsigned i;
890 interface_t *device;
892 sc->stat_fd = -1;
893 sc->fork_child = WS_INVALID_PID;
895 /* Fire up dumpcap. */
897 * XXX - on systems with BPF, the number of BPF devices limits the
898 * number of devices on which you can capture simultaneously.
900 * This means that
902 * 1) this might fail if you run out of BPF devices
904 * and
906 * 2) opening every interface could leave too few BPF devices
907 * for *other* programs.
909 * It also means the system could end up getting a lot of traffic
910 * that it has to pass through the networking stack and capture
911 * mechanism, so opening all the devices and presenting packet
912 * counts might not always be a good idea.
914 if (sync_interface_stats_open(&stat_fd, &fork_child, NULL, &msg, NULL) == 0) {
915 sc->stat_fd = stat_fd;
916 sc->fork_child = fork_child;
918 /* Initialize the cache */
919 for (i = 0; i < capture_opts->all_ifaces->len; i++) {
920 device = &g_array_index(capture_opts->all_ifaces, interface_t, i);
921 if (device->if_info.type != IF_PIPE && device->if_info.type != IF_EXTCAP) {
922 sc_item = g_new0(if_stat_cache_item_t, 1);
923 ws_assert(device->if_info.name);
924 sc_item->name = g_strdup(device->if_info.name);
925 sc->cache_list = g_list_prepend(sc->cache_list, sc_item);
928 } else {
929 ws_warning("%s", msg);
930 g_free(msg); /* XXX: should we display this to the user via the GUI? */
932 return sc;
935 if_stat_cache_t *
936 capture_interface_stat_start(capture_options *capture_opts _U_, GList **if_list)
938 int stat_fd;
939 ws_process_id fork_child;
940 char *msg;
941 if_stat_cache_t *sc = g_new0(if_stat_cache_t, 1);
942 if_stat_cache_item_t *sc_item;
943 char *data = NULL;
945 sc->stat_fd = -1;
946 sc->fork_child = WS_INVALID_PID;
948 /* Fire up dumpcap. */
950 * XXX - on systems with BPF, the number of BPF devices limits the
951 * number of devices on which you can capture simultaneously.
953 * This means that
955 * 1) this might fail if you run out of BPF devices
957 * and
959 * 2) opening every interface could leave too few BPF devices
960 * for *other* programs.
962 * It also means the system could end up getting a lot of traffic
963 * that it has to pass through the networking stack and capture
964 * mechanism, so opening all the devices and presenting packet
965 * counts might not always be a good idea.
967 /* XXX - We should use capture_opts to control whether we request
968 * the monitor_mode version of the supported link-types for interfaces.
970 int status;
971 iface_mon_enable(false);
972 status = sync_interface_stats_open(&stat_fd, &fork_child, &data, &msg, NULL);
973 iface_mon_enable(true);
974 /* In order to initialize the stat cache (below), we need to have
975 * filled in capture_opts->all_ifaces
977 * Note that the operation above can return a failed status but
978 * valid data, e.g. if dumpcap returns an interface list but none
979 * of them have permission to do a capture.
981 int err = 0;
982 char *err_msg = NULL;
983 *if_list = deserialize_interface_list(data, &err, &err_msg);
984 if (err != 0) {
985 ws_info("%s", err_msg);
986 g_free(err_msg);
988 if (status == 0) {
989 sc->stat_fd = stat_fd;
990 sc->fork_child = fork_child;
992 /* Initialize the cache */
993 for (GList *if_entry = *if_list; if_entry != NULL; if_entry = g_list_next(if_entry)) {
994 if_info_t *if_info = (if_info_t*)if_entry->data;
995 /* We just got this list from dumpcap so it shouldn't
996 * contain stdin, pipes, extcaps, or remote interfaces
997 * list. We could test if_info->type and the name to
998 * exclude those types from the cache anyway, though.
1000 sc_item = g_new0(if_stat_cache_item_t, 1);
1001 ws_assert(if_info->name);
1002 sc_item->name = g_strdup(if_info->name);
1003 sc->cache_list = g_list_prepend(sc->cache_list, sc_item);
1005 } else if (status == WS_EXIT_NO_INTERFACES) {
1007 * No interfaces were found. If that's not the
1008 * result of an error when fetching the local
1009 * interfaces, let the user know.
1011 ws_info("%s", msg);
1012 g_free(msg); /* XXX: should we display this to the user via the GUI? */
1013 } else {
1014 ws_warning("%s", msg);
1015 g_free(msg); /* XXX: should we display this to the user via the GUI? */
1018 #ifdef HAVE_PCAP_REMOTE
1019 *if_list = append_remote_list(*if_list);
1020 #endif
1022 *if_list = append_extcap_interface_list(*if_list);
1023 return sc;
1026 #define MAX_STAT_LINE_LEN 500
1028 static void
1029 capture_stat_cache_update(if_stat_cache_t *sc)
1031 char stat_line[MAX_STAT_LINE_LEN] = "";
1032 char **stat_parts;
1033 GList *sc_entry;
1034 if_stat_cache_item_t *sc_item;
1036 if (!sc || sc->fork_child == WS_INVALID_PID) {
1037 return;
1040 while (sync_pipe_gets_nonblock(sc->stat_fd, stat_line, MAX_STAT_LINE_LEN) > 0) {
1041 g_strstrip(stat_line);
1042 stat_parts = g_strsplit(stat_line, "\t", 3);
1043 if (stat_parts[0] == NULL || stat_parts[1] == NULL ||
1044 stat_parts[2] == NULL) {
1045 g_strfreev(stat_parts);
1046 continue;
1048 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
1049 sc_item = (if_stat_cache_item_t *)sc_entry->data;
1050 if (strcmp(sc_item->name, stat_parts[0]) == 0) {
1051 sc_item->ps.ps_recv = (u_int) strtoul(stat_parts[1], NULL, 10);
1052 sc_item->ps.ps_drop = (u_int) strtoul(stat_parts[2], NULL, 10);
1055 g_strfreev(stat_parts);
1059 bool
1060 capture_stats(if_stat_cache_t *sc, char *ifname, struct pcap_stat *ps)
1062 GList *sc_entry;
1063 if_stat_cache_item_t *sc_item;
1065 if (!sc || sc->fork_child == WS_INVALID_PID || !ifname || !ps) {
1066 return false;
1069 capture_stat_cache_update(sc);
1070 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
1071 sc_item = (if_stat_cache_item_t *)sc_entry->data;
1072 if (strcmp(sc_item->name, ifname) == 0) {
1073 memcpy(ps, &sc_item->ps, sizeof(struct pcap_stat));
1074 return true;
1077 return false;
1080 void
1081 capture_stat_stop(if_stat_cache_t *sc)
1083 GList *sc_entry;
1084 if_stat_cache_item_t *sc_item;
1085 int ret;
1086 char *msg;
1088 if (!sc) {
1089 return;
1092 if (sc->fork_child != WS_INVALID_PID) {
1093 ret = sync_interface_stats_close(&sc->stat_fd, &sc->fork_child, &msg);
1094 if (ret == -1) {
1095 /* XXX - report failure? */
1096 g_free(msg);
1100 for (sc_entry = sc->cache_list; sc_entry != NULL; sc_entry = g_list_next(sc_entry)) {
1101 sc_item = (if_stat_cache_item_t *)sc_entry->data;
1102 g_free(sc_item->name);
1103 g_free(sc_item);
1105 g_list_free(sc->cache_list);
1106 g_free(sc);
1109 /* Initialize a capture session for our callbacks. */
1110 void
1111 capture_input_init(capture_session *cap_session, capture_file *cf)
1113 capture_session_init(cap_session, cf,
1114 capture_input_new_file, capture_input_new_packets,
1115 capture_input_drops, capture_input_error,
1116 capture_input_cfilter_error, capture_input_closed);
1118 #endif /* HAVE_LIBPCAP */