summaryrefslogtreecommitdiffstats
path: root/src/dns_message.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-12-12 22:18:22 +0100
committerDaniel Baumann <daniel@debian.org>2024-12-12 22:37:18 +0100
commitd7dba196f14971b34d3a5558ef64f9765aa6a9c4 (patch)
tree5cd92190c79ef2be590218b93c5206f8ca9b749e /src/dns_message.c
parentInitial commit. (diff)
downloaddsc-d7dba196f14971b34d3a5558ef64f9765aa6a9c4.tar.xz
dsc-d7dba196f14971b34d3a5558ef64f9765aa6a9c4.zip
Adding upstream version 2.15.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'src/dns_message.c')
-rw-r--r--src/dns_message.c577
1 files changed, 577 insertions, 0 deletions
diff --git a/src/dns_message.c b/src/dns_message.c
new file mode 100644
index 0000000..3041148
--- /dev/null
+++ b/src/dns_message.c
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 2008-2024 OARC, Inc.
+ * Copyright (c) 2007-2008, Internet Systems Consortium, Inc.
+ * Copyright (c) 2003-2007, The Measurement Factory, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "dns_message.h"
+#include "xmalloc.h"
+#include "syslog_debug.h"
+#include "tld_list.h"
+#include "dns_protocol.h"
+
+#include "null_index.h"
+#include "qtype_index.h"
+#include "qclass_index.h"
+#include "country_index.h"
+#include "asn_index.h"
+#include "tld_index.h"
+#include "rcode_index.h"
+#include "client_index.h"
+#include "client_subnet_index.h"
+#include "server_ip_addr_index.h"
+#include "qnamelen_index.h"
+#include "label_count_index.h"
+#include "edns_cookie_index.h"
+#include "edns_nsid_index.h"
+#include "edns_ede_index.h"
+#include "edns_ecs_index.h"
+#include "qname_index.h"
+#include "msglen_index.h"
+#include "certain_qnames_index.h"
+#include "idn_qname_index.h"
+#include "query_classification_index.h"
+#include "edns_version_index.h"
+#include "edns_bufsiz_index.h"
+#include "do_bit_index.h"
+#include "rd_bit_index.h"
+#include "tc_bit_index.h"
+#include "qr_aa_bits_index.h"
+#include "opcode_index.h"
+#include "transport_index.h"
+#include "dns_ip_version_index.h"
+#include "dns_source_port_index.h"
+#include "response_time_index.h"
+#include "encryption_index.h"
+
+#include "ip_direction_index.h"
+#include "ip_proto_index.h"
+#include "ip_version_index.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <regex.h>
+
+extern int debug_flag;
+static md_array_list* Arrays = 0;
+static filter_list* DNSFilters = 0;
+
+static indexer indexers[] = {
+ { "client", 0, client_indexer, client_iterator, client_reset },
+ { "server", 0, sip_indexer, sip_iterator, sip_reset },
+ { "country", country_init, country_indexer, country_iterator, country_reset },
+ { "asn", asn_init, asn_indexer, asn_iterator, asn_reset },
+ { "client_subnet", client_subnet_init, client_subnet_indexer, client_subnet_iterator, client_subnet_reset },
+ { "null", 0, null_indexer, null_iterator },
+ { "qclass", 0, qclass_indexer, qclass_iterator, qclass_reset },
+ { "qnamelen", 0, qnamelen_indexer, qnamelen_iterator, qnamelen_reset },
+ { "label_count", 0, label_count_indexer, label_count_iterator, label_count_reset },
+ { "qname", 0, qname_indexer, qname_iterator, qname_reset },
+ { "second_ld", 0, second_ld_indexer, second_ld_iterator, second_ld_reset },
+ { "third_ld", 0, third_ld_indexer, third_ld_iterator, third_ld_reset },
+ { "msglen", 0, msglen_indexer, msglen_iterator, msglen_reset },
+ { "qtype", 0, qtype_indexer, qtype_iterator, qtype_reset },
+ { "rcode", 0, rcode_indexer, rcode_iterator, rcode_reset },
+ { "tld", 0, tld_indexer, tld_iterator, tld_reset },
+ { "certain_qnames", 0, certain_qnames_indexer, certain_qnames_iterator },
+ { "query_classification", 0, query_classification_indexer, query_classification_iterator },
+ { "idn_qname", 0, idn_qname_indexer, idn_qname_iterator },
+ { "edns_version", indexer_want_edns, edns_version_indexer, edns_version_iterator },
+ { "edns_bufsiz", indexer_want_edns, edns_bufsiz_indexer, edns_bufsiz_iterator },
+ { "edns_cookie", indexer_want_edns_options, edns_cookie_indexer, edns_cookie_iterator },
+ { "edns_cookie_len", indexer_want_edns_options, edns_cookie_len_indexer, edns_cookie_len_iterator, edns_cookie_len_reset },
+ { "edns_cookie_client", indexer_want_edns_options, edns_cookie_client_indexer, edns_cookie_client_iterator, edns_cookie_client_reset },
+ { "edns_cookie_server", indexer_want_edns_options, edns_cookie_server_indexer, edns_cookie_server_iterator, edns_cookie_server_reset },
+ { "edns_ecs", indexer_want_edns_options, edns_ecs_indexer, edns_ecs_iterator },
+ { "edns_ecs_family", indexer_want_edns_options, edns_ecs_family_indexer, edns_ecs_family_iterator, edns_ecs_family_reset },
+ { "edns_ecs_source_prefix", indexer_want_edns_options, edns_ecs_source_prefix_indexer, edns_ecs_source_prefix_iterator, edns_ecs_source_prefix_reset },
+ { "edns_ecs_scope_prefix", indexer_want_edns_options, edns_ecs_scope_prefix_indexer, edns_ecs_scope_prefix_iterator, edns_ecs_scope_prefix_reset },
+ { "edns_ecs_address", indexer_want_edns_options, edns_ecs_address_indexer, edns_ecs_address_iterator, edns_ecs_address_reset },
+ { "edns_ecs_subnet", indexer_want_edns_options, edns_ecs_subnet_indexer, edns_ecs_subnet_iterator, edns_ecs_subnet_reset },
+ { "edns_ede", indexer_want_edns_options, edns_ede_indexer, edns_ede_iterator },
+ { "edns_ede_code", indexer_want_edns_options, edns_ede_code_indexer, edns_ede_code_iterator, edns_ede_code_reset },
+ { "edns_ede_textlen", indexer_want_edns_options, edns_ede_textlen_indexer, edns_ede_textlen_iterator, edns_ede_textlen_reset },
+ { "edns_ede_text", indexer_want_edns_options, edns_ede_text_indexer, edns_ede_text_iterator, edns_ede_text_reset },
+ { "edns_nsid", indexer_want_edns_options, edns_nsid_indexer, edns_nsid_iterator },
+ { "edns_nsid_len", indexer_want_edns_options, edns_nsid_len_indexer, edns_nsid_len_iterator, edns_nsid_len_reset },
+ { "edns_nsid_data", indexer_want_edns_options, edns_nsid_data_indexer, edns_nsid_data_iterator, edns_nsid_data_reset },
+ { "edns_nsid_text", indexer_want_edns_options, edns_nsid_text_indexer, edns_nsid_text_iterator, edns_nsid_text_reset },
+ { "do_bit", 0, do_bit_indexer, do_bit_iterator },
+ { "rd_bit", 0, rd_bit_indexer, rd_bit_iterator },
+ { "tc_bit", 0, tc_bit_indexer, tc_bit_iterator },
+ { "opcode", 0, opcode_indexer, opcode_iterator, opcode_reset },
+ { "transport", 0, transport_indexer, transport_iterator },
+ { "dns_ip_version", 0, dns_ip_version_indexer, dns_ip_version_iterator, dns_ip_version_reset },
+ { "dns_source_port", 0, dns_source_port_indexer, dns_source_port_iterator, dns_source_port_reset },
+ { "dns_sport_range", 0, dns_sport_range_indexer, dns_sport_range_iterator, dns_sport_range_reset },
+ { "qr_aa_bits", 0, qr_aa_bits_indexer, qr_aa_bits_iterator },
+ { "response_time", 0, response_time_indexer, response_time_iterator, response_time_reset, response_time_flush },
+ { "ip_direction", 0, ip_direction_indexer, ip_direction_iterator },
+ { "ip_proto", 0, ip_proto_indexer, ip_proto_iterator, ip_proto_reset },
+ { "ip_version", 0, ip_version_indexer, ip_version_iterator, ip_version_reset },
+ { "encryption", 0, encryption_indexer, encryption_iterator },
+ { 0 }
+};
+
+/*
+ * Filters
+ */
+
+static int queries_only_filter(const dns_message* m, const void* ctx)
+{
+ return m->qr ? 0 : 1;
+}
+
+static int nxdomains_only_filter(const dns_message* m, const void* ctx)
+{
+ return m->rcode == 3;
+}
+
+static int ad_filter(const dns_message* m, const void* ctx)
+{
+ return m->ad;
+}
+
+static int popular_qtypes_filter(const dns_message* m, const void* ctx)
+{
+ switch (m->qtype) {
+ case 1:
+ case 2:
+ case 5:
+ case 6:
+ case 12:
+ case 15:
+ case 28:
+ case 33:
+ case 38:
+ case 255:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int aaaa_or_a6_filter(const dns_message* m, const void* ctx)
+{
+ switch (m->qtype) {
+ case T_AAAA:
+ case T_A6:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int idn_qname_filter(const dns_message* m, const void* ctx)
+{
+ return !strncmp(m->qname, "xn--", 4);
+}
+
+static int root_servers_net_filter(const dns_message* m, const void* ctx)
+{
+ return !strcmp(m->qname + 1, ".root-servers.net");
+}
+
+static int chaos_class_filter(const dns_message* m, const void* ctx)
+{
+ return m->qclass == C_CHAOS;
+}
+
+static int priming_query_filter(const dns_message* m, const void* ctx)
+{
+ if (m->qtype != T_NS)
+ return 0;
+ if (!strcmp(m->qname, "."))
+ return 0;
+ return 1;
+}
+
+static int replies_only_filter(const dns_message* m, const void* ctx)
+{
+ return m->qr ? 1 : 0;
+}
+
+static int qname_filter(const dns_message* m, const void* ctx)
+{
+ return !regexec((const regex_t*)ctx, m->qname, 0, 0, 0);
+}
+
+static int servfail_filter(const dns_message* m, const void* ctx)
+{
+ return m->rcode == 2;
+}
+
+static int edns0_filter(const dns_message* m, const void* ctx)
+{
+ return m->edns.found && m->edns.version == 0;
+}
+
+static int edns0_cookie_filter(const dns_message* m, const void* ctx)
+{
+ return m->edns.option.cookie;
+}
+
+static int edns0_nsid_filter(const dns_message* m, const void* ctx)
+{
+ return m->edns.option.nsid;
+}
+
+static int edns0_ede_filter(const dns_message* m, const void* ctx)
+{
+ return m->edns.option.ede;
+}
+
+static int edns0_ecs_filter(const dns_message* m, const void* ctx)
+{
+ return m->edns.option.ecs;
+}
+
+/*
+ * Helpers
+ */
+
+static const char* printable_dnsname(const char* name)
+{
+ static char buf[MAX_QNAME_SZ];
+ int i;
+
+ for (i = 0; i < sizeof(buf) - 1;) {
+ if (!*name)
+ break;
+ if (isgraph(*name)) {
+ buf[i] = *name;
+ i++;
+ } else {
+ if (i + 3 > MAX_QNAME_SZ - 1)
+ break; /* expanded character would overflow buffer */
+ snprintf(buf + i, sizeof(buf) - i - 1, "%%%02x", (unsigned char)*name);
+ i += 3;
+ }
+ name++;
+ }
+ buf[i] = '\0';
+ return buf;
+}
+
+static void dns_message_print(dns_message* m)
+{
+ char buf[128];
+ inXaddr_ntop(m->qr ? &m->tm->dst_ip_addr : &m->tm->src_ip_addr, buf, 128);
+ fprintf(stderr, "%15s:%5d", buf, m->qr ? m->tm->dst_port : m->tm->src_port);
+ fprintf(stderr, "\t%s", (m->tm->proto == IPPROTO_UDP) ? "UDP" : (m->tm->proto == IPPROTO_TCP) ? "TCP" : "???");
+ fprintf(stderr, "\tQT=%d", m->qtype);
+ fprintf(stderr, "\tQC=%d", m->qclass);
+ fprintf(stderr, "\tlen=%d", m->msglen);
+ fprintf(stderr, "\tqname=%s", printable_dnsname(m->qname));
+ fprintf(stderr, "\ttld=%s", printable_dnsname(dns_message_tld(m)));
+ fprintf(stderr, "\topcode=%d", m->opcode);
+ fprintf(stderr, "\trcode=%d", m->rcode);
+ fprintf(stderr, "\tmalformed=%d", m->malformed);
+ fprintf(stderr, "\tqr=%d", m->qr);
+ fprintf(stderr, "\trd=%d", m->rd);
+ fprintf(stderr, "\n");
+}
+
+static indexer* dns_message_find_indexer(const char* in)
+{
+ indexer* indexer;
+ for (indexer = indexers; indexer->name; indexer++) {
+ if (0 == strcmp(in, indexer->name))
+ return indexer;
+ }
+ dsyslogf(LOG_ERR, "unknown indexer '%s'", in);
+ return NULL;
+}
+
+static int dns_message_find_filters(const char* fn, filter_list** fl)
+{
+ char* tok = 0;
+ char* t;
+ char* copy = xstrdup(fn);
+ filter_list* f;
+ if (NULL == copy)
+ return 0;
+ for (t = strtok_r(copy, ",", &tok); t; t = strtok_r(NULL, ",", &tok)) {
+ if (0 == strcmp(t, "any"))
+ continue;
+ for (f = DNSFilters; f; f = f->next) {
+ if (0 == strcmp(t, f->filter->name))
+ break;
+ }
+ if (f) {
+ fl = md_array_filter_list_append(fl, f->filter);
+ continue;
+ }
+ dsyslogf(LOG_ERR, "unknown filter '%s'", t);
+ xfree(copy);
+ return 0;
+ }
+ xfree(copy);
+ return 1;
+}
+
+/*
+ * Public
+ */
+
+void dns_message_handle(dns_message* m)
+{
+ md_array_list* a;
+ if (debug_flag > 1)
+ dns_message_print(m);
+ for (a = Arrays; a; a = a->next)
+ md_array_count(a->theArray, m);
+}
+
+int dns_message_add_array(const char* name, const char* fn, const char* fi, const char* sn, const char* si, const char* f, dataset_opt opts)
+{
+ filter_list* filters = NULL;
+ indexer * indexer1, *indexer2;
+ md_array_list* a;
+
+ if (NULL == (indexer1 = dns_message_find_indexer(fi)))
+ return 0;
+ if (NULL == (indexer2 = dns_message_find_indexer(si)))
+ return 0;
+ if (0 == dns_message_find_filters(f, &filters))
+ return 0;
+
+ a = xcalloc(1, sizeof(*a));
+ if (a == NULL) {
+ dsyslogf(LOG_ERR, "Cant allocate memory for '%s' DNS message array", name);
+ return 0;
+ }
+ a->theArray = md_array_create(name, filters, fn, indexer1, sn, indexer2);
+ if (NULL == a->theArray) {
+ dsyslogf(LOG_ERR, "Cant allocate memory for '%s' DNS message array", name);
+ xfree(a);
+ return 0;
+ }
+ a->theArray->opts = opts;
+ assert(a->theArray);
+ a->next = Arrays;
+ Arrays = a;
+ return 1;
+}
+
+void dns_message_flush_arrays(void)
+{
+ md_array_list* a;
+ for (a = Arrays; a; a = a->next) {
+ if (a->theArray->d1.indexer->flush_fn || a->theArray->d2.indexer->flush_fn)
+ md_array_flush(a->theArray);
+ }
+}
+
+void dns_message_report(FILE* fp, md_array_printer* printer)
+{
+ md_array_list* a;
+ for (a = Arrays; a; a = a->next) {
+ md_array_print(a->theArray, printer, fp);
+ }
+}
+
+void dns_message_clear_arrays(void)
+{
+ md_array_list* a;
+ for (a = Arrays; a; a = a->next)
+ md_array_clear(a->theArray);
+}
+
+/*
+ * QnameToNld
+ *
+ * qname is a 0-terminated string containing a DNS name
+ * nld is the domain level to find
+ *
+ * return value is a pointer into the qname string.
+ *
+ * Handles the following cases:
+ * qname is empty ("")
+ * qname ends with one or more dots
+ * qname begins with one or more dots
+ * multiple consequtive dots in qname
+ *
+ * TESTS
+ * assert(0 == strcmp(QnameToNld("a.b.c.d", 1), "d"));
+ * assert(0 == strcmp(QnameToNld("a.b.c.d", 2), "c.d"));
+ * assert(0 == strcmp(QnameToNld("a.b.c.d.", 2), "c.d."));
+ * assert(0 == strcmp(QnameToNld("a.b.c.d....", 2), "c.d...."));
+ * assert(0 == strcmp(QnameToNld("c.d", 5), "c.d"));
+ * assert(0 == strcmp(QnameToNld(".c.d", 5), "c.d"));
+ * assert(0 == strcmp(QnameToNld(".......c.d", 5), "c.d"));
+ * assert(0 == strcmp(QnameToNld("", 1), ""));
+ * assert(0 == strcmp(QnameToNld(".", 1), "."));
+ * assert(0 == strcmp(QnameToNld("a.b..c..d", 2), "c..d"));
+ * assert(0 == strcmp(QnameToNld("a.b................c..d", 3), "b................c..d"));
+ */
+const char* dns_message_QnameToNld(const char* qname, int nld)
+{
+ const char* e = qname + strlen(qname) - 1;
+ const char* t;
+ int dotcount = 0;
+ int state = 0; /* 0 = not in dots, 1 = in dots */
+ while (*e == '.' && e > qname)
+ e--;
+ t = e;
+ if (0 == strcmp(t, ".arpa"))
+ dotcount--;
+ if (have_tld_list) {
+ // Use TLD list to find labels that are the "TLD"
+ const char *lt = 0, *ot = t;
+ int done = 0;
+ while (t > qname) {
+ t--;
+ if ('.' == *t) {
+ if (0 == state) {
+ int r = tld_list_find(t + 1);
+ if (r & 1) {
+ // this is a tld
+ lt = t;
+ }
+ if (!r || !(r & 2)) {
+ // no more children
+ if (lt) {
+ // reset to what we last found
+ t = lt;
+ dotcount++;
+ state = 1;
+ } else {
+ // or reset
+ t = ot;
+ state = 0;
+ }
+ done = 1;
+ break;
+ }
+ }
+ state = 1;
+ } else {
+ state = 0;
+ }
+ }
+ if (!done) {
+ // nothing found, reset t
+ t = e;
+ }
+ }
+ while (t > qname && dotcount < nld) {
+ t--;
+ if ('.' == *t) {
+ if (0 == state)
+ dotcount++;
+ state = 1;
+ } else {
+ state = 0;
+ }
+ }
+ while (*t == '.' && t < e)
+ t++;
+ return t;
+}
+
+const char* dns_message_tld(dns_message* m)
+{
+ if (NULL == m->tld)
+ m->tld = dns_message_QnameToNld(m->qname, 1);
+ return m->tld;
+}
+
+void dns_message_filters_init(void)
+{
+ filter_list** fl = &DNSFilters;
+
+ fl = md_array_filter_list_append(fl, md_array_create_filter("queries-only", queries_only_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("replies-only", replies_only_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("nxdomains-only", nxdomains_only_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("popular-qtypes", popular_qtypes_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("idn-only", idn_qname_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("aaaa-or-a6-only", aaaa_or_a6_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("root-servers-net-only", root_servers_net_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("chaos-class", chaos_class_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("priming-query", priming_query_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("servfail-only", servfail_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("edns0-only", edns0_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("edns0-cookie-only", edns0_cookie_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("edns0-nsid-only", edns0_nsid_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("edns0-ede-only", edns0_ede_filter, 0));
+ fl = md_array_filter_list_append(fl, md_array_create_filter("edns0-ecs-only", edns0_ecs_filter, 0));
+ (void)md_array_filter_list_append(fl, md_array_create_filter("authentic-data-only", ad_filter, 0));
+}
+
+void dns_message_indexers_init(void)
+{
+ indexer* indexer;
+
+ for (indexer = indexers; indexer->name; indexer++) {
+ if (indexer->init_fn)
+ indexer->init_fn();
+ }
+}
+
+int add_qname_filter(const char* name, const char* pat)
+{
+ filter_list** fl = &DNSFilters;
+ regex_t* r;
+ int x;
+ while ((*fl))
+ fl = &((*fl)->next);
+ r = xcalloc(1, sizeof(*r));
+ if (NULL == r) {
+ dsyslogf(LOG_ERR, "Cant allocate memory for '%s' qname filter", name);
+ return 0;
+ }
+ if (0 != (x = regcomp(r, pat, REG_EXTENDED | REG_ICASE))) {
+ char errbuf[512];
+ regerror(x, r, errbuf, 512);
+ dsyslogf(LOG_ERR, "regcomp: %s", errbuf);
+ }
+ (void)md_array_filter_list_append(fl, md_array_create_filter(name, qname_filter, r));
+ return 1;
+}
+
+void indexer_want_edns(void)
+{
+ dns_protocol_parse_edns = 1;
+}
+
+void indexer_want_edns_options(void)
+{
+ dns_protocol_parse_edns = 1;
+ dns_protocol_parse_edns_options = 1;
+}