1 /* Check that RES_ROTATE works with few nameserver entries (bug 13028).
2 Copyright (C) 2017-2020 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/>. */
23 #include <support/check.h>
24 #include <support/check_nss.h>
25 #include <support/resolv_test.h>
26 #include <support/test-driver.h>
28 static volatile int drop_server
= -1;
29 static volatile unsigned int query_counts
[resolv_max_test_servers
];
31 static const char address_ipv4
[4] = {192, 0, 2, 1};
32 static const char address_ipv6
[16]
33 = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
36 response (const struct resolv_response_context
*ctx
,
37 struct resolv_response_builder
*b
,
38 const char *qname
, uint16_t qclass
, uint16_t qtype
)
40 if (ctx
->server_index
== drop_server
)
42 resolv_response_drop (b
);
43 resolv_response_close (b
);
47 bool force_tcp
= strncmp (qname
, "2.", 2) == 0;
48 struct resolv_response_flags flags
= {.tc
= force_tcp
&& !ctx
->tcp
};
49 resolv_response_init (b
, flags
);
50 resolv_response_add_question (b
, qname
, qclass
, qtype
);
54 TEST_VERIFY_EXIT (ctx
->server_index
< resolv_max_test_servers
);
55 ++query_counts
[ctx
->server_index
];
57 resolv_response_section (b
, ns_s_an
);
58 resolv_response_open_record (b
, qname
, qclass
, qtype
, 0);
63 char addr
[sizeof (address_ipv4
)];
64 memcpy (addr
, address_ipv4
, sizeof (address_ipv4
));
65 addr
[3] = 1 + ctx
->tcp
;
66 resolv_response_add_data (b
, addr
, sizeof (addr
));
71 char addr
[sizeof (address_ipv6
)];
72 memcpy (addr
, address_ipv6
, sizeof (address_ipv6
));
73 addr
[15] = 1 + ctx
->tcp
;
74 resolv_response_add_data (b
, addr
, sizeof (addr
));
79 resolv_response_add_name (b
, "2.host.example");
81 resolv_response_add_name (b
, "host.example");
84 FAIL_EXIT1 ("unexpected QTYPE: %s/%u/%u", qname
, qclass
, qtype
);
86 resolv_response_close_record (b
);
90 check_forward_1 (const char *name
, int family
)
93 if (strncmp (name
, "2.", 2) == 0)
98 char expected_hostent_v4
[200];
99 snprintf (expected_hostent_v4
, sizeof (expected_hostent_v4
),
100 "name: %s\naddress: 192.0.2.%d\n", name
, lsb
);
101 char expected_hostent_v6
[200];
102 snprintf (expected_hostent_v6
, sizeof (expected_hostent_v6
),
103 "name: %s\naddress: 2001:db8::%d\n", name
, lsb
);
104 char expected_ai
[200];
106 unsigned char address
[16];
107 size_t address_length
;
109 char *expected_hostent
;
113 expected_hostent
= expected_hostent_v4
;
114 snprintf (expected_ai
, sizeof (expected_ai
),
115 "address: STREAM/TCP 192.0.2.%d 80\n", lsb
);
116 TEST_VERIFY_EXIT (sizeof (address_ipv4
) == sizeof (struct in_addr
));
117 memcpy (address
, address_ipv4
, sizeof (address_ipv4
));
118 address_length
= sizeof (address_ipv4
);
121 expected_hostent
= expected_hostent_v6
;
122 snprintf (expected_ai
, sizeof (expected_ai
),
123 "address: STREAM/TCP 2001:db8::%d 80\n", lsb
);
124 TEST_VERIFY_EXIT (sizeof (address_ipv6
) == sizeof (struct in6_addr
));
125 memcpy (address
, address_ipv6
, sizeof (address_ipv6
));
126 address_length
= sizeof (address_ipv6
);
129 expected_hostent
= NULL
;
130 snprintf (expected_ai
, sizeof (expected_ai
),
131 "address: STREAM/TCP 192.0.2.%d 80\n"
132 "address: STREAM/TCP 2001:db8::%d 80\n",
137 FAIL_EXIT1 ("unknown address family %d", family
);
141 if (family
== AF_INET
)
143 struct hostent
*e
= gethostbyname (name
);
144 check_hostent (name
, e
, expected_hostent_v4
);
147 if (family
!= AF_UNSPEC
)
149 struct hostent
*e
= gethostbyname2 (name
, family
);
150 check_hostent (name
, e
, expected_hostent
);
153 if (address_length
> 0)
155 address
[address_length
- 1] = lsb
;
156 struct hostent
*e
= gethostbyaddr (address
, address_length
, family
);
157 check_hostent (name
, e
, expected_hostent
);
160 struct addrinfo hints
=
163 .ai_socktype
= SOCK_STREAM
,
164 .ai_protocol
= IPPROTO_TCP
,
167 int ret
= getaddrinfo (name
, "80", &hints
, &ai
);
168 check_addrinfo (name
, ai
, ret
, expected_ai
);
171 for (struct addrinfo
*p
= ai
; p
!= NULL
; p
= p
->ai_next
)
174 ret
= getnameinfo (p
->ai_addr
, p
->ai_addrlen
,
176 NULL
, 0, /* service */
180 support_record_failure ();
181 printf ("error: getnameinfo: %d\n", ret
);
186 TEST_VERIFY (strcmp (host
, "host.example") == 0);
188 TEST_VERIFY (strcmp (host
, "2.host.example") == 0);
196 check_forward (int family
)
198 check_forward_1 ("host.example", family
);
199 check_forward_1 ("2.host.example", family
);
205 for (int force_tcp
= 0; force_tcp
< 2; ++force_tcp
)
206 for (int nscount
= 1; nscount
<= 3; ++nscount
)
207 for (int disable_server
= -1; disable_server
< nscount
; ++disable_server
)
208 for (drop_server
= -1; drop_server
< nscount
; ++drop_server
)
210 /* A disabled server will never receive queries and
211 therefore cannot drop them. */
212 if (drop_server
>= 0 && drop_server
== disable_server
)
214 /* No servers remaining to query, all queries are expected
216 int broken_servers
= (disable_server
>= 0) + (drop_server
>= 0);
217 if (nscount
<= broken_servers
)
220 if (test_verbose
> 0)
221 printf ("info: tcp=%d nscount=%d disable=%d drop=%d\n",
222 force_tcp
, nscount
, disable_server
, drop_server
);
223 struct resolv_redirect_config config
=
225 .response_callback
= response
,
228 if (disable_server
>= 0)
230 config
.servers
[disable_server
].disable_udp
= true;
231 config
.servers
[disable_server
].disable_tcp
= true;
234 struct resolv_test
*aux
= resolv_test_start (config
);
235 _res
.options
|= RES_ROTATE
;
237 /* Run a few queries to make sure that all of them
238 succeed. We always perform more than nscount queries,
239 so we cover all active servers due to RES_ROTATE. */
240 for (size_t i
= 0; i
< resolv_max_test_servers
; ++i
)
242 check_forward (AF_INET
);
243 check_forward (AF_INET6
);
244 check_forward (AF_UNSPEC
);
246 for (int i
= 0; i
< nscount
; ++i
)
248 if (i
!= disable_server
&& i
!= drop_server
249 && query_counts
[i
] == 0)
251 support_record_failure ();
252 printf ("error: nscount=%d, but no query to server %d\n",
257 resolv_test_end (aux
);
263 #include <support/test-driver.c>