diff options
-rwxr-xr-x | configure | 20 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | src/network.c | 365 |
3 files changed, 161 insertions, 226 deletions
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for dnscap 2.0.2. +# Generated by GNU Autoconf 2.69 for dnscap 2.0.3. # # Report bugs to <dnscap-users@dns-oarc.net>. # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='dnscap' PACKAGE_TARNAME='dnscap' -PACKAGE_VERSION='2.0.2' -PACKAGE_STRING='dnscap 2.0.2' +PACKAGE_VERSION='2.0.3' +PACKAGE_STRING='dnscap 2.0.3' PACKAGE_BUGREPORT='dnscap-users@dns-oarc.net' PACKAGE_URL='https://github.com/DNS-OARC/dnscap/issues' @@ -1353,7 +1353,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures dnscap 2.0.2 to adapt to many kinds of systems. +\`configure' configures dnscap 2.0.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1424,7 +1424,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dnscap 2.0.2:";; + short | recursive ) echo "Configuration of dnscap 2.0.3:";; esac cat <<\_ACEOF @@ -1556,7 +1556,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -dnscap configure 2.0.2 +dnscap configure 2.0.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1979,7 +1979,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by dnscap $as_me 2.0.2, which was +It was created by dnscap $as_me 2.0.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2842,7 +2842,7 @@ fi # Define the identity of the package. PACKAGE='dnscap' - VERSION='2.0.2' + VERSION='2.0.3' cat >>confdefs.h <<_ACEOF @@ -15015,7 +15015,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by dnscap $as_me 2.0.2, which was +This file was extended by dnscap $as_me 2.0.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -15082,7 +15082,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -dnscap config.status 2.0.2 +dnscap config.status 2.0.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index aeaa615..843e8c9 100644 --- a/configure.ac +++ b/configure.ac @@ -33,7 +33,7 @@ # POSSIBILITY OF SUCH DAMAGE. AC_PREREQ(2.61) -AC_INIT([dnscap], [2.0.2], [dnscap-users@dns-oarc.net], [dnscap], [https://github.com/DNS-OARC/dnscap/issues]) +AC_INIT([dnscap], [2.0.3], [dnscap-users@dns-oarc.net], [dnscap], [https://github.com/DNS-OARC/dnscap/issues]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AC_CONFIG_SRCDIR([src/dnscap.c]) AC_CONFIG_HEADER([src/config.h]) 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) |