/* capture child tells us we have new packets to read */ void capture_input_new_packets(capture_session *cap_session, int to_read) { capture_options *capture_opts = cap_session->capture_opts; int err; g_assert(capture_opts->save_file); if(capture_opts->real_time_mode) { /* Read from the capture file the number of records the child told us it added. */ switch (cf_continue_tail((capture_file *)cap_session->cf, to_read, &err)) { case CF_READ_OK: case CF_READ_ERROR: /* Just because we got an error, that doesn't mean we were unable to read any of the file; we handle what we could get from the file. XXX - abort on a read error? */ capture_callback_invoke(capture_cb_capture_update_continue, cap_session); break; case CF_READ_ABORTED: /* Kill the child capture process; the user wants to exit, and we shouldn't just leave it running. */ capture_kill_child(cap_session); break; } } else { /* increase the capture file packet counter by the number of incoming packets */ cf_set_packet_count((capture_file *)cap_session->cf, cf_get_packet_count((capture_file *)cap_session->cf) + to_read); cf_fake_continue_tail((capture_file *)cap_session->cf); capture_callback_invoke(capture_cb_capture_fixed_continue, cap_session); } /* update the main window so we get events (e.g. from the stop toolbar button) */ /* This causes a hang on Windows (see bug 7305). Do we need this on any platform? */ #ifndef _WIN32 main_window_update(); #endif if(capture_opts->show_info) capture_info_new_packets(to_read); }
void capture_stop(capture_session *cap_session) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Stop ..."); capture_callback_invoke(capture_cb_capture_stopping, cap_session); /* stop the capture child gracefully */ sync_pipe_stop(cap_session); }
/** * Start a capture. * * @return TRUE if the capture starts successfully, FALSE otherwise. */ gboolean capture_start(capture_options *capture_opts, capture_session *cap_session, void(*update_cb)(void)) { gboolean ret; GString *source; cap_session->state = CAPTURE_PREPARING; cap_session->count = 0; g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ..."); source = get_iface_list_string(capture_opts, IFLIST_SHOW_FILTER); cf_set_tempfile_source((capture_file *)cap_session->cf, source->str); g_string_free(source, TRUE); /* try to start the capture child process */ ret = sync_pipe_start(capture_opts, cap_session, update_cb); if(!ret) { if(capture_opts->save_file != NULL) { g_free(capture_opts->save_file); capture_opts->save_file = NULL; } g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start failed."); cap_session->state = CAPTURE_STOPPED; } else { /* the capture child might not respond shortly after bringing it up */ /* (for example: it will block if no input arrives from an input capture pipe (e.g. mkfifo)) */ /* to prevent problems, bring the main GUI into "capture mode" right after a successful */ /* spawn/exec of the capture child, without waiting for any response from it */ capture_callback_invoke(capture_cb_capture_prepared, cap_session); if(capture_opts->show_info) capture_info_open(cap_session); } return ret; }
/* capture child closed its side of the pipe, do the required cleanup */ void capture_input_closed(capture_session *cap_session, gchar *msg) { capture_options *capture_opts = cap_session->capture_opts; int err; int packet_count_save; g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture stopped!"); g_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING); if (msg != NULL) simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", msg); if(cap_session->state == CAPTURE_PREPARING) { /* We didn't start a capture; note that the attempt to start it failed. */ capture_callback_invoke(capture_cb_capture_failed, cap_session); } else { /* We started a capture; process what's left of the capture file if we were in "update list of packets in real time" mode, or process all of it if we weren't. */ if(capture_opts->real_time_mode) { cf_read_status_t status; /* Read what remains of the capture file. */ status = cf_finish_tail((capture_file *)cap_session->cf, &err); /* XXX: If -Q (quit-after-cap) then cf->count clr'd below so save it first */ packet_count_save = cf_get_packet_count((capture_file *)cap_session->cf); /* Tell the GUI we are not doing a capture any more. Must be done after the cf_finish_tail(), so file lengths are correctly displayed */ capture_callback_invoke(capture_cb_capture_update_finished, cap_session); /* Finish the capture. */ switch (status) { case CF_READ_OK: if ((packet_count_save == 0) && !capture_opts->restart) { simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, "%sNo packets captured!%s\n" "\n" "As no data was captured, closing the %scapture file!\n" "\n" "\n" "Help about capturing can be found at:\n" "\n" " http://wiki.wireshark.org/CaptureSetup" #ifdef _WIN32 "\n\n" "Wireless (Wi-Fi/WLAN):\n" "Try to switch off promiscuous mode in the Capture Options!" #endif "", simple_dialog_primary_start(), simple_dialog_primary_end(), cf_is_tempfile((capture_file *)cap_session->cf) ? "temporary " : ""); cf_close((capture_file *)cap_session->cf); } break; case CF_READ_ERROR: /* Just because we got an error, that doesn't mean we were unable to read any of the file; we handle what we could get from the file. */ break; case CF_READ_ABORTED: /* Exit by leaving the main loop, so that any quit functions we registered get called. */ main_window_quit(); break; } } else { /* first of all, we are not doing a capture any more */ capture_callback_invoke(capture_cb_capture_fixed_finished, cap_session); /* this is a normal mode capture and if no error happened, read in the capture file data */ if(capture_opts->save_file != NULL) { capture_input_read_all(cap_session, cf_is_tempfile((capture_file *)cap_session->cf), cf_get_drops_known((capture_file *)cap_session->cf), cf_get_drops((capture_file *)cap_session->cf)); } } } if(capture_opts->show_info) capture_info_close(); cap_session->state = CAPTURE_STOPPED; /* if we couldn't open a capture file, there's nothing more for us to do */ if(capture_opts->save_file == NULL) { cf_close((capture_file *)cap_session->cf); return; } /* does the user wants to restart the current capture? */ if(capture_opts->restart) { capture_opts->restart = FALSE; ws_unlink(capture_opts->save_file); /* if it was a tempfile, throw away the old filename (so it will become a tempfile again) */ if(cf_is_tempfile((capture_file *)cap_session->cf)) { g_free(capture_opts->save_file); capture_opts->save_file = NULL; } /* ... and start the capture again */ if (capture_opts->ifaces->len == 0) { collect_ifaces(capture_opts); } /* close the currently loaded capture file */ cf_close((capture_file *)cap_session->cf); capture_start(capture_opts, cap_session); } else { /* We're not doing a capture any more, so we don't have a save file. */ g_free(capture_opts->save_file); capture_opts->save_file = NULL; } }
/* capture child tells us we have a new (or the first) capture file */ gboolean capture_input_new_file(capture_session *cap_session, gchar *new_file) { capture_options *capture_opts = cap_session->capture_opts; gboolean is_tempfile; int err; if(cap_session->state == CAPTURE_PREPARING) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture started!"); } g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "File: \"%s\"", new_file); g_assert(cap_session->state == CAPTURE_PREPARING || cap_session->state == CAPTURE_RUNNING); /* free the old filename */ if(capture_opts->save_file != NULL) { /* we start a new capture file, close the old one (if we had one before). */ /* (we can only have an open capture file in real_time_mode!) */ if( ((capture_file *) cap_session->cf)->state != FILE_CLOSED) { if(capture_opts->real_time_mode) { capture_callback_invoke(capture_cb_capture_update_finished, cap_session); cf_finish_tail((capture_file *)cap_session->cf, &err); cf_close((capture_file *)cap_session->cf); } else { capture_callback_invoke(capture_cb_capture_fixed_finished, cap_session); } } g_free(capture_opts->save_file); is_tempfile = FALSE; cf_set_tempfile((capture_file *)cap_session->cf, FALSE); } else { /* we didn't have a save_file before; must be a tempfile */ is_tempfile = TRUE; cf_set_tempfile((capture_file *)cap_session->cf, TRUE); } /* save the new filename */ capture_opts->save_file = g_strdup(new_file); /* if we are in real-time mode, open the new file now */ if(capture_opts->real_time_mode) { /* Attempt to open the capture file and set up to read from it. */ switch(cf_start_tail((capture_file *)cap_session->cf, capture_opts->save_file, is_tempfile, &err)) { case CF_OK: break; case CF_ERROR: /* Don't unlink (delete) the save file - leave it around, for debugging purposes. */ g_free(capture_opts->save_file); capture_opts->save_file = NULL; return FALSE; } } else { capture_callback_invoke(capture_cb_capture_prepared, cap_session); } if(capture_opts->show_info) { if (!capture_info_new_file(new_file)) return FALSE; } if(capture_opts->real_time_mode) { capture_callback_invoke(capture_cb_capture_update_started, cap_session); } else { capture_callback_invoke(capture_cb_capture_fixed_started, cap_session); } cap_session->state = CAPTURE_RUNNING; return TRUE; }
/** * Start a capture. * * @return TRUE if the capture starts successfully, FALSE otherwise. */ gboolean capture_start(capture_options *capture_opts, capture_session *cap_session) { gboolean ret; guint i; GString *source = g_string_new(""); cap_session->state = CAPTURE_PREPARING; g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start ..."); #ifdef _WIN32 if (capture_opts->ifaces->len < 2) { #else if (capture_opts->ifaces->len < 4) { #endif for (i = 0; i < capture_opts->ifaces->len; i++) { interface_options interface_opts; interface_opts = g_array_index(capture_opts->ifaces, interface_options, i); if (i > 0) { if (capture_opts->ifaces->len > 2) { g_string_append_printf(source, ","); } g_string_append_printf(source, " "); if (i == capture_opts->ifaces->len - 1) { g_string_append_printf(source, "and "); } } g_string_append_printf(source, "%s", get_iface_description_for_interface(capture_opts, i)); if ((interface_opts.cfilter != NULL) && (strlen(interface_opts.cfilter) > 0)) { g_string_append_printf(source, " (%s)", interface_opts.cfilter); } } } else { g_string_append_printf(source, "%u interfaces", capture_opts->ifaces->len); } cf_set_tempfile_source((capture_file *)cap_session->cf, source->str); g_string_free(source, TRUE); /* try to start the capture child process */ ret = sync_pipe_start(capture_opts, cap_session); if(!ret) { if(capture_opts->save_file != NULL) { g_free(capture_opts->save_file); capture_opts->save_file = NULL; } g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Start failed!"); cap_session->state = CAPTURE_STOPPED; } else { /* the capture child might not respond shortly after bringing it up */ /* (for example: it will block if no input arrives from an input capture pipe (e.g. mkfifo)) */ /* to prevent problems, bring the main GUI into "capture mode" right after a successful */ /* spawn/exec of the capture child, without waiting for any response from it */ capture_callback_invoke(capture_cb_capture_prepared, cap_session); if(capture_opts->show_info) capture_info_open(cap_session); } return ret; } void capture_stop(capture_session *cap_session) { g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Capture Stop ..."); capture_callback_invoke(capture_cb_capture_stopping, cap_session); /* stop the capture child gracefully */ sync_pipe_stop(cap_session); }