2 * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <arpa/inet.h>
32 #include <sys/socket.h>
33 #include <sys/types.h>
34 #include <netinet/in.h>
42 #include <stringlist.h>
52 static struct addrinfo hints
;
53 static enum test_methods method
= TEST_GETADDRINFO
;
55 DECLARE_TEST_DATA(addrinfo
)
56 DECLARE_TEST_FILE_SNAPSHOT(addrinfo
)
57 DECLARE_2PASS_TEST(addrinfo
)
59 static void clone_addrinfo(struct addrinfo
*, struct addrinfo
const *);
60 static int compare_addrinfo(struct addrinfo
*, struct addrinfo
*, void *);
61 static void dump_addrinfo(struct addrinfo
*);
62 static void free_addrinfo(struct addrinfo
*);
64 static void sdump_addrinfo(struct addrinfo
*, char *, size_t);
66 IMPLEMENT_TEST_DATA(addrinfo
)
67 IMPLEMENT_TEST_FILE_SNAPSHOT(addrinfo
)
68 IMPLEMENT_2PASS_TEST(addrinfo
)
71 clone_addrinfo(struct addrinfo
*dest
, struct addrinfo
const *src
)
76 memcpy(dest
, src
, sizeof(struct addrinfo
));
77 if (src
->ai_canonname
!= NULL
)
78 dest
->ai_canonname
= strdup(src
->ai_canonname
);
80 if (src
->ai_addr
!= NULL
) {
81 dest
->ai_addr
= (struct sockaddr
*)malloc(src
->ai_addrlen
);
82 assert(dest
->ai_addr
!= NULL
);
83 memcpy(dest
->ai_addr
, src
->ai_addr
, src
->ai_addrlen
);
86 if (src
->ai_next
!= NULL
) {
87 dest
->ai_next
= (struct addrinfo
*)malloc(
88 sizeof(struct addrinfo
));
89 assert(dest
->ai_next
!= NULL
);
90 clone_addrinfo(dest
->ai_next
, src
->ai_next
);
95 compare_addrinfo_(struct addrinfo
*ai1
, struct addrinfo
*ai2
)
97 if ((ai1
== NULL
) || (ai2
== NULL
))
100 if ((ai1
->ai_flags
!= ai2
->ai_flags
) ||
101 (ai1
->ai_family
!= ai2
->ai_family
) ||
102 (ai1
->ai_socktype
!= ai2
->ai_socktype
) ||
103 (ai1
->ai_protocol
!= ai2
->ai_protocol
) ||
104 (ai1
->ai_addrlen
!= ai2
->ai_addrlen
) ||
105 (((ai1
->ai_addr
== NULL
) || (ai2
->ai_addr
== NULL
)) &&
106 (ai1
->ai_addr
!= ai2
->ai_addr
)) ||
107 (((ai1
->ai_canonname
== NULL
) || (ai2
->ai_canonname
== NULL
)) &&
108 (ai1
->ai_canonname
!= ai2
->ai_canonname
)))
111 if ((ai1
->ai_canonname
!= NULL
) &&
112 (strcmp(ai1
->ai_canonname
, ai2
->ai_canonname
) != 0))
115 if ((ai1
->ai_addr
!= NULL
) &&
116 (memcmp(ai1
->ai_addr
, ai2
->ai_addr
, ai1
->ai_addrlen
) != 0))
119 if ((ai1
->ai_next
== NULL
) && (ai2
->ai_next
== NULL
))
122 return (compare_addrinfo_(ai1
->ai_next
, ai2
->ai_next
));
126 compare_addrinfo(struct addrinfo
*ai1
, struct addrinfo
*ai2
, void *mdata
)
131 printf("testing equality of 2 addrinfo structures\n");
134 rv
= compare_addrinfo_(ai1
, ai2
);
142 printf("not equal\n");
150 free_addrinfo(struct addrinfo
*ai
)
156 free(ai
->ai_canonname
);
157 free_addrinfo(ai
->ai_next
);
161 sdump_addrinfo(struct addrinfo
*ai
, char *buffer
, size_t buflen
)
165 written
= snprintf(buffer
, buflen
, "%d %d %d %d %d ",
166 ai
->ai_flags
, ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
,
169 if (written
> buflen
)
173 written
= snprintf(buffer
, buflen
, "%s ",
174 ai
->ai_canonname
== NULL
? "(null)" : ai
->ai_canonname
);
176 if (written
> buflen
)
180 if (ai
->ai_addr
== NULL
) {
181 written
= snprintf(buffer
, buflen
, "(null)");
183 if (written
> buflen
)
187 for (i
= 0; i
< ai
->ai_addrlen
; ++i
) {
188 written
= snprintf(buffer
, buflen
,
189 i
+ 1 != ai
->ai_addrlen
? "%d." : "%d",
190 ((unsigned char *)ai
->ai_addr
)[i
]);
192 if (written
> buflen
)
201 if (ai
->ai_next
!= NULL
) {
202 written
= snprintf(buffer
, buflen
, ":");
204 if (written
> buflen
)
208 sdump_addrinfo(ai
->ai_next
, buffer
, buflen
);
213 dump_addrinfo(struct addrinfo
*result
)
215 if (result
!= NULL
) {
217 sdump_addrinfo(result
, buffer
, sizeof(buffer
));
218 printf("%s\n", buffer
);
224 addrinfo_read_snapshot_addr(char *addr
, unsigned char *result
, size_t len
)
229 while ( (s
= strsep(&ps
, ".")) != NULL
) {
233 *result
= (unsigned char)strtol(s
, &ts
, 10);
247 addrinfo_read_snapshot_ai(struct addrinfo
*ai
, char *line
)
255 memset(ai
, 0, sizeof(struct addrinfo
));
256 while ( (s
= strsep(&ps
, " ")) != NULL
) {
262 pi
= &ai
->ai_flags
+ i
;
263 *pi
= (int)strtol(s
, &ts
, 10);
268 ai
->ai_addrlen
= (socklen_t
)strtol(s
, &ts
, 10);
273 if (strcmp(s
, "(null)") != 0) {
274 ai
->ai_canonname
= strdup(s
);
275 assert(ai
->ai_canonname
!= NULL
);
279 if (strcmp(s
, "(null)") != 0) {
280 ai
->ai_addr
= (struct sockaddr
*)malloc(
282 assert(ai
->ai_addr
!= NULL
);
283 memset(ai
->ai_addr
, 0, ai
->ai_addrlen
);
284 rv
= addrinfo_read_snapshot_addr(s
,
285 (unsigned char *)ai
->ai_addr
,
293 /* NOTE: should not be reachable */
302 if ((i
!= 7) || (rv
!= 0)) {
304 memset(ai
, 0, sizeof(struct addrinfo
));
312 addrinfo_read_snapshot_func(struct addrinfo
*ai
, char *line
)
314 struct addrinfo
*ai2
;
319 printf("1 line read from snapshot:\n%s\n", line
);
325 s
= strsep(&ps
, ":");
329 rv
= addrinfo_read_snapshot_ai(ai
, s
);
334 while ( (s
= strsep(&ps
, ":")) != NULL
) {
335 ai2
->ai_next
= (struct addrinfo
*)malloc(
336 sizeof(struct addrinfo
));
337 assert(ai2
->ai_next
!= NULL
);
338 memset(ai2
->ai_next
, 0, sizeof(struct addrinfo
));
340 rv
= addrinfo_read_snapshot_ai(ai2
->ai_next
, s
);
353 addrinfo_test_correctness(struct addrinfo
*ai
, void *mdata
)
356 printf("testing correctness with the following data:\n");
363 if (!((ai
->ai_family
>= 0) && (ai
->ai_family
< AF_MAX
)))
366 if ((ai
->ai_socktype
!= 0) && (ai
->ai_socktype
!= SOCK_STREAM
) &&
367 (ai
->ai_socktype
!= SOCK_DGRAM
) && (ai
->ai_socktype
!= SOCK_RAW
))
370 if ((ai
->ai_protocol
!= 0) && (ai
->ai_protocol
!= IPPROTO_UDP
) &&
371 (ai
->ai_protocol
!= IPPROTO_TCP
))
374 if ((ai
->ai_flags
& ~(AI_CANONNAME
| AI_NUMERICHOST
| AI_PASSIVE
)) != 0)
377 if ((ai
->ai_addrlen
!= ai
->ai_addr
->sa_len
) ||
378 (ai
->ai_family
!= ai
->ai_addr
->sa_family
))
387 printf("incorrect\n");
393 addrinfo_read_hostlist_func(struct addrinfo
*ai
, char *line
)
395 struct addrinfo
*result
;
399 printf("resolving %s: ", line
);
400 rv
= getaddrinfo(line
, NULL
, &hints
, &result
);
405 rv
= addrinfo_test_correctness(result
, NULL
);
407 freeaddrinfo(result
);
411 clone_addrinfo(ai
, result
);
412 freeaddrinfo(result
);
415 printf("not found\n");
417 memset(ai
, 0, sizeof(struct addrinfo
));
425 (void)fprintf(stderr
,
426 "Usage: %s [-d] [-46] [-s <file]> -f <file>\n",
432 main(int argc
, char **argv
)
434 struct addrinfo_test_data td
, td_snap
;
435 char *snapshot_file
, *hostlist_file
;
442 snapshot_file
= NULL
;
443 hostlist_file
= NULL
;
444 memset(&hints
, 0, sizeof(struct addrinfo
));
445 hints
.ai_family
= PF_UNSPEC
;
446 hints
.ai_flags
= AI_CANONNAME
;
447 while ((c
= getopt(argc
, argv
, "46dns:f:")) != -1)
450 hints
.ai_family
= PF_INET
;
452 hints
.ai_family
= PF_INET6
;
458 snapshot_file
= strdup(optarg
);
459 method
= TEST_BUILD_SNAPSHOT
;
462 hostlist_file
= strdup(optarg
);
468 TEST_DATA_INIT(addrinfo
, &td
, clone_addrinfo
, free_addrinfo
);
469 TEST_DATA_INIT(addrinfo
, &td_snap
, clone_addrinfo
, free_addrinfo
);
471 if (hostlist_file
== NULL
)
474 if (access(hostlist_file
, R_OK
) != 0) {
476 printf("can't access the hostlist file %s\n",
483 printf("building host lists from %s\n", hostlist_file
);
485 rv
= TEST_SNAPSHOT_FILE_READ(addrinfo
, hostlist_file
, &td
,
486 addrinfo_read_hostlist_func
);
490 if (snapshot_file
!= NULL
) {
491 if (access(snapshot_file
, W_OK
| R_OK
) != 0) {
493 method
= TEST_BUILD_SNAPSHOT
;
496 printf("can't access the snapshot file %s\n",
503 rv
= TEST_SNAPSHOT_FILE_READ(addrinfo
, snapshot_file
,
504 &td_snap
, addrinfo_read_snapshot_func
);
507 printf("error reading snapshot file\n");
514 case TEST_GETADDRINFO
:
515 if (snapshot_file
!= NULL
)
516 rv
= DO_2PASS_TEST(addrinfo
, &td
, &td_snap
,
517 compare_addrinfo
, NULL
);
519 case TEST_BUILD_SNAPSHOT
:
520 if (snapshot_file
!= NULL
) {
521 rv
= TEST_SNAPSHOT_FILE_WRITE(addrinfo
, snapshot_file
, &td
,
531 TEST_DATA_DESTROY(addrinfo
, &td_snap
);
532 TEST_DATA_DESTROY(addrinfo
, &td
);