10 #define err() e(__LINE__)
13 static void printstr(const char *s
)
21 static void test_getaddrinfo_err(
29 const char *exp_result
,
32 printf("error %d: getaddrinfo(", n
);
38 printf("{ 0x%x, %d, %d }", flags
, family
, socktype
);
42 printf("); result: ");
44 printf("; expected: ");
50 /* yes, this is ugly, but not as ugly as repeating it all every time */
51 #define TEST_GETADDRINFO_ERR_PARAMS \
52 nodename, servname, passhints, flags, family, socktype
54 static void test_getaddrinfo_err_nr(
65 char exp_result_s
[23], result_s
[23];
67 /* convert result to string */
68 snprintf(exp_result_s
, sizeof(exp_result_s
), "%d/0x%x",
69 exp_result
, exp_result
);
70 snprintf(result_s
, sizeof(result_s
), "%d/0x%x", result
, result
);
71 test_getaddrinfo_err(n
, TEST_GETADDRINFO_ERR_PARAMS
,
72 exp_result_s
, result_s
);
75 static void test_getnameinfo_err(
82 const char *exp_result
,
85 printf("error %d: getnameinfo(0x%.8x, %d, %d, %d, 0x%x); result: ",
86 n
, ntohl(ipaddr
), ntohs(port
), nodelen
, servicelen
, flags
);
88 printf("; expected: ");
94 /* yes, this is ugly, but not as ugly as repeating it all every time */
95 #define TEST_GETNAMEINFO_ERR_PARAMS ipaddr, port, nodelen, servicelen, flags
97 static void test_getnameinfo_err_nr(
102 socklen_t servicelen
,
107 char exp_result_s
[23], result_s
[23];
109 /* convert result to string */
110 snprintf(exp_result_s
, sizeof(exp_result_s
), "%d/0x%x",
111 exp_result
, exp_result
);
112 snprintf(result_s
, sizeof(result_s
), "%d/0x%x", result
, result
);
113 test_getnameinfo_err(n
, TEST_GETNAMEINFO_ERR_PARAMS
,
114 exp_result_s
, result_s
);
117 static void test_getaddrinfo(
118 const char *nodename
,
119 int nodename_numerical
,
120 const char *servname
,
121 int servname_numerical
,
127 unsigned long exp_ip
,
129 unsigned short exp_port
)
131 struct addrinfo
*ai
, *ai_cur
;
132 struct addrinfo hints
;
133 struct sockaddr_in
*sockaddr_in
;
134 int ai_count_dgram
, ai_count_stream
, r
;
136 /* some parameters are only meaningful with hints */
137 assert(passhints
|| !flags
);
138 assert(passhints
|| family
== AF_UNSPEC
);
139 assert(passhints
|| !socktype
);
141 /* a combination of parameters don't make sense to test */
142 if (nodename
== NULL
&& servname
== NULL
) return;
143 if (nodename
== NULL
&& (flags
& AI_NUMERICHOST
)) return;
144 if (servname
== NULL
&& (flags
& AI_NUMERICSERV
)) return;
146 /* initialize hints */
147 memset(&hints
, 0, sizeof(hints
));
148 hints
.ai_flags
= flags
;
149 hints
.ai_family
= family
;
150 hints
.ai_socktype
= socktype
;
152 /* perform query and test result */
153 ai
= (struct addrinfo
*) 0xDEADBEEF;
154 r
= getaddrinfo(nodename
, servname
, passhints
? &hints
: NULL
, &ai
);
155 if (r
< 0 || r
>= 32 || !((1 << r
) & exp_results
))
156 test_getaddrinfo_err_nr(1, TEST_GETADDRINFO_ERR_PARAMS
, exp_results
, r
);
161 /* the function succeeded; do the results make sense? */
167 /* test result fields */
168 if (ai_cur
->ai_family
!= AF_INET
)
169 test_getaddrinfo_err_nr(2, TEST_GETADDRINFO_ERR_PARAMS
,
170 AF_INET
, ai_cur
->ai_family
);
172 if (socktype
&& ai_cur
->ai_socktype
!= socktype
)
173 test_getaddrinfo_err_nr(3, TEST_GETADDRINFO_ERR_PARAMS
,
174 socktype
, ai_cur
->ai_socktype
);
176 switch (ai_cur
->ai_socktype
)
178 case SOCK_DGRAM
: ai_count_dgram
++; break;
179 case SOCK_STREAM
: ai_count_stream
++; break;
182 /* do address and port match? */
183 if (ai_cur
->ai_addrlen
!= sizeof(struct sockaddr_in
))
184 test_getaddrinfo_err_nr(4, TEST_GETADDRINFO_ERR_PARAMS
,
185 sizeof(struct sockaddr_in
),
189 sockaddr_in
= (struct sockaddr_in
*) ai_cur
->ai_addr
;
190 if (sockaddr_in
->sin_addr
.s_addr
!= exp_ip
)
191 test_getaddrinfo_err_nr(5,
192 TEST_GETADDRINFO_ERR_PARAMS
,
194 ntohl(sockaddr_in
->sin_addr
.s_addr
));
196 if (sockaddr_in
->sin_port
!= exp_port
)
197 test_getaddrinfo_err_nr(6,
198 TEST_GETADDRINFO_ERR_PARAMS
,
200 ntohs(sockaddr_in
->sin_port
));
203 /* If a hostname is numeric, there can't be a canonical name.
204 * Instead, the returned canonname (if requested) will be
205 * identical to the supplied hostname */
206 if (nodename
!= NULL
&& nodename_numerical
&&
207 (flags
& AI_CANONNAME
)) {
208 if (strncmp(ai_cur
->ai_canonname
, nodename
,
210 test_getaddrinfo_err(11,
211 TEST_GETADDRINFO_ERR_PARAMS
,
212 nodename
, ai_cur
->ai_canonname
);
214 /* is canonical supplied? */
215 if (exp_canonname
&& nodename
&&
216 (!ai_cur
->ai_canonname
|| !*ai_cur
->ai_canonname
))
217 test_getaddrinfo_err(7,
218 TEST_GETADDRINFO_ERR_PARAMS
,
219 "(anything)", ai_cur
->ai_canonname
);
221 if (!exp_canonname
&& ai_cur
->ai_canonname
)
222 test_getaddrinfo_err(8,
223 TEST_GETADDRINFO_ERR_PARAMS
,
224 NULL
, ai_cur
->ai_canonname
);
227 /* move to next result */
228 ai_cur
= ai_cur
->ai_next
;
231 /* If socket type is non-zero, make sure we got what we wanted. Else
232 * any result is okay. */
234 if (ai_count_dgram
!= ((socktype
== SOCK_STREAM
) ? 0 : 1))
235 test_getaddrinfo_err_nr(9, TEST_GETADDRINFO_ERR_PARAMS
,
236 (socktype
== SOCK_STREAM
) ? 0 : 1, ai_count_dgram
);
238 if (ai_count_stream
!= ((socktype
== SOCK_DGRAM
) ? 0 : 1))
239 test_getaddrinfo_err_nr(10, TEST_GETADDRINFO_ERR_PARAMS
,
240 (socktype
== SOCK_DGRAM
) ? 0 : 1, ai_count_stream
);
247 static void memsetl(void *s
, unsigned long c
, size_t n
)
249 unsigned char *p
= (unsigned char *) s
;
252 for (i
= 0; i
< n
; i
++)
253 p
[i
] = c
>> (8 * (i
% sizeof(c
)));
256 void test_getnameinfo(
257 unsigned long ipaddr
,
259 const char *exp_node
,
261 const char *exp_service
,
262 socklen_t servicelen
,
266 struct sockaddr_in sockaddr
;
267 char node
[256], service
[256];
270 /* avoid buffer overflows */
271 assert(nodelen
<= sizeof(node
));
272 assert(servicelen
<= sizeof(service
));
274 /* perform query and test result */
275 sockaddr
.sin_family
= AF_INET
;
276 sockaddr
.sin_addr
.s_addr
= ipaddr
;
277 sockaddr
.sin_port
= port
;
278 memsetl(node
, 0xDEADBEEF, nodelen
);
279 memsetl(service
, 0xDEADBEEF, servicelen
);
280 r
= getnameinfo((struct sockaddr
*) &sockaddr
, sizeof(sockaddr
),
281 node
, nodelen
, service
, servicelen
, flags
);
283 if (r
< 0 || r
>= 32 || !((1 << r
) & exp_results
))
284 test_getnameinfo_err_nr(1, TEST_GETNAMEINFO_ERR_PARAMS
,
291 if (nodelen
&& strcmp(exp_node
, node
) != 0)
292 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS
,
295 if (servicelen
&& strcmp(exp_service
, service
) != 0)
296 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS
,
297 exp_service
, service
);
302 const char *nodename
;
303 unsigned long ipaddr
;
309 { NULL
, 0x7f000001, 1, 1, 0, 0 },
310 { "0.0.0.0", 0x00000000, 1, 0, 0, 0 },
311 { "0.0.0.255", 0x000000ff, 1, 0, 0, 0 },
312 { "0.0.255.0", 0x0000ff00, 1, 0, 0, 0 },
313 { "0.255.0.0", 0x00ff0000, 1, 0, 0, 0 },
314 { "255.0.0.0", 0xff000000, 1, 0, 0, 0 },
315 { "127.0.0.1", 0x7f000001, 1, 0, 0, 0 },
316 { "localhost", 0x7f000001, 0, 1, 0, 0, },
317 { "static.minix3.org", 0xC023C00A, 0, 1, 1, 0, },
318 { "", 0x00000000, 1, 0, 0, (1<<EAI_NONAME
)|(1<<EAI_FAIL
)|(1<<EAI_NODATA
)},
319 { "256.256.256.256",0x00000000, 1, 0, 0, (1<<EAI_NONAME
)|(1<<EAI_FAIL
)|(1<<EAI_NODATA
)},
320 { "minix3.xyz", 0x00000000, 0, 0, 1, (1<<EAI_NONAME
)|(1<<EAI_FAIL
)|(1<<EAI_NODATA
)}};
324 const char *servname
;
330 { NULL
, 0, 1, 0, 0 },
333 { "32767", 32767, 1, 0, 0 },
334 { "32768", 32768, 1, 0, 0 },
335 { "65535", 65535, 1, 0, 0 },
336 { "echo", 7, 0, 0, 0 },
337 { "ftp", 21, 0, SOCK_STREAM
, 0 },
338 { "tftp", 69, 0, SOCK_DGRAM
, 0 },
339 { "-1", 0, 1, 0, (1<<EAI_NONAME
) | (1<<EAI_SERVICE
) },
340 { "", 0, 1, 0, (1<<EAI_NONAME
) | (1<<EAI_SERVICE
) },
341 { "65537", 0, 1, 0, (1 << EAI_SERVICE
) },
342 { "XXX", 0, 0, 0, (1 << EAI_SERVICE
) }};
351 { AF_UNSPEC
+ AF_INET
+ 1, (1 << EAI_FAMILY
) }};
361 { SOCK_STREAM
+ SOCK_DGRAM
+ 1,
362 (1 << EAI_SOCKTYPE
) | (1 << EAI_FAIL
) | (1 << EAI_NONAME
) }};
364 #define LENGTH(a) (sizeof((a)) / sizeof((a)[0]))
366 static void test_getaddrinfo_all(int use_network
)
368 int flag_PASSIVE
, flag_CANONNAME
, flag_NUMERICHOST
, flag_NUMERICSERV
;
369 int exp_results
, flags
, i
, j
, k
, l
, passhints
;
370 unsigned long ipaddr
;
372 /* loop through various parameter values */
373 for (i
= 0; i
< LENGTH(hosts
); i
++)
374 for (j
= 0; j
< LENGTH(services
); j
++)
375 for (k
= 0; k
< LENGTH(families
); k
++)
376 for (l
= 0; l
< LENGTH(socktypes
); l
++)
377 for (flag_PASSIVE
= 0; flag_PASSIVE
< 2; flag_PASSIVE
++)
378 for (flag_CANONNAME
= 0; flag_CANONNAME
< 2; flag_CANONNAME
++)
379 for (flag_NUMERICHOST
= 0; flag_NUMERICHOST
< 2; flag_NUMERICHOST
++)
380 for (flag_NUMERICSERV
= 0; flag_NUMERICSERV
< 2; flag_NUMERICSERV
++)
381 for (passhints
= 0; passhints
< 2; passhints
++)
383 /* skip tests that need but cannot use network */
384 if (!use_network
&& hosts
[i
].need_network
)
387 /* determine flags */
388 flags
= (flag_PASSIVE
? AI_PASSIVE
: 0) |
389 (flag_CANONNAME
? AI_CANONNAME
: 0) |
390 (flag_NUMERICHOST
? AI_NUMERICHOST
: 0) |
391 (flag_NUMERICSERV
? AI_NUMERICSERV
: 0);
393 /* some options require hints */
394 if (families
[k
].value
!= AF_UNSPEC
||
395 socktypes
[l
].value
!= 0 || flags
) {
399 /* flags may influence IP address */
400 ipaddr
= hosts
[i
].ipaddr
;
401 if (!hosts
[i
].nodename
&& flag_PASSIVE
)
404 /* determine expected result */
406 hosts
[i
].exp_result
|
407 services
[j
].exp_result
|
408 families
[k
].exp_result
|
409 socktypes
[l
].exp_result
;
410 if (!hosts
[i
].nodename
&& !services
[j
].servname
)
411 exp_results
|= (1 << EAI_NONAME
);
413 if (flag_NUMERICHOST
&& !hosts
[i
].numeric
)
414 exp_results
|= (1 << EAI_NONAME
);
416 if (flag_NUMERICSERV
&& !services
[j
].numeric
)
417 exp_results
|= (1 << EAI_NONAME
);
419 /* When we don't pass hints, getaddrinfo will find suitable
420 * settings for us. If we do pass hints, there might be
424 /* Can't have conflicting socket types */
425 if (services
[j
].socktype
&&
426 socktypes
[l
].value
&&
427 socktypes
[l
].value
!= services
[j
].socktype
) {
428 exp_results
|= (1 << EAI_SERVICE
);
432 /* with no reason for failure, we demand success */
434 exp_results
|= (1 << 0);
436 /* test getaddrinfo function */
440 services
[j
].servname
,
448 flag_CANONNAME
&& hosts
[i
].canonname
,
449 htons(services
[j
].port
));
455 const char *nodename
;
457 unsigned long ipaddr
;
460 { "0.0.0.0", "0.0.0.0", 0x00000000, 0 },
461 { "0.0.0.255", "0.0.0.255", 0x000000ff, 0 },
462 { "0.0.255.0", "0.0.255.0", 0x0000ff00, 0 },
463 { "0.255.0.0", "0.255.0.0", 0x00ff0000, 0 },
464 { "255.0.0.0", "255.0.0.0", 0xff000000, 0 },
465 { "localhost", "127.0.0.1", 0x7f000001, 1 },
466 /* no reverse DNS unfortunately */
467 /* { "minix3.org", "130.37.20.20", 0x82251414, 1 } */};
471 const char *servname
;
477 { "tcpmux", "1", 1, SOCK_STREAM
},
478 { "32767", "32767", 32767, 0 },
479 { "32768", "32768", 32768, 0 },
480 { "65535", "65535", 65535, 0 },
481 { "echo", "7", 7, 0 },
482 { "ftp", "21", 21, SOCK_STREAM
},
483 { "tftp", "69", 69, SOCK_DGRAM
}};
485 static int buflens
[] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 255 };
487 static void test_getnameinfo_all(void)
489 int flag_NUMERICHOST
, flag_NAMEREQD
, flag_NUMERICSERV
, flag_DGRAM
;
490 int exp_results
, flags
, i
, j
, k
, l
, socktypemismatch
;
491 const char *nodename
, *servname
;
493 /* loop through various parameter values */
494 for (i
= 0; i
< LENGTH(ipaddrs
); i
++)
495 for (j
= 0; j
< LENGTH(ports
); j
++)
496 for (k
= 0; k
< LENGTH(buflens
); k
++)
497 for (l
= 0; l
< LENGTH(buflens
); l
++)
498 for (flag_NUMERICHOST
= 0; flag_NUMERICHOST
< 2; flag_NUMERICHOST
++)
499 for (flag_NAMEREQD
= 0; flag_NAMEREQD
< 2; flag_NAMEREQD
++)
500 for (flag_NUMERICSERV
= 0; flag_NUMERICSERV
< 2; flag_NUMERICSERV
++)
501 for (flag_DGRAM
= 0; flag_DGRAM
< 2; flag_DGRAM
++)
503 /* determine flags */
504 flags
= (flag_NUMERICHOST
? NI_NUMERICHOST
: 0) |
505 (flag_NAMEREQD
? NI_NAMEREQD
: 0) |
506 (flag_NUMERICSERV
? NI_NUMERICSERV
: 0) |
507 (flag_DGRAM
? NI_DGRAM
: 0);
509 /* determine expected result */
512 nodename
= flag_NUMERICHOST
? ipaddrs
[i
].nodenum
: ipaddrs
[i
].nodename
;
513 if (buflens
[k
] > 0 && buflens
[k
] <= strlen(nodename
))
514 exp_results
|= (1 << EAI_OVERFLOW
) | (1 << EAI_MEMORY
);
517 (flag_DGRAM
&& ports
[j
].socktype
== SOCK_STREAM
) ||
518 (!flag_DGRAM
&& ports
[j
].socktype
== SOCK_DGRAM
);
519 servname
= (flag_NUMERICSERV
|| socktypemismatch
) ?
520 ports
[j
].servnum
: ports
[j
].servname
;
521 if (buflens
[l
] > 0 && buflens
[l
] <= strlen(servname
))
522 exp_results
|= (1 << EAI_OVERFLOW
) | (1 << EAI_MEMORY
);
524 if (flag_NAMEREQD
&& (!ipaddrs
[i
].havename
|| flag_NUMERICHOST
) && buflens
[k
])
525 exp_results
|= (1 << EAI_NONAME
);
527 /* with no reason for failure, we demand success */
529 exp_results
|= (1 << 0);
531 /* perform the test */
533 htonl(ipaddrs
[i
].ipaddr
),
534 htons(ports
[j
].port
),
544 static int can_use_network(void)
548 /* try to ping minix3.org */
549 status
= system("ping www.minix3.org > /dev/null 2>&1");
552 printf("cannot execute ping\n");
565 use_network
= can_use_network();
567 printf("Warning: no network\n");
568 test_getaddrinfo_all(use_network
);
569 test_getnameinfo_all();