Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/tests/nss/getaddrinfo_test.c
39500 views
1
/*-
2
* Copyright (c) 2006 Michael Bushkov <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*
26
*/
27
28
#include <sys/param.h>
29
#include <sys/socket.h>
30
#include <arpa/inet.h>
31
#include <netinet/in.h>
32
#include <errno.h>
33
#include <netdb.h>
34
#include <resolv.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <stringlist.h>
39
#include <unistd.h>
40
41
#include <atf-c.h>
42
43
#include "freebsd_test_suite/macros.h"
44
#include "testutil.h"
45
46
enum test_methods {
47
TEST_GETADDRINFO,
48
TEST_BUILD_SNAPSHOT
49
};
50
51
static struct addrinfo hints;
52
static enum test_methods method = TEST_GETADDRINFO;
53
54
DECLARE_TEST_DATA(addrinfo)
55
DECLARE_TEST_FILE_SNAPSHOT(addrinfo)
56
DECLARE_2PASS_TEST(addrinfo)
57
58
static void clone_addrinfo(struct addrinfo *, struct addrinfo const *);
59
static int compare_addrinfo(struct addrinfo *, struct addrinfo *, void *);
60
static void dump_addrinfo(struct addrinfo *);
61
62
static void sdump_addrinfo(struct addrinfo *, char *, size_t);
63
64
IMPLEMENT_TEST_DATA(addrinfo)
65
IMPLEMENT_TEST_FILE_SNAPSHOT(addrinfo)
66
IMPLEMENT_2PASS_TEST(addrinfo)
67
68
static void
69
clone_addrinfo(struct addrinfo *dest, struct addrinfo const *src)
70
{
71
72
ATF_REQUIRE(dest != NULL);
73
ATF_REQUIRE(src != NULL);
74
75
memcpy(dest, src, sizeof(struct addrinfo));
76
if (src->ai_canonname != NULL)
77
dest->ai_canonname = strdup(src->ai_canonname);
78
79
if (src->ai_addr != NULL) {
80
dest->ai_addr = malloc(src->ai_addrlen);
81
ATF_REQUIRE(dest->ai_addr != NULL);
82
memcpy(dest->ai_addr, src->ai_addr, src->ai_addrlen);
83
}
84
85
if (src->ai_next != NULL) {
86
dest->ai_next = malloc(sizeof(struct addrinfo));
87
ATF_REQUIRE(dest->ai_next != NULL);
88
clone_addrinfo(dest->ai_next, src->ai_next);
89
}
90
}
91
92
static int
93
compare_addrinfo_(struct addrinfo *ai1, struct addrinfo *ai2)
94
{
95
96
if ((ai1 == NULL) || (ai2 == NULL))
97
return (-1);
98
99
if (ai1->ai_flags != ai2->ai_flags ||
100
ai1->ai_family != ai2->ai_family ||
101
ai1->ai_socktype != ai2->ai_socktype ||
102
ai1->ai_protocol != ai2->ai_protocol ||
103
ai1->ai_addrlen != ai2->ai_addrlen ||
104
((ai1->ai_addr == NULL || ai2->ai_addr == NULL) &&
105
ai1->ai_addr != ai2->ai_addr) ||
106
((ai1->ai_canonname == NULL || ai2->ai_canonname == NULL) &&
107
ai1->ai_canonname != ai2->ai_canonname))
108
return (-1);
109
110
if (ai1->ai_canonname != NULL &&
111
strcmp(ai1->ai_canonname, ai2->ai_canonname) != 0)
112
return (-1);
113
114
if (ai1->ai_addr != NULL &&
115
memcmp(ai1->ai_addr, ai2->ai_addr, ai1->ai_addrlen) != 0)
116
return (-1);
117
118
if (ai1->ai_next == NULL && ai2->ai_next == NULL)
119
return (0);
120
else
121
return (compare_addrinfo_(ai1->ai_next, ai2->ai_next));
122
}
123
124
static int
125
compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2,
126
void *mdata __unused)
127
{
128
int rv;
129
130
printf("testing equality of 2 addrinfo structures\n");
131
132
rv = compare_addrinfo_(ai1, ai2);
133
134
if (rv == 0)
135
printf("equal\n");
136
else {
137
dump_addrinfo(ai1);
138
dump_addrinfo(ai2);
139
printf("not equal\n");
140
}
141
142
return (rv);
143
}
144
145
static void
146
free_addrinfo(struct addrinfo *ai)
147
{
148
if (ai == NULL)
149
return;
150
151
free(ai->ai_addr);
152
free(ai->ai_canonname);
153
free_addrinfo(ai->ai_next);
154
}
155
156
void
157
sdump_addrinfo(struct addrinfo *ai, char *buffer, size_t buflen)
158
{
159
int written, i;
160
161
written = snprintf(buffer, buflen, "%d %d %d %d %d ",
162
ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol,
163
ai->ai_addrlen);
164
buffer += written;
165
if (written > (int)buflen)
166
return;
167
buflen -= written;
168
169
written = snprintf(buffer, buflen, "%s ",
170
ai->ai_canonname == NULL ? "(null)" : ai->ai_canonname);
171
buffer += written;
172
if (written > (int)buflen)
173
return;
174
buflen -= written;
175
176
if (ai->ai_addr == NULL) {
177
written = snprintf(buffer, buflen, "(null)");
178
buffer += written;
179
if (written > (int)buflen)
180
return;
181
buflen -= written;
182
} else {
183
for (i = 0; i < (int)ai->ai_addrlen; i++) {
184
written = snprintf(buffer, buflen,
185
i + 1 != (int)ai->ai_addrlen ? "%d." : "%d",
186
((unsigned char *)ai->ai_addr)[i]);
187
buffer += written;
188
if (written > (int)buflen)
189
return;
190
buflen -= written;
191
192
if (buflen == 0)
193
return;
194
}
195
}
196
197
if (ai->ai_next != NULL) {
198
written = snprintf(buffer, buflen, ":");
199
buffer += written;
200
if (written > (int)buflen)
201
return;
202
buflen -= written;
203
204
sdump_addrinfo(ai->ai_next, buffer, buflen);
205
}
206
}
207
208
void
209
dump_addrinfo(struct addrinfo *result)
210
{
211
if (result != NULL) {
212
char buffer[2048];
213
sdump_addrinfo(result, buffer, sizeof(buffer));
214
printf("%s\n", buffer);
215
} else
216
printf("(null)\n");
217
}
218
219
static int
220
addrinfo_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
221
{
222
char *s, *ps, *ts;
223
224
ps = addr;
225
while ((s = strsep(&ps, ".")) != NULL) {
226
if (len == 0)
227
return (-1);
228
229
*result = (unsigned char)strtol(s, &ts, 10);
230
++result;
231
if (*ts != '\0')
232
return (-1);
233
234
--len;
235
}
236
if (len != 0)
237
return (-1);
238
else
239
return (0);
240
}
241
242
static int
243
addrinfo_read_snapshot_ai(struct addrinfo *ai, char *line)
244
{
245
char *s, *ps, *ts;
246
int i, rv, *pi;
247
248
rv = 0;
249
i = 0;
250
ps = line;
251
memset(ai, 0, sizeof(struct addrinfo));
252
while ((s = strsep(&ps, " ")) != NULL) {
253
switch (i) {
254
case 0:
255
case 1:
256
case 2:
257
case 3:
258
pi = &ai->ai_flags + i;
259
*pi = (int)strtol(s, &ts, 10);
260
if (*ts != '\0')
261
goto fin;
262
break;
263
case 4:
264
ai->ai_addrlen = (socklen_t)strtol(s, &ts, 10);
265
if (*ts != '\0')
266
goto fin;
267
break;
268
case 5:
269
if (strcmp(s, "(null)") != 0) {
270
ai->ai_canonname = strdup(s);
271
ATF_REQUIRE(ai->ai_canonname != NULL);
272
}
273
break;
274
case 6:
275
if (strcmp(s, "(null)") != 0) {
276
ai->ai_addr = calloc(1, ai->ai_addrlen);
277
ATF_REQUIRE(ai->ai_addr != NULL);
278
rv = addrinfo_read_snapshot_addr(s,
279
(unsigned char *)ai->ai_addr,
280
ai->ai_addrlen);
281
282
if (rv != 0)
283
goto fin;
284
}
285
break;
286
default:
287
/* NOTE: should not be reachable */
288
rv = -1;
289
goto fin;
290
}
291
292
++i;
293
}
294
295
fin:
296
if (i != 7 || rv != 0) {
297
free_addrinfo(ai);
298
ai = NULL;
299
return (-1);
300
}
301
302
return (0);
303
}
304
305
static int
306
addrinfo_read_snapshot_func(struct addrinfo *ai, char *line)
307
{
308
struct addrinfo *ai2;
309
char *s, *ps;
310
int rv;
311
312
printf("1 line read from snapshot:\n%s\n", line);
313
314
rv = 0;
315
ps = line;
316
317
s = strsep(&ps, ":");
318
if (s == NULL)
319
return (-1);
320
321
rv = addrinfo_read_snapshot_ai(ai, s);
322
if (rv != 0)
323
return (-1);
324
325
ai2 = ai;
326
while ((s = strsep(&ps, ":")) != NULL) {
327
ai2->ai_next = calloc(1, sizeof(struct addrinfo));
328
ATF_REQUIRE(ai2->ai_next != NULL);
329
330
rv = addrinfo_read_snapshot_ai(ai2->ai_next, s);
331
if (rv != 0) {
332
free_addrinfo(ai);
333
ai = NULL;
334
return (-1);
335
}
336
337
ai2 = ai2->ai_next;
338
}
339
340
return (0);
341
}
342
343
static int
344
addrinfo_test_correctness(struct addrinfo *ai, void *mdata __unused)
345
{
346
347
printf("testing correctness with the following data:\n");
348
dump_addrinfo(ai);
349
350
if (ai == NULL)
351
goto errfin;
352
353
if (!(ai->ai_family >= 0 && ai->ai_family < AF_MAX))
354
goto errfin;
355
356
if (ai->ai_socktype != 0 && ai->ai_socktype != SOCK_STREAM &&
357
ai->ai_socktype != SOCK_DGRAM && ai->ai_socktype != SOCK_RAW)
358
goto errfin;
359
360
if (ai->ai_protocol != 0 && ai->ai_protocol != IPPROTO_UDP &&
361
ai->ai_protocol != IPPROTO_TCP)
362
goto errfin;
363
364
if ((ai->ai_flags & ~(AI_CANONNAME | AI_NUMERICHOST | AI_PASSIVE)) != 0)
365
goto errfin;
366
367
if (ai->ai_addrlen != ai->ai_addr->sa_len ||
368
ai->ai_family != ai->ai_addr->sa_family)
369
goto errfin;
370
371
printf("correct\n");
372
373
return (0);
374
errfin:
375
printf("incorrect\n");
376
377
return (-1);
378
}
379
380
static int
381
addrinfo_read_hostlist_func(struct addrinfo *ai, char *line)
382
{
383
struct addrinfo *result;
384
int rv;
385
386
printf("resolving %s: ", line);
387
rv = getaddrinfo(line, NULL, &hints, &result);
388
if (rv == 0) {
389
printf("found\n");
390
391
rv = addrinfo_test_correctness(result, NULL);
392
if (rv != 0) {
393
freeaddrinfo(result);
394
result = NULL;
395
return (rv);
396
}
397
398
clone_addrinfo(ai, result);
399
freeaddrinfo(result);
400
result = NULL;
401
} else {
402
printf("not found\n");
403
404
memset(ai, 0, sizeof(struct addrinfo));
405
}
406
return (0);
407
}
408
409
static void
410
run_tests(char *hostlist_file, const char *snapshot_file, int ai_family)
411
{
412
struct addrinfo_test_data td, td_snap;
413
char *snapshot_file_copy;
414
int rv;
415
416
if (snapshot_file == NULL)
417
snapshot_file_copy = NULL;
418
else {
419
snapshot_file_copy = strdup(snapshot_file);
420
ATF_REQUIRE(snapshot_file_copy != NULL);
421
}
422
423
memset(&hints, 0, sizeof(struct addrinfo));
424
hints.ai_family = ai_family;
425
hints.ai_flags = AI_CANONNAME;
426
427
if (snapshot_file != NULL)
428
method = TEST_BUILD_SNAPSHOT;
429
430
TEST_DATA_INIT(addrinfo, &td, clone_addrinfo, free_addrinfo);
431
TEST_DATA_INIT(addrinfo, &td_snap, clone_addrinfo, free_addrinfo);
432
433
ATF_REQUIRE_MSG(access(hostlist_file, R_OK) == 0,
434
"can't access the hostlist file %s\n", hostlist_file);
435
436
printf("building host lists from %s\n", hostlist_file);
437
438
rv = TEST_SNAPSHOT_FILE_READ(addrinfo, hostlist_file, &td,
439
addrinfo_read_hostlist_func);
440
if (rv != 0)
441
goto fin;
442
443
if (snapshot_file != NULL) {
444
if (access(snapshot_file, W_OK | R_OK) != 0) {
445
if (errno == ENOENT)
446
method = TEST_BUILD_SNAPSHOT;
447
else {
448
printf("can't access the snapshot "
449
"file %s\n", snapshot_file);
450
451
rv = -1;
452
goto fin;
453
}
454
} else {
455
rv = TEST_SNAPSHOT_FILE_READ(addrinfo, snapshot_file,
456
&td_snap, addrinfo_read_snapshot_func);
457
if (rv != 0) {
458
printf("error reading snapshot file: %s\n",
459
strerror(errno));
460
goto fin;
461
}
462
}
463
}
464
465
switch (method) {
466
case TEST_GETADDRINFO:
467
if (snapshot_file != NULL)
468
ATF_CHECK(DO_2PASS_TEST(addrinfo, &td, &td_snap,
469
compare_addrinfo, NULL) == 0);
470
break;
471
case TEST_BUILD_SNAPSHOT:
472
if (snapshot_file != NULL) {
473
ATF_CHECK(TEST_SNAPSHOT_FILE_WRITE(addrinfo,
474
snapshot_file, &td, sdump_addrinfo) == 0);
475
}
476
break;
477
default:
478
break;
479
}
480
481
fin:
482
TEST_DATA_DESTROY(addrinfo, &td_snap);
483
TEST_DATA_DESTROY(addrinfo, &td);
484
485
free(snapshot_file_copy);
486
}
487
488
#define HOSTLIST_FILE "mach"
489
#define RUN_TESTS(tc, snapshot_file, ai_family) do { \
490
char *_hostlist_file; \
491
ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \
492
atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \
493
run_tests(_hostlist_file, snapshot_file, ai_family); \
494
free(_hostlist_file); \
495
} while (0)
496
497
ATF_TC_WITHOUT_HEAD(pf_unspec);
498
ATF_TC_BODY(pf_unspec, tc)
499
{
500
501
RUN_TESTS(tc, NULL, AF_UNSPEC);
502
}
503
504
ATF_TC_WITHOUT_HEAD(pf_unspec_with_snapshot);
505
ATF_TC_BODY(pf_unspec_with_snapshot, tc)
506
{
507
508
RUN_TESTS(tc, "snapshot_ai", AF_UNSPEC);
509
}
510
511
ATF_TC_WITHOUT_HEAD(pf_inet);
512
ATF_TC_BODY(pf_inet, tc)
513
{
514
515
ATF_REQUIRE_FEATURE("inet");
516
RUN_TESTS(tc, NULL, AF_INET);
517
}
518
519
ATF_TC_WITHOUT_HEAD(pf_inet_with_snapshot);
520
ATF_TC_BODY(pf_inet_with_snapshot, tc)
521
{
522
523
ATF_REQUIRE_FEATURE("inet");
524
RUN_TESTS(tc, "snapshot_ai4", AF_INET);
525
}
526
527
ATF_TC_WITHOUT_HEAD(pf_inet6);
528
ATF_TC_BODY(pf_inet6, tc)
529
{
530
531
ATF_REQUIRE_FEATURE("inet6");
532
RUN_TESTS(tc, NULL, AF_INET6);
533
}
534
535
ATF_TC_WITHOUT_HEAD(pf_inet6_with_snapshot);
536
ATF_TC_BODY(pf_inet6_with_snapshot, tc)
537
{
538
539
ATF_REQUIRE_FEATURE("inet6");
540
RUN_TESTS(tc, "snapshot_ai6", AF_INET6);
541
}
542
543
ATF_TP_ADD_TCS(tp)
544
{
545
546
ATF_TP_ADD_TC(tp, pf_unspec);
547
ATF_TP_ADD_TC(tp, pf_unspec_with_snapshot);
548
ATF_TP_ADD_TC(tp, pf_inet);
549
ATF_TP_ADD_TC(tp, pf_inet_with_snapshot);
550
ATF_TP_ADD_TC(tp, pf_inet6);
551
ATF_TP_ADD_TC(tp, pf_inet6_with_snapshot);
552
553
return (atf_no_error());
554
}
555
556