summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2022-06-19 06:52:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2022-06-19 06:52:14 +0000
commitf2aef121656aab183c22ef9b457910eb3d743232 (patch)
treeaa1d37cb6fb5aa20619f57c47a0b712b71325b1a /src
parentAdding upstream version 2.0.2. (diff)
downloaddnscap-f2aef121656aab183c22ef9b457910eb3d743232.tar.xz
dnscap-f2aef121656aab183c22ef9b457910eb3d743232.zip
Adding upstream version 2.0.3.upstream/2.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src')
-rw-r--r--src/network.c365
1 files changed, 150 insertions, 215 deletions
diff --git a/src/network.c b/src/network.c
index 76a645d..6e969c8 100644
--- a/src/network.c
+++ b/src/network.c
@@ -460,6 +460,143 @@ breakloop:
main_exit = TRUE;
}
+/*
+ * Determine if packet should be filtered based on query type
+ * return values: -1 error
+ * 0 don't filter
+ * 1 filter
+ * for non-zero return status, reason should be set to a
+ * static string.
+ */
+static int
+_filter_by_qtype(const ldns_pkt* lpkt, char** reason)
+{
+ ldns_rr_list* rrs = ldns_pkt_question(lpkt);
+ if (!rrs) {
+ *reason = "failed to get list of questions";
+ return -1;
+ }
+ /* Look at each RR in the section (or each QNAME in
+ the question section). */
+ size_t i, n;
+ for (i = 0, n = ldns_rr_list_rr_count(rrs); i < n; i++) {
+ ldns_rr* rr = ldns_rr_list_rr(rrs, i);
+ if (!rr) {
+ *reason = "failed to get question";
+ return -1;
+ }
+ if (match_qtype && ldns_rr_get_type(rr) == match_qtype) {
+ if (dumptrace >= 2)
+ fprintf(stderr, "Packet query type %u matches filter on type == %u\n", ldns_rr_get_type(rr), match_qtype);
+ return 0;
+ } else if (nmatch_qtype && ldns_rr_get_type(rr) == nmatch_qtype) {
+ if (dumptrace >= 2)
+ fprintf(stderr, "Packet query type %u matches filter on type != %u\n", ldns_rr_get_type(rr), nmatch_qtype);
+ *reason = "matched unwanted qtype";
+ return 1;
+ }
+ }
+ if (match_qtype) {
+ *reason = "didn't match wanted qtype";
+ return 1; // didn't match any question RRs
+ }
+ return 0;
+}
+
+/*
+ * Determine if packet should be filtered based on query name
+ * return values: -1 error
+ * 0 don't filter
+ * 1 filter
+ * for non-zero return status, reason should be set to a
+ * static string.
+ */
+static int
+_filter_by_qname(const ldns_pkt* lpkt, char** reason)
+{
+ int match = -1;
+ int negmatch = -1;
+ ldns_buffer* buf = ldns_buffer_new(512);
+ if (!buf) {
+ fprintf(stderr, "%s: out of memory", ProgramName);
+ exit(1);
+ }
+
+ /* Look at each section of the message:
+ question, answer, authority, additional */
+ ldns_rr_list* rrs = ldns_pkt_all(lpkt);
+ if (!rrs) {
+ ldns_buffer_free(buf);
+ *reason = "failed to get list of RRs";
+ return -1;
+ }
+
+ /*
+ * Initialize matching counters
+ */
+ myregex_ptr myregex;
+ for (myregex = HEAD(myregexes); myregex != NULL; myregex = NEXT(myregex, link)) {
+ if (myregex->not) {
+ negmatch = 0;
+ } else {
+ match = 0;
+ }
+ }
+
+ /* Look at each RR in the section (or each QNAME in
+ the question section). */
+ size_t i, n;
+ for (i = 0, n = ldns_rr_list_rr_count(rrs); i < n; i++) {
+ ldns_rr* rr = ldns_rr_list_rr(rrs, i);
+ if (!rr) {
+ ldns_rr_list_deep_free(rrs);
+ ldns_buffer_free(buf);
+ *reason = "failed to get RR";
+ return -1;
+ }
+
+ ldns_buffer_clear(buf);
+ if (ldns_rdf2buffer_str(buf, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
+ ldns_rr_list_deep_free(rrs);
+ ldns_buffer_free(buf);
+ *reason = "failed to get RR";
+ return -1;
+ }
+
+ for (myregex = HEAD(myregexes);
+ myregex != NULL;
+ myregex = NEXT(myregex, link)) {
+
+ if (regexec(&myregex->reg, (char*)ldns_buffer_begin(buf), 0, NULL, 0) == 0) {
+ if (myregex->not)
+ negmatch++;
+ else
+ match++;
+
+ if (dumptrace >= 2)
+ fprintf(stderr,
+ "; \"%s\" %s~ /%s/ %d %d\n",
+ (char*)ldns_buffer_begin(buf),
+ myregex->not ? "!" : "",
+ myregex->str,
+ match,
+ negmatch);
+ }
+ }
+ }
+ ldns_rr_list_deep_free(rrs);
+ ldns_buffer_free(buf);
+
+ /*
+ * Fail if any negative matches or if no positive matches
+ */
+ if (negmatch > 0 || match == 0) {
+ *reason = "failed regex match";
+ return 1;
+ }
+ return 0;
+}
+
void network_pkt2(const char* descr, my_bpftimeval ts, const pcap_thread_packet_t* packet, const u_char* payload, size_t length)
{
u_char pkt_copy[SNAPLEN], *pkt = pkt_copy;
@@ -471,7 +608,6 @@ void network_pkt2(const char* descr, my_bpftimeval ts, const pcap_thread_packet_
tcpstate_ptr tcpstate = NULL;
size_t len, dnslen = 0;
HEADER dns;
- ldns_pkt* lpkt = 0;
/* Make a writable copy of the packet and use that copy from now on. */
if (length > SNAPLEN)
@@ -889,6 +1025,7 @@ void network_pkt2(const char* descr, my_bpftimeval ts, const pcap_thread_packet_
}
}
if (!EMPTY(myregexes) || match_qtype || nmatch_qtype) {
+ ldns_pkt* lpkt = 0;
if (ldns_wire2pkt(&lpkt, dnspkt, dnslen) != LDNS_STATUS_OK) {
/* DNS message may have padding, try get actual size */
size_t dnslen2 = calcdnslen(dnspkt, dnslen);
@@ -902,121 +1039,17 @@ void network_pkt2(const char* descr, my_bpftimeval ts, const pcap_thread_packet_
return;
}
}
- }
- if (match_qtype || nmatch_qtype) {
- ldns_rr_list* rrs = ldns_pkt_question(lpkt);
- if (!rrs) {
- ldns_pkt_free(lpkt);
- tcpstate_discard(tcpstate, "failed to get list of questions");
- return;
- }
- /* Look at each RR in the section (or each QNAME in
- the question section). */
- size_t i, n;
- for (i = 0, n = ldns_rr_list_rr_count(rrs); i < n; i++) {
- ldns_rr* rr = ldns_rr_list_rr(rrs, i);
- if (!rr) {
- ldns_pkt_free(lpkt);
- tcpstate_discard(tcpstate, "failed to get question");
- return;
- }
-
- if (match_qtype && ldns_rr_get_type(rr) != match_qtype) {
- ldns_pkt_free(lpkt);
- tcpstate_discard(tcpstate, "qtype not match");
- return;
- } else if (nmatch_qtype && ldns_rr_get_type(rr) == nmatch_qtype) {
- ldns_pkt_free(lpkt);
- tcpstate_discard(tcpstate, "!qtype match");
- return;
- }
- }
- }
- if (!EMPTY(myregexes)) {
- int match, negmatch;
- ldns_buffer* buf = ldns_buffer_new(512);
-
- if (!buf) {
- fprintf(stderr, "%s: out of memory", ProgramName);
- exit(1);
- }
-
- match = -1;
- negmatch = -1;
- /* Look at each section of the message:
- question, answer, authority, additional */
- ldns_rr_list* rrs = ldns_pkt_all(lpkt);
- if (!rrs) {
+ char* reason = 0;
+ if ((match_qtype || nmatch_qtype) && _filter_by_qtype(lpkt, &reason)) {
ldns_pkt_free(lpkt);
- ldns_buffer_free(buf);
- tcpstate_discard(tcpstate, "failed to get list of RRs");
+ tcpstate_discard(tcpstate, reason);
return;
}
- /* Look at each RR in the section (or each QNAME in
- the question section). */
- size_t i, n;
- for (i = 0, n = ldns_rr_list_rr_count(rrs); i < n; i++) {
- ldns_rr* rr = ldns_rr_list_rr(rrs, i);
- if (!rr) {
- ldns_rr_list_deep_free(rrs);
- ldns_pkt_free(lpkt);
- ldns_buffer_free(buf);
- tcpstate_discard(tcpstate, "failed to get RR");
- return;
- }
-
- ldns_buffer_clear(buf);
- if (ldns_rdf2buffer_str(buf, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
- ldns_rr_list_deep_free(rrs);
- ldns_pkt_free(lpkt);
- ldns_buffer_free(buf);
- tcpstate_discard(tcpstate, "failed to get RR");
- return;
- }
-
- myregex_ptr myregex;
- for (myregex = HEAD(myregexes);
- myregex != NULL;
- myregex = NEXT(myregex, link)) {
- if (myregex->not ) {
- if (negmatch < 0)
- negmatch = 0;
- } else {
- if (match < 0)
- match = 0;
- }
-
- if (regexec(&myregex->reg, (char*)ldns_buffer_begin(buf), 0, NULL, 0) == 0) {
- if (myregex->not )
- negmatch++;
- else
- match++;
-
- if (dumptrace >= 2)
- fprintf(stderr,
- "; \"%s\" %s~ /%s/ %d %d\n",
- (char*)ldns_buffer_begin(buf),
- myregex->not ? "!" : "",
- myregex->str,
- match,
- negmatch);
- }
- }
- }
- ldns_rr_list_deep_free(rrs);
- ldns_buffer_free(buf);
-
- /*
- * Fail if any negative matching or if no match, match can be -1 which
- * indicates that there are only negative matching
- */
- if (negmatch > 0 || match == 0) {
+ if (!EMPTY(myregexes) && _filter_by_qname(lpkt, &reason)) {
ldns_pkt_free(lpkt);
- tcpstate_discard(tcpstate, "failed regex match");
+ tcpstate_discard(tcpstate, reason);
return;
}
- }
- if (lpkt) {
ldns_pkt_free(lpkt);
}
@@ -1053,7 +1086,6 @@ void network_pkt(const char* descr, my_bpftimeval ts, unsigned pf,
struct ip* ip;
size_t len, dnslen = 0;
HEADER dns;
- ldns_pkt* lpkt = 0;
if (dumptrace >= 4)
fprintf(stderr, "processing %s packet: len=%zu\n", (pf == PF_INET ? "IPv4" : (pf == PF_INET6 ? "IPv6" : "unknown")), olen);
@@ -1559,6 +1591,7 @@ void network_pkt(const char* descr, my_bpftimeval ts, unsigned pf,
}
}
if (!EMPTY(myregexes) || match_qtype || nmatch_qtype) {
+ ldns_pkt* lpkt = 0;
if (ldns_wire2pkt(&lpkt, dnspkt, dnslen) != LDNS_STATUS_OK) {
/* DNS message may have padding, try get actual size */
size_t dnslen2 = calcdnslen(dnspkt, dnslen);
@@ -1572,111 +1605,16 @@ void network_pkt(const char* descr, my_bpftimeval ts, unsigned pf,
goto network_pkt_end;
}
}
- }
- if (match_qtype || nmatch_qtype) {
- ldns_rr_list* rrs = ldns_pkt_question(lpkt);
- if (!rrs) {
- tcpstate_discard(tcpstate, "failed to get list of questions");
- goto network_pkt_end;
- }
- /* Look at each RR in the section (or each QNAME in
- the question section). */
- size_t i, n;
- for (i = 0, n = ldns_rr_list_rr_count(rrs); i < n; i++) {
- ldns_rr* rr = ldns_rr_list_rr(rrs, i);
- if (!rr) {
- tcpstate_discard(tcpstate, "failed to get question");
- goto network_pkt_end;
- }
-
- if (match_qtype && ldns_rr_get_type(rr) != match_qtype) {
- tcpstate_discard(tcpstate, "qtype not match");
- goto network_pkt_end;
- } else if (nmatch_qtype && ldns_rr_get_type(rr) == nmatch_qtype) {
- tcpstate_discard(tcpstate, "!qtype match");
- goto network_pkt_end;
- }
- }
- }
- if (!EMPTY(myregexes)) {
- int match, negmatch;
- ldns_buffer* buf = ldns_buffer_new(512);
-
- if (!buf) {
- fprintf(stderr, "%s: out of memory", ProgramName);
- exit(1);
- }
-
- match = -1;
- negmatch = -1;
- /* Look at each section of the message:
- question, answer, authority, additional */
- ldns_rr_list* rrs = ldns_pkt_all(lpkt);
- if (!rrs) {
- ldns_buffer_free(buf);
- tcpstate_discard(tcpstate, "failed to get list of RRs");
+ char* reason = 0;
+ if ((match_qtype || nmatch_qtype) && _filter_by_qtype(lpkt, &reason)) {
+ tcpstate_discard(tcpstate, reason);
goto network_pkt_end;
}
- /* Look at each RR in the section (or each QNAME in
- the question section). */
- size_t i, n;
- for (i = 0, n = ldns_rr_list_rr_count(rrs); i < n; i++) {
- ldns_rr* rr = ldns_rr_list_rr(rrs, i);
- if (!rr) {
- ldns_rr_list_deep_free(rrs);
- ldns_buffer_free(buf);
- tcpstate_discard(tcpstate, "failed to get RR");
- goto network_pkt_end;
- }
-
- ldns_buffer_clear(buf);
- if (ldns_rdf2buffer_str(buf, ldns_rr_owner(rr)) != LDNS_STATUS_OK) {
- ldns_rr_list_deep_free(rrs);
- ldns_buffer_free(buf);
- tcpstate_discard(tcpstate, "failed to get RR");
- goto network_pkt_end;
- }
-
- myregex_ptr myregex;
- for (myregex = HEAD(myregexes);
- myregex != NULL;
- myregex = NEXT(myregex, link)) {
- if (myregex->not ) {
- if (negmatch < 0)
- negmatch = 0;
- } else {
- if (match < 0)
- match = 0;
- }
-
- if (regexec(&myregex->reg, (char*)ldns_buffer_begin(buf), 0, NULL, 0) == 0) {
- if (myregex->not )
- negmatch++;
- else
- match++;
-
- if (dumptrace >= 2)
- fprintf(stderr,
- "; \"%s\" %s~ /%s/ %d %d\n",
- (char*)ldns_buffer_begin(buf),
- myregex->not ? "!" : "",
- myregex->str,
- match,
- negmatch);
- }
- }
- }
- ldns_rr_list_deep_free(rrs);
- ldns_buffer_free(buf);
-
- /*
- * Fail if any negative matching or if no match, match can be -1 which
- * indicates that there are only negative matching
- */
- if (negmatch > 0 || match == 0) {
- tcpstate_discard(tcpstate, "failed regex match");
+ if (!EMPTY(myregexes) && _filter_by_qname(lpkt, &reason)) {
+ tcpstate_discard(tcpstate, reason);
goto network_pkt_end;
}
+ ldns_pkt_free(lpkt);
}
/* Policy hiding. */
@@ -1754,9 +1692,6 @@ void network_pkt(const char* descr, my_bpftimeval ts, unsigned pf,
network_pkt_end:
network_ip = 0;
network_ipv6 = 0;
- if (lpkt) {
- ldns_pkt_free(lpkt);
- }
}
uint16_t in_checksum(const u_char* ptr, size_t len)