1 /* Test handling of binary domain names with res_send.
2    Copyright (C) 2018-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <resolv.h>
20 #include <string.h>
21 #include <support/check.h>
22 #include <support/resolv_test.h>
23 
24 static void
response(const struct resolv_response_context * ctx,struct resolv_response_builder * b,const char * qname,uint16_t qclass,uint16_t qtype)25 response (const struct resolv_response_context *ctx,
26           struct resolv_response_builder *b,
27           const char *qname, uint16_t qclass, uint16_t qtype)
28 {
29   TEST_COMPARE (qclass, C_IN);
30   TEST_COMPARE (qtype, T_TXT);
31   TEST_VERIFY (strlen (qname) <= 255);
32 
33   struct resolv_response_flags flags = { 0 };
34   resolv_response_init (b, flags);
35   resolv_response_add_question (b, qname, qclass, qtype);
36   resolv_response_section (b, ns_s_an);
37   resolv_response_open_record (b, qname, qclass, T_TXT, 0x12345678);
38   unsigned char qnamelen = strlen (qname);
39   resolv_response_add_data (b, &qnamelen, 1);
40   resolv_response_add_data (b, qname, qnamelen);
41   resolv_response_close_record (b);
42 }
43 
44 static int
do_test(void)45 do_test (void)
46 {
47   struct resolv_test *aux = resolv_test_start
48     ((struct resolv_redirect_config)
49      {
50        .response_callback = response,
51      });
52 
53   for (int b = 0; b <= 255; ++b)
54     {
55       unsigned char query[] =
56         {
57           b, b,                 /* Transaction ID.  */
58           1, 0,                 /* Query with RD flag.  */
59           0, 1,                 /* One question.  */
60           0, 0, 0, 0, 0, 0,     /* The other sections are empty.  */
61           1, b, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
62           0, T_TXT,             /* TXT query.  */
63           0, 1,                 /* Class IN.  */
64         };
65       unsigned char response[512];
66       int ret = res_send (query, sizeof (query), response, sizeof (response));
67 
68       char expected_name[20];
69       /* The name is uncompressed in the query, so we can reference it
70          directly.  */
71       TEST_VERIFY_EXIT (ns_name_ntop (query + 12, expected_name,
72                                       sizeof (expected_name)) >= 0);
73       TEST_COMPARE (ret,
74                     (ssize_t) sizeof (query)
75                     + 2             /* Compression reference.  */
76                     + 2 + 2 + 4 + 2 /* Type, class, TTL, RDATA length.  */
77                     + 1             /* Pascal-style string length.  */
78                     + strlen (expected_name));
79 
80       /* Mark as answer, with recursion available, and one answer.  */
81       query[2] = 0x81;
82       query[3] = 0x80;
83       query[7] = 1;
84 
85       /* Prefix of the response must match the query.  */
86       TEST_COMPARE (memcmp (response, query, sizeof (query)), 0);
87 
88       /* The actual answer follows, starting with the compression
89          reference.  */
90       unsigned char *p = response + sizeof (query);
91       TEST_COMPARE (*p++, 0xc0);
92       TEST_COMPARE (*p++, 0x0c);
93 
94       /* Type and class.  */
95       TEST_COMPARE (*p++, 0);
96       TEST_COMPARE (*p++, T_TXT);
97       TEST_COMPARE (*p++, 0);
98       TEST_COMPARE (*p++, C_IN);
99 
100       /* TTL.  */
101       TEST_COMPARE (*p++, 0x12);
102       TEST_COMPARE (*p++, 0x34);
103       TEST_COMPARE (*p++, 0x56);
104       TEST_COMPARE (*p++, 0x78);
105 
106       /* RDATA length.  */
107       TEST_COMPARE (*p++, 0);
108       TEST_COMPARE (*p++, 1 + strlen (expected_name));
109 
110       /* RDATA.  */
111       TEST_COMPARE (*p++, strlen (expected_name));
112       TEST_COMPARE (memcmp (p, expected_name, strlen (expected_name)), 0);
113     }
114 
115   resolv_test_end (aux);
116 
117   return 0;
118 }
119 
120 #include <support/test-driver.c>
121