-#ifdef MUST_DO_SELECT
- global_ld.pcap_fd = 0;
-#endif
- global_ld.autostop_files = 0;
- global_ld.save_file_fd = -1;
-
- /* We haven't yet gotten the capture statistics. */
- *stats_known = FALSE;
-
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop starting ...");
- capture_opts_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, capture_opts);
-
- /* open the "input file" from network interface or capture pipe */
- if (!capture_loop_open_input(capture_opts, &global_ld, errmsg, sizeof(errmsg),
- secondary_errmsg, sizeof(secondary_errmsg))) {
- goto error;
- }
-
- /* init the input filter from the network interface (capture pipe will do nothing) */
- switch (capture_loop_init_filter(global_ld.pcap_h, global_ld.from_cap_pipe,
- capture_opts->iface,
- capture_opts->cfilter)) {
-
- case INITFILTER_NO_ERROR:
- break;
-
- case INITFILTER_BAD_FILTER:
- cfilter_error = TRUE;
- g_snprintf(errmsg, sizeof(errmsg), "%s", pcap_geterr(global_ld.pcap_h));
- goto error;
-
- case INITFILTER_OTHER_ERROR:
- g_snprintf(errmsg, sizeof(errmsg), "Can't install filter (%s).",
- pcap_geterr(global_ld.pcap_h));
- g_snprintf(secondary_errmsg, sizeof(secondary_errmsg), "%s", please_report);
- goto error;
- }
-
- /* If we're supposed to write to a capture file, open it for output
- (temporary/specified name/ringbuffer) */
- if (capture_opts->saving_to_file) {
- if (!capture_loop_open_output(capture_opts, &global_ld.save_file_fd,
- errmsg, sizeof(errmsg))) {
- goto error;
+
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop running!");
+
+ /* WOW, everything is prepared! */
+ /* please fasten your seat belts, we will enter now the actual capture loop */
+ if (use_threads) {
+ pcap_queue = g_async_queue_new();
+ pcap_queue_bytes = 0;
+ pcap_queue_packets = 0;
+ for (i = 0; i < global_ld.pcaps->len; i++) {
+ pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i);
+#if GLIB_CHECK_VERSION(2,31,0)
+ /* XXX - Add an interface name here? */
+ pcap_opts->tid = g_thread_new("Capture read", pcap_read_handler, pcap_opts);
+#else
+ pcap_opts->tid = g_thread_create(pcap_read_handler, pcap_opts, TRUE, NULL);
+#endif
+ }
+ }
+ while (global_ld.go) {
+ /* dispatch incoming packets */
+ if (use_threads) {
+ GTimeVal write_thread_time;
+ pcap_queue_element *queue_element;
+
+ g_get_current_time(&write_thread_time);
+ g_time_val_add(&write_thread_time, WRITER_THREAD_TIMEOUT);
+ g_async_queue_lock(pcap_queue);
+ queue_element = g_async_queue_timed_pop_unlocked(pcap_queue, &write_thread_time);
+ if (queue_element) {
+ pcap_queue_bytes -= queue_element->phdr.caplen;
+ pcap_queue_packets -= 1;
+ }
+ g_async_queue_unlock(pcap_queue);
+ if (queue_element) {
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
+ "Dequeued a packet of length %d captured on interface %d.",
+ queue_element->phdr.caplen, queue_element->pcap_opts->interface_id);
+
+ capture_loop_write_packet_cb((u_char *) queue_element->pcap_opts,
+ &queue_element->phdr,
+ queue_element->pd);
+ g_free(queue_element->pd);
+ g_free(queue_element);
+ inpkts = 1;
+ } else {
+ inpkts = 0;
+ }
+ } else {
+ pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, 0);
+ inpkts = capture_loop_dispatch(&global_ld, errmsg,
+ sizeof(errmsg), pcap_opts);
+ }
+#ifdef SIGINFO
+ /* Were we asked to print packet counts by the SIGINFO handler? */
+ if (global_ld.report_packet_count) {
+ fprintf(stderr, "%u packet%s captured\n", global_ld.packet_count,
+ plurality(global_ld.packet_count, "", "s"));
+ global_ld.report_packet_count = FALSE;
+ }
+#endif
+
+#ifdef _WIN32
+ /* any news from our parent (signal pipe)? -> just stop the capture */
+ if (!signal_pipe_check_running()) {
+ global_ld.go = FALSE;
+ }
+#endif
+
+ if (inpkts > 0) {
+ global_ld.inpkts_to_sync_pipe += inpkts;
+
+ /* check capture size condition */
+ if (cnd_autostop_size != NULL &&
+ cnd_eval(cnd_autostop_size, (guint32)global_ld.bytes_written)) {
+ /* Capture size limit reached, do we have another file? */
+ if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files,
+ cnd_autostop_size, cnd_file_duration))
+ continue;
+ } /* cnd_autostop_size */
+ if (capture_opts->output_to_pipe) {
+ libpcap_dump_flush(global_ld.pdh, NULL);
+ }
+ } /* inpkts */
+
+ /* Only update once every 500ms so as not to overload slow displays.
+ * This also prevents too much context-switching between the dumpcap
+ * and wireshark processes.
+ */
+#define DUMPCAP_UPD_TIME 500
+
+#ifdef WIN32
+ cur_time = GetTickCount(); /* Note: wraps to 0 if sys runs for 49.7 days */
+ if ((cur_time - upd_time) > DUMPCAP_UPD_TIME) { /* wrap just causes an extra update */
+#else
+ gettimeofday(&cur_time, NULL);
+ if ((cur_time.tv_sec * 1000000 + cur_time.tv_usec) >
+ (upd_time.tv_sec * 1000000 + upd_time.tv_usec + DUMPCAP_UPD_TIME*1000)) {
+#endif
+
+ upd_time = cur_time;
+
+#if 0
+ if (pcap_stats(pch, stats) >= 0) {
+ *stats_known = TRUE;
+ }
+#endif
+ /* Let the parent process know. */
+ if (global_ld.inpkts_to_sync_pipe) {
+ /* do sync here */
+ libpcap_dump_flush(global_ld.pdh, NULL);
+
+ /* Send our parent a message saying we've written out
+ "global_ld.inpkts_to_sync_pipe" packets to the capture file. */
+ if (!quiet)
+ report_packet_count(global_ld.inpkts_to_sync_pipe);
+
+ global_ld.inpkts_to_sync_pipe = 0;
+ }
+
+ /* check capture duration condition */
+ if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) {
+ /* The maximum capture time has elapsed; stop the capture. */
+ global_ld.go = FALSE;
+ continue;
+ }
+
+ /* check capture file duration condition */
+ if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
+ /* duration limit reached, do we have another file? */
+ if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files,
+ cnd_autostop_size, cnd_file_duration))
+ continue;
+ } /* cnd_file_duration */
+ }