+/* one packet was captured, queue it */
+static void
+capture_loop_queue_packet_cb(u_char *pcap_opts_p, const struct pcap_pkthdr *phdr,
+ const u_char *pd)
+{
+ pcap_options *pcap_opts = (pcap_options *) (void *) pcap_opts_p;
+ pcap_queue_element *queue_element;
+ gboolean limit_reached;
+
+ /* We may be called multiple times from pcap_dispatch(); if we've set
+ the "stop capturing" flag, ignore this packet, as we're not
+ supposed to be saving any more packets. */
+ if (!global_ld.go)
+ return;
+
+ queue_element = (pcap_queue_element *)g_malloc(sizeof(pcap_queue_element));
+ if (queue_element == NULL) {
+ pcap_opts->dropped++;
+ return;
+ }
+ queue_element->pcap_opts = pcap_opts;
+ queue_element->phdr = *phdr;
+ queue_element->pd = (u_char *)g_malloc(phdr->caplen);
+ if (queue_element->pd == NULL) {
+ pcap_opts->dropped++;
+ g_free(queue_element);
+ return;
+ }
+ memcpy(queue_element->pd, pd, phdr->caplen);
+ g_async_queue_lock(pcap_queue);
+ if (((pcap_queue_byte_limit > 0) && (pcap_queue_bytes < pcap_queue_byte_limit)) &&
+ ((pcap_queue_packet_limit > 0) && (pcap_queue_packets < pcap_queue_packet_limit))) {
+ limit_reached = FALSE;
+ g_async_queue_push_unlocked(pcap_queue, queue_element);
+ pcap_queue_bytes += phdr->caplen;
+ pcap_queue_packets += 1;
+ } else {
+ limit_reached = TRUE;
+ }
+ g_async_queue_unlock(pcap_queue);
+ if (limit_reached) {
+ pcap_opts->dropped++;
+ g_free(queue_element->pd);
+ g_free(queue_element);
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
+ "Dropped a packet of length %d captured on interface %u.",
+ phdr->caplen, pcap_opts->interface_id);
+ } else {
+ pcap_opts->received++;
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
+ "Queued a packet of length %d captured on interface %u.",
+ phdr->caplen, pcap_opts->interface_id);
+ }
+ /* I don't want to hold the mutex over the debug output. So the
+ output may be wrong */
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO,
+ "Queue size is now %" G_GINT64_MODIFIER "d bytes (%" G_GINT64_MODIFIER "d packets)",
+ pcap_queue_bytes, pcap_queue_packets);
+}