Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/tests/net/getaddrinfo/getaddrinfo.c
39562 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2025 Gleb Smirnoff <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <dlfcn.h>
29
#include <errno.h>
30
#include <netdb.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <resolv.h>
34
35
#include <atf-c.h>
36
37
static const char goodname[] = "www.freebsd.org";
38
static const char goodname_dot[] = "www.freebsd.org.";
39
static const char badname[] = "does-not-exist.freebsd.org";
40
static const char badname_dot[] = "does-not-exist.freebsd.org.";
41
static const char ipv6onlyname[] = "beefy15.nyi.freebsd.org";
42
static const char ipv6onlyname_dot[] = "beefy15.nyi.freebsd.org.";
43
static const char ipv4onlyname[] = "ipv4only.arpa";
44
static const char ipv4onlyname_dot[] = "ipv4only.arpa.";
45
/*
46
* We need an IP address that doesn't exist, but not reported with ICMP
47
* unreachable by the nearest router. Let's try TEST-NET-3.
48
*/
49
static char badresolvconf[] = "nameserver 203.0.113.1";
50
static char badresolvconf2[] = "nameserver 203.0.113.1\n"
51
"nameserver 203.0.113.2";
52
static char *resconf = NULL;
53
FILE *
54
fopen(const char * restrict path, const char * restrict mode)
55
{
56
static FILE *(*orig)(const char *, const char *);
57
58
if (orig == NULL && (orig = dlsym(RTLD_NEXT, "fopen")) == NULL)
59
atf_libc_error(ENOENT, "dlsym(fopen): %s", dlerror());
60
if (resconf != NULL && strcmp(path, _PATH_RESCONF) == 0)
61
return (fmemopen(resconf, strlen(resconf), mode));
62
else
63
return (orig(path, mode));
64
}
65
66
static int send_error = 0;
67
ssize_t
68
send(int s, const void *msg, size_t len, int flags)
69
{
70
static ssize_t (*orig)(int, const void *, size_t, int);
71
72
if (orig == NULL && (orig = dlsym(RTLD_NEXT, "send")) == NULL)
73
atf_libc_error(ENOENT, "dlsym(send): %s", dlerror());
74
if (send_error != 0) {
75
errno = send_error;
76
return (-1);
77
} else {
78
return (orig(s, msg, len, flags));
79
}
80
}
81
82
ATF_TC(basic);
83
ATF_TC_HEAD(basic, tc)
84
{
85
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
86
}
87
88
ATF_TC_BODY(basic, tc)
89
{
90
static const struct addrinfo hints = {
91
.ai_family = AF_UNSPEC,
92
.ai_flags = AI_CANONNAME,
93
};
94
struct addrinfo *res;
95
int rv;
96
97
rv = getaddrinfo(goodname, NULL, &hints, &res);
98
ATF_REQUIRE_MSG(rv == 0,
99
"Expected 0, got %d (%s)", rv, gai_strerror(rv));
100
freeaddrinfo(res);
101
102
rv = getaddrinfo(goodname_dot, NULL, &hints, &res);
103
ATF_REQUIRE_MSG(rv == 0,
104
"Expected 0, got %d (%s)", rv, gai_strerror(rv));
105
freeaddrinfo(res);
106
107
rv = getaddrinfo(badname, NULL, &hints, &res);
108
ATF_REQUIRE_MSG(rv == EAI_NONAME,
109
"Expected %d (EAI_NONAME), got %d (%s)",
110
EAI_NONAME, rv, gai_strerror(rv));
111
112
rv = getaddrinfo(badname_dot, NULL, &hints, &res);
113
ATF_REQUIRE_MSG(rv == EAI_NONAME,
114
"Expected %d (EAI_NONAME), got %d (%s)",
115
EAI_NONAME, rv, gai_strerror(rv));
116
}
117
118
ATF_TC_WITHOUT_HEAD(timeout);
119
ATF_TC_BODY(timeout, tc)
120
{
121
static const struct addrinfo hints = {
122
.ai_family = AF_UNSPEC,
123
.ai_flags = AI_CANONNAME,
124
};
125
struct addrinfo *res;
126
int rv;
127
128
resconf = badresolvconf;
129
rv = getaddrinfo(goodname, NULL, &hints, &res);
130
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
131
"Expected %d (EAI_AGAIN), got %d (%s)",
132
EAI_AGAIN, rv, gai_strerror(rv));
133
134
rv = getaddrinfo(goodname_dot, NULL, &hints, &res);
135
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
136
"Expected %d (EAI_AGAIN), got %d (%s)",
137
EAI_AGAIN, rv, gai_strerror(rv));
138
}
139
140
ATF_TC_WITHOUT_HEAD(timeout_specific);
141
ATF_TC_BODY(timeout_specific, tc)
142
{
143
static const struct addrinfo hints = {
144
.ai_family = AF_INET,
145
.ai_socktype = SOCK_STREAM,
146
.ai_flags = AI_CANONNAME,
147
};
148
struct addrinfo *res;
149
int rv;
150
151
resconf = badresolvconf;
152
rv = getaddrinfo(goodname, "666", &hints, &res);
153
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
154
"Expected %d (EAI_AGAIN), got %d (%s)",
155
EAI_AGAIN, rv, gai_strerror(rv));
156
157
rv = getaddrinfo(goodname_dot, "666", &hints, &res);
158
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
159
"Expected %d (EAI_AGAIN), got %d (%s)",
160
EAI_AGAIN, rv, gai_strerror(rv));
161
}
162
163
ATF_TC_WITHOUT_HEAD(timeout2);
164
ATF_TC_BODY(timeout2, tc)
165
{
166
static const struct addrinfo hints = {
167
.ai_family = AF_UNSPEC,
168
.ai_flags = AI_CANONNAME,
169
};
170
struct addrinfo *res;
171
int rv;
172
173
resconf = badresolvconf2;
174
rv = getaddrinfo(goodname, NULL, &hints, &res);
175
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
176
"Expected %d (EAI_AGAIN), got %d (%s)",
177
EAI_AGAIN, rv, gai_strerror(rv));
178
179
rv = getaddrinfo(goodname_dot, NULL, &hints, &res);
180
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
181
"Expected %d (EAI_AGAIN), got %d (%s)",
182
EAI_AGAIN, rv, gai_strerror(rv));
183
}
184
185
/*
186
* Emulate interface/network down.
187
*/
188
ATF_TC_WITHOUT_HEAD(netdown);
189
ATF_TC_BODY(netdown, tc)
190
{
191
static const struct addrinfo hints = {
192
.ai_family = AF_UNSPEC,
193
.ai_flags = AI_CANONNAME,
194
};
195
struct addrinfo *res;
196
int rv;
197
198
send_error = ENETDOWN;
199
rv = getaddrinfo(goodname, NULL, &hints, &res);
200
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
201
"Expected %d (EAI_AGAIN), got %d (%s)",
202
EAI_AGAIN, rv, gai_strerror(rv));
203
204
rv = getaddrinfo(goodname_dot, NULL, &hints, &res);
205
ATF_REQUIRE_MSG(rv == EAI_AGAIN,
206
"Expected %d (EAI_AGAIN), got %d (%s)",
207
EAI_AGAIN, rv, gai_strerror(rv));
208
}
209
210
/*
211
* See https://reviews.freebsd.org/D37139.
212
*/
213
ATF_TC(nofamily);
214
ATF_TC_HEAD(nofamily, tc)
215
{
216
atf_tc_set_md_var(tc, "require.config", "allow_network_access");
217
}
218
ATF_TC_BODY(nofamily, tc)
219
{
220
static const struct addrinfo hints4 = {
221
.ai_family = AF_INET,
222
.ai_flags = AI_CANONNAME,
223
}, hints6 = {
224
.ai_family = AF_INET6,
225
.ai_flags = AI_CANONNAME,
226
};
227
struct addrinfo *res;
228
int rv;
229
230
rv = getaddrinfo(ipv6onlyname, NULL, &hints4, &res);
231
ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY,
232
"Expected %d (EAI_ADDRFAMILY), got %d (%s)",
233
EAI_ADDRFAMILY, rv, gai_strerror(rv));
234
235
rv = getaddrinfo(ipv6onlyname_dot, NULL, &hints4, &res);
236
ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY,
237
"Expected %d (EAI_ADDRFAMILY), got %d (%s)",
238
EAI_ADDRFAMILY, rv, gai_strerror(rv));
239
240
rv = getaddrinfo(ipv4onlyname, NULL, &hints6, &res);
241
ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY,
242
"Expected %d (EAI_ADDRFAMILY), got %d (%s)",
243
EAI_ADDRFAMILY, rv, gai_strerror(rv));
244
245
rv = getaddrinfo(ipv4onlyname_dot, NULL, &hints6, &res);
246
ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY,
247
"Expected %d (EAI_ADDRFAMILY), got %d (%s)",
248
EAI_ADDRFAMILY, rv, gai_strerror(rv));
249
250
rv = getaddrinfo(badname, NULL, &hints4, &res);
251
ATF_REQUIRE_MSG(rv == EAI_NONAME,
252
"Expected %d (EAI_NONAME), got %d (%s)",
253
EAI_NONAME, rv, gai_strerror(rv));
254
255
rv = getaddrinfo(badname_dot, NULL, &hints6, &res);
256
ATF_REQUIRE_MSG(rv == EAI_NONAME,
257
"Expected %d (EAI_NONAME), got %d (%s)",
258
EAI_NONAME, rv, gai_strerror(rv));
259
}
260
261
ATF_TP_ADD_TCS(tp)
262
{
263
ATF_TP_ADD_TC(tp, basic);
264
ATF_TP_ADD_TC(tp, timeout);
265
ATF_TP_ADD_TC(tp, timeout_specific);
266
ATF_TP_ADD_TC(tp, timeout2);
267
ATF_TP_ADD_TC(tp, netdown);
268
ATF_TP_ADD_TC(tp, nofamily);
269
270
return (atf_no_error());
271
}
272
273