diff options
author | Florian Weimer <fweimer@redhat.com> | 2018-01-08 14:33:17 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2018-01-08 20:07:24 +0100 |
commit | 401311cfba71b61d93d23aa17e5c9ac5fb047d48 (patch) | |
tree | c75e333a4167d782bd22da480b516c6b7e07c9ae /resolv | |
parent | 2b3aa44656dd873e2753c98fdcb95be6a9d147a6 (diff) | |
download | glibc-401311cfba71b61d93d23aa17e5c9ac5fb047d48.tar glibc-401311cfba71b61d93d23aa17e5c9ac5fb047d48.tar.gz glibc-401311cfba71b61d93d23aa17e5c9ac5fb047d48.tar.bz2 glibc-401311cfba71b61d93d23aa17e5c9ac5fb047d48.zip |
resolv: Support binary labels in test framework
The old implementation based on hsearch_r used an ad-hoc C string
encoding and produced an incorrect format on the wire for domain
names which contained bytes which needed escaping when printed.
This commit switches to ns_name_pton for the wire format conversion
(now that we have separate tests for it) and uses a tsearch tree
with a suitable comparison function to locate compression targets.
Diffstat (limited to 'resolv')
-rw-r--r-- | resolv/Makefile | 2 | ||||
-rw-r--r-- | resolv/tst-resolv-binary.c | 120 |
2 files changed, 122 insertions, 0 deletions
diff --git a/resolv/Makefile b/resolv/Makefile index b98e68f6cc..6e70ae9f6b 100644 --- a/resolv/Makefile +++ b/resolv/Makefile @@ -51,6 +51,7 @@ tests += \ tst-res_hnok \ tst-res_use_inet6 \ tst-resolv-basic \ + tst-resolv-binary \ tst-resolv-edns \ tst-resolv-network \ tst-resolv-res_init-multi \ @@ -159,6 +160,7 @@ $(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so diff --git a/resolv/tst-resolv-binary.c b/resolv/tst-resolv-binary.c new file mode 100644 index 0000000000..e7e6d87994 --- /dev/null +++ b/resolv/tst-resolv-binary.c @@ -0,0 +1,120 @@ +/* Test handling of binary domain names with res_send. + Copyright (C) 2018 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 <resolv.h> +#include <string.h> +#include <support/check.h> +#include <support/resolv_test.h> + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_COMPARE (qclass, C_IN); + TEST_COMPARE (qtype, T_TXT); + TEST_VERIFY (strlen (qname) <= 255); + + struct resolv_response_flags flags = { 0 }; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_TXT, 0x12345678); + unsigned char qnamelen = strlen (qname); + resolv_response_add_data (b, &qnamelen, 1); + resolv_response_add_data (b, qname, qnamelen); + resolv_response_close_record (b); +} + +static int +do_test (void) +{ + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + for (int b = 0; b <= 255; ++b) + { + unsigned char query[] = + { + b, b, /* Transaction ID. */ + 1, 0, /* Query with RD flag. */ + 0, 1, /* One question. */ + 0, 0, 0, 0, 0, 0, /* The other sections are empty. */ + 1, b, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0, + 0, T_TXT, /* TXT query. */ + 0, 1, /* Class IN. */ + }; + unsigned char response[512]; + int ret = res_send (query, sizeof (query), response, sizeof (response)); + + char expected_name[20]; + /* The name is uncompressed in the query, so we can reference it + directly. */ + TEST_VERIFY_EXIT (ns_name_ntop (query + 12, expected_name, + sizeof (expected_name)) >= 0); + TEST_COMPARE (ret, + (ssize_t) sizeof (query) + + 2 /* Compression reference. */ + + 2 + 2 + 4 + 2 /* Type, class, TTL, RDATA length. */ + + 1 /* Pascal-style string length. */ + + strlen (expected_name)); + + /* Mark as answer, with recursion available, and one answer. */ + query[2] = 0x81; + query[3] = 0x80; + query[7] = 1; + + /* Prefix of the response must match the query. */ + TEST_COMPARE (memcmp (response, query, sizeof (query)), 0); + + /* The actual answer follows, starting with the compression + reference. */ + unsigned char *p = response + sizeof (query); + TEST_COMPARE (*p++, 0xc0); + TEST_COMPARE (*p++, 0x0c); + + /* Type and class. */ + TEST_COMPARE (*p++, 0); + TEST_COMPARE (*p++, T_TXT); + TEST_COMPARE (*p++, 0); + TEST_COMPARE (*p++, C_IN); + + /* TTL. */ + TEST_COMPARE (*p++, 0x12); + TEST_COMPARE (*p++, 0x34); + TEST_COMPARE (*p++, 0x56); + TEST_COMPARE (*p++, 0x78); + + /* RDATA length. */ + TEST_COMPARE (*p++, 0); + TEST_COMPARE (*p++, 1 + strlen (expected_name)); + + /* RDATA. */ + TEST_COMPARE (*p++, strlen (expected_name)); + TEST_COMPARE (memcmp (p, expected_name, strlen (expected_name)), 0); + } + + resolv_test_end (aux); + + return 0; +} + +#include <support/test-driver.c> |