12 #define err() e(__LINE__)
14 static void printstr(const char *s
)
22 static void test_getaddrinfo_err(
30 const char *exp_result
,
33 printf("error %d: getaddrinfo(", n
);
39 printf("{ 0x%x, %d, %d }", flags
, family
, socktype
);
43 printf("); result: ");
45 printf("; expected: ");
51 /* yes, this is ugly, but not as ugly as repeating it all every time */
52 #define TEST_GETADDRINFO_ERR_PARAMS \
53 nodename, servname, passhints, flags, family, socktype
55 static void test_getaddrinfo_err_nr(
66 char exp_result_s
[23], result_s
[23];
68 /* convert result to string */
69 snprintf(exp_result_s
, sizeof(exp_result_s
), "%d/0x%x",
70 exp_result
, exp_result
);
71 snprintf(result_s
, sizeof(result_s
), "%d/0x%x", result
, result
);
72 test_getaddrinfo_err(n
, TEST_GETADDRINFO_ERR_PARAMS
,
73 exp_result_s
, result_s
);
76 static void test_getnameinfo_err(
83 const char *exp_result
,
86 printf("error %d: getnameinfo(0x%.8x, %d, %d, %d, 0x%x); result: ",
87 n
, ntohl(ipaddr
), ntohs(port
), nodelen
, servicelen
, flags
);
89 printf("; expected: ");
95 /* yes, this is ugly, but not as ugly as repeating it all every time */
96 #define TEST_GETNAMEINFO_ERR_PARAMS ipaddr, port, nodelen, servicelen, flags
98 static void test_getnameinfo_err_nr(
100 unsigned long ipaddr
,
103 socklen_t servicelen
,
108 char exp_result_s
[23], result_s
[23];
110 /* convert result to string */
111 snprintf(exp_result_s
, sizeof(exp_result_s
), "%d/0x%x",
112 exp_result
, exp_result
);
113 snprintf(result_s
, sizeof(result_s
), "%d/0x%x", result
, result
);
114 test_getnameinfo_err(n
, TEST_GETNAMEINFO_ERR_PARAMS
,
115 exp_result_s
, result_s
);
118 static void test_getaddrinfo(
119 const char *nodename
,
120 int nodename_numerical
,
121 const char *servname
,
122 int servname_numerical
,
128 unsigned long exp_ip
,
130 unsigned short exp_port
)
132 struct addrinfo
*ai
, *ai_cur
;
133 struct addrinfo hints
;
134 struct sockaddr_in
*sockaddr_in
;
135 int ai_count_dgram
, ai_count_stream
, r
;
137 /* some parameters are only meaningful with hints */
138 assert(passhints
|| !flags
);
139 assert(passhints
|| family
== AF_UNSPEC
);
140 assert(passhints
|| !socktype
);
142 /* a combination of parameters don't make sense to test */
143 if (nodename
== NULL
&& servname
== NULL
) return;
144 if (nodename
== NULL
&& (flags
& AI_NUMERICHOST
)) return;
145 if (servname
== NULL
&& (flags
& AI_NUMERICSERV
)) return;
147 /* initialize hints */
148 memset(&hints
, 0, sizeof(hints
));
149 hints
.ai_flags
= flags
;
150 hints
.ai_family
= family
;
151 hints
.ai_socktype
= socktype
;
153 /* perform query and test result */
154 ai
= (struct addrinfo
*) 0xDEADBEEF;
155 r
= getaddrinfo(nodename
, servname
, passhints
? &hints
: NULL
, &ai
);
156 if (r
< 0 || r
>= 32 || !((1 << r
) & exp_results
))
157 test_getaddrinfo_err_nr(1, TEST_GETADDRINFO_ERR_PARAMS
, exp_results
, r
);
162 /* the function succeeded; do the results make sense? */
169 * TODO: this test was written for IPv4. For now, skip IPv6
170 * results altogether. Later, we should add additional code
171 * for IPv6. However, since this test now largely exercises
172 * NetBSD code, it is not as important as it once was.
174 if (ai_cur
->ai_family
== AF_INET6
) {
175 ai_cur
= ai_cur
->ai_next
;
179 /* test result fields */
180 if (ai_cur
->ai_family
!= AF_INET
)
181 test_getaddrinfo_err_nr(2, TEST_GETADDRINFO_ERR_PARAMS
,
182 AF_INET
, ai_cur
->ai_family
);
184 if (socktype
&& ai_cur
->ai_socktype
!= socktype
)
185 test_getaddrinfo_err_nr(3, TEST_GETADDRINFO_ERR_PARAMS
,
186 socktype
, ai_cur
->ai_socktype
);
188 switch (ai_cur
->ai_socktype
)
190 case SOCK_DGRAM
: ai_count_dgram
++; break;
191 case SOCK_STREAM
: ai_count_stream
++; break;
194 /* do address and port match? */
195 if (ai_cur
->ai_addrlen
!= sizeof(struct sockaddr_in
))
196 test_getaddrinfo_err_nr(4, TEST_GETADDRINFO_ERR_PARAMS
,
197 sizeof(struct sockaddr_in
),
201 sockaddr_in
= (struct sockaddr_in
*) ai_cur
->ai_addr
;
202 if (sockaddr_in
->sin_addr
.s_addr
!= exp_ip
)
203 test_getaddrinfo_err_nr(5,
204 TEST_GETADDRINFO_ERR_PARAMS
,
206 ntohl(sockaddr_in
->sin_addr
.s_addr
));
208 if (sockaddr_in
->sin_port
!= exp_port
)
209 test_getaddrinfo_err_nr(6,
210 TEST_GETADDRINFO_ERR_PARAMS
,
212 ntohs(sockaddr_in
->sin_port
));
215 /* If a hostname is numeric, there can't be a canonical name.
216 * Instead, the returned canonname (if requested) will be
217 * identical to the supplied hostname */
218 if (nodename
!= NULL
&& nodename_numerical
&&
219 (flags
& AI_CANONNAME
)) {
220 if (strncmp(ai_cur
->ai_canonname
, nodename
,
222 test_getaddrinfo_err(11,
223 TEST_GETADDRINFO_ERR_PARAMS
,
224 nodename
, ai_cur
->ai_canonname
);
226 /* is canonical supplied? */
227 if (exp_canonname
&& nodename
&&
228 (!ai_cur
->ai_canonname
|| !*ai_cur
->ai_canonname
))
229 test_getaddrinfo_err(7,
230 TEST_GETADDRINFO_ERR_PARAMS
,
231 "(anything)", ai_cur
->ai_canonname
);
233 if (!exp_canonname
&& ai_cur
->ai_canonname
)
234 test_getaddrinfo_err(8,
235 TEST_GETADDRINFO_ERR_PARAMS
,
236 NULL
, ai_cur
->ai_canonname
);
239 /* move to next result */
240 ai_cur
= ai_cur
->ai_next
;
243 /* If socket type is non-zero, make sure we got what we wanted. Else
244 * any result is okay. */
246 if (ai_count_dgram
!= ((socktype
== SOCK_STREAM
) ? 0 : 1))
247 test_getaddrinfo_err_nr(9, TEST_GETADDRINFO_ERR_PARAMS
,
248 (socktype
== SOCK_STREAM
) ? 0 : 1, ai_count_dgram
);
250 if (ai_count_stream
!= ((socktype
== SOCK_DGRAM
) ? 0 : 1))
251 test_getaddrinfo_err_nr(10, TEST_GETADDRINFO_ERR_PARAMS
,
252 (socktype
== SOCK_DGRAM
) ? 0 : 1, ai_count_stream
);
259 static void memsetl(void *s
, unsigned long c
, size_t n
)
261 unsigned char *p
= (unsigned char *) s
;
264 for (i
= 0; i
< n
; i
++)
265 p
[i
] = c
>> (8 * (i
% sizeof(c
)));
268 static void test_getnameinfo(
269 unsigned long ipaddr
,
271 const char *exp_node
,
273 const char *exp_service
,
274 socklen_t servicelen
,
278 struct sockaddr_in sockaddr
;
279 char node
[256], service
[256];
282 /* avoid buffer overflows */
283 assert(nodelen
<= sizeof(node
));
284 assert(servicelen
<= sizeof(service
));
286 /* perform query and test result */
287 sockaddr
.sin_family
= AF_INET
;
288 sockaddr
.sin_addr
.s_addr
= ipaddr
;
289 sockaddr
.sin_port
= port
;
290 memsetl(node
, 0xDEADBEEF, nodelen
);
291 memsetl(service
, 0xDEADBEEF, servicelen
);
292 r
= getnameinfo((struct sockaddr
*) &sockaddr
, sizeof(sockaddr
),
293 node
, nodelen
, service
, servicelen
, flags
);
295 if (r
< 0 || r
>= 32 || !((1 << r
) & exp_results
))
296 test_getnameinfo_err_nr(1, TEST_GETNAMEINFO_ERR_PARAMS
,
303 if (nodelen
&& strcmp(exp_node
, node
) != 0)
304 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS
,
307 if (servicelen
&& strcmp(exp_service
, service
) != 0)
308 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS
,
309 exp_service
, service
);
314 const char *nodename
;
315 unsigned long ipaddr
;
321 { NULL
, 0x7f000001, 1, 1, 0, 0 },
322 { "0.0.0.0", 0x00000000, 1, 0, 0, 0 },
323 { "0.0.0.255", 0x000000ff, 1, 0, 0, 0 },
324 { "0.0.255.0", 0x0000ff00, 1, 0, 0, 0 },
325 { "0.255.0.0", 0x00ff0000, 1, 0, 0, 0 },
326 { "255.0.0.0", 0xff000000, 1, 0, 0, 0 },
327 { "127.0.0.1", 0x7f000001, 1, 0, 0, 0 },
328 { "localhost", 0x7f000001, 0, 1, 0, 0, },
329 { "test48.minix3.org", 0x7f010203, 0, 1, 1, 0, },
330 { "minix3.example.com", 0x00000000, 0, 0, 1, (1<<EAI_NONAME
)|(1<<EAI_FAIL
)|(1<<EAI_NODATA
)}};
334 const char *servname
;
340 { NULL
, 0, 1, 0, 0 },
343 { "32767", 32767, 1, 0, 0 },
344 { "32768", 32768, 1, 0, 0 },
345 { "65535", 65535, 1, 0, 0 },
346 { "echo", 7, 0, 0, 0 },
347 { "ftp", 21, 0, 0, 0 },
348 { "tftp", 69, 0, 0, 0 },
349 { "-1", 0, 1, 0, (1<<EAI_NONAME
) | (1<<EAI_SERVICE
) },
350 { "", 0, 1, 0, (1<<EAI_NONAME
) | (1<<EAI_SERVICE
) },
351 { "65537", 0, 1, 0, (1 << EAI_SERVICE
) },
352 { "XXX", 0, 0, 0, (1 << EAI_SERVICE
) }};
361 { AF_UNSPEC
+ AF_INET
+ 1, (1 << EAI_FAMILY
) }};
371 { SOCK_STREAM
+ SOCK_DGRAM
+ 1,
372 (1 << EAI_SOCKTYPE
) | (1 << EAI_FAIL
) | (1 << EAI_NONAME
) }};
374 #define LENGTH(a) (sizeof((a)) / sizeof((a)[0]))
376 static void test_getaddrinfo_all(int use_network
)
378 int flag_PASSIVE
, flag_CANONNAME
, flag_NUMERICHOST
, flag_NUMERICSERV
;
379 int exp_results
, flags
, flagcount
, i
, j
, k
, l
, passhints
;
380 unsigned long ipaddr
;
382 /* loop through various parameter values */
383 for (i
= 0; i
< LENGTH(hosts
); i
++)
384 for (j
= 0; j
< LENGTH(services
); j
++)
385 for (k
= 0; k
< LENGTH(families
); k
++)
386 for (l
= 0; l
< LENGTH(socktypes
); l
++)
387 for (flag_PASSIVE
= 0; flag_PASSIVE
< 2; flag_PASSIVE
++)
388 for (flag_CANONNAME
= 0; flag_CANONNAME
< 2; flag_CANONNAME
++)
389 for (flag_NUMERICHOST
= 0; flag_NUMERICHOST
< 2; flag_NUMERICHOST
++)
390 for (flag_NUMERICSERV
= 0; flag_NUMERICSERV
< 2; flag_NUMERICSERV
++)
391 for (passhints
= 0; passhints
< 2; passhints
++)
393 /* skip some redundant combinations */
394 flagcount
= flag_PASSIVE
+ flag_CANONNAME
+
395 flag_NUMERICHOST
+ flag_NUMERICSERV
;
396 if (flagcount
> 1 && flagcount
< 4) continue;
398 /* skip tests that need but cannot use network */
399 if (!use_network
&& hosts
[i
].need_network
)
402 /* determine flags */
403 flags
= (flag_PASSIVE
? AI_PASSIVE
: 0) |
404 (flag_CANONNAME
? AI_CANONNAME
: 0) |
405 (flag_NUMERICHOST
? AI_NUMERICHOST
: 0) |
406 (flag_NUMERICSERV
? AI_NUMERICSERV
: 0);
408 /* some options require hints */
409 if (families
[k
].value
!= AF_UNSPEC
||
410 socktypes
[l
].value
!= 0 || flags
) {
414 /* flags may influence IP address */
415 ipaddr
= hosts
[i
].ipaddr
;
416 if (!hosts
[i
].nodename
&& flag_PASSIVE
)
419 /* determine expected result */
421 hosts
[i
].exp_result
|
422 services
[j
].exp_result
|
423 families
[k
].exp_result
|
424 socktypes
[l
].exp_result
;
425 if (!hosts
[i
].nodename
&& !services
[j
].servname
)
426 exp_results
|= (1 << EAI_NONAME
);
428 if (flag_NUMERICHOST
&& !hosts
[i
].numeric
)
429 exp_results
|= (1 << EAI_NONAME
);
431 if (flag_NUMERICSERV
&& !services
[j
].numeric
)
432 exp_results
|= (1 << EAI_NONAME
);
434 /* When we don't pass hints, getaddrinfo will find suitable
435 * settings for us. If we do pass hints, there might be
439 /* Can't have conflicting socket types */
440 if (services
[j
].socktype
&&
441 socktypes
[l
].value
&&
442 socktypes
[l
].value
!= services
[j
].socktype
) {
443 exp_results
|= (1 << EAI_SERVICE
);
447 /* with no reason for failure, we demand success */
449 exp_results
|= (1 << 0);
451 /* test getaddrinfo function */
455 services
[j
].servname
,
463 flag_CANONNAME
&& hosts
[i
].canonname
,
464 htons(services
[j
].port
));
470 const char *nodename
;
472 unsigned long ipaddr
;
475 { "0.0.0.0", "0.0.0.0", 0x00000000, 0 },
476 { "0.0.0.255", "0.0.0.255", 0x000000ff, 0 },
477 { "0.0.255.0", "0.0.255.0", 0x0000ff00, 0 },
478 { "0.255.0.0", "0.255.0.0", 0x00ff0000, 0 },
479 { "255.0.0.0", "255.0.0.0", 0xff000000, 0 },
480 { "localhost", "127.0.0.1", 0x7f000001, 1 },
481 /* no reverse DNS unfortunately */
482 /* { "minix3.org", "130.37.20.20", 0x82251414, 1 } */};
486 const char *servname
;
490 struct servent
*se_tcp
; /* getservbyport() s_name on this port with "tcp" */
491 struct servent
*se_udp
; /* getservbyport() s_name on this port with "udp" */
494 { "tcpmux", "1", 1, SOCK_STREAM
},
495 { "32767", "32767", 32767, 0 },
496 { "32768", "32768", 32768, 0 },
497 { "65535", "65535", 65535, 0 },
498 { "echo", "7", 7, 0 },
499 { "ftp", "21", 21, SOCK_STREAM
},
500 { "tftp", "69", 69, SOCK_DGRAM
}};
502 static int buflens
[] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 255 };
504 static void test_getnameinfo_all(void)
506 int flag_NUMERICHOST
, flag_NAMEREQD
, flag_NUMERICSERV
, flag_DGRAM
;
507 int exp_results
, flagcount
, flags
, i
, j
, k
, l
;
508 const char *nodename
, *servname
;
510 /* set ports servent structs */
511 for (j
= 0; j
< LENGTH(ports
); j
++) {
512 struct servent
*se_tcp
, *se_udp
;
514 se_tcp
= getservbyport(htons(ports
[j
].port
), "tcp");
515 ports
[j
].se_tcp
= se_tcp
;
517 if(ports
[j
].se_tcp
) {
518 ports
[j
].se_tcp
= malloc(sizeof(struct servent
));
519 memcpy(ports
[j
].se_tcp
, se_tcp
, sizeof(*se_tcp
));
520 assert(ports
[j
].se_tcp
->s_name
);
521 ports
[j
].se_tcp
->s_name
= strdup(ports
[j
].se_tcp
->s_name
);
522 assert(ports
[j
].se_tcp
->s_name
);
525 se_udp
= getservbyport(htons(ports
[j
].port
), "udp");
526 ports
[j
].se_udp
= se_udp
;
528 if(ports
[j
].se_udp
) {
529 ports
[j
].se_udp
= malloc(sizeof(struct servent
));
530 memcpy(ports
[j
].se_udp
, se_udp
, sizeof(*se_udp
));
531 assert(ports
[j
].se_udp
->s_name
);
532 ports
[j
].se_udp
->s_name
= strdup(ports
[j
].se_udp
->s_name
);
533 assert(ports
[j
].se_udp
->s_name
);
537 /* loop through various parameter values */
538 for (i
= 0; i
< LENGTH(ipaddrs
); i
++)
539 for (j
= 0; j
< LENGTH(ports
); j
++)
540 for (k
= 0; k
< LENGTH(buflens
); k
++)
541 for (l
= 0; l
< LENGTH(buflens
); l
++)
542 for (flag_NUMERICHOST
= 0; flag_NUMERICHOST
< 2; flag_NUMERICHOST
++)
543 for (flag_NAMEREQD
= 0; flag_NAMEREQD
< 2; flag_NAMEREQD
++)
544 for (flag_NUMERICSERV
= 0; flag_NUMERICSERV
< 2; flag_NUMERICSERV
++)
545 for (flag_DGRAM
= 0; flag_DGRAM
< 2; flag_DGRAM
++)
547 /* skip some redundant combinations */
548 flagcount
= flag_NUMERICHOST
+ flag_NAMEREQD
+
549 flag_NUMERICSERV
+ flag_DGRAM
;
550 if (flagcount
> 1 && flagcount
< 4) continue;
551 if (k
> 1 && k
< LENGTH(buflens
) - 2 &&
552 l
> 1 && l
< LENGTH(buflens
) - 2) continue;
554 /* determine flags */
555 flags
= (flag_NUMERICHOST
? NI_NUMERICHOST
: 0) |
556 (flag_NAMEREQD
? NI_NAMEREQD
: 0) |
557 (flag_NUMERICSERV
? NI_NUMERICSERV
: 0) |
558 (flag_DGRAM
? NI_DGRAM
: 0);
560 /* determine expected result */
563 nodename
= flag_NUMERICHOST
? ipaddrs
[i
].nodenum
: ipaddrs
[i
].nodename
;
564 if (buflens
[k
] > 0 && buflens
[k
] <= strlen(nodename
))
565 exp_results
|= (1 << EAI_OVERFLOW
) | (1 << EAI_MEMORY
);
567 struct servent
*se
= flag_DGRAM
? ports
[j
].se_udp
: ports
[j
].se_tcp
;
569 servname
= (flag_NUMERICSERV
) ?
570 ports
[j
].servnum
: (se
? se
->s_name
: ports
[j
].servname
);
572 if (buflens
[l
] > 0 && buflens
[l
] <= strlen(servname
))
573 exp_results
|= (1 << EAI_OVERFLOW
) | (1 << EAI_MEMORY
);
575 if (flag_NAMEREQD
&& (!ipaddrs
[i
].havename
|| flag_NUMERICHOST
) && buflens
[k
])
576 exp_results
|= (1 << EAI_NONAME
);
578 /* with no reason for failure, we demand success */
580 exp_results
|= (1 << 0);
582 /* perform the test */
584 htonl(ipaddrs
[i
].ipaddr
),
585 htons(ports
[j
].port
),
601 use_network
= get_setting_use_network();
602 test_getaddrinfo_all(use_network
);
603 test_getnameinfo_all();