diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | support/Makefile | 3 | ||||
-rw-r--r-- | support/support_format_dns_packet.c | 21 | ||||
-rw-r--r-- | support/tst-support_format_dns_packet.c | 97 |
4 files changed, 123 insertions, 7 deletions
@@ -1,3 +1,12 @@ +2017-03-15 Florian Weimer <fweimer@redhat.com> + + * support/support_format_dns_packet.c (support_format_dns_packet): + Handle CNAME records in the response. Extract RDATA names from + rdata, not the whole packet. Check AAAA record length. + * support/tst-support_format_dns_packet.c: New file. + * support/Makefile (tests): Add tst-support_format_dns_packet. + (tst-support_format_dns_packet): Link against libresolv. + 2017-03-14 Adhemerval Zanella <adhemerval.zanella@linaro.org> [BZ #21232] diff --git a/support/Makefile b/support/Makefile index 2ace559ae0..db7bb130b2 100644 --- a/support/Makefile +++ b/support/Makefile @@ -111,6 +111,7 @@ endif tests = \ README-testing \ tst-support-namespace \ + tst-support_format_dns_packet \ tst-support_record_failure \ ifeq ($(run-built-tests),yes) @@ -125,4 +126,6 @@ $(objpfx)tst-support_record_failure-2.out: tst-support_record_failure-2.sh \ $(evaluate-test) endif +$(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv.so + include ../Rules diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c index 21fe7e5c8d..2992c57971 100644 --- a/support/support_format_dns_packet.c +++ b/support/support_format_dns_packet.c @@ -174,7 +174,7 @@ support_format_dns_packet (const unsigned char *buffer, size_t length) goto out; } /* Skip non-matching record types. */ - if (rtype != qtype || rclass != qclass) + if ((rtype != qtype && rtype != T_CNAME) || rclass != qclass) continue; switch (rtype) { @@ -186,22 +186,29 @@ support_format_dns_packet (const unsigned char *buffer, size_t length) rdata.data[2], rdata.data[3]); else - fprintf (mem.out, "error: A record of size %d: %s\n", rdlen, rname.name); + fprintf (mem.out, "error: A record of size %d: %s\n", + rdlen, rname.name); break; case T_AAAA: { - char buf[100]; - if (inet_ntop (AF_INET6, rdata.data, buf, sizeof (buf)) == NULL) - fprintf (mem.out, "error: AAAA record decoding failed: %m\n"); + if (rdlen == 16) + { + char buf[100]; + if (inet_ntop (AF_INET6, rdata.data, buf, sizeof (buf)) == NULL) + fprintf (mem.out, "error: AAAA record decoding failed: %m\n"); + else + fprintf (mem.out, "address: %s\n", buf); + } else - fprintf (mem.out, "address: %s\n", buf); + fprintf (mem.out, "error: AAAA record of size %d: %s\n", + rdlen, rname.name); } break; case T_CNAME: case T_PTR: { struct dname name; - if (extract_name (full, &in, &name)) + if (extract_name (full, &rdata, &name)) fprintf (mem.out, "name: %s\n", name.name); else fprintf (mem.out, "error: malformed CNAME/PTR record\n"); diff --git a/support/tst-support_format_dns_packet.c b/support/tst-support_format_dns_packet.c new file mode 100644 index 0000000000..ecd7abfe2b --- /dev/null +++ b/support/tst-support_format_dns_packet.c @@ -0,0 +1,97 @@ +/* Tests for the support_format_dns_packet function. + Copyright (C) 2016-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <support/check.h> +#include <support/format_nss.h> +#include <support/run_diff.h> + +static void +check_packet (const void *buffer, size_t length, + const char *name, const char *expected) +{ + char *actual = support_format_dns_packet (buffer, length); + if (strcmp (actual, expected) != 0) + { + support_record_failure (); + printf ("error: formatted packet does not match: %s\n", name); + support_run_diff ("expected", expected, + "actual", actual); + } + free (actual); +} + +static void +test_aaaa_length (void) +{ + static const char packet[] = + /* Header: Response with two records. */ + "\x12\x34\x80\x00\x00\x01\x00\x02\x00\x00\x00\x00" + /* Question section. www.example/IN/AAAA. */ + "\x03www\x07""example\x00\x00\x1c\x00\x01" + /* Answer section. www.example AAAA [corrupted]. */ + "\xc0\x0c" + "\x00\x1c\x00\x01\x00\x00\x00\x00\x00\x10" + "\x20\x01\x0d\xb8\x05\x06\x07\x08" + "\x11\x12\x13\x14\x15\x16\x17\x18" + /* www.example AAAA [corrupted]. */ + "\xc0\x0c" + "\x00\x1c\x00\x01\x00\x00\x00\x00\x00\x11" + "\x01\x02\x03\x04\x05\x06\x07\x08" + "\x11\x12\x13\x14\x15\x16\x17\x18" "\xff"; + check_packet (packet, sizeof (packet) - 1, __func__, + "name: www.example\n" + "address: 2001:db8:506:708:1112:1314:1516:1718\n" + "error: AAAA record of size 17: www.example\n"); +} + +static void +test_multiple_cnames (void) +{ + static const char packet[] = + /* Header: Response with three records. */ + "\x12\x34\x80\x00\x00\x01\x00\x03\x00\x00\x00\x00" + /* Question section. www.example/IN/A. */ + "\x03www\x07""example\x00\x00\x01\x00\x01" + /* Answer section. www.example CNAME www1.example. */ + "\xc0\x0c" + "\x00\x05\x00\x01\x00\x00\x00\x00\x00\x07" + "\x04www1\xc0\x10" + /* www1 CNAME www2. */ + "\x04www1\xc0\x10" + "\x00\x05\x00\x01\x00\x00\x00\x00\x00\x07" + "\x04www2\xc0\x10" + /* www2 A 192.0.2.1. */ + "\x04www2\xc0\x10" + "\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04" + "\xc0\x00\x02\x01"; + check_packet (packet, sizeof (packet) - 1, __func__, + "name: www.example\n" + "name: www1.example\n" + "name: www2.example\n" + "address: 192.0.2.1\n"); +} + +static int +do_test (void) +{ + test_aaaa_length (); + test_multiple_cnames (); + return 0; +} + +#include <support/test-driver.c> |