Obey HAVE_GOLD=no to no intent to build gold
[minix3.git] / minix / tests / test48.c
blob5cb239176045e4804fa8da632bcd900f6c5d8d01
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)
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),
187 ai_cur->ai_addrlen);
188 else
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,
194 ntohl(exp_ip),
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,
200 ntohs(exp_port),
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,
210 strlen(nodename)))
211 test_getaddrinfo_err(11,
212 TEST_GETADDRINFO_ERR_PARAMS,
213 nodename, ai_cur->ai_canonname);
214 } else {
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. */
234 if (socktype) {
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);
244 /* clean up */
245 freeaddrinfo(ai);
248 static void memsetl(void *s, unsigned long c, size_t n)
250 unsigned char *p = (unsigned char *) s;
251 size_t i;
253 for (i = 0; i < n; i++)
254 p[i] = c >> (8 * (i % sizeof(c)));
257 static void test_getnameinfo(
258 unsigned long ipaddr,
259 unsigned short port,
260 const char *exp_node,
261 socklen_t nodelen,
262 const char *exp_service,
263 socklen_t servicelen,
264 int flags,
265 int exp_results)
267 struct sockaddr_in sockaddr;
268 char node[256], service[256];
269 int r;
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,
286 exp_results, r);
288 if (r)
289 return;
291 /* check results */
292 if (nodelen && strcmp(exp_node, node) != 0)
293 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
294 exp_node, node);
296 if (servicelen && strcmp(exp_service, service) != 0)
297 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
298 exp_service, service);
301 static struct
303 const char *nodename;
304 unsigned long ipaddr;
305 int numeric;
306 int canonname;
307 int need_network;
308 int exp_result;
309 } hosts[] = {
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 { "test48.minix3.org", 0x7f010203, 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.example.com", 0x00000000, 0, 0, 1, (1<<EAI_NONAME)|(1<<EAI_FAIL)|(1<<EAI_NODATA)}};
323 static struct
325 const char *servname;
326 unsigned short port;
327 int numeric;
328 int socktype;
329 int exp_result;
330 } services[] = {
331 { NULL, 0, 1, 0, 0 },
332 { "0", 0, 1, 0, 0 },
333 { "1", 1, 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) }};
345 static struct
347 int value;
348 int exp_result;
349 } families[] = {
350 { AF_UNSPEC, 0 },
351 { AF_INET, 0 },
352 { AF_UNSPEC + AF_INET + 1, (1 << EAI_FAMILY) }};
354 static struct
356 int value;
357 int exp_result;
358 } socktypes[] = {
359 { 0, 0 },
360 { SOCK_STREAM, 0 },
361 { SOCK_DGRAM, 0 },
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, flagcount, 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 some redundant combinations */
385 flagcount = flag_PASSIVE + flag_CANONNAME +
386 flag_NUMERICHOST + flag_NUMERICSERV;
387 if (flagcount > 1 && flagcount < 4) continue;
389 /* skip tests that need but cannot use network */
390 if (!use_network && hosts[i].need_network)
391 continue;
393 /* determine flags */
394 flags = (flag_PASSIVE ? AI_PASSIVE : 0) |
395 (flag_CANONNAME ? AI_CANONNAME : 0) |
396 (flag_NUMERICHOST ? AI_NUMERICHOST : 0) |
397 (flag_NUMERICSERV ? AI_NUMERICSERV : 0);
399 /* some options require hints */
400 if (families[k].value != AF_UNSPEC ||
401 socktypes[l].value != 0 || flags) {
402 passhints = 1;
405 /* flags may influence IP address */
406 ipaddr = hosts[i].ipaddr;
407 if (!hosts[i].nodename && flag_PASSIVE)
408 ipaddr = INADDR_ANY;
410 /* determine expected result */
411 exp_results =
412 hosts[i].exp_result |
413 services[j].exp_result |
414 families[k].exp_result |
415 socktypes[l].exp_result;
416 if (!hosts[i].nodename && !services[j].servname)
417 exp_results |= (1 << EAI_NONAME);
419 if (flag_NUMERICHOST && !hosts[i].numeric)
420 exp_results |= (1 << EAI_NONAME);
422 if (flag_NUMERICSERV && !services[j].numeric)
423 exp_results |= (1 << EAI_NONAME);
425 /* When we don't pass hints, getaddrinfo will find suitable
426 * settings for us. If we do pass hints, there might be
427 * conflicts.
429 if (passhints) {
430 /* Can't have conflicting socket types */
431 if (services[j].socktype &&
432 socktypes[l].value &&
433 socktypes[l].value != services[j].socktype) {
434 exp_results |= (1 << EAI_SERVICE);
438 /* with no reason for failure, we demand success */
439 if (!exp_results)
440 exp_results |= (1 << 0);
442 /* test getaddrinfo function */
443 test_getaddrinfo(
444 hosts[i].nodename,
445 hosts[i].numeric,
446 services[j].servname,
447 services[j].numeric,
448 passhints,
449 flags,
450 families[k].value,
451 socktypes[l].value,
452 exp_results,
453 htonl(ipaddr),
454 flag_CANONNAME && hosts[i].canonname,
455 htons(services[j].port));
459 static struct
461 const char *nodename;
462 const char *nodenum;
463 unsigned long ipaddr;
464 int havename;
465 } ipaddrs[] = {
466 { "0.0.0.0", "0.0.0.0", 0x00000000, 0 },
467 { "0.0.0.255", "0.0.0.255", 0x000000ff, 0 },
468 { "0.0.255.0", "0.0.255.0", 0x0000ff00, 0 },
469 { "0.255.0.0", "0.255.0.0", 0x00ff0000, 0 },
470 { "255.0.0.0", "255.0.0.0", 0xff000000, 0 },
471 { "localhost", "127.0.0.1", 0x7f000001, 1 },
472 /* no reverse DNS unfortunately */
473 /* { "minix3.org", "130.37.20.20", 0x82251414, 1 } */};
475 static struct
477 const char *servname;
478 const char *servnum;
479 unsigned short port;
480 int socktype;
481 struct servent *se_tcp; /* getservbyport() s_name on this port with "tcp" */
482 struct servent *se_udp; /* getservbyport() s_name on this port with "udp" */
483 } ports[] = {
484 { "0", "0", 0, 0 },
485 { "tcpmux", "1", 1, SOCK_STREAM },
486 { "32767", "32767", 32767, 0 },
487 { "32768", "32768", 32768, 0 },
488 { "65535", "65535", 65535, 0 },
489 { "echo", "7", 7, 0 },
490 { "ftp", "21", 21, SOCK_STREAM },
491 { "tftp", "69", 69, SOCK_DGRAM }};
493 static int buflens[] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 255 };
495 static void test_getnameinfo_all(void)
497 int flag_NUMERICHOST, flag_NAMEREQD, flag_NUMERICSERV, flag_DGRAM;
498 int exp_results, flagcount, flags, i, j, k, l;
499 const char *nodename, *servname;
501 /* set ports servent structs */
502 for (j = 0; j < LENGTH(ports); j++) {
503 struct servent *se_tcp, *se_udp;
505 se_tcp = getservbyport(htons(ports[j].port), "tcp");
506 ports[j].se_tcp = se_tcp;
508 if(ports[j].se_tcp) {
509 ports[j].se_tcp = malloc(sizeof(struct servent));
510 memcpy(ports[j].se_tcp, se_tcp, sizeof(*se_tcp));
511 assert(ports[j].se_tcp->s_name);
512 ports[j].se_tcp->s_name = strdup(ports[j].se_tcp->s_name);
513 assert(ports[j].se_tcp->s_name);
516 se_udp = getservbyport(htons(ports[j].port), "udp");
517 ports[j].se_udp = se_udp;
519 if(ports[j].se_udp) {
520 ports[j].se_udp = malloc(sizeof(struct servent));
521 memcpy(ports[j].se_udp, se_udp, sizeof(*se_udp));
522 assert(ports[j].se_udp->s_name);
523 ports[j].se_udp->s_name = strdup(ports[j].se_udp->s_name);
524 assert(ports[j].se_udp->s_name);
528 /* loop through various parameter values */
529 for (i = 0; i < LENGTH(ipaddrs); i++)
530 for (j = 0; j < LENGTH(ports); j++)
531 for (k = 0; k < LENGTH(buflens); k++)
532 for (l = 0; l < LENGTH(buflens); l++)
533 for (flag_NUMERICHOST = 0; flag_NUMERICHOST < 2; flag_NUMERICHOST++)
534 for (flag_NAMEREQD = 0; flag_NAMEREQD < 2; flag_NAMEREQD++)
535 for (flag_NUMERICSERV = 0; flag_NUMERICSERV < 2; flag_NUMERICSERV++)
536 for (flag_DGRAM = 0; flag_DGRAM < 2; flag_DGRAM++)
538 /* skip some redundant combinations */
539 flagcount = flag_NUMERICHOST + flag_NAMEREQD +
540 flag_NUMERICSERV + flag_DGRAM;
541 if (flagcount > 1 && flagcount < 4) continue;
542 if (k > 1 && k < LENGTH(buflens) - 2 &&
543 l > 1 && l < LENGTH(buflens) - 2) continue;
545 /* determine flags */
546 flags = (flag_NUMERICHOST ? NI_NUMERICHOST : 0) |
547 (flag_NAMEREQD ? NI_NAMEREQD : 0) |
548 (flag_NUMERICSERV ? NI_NUMERICSERV : 0) |
549 (flag_DGRAM ? NI_DGRAM : 0);
551 /* determine expected result */
552 exp_results = 0;
554 nodename = flag_NUMERICHOST ? ipaddrs[i].nodenum : ipaddrs[i].nodename;
555 if (buflens[k] > 0 && buflens[k] <= strlen(nodename))
556 exp_results |= (1 << EAI_OVERFLOW) | (1 << EAI_MEMORY);
558 struct servent *se = flag_DGRAM ? ports[j].se_udp : ports[j].se_tcp;
560 servname = (flag_NUMERICSERV) ?
561 ports[j].servnum : (se ? se->s_name : ports[j].servname);
563 if (buflens[l] > 0 && buflens[l] <= strlen(servname))
564 exp_results |= (1 << EAI_OVERFLOW) | (1 << EAI_MEMORY);
566 if (flag_NAMEREQD && (!ipaddrs[i].havename || flag_NUMERICHOST) && buflens[k])
567 exp_results |= (1 << EAI_NONAME);
569 /* with no reason for failure, we demand success */
570 if (!exp_results)
571 exp_results |= (1 << 0);
573 /* perform the test */
574 test_getnameinfo(
575 htonl(ipaddrs[i].ipaddr),
576 htons(ports[j].port),
577 nodename,
578 buflens[k],
579 servname,
580 buflens[l],
581 flags,
582 exp_results);
586 int main(void)
588 int use_network;
590 start(48);
592 use_network = get_setting_use_network();
593 test_getaddrinfo_all(use_network);
594 test_getnameinfo_all();
596 quit();
597 return 0;