1 /* Test __libc_res_nsend buffer mismanagement, basic TCP coverage.
2 Copyright (C) 2016-2021 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
25 #include <support/check.h>
26 #include <support/check_nss.h>
27 #include <support/resolv_test.h>
28 #include <support/xthread.h>
29 #include <support/xmemstream.h>
31 static pthread_mutex_t lock
= PTHREAD_MUTEX_INITIALIZER
;
33 static int initial_address_count
= 1;
34 static int subsequent_address_count
= 2000;
35 static int response_number
= 0;
38 response (const struct resolv_response_context
*ctx
,
39 struct resolv_response_builder
*b
,
40 const char *qname
, uint16_t qclass
, uint16_t qtype
)
42 TEST_VERIFY_EXIT (qname
!= NULL
);
44 /* If not using TCP, just force its use. */
47 struct resolv_response_flags flags
= {.tc
= true};
48 resolv_response_init (b
, flags
);
49 resolv_response_add_question (b
, qname
, qclass
, qtype
);
53 struct resolv_response_flags flags
= {};
54 resolv_response_init (b
, flags
);
55 resolv_response_add_question (b
, qname
, qclass
, qtype
);
57 resolv_response_section (b
, ns_s_an
);
59 /* The number of addresses (in the additional section) for the name
60 server record (in the authoritative section). */
62 xpthread_mutex_lock (&lock
);
64 if (response_number
== 1)
65 address_count
= initial_address_count
;
66 else if (response_number
== 2)
69 resolv_response_drop (b
);
70 resolv_response_close (b
);
73 address_count
= subsequent_address_count
;
74 xpthread_mutex_unlock (&lock
);
76 /* Only add the address record to the answer section if we requested
77 any name server addresses. */
78 if (address_count
> 0)
80 resolv_response_open_record (b
, qname
, qclass
, qtype
, 0);
85 char ipv4
[4] = {10, response_number
>> 8, response_number
, 0};
86 ipv4
[3] = 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
87 resolv_response_add_data (b
, &ipv4
, sizeof (ipv4
));
93 = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0,
94 response_number
>> 8, response_number
, 0, 0};
95 ipv6
[15] = 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
96 resolv_response_add_data (b
, &ipv6
, sizeof (ipv6
));
100 support_record_failure ();
101 printf ("error: unexpected QTYPE: %s/%u/%u\n",
102 qname
, qclass
, qtype
);
104 resolv_response_close_record (b
);
106 /* Add the name server record. */
107 resolv_response_section (b
, ns_s_ns
);
108 resolv_response_open_record (b
, "example", C_IN
, T_NS
, 0);
109 resolv_response_add_name (b
, "ns.example");
110 resolv_response_close_record (b
);
112 /* Increase the response size with name server addresses. These
113 addresses are not copied out of nss_dns, and thus do not
114 trigger getaddrinfo retries with a larger buffer, making
115 testing more predictable. */
116 resolv_response_section (b
, ns_s_ar
);
117 for (int i
= 1; i
<= address_count
; ++i
)
119 resolv_response_open_record (b
, "ns.example", qclass
, qtype
, 0);
124 char ipv4
[4] = {response_number
, i
>> 8, i
, 0};
125 ipv4
[3] = 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
126 resolv_response_add_data (b
, &ipv4
, sizeof (ipv4
));
132 = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0,
133 response_number
>> 8, response_number
,
135 ipv6
[15] = 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
136 resolv_response_add_data (b
, &ipv6
, sizeof (ipv6
));
140 support_record_failure ();
141 printf ("error: unexpected QTYPE: %s/%u/%u\n",
142 qname
, qclass
, qtype
);
144 resolv_response_close_record (b
);
150 expected_result (unsigned port
, unsigned response_number
)
152 struct xmemstream mem
;
153 xopen_memstream (&mem
);
154 /* We fail the second TCP query to the first server by closing the
155 connection immediately, without returning any data. This should
156 cause failover to the second server. */
157 int server_index
= 1;
158 fprintf (mem
.out
, "address: STREAM/TCP 10.%u.%u.%u %u\n",
159 (response_number
>> 8) & 0xff, response_number
& 0xff,
160 2 + 4 * server_index
, port
);
161 fprintf (mem
.out
, "address: STREAM/TCP 2001:db8::%x:%x %u\n",
162 (response_number
+ 1) & 0xffff,
163 2 + 4 * server_index
, port
);
164 xfclose_memstream (&mem
);
169 test_different_sizes (void)
171 struct addrinfo hints
=
173 .ai_family
= AF_UNSPEC
,
174 .ai_socktype
= SOCK_STREAM
,
175 .ai_protocol
= IPPROTO_TCP
,
181 /* This magic number produces a response size close to 2048
183 initial_address_count
= 124;
186 ret
= getaddrinfo ("www.example", "80", &hints
, &ai
);
187 expected
= expected_result (80, 3);
188 check_addrinfo ("www.example:80", ai
, ret
, expected
);
194 ret
= getaddrinfo ("www123.example", "80", &hints
, &ai
);
199 ret
= getaddrinfo ("www1234.example", "80", &hints
, &ai
);
204 ret
= getaddrinfo ("www12345.example", "80", &hints
, &ai
);
212 struct resolv_test
*obj
= resolv_test_start
213 ((struct resolv_redirect_config
)
215 .response_callback
= response
218 test_different_sizes ();
220 _res
.options
|= RES_SNGLKUP
;
221 test_different_sizes ();
223 _res
.options
|= RES_SNGLKUPREOP
;
224 test_different_sizes ();
226 resolv_test_end (obj
);
230 #include <support/test-driver.c>