Remove building with NOCRYPTO option
[minix.git] / minix / tests / test48.c
blob8b8d2458fa4e65ecab59a44e0de64b911b982d3b
1 #include <arpa/inet.h>
2 #include <assert.h>
3 #include <netdb.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
9 int max_error = 3;
10 #include "common.h"
12 #define err() e(__LINE__)
14 static void printstr(const char *s)
16 if (s)
17 printf("\"%s\"", s);
18 else
19 printf("NULL");
22 static void test_getaddrinfo_err(
23 int n,
24 const char *nodename,
25 const char *servname,
26 int passhints,
27 int flags,
28 int family,
29 int socktype,
30 const char *exp_result,
31 const char *result)
33 printf("error %d: getaddrinfo(", n);
34 printstr(nodename);
35 printf(", ");
36 printstr(servname);
37 printf(", ");
38 if (passhints)
39 printf("{ 0x%x, %d, %d }", flags, family, socktype);
40 else
41 printf("NULL");
43 printf("); result: ");
44 printstr(result);
45 printf("; expected: ");
46 printstr(exp_result);
47 printf("\n");
48 err();
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(
56 int n,
57 const char *nodename,
58 const char *servname,
59 int passhints,
60 int flags,
61 int family,
62 int socktype,
63 int exp_result,
64 int result)
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(
77 int n,
78 unsigned long ipaddr,
79 unsigned short port,
80 socklen_t nodelen,
81 socklen_t servicelen,
82 int flags,
83 const char *exp_result,
84 const char *result)
86 printf("error %d: getnameinfo(0x%.8x, %d, %d, %d, 0x%x); result: ",
87 n, ntohl(ipaddr), ntohs(port), nodelen, servicelen, flags);
88 printstr(result);
89 printf("; expected: ");
90 printstr(exp_result);
91 printf("\n");
92 err();
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(
99 int n,
100 unsigned long ipaddr,
101 unsigned short port,
102 socklen_t nodelen,
103 socklen_t servicelen,
104 int flags,
105 int exp_result,
106 int result)
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,
123 int passhints,
124 int flags,
125 int family,
126 int socktype,
127 int exp_results,
128 unsigned long exp_ip,
129 int exp_canonname,
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);
159 if (r)
160 return;
162 /* the function succeeded; do the results make sense? */
163 ai_cur = ai;
164 ai_count_dgram = 0;
165 ai_count_stream = 0;
166 while (ai_cur)
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;
176 continue;
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),
198 ai_cur->ai_addrlen);
199 else
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,
205 ntohl(exp_ip),
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,
211 ntohs(exp_port),
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,
221 strlen(nodename)))
222 test_getaddrinfo_err(11,
223 TEST_GETADDRINFO_ERR_PARAMS,
224 nodename, ai_cur->ai_canonname);
225 } else {
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. */
245 if (socktype) {
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);
255 /* clean up */
256 freeaddrinfo(ai);
259 static void memsetl(void *s, unsigned long c, size_t n)
261 unsigned char *p = (unsigned char *) s;
262 size_t i;
264 for (i = 0; i < n; i++)
265 p[i] = c >> (8 * (i % sizeof(c)));
268 static void test_getnameinfo(
269 unsigned long ipaddr,
270 unsigned short port,
271 const char *exp_node,
272 socklen_t nodelen,
273 const char *exp_service,
274 socklen_t servicelen,
275 int flags,
276 int exp_results)
278 struct sockaddr_in sockaddr;
279 char node[256], service[256];
280 int r;
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,
297 exp_results, r);
299 if (r)
300 return;
302 /* check results */
303 if (nodelen && strcmp(exp_node, node) != 0)
304 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
305 exp_node, node);
307 if (servicelen && strcmp(exp_service, service) != 0)
308 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
309 exp_service, service);
312 static struct
314 const char *nodename;
315 unsigned long ipaddr;
316 int numeric;
317 int canonname;
318 int need_network;
319 int exp_result;
320 } hosts[] = {
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)}};
332 static struct
334 const char *servname;
335 unsigned short port;
336 int numeric;
337 int socktype;
338 int exp_result;
339 } services[] = {
340 { NULL, 0, 1, 0, 0 },
341 { "0", 0, 1, 0, 0 },
342 { "1", 1, 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) }};
354 static struct
356 int value;
357 int exp_result;
358 } families[] = {
359 { AF_UNSPEC, 0 },
360 { AF_INET, 0 },
361 { AF_UNSPEC + AF_INET + 1, (1 << EAI_FAMILY) }};
363 static struct
365 int value;
366 int exp_result;
367 } socktypes[] = {
368 { 0, 0 },
369 { SOCK_STREAM, 0 },
370 { SOCK_DGRAM, 0 },
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)
400 continue;
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) {
411 passhints = 1;
414 /* flags may influence IP address */
415 ipaddr = hosts[i].ipaddr;
416 if (!hosts[i].nodename && flag_PASSIVE)
417 ipaddr = INADDR_ANY;
419 /* determine expected result */
420 exp_results =
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
436 * conflicts.
438 if (passhints) {
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 */
448 if (!exp_results)
449 exp_results |= (1 << 0);
451 /* test getaddrinfo function */
452 test_getaddrinfo(
453 hosts[i].nodename,
454 hosts[i].numeric,
455 services[j].servname,
456 services[j].numeric,
457 passhints,
458 flags,
459 families[k].value,
460 socktypes[l].value,
461 exp_results,
462 htonl(ipaddr),
463 flag_CANONNAME && hosts[i].canonname,
464 htons(services[j].port));
468 static struct
470 const char *nodename;
471 const char *nodenum;
472 unsigned long ipaddr;
473 int havename;
474 } ipaddrs[] = {
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 } */};
484 static struct
486 const char *servname;
487 const char *servnum;
488 unsigned short port;
489 int socktype;
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" */
492 } ports[] = {
493 { "0", "0", 0, 0 },
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 */
561 exp_results = 0;
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 */
579 if (!exp_results)
580 exp_results |= (1 << 0);
582 /* perform the test */
583 test_getnameinfo(
584 htonl(ipaddrs[i].ipaddr),
585 htons(ports[j].port),
586 nodename,
587 buflens[k],
588 servname,
589 buflens[l],
590 flags,
591 exp_results);
595 int main(void)
597 int use_network;
599 start(48);
601 use_network = get_setting_use_network();
602 test_getaddrinfo_all(use_network);
603 test_getnameinfo_all();
605 quit();
606 return 0;