1 | /* Test name resolution behavior for octal, hexadecimal IPv4 addresses. |
2 | Copyright (C) 2019-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 <netdb.h> |
20 | #include <stdlib.h> |
21 | #include <support/check.h> |
22 | #include <support/check_nss.h> |
23 | #include <support/resolv_test.h> |
24 | #include <support/support.h> |
25 | |
26 | static void |
27 | response (const struct resolv_response_context *ctx, |
28 | struct resolv_response_builder *b, |
29 | const char *qname, uint16_t qclass, uint16_t qtype) |
30 | { |
31 | /* The tests are not supposed send any DNS queries. */ |
32 | FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d" , qname, qclass, qtype); |
33 | } |
34 | |
35 | static void |
36 | run_query_addrinfo (const char *query, const char *address) |
37 | { |
38 | char *quoted_query = support_quote_string (query); |
39 | |
40 | struct addrinfo *ai; |
41 | struct addrinfo hints = |
42 | { |
43 | .ai_socktype = SOCK_STREAM, |
44 | .ai_protocol = IPPROTO_TCP, |
45 | }; |
46 | |
47 | char *context = xasprintf (format: "getaddrinfo \"%s\" AF_INET" , quoted_query); |
48 | char *expected = xasprintf (format: "address: STREAM/TCP %s 80\n" , address); |
49 | hints.ai_family = AF_INET; |
50 | int ret = getaddrinfo (name: query, service: "80" , req: &hints, pai: &ai); |
51 | check_addrinfo (query_description: context, ai, ret, expected); |
52 | if (ret == 0) |
53 | freeaddrinfo (ai: ai); |
54 | free (ptr: context); |
55 | |
56 | context = xasprintf (format: "getaddrinfo \"%s\" AF_UNSPEC" , quoted_query); |
57 | hints.ai_family = AF_UNSPEC; |
58 | ret = getaddrinfo (name: query, service: "80" , req: &hints, pai: &ai); |
59 | check_addrinfo (query_description: context, ai, ret, expected); |
60 | if (ret == 0) |
61 | freeaddrinfo (ai: ai); |
62 | free (ptr: expected); |
63 | free (ptr: context); |
64 | |
65 | context = xasprintf (format: "getaddrinfo \"%s\" AF_INET6" , quoted_query); |
66 | expected = xasprintf (format: "flags: AI_V4MAPPED\n" |
67 | "address: STREAM/TCP ::ffff:%s 80\n" , |
68 | address); |
69 | hints.ai_family = AF_INET6; |
70 | hints.ai_flags = AI_V4MAPPED; |
71 | ret = getaddrinfo (name: query, service: "80" , req: &hints, pai: &ai); |
72 | check_addrinfo (query_description: context, ai, ret, expected); |
73 | if (ret == 0) |
74 | freeaddrinfo (ai: ai); |
75 | free (ptr: expected); |
76 | free (ptr: context); |
77 | |
78 | free (ptr: quoted_query); |
79 | } |
80 | |
81 | static void |
82 | run_query (const char *query, const char *address) |
83 | { |
84 | char *quoted_query = support_quote_string (query); |
85 | char *context = xasprintf (format: "gethostbyname (\"%s\")" , quoted_query); |
86 | char *expected = xasprintf (format: "name: %s\n" |
87 | "address: %s\n" , query, address); |
88 | check_hostent (query_description: context, gethostbyname (name: query), expected); |
89 | free (ptr: context); |
90 | |
91 | context = xasprintf (format: "gethostbyname_r \"%s\"" , quoted_query); |
92 | struct hostent storage; |
93 | char buf[4096]; |
94 | struct hostent *e = NULL; |
95 | TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), |
96 | &e, &h_errno), 0); |
97 | check_hostent (query_description: context, e, expected); |
98 | free (ptr: context); |
99 | |
100 | context = xasprintf (format: "gethostbyname2 (\"%s\", AF_INET)" , quoted_query); |
101 | check_hostent (query_description: context, gethostbyname2 (name: query, AF_INET), expected); |
102 | free (ptr: context); |
103 | |
104 | context = xasprintf (format: "gethostbyname2_r \"%s\" AF_INET" , quoted_query); |
105 | e = NULL; |
106 | TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf), |
107 | &e, &h_errno), 0); |
108 | check_hostent (query_description: context, e, expected); |
109 | free (ptr: context); |
110 | free (ptr: expected); |
111 | |
112 | free (ptr: quoted_query); |
113 | |
114 | /* The gethostbyname tests are always valid for getaddrinfo, but not |
115 | vice versa. */ |
116 | run_query_addrinfo (query, address); |
117 | } |
118 | |
119 | static int |
120 | do_test (void) |
121 | { |
122 | struct resolv_test *aux = resolv_test_start |
123 | ((struct resolv_redirect_config) |
124 | { |
125 | .response_callback = response, |
126 | }); |
127 | |
128 | run_query (query: "192.000.002.010" , address: "192.0.2.8" ); |
129 | |
130 | /* Hexadecimal numbers are not accepted by gethostbyname. */ |
131 | run_query_addrinfo (query: "0xc0000210" , address: "192.0.2.16" ); |
132 | run_query_addrinfo (query: "192.0x234" , address: "192.0.2.52" ); |
133 | |
134 | resolv_test_end (aux); |
135 | |
136 | return 0; |
137 | } |
138 | |
139 | #include <support/test-driver.c> |
140 | |