use oxpcie only if enabled to avoid baud bottleneck of uart.
[minix.git] / test / test48.c
blobbbed6685d564e39281a03da7a9da30c64b36b71b
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 #define MAX_ERRORS 8
11 static int errct;
13 static void quit(void)
15 if (errct > 0)
17 printf("%d errors\n", errct);
18 exit(1);
20 else
22 printf("ok\n");
23 exit(0);
27 static void err(void)
29 if (++errct >= MAX_ERRORS)
31 printf("aborted, too many errors\n");
32 quit();
36 static void printstr(const char *s)
38 if (s)
39 printf("\"%s\"", s);
40 else
41 printf("NULL");
44 static void test_getaddrinfo_err(
45 int n,
46 const char *nodename,
47 const char *servname,
48 int passhints,
49 int flags,
50 int family,
51 int socktype,
52 const char *exp_result,
53 const char *result)
55 printf("error %d: getaddrinfo(", n);
56 printstr(nodename);
57 printf(", ");
58 printstr(servname);
59 printf(", ");
60 if (passhints)
61 printf("{ 0x%x, %d, %d }", flags, family, socktype);
62 else
63 printf("NULL");
65 printf("); result: ");
66 printstr(result);
67 printf("; expected: ");
68 printstr(exp_result);
69 printf("\n");
70 err();
73 /* yes, this is ugly, but not as ugly as repeating it all every time */
74 #define TEST_GETADDRINFO_ERR_PARAMS \
75 nodename, servname, passhints, flags, family, socktype
77 static void test_getaddrinfo_err_nr(
78 int n,
79 const char *nodename,
80 const char *servname,
81 int passhints,
82 int flags,
83 int family,
84 int socktype,
85 int exp_result,
86 int result)
88 char exp_result_s[23], result_s[23];
90 /* convert result to string */
91 snprintf(exp_result_s, sizeof(exp_result_s), "%d/0x%x",
92 exp_result, exp_result);
93 snprintf(result_s, sizeof(result_s), "%d/0x%x", result, result);
94 test_getaddrinfo_err(n, TEST_GETADDRINFO_ERR_PARAMS,
95 exp_result_s, result_s);
98 static void test_getnameinfo_err(
99 int n,
100 unsigned long ipaddr,
101 unsigned short port,
102 socklen_t nodelen,
103 socklen_t servicelen,
104 int flags,
105 const char *exp_result,
106 const char *result)
108 printf("error %d: getnameinfo(0x%.8x, %d, %d, %d, 0x%x); result: ",
109 n, ntohl(ipaddr), ntohs(port), nodelen, servicelen, flags);
110 printstr(result);
111 printf("; expected: ");
112 printstr(exp_result);
113 printf("\n");
114 err();
117 /* yes, this is ugly, but not as ugly as repeating it all every time */
118 #define TEST_GETNAMEINFO_ERR_PARAMS ipaddr, port, nodelen, servicelen, flags
120 static void test_getnameinfo_err_nr(
121 int n,
122 unsigned long ipaddr,
123 unsigned short port,
124 socklen_t nodelen,
125 socklen_t servicelen,
126 int flags,
127 int exp_result,
128 int result)
130 char exp_result_s[23], result_s[23];
132 /* convert result to string */
133 snprintf(exp_result_s, sizeof(exp_result_s), "%d/0x%x",
134 exp_result, exp_result);
135 snprintf(result_s, sizeof(result_s), "%d/0x%x", result, result);
136 test_getnameinfo_err(n, TEST_GETNAMEINFO_ERR_PARAMS,
137 exp_result_s, result_s);
140 static void test_getaddrinfo(
141 const char *nodename,
142 const char *servname,
143 int passhints,
144 int flags,
145 int family,
146 int socktype,
147 int exp_results,
148 unsigned long exp_ip,
149 int exp_canonname,
150 unsigned short exp_port)
152 struct addrinfo *ai, *ai_cur;
153 struct addrinfo hints;
154 struct sockaddr_in *sockaddr_in;
155 int ai_count_dgram, ai_count_stream, r;
157 /* some parameters are only meaningful with hints */
158 assert(passhints || !flags);
159 assert(passhints || family == AF_UNSPEC);
160 assert(passhints || !socktype);
162 /* initialize hints */
163 memset(&hints, 0, sizeof(hints));
164 hints.ai_flags = flags;
165 hints.ai_family = family;
166 hints.ai_socktype = socktype;
167 hints.ai_family = family;
169 /* perform query and test result */
170 ai = (struct addrinfo *) 0xDEADBEEF;
171 r = getaddrinfo(nodename, servname, passhints ? &hints : NULL, &ai);
172 if (r < 0 || r >= 32 || !((1 << r) & exp_results))
173 test_getaddrinfo_err_nr(1, TEST_GETADDRINFO_ERR_PARAMS, exp_results, r);
175 if (r)
176 return;
178 /* the function succeeded; do the results make sense? */
179 ai_cur = ai;
180 ai_count_dgram = 0;
181 ai_count_stream = 0;
182 while (ai_cur)
184 /* test result fields */
185 if (ai_cur->ai_family != AF_INET)
186 test_getaddrinfo_err_nr(2, TEST_GETADDRINFO_ERR_PARAMS,
187 AF_INET, ai_cur->ai_family);
189 if (socktype && ai_cur->ai_socktype != socktype)
190 test_getaddrinfo_err_nr(3, TEST_GETADDRINFO_ERR_PARAMS,
191 socktype, ai_cur->ai_socktype);
193 switch (ai_cur->ai_socktype)
195 case SOCK_DGRAM: ai_count_dgram++; break;
196 case SOCK_STREAM: ai_count_stream++; break;
199 /* do address and port match? */
200 if (ai_cur->ai_addrlen != sizeof(struct sockaddr_in))
201 test_getaddrinfo_err_nr(4, TEST_GETADDRINFO_ERR_PARAMS,
202 sizeof(struct sockaddr_in),
203 ai_cur->ai_addrlen);
204 else
206 sockaddr_in = (struct sockaddr_in *) ai_cur->ai_addr;
207 if (sockaddr_in->sin_addr.s_addr != exp_ip)
208 test_getaddrinfo_err_nr(5,
209 TEST_GETADDRINFO_ERR_PARAMS,
210 ntohl(exp_ip),
211 ntohl(sockaddr_in->sin_addr.s_addr));
213 if (sockaddr_in->sin_port != exp_port)
214 test_getaddrinfo_err_nr(6,
215 TEST_GETADDRINFO_ERR_PARAMS,
216 ntohs(exp_port),
217 ntohs(sockaddr_in->sin_port));
220 /* is canonical supplied? */
221 if (exp_canonname &&
222 (!ai_cur->ai_canonname || !*ai_cur->ai_canonname))
223 test_getaddrinfo_err(7,
224 TEST_GETADDRINFO_ERR_PARAMS,
225 "(anything)", ai_cur->ai_canonname);
227 if (!exp_canonname && ai_cur->ai_canonname)
228 test_getaddrinfo_err(8,
229 TEST_GETADDRINFO_ERR_PARAMS,
230 NULL, ai_cur->ai_canonname);
232 /* move to next result */
233 ai_cur = ai_cur->ai_next;
236 /* check number of results */
237 if (ai_count_dgram != ((socktype == SOCK_STREAM) ? 0 : 1))
238 test_getaddrinfo_err_nr(9, TEST_GETADDRINFO_ERR_PARAMS,
239 (socktype == SOCK_STREAM) ? 0 : 1, ai_count_dgram);
241 if (ai_count_stream != ((socktype == SOCK_DGRAM) ? 0 : 1))
242 test_getaddrinfo_err_nr(10, TEST_GETADDRINFO_ERR_PARAMS,
243 (socktype == SOCK_DGRAM) ? 0 : 1, ai_count_stream);
245 /* clean up */
246 freeaddrinfo(ai);
249 static void memsetl(void *s, unsigned long c, size_t n)
251 unsigned char *p = (unsigned char *) s;
252 size_t i;
254 for (i = 0; i < n; i++)
255 p[i] = c >> (8 * (i % sizeof(c)));
258 void test_getnameinfo(
259 unsigned long ipaddr,
260 unsigned short port,
261 const char *exp_node,
262 socklen_t nodelen,
263 const char *exp_service,
264 socklen_t servicelen,
265 int flags,
266 int exp_results)
268 struct sockaddr_in sockaddr;
269 char node[256], service[256];
270 int r;
272 /* avoid buffer overflows */
273 assert(nodelen <= sizeof(node));
274 assert(servicelen <= sizeof(service));
276 /* perform query and test result */
277 sockaddr.sin_family = AF_INET;
278 sockaddr.sin_addr.s_addr = ipaddr;
279 sockaddr.sin_port = port;
280 memsetl(node, 0xDEADBEEF, nodelen);
281 memsetl(service, 0xDEADBEEF, servicelen);
282 r = getnameinfo((struct sockaddr *) &sockaddr, sizeof(sockaddr),
283 node, nodelen, service, servicelen, flags);
285 if (r < 0 || r >= 32 || !((1 << r) & exp_results))
286 test_getnameinfo_err_nr(1, TEST_GETNAMEINFO_ERR_PARAMS,
287 exp_results, r);
289 if (r)
290 return;
292 /* check results */
293 if (nodelen && strcmp(exp_node, node) != 0)
294 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
295 exp_node, node);
297 if (servicelen && strcmp(exp_service, service) != 0)
298 test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
299 exp_service, service);
302 static struct
304 const char *nodename;
305 unsigned long ipaddr;
306 int numeric;
307 int canonname;
308 int need_network;
309 int exp_result;
310 } hosts[] = {
311 { NULL, 0x7f000001, 1, 1, 0, 0 },
312 { "0.0.0.0", 0x00000000, 1, 0, 0, 0, },
313 { "0.0.0.255", 0x000000ff, 1, 0, 0, 0, },
314 { "0.0.255.0", 0x0000ff00, 1, 0, 0, 0, },
315 { "0.255.0.0", 0x00ff0000, 1, 0, 0, 0, },
316 { "255.0.0.0", 0xff000000, 1, 0, 0, 0, },
317 { "127.0.0.1", 0x7f000001, 1, 0, 0, 0, },
318 { "localhost", 0x7f000001, 0, 1, 0, 0, },
319 { "minix3.org", 0x82251414, 0, 1, 1, 0, },
320 { "", 0x00000000, 1, 0, 0, (1 << EAI_NONAME) },
321 { "256.256.256.256", 0x00000000, 1, 0, 0, (1 << EAI_NONAME) },
322 { "minix3.xxx", 0x00000000, 0, 0, 1, (1 << EAI_NONAME) }};
324 static struct
326 const char *servname;
327 unsigned short port;
328 int numeric;
329 int socktype;
330 int exp_result;
331 } services[] = {
332 { NULL, 0, 1, 0, 0 },
333 { "0", 0, 1, 0, 0 },
334 { "1", 1, 1, 0, 0 },
335 { "32767", 32767, 1, 0, 0 },
336 { "32768", 32768, 1, 0, 0 },
337 { "65535", 65535, 1, 0, 0 },
338 { "echo", 7, 0, 0, 0 },
339 { "ftp", 21, 0, SOCK_STREAM, 0 },
340 { "tftp", 69, 0, SOCK_DGRAM , 0 },
341 { "-1", 0, 1, 0, (1 << EAI_SERVICE) },
342 { "", 0, 1, 0, (1 << EAI_SERVICE) },
343 { "65537", 0, 1, 0, (1 << EAI_SERVICE) },
344 { "XXX", 0, 0, 0, (1 << EAI_SERVICE) }};
346 static struct
348 int value;
349 int exp_result;
350 } families[] = {
351 { AF_UNSPEC, 0 },
352 { AF_INET, 0 },
353 { AF_UNSPEC + AF_INET + 1, (1 << EAI_FAMILY) }};
355 static struct
357 int value;
358 int exp_result;
359 } socktypes[] = {
360 { 0, 0 },
361 { SOCK_STREAM, 0 },
362 { SOCK_DGRAM, 0 },
363 { SOCK_STREAM + SOCK_DGRAM + 1, (1 << EAI_SOCKTYPE) }};
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, needhints, 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++)
383 /* skip tests that need but cannot use network */
384 if (!use_network && hosts[i].need_network)
385 continue;
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 /* flags may influence IP address */
394 ipaddr = hosts[i].ipaddr;
395 if (!hosts[i].nodename && flag_PASSIVE)
396 ipaddr = INADDR_ANY;
398 /* determine expected result */
399 exp_results =
400 hosts[i].exp_result |
401 services[j].exp_result |
402 families[k].exp_result |
403 socktypes[l].exp_result;
404 if (!hosts[i].nodename && !services[j].servname)
405 exp_results |= (1 << EAI_NONAME);
407 if (flag_NUMERICHOST && !hosts[i].numeric)
408 exp_results |= (1 << EAI_NONAME);
410 if (flag_NUMERICSERV && !services[j].numeric)
411 exp_results |= (1 << EAI_SERVICE);
413 if (services[j].socktype && socktypes[l].value != services[j].socktype)
414 exp_results |= (1 << EAI_SERVICE);
416 /* with no reason for failure, we demand success */
417 if (!exp_results)
418 exp_results |= (1 << 0);
420 /* some options require hints */
421 needhints = (families[k].value != AF_UNSPEC ||
422 socktypes[l].value != 0 || flags) ? 1 : 0;
423 for (passhints = needhints; passhints < 2; passhints++)
425 /* test getaddrinfo function */
426 test_getaddrinfo(
427 hosts[i].nodename,
428 services[j].servname,
429 passhints,
430 flags,
431 families[k].value,
432 socktypes[l].value,
433 exp_results,
434 htonl(ipaddr),
435 flag_CANONNAME && hosts[i].canonname,
436 htons(services[j].port));
441 static struct
443 const char *nodename;
444 const char *nodenum;
445 unsigned long ipaddr;
446 int havename;
447 } ipaddrs[] = {
448 { "0.0.0.0", "0.0.0.0", 0x00000000, 0 },
449 { "0.0.0.255", "0.0.0.255", 0x000000ff, 0 },
450 { "0.0.255.0", "0.0.255.0", 0x0000ff00, 0 },
451 { "0.255.0.0", "0.255.0.0", 0x00ff0000, 0 },
452 { "255.0.0.0", "255.0.0.0", 0xff000000, 0 },
453 { "localhost", "127.0.0.1", 0x7f000001, 1 },
454 /* no reverse DNS unfortunately */
455 /* { "minix3.org", "130.37.20.20", 0x82251414, 1 } */};
457 static struct
459 const char *servname;
460 const char *servnum;
461 unsigned short port;
462 int socktype;
463 } ports[] = {
464 { "0", "0", 0, 0 },
465 { "tcpmux", "1", 1, SOCK_STREAM },
466 { "32767", "32767", 32767, 0 },
467 { "32768", "32768", 32768, 0 },
468 { "65535", "65535", 65535, 0 },
469 { "echo", "7", 7, 0 },
470 { "ftp", "21", 21, SOCK_STREAM },
471 { "tftp", "69", 69, SOCK_DGRAM }};
473 static int buflens[] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 255 };
475 static void test_getnameinfo_all(void)
477 int flag_NUMERICHOST, flag_NAMEREQD, flag_NUMERICSERV, flag_DGRAM;
478 int exp_results, flags, i, j, k, l, socktypemismatch;
479 const char *nodename, *servname;
481 /* loop through various parameter values */
482 for (i = 0; i < LENGTH(ipaddrs); i++)
483 for (j = 0; j < LENGTH(ports); j++)
484 for (k = 0; k < LENGTH(buflens); k++)
485 for (l = 0; l < LENGTH(buflens); l++)
486 for (flag_NUMERICHOST = 0; flag_NUMERICHOST < 2; flag_NUMERICHOST++)
487 for (flag_NAMEREQD = 0; flag_NAMEREQD < 2; flag_NAMEREQD++)
488 for (flag_NUMERICSERV = 0; flag_NUMERICSERV < 2; flag_NUMERICSERV++)
489 for (flag_DGRAM = 0; flag_DGRAM < 2; flag_DGRAM++)
491 /* determine flags */
492 flags = (flag_NUMERICHOST ? NI_NUMERICHOST : 0) |
493 (flag_NAMEREQD ? NI_NAMEREQD : 0) |
494 (flag_NUMERICSERV ? NI_NUMERICSERV : 0) |
495 (flag_DGRAM ? NI_DGRAM : 0);
497 /* determine expected result */
498 exp_results = 0;
499 if (!buflens[k] && !buflens[l])
500 exp_results |= (1 << EAI_NONAME);
502 nodename = flag_NUMERICHOST ? ipaddrs[i].nodenum : ipaddrs[i].nodename;
503 if (buflens[k] > 0 && buflens[k] <= strlen(nodename))
504 exp_results |= (1 << EAI_OVERFLOW);
506 socktypemismatch =
507 (flag_DGRAM && ports[j].socktype == SOCK_STREAM) ||
508 (!flag_DGRAM && ports[j].socktype == SOCK_DGRAM);
509 servname = (flag_NUMERICSERV || socktypemismatch) ?
510 ports[j].servnum : ports[j].servname;
511 if (buflens[l] > 0 && buflens[l] <= strlen(servname))
512 exp_results |= (1 << EAI_OVERFLOW);
514 if (flag_NAMEREQD && (!ipaddrs[i].havename | flag_NUMERICHOST) && buflens[k])
515 exp_results |= (1 << EAI_NONAME);
517 /* with no reason for failure, we demand success */
518 if (!exp_results)
519 exp_results |= (1 << 0);
521 /* perform the test */
522 test_getnameinfo(
523 htonl(ipaddrs[i].ipaddr),
524 htons(ports[j].port),
525 nodename,
526 buflens[k],
527 servname,
528 buflens[l],
529 flags,
530 exp_results);
534 static int can_use_network(void)
536 pid_t pid;
537 int status;
539 /* try to ping minix3.org */
540 status = system("ping www.minix3.org > /dev/null 2>&1");
541 if (status == 127)
543 printf("cannot execute ping\n");
544 err();
547 return status == 0;
550 int main(void)
552 int use_network;
554 printf("Test 48 ");
555 fflush(stdout);
557 use_network = can_use_network();
558 if (!use_network)
559 printf("Warning: no network\n");
561 test_getaddrinfo_all(use_network);
562 test_getnameinfo_all();
564 quit();
565 return 0;