22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
35 #include "dnsqr.pb-c.h"
37 #include "libmy/list.h"
38 #include "libmy/lookup3.h"
39 #include "libmy/my_alloc.h"
40 #include "libmy/string_replace.h"
41 #include "libmy/ubuf.h"
45 #define DEFAULT_NUM_SLOTS 262144
46 #define DEFAULT_MAX_VALUES 131072
47 #define DEFAULT_QUERY_TIMEOUT 60
49 #define DNS_FLAG_QR(flags) (((flags) >> 15) & 0x01)
50 #define DNS_FLAG_RD(flags) (((flags) >> 8) & 0x01)
51 #define DNS_FLAG_RCODE(flags) ((flags) & 0xf)
55 typedef struct list_entry list_entry_t;
56 typedef struct hash_entry hash_entry_t;
59 ISC_LINK(
struct list_entry) link;
64 Nmsg__Base__DnsQR *dnsqr;
72 ISC_LIST(
struct list_entry) list;
73 struct reasm_ip *reasm;
80 bool zero_resolver_address;
84 uint32_t query_timeout;
87 uint32_t count_unanswered_query;
88 uint32_t count_unsolicited_response;
89 uint32_t count_query_response;
90 uint32_t count_packet;
94 wdns_name_t **filter_qnames_exclude;
95 uint32_t filter_qnames_exclude_slots;
97 wdns_name_t **filter_qnames_include;
98 uint32_t filter_qnames_include_slots;
103 uint32_t response_ip;
106 uint16_t response_port;
111 uint8_t query_ip6[16];
112 uint8_t response_ip6[16];
115 uint16_t response_port;
129 } __attribute__((__packed__)) udp_pseudo_ipv4;
141 } __attribute__((__packed__)) udp_pseudo_ipv6;
143 typedef
nmsg_res (*dnsqr_append_fp)(Nmsg__Base__DnsQR *dnsqr,
144 const uint8_t *pkt,
size_t pkt_len,
145 const struct timespec *ts);
149 static
nmsg_res dnsqr_init(
void **clos);
150 static
nmsg_res dnsqr_fini(
void **clos);
151 static
nmsg_res dnsqr_pcap_init(
void *clos, nmsg_pcap_t pcap);
152 static
nmsg_res dnsqr_pkt_to_payload(
void *clos, nmsg_pcap_t pcap, nmsg_message_t *m);
154 static NMSG_MSGMOD_FIELD_PRINTER(dnsqr_proto_print);
155 static NMSG_MSGMOD_FIELD_PRINTER(dnsqr_message_print);
156 static NMSG_MSGMOD_FIELD_PRINTER(dnsqr_rcode_print);
157 static NMSG_MSGMOD_FIELD_GETTER(dnsqr_get_delay);
158 static NMSG_MSGMOD_FIELD_GETTER(dnsqr_get_query);
159 static NMSG_MSGMOD_FIELD_GETTER(dnsqr_get_response);
160 static NMSG_MSGMOD_FIELD_GETTER(dnsqr_get_udp_checksum);
175 .name =
"response_ip"
179 .print = dnsqr_proto_print
187 .name =
"response_port"
195 .print = dns_name_print
200 .print = dns_class_print
205 .print = dns_type_print
210 .print = dnsqr_rcode_print
214 .name =
"query_packet",
219 .name =
"query_time_sec",
224 .name =
"query_time_nsec",
229 .name =
"response_packet",
234 .name =
"response_time_sec",
239 .name =
"response_time_nsec",
249 .get = dnsqr_get_delay
253 .name =
"udp_checksum",
254 .get = dnsqr_get_udp_checksum
258 .name =
"resolver_address_zeroed"
263 .get = dnsqr_get_query,
264 .print = dnsqr_message_print
269 .get = dnsqr_get_response,
270 .print = dnsqr_message_print
275 .get = dnsqr_get_response,
288 NMSG_MSGMOD_FIELD_END
294 NMSG_MSGMOD_REQUIRED_INIT,
295 .vendor = NMSG_VENDOR_BASE,
296 .msgtype = { NMSG_VENDOR_BASE_DNSQR_ID, NMSG_VENDOR_BASE_DNSQR_NAME },
298 .pbdescr = &nmsg__base__dns_qr__descriptor,
299 .fields = dnsqr_fields,
302 .pkt_to_payload = dnsqr_pkt_to_payload,
303 .pcap_init = dnsqr_pcap_init,
308 static void dnsqr_print_stats(dnsqr_ctx_t *ctx);
313 dnsqr_checksum_verify(Nmsg__Base__DnsQR *dnsqr) {
324 size_t pseudo_len = 0;
328 if (dnsqr->has_resolver_address_zeroed &&
329 dnsqr->resolver_address_zeroed)
331 return (NMSG__BASE__UDP_CHECKSUM__ERROR);
335 for (
unsigned r = 0; r < dnsqr->n_response_packet; r++) {
336 uint8_t *data = NULL;
337 ssize_t data_len = 0;
339 ip = (
struct nmsg_iphdr *) dnsqr->response_packet[r].data;
340 ip_len = dnsqr->response_packet[r].len;
344 return (NMSG__BASE__UDP_CHECKSUM__ERROR);
346 if (dg.proto_network == PF_INET && dg.proto_transport == IPPROTO_UDP) {
347 data = (uint8_t *) dg.payload;
348 data_len = dg.len_payload;
350 if (dg.transport != NULL) {
353 return (NMSG__BASE__UDP_CHECKSUM__ERROR);
356 pseudo_len =
sizeof(ph);
357 memset(&ph, 0,
sizeof(ph));
360 if (udp->uh_sum == 0)
361 return (NMSG__BASE__UDP_CHECKSUM__ABSENT);
364 memcpy(&ph.src[0], &ip->ip_src, 4);
365 memcpy(&ph.dst[0], &ip->ip_dst, 4);
366 memcpy(&ph.proto, &ip->ip_p, 1);
367 memcpy(&ph.udp_len, &udp->uh_ulen, 2);
368 memcpy(&ph.src_port, &udp->uh_sport, 2);
369 memcpy(&ph.dst_port, &udp->uh_dport, 2);
370 memcpy(&ph.length, &udp->uh_ulen, 2);
371 memcpy(&ph.checksum, &udp->uh_sum, 2);
373 }
else if (dg.proto_network == PF_INET6 && dg.proto_transport == IPPROTO_UDP) {
374 data = (uint8_t *) dg.payload;
375 data_len = dg.len_payload;
377 if (dg.transport != NULL) {
380 return (NMSG__BASE__UDP_CHECKSUM__ERROR);
382 p = (uint8_t *) &ph6;
383 pseudo_len =
sizeof(ph6);
385 struct ip6_hdr *ip6 = (
struct ip6_hdr *) (dg.network);
386 memset(&ph6, 0,
sizeof(ph6));
388 if (udp->uh_sum == 0)
389 return (NMSG__BASE__UDP_CHECKSUM__ABSENT);
392 memcpy(&ph6.src[0], &ip6->ip6_src, 16);
393 memcpy(&ph6.dst[0], &ip6->ip6_dst, 16);
394 memcpy(&ph6.src_port, &udp->uh_sport, 2);
395 memcpy(&ph6.dst_port, &udp->uh_dport, 2);
396 memcpy(&ph6.length, &udp->uh_ulen, 2);
397 memcpy(&ph6.checksum, &udp->uh_sum, 2);
399 memcpy(&word, &udp->uh_ulen, 2);
400 ph6.upper_len = (uint32_t) word;
401 ph6.next = IPPROTO_UDP;
404 return (NMSG__BASE__UDP_CHECKSUM__ERROR);
408 return (NMSG__BASE__UDP_CHECKSUM__ERROR);
411 for (
int i = 0; i < data_len - 1; i += 2) {
412 memcpy(&word, data + i, 2);
417 if ((data_len & 1) == 1) {
418 word = (data[data_len - 1] << 8) & 0xff00;
426 return (NMSG__BASE__UDP_CHECKSUM__ERROR);
429 for (
int i = 0; i < (ssize_t) pseudo_len; i += 2) {
430 memcpy(&word, p + i, 2);
436 sum = (sum & 0xffff) + (sum >> 16);
437 sum = (uint16_t) ~sum;
441 return (NMSG__BASE__UDP_CHECKSUM__CORRECT);
442 return (NMSG__BASE__UDP_CHECKSUM__INCORRECT);
446 dnsqr_zero_resolver_address(Nmsg__Base__DnsQR *dnsqr) {
451 dnsqr->resolver_address_zeroed =
true;
452 dnsqr->has_resolver_address_zeroed =
true;
455 memset(dnsqr->query_ip.data, 0, dnsqr->query_ip.len);
458 for (
unsigned i = 0; i < dnsqr->n_query_packet; i++) {
459 ip = (
struct nmsg_iphdr *) dnsqr->query_packet[i].data;
460 ip_len = dnsqr->query_packet[i].len;
464 memset(&ip->ip_src, 0, 4);
465 }
else if (ip->ip_v == 6) {
466 ip6 = (
struct ip6_hdr *) ip;
467 if (ip_len >=
sizeof(
struct ip6_hdr))
468 memset(&ip6->ip6_src, 0, 16);
473 for (
unsigned i = 0; i < dnsqr->n_response_packet; i++) {
474 ip = (
struct nmsg_iphdr *) dnsqr->response_packet[i].data;
475 ip_len = dnsqr->response_packet[i].len;
479 memset(&ip->ip_dst, 0, 4);
480 }
else if (ip->ip_v == 6) {
481 ip6 = (
struct ip6_hdr *) ip;
482 if (ip_len >=
sizeof(
struct ip6_hdr))
483 memset(&ip6->ip6_dst, 0, 16);
489 getenv_int(
const char *name, int64_t *value) {
496 *value = strtol(s, &t, 0);
503 dnsqr_filter_lookup(wdns_name_t **table, uint32_t num_slots, wdns_name_t *name) {
504 unsigned slot, slot_stop;
506 slot = my_hashlittle(name->data, name->len, 0) % num_slots;
508 slot_stop = slot - 1;
510 slot_stop = num_slots - 1;
513 wdns_name_t *ent = table[slot];
521 ent->len == name->len &&
522 memcmp(ent->data, name->data, name->len) == 0)
528 assert(slot != slot_stop);
530 if (slot >= num_slots)
536 dnsqr_filter_insert(wdns_name_t **table, uint32_t num_slots, wdns_name_t *name) {
537 unsigned slot, slot_stop;
540 slot = my_hashlittle(name->data, name->len, 0) % num_slots;
542 slot_stop = slot - 1;
544 slot_stop = num_slots - 1;
556 assert(slot != slot_stop);
558 if (slot >= num_slots)
564 dnsqr_filter_init(
const char *env_var, wdns_name_t ***table, uint32_t *num_slots) {
565 char *names, *saveptr, *token;
569 if (getenv(env_var) == NULL)
574 names = strdup(getenv(env_var));
575 assert(names != NULL);
577 for (i = 0; i < strlen(names); i++) {
582 *num_slots = num_names * 2;
584 *table = my_calloc(1,
sizeof(
void *) * *num_slots);
586 token = strtok_r(names,
":", &saveptr);
591 name = my_malloc(
sizeof(*name));
592 res = wdns_str_to_name(token, name);
593 if (res == wdns_res_success) {
594 wdns_downcase_name(name);
595 dnsqr_filter_insert(*table, *num_slots, name);
599 "%s: wdns_str_to_name() failed, token='%s' res=%d\n",
600 __func__, token, res);
603 }
while ((token = strtok_r(NULL,
":", &saveptr)) != NULL);
609 dnsqr_filter_destroy(wdns_name_t **table, uint32_t num_slots) {
612 for (i = 0; i < num_slots; i++) {
613 if (table[i] != NULL) {
614 free(table[i]->data);
622 dnsqr_init(
void **clos) {
624 int64_t qr, rd, max, timeout, zero;
626 ctx = my_calloc(1,
sizeof(*ctx));
627 pthread_mutex_init(&ctx->lock, NULL);
629 ctx->reasm = reasm_ip_new();
630 assert(ctx->reasm != NULL);
632 ISC_LIST_INIT(ctx->list);
634 if (getenv_int(
"DNSQR_CAPTURE_QR", &qr) &&
635 (qr == 0 || qr == 1))
637 ctx->capture_qr = qr;
639 ctx->capture_qr = -1;
642 if (getenv_int(
"DNSQR_CAPTURE_RD", &rd) &&
643 (rd == 0 || rd == 1))
645 ctx->capture_rd = rd;
647 ctx->capture_rd = -1;
650 if (getenv_int(
"DNSQR_ZERO_RESOLVER_ADDRESS", &zero) && zero)
651 ctx->zero_resolver_address =
true;
653 if (getenv_int(
"DNSQR_STATE_TABLE_MAX", &max) && max > 0) {
654 ctx->max_values = max;
655 ctx->num_slots = ctx->max_values * 2;
657 ctx->num_slots = DEFAULT_NUM_SLOTS;
658 ctx->max_values = DEFAULT_MAX_VALUES;
661 if (getenv_int(
"DNSQR_QUERY_TIMEOUT", &timeout) && timeout > 0)
662 ctx->query_timeout = timeout;
664 ctx->query_timeout = DEFAULT_QUERY_TIMEOUT;
666 dnsqr_filter_init(
"DNSQR_FILTER_QNAMES_INCLUDE",
667 &ctx->filter_qnames_include,
668 &ctx->filter_qnames_include_slots);
669 dnsqr_filter_init(
"DNSQR_FILTER_QNAMES_EXCLUDE",
670 &ctx->filter_qnames_exclude,
671 &ctx->filter_qnames_exclude_slots);
673 ctx->len_table =
sizeof(hash_entry_t) * ctx->num_slots;
675 ctx->table = mmap(NULL, ctx->len_table,
676 PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
677 assert(ctx->table != MAP_FAILED);
684 dnsqr_fini(
void **clos) {
688 ctx = (dnsqr_ctx_t *) *clos;
690 for (n = 0; n < ctx->num_slots; n++) {
691 hash_entry_t *he = &ctx->table[n];
692 if (he->dnsqr != NULL)
693 nmsg__base__dns_qr__free_unpacked(he->dnsqr, NULL);
696 dnsqr_filter_destroy(ctx->filter_qnames_include, ctx->filter_qnames_include_slots);
697 dnsqr_filter_destroy(ctx->filter_qnames_exclude, ctx->filter_qnames_exclude_slots);
699 dnsqr_print_stats(ctx);
701 reasm_ip_free(ctx->reasm);
703 munmap(ctx->table, ctx->len_table);
711 get_af(
const char *addr) {
718 slash = strchr(s,
'/');
721 if (inet_pton(AF_INET, s, buf) == 1) {
723 }
else if (inet_pton(AF_INET6, s, buf) == 1) {
733 addrs_to_bpf(
const char *addrs,
const char *bpfdir,
int af) {
734 char *ret, *tok_addrs, *addr, *saveptr;
740 tok_addrs = strdup(addrs);
741 assert(tok_addrs != NULL);
743 addr = strtok_r(tok_addrs,
",", &saveptr);
746 while (isspace(addr[0]))
749 size_t i = strlen(addr);
751 if (isspace(addr[i]))
757 addr_af = get_af(addr);
760 if (addr_af != AF_INET && addr_af != AF_INET6) {
766 if (ubuf_size(bpf) > 0)
767 ubuf_add_cstr(bpf,
" or ");
768 ubuf_add_cstr(bpf, bpfdir);
769 ubuf_add_cstr(bpf,
" ");
770 if (strchr(addr,
'/') != NULL)
771 ubuf_add_cstr(bpf,
"net ");
772 ubuf_add_cstr(bpf, addr);
773 }
while ((addr = strtok_r(NULL,
",", &saveptr)) != NULL);
777 ubuf_detach(bpf, (uint8_t **) &ret, &retsz);
782 #define ipv4_frags "(ip[6:2] & 0x3fff != 0)"
783 #define udp_qr_query "(((udp[10:2] >> 15) & 0x01) == 0)"
784 #define udp_qr_response "(((udp[10:2] >> 15) & 0x01) == 1)"
786 static const char *s_pattern_auth4 =
788 "((@DST@) and udp dst port 53) or "
789 "((@SRC@) and udp src port 53) or "
790 "((@SRC@) and " ipv4_frags
") or "
793 static const char *s_pattern_auth4_queries =
795 "(@DST@) and udp dst port 53 and " udp_qr_query
797 static const char *s_pattern_auth4_responses =
799 "((@SRC@) and udp src port 53 and " udp_qr_response
") or "
800 "((@SRC@) and " ipv4_frags
")"
803 static const char *s_pattern_res4 =
805 "((@SRC@) and udp dst port 53) or "
806 "((@DST@) and udp src port 53) or "
807 "((@DST@) and " ipv4_frags
") or "
810 static const char *s_pattern_res4_queries =
811 "((@SRC@) and udp dst port 53 and " udp_qr_query
")";
812 static const char *s_pattern_res4_responses =
814 "((@DST@) and udp src port 53 and " udp_qr_response
") or "
815 "((@DST@) and " ipv4_frags
")"
820 #undef udp_qr_response
822 static const char *s_pattern_auth6 =
823 "((@DST@) or (@SRC@))";
825 static const char *s_pattern_res6 =
826 "((@SRC@) or (@DST@))";
829 bpf_replace(
const char *s_pattern,
const char *bpf_src,
const char *bpf_dst) {
831 rep0 = string_replace(s_pattern,
"@SRC@", bpf_src);
832 rep1 = string_replace(rep0,
"@DST@", bpf_dst);
838 dnsqr_pcap_init(
void *clos, nmsg_pcap_t pcap) {
839 dnsqr_ctx_t *ctx = (dnsqr_ctx_t *) clos;
840 const char *auth_addrs = NULL;
841 const char *res_addrs = NULL;
844 bool do_auth4 =
false;
845 bool do_auth6 =
false;
846 bool do_res4 =
false;
847 bool do_res6 =
false;
850 char *bpf_auth = NULL;
851 char *bpf_auth4 = NULL;
852 char *bpf_auth4_dst = NULL;
853 char *bpf_auth4_src = NULL;
854 char *bpf_auth6 = NULL;
855 char *bpf_auth6_dst = NULL;
856 char *bpf_auth6_src = NULL;
857 char *bpf_res = NULL;
858 char *bpf_res4 = NULL;
859 char *bpf_res4_dst = NULL;
860 char *bpf_res4_src = NULL;
861 char *bpf_res6 = NULL;
862 char *bpf_res6_dst = NULL;
863 char *bpf_res6_src = NULL;
867 auth_addrs = getenv(
"DNSQR_AUTH_ADDRS");
869 bpf_auth4_src = addrs_to_bpf(auth_addrs,
"src", AF_INET);
870 bpf_auth4_dst = addrs_to_bpf(auth_addrs,
"dst", AF_INET);
871 bpf_auth6_src = addrs_to_bpf(auth_addrs,
"src", AF_INET6);
872 bpf_auth6_dst = addrs_to_bpf(auth_addrs,
"dst", AF_INET6);
874 if (bpf_auth4_src == NULL ||
875 bpf_auth4_dst == NULL ||
876 bpf_auth6_src == NULL ||
877 bpf_auth6_dst == NULL)
883 do_auth4 = (strlen(bpf_auth4_src) > 0) ?
true :
false;
884 do_auth6 = (strlen(bpf_auth6_src) > 0) ?
true :
false;
887 if (ctx->capture_qr == -1) {
888 bpf_auth4 = bpf_replace(s_pattern_auth4,
891 }
else if (ctx->capture_qr == 0) {
892 bpf_auth4 = bpf_replace(s_pattern_auth4_queries,
895 }
else if (ctx->capture_qr == 1) {
896 bpf_auth4 = bpf_replace(s_pattern_auth4_responses,
902 bpf_auth6 = bpf_replace(s_pattern_auth6, bpf_auth6_src, bpf_auth6_dst);
904 nmsg_asprintf(&bpf_auth,
"%s%s%s",
905 (do_auth4) ? bpf_auth4 :
"",
906 (do_auth4 && do_auth6) ?
" or " :
"",
907 (do_auth6) ? bpf_auth6 :
""
909 assert(bpf_auth != NULL);
912 res_addrs = getenv(
"DNSQR_RES_ADDRS");
914 bpf_res4_src = addrs_to_bpf(res_addrs,
"src", AF_INET);
915 bpf_res4_dst = addrs_to_bpf(res_addrs,
"dst", AF_INET);
916 bpf_res6_src = addrs_to_bpf(res_addrs,
"src", AF_INET6);
917 bpf_res6_dst = addrs_to_bpf(res_addrs,
"dst", AF_INET6);
919 if (bpf_res4_src == NULL ||
920 bpf_res4_dst == NULL ||
921 bpf_res6_src == NULL ||
922 bpf_res6_dst == NULL)
928 do_res4 = (strlen(bpf_res4_src) > 0) ?
true :
false;
929 do_res6 = (strlen(bpf_res6_src) > 0) ?
true :
false;
932 if (ctx->capture_qr == -1) {
933 bpf_res4 = bpf_replace(s_pattern_res4,
936 }
else if (ctx->capture_qr == 0) {
937 bpf_res4 = bpf_replace(s_pattern_res4_queries,
940 }
else if (ctx->capture_qr == 1) {
941 bpf_res4 = bpf_replace(s_pattern_res4_responses,
947 bpf_res6 = bpf_replace(s_pattern_res6, bpf_res6_src, bpf_res6_dst);
949 nmsg_asprintf(&bpf_res,
"%s%s%s",
950 (do_res4) ? bpf_res4 :
"",
951 (do_res4 && do_res6) ?
" or " :
"",
952 (do_res6) ? bpf_res6 :
"");
953 assert(bpf_res != NULL);
956 if (!auth_addrs && !res_addrs)
959 nmsg_asprintf(&bpf,
"%s%s%s",
960 (bpf_auth != NULL) ? bpf_auth :
"",
961 ((bpf_auth != NULL) && (bpf_res != NULL)) ?
" or " :
"",
962 (bpf_res != NULL) ? bpf_res :
"");
987 dnsqr_proto_print(nmsg_message_t msg,
995 proto = *((uint16_t *) ptr);
1010 dnsqr_message_print(nmsg_message_t msg,
1014 const char *endline)
1016 ProtobufCBinaryData *bdata;
1021 bdata = (ProtobufCBinaryData *) ptr;
1025 status = wdns_parse_message(&dns, bdata->data, bdata->len);
1026 if (status == wdns_res_success) {
1029 s = wdns_message_to_str(&dns);
1032 field->
name, bdata->len, endline, s, endline);
1034 wdns_clear_message(&dns);
1037 wdns_clear_message(&dns);
1044 dnsqr_rcode_print(nmsg_message_t msg,
1048 const char *endline)
1051 uint16_t *rcode = ptr;
1053 s = wdns_rcode_to_str(*rcode);
1056 s ? s :
"<UNKNOWN>",
1061 dnsqr_get_udp_checksum(nmsg_message_t msg,
1070 if (dnsqr == NULL || val_idx != 0 || dnsqr->n_response_packet <= 0)
1073 if (!dnsqr->has_udp_checksum)
1074 dnsqr->udp_checksum = dnsqr_checksum_verify(dnsqr);
1075 *data = (
void *) &dnsqr->udp_checksum;
1077 *len =
sizeof(dnsqr->udp_checksum);
1083 dnsqr_get_delay(nmsg_message_t msg,
1093 struct timespec ts_delay;
1095 if (dnsqr == NULL || val_idx != 0 ||
1096 dnsqr->type != NMSG__BASE__DNS_QRTYPE__UDP_QUERY_RESPONSE)
1099 if ((dnsqr->n_query_time_sec != dnsqr->n_query_time_nsec) ||
1100 dnsqr->n_query_time_sec != 1)
1103 if ((dnsqr->n_response_time_sec != dnsqr->n_response_time_nsec) ||
1104 dnsqr->n_response_time_sec < 1)
1107 if (dnsqr->n_response_time_sec == 1) {
1108 ts_delay.tv_sec = dnsqr->response_time_sec[0] - dnsqr->query_time_sec[0];
1109 ts_delay.tv_nsec = dnsqr->response_time_nsec[0] - dnsqr->query_time_nsec[0];
1110 if (ts_delay.tv_nsec < 0) {
1111 ts_delay.tv_sec -= 1;
1112 ts_delay.tv_nsec += 1000000000;
1114 delay = ts_delay.tv_sec + ts_delay.tv_nsec / 1E9;
1116 double max_delay = 0.0;
1118 for (
unsigned i = 0; i < dnsqr->n_response_time_sec; i++) {
1119 ts_delay.tv_sec = dnsqr->response_time_sec[i] - dnsqr->query_time_sec[0];
1120 ts_delay.tv_nsec = dnsqr->response_time_nsec[i] - dnsqr->query_time_nsec[0];
1121 if (ts_delay.tv_nsec < 0) {
1122 ts_delay.tv_sec -= 1;
1123 ts_delay.tv_nsec += 1000000000;
1125 delay = ts_delay.tv_sec + ts_delay.tv_nsec / 1E9;
1127 if (delay > max_delay)
1133 pdelay = my_malloc(
sizeof(
double));
1136 *data = (
void *) pdelay;
1138 *len =
sizeof(double);
1144 dnsqr_get_query(nmsg_message_t msg,
1156 if (dnsqr == NULL || val_idx != 0 || dnsqr->n_query_packet != 1)
1159 if (dnsqr->query_ip.data != NULL) {
1160 if (dnsqr->query_ip.len == 4)
1162 dnsqr->query_packet[0].len,
1163 dnsqr->query_packet[0].data);
1164 else if (dnsqr->query_ip.len == 16)
1166 dnsqr->query_packet[0].len,
1167 dnsqr->query_packet[0].data);
1173 *data = (
void *) dg.payload;
1175 *len = dg.len_payload;
1181 dnsqr_get_response(nmsg_message_t msg,
1195 if (dnsqr == NULL || val_idx != 0 || dnsqr->n_response_packet < 1)
1198 if (dnsqr->response_ip.data == NULL)
1201 if (dnsqr->n_response_packet > 1) {
1203 enum reasm_proto proto;
1209 struct reasm_frag_entry *frag, *list_head;
1210 struct reasm_ip_entry *entry;
1212 list_head = my_calloc(1,
sizeof(*list_head));
1213 entry = my_calloc(1,
sizeof(*entry));
1215 entry->frags = list_head;
1218 for (n = 0; n < dnsqr->n_response_packet; n++) {
1219 ts.tv_sec = dnsqr->response_time_sec[n];
1220 ts.tv_nsec = dnsqr->response_time_nsec[n];
1222 frag = reasm_parse_packet(dnsqr->response_packet[n].data,
1223 dnsqr->response_packet[n].len,
1224 &ts, &proto, &
id, &hash, &last_frag);
1225 entry->protocol = proto;
1227 reasm_add_fragment(entry, frag, last_frag) ==
false)
1229 reasm_free_entry(entry);
1233 if (reasm_is_complete(entry)) {
1239 reasm_free_entry(entry);
1243 reasm_assemble(entry, pkt, &pkt_len);
1246 reasm_free_entry(entry);
1250 if (proto == PROTO_IPV4) {
1252 }
else if (proto == PROTO_IPV6) {
1258 reasm_free_entry(entry);
1260 reasm_free_entry(entry);
1265 pkt = dnsqr->response_packet[0].data;
1266 pkt_len = dnsqr->response_packet[0].len;
1267 if (dnsqr->response_ip.len == 4)
1269 else if (dnsqr->response_ip.len == 16)
1276 *data = (
void *) dg.payload;
1278 *len = dg.len_payload;
1284 dnsqr_eq6(Nmsg__Base__DnsQR *d1, Nmsg__Base__DnsQR *d2) {
1285 if (d1->id == d2->id &&
1286 d1->query_port == d2->query_port &&
1287 d1->response_port == d2->response_port &&
1288 d1->proto == d2->proto &&
1289 d1->query_ip.len == d2->query_ip.len &&
1290 d1->response_ip.len == d2->response_ip.len)
1292 if (memcmp(d1->query_ip.data, d2->query_ip.data, d1->query_ip.len) == 0 &&
1293 memcmp(d1->response_ip.data, d2->response_ip.data, d1->response_ip.len) == 0)
1303 dnsqr_eq9(Nmsg__Base__DnsQR *d1, Nmsg__Base__DnsQR *d2) {
1304 if (d1->id == d2->id &&
1305 d1->query_port == d2->query_port &&
1306 d1->response_port == d2->response_port &&
1307 d1->qname.len == d2->qname.len &&
1308 d1->qtype == d2->qtype &&
1309 d1->qclass == d2->qclass &&
1310 d1->proto == d2->proto &&
1311 d1->query_ip.len == d2->query_ip.len &&
1312 d1->response_ip.len == d2->response_ip.len)
1314 if (memcmp(d1->query_ip.data, d2->query_ip.data, d1->query_ip.len) == 0 &&
1315 memcmp(d1->response_ip.data, d2->response_ip.data, d1->response_ip.len) == 0 &&
1316 memcmp(d1->qname.data, d2->qname.data, d1->qname.len) == 0)
1326 dnsqr_eq(Nmsg__Base__DnsQR *d1, Nmsg__Base__DnsQR *d2, uint16_t rcode) {
1327 if (d1->qname.data != NULL && d2->qname.data != NULL) {
1328 return (dnsqr_eq9(d1, d2));
1331 case WDNS_R_FORMERR:
1332 case WDNS_R_SERVFAIL:
1334 case WDNS_R_REFUSED:
1335 return (dnsqr_eq6(d1, d2));
1342 dnsqr_hash(Nmsg__Base__DnsQR *dnsqr) {
1349 assert(dnsqr->query_ip.len == 4 || dnsqr->query_ip.len == 16);
1350 assert(dnsqr->response_ip.len == 4 || dnsqr->response_ip.len == 16);
1352 if (dnsqr->query_ip.len == 4) {
1353 memcpy(&key.query_ip, dnsqr->query_ip.data, 4);
1354 memcpy(&key.response_ip, dnsqr->response_ip.data, 4);
1355 key.proto = dnsqr->proto;
1356 key.query_port = dnsqr->query_port;
1357 key.response_port = dnsqr->response_port;
1361 }
else if (dnsqr->query_ip.len == 16) {
1362 memcpy(&key6.query_ip6, dnsqr->query_ip.data, 16);
1363 memcpy(&key6.response_ip6, dnsqr->response_ip.data, 16);
1364 key6.proto = dnsqr->proto;
1365 key6.query_port = dnsqr->query_port;
1366 key6.response_port = dnsqr->response_port;
1367 key6.id = dnsqr->id;
1374 hash = my_hashlittle(k, len, 0);
1379 dnsqr_insert_query(dnsqr_ctx_t *ctx, Nmsg__Base__DnsQR *dnsqr) {
1382 unsigned slot, slot_stop;
1384 hash = dnsqr_hash(dnsqr);
1385 slot = hash % ctx->num_slots;
1388 slot_stop = slot - 1;
1390 slot_stop = ctx->num_slots - 1;
1393 pthread_mutex_lock(&ctx->lock);
1396 hash_entry_t *he = &ctx->table[slot];
1399 if (he->dnsqr == NULL) {
1403 le = my_calloc(1,
sizeof(*le));
1406 ISC_LINK_INIT(le, link);
1407 ISC_LIST_APPEND(ctx->list, le, link);
1412 assert(slot != slot_stop);
1414 if (slot >= ctx->num_slots)
1419 pthread_mutex_unlock(&ctx->lock);
1423 dnsqr_remove(dnsqr_ctx_t *ctx, hash_entry_t *he) {
1427 i = j = slot = (he - ctx->table);
1429 assert(he->dnsqr != NULL);
1432 ISC_LIST_UNLINK(ctx->list, he->le, link);
1438 j = (j + 1) % ctx->num_slots;
1439 if (ctx->table[j].dnsqr == NULL) {
1445 k = dnsqr_hash(ctx->table[j].dnsqr) % ctx->num_slots;
1446 if ((j > i && (k <= i || k > j)) ||
1447 (j < i && (k <= i && k > j)))
1451 memcpy(&ctx->table[i], &ctx->table[j],
sizeof(hash_entry_t));
1454 memset(&ctx->table[j], 0,
sizeof(hash_entry_t));
1457 ctx->table[i].le->he = &ctx->table[i];
1465 static Nmsg__Base__DnsQR *
1466 dnsqr_trim(dnsqr_ctx_t *ctx) {
1467 Nmsg__Base__DnsQR *dnsqr = NULL;
1470 struct timespec timeout;
1473 pthread_mutex_lock(&ctx->lock);
1475 le = ISC_LIST_HEAD(ctx->list);
1478 assert(le->he != NULL);
1480 assert(he->dnsqr != NULL);
1481 assert(he->dnsqr->n_query_time_sec > 0);
1482 assert(he->dnsqr->n_query_time_nsec > 0);
1483 if (ctx->count > ctx->max_values ||
1484 ctx->stop ==
true ||
1485 ctx->now.tv_sec - he->dnsqr->query_time_sec[0] > ctx->query_timeout)
1488 dnsqr_remove(ctx, he);
1490 timeout.tv_sec = ctx->now.tv_sec - dnsqr->query_time_sec[0];
1491 timeout.tv_nsec = ctx->now.tv_nsec - dnsqr->query_time_nsec[0];
1492 if (timeout.tv_nsec < 0) {
1493 timeout.tv_sec -= 1;
1494 timeout.tv_nsec += 1000000000;
1496 dnsqr->timeout = timeout.tv_sec + (((double) timeout.tv_nsec) / 1E9);
1497 dnsqr->has_timeout =
true;
1500 ctx->count_unanswered_query += 1;
1506 pthread_mutex_unlock(&ctx->lock);
1511 static Nmsg__Base__DnsQR *
1512 dnsqr_retrieve(dnsqr_ctx_t *ctx, Nmsg__Base__DnsQR *dnsqr, uint16_t rcode) {
1513 Nmsg__Base__DnsQR *query = NULL;
1515 unsigned slot, slot_stop;
1517 hash = dnsqr_hash(dnsqr);
1518 slot = hash % ctx->num_slots;
1521 slot_stop = slot - 1;
1523 slot_stop = ctx->num_slots - 1;
1526 pthread_mutex_lock(&ctx->lock);
1529 hash_entry_t *he = &ctx->table[slot];
1532 if (he->dnsqr == NULL) {
1538 if (dnsqr_eq(dnsqr, he->dnsqr, rcode) ==
true) {
1540 dnsqr_remove(ctx, he);
1545 assert(slot != slot_stop);
1547 if (slot >= ctx->num_slots)
1553 pthread_mutex_unlock(&ctx->lock);
1558 static nmsg_message_t
1559 dnsqr_to_message(dnsqr_ctx_t *ctx, Nmsg__Base__DnsQR *dnsqr) {
1560 ProtobufCBufferSimple sbuf;
1565 if (dnsqr->n_response_packet > 0) {
1566 dnsqr->udp_checksum = dnsqr_checksum_verify(dnsqr);
1567 dnsqr->has_udp_checksum =
true;
1570 if (ctx->zero_resolver_address)
1571 dnsqr_zero_resolver_address(dnsqr);
1573 sbuf.base.append = protobuf_c_buffer_simple_append;
1575 sbuf.data = my_malloc(1024);
1576 sbuf.must_free_data = 1;
1577 sbuf.alloced = 1024;
1579 buf_sz = protobuf_c_message_pack_to_buffer((ProtobufCMessage *) dnsqr,
1580 (ProtobufCBuffer *) &sbuf);
1581 if (sbuf.data == NULL)
1585 NMSG_VENDOR_BASE_DNSQR_ID,
1586 sbuf.data, buf_sz, NULL);
1589 if (dnsqr->n_query_time_sec > 0) {
1590 ts.tv_sec = dnsqr->query_time_sec[0];
1591 ts.tv_nsec = dnsqr->query_time_nsec[0];
1593 }
else if (dnsqr->n_response_time_sec > 0) {
1594 ts.tv_sec = dnsqr->response_time_sec[0];
1595 ts.tv_nsec = dnsqr->response_time_nsec[0];
1603 do_packet_dns(Nmsg__Base__DnsQR *dnsqr,
struct nmsg_ipdg *dg, uint16_t *flags) {
1616 load_net16(p, &dnsqr->id);
1617 load_net16(p + 2, flags);
1618 load_net16(p + 4, &qdcount);
1623 if (qdcount == 1 && len > 0) {
1624 dnsqr->qname.len = wdns_skip_name(&p, p + len);
1625 dnsqr->qname.data = my_malloc(dnsqr->qname.len);
1626 len -= dnsqr->qname.len;
1632 memcpy(dnsqr->qname.data, p, dnsqr->qname.len);
1633 dnsqr->has_qname =
true;
1634 p += dnsqr->qname.len;
1636 memcpy(&qtype, p, 2);
1638 memcpy(&qclass, p, 2);
1641 dnsqr->qtype = ntohs(qtype);
1642 dnsqr->has_qtype =
true;
1643 dnsqr->qclass = ntohs(qclass);
1644 dnsqr->has_qclass =
true;
1651 do_packet_udp(Nmsg__Base__DnsQR *dnsqr,
struct nmsg_ipdg *dg, uint16_t *flags) {
1660 src_port = ntohs(udp->uh_sport);
1661 dst_port = ntohs(udp->uh_dport);
1663 if (!(src_port == 53 || src_port == 5353 || dst_port == 53 || dst_port == 5353))
1666 res = do_packet_dns(dnsqr, dg, flags);
1670 if (DNS_FLAG_QR(*flags) ==
false) {
1672 dnsqr->query_port = src_port;
1673 dnsqr->response_port = dst_port;
1676 dnsqr->query_port = dst_port;
1677 dnsqr->response_port = src_port;
1684 do_packet_tcp(Nmsg__Base__DnsQR *dnsqr,
struct nmsg_ipdg *dg, uint16_t *flags) {
1692 src_port = ntohs(tcp->th_sport);
1693 dst_port = ntohs(tcp->th_dport);
1695 if (!(src_port == 53 || dst_port == 53))
1701 dnsqr->has_tcp =
true;
1703 dnsqr->type = NMSG__BASE__DNS_QRTYPE__TCP;
1709 do_packet_icmp(Nmsg__Base__DnsQR *dnsqr,
struct nmsg_ipdg *dg, uint16_t *flags) {
1718 if (icmp_dg.transport == NULL)
1720 if (icmp_dg.proto_transport == IPPROTO_UDP) {
1723 udp = (
const struct nmsg_udphdr *) icmp_dg.transport;
1724 src_port = ntohs(udp->uh_sport);
1725 dst_port = ntohs(udp->uh_dport);
1727 if (!(src_port == 53 || src_port == 5353 || dst_port == 53 || dst_port == 5353))
1729 }
else if (icmp_dg.proto_transport == IPPROTO_TCP) {
1732 tcp = (
const struct nmsg_tcphdr *) icmp_dg.transport;
1733 src_port = ntohs(tcp->th_sport);
1734 dst_port = ntohs(tcp->th_dport);
1736 if (!(src_port == 53 || dst_port == 53))
1745 dnsqr->has_icmp =
true;
1747 dnsqr->type = NMSG__BASE__DNS_QRTYPE__ICMP;
1753 do_packet_v4(Nmsg__Base__DnsQR *dnsqr,
struct nmsg_ipdg *dg, uint16_t *flags) {
1759 res = do_packet_udp(dnsqr, dg, flags);
1762 return (do_packet_tcp(dnsqr, dg, flags));
1764 return (do_packet_icmp(dnsqr, dg, flags));
1774 dnsqr->query_ip.len = 4;
1775 dnsqr->query_ip.data = my_malloc(4);
1778 dnsqr->response_ip.len = 4;
1779 dnsqr->response_ip.data = my_malloc(4);
1783 if (DNS_FLAG_QR(*flags) ==
false) {
1785 memcpy(dnsqr->query_ip.data, &ip->ip_src, 4);
1786 memcpy(dnsqr->response_ip.data, &ip->ip_dst, 4);
1789 memcpy(dnsqr->query_ip.data, &ip->ip_dst, 4);
1790 memcpy(dnsqr->response_ip.data, &ip->ip_src, 4);
1797 do_packet_v6(Nmsg__Base__DnsQR *dnsqr,
struct nmsg_ipdg *dg, uint16_t *flags) {
1798 const struct ip6_hdr *ip6;
1803 res = do_packet_udp(dnsqr, dg, flags);
1806 return (do_packet_tcp(dnsqr, dg, flags));
1808 return (do_packet_icmp(dnsqr, dg, flags));
1818 dnsqr->query_ip.len = 16;
1819 dnsqr->query_ip.data = my_malloc(16);
1822 dnsqr->response_ip.len = 16;
1823 dnsqr->response_ip.data = my_malloc(16);
1825 ip6 = (
const struct ip6_hdr *) dg->
network;
1827 if (DNS_FLAG_QR(*flags) ==
false) {
1829 memcpy(dnsqr->query_ip.data, &ip6->ip6_src, 16);
1830 memcpy(dnsqr->response_ip.data, &ip6->ip6_dst, 16);
1833 memcpy(dnsqr->query_ip.data, &ip6->ip6_dst, 16);
1834 memcpy(dnsqr->response_ip.data, &ip6->ip6_src, 16);
1841 get_query_flags(Nmsg__Base__DnsQR *dnsqr, uint16_t *flags) {
1845 if (dnsqr->query_ip.data != NULL && dnsqr->n_query_packet > 0) {
1846 if (dnsqr->query_ip.len == 4) {
1848 dnsqr->query_packet[0].len,
1849 dnsqr->query_packet[0].data);
1852 }
else if (dnsqr->query_ip.len == 16) {
1854 dnsqr->query_packet[0].len,
1855 dnsqr->query_packet[0].data);
1866 memcpy(flags, dg.
payload + 2,
sizeof(*flags));
1867 *flags = htons(*flags);
1875 dnsqr_merge(Nmsg__Base__DnsQR *d1, Nmsg__Base__DnsQR *d2) {
1876 assert(d2->n_query_packet == 0 &&
1877 d2->n_query_time_sec == 0 &&
1878 d2->n_query_time_nsec == 0 &&
1879 d2->query_packet == NULL &&
1880 d2->query_time_sec == NULL &&
1881 d2->query_time_nsec == NULL);
1883 d2->n_query_packet = d1->n_query_packet;
1884 d2->n_query_time_sec = d1->n_query_time_sec;
1885 d2->n_query_time_nsec = d1->n_query_time_nsec;
1886 d2->query_packet = d1->query_packet;
1887 d2->query_time_sec = d1->query_time_sec;
1888 d2->query_time_nsec = d1->query_time_nsec;
1890 d1->n_query_packet = 0;
1891 d1->n_query_time_sec = 0;
1892 d1->n_query_time_nsec = 0;
1893 d1->query_packet = NULL;
1894 d1->query_time_sec = NULL;
1895 d1->query_time_nsec = NULL;
1897 if (d2->has_qname ==
false && d1->has_qname ==
true) {
1898 memcpy(&d2->qname, &d1->qname,
sizeof(ProtobufCBinaryData));
1899 memset(&d1->qname, 0,
sizeof(ProtobufCBinaryData));
1900 d2->has_qname =
true;
1902 if (d2->has_qtype ==
false && d1->has_qtype ==
true) {
1903 d2->qtype = d1->qtype;
1904 d2->has_qtype =
true;
1906 if (d2->has_qclass ==
false && d1->has_qclass ==
true) {
1907 d2->qclass = d1->qclass;
1908 d2->has_qclass =
true;
1911 nmsg__base__dns_qr__free_unpacked(d1, NULL);
1914 #define extend_field_array(x, n) do { \
1915 (x) = realloc((x), (n) * sizeof(*(x))); \
1916 assert((x) != NULL); \
1920 dnsqr_append_query_packet(Nmsg__Base__DnsQR *dnsqr,
1921 const uint8_t *pkt,
size_t pkt_len,
1922 const struct timespec *ts)
1927 n = idx = dnsqr->n_query_packet;
1930 extend_field_array(dnsqr->query_packet, n);
1931 extend_field_array(dnsqr->query_time_sec, n);
1932 extend_field_array(dnsqr->query_time_nsec, n);
1934 pkt_copy = my_malloc(pkt_len);
1935 memcpy(pkt_copy, pkt, pkt_len);
1937 dnsqr->n_query_packet += 1;
1938 dnsqr->n_query_time_sec += 1;
1939 dnsqr->n_query_time_nsec += 1;
1941 dnsqr->query_packet[idx].len = pkt_len;
1942 dnsqr->query_packet[idx].data = pkt_copy;
1943 dnsqr->query_time_sec[idx] = ts->tv_sec;
1944 dnsqr->query_time_nsec[idx] = ts->tv_nsec;
1950 dnsqr_append_response_packet(Nmsg__Base__DnsQR *dnsqr,
1951 const uint8_t *pkt,
size_t pkt_len,
1952 const struct timespec *ts)
1957 n = idx = dnsqr->n_response_packet;
1960 extend_field_array(dnsqr->response_packet, n);
1961 extend_field_array(dnsqr->response_time_sec, n);
1962 extend_field_array(dnsqr->response_time_nsec, n);
1964 pkt_copy = my_malloc(pkt_len);
1965 memcpy(pkt_copy, pkt, pkt_len);
1967 dnsqr->n_response_packet += 1;
1968 dnsqr->n_response_time_sec += 1;
1969 dnsqr->n_response_time_nsec += 1;
1971 dnsqr->response_packet[idx].len = pkt_len;
1972 dnsqr->response_packet[idx].data = pkt_copy;
1973 dnsqr->response_time_sec[idx] = ts->tv_sec;
1974 dnsqr->response_time_nsec[idx] = ts->tv_nsec;
1980 dnsqr_append_frag(dnsqr_append_fp func,
1981 Nmsg__Base__DnsQR *dnsqr,
1982 struct reasm_ip_entry *entry)
1985 struct reasm_frag_entry *frag = entry->frags->next;
1987 while (frag != NULL) {
1988 res = func(dnsqr, frag->data, frag->len + frag->data_offset, &frag->ts);
1997 dnsqr_print_stats(dnsqr_ctx_t *ctx) {
1999 fprintf(stderr,
"%s: c= %u qr= %u uq= %u ur= %u p= %u\n", __func__,
2001 ctx->count_query_response,
2002 ctx->count_unanswered_query,
2003 ctx->count_unsolicited_response,
2005 ctx->count_query_response = 0;
2006 ctx->count_unanswered_query = 0;
2007 ctx->count_unsolicited_response = 0;
2012 do_filter_query_rd(dnsqr_ctx_t *ctx, Nmsg__Base__DnsQR *dnsqr) {
2013 if (ctx->capture_rd == 0 || ctx->capture_rd == 1) {
2015 if (get_query_flags(dnsqr, &qflags))
2016 if (DNS_FLAG_RD(qflags) != ctx->capture_rd)
2023 do_filter_rd(dnsqr_ctx_t *ctx, uint16_t flags) {
2024 if (ctx->capture_rd == 0 || ctx->capture_rd == 1) {
2025 if (DNS_FLAG_RD(flags) != ctx->capture_rd)
2032 do_filter_query_name(dnsqr_ctx_t *ctx, Nmsg__Base__DnsQR *dnsqr) {
2036 if (dnsqr->has_qname ==
false)
2039 if (ctx->filter_qnames_include != NULL) {
2040 name.len = dnsqr->qname.len;
2041 name.data = alloca(name.len);
2042 assert(name.data != NULL);
2043 memcpy(name.data, dnsqr->qname.data, name.len);
2044 wdns_downcase_name(&name);
2047 if (dnsqr_filter_lookup(ctx->filter_qnames_include,
2048 ctx->filter_qnames_include_slots,
2055 res = wdns_left_chop(&name, &name);
2056 if (res != wdns_res_success)
2061 if (ctx->filter_qnames_exclude != NULL) {
2062 name.len = dnsqr->qname.len;
2063 name.data = alloca(name.len);
2064 assert(name.data != NULL);
2065 memcpy(name.data, dnsqr->qname.data, name.len);
2066 wdns_downcase_name(&name);
2069 if (dnsqr_filter_lookup(ctx->filter_qnames_exclude,
2070 ctx->filter_qnames_exclude_slots,
2077 res = wdns_left_chop(&name, &name);
2078 if (res != wdns_res_success)
2087 do_filter(dnsqr_ctx_t *ctx, Nmsg__Base__DnsQR *dnsqr) {
2088 return (do_filter_query_rd(ctx, dnsqr) ||
2089 do_filter_query_name(ctx, dnsqr));
2093 do_packet(dnsqr_ctx_t *ctx, nmsg_pcap_t pcap, nmsg_message_t *m,
2094 const uint8_t *pkt,
const struct pcap_pkthdr *pkt_hdr,
2095 const struct timespec *ts)
2097 Nmsg__Base__DnsQR *dnsqr = NULL;
2101 struct reasm_ip_entry *reasm_entry = NULL;
2103 uint8_t *new_pkt = NULL;
2107 if (pkt_hdr->caplen != pkt_hdr->len)
2114 pthread_mutex_lock(&ctx->lock);
2115 ctx->now.tv_sec = ts->tv_sec;
2116 ctx->now.tv_nsec = ts->tv_nsec;
2118 ctx->count_packet += 1;
2119 if ((ctx->count_packet % 100000) == 0)
2120 dnsqr_print_stats(ctx);
2123 pthread_mutex_unlock(&ctx->lock);
2126 if (reasm_entry != NULL) {
2129 reasm_assemble(reasm_entry, new_pkt, &new_pkt_len);
2145 dnsqr = my_calloc(1,
sizeof(*dnsqr));
2146 nmsg__base__dns_qr__init(dnsqr);
2152 res = do_packet_v4(dnsqr, &dg, &flags);
2161 res = do_packet_v6(dnsqr, &dg, &flags);
2174 if (ctx->capture_qr == 0 && DNS_FLAG_QR(flags) ==
false) {
2176 dnsqr->type = NMSG__BASE__DNS_QRTYPE__UDP_QUERY_ONLY;
2182 *m = dnsqr_to_message(ctx, dnsqr);
2184 }
else if (ctx->capture_qr == 1 && DNS_FLAG_QR(flags) ==
true) {
2186 dnsqr->type = NMSG__BASE__DNS_QRTYPE__UDP_RESPONSE_ONLY;
2187 dnsqr->rcode = DNS_FLAG_RCODE(flags);
2188 dnsqr->has_rcode =
true;
2191 res = dnsqr_append_frag(dnsqr_append_response_packet,
2195 res = dnsqr_append_response_packet(dnsqr,
2202 *m = dnsqr_to_message(ctx, dnsqr);
2207 }
else if (dg.
proto_transport == IPPROTO_UDP && DNS_FLAG_QR(flags) ==
false) {
2209 dnsqr->type = NMSG__BASE__DNS_QRTYPE__UDP_UNANSWERED_QUERY;
2211 res = dnsqr_append_frag(dnsqr_append_query_packet, dnsqr, reasm_entry);
2216 dnsqr_insert_query(ctx, dnsqr);
2221 Nmsg__Base__DnsQR *query;
2223 dnsqr->rcode = DNS_FLAG_RCODE(flags);
2224 dnsqr->has_rcode =
true;
2227 res = dnsqr_append_frag(dnsqr_append_response_packet, dnsqr, reasm_entry);
2233 query = dnsqr_retrieve(ctx, dnsqr, DNS_FLAG_RCODE(flags));
2234 if (query == NULL) {
2237 dnsqr->type = NMSG__BASE__DNS_QRTYPE__UDP_UNSOLICITED_RESPONSE;
2239 if (do_filter_rd(ctx, flags)) {
2244 *m = dnsqr_to_message(ctx, dnsqr);
2247 pthread_mutex_lock(&ctx->lock);
2248 ctx->count_unsolicited_response += 1;
2249 pthread_mutex_unlock(&ctx->lock);
2254 dnsqr->type = NMSG__BASE__DNS_QRTYPE__UDP_QUERY_RESPONSE;
2255 dnsqr_merge(query, dnsqr);
2257 if (do_filter(ctx, dnsqr)) {
2262 *m = dnsqr_to_message(ctx, dnsqr);
2265 pthread_mutex_lock(&ctx->lock);
2266 ctx->count_query_response += 1;
2267 pthread_mutex_unlock(&ctx->lock);
2273 *m = dnsqr_to_message(ctx, dnsqr);
2279 nmsg__base__dns_qr__free_unpacked(dnsqr, NULL);
2280 if (new_pkt != NULL)
2282 if (reasm_entry != NULL)
2283 reasm_free_entry(reasm_entry);
2288 dnsqr_pkt_to_payload(
void *clos, nmsg_pcap_t pcap, nmsg_message_t *m) {
2289 Nmsg__Base__DnsQR *dnsqr;
2290 dnsqr_ctx_t *ctx = (dnsqr_ctx_t *) clos;
2293 struct pcap_pkthdr *pkt_hdr;
2294 const uint8_t *pkt_data;
2296 dnsqr = dnsqr_trim(ctx);
2297 if (dnsqr != NULL) {
2298 if (do_filter(ctx, dnsqr)) {
2299 nmsg__base__dns_qr__free_unpacked(dnsqr, NULL);
2301 *m = dnsqr_to_message(ctx, dnsqr);
2302 nmsg__base__dns_qr__free_unpacked(dnsqr, NULL);
2308 pthread_mutex_lock(&ctx->lock);
2310 pthread_mutex_unlock(&ctx->lock);
2318 return (do_packet(ctx, pcap, m, pkt_data, pkt_hdr, &ts));
2320 pthread_mutex_lock(&ctx->lock);
2322 pthread_mutex_unlock(&ctx->lock);
Structure exported by message modules to implement a new message type.
nmsg_res nmsg_ipdg_parse_pcap_raw(struct nmsg_ipdg *dg, int datalink, const uint8_t *pkt, size_t len)
Like nmsg_ipdg_parse_pcap(), but performs no fragment handling.
unsigned len_network
length starting from network
int proto_transport
transport protocol
unsigned len_payload
length starting from payload
#define NMSG_IPSZ_MAX
Maximize size of an IP datagram.
nmsg_res nmsg_ipdg_parse(struct nmsg_ipdg *dg, unsigned etype, size_t len, const u_char *pkt)
Parse IP packets from the network layer, discarding fragments.
Structure mapping protocol buffer schema fields to nmsg_msgmod_field_type values for "transparent" mo...
const u_char * payload
pointer to application payload
const u_char * transport
pointer to transport header
void nmsg_message_set_time(nmsg_message_t msg, const struct timespec *ts)
Set the timestamp of a message object.
const u_char * network
pointer to network header
nmsg_msgmod_field_type type
Intended (nmsg) type of this protobuf field.
const char * name
Name of the field.
void * nmsg_message_get_payload(nmsg_message_t msg)
WARNING: experts only.
int proto_network
PF_* value.
nmsg_message_t nmsg_message_from_raw_payload(unsigned vid, unsigned msgtype, uint8_t *data, size_t sz, const struct timespec *ts)
Initialize a new message object from an opaque payload blob.
#define NMSG_MSGMOD_FIELD_REPEATED
field is repeated
#define NMSG_MSGMOD_FIELD_NOPRINT
don't print the field
int nmsg_get_debug(void)
Retrieve the current debug level.
nmsg_res nmsg_strbuf_append(struct nmsg_strbuf *sb, const char *fmt,...)
Append to a string buffer.
nmsg_res nmsg_message_add_allocation(nmsg_message_t msg, void *ptr)
Add an allocated object to a message object.