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? */
168 /* test result fields */
169 if (ai_cur
->ai_family
!= AF_INET
)
170 test_getaddrinfo_err_nr(2, TEST_GETADDRINFO_ERR_PARAMS
,
171 AF_INET
, ai_cur
->ai_family
);
173 if (socktype
&& ai_cur
->ai_socktype
!= socktype
)
174 test_getaddrinfo_err_nr(3, TEST_GETADDRINFO_ERR_PARAMS
,
175 socktype
, ai_cur
->ai_socktype
);
177 switch (ai_cur
->ai_socktype
)
179 case SOCK_DGRAM
: ai_count_dgram
++; break;
180 case SOCK_STREAM
: ai_count_stream
++; break;
183 /* do address and port match? */
184 if (ai_cur
->ai_addrlen
!= sizeof(struct sockaddr_in
))
185 test_getaddrinfo_err_nr(4, TEST_GETADDRINFO_ERR_PARAMS
,
186 sizeof(struct sockaddr_in
),
190 sockaddr_in
= (struct sockaddr_in
*) ai_cur
->ai_addr
;
191 if (sockaddr_in
->sin_addr
.s_addr
!= exp_ip
)
192 test_getaddrinfo_err_nr(5,
193 TEST_GETADDRINFO_ERR_PARAMS
,
195 ntohl(sockaddr_in
->sin_addr
.s_addr
));
197 if (sockaddr_in
->sin_port
!= exp_port
)
198 test_getaddrinfo_err_nr(6,
199 TEST_GETADDRINFO_ERR_PARAMS
,
201 ntohs(sockaddr_in
->sin_port
));
204 /* If a hostname is numeric, there can't be a canonical name.
205 * Instead, the returned canonname (if requested) will be
206 * identical to the supplied hostname */
207 if (nodename
!= NULL
&& nodename_numerical
&&
208 (flags
& AI_CANONNAME
)) {
209 if (strncmp(ai_cur
->ai_canonname
, nodename
,
211 test_getaddrinfo_err(11,
212 TEST_GETADDRINFO_ERR_PARAMS
,
213 nodename
, ai_cur
->ai_canonname
);
215 /* is canonical supplied? */
216 if (exp_canonname
&& nodename
&&
217 (!ai_cur
->ai_canonname
|| !*ai_cur
->ai_canonname
))
218 test_getaddrinfo_err(7,
219 TEST_GETADDRINFO_ERR_PARAMS
,
220 "(anything)", ai_cur
->ai_canonname
);
222 if (!exp_canonname
&& ai_cur
->ai_canonname
)
223 test_getaddrinfo_err(8,
224 TEST_GETADDRINFO_ERR_PARAMS
,
225 NULL
, ai_cur
->ai_canonname
);
228 /* move to next result */
229 ai_cur
= ai_cur
->ai_next
;
232 /* If socket type is non-zero, make sure we got what we wanted. Else
233 * any result is okay. */
235 if (ai_count_dgram
!= ((socktype
== SOCK_STREAM
) ? 0 : 1))
236 test_getaddrinfo_err_nr(9, TEST_GETADDRINFO_ERR_PARAMS
,
237 (socktype
== SOCK_STREAM
) ? 0 : 1, ai_count_dgram
);
239 if (ai_count_stream
!= ((socktype
== SOCK_DGRAM
) ? 0 : 1))
240 test_getaddrinfo_err_nr(10, TEST_GETADDRINFO_ERR_PARAMS
,
241 (socktype
== SOCK_DGRAM
) ? 0 : 1, ai_count_stream
);
248 static void memsetl(void *s
, unsigned long c
, size_t n
)
250 unsigned char *p
= (unsigned char *) s
;
253 for (i
= 0; i
< n
; i
++)
254 p
[i
] = c
>> (8 * (i
% sizeof(c
)));
257 static void test_getnameinfo(
258 unsigned long ipaddr
,
260 const char *exp_node
,
262 const char *exp_service
,
263 socklen_t servicelen
,
267 struct sockaddr_in sockaddr
;
268 char node
[256], service
[256];
271 /* avoid buffer overflows */
272 assert(nodelen
<= sizeof(node
));
273 assert(servicelen
<= sizeof(service
));
275 /* perform query and test result */
276 sockaddr
.sin_family
= AF_INET
;
277 sockaddr
.sin_addr
.s_addr
= ipaddr
;
278 sockaddr
.sin_port
= port
;
279 memsetl(node
, 0xDEADBEEF, nodelen
);
280 memsetl(service
, 0xDEADBEEF, servicelen
);
281 r
= getnameinfo((struct sockaddr
*) &sockaddr
, sizeof(sockaddr
),
282 node
, nodelen
, service
, servicelen
, flags
);
284 if (r
< 0 || r
>= 32 || !((1 << r
) & exp_results
))
285 test_getnameinfo_err_nr(1, TEST_GETNAMEINFO_ERR_PARAMS
,
292 if (nodelen
&& strcmp(exp_node
, node
) != 0)
293 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS
,
296 if (servicelen
&& strcmp(exp_service
, service
) != 0)
297 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS
,
298 exp_service
, service
);
303 const char *nodename
;
304 unsigned long ipaddr
;
310 { NULL
, 0x7f000001, 1, 1, 0, 0 },
311 { "0.0.0.0", 0x00000000, 1, 0, 0, 0 },
312 { "0.0.0.255", 0x000000ff, 1, 0, 0, 0 },
313 { "0.0.255.0", 0x0000ff00, 1, 0, 0, 0 },
314 { "0.255.0.0", 0x00ff0000, 1, 0, 0, 0 },
315 { "255.0.0.0", 0xff000000, 1, 0, 0, 0 },
316 { "127.0.0.1", 0x7f000001, 1, 0, 0, 0 },
317 { "localhost", 0x7f000001, 0, 1, 0, 0, },
318 { "static.minix3.org", 0xC023C00A, 0, 1, 1, 0, },
319 { "", 0x00000000, 1, 0, 0, (1<<EAI_NONAME
)|(1<<EAI_FAIL
)|(1<<EAI_NODATA
)},
320 { "256.256.256.256",0x00000000, 1, 0, 0, (1<<EAI_NONAME
)|(1<<EAI_FAIL
)|(1<<EAI_NODATA
)},
321 { "minix3.xyz", 0x00000000, 0, 0, 1, (1<<EAI_NONAME
)|(1<<EAI_FAIL
)|(1<<EAI_NODATA
)}};
325 const char *servname
;
331 { NULL
, 0, 1, 0, 0 },
334 { "32767", 32767, 1, 0, 0 },
335 { "32768", 32768, 1, 0, 0 },
336 { "65535", 65535, 1, 0, 0 },
337 { "echo", 7, 0, 0, 0 },
338 { "ftp", 21, 0, 0, 0 },
339 { "tftp", 69, 0, 0, 0 },
340 { "-1", 0, 1, 0, (1<<EAI_NONAME
) | (1<<EAI_SERVICE
) },
341 { "", 0, 1, 0, (1<<EAI_NONAME
) | (1<<EAI_SERVICE
) },
342 { "65537", 0, 1, 0, (1 << EAI_SERVICE
) },
343 { "XXX", 0, 0, 0, (1 << EAI_SERVICE
) }};
352 { AF_UNSPEC
+ AF_INET
+ 1, (1 << EAI_FAMILY
) }};
362 { SOCK_STREAM
+ SOCK_DGRAM
+ 1,
363 (1 << EAI_SOCKTYPE
) | (1 << EAI_FAIL
) | (1 << EAI_NONAME
) }};
365 #define LENGTH(a) (sizeof((a)) / sizeof((a)[0]))
367 static void test_getaddrinfo_all(int use_network
)
369 int flag_PASSIVE
, flag_CANONNAME
, flag_NUMERICHOST
, flag_NUMERICSERV
;
370 int exp_results
, flags
, i
, j
, k
, l
, passhints
;
371 unsigned long ipaddr
;
373 /* loop through various parameter values */
374 for (i
= 0; i
< LENGTH(hosts
); i
++)
375 for (j
= 0; j
< LENGTH(services
); j
++)
376 for (k
= 0; k
< LENGTH(families
); k
++)
377 for (l
= 0; l
< LENGTH(socktypes
); l
++)
378 for (flag_PASSIVE
= 0; flag_PASSIVE
< 2; flag_PASSIVE
++)
379 for (flag_CANONNAME
= 0; flag_CANONNAME
< 2; flag_CANONNAME
++)
380 for (flag_NUMERICHOST
= 0; flag_NUMERICHOST
< 2; flag_NUMERICHOST
++)
381 for (flag_NUMERICSERV
= 0; flag_NUMERICSERV
< 2; flag_NUMERICSERV
++)
382 for (passhints
= 0; passhints
< 2; passhints
++)
384 /* skip tests that need but cannot use network */
385 if (!use_network
&& hosts
[i
].need_network
)
388 /* determine flags */
389 flags
= (flag_PASSIVE
? AI_PASSIVE
: 0) |
390 (flag_CANONNAME
? AI_CANONNAME
: 0) |
391 (flag_NUMERICHOST
? AI_NUMERICHOST
: 0) |
392 (flag_NUMERICSERV
? AI_NUMERICSERV
: 0);
394 /* some options require hints */
395 if (families
[k
].value
!= AF_UNSPEC
||
396 socktypes
[l
].value
!= 0 || flags
) {
400 /* flags may influence IP address */
401 ipaddr
= hosts
[i
].ipaddr
;
402 if (!hosts
[i
].nodename
&& flag_PASSIVE
)
405 /* determine expected result */
407 hosts
[i
].exp_result
|
408 services
[j
].exp_result
|
409 families
[k
].exp_result
|
410 socktypes
[l
].exp_result
;
411 if (!hosts
[i
].nodename
&& !services
[j
].servname
)
412 exp_results
|= (1 << EAI_NONAME
);
414 if (flag_NUMERICHOST
&& !hosts
[i
].numeric
)
415 exp_results
|= (1 << EAI_NONAME
);
417 if (flag_NUMERICSERV
&& !services
[j
].numeric
)
418 exp_results
|= (1 << EAI_NONAME
);
420 /* When we don't pass hints, getaddrinfo will find suitable
421 * settings for us. If we do pass hints, there might be
425 /* Can't have conflicting socket types */
426 if (services
[j
].socktype
&&
427 socktypes
[l
].value
&&
428 socktypes
[l
].value
!= services
[j
].socktype
) {
429 exp_results
|= (1 << EAI_SERVICE
);
433 /* with no reason for failure, we demand success */
435 exp_results
|= (1 << 0);
437 /* test getaddrinfo function */
441 services
[j
].servname
,
449 flag_CANONNAME
&& hosts
[i
].canonname
,
450 htons(services
[j
].port
));
456 const char *nodename
;
458 unsigned long ipaddr
;
461 { "0.0.0.0", "0.0.0.0", 0x00000000, 0 },
462 { "0.0.0.255", "0.0.0.255", 0x000000ff, 0 },
463 { "0.0.255.0", "0.0.255.0", 0x0000ff00, 0 },
464 { "0.255.0.0", "0.255.0.0", 0x00ff0000, 0 },
465 { "255.0.0.0", "255.0.0.0", 0xff000000, 0 },
466 { "localhost", "127.0.0.1", 0x7f000001, 1 },
467 /* no reverse DNS unfortunately */
468 /* { "minix3.org", "130.37.20.20", 0x82251414, 1 } */};
472 const char *servname
;
476 struct servent
*se_tcp
; /* getservbyport() s_name on this port with "tcp" */
477 struct servent
*se_udp
; /* getservbyport() s_name on this port with "udp" */
480 { "tcpmux", "1", 1, SOCK_STREAM
},
481 { "32767", "32767", 32767, 0 },
482 { "32768", "32768", 32768, 0 },
483 { "65535", "65535", 65535, 0 },
484 { "echo", "7", 7, 0 },
485 { "ftp", "21", 21, SOCK_STREAM
},
486 { "tftp", "69", 69, SOCK_DGRAM
}};
488 static int buflens
[] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 255 };
490 static void test_getnameinfo_all(void)
492 int flag_NUMERICHOST
, flag_NAMEREQD
, flag_NUMERICSERV
, flag_DGRAM
;
493 int exp_results
, flags
, i
, j
, k
, l
, socktypemismatch
;
494 const char *nodename
, *servname
;
496 /* set ports servent structs */
497 for (j
= 0; j
< LENGTH(ports
); j
++) {
498 struct servent
*se_tcp
, *se_udp
;
500 se_tcp
= getservbyport(htons(ports
[j
].port
), "tcp");
501 ports
[j
].se_tcp
= se_tcp
;
503 if(ports
[j
].se_tcp
) {
504 ports
[j
].se_tcp
= malloc(sizeof(struct servent
));
505 memcpy(ports
[j
].se_tcp
, se_tcp
, sizeof(*se_tcp
));
506 assert(ports
[j
].se_tcp
->s_name
);
507 ports
[j
].se_tcp
->s_name
= strdup(ports
[j
].se_tcp
->s_name
);
508 assert(ports
[j
].se_tcp
->s_name
);
511 se_udp
= getservbyport(htons(ports
[j
].port
), "udp");
512 ports
[j
].se_udp
= se_udp
;
514 if(ports
[j
].se_udp
) {
515 ports
[j
].se_udp
= malloc(sizeof(struct servent
));
516 memcpy(ports
[j
].se_udp
, se_udp
, sizeof(*se_udp
));
517 assert(ports
[j
].se_udp
->s_name
);
518 ports
[j
].se_udp
->s_name
= strdup(ports
[j
].se_udp
->s_name
);
519 assert(ports
[j
].se_udp
->s_name
);
523 /* loop through various parameter values */
524 for (i
= 0; i
< LENGTH(ipaddrs
); i
++)
525 for (j
= 0; j
< LENGTH(ports
); j
++)
526 for (k
= 0; k
< LENGTH(buflens
); k
++)
527 for (l
= 0; l
< LENGTH(buflens
); l
++)
528 for (flag_NUMERICHOST
= 0; flag_NUMERICHOST
< 2; flag_NUMERICHOST
++)
529 for (flag_NAMEREQD
= 0; flag_NAMEREQD
< 2; flag_NAMEREQD
++)
530 for (flag_NUMERICSERV
= 0; flag_NUMERICSERV
< 2; flag_NUMERICSERV
++)
531 for (flag_DGRAM
= 0; flag_DGRAM
< 2; flag_DGRAM
++)
533 /* determine flags */
534 flags
= (flag_NUMERICHOST
? NI_NUMERICHOST
: 0) |
535 (flag_NAMEREQD
? NI_NAMEREQD
: 0) |
536 (flag_NUMERICSERV
? NI_NUMERICSERV
: 0) |
537 (flag_DGRAM
? NI_DGRAM
: 0);
539 /* determine expected result */
542 nodename
= flag_NUMERICHOST
? ipaddrs
[i
].nodenum
: ipaddrs
[i
].nodename
;
543 if (buflens
[k
] > 0 && buflens
[k
] <= strlen(nodename
))
544 exp_results
|= (1 << EAI_OVERFLOW
) | (1 << EAI_MEMORY
);
547 (flag_DGRAM
&& ports
[j
].socktype
== SOCK_STREAM
) ||
548 (!flag_DGRAM
&& ports
[j
].socktype
== SOCK_DGRAM
);
550 struct servent
*se
= flag_DGRAM
? ports
[j
].se_udp
: ports
[j
].se_tcp
;
552 servname
= (flag_NUMERICSERV
) ?
553 ports
[j
].servnum
: (se
? se
->s_name
: ports
[j
].servname
);
555 if (buflens
[l
] > 0 && buflens
[l
] <= strlen(servname
))
556 exp_results
|= (1 << EAI_OVERFLOW
) | (1 << EAI_MEMORY
);
558 if (flag_NAMEREQD
&& (!ipaddrs
[i
].havename
|| flag_NUMERICHOST
) && buflens
[k
])
559 exp_results
|= (1 << EAI_NONAME
);
561 /* with no reason for failure, we demand success */
563 exp_results
|= (1 << 0);
565 /* perform the test */
567 htonl(ipaddrs
[i
].ipaddr
),
568 htons(ports
[j
].port
),
578 static int can_use_network(void)
582 /* try to ping minix3.org */
583 status
= system("ping www.minix3.org > /dev/null 2>&1");
586 printf("cannot execute ping\n");
599 use_network
= can_use_network();
601 printf("Warning: no network\n");
602 test_getaddrinfo_all(use_network
);
603 test_getnameinfo_all();