custom message for vm_update
[minix3.git] / test / test48.c
blob33f565c664b390e45622f7cf82ed51bde022f595
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 { "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)}};
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, 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)
386 continue;
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) {
397 passhints = 1;
400 /* flags may influence IP address */
401 ipaddr = hosts[i].ipaddr;
402 if (!hosts[i].nodename && flag_PASSIVE)
403 ipaddr = INADDR_ANY;
405 /* determine expected result */
406 exp_results =
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
422 * conflicts.
424 if (passhints) {
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 */
434 if (!exp_results)
435 exp_results |= (1 << 0);
437 /* test getaddrinfo function */
438 test_getaddrinfo(
439 hosts[i].nodename,
440 hosts[i].numeric,
441 services[j].servname,
442 services[j].numeric,
443 passhints,
444 flags,
445 families[k].value,
446 socktypes[l].value,
447 exp_results,
448 htonl(ipaddr),
449 flag_CANONNAME && hosts[i].canonname,
450 htons(services[j].port));
454 static struct
456 const char *nodename;
457 const char *nodenum;
458 unsigned long ipaddr;
459 int havename;
460 } ipaddrs[] = {
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 } */};
470 static struct
472 const char *servname;
473 const char *servnum;
474 unsigned short port;
475 int socktype;
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" */
478 } ports[] = {
479 { "0", "0", 0, 0 },
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 */
540 exp_results = 0;
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);
546 socktypemismatch =
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 */
562 if (!exp_results)
563 exp_results |= (1 << 0);
565 /* perform the test */
566 test_getnameinfo(
567 htonl(ipaddrs[i].ipaddr),
568 htons(ports[j].port),
569 nodename,
570 buflens[k],
571 servname,
572 buflens[l],
573 flags,
574 exp_results);
578 static int can_use_network(void)
580 int status;
582 /* try to ping minix3.org */
583 status = system("ping www.minix3.org > /dev/null 2>&1");
584 if (status == 127)
586 printf("cannot execute ping\n");
587 err();
590 return status == 0;
593 int main(void)
595 int use_network;
597 start(48);
599 use_network = can_use_network();
600 if (!use_network)
601 printf("Warning: no network\n");
602 test_getaddrinfo_all(use_network);
603 test_getnameinfo_all();
605 quit();
606 return 0;