1 /*-
2 * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: stable/10/tools/regression/lib/libc/nss/test-gethostby.c 291759 2015-12-04 09:18:12Z ngie $");
30
31 #include <arpa/inet.h>
32 #include <sys/socket.h>
33 #include <sys/types.h>
34 #include <netinet/in.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <netdb.h>
38 #include <resolv.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <stringlist.h>
43 #include <unistd.h>
44 #include "testutil.h"
45
46 #ifndef min
47 #define min(a,b) (((a)<(b))?(a):(b))
48 #endif
49
50 enum test_methods {
51 TEST_GETHOSTBYNAME2,
52 TEST_GETHOSTBYADDR,
53 TEST_GETHOSTBYNAME2_GETADDRINFO,
54 TEST_GETHOSTBYADDR_GETNAMEINFO,
55 TEST_BUILD_SNAPSHOT,
56 TEST_BUILD_ADDR_SNAPSHOT
57 };
58
59 static int use_ipnode_functions = 0;
60 static int use_ipv6_mapping = 0;
61 static int ipnode_flags = 0;
62 static int debug = 0;
63 static int af_type = AF_INET;
64 static enum test_methods method = TEST_BUILD_SNAPSHOT;
65
66 DECLARE_TEST_DATA(hostent)
67 DECLARE_TEST_FILE_SNAPSHOT(hostent)
68 DECLARE_1PASS_TEST(hostent)
69 DECLARE_2PASS_TEST(hostent)
70
71 /* These stubs will use gethostby***() or getipnodeby***() functions,
72 * depending on the use_ipnode_functions global variable value */
73 static struct hostent *__gethostbyname2(const char *, int);
74 static struct hostent *__gethostbyaddr(const void *, socklen_t, int);
75 static void __freehostent(struct hostent *);
76
77 static void clone_hostent(struct hostent *, struct hostent const *);
78 static int compare_hostent(struct hostent *, struct hostent *, void *);
79 static void dump_hostent(struct hostent *);
80 static void free_hostent(struct hostent *);
81
82 static int is_hostent_equal(struct hostent *, struct addrinfo *);
83
84 static void sdump_hostent(struct hostent *, char *, size_t);
85 static int hostent_read_hostlist_func(struct hostent *, char *);
86 static int hostent_read_snapshot_addr(char *, unsigned char *, size_t);
87 static int hostent_read_snapshot_func(struct hostent *, char *);
88
89 static int hostent_test_correctness(struct hostent *, void *);
90 static int hostent_test_gethostbyaddr(struct hostent *, void *);
91 static int hostent_test_getaddrinfo_eq(struct hostent *, void *);
92 static int hostent_test_getnameinfo_eq(struct hostent *, void *);
93
94 static void usage(void) __attribute__((__noreturn__));
95
96 IMPLEMENT_TEST_DATA(hostent)
IMPLEMENT_TEST_FILE_SNAPSHOT(hostent)97 IMPLEMENT_TEST_FILE_SNAPSHOT(hostent)
98 IMPLEMENT_1PASS_TEST(hostent)
99 IMPLEMENT_2PASS_TEST(hostent)
100
101 static struct hostent *
102 __gethostbyname2(const char *name, int af)
103 {
104 struct hostent *he;
105 int error;
106
107 if (use_ipnode_functions == 0)
108 he = gethostbyname2(name, af);
109 else {
110 error = 0;
111 he = getipnodebyname(name, af, ipnode_flags, &error);
112 if (he == NULL);
113 errno = error;
114 }
115
116 return (he);
117 }
118
119 static struct hostent *
__gethostbyaddr(const void * addr,socklen_t len,int af)120 __gethostbyaddr(const void *addr, socklen_t len, int af)
121 {
122 struct hostent *he;
123 int error;
124
125 if (use_ipnode_functions == 0)
126 he = gethostbyaddr(addr, len, af);
127 else {
128 error = 0;
129 he = getipnodebyaddr(addr, len, af, &error);
130 if (he == NULL)
131 errno = error;
132 }
133
134 return (he);
135 }
136
137 static void
__freehostent(struct hostent * he)138 __freehostent(struct hostent *he)
139 {
140 /* NOTE: checking for he != NULL - just in case */
141 if ((use_ipnode_functions != 0) && (he != NULL))
142 freehostent(he);
143 }
144
145 static void
clone_hostent(struct hostent * dest,struct hostent const * src)146 clone_hostent(struct hostent *dest, struct hostent const *src)
147 {
148 assert(dest != NULL);
149 assert(src != NULL);
150
151 char **cp;
152 int aliases_num;
153 int addrs_num;
154 size_t offset;
155
156 memset(dest, 0, sizeof(struct hostent));
157
158 if (src->h_name != NULL) {
159 dest->h_name = strdup(src->h_name);
160 assert(dest->h_name != NULL);
161 }
162
163 dest->h_addrtype = src->h_addrtype;
164 dest->h_length = src->h_length;
165
166 if (src->h_aliases != NULL) {
167 aliases_num = 0;
168 for (cp = src->h_aliases; *cp; ++cp)
169 ++aliases_num;
170
171 dest->h_aliases = (char **)malloc((aliases_num + 1) *
172 (sizeof(char *)));
173 assert(dest->h_aliases != NULL);
174 memset(dest->h_aliases, 0, (aliases_num + 1) *
175 (sizeof(char *)));
176
177 for (cp = src->h_aliases; *cp; ++cp) {
178 dest->h_aliases[cp - src->h_aliases] = strdup(*cp);
179 assert(dest->h_aliases[cp - src->h_aliases] != NULL);
180 }
181 }
182
183 if (src->h_addr_list != NULL) {
184 addrs_num = 0;
185 for (cp = src->h_addr_list; *cp; ++cp)
186 ++addrs_num;
187
188 dest->h_addr_list = (char **)malloc((addrs_num + 1) *
189 (sizeof(char *)));
190 assert(dest->h_addr_list != NULL);
191 memset(dest->h_addr_list, 0, (addrs_num + 1) *
192 (sizeof(char *)));
193
194 for (cp = src->h_addr_list; *cp; ++cp) {
195 offset = cp - src->h_addr_list;
196 dest->h_addr_list[offset] =
197 (char *)malloc(src->h_length);
198 assert(dest->h_addr_list[offset] != NULL);
199 memcpy(dest->h_addr_list[offset],
200 src->h_addr_list[offset], src->h_length);
201 }
202 }
203 }
204
205 static void
free_hostent(struct hostent * ht)206 free_hostent(struct hostent *ht)
207 {
208 char **cp;
209
210 assert(ht != NULL);
211
212 free(ht->h_name);
213
214 if (ht->h_aliases != NULL) {
215 for (cp = ht->h_aliases; *cp; ++cp)
216 free(*cp);
217 free(ht->h_aliases);
218 }
219
220 if (ht->h_addr_list != NULL) {
221 for (cp = ht->h_addr_list; *cp; ++cp)
222 free(*cp);
223 free(ht->h_addr_list);
224 }
225 }
226
227 static int
compare_hostent(struct hostent * ht1,struct hostent * ht2,void * mdata)228 compare_hostent(struct hostent *ht1, struct hostent *ht2, void *mdata)
229 {
230 char **c1, **c2, **ct, **cb;
231 int b;
232
233 if (ht1 == ht2)
234 return 0;
235
236 if ((ht1 == NULL) || (ht2 == NULL))
237 goto errfin;
238
239 if ((ht1->h_name == NULL) || (ht2->h_name == NULL))
240 goto errfin;
241
242 if ((ht1->h_addrtype != ht2->h_addrtype) ||
243 (ht1->h_length != ht2->h_length) ||
244 (strcmp(ht1->h_name, ht2->h_name) != 0))
245 goto errfin;
246
247 c1 = ht1->h_aliases;
248 c2 = ht2->h_aliases;
249
250 if (((ht1->h_aliases == NULL) || (ht2->h_aliases == NULL)) &&
251 (ht1->h_aliases != ht2->h_aliases))
252 goto errfin;
253
254 if ((c1 != NULL) && (c2 != NULL)) {
255 cb = c1;
256 for (;*c1; ++c1) {
257 b = 0;
258 for (ct = c2; *ct; ++ct) {
259 if (strcmp(*c1, *ct) == 0) {
260 b = 1;
261 break;
262 }
263 }
264 if (b == 0) {
265 if (debug)
266 printf("h1 aliases item can't be "\
267 "found in h2 aliases\n");
268 goto errfin;
269 }
270 }
271
272 c1 = cb;
273 for (;*c2; ++c2) {
274 b = 0;
275 for (ct = c1; *ct; ++ct) {
276 if (strcmp(*c2, *ct) == 0) {
277 b = 1;
278 break;
279 }
280 }
281 if (b == 0) {
282 if (debug)
283 printf("h2 aliases item can't be "\
284 " found in h1 aliases\n");
285 goto errfin;
286 }
287 }
288 }
289
290 c1 = ht1->h_addr_list;
291 c2 = ht2->h_addr_list;
292
293 if (((ht1->h_addr_list == NULL) || (ht2->h_addr_list== NULL)) &&
294 (ht1->h_addr_list != ht2->h_addr_list))
295 goto errfin;
296
297 if ((c1 != NULL) && (c2 != NULL)) {
298 cb = c1;
299 for (;*c1; ++c1) {
300 b = 0;
301 for (ct = c2; *ct; ++ct) {
302 if (memcmp(*c1, *ct, ht1->h_length) == 0) {
303 b = 1;
304 break;
305 }
306 }
307 if (b == 0) {
308 if (debug)
309 printf("h1 addresses item can't be "\
310 "found in h2 addresses\n");
311 goto errfin;
312 }
313 }
314
315 c1 = cb;
316 for (;*c2; ++c2) {
317 b = 0;
318 for (ct = c1; *ct; ++ct) {
319 if (memcmp(*c2, *ct, ht1->h_length) == 0) {
320 b = 1;
321 break;
322 }
323 }
324 if (b == 0) {
325 if (debug)
326 printf("h2 addresses item can't be "\
327 "found in h1 addresses\n");
328 goto errfin;
329 }
330 }
331 }
332
333 return 0;
334
335 errfin:
336 if ((debug) && (mdata == NULL)) {
337 printf("following structures are not equal:\n");
338 dump_hostent(ht1);
339 dump_hostent(ht2);
340 }
341
342 return (-1);
343 }
344
345 static int
check_addrinfo_for_name(struct addrinfo * ai,char const * name)346 check_addrinfo_for_name(struct addrinfo *ai, char const *name)
347 {
348 struct addrinfo *ai2;
349
350 for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
351 if (strcmp(ai2->ai_canonname, name) == 0)
352 return (0);
353 }
354
355 return (-1);
356 }
357
358 static int
check_addrinfo_for_addr(struct addrinfo * ai,char const * addr,socklen_t addrlen,int af)359 check_addrinfo_for_addr(struct addrinfo *ai, char const *addr,
360 socklen_t addrlen, int af)
361 {
362 struct addrinfo *ai2;
363
364 for (ai2 = ai; ai2 != NULL; ai2 = ai2->ai_next) {
365 if (af != ai2->ai_family)
366 continue;
367
368 switch (af) {
369 case AF_INET:
370 if (memcmp(addr,
371 (void *)&((struct sockaddr_in *)ai2->ai_addr)->sin_addr,
372 min(addrlen, ai2->ai_addrlen)) == 0)
373 return (0);
374 break;
375 case AF_INET6:
376 if (memcmp(addr,
377 (void *)&((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr,
378 min(addrlen, ai2->ai_addrlen)) == 0)
379 return (0);
380 break;
381 default:
382 break;
383 }
384 }
385
386 return (-1);
387 }
388
389 static int
is_hostent_equal(struct hostent * he,struct addrinfo * ai)390 is_hostent_equal(struct hostent *he, struct addrinfo *ai)
391 {
392 char **cp;
393 int rv;
394
395 if (debug)
396 printf("checking equality of he and ai\n");
397
398 rv = check_addrinfo_for_name(ai, he->h_name);
399 if (rv != 0) {
400 if (debug)
401 printf("not equal - he->h_name couldn't be found\n");
402
403 return (rv);
404 }
405
406 for (cp = he->h_addr_list; *cp; ++cp) {
407 rv = check_addrinfo_for_addr(ai, *cp, he->h_length,
408 he->h_addrtype);
409 if (rv != 0) {
410 if (debug)
411 printf("not equal - one of he->h_addr_list couldn't be found\n");
412
413 return (rv);
414 }
415 }
416
417 if (debug)
418 printf("equal\n");
419
420 return (0);
421 }
422
423 static void
sdump_hostent(struct hostent * ht,char * buffer,size_t buflen)424 sdump_hostent(struct hostent *ht, char *buffer, size_t buflen)
425 {
426 char **cp;
427 size_t i;
428 int written;
429
430 written = snprintf(buffer, buflen, "%s %d %d",
431 ht->h_name, ht->h_addrtype, ht->h_length);
432 buffer += written;
433 if (written > buflen)
434 return;
435 buflen -= written;
436
437 if (ht->h_aliases != NULL) {
438 if (*(ht->h_aliases) != NULL) {
439 for (cp = ht->h_aliases; *cp; ++cp) {
440 written = snprintf(buffer, buflen, " %s",*cp);
441 buffer += written;
442 if (written > buflen)
443 return;
444 buflen -= written;
445
446 if (buflen == 0)
447 return;
448 }
449 } else {
450 written = snprintf(buffer, buflen, " noaliases");
451 buffer += written;
452 if (written > buflen)
453 return;
454 buflen -= written;
455 }
456 } else {
457 written = snprintf(buffer, buflen, " (null)");
458 buffer += written;
459 if (written > buflen)
460 return;
461 buflen -= written;
462 }
463
464 written = snprintf(buffer, buflen, " : ");
465 buffer += written;
466 if (written > buflen)
467 return;
468 buflen -= written;
469
470 if (ht->h_addr_list != NULL) {
471 if (*(ht->h_addr_list) != NULL) {
472 for (cp = ht->h_addr_list; *cp; ++cp) {
473 for (i = 0; i < ht->h_length; ++i ) {
474 written = snprintf(buffer, buflen,
475 i + 1 != ht->h_length ? "%d." : "%d",
476 (unsigned char)(*cp)[i]);
477 buffer += written;
478 if (written > buflen)
479 return;
480 buflen -= written;
481
482 if (buflen == 0)
483 return;
484 }
485
486 if (*(cp + 1) ) {
487 written = snprintf(buffer, buflen, " ");
488 buffer += written;
489 if (written > buflen)
490 return;
491 buflen -= written;
492 }
493 }
494 } else {
495 written = snprintf(buffer, buflen, " noaddrs");
496 buffer += written;
497 if (written > buflen)
498 return;
499 buflen -= written;
500 }
501 } else {
502 written = snprintf(buffer, buflen, " (null)");
503 buffer += written;
504 if (written > buflen)
505 return;
506 buflen -= written;
507 }
508 }
509
510 static int
hostent_read_hostlist_func(struct hostent * he,char * line)511 hostent_read_hostlist_func(struct hostent *he, char *line)
512 {
513 struct hostent *result;
514 int rv;
515
516 if (debug)
517 printf("resolving %s: ", line);
518 result = __gethostbyname2(line, af_type);
519 if (result != NULL) {
520 if (debug)
521 printf("found\n");
522
523 rv = hostent_test_correctness(result, NULL);
524 if (rv != 0) {
525 __freehostent(result);
526 return (rv);
527 }
528
529 clone_hostent(he, result);
530 __freehostent(result);
531 } else {
532 if (debug)
533 printf("not found\n");
534
535 memset(he, 0, sizeof(struct hostent));
536 he->h_name = strdup(line);
537 assert(he->h_name != NULL);
538 }
539 return (0);
540 }
541
542 static int
hostent_read_snapshot_addr(char * addr,unsigned char * result,size_t len)543 hostent_read_snapshot_addr(char *addr, unsigned char *result, size_t len)
544 {
545 char *s, *ps, *ts;
546
547 ps = addr;
548 while ( (s = strsep(&ps, ".")) != NULL) {
549 if (len == 0)
550 return (-1);
551
552 *result = (unsigned char)strtol(s, &ts, 10);
553 ++result;
554 if (*ts != '\0')
555 return (-1);
556
557 --len;
558 }
559 if (len != 0)
560 return (-1);
561 else
562 return (0);
563 }
564
565 static int
hostent_read_snapshot_func(struct hostent * ht,char * line)566 hostent_read_snapshot_func(struct hostent *ht, char *line)
567 {
568 StringList *sl1, *sl2;
569 char *s, *ps, *ts;
570 int i, rv;
571
572 if (debug)
573 printf("1 line read from snapshot:\n%s\n", line);
574
575 rv = 0;
576 i = 0;
577 sl1 = sl2 = NULL;
578 ps = line;
579 memset(ht, 0, sizeof(struct hostent));
580 while ( (s = strsep(&ps, " ")) != NULL) {
581 switch (i) {
582 case 0:
583 ht->h_name = strdup(s);
584 assert(ht->h_name != NULL);
585 break;
586
587 case 1:
588 ht->h_addrtype = (int)strtol(s, &ts, 10);
589 if (*ts != '\0')
590 goto fin;
591 break;
592
593 case 2:
594 ht->h_length = (int)strtol(s, &ts, 10);
595 if (*ts != '\0')
596 goto fin;
597 break;
598
599 case 3:
600 if (sl1 == NULL) {
601 if (strcmp(s, "(null)") == 0)
602 return (0);
603
604 sl1 = sl_init();
605 assert(sl1 != NULL);
606
607 if (strcmp(s, "noaliases") != 0) {
608 ts = strdup(s);
609 assert(ts != NULL);
610 sl_add(sl1, ts);
611 }
612 } else {
613 if (strcmp(s, ":") == 0)
614 ++i;
615 else {
616 ts = strdup(s);
617 assert(ts != NULL);
618 sl_add(sl1, ts);
619 }
620 }
621 break;
622
623 case 4:
624 if (sl2 == NULL) {
625 if (strcmp(s, "(null)") == 0)
626 return (0);
627
628 sl2 = sl_init();
629 assert(sl2 != NULL);
630
631 if (strcmp(s, "noaddrs") != 0) {
632 ts = (char *)malloc(ht->h_length);
633 assert(ts != NULL);
634 memset(ts, 0, ht->h_length);
635 rv = hostent_read_snapshot_addr(s,\
636 (unsigned char *)ts, ht->h_length);
637 sl_add(sl2, ts);
638 if (rv != 0)
639 goto fin;
640 }
641 } else {
642 ts = (char *)malloc(ht->h_length);
643 assert(ts != NULL);
644 memset(ts, 0, ht->h_length);
645 rv = hostent_read_snapshot_addr(s,\
646 (unsigned char *)ts, ht->h_length);
647 sl_add(sl2, ts);
648 if (rv != 0)
649 goto fin;
650 }
651 break;
652 default:
653 break;
654 };
655
656 if ((i != 3) && (i != 4))
657 ++i;
658 }
659
660 fin:
661 if (sl1 != NULL) {
662 sl_add(sl1, NULL);
663 ht->h_aliases = sl1->sl_str;
664 }
665 if (sl2 != NULL) {
666 sl_add(sl2, NULL);
667 ht->h_addr_list = sl2->sl_str;
668 }
669
670 if ((i != 4) || (rv != 0)) {
671 free_hostent(ht);
672 memset(ht, 0, sizeof(struct hostent));
673 return (-1);
674 }
675
676 /* NOTE: is it a dirty hack or not? */
677 free(sl1);
678 free(sl2);
679 return (0);
680 }
681
682 static void
dump_hostent(struct hostent * result)683 dump_hostent(struct hostent *result)
684 {
685 if (result != NULL) {
686 char buffer[1024];
687 sdump_hostent(result, buffer, sizeof(buffer));
688 printf("%s\n", buffer);
689 } else
690 printf("(null)\n");
691 }
692
693 static int
hostent_test_correctness(struct hostent * ht,void * mdata)694 hostent_test_correctness(struct hostent *ht, void *mdata)
695 {
696 if (debug) {
697 printf("testing correctness with the following data:\n");
698 dump_hostent(ht);
699 }
700
701 if (ht == NULL)
702 goto errfin;
703
704 if (ht->h_name == NULL)
705 goto errfin;
706
707 if (!((ht->h_addrtype >= 0) && (ht->h_addrtype < AF_MAX)))
708 goto errfin;
709
710 if ((ht->h_length != sizeof(struct in_addr)) &&
711 (ht->h_length != sizeof(struct in6_addr)))
712 goto errfin;
713
714 if (ht->h_aliases == NULL)
715 goto errfin;
716
717 if (ht->h_addr_list == NULL)
718 goto errfin;
719
720 if (debug)
721 printf("correct\n");
722
723 return (0);
724 errfin:
725 if (debug)
726 printf("incorrect\n");
727
728 return (-1);
729 }
730
731 static int
hostent_test_gethostbyaddr(struct hostent * he,void * mdata)732 hostent_test_gethostbyaddr(struct hostent *he, void *mdata)
733 {
734 struct hostent *result;
735 struct hostent_test_data *addr_test_data;
736 int rv;
737
738 addr_test_data = (struct hostent_test_data *)mdata;
739
740 /* We should omit unresolved hostents */
741 if (he->h_addr_list != NULL) {
742 char **cp;
743 for (cp = he->h_addr_list; *cp; ++cp) {
744 if (debug)
745 printf("doing reverse lookup for %s\n", he->h_name);
746
747 result = __gethostbyaddr(*cp, he->h_length,
748 he->h_addrtype);
749 if (result == NULL) {
750 if (debug)
751 printf("warning: reverse lookup failed\n");
752
753 continue;
754 }
755 rv = hostent_test_correctness(result, NULL);
756 if (rv != 0) {
757 __freehostent(result);
758 return (rv);
759 }
760
761 if (addr_test_data != NULL)
762 TEST_DATA_APPEND(hostent, addr_test_data, result);
763
764 __freehostent(result);
765 }
766 }
767
768 return (0);
769 }
770
771 static int
hostent_test_getaddrinfo_eq(struct hostent * he,void * mdata)772 hostent_test_getaddrinfo_eq(struct hostent *he, void *mdata)
773 {
774 struct addrinfo *ai, hints;
775 int rv;
776
777 ai = NULL;
778 memset(&hints, 0, sizeof(struct addrinfo));
779 hints.ai_family = af_type;
780 hints.ai_flags = AI_CANONNAME;
781
782 if (debug)
783 printf("using getaddrinfo() to resolve %s\n", he->h_name);
784
785 /* struct hostent *he was not resolved */
786 if (he->h_addr_list == NULL) {
787 /* We can be sure that he->h_name is not NULL */
788 rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
789 if (rv == 0) {
790 if (debug)
791 printf("not ok - shouldn't have been resolved\n");
792 return (-1);
793 }
794 } else {
795 rv = getaddrinfo(he->h_name, NULL, &hints, &ai);
796 if (rv != 0) {
797 if (debug)
798 printf("not ok - should have beed resolved\n");
799 return (-1);
800 }
801
802 rv = is_hostent_equal(he, ai);
803 if (rv != 0) {
804 if (debug)
805 printf("not ok - addrinfo and hostent are not equal\n");
806 return (-1);
807 }
808
809 }
810
811 return (0);
812 }
813
814 static int
hostent_test_getnameinfo_eq(struct hostent * he,void * mdata)815 hostent_test_getnameinfo_eq(struct hostent *he, void *mdata)
816 {
817 char buffer[NI_MAXHOST];
818 struct sockaddr_in sin;
819 struct sockaddr_in6 sin6;
820 struct sockaddr *saddr;
821 struct hostent *result;
822 int rv;
823
824 if (he->h_addr_list != NULL) {
825 char **cp;
826 for (cp = he->h_addr_list; *cp; ++cp) {
827 if (debug)
828 printf("doing reverse lookup for %s\n", he->h_name);
829
830 result = __gethostbyaddr(*cp, he->h_length,
831 he->h_addrtype);
832 if (result != NULL) {
833 rv = hostent_test_correctness(result, NULL);
834 if (rv != 0) {
835 __freehostent(result);
836 return (rv);
837 }
838 } else {
839 if (debug)
840 printf("reverse lookup failed\n");
841 }
842
843 switch (he->h_addrtype) {
844 case AF_INET:
845 memset(&sin, 0, sizeof(struct sockaddr_in));
846 sin.sin_len = sizeof(struct sockaddr_in);
847 sin.sin_family = AF_INET;
848 memcpy(&sin.sin_addr, *cp, he->h_length);
849
850 saddr = (struct sockaddr *)&sin;
851 break;
852 case AF_INET6:
853 memset(&sin6, 0, sizeof(struct sockaddr_in6));
854 sin6.sin6_len = sizeof(struct sockaddr_in6);
855 sin6.sin6_family = AF_INET6;
856 memcpy(&sin6.sin6_addr, *cp, he->h_length);
857
858 saddr = (struct sockaddr *)&sin6;
859 break;
860 default:
861 if (debug)
862 printf("warning: %d family is unsupported\n",
863 he->h_addrtype);
864 continue;
865 }
866
867 assert(saddr != NULL);
868 rv = getnameinfo(saddr, saddr->sa_len, buffer,
869 sizeof(buffer), NULL, 0, NI_NAMEREQD);
870
871 if ((rv != 0) && (result != NULL)) {
872 if (debug)
873 printf("not ok - getnameinfo() didn't make the reverse lookup, when it should have (%s)\n",
874 gai_strerror(rv));
875 return (rv);
876 }
877
878 if ((rv == 0) && (result == NULL)) {
879 if (debug)
880 printf("not ok - getnameinfo() made the reverse lookup, when it shouldn't have\n");
881 return (rv);
882 }
883
884 if ((rv != 0) && (result == NULL)) {
885 if (debug)
886 printf("ok - both getnameinfo() and ***byaddr() failed\n");
887
888 continue;
889 }
890
891 if (debug)
892 printf("comparing %s with %s\n", result->h_name,
893 buffer);
894
895 rv = strcmp(result->h_name, buffer);
896 __freehostent(result);
897
898 if (rv != 0) {
899 if (debug)
900 printf("not ok - getnameinfo() and ***byaddr() results are not equal\n");
901 return (rv);
902 } else {
903 if (debug)
904 printf("ok - getnameinfo() and ***byaddr() results are equal\n");
905 }
906 }
907 }
908
909 return (0);
910 }
911
912 static void
usage(void)913 usage(void)
914 {
915 (void)fprintf(stderr,
916 "Usage: %s -na2i [-o] [-d] [-46] [-mAcM] [-C] [-s <file>] -f <file>\n",
917 getprogname());
918 exit(1);
919 }
920
921 int
main(int argc,char ** argv)922 main(int argc, char **argv)
923 {
924 struct hostent_test_data td, td_addr, td_snap;
925 char *snapshot_file, *hostlist_file;
926 res_state statp;
927 int rv;
928 int c;
929
930 if (argc < 2)
931 usage();
932
933 snapshot_file = NULL;
934 hostlist_file = NULL;
935 while ((c = getopt(argc, argv, "nad2iod46mAcMs:f:")) != -1)
936 switch (c) {
937 case '4':
938 af_type = AF_INET;
939 break;
940 case '6':
941 af_type = AF_INET6;
942 break;
943 case 'M':
944 af_type = AF_INET6;
945 use_ipv6_mapping = 1;
946 ipnode_flags |= AI_V4MAPPED_CFG;
947 break;
948 case 'm':
949 af_type = AF_INET6;
950 use_ipv6_mapping = 1;
951 ipnode_flags |= AI_V4MAPPED;
952 break;
953 case 'c':
954 ipnode_flags |= AI_ADDRCONFIG;
955 break;
956 case 'A':
957 ipnode_flags |= AI_ALL;
958 break;
959 case 'o':
960 use_ipnode_functions = 1;
961 break;
962 case 'd':
963 debug = 1;
964 break;
965 case 'n':
966 method = TEST_GETHOSTBYNAME2;
967 break;
968 case 'a':
969 method = TEST_GETHOSTBYADDR;
970 break;
971 case '2':
972 method = TEST_GETHOSTBYNAME2_GETADDRINFO;
973 break;
974 case 'i':
975 method = TEST_GETHOSTBYADDR_GETNAMEINFO;
976 break;
977 case 's':
978 snapshot_file = strdup(optarg);
979 break;
980 case 'f':
981 hostlist_file = strdup(optarg);
982 break;
983 default:
984 usage();
985 }
986
987 if (use_ipnode_functions == 0) {
988 statp = __res_state();
989 if ((statp == NULL) || ((statp->options & RES_INIT) == 0 &&
990 res_ninit(statp) == -1)) {
991 if (debug)
992 printf("error: can't init res_state\n");
993
994 free(snapshot_file);
995 free(hostlist_file);
996 return (-1);
997 }
998
999 if (use_ipv6_mapping == 0)
1000 statp->options &= ~RES_USE_INET6;
1001 else
1002 statp->options |= RES_USE_INET6;
1003 }
1004
1005 TEST_DATA_INIT(hostent, &td, clone_hostent, free_hostent);
1006 TEST_DATA_INIT(hostent, &td_addr, clone_hostent, free_hostent);
1007 TEST_DATA_INIT(hostent, &td_snap, clone_hostent, free_hostent);
1008
1009 if (hostlist_file == NULL)
1010 usage();
1011
1012 if (access(hostlist_file, R_OK) != 0) {
1013 if (debug)
1014 printf("can't access the hostlist file %s\n",
1015 hostlist_file);
1016
1017 usage();
1018 }
1019
1020 if (debug)
1021 printf("building host lists from %s\n", hostlist_file);
1022
1023 rv = TEST_SNAPSHOT_FILE_READ(hostent, hostlist_file, &td,
1024 hostent_read_hostlist_func);
1025 if (rv != 0)
1026 goto fin;
1027
1028 if (snapshot_file != NULL) {
1029 if (access(snapshot_file, W_OK | R_OK) != 0) {
1030 if (errno == ENOENT) {
1031 if (method != TEST_GETHOSTBYADDR)
1032 method = TEST_BUILD_SNAPSHOT;
1033 else
1034 method = TEST_BUILD_ADDR_SNAPSHOT;
1035 } else {
1036 if (debug)
1037 printf("can't access the snapshot file %s\n",
1038 snapshot_file);
1039
1040 rv = -1;
1041 goto fin;
1042 }
1043 } else {
1044 rv = TEST_SNAPSHOT_FILE_READ(hostent, snapshot_file,
1045 &td_snap, hostent_read_snapshot_func);
1046 if (rv != 0) {
1047 if (debug)
1048 printf("error reading snapshot file\n");
1049 goto fin;
1050 }
1051 }
1052 }
1053
1054 switch (method) {
1055 case TEST_GETHOSTBYNAME2:
1056 if (snapshot_file != NULL)
1057 rv = DO_2PASS_TEST(hostent, &td, &td_snap,
1058 compare_hostent, NULL);
1059 break;
1060 case TEST_GETHOSTBYADDR:
1061 rv = DO_1PASS_TEST(hostent, &td,
1062 hostent_test_gethostbyaddr, (void *)&td_addr);
1063
1064 if (snapshot_file != NULL)
1065 rv = DO_2PASS_TEST(hostent, &td_addr, &td_snap,
1066 compare_hostent, NULL);
1067 break;
1068 case TEST_GETHOSTBYNAME2_GETADDRINFO:
1069 rv = DO_1PASS_TEST(hostent, &td,
1070 hostent_test_getaddrinfo_eq, NULL);
1071 break;
1072 case TEST_GETHOSTBYADDR_GETNAMEINFO:
1073 rv = DO_1PASS_TEST(hostent, &td,
1074 hostent_test_getnameinfo_eq, NULL);
1075 break;
1076 case TEST_BUILD_SNAPSHOT:
1077 if (snapshot_file != NULL) {
1078 rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file, &td,
1079 sdump_hostent);
1080 }
1081 break;
1082 case TEST_BUILD_ADDR_SNAPSHOT:
1083 if (snapshot_file != NULL) {
1084 rv = DO_1PASS_TEST(hostent, &td,
1085 hostent_test_gethostbyaddr, (void *)&td_addr);
1086
1087 rv = TEST_SNAPSHOT_FILE_WRITE(hostent, snapshot_file,
1088 &td_addr, sdump_hostent);
1089 }
1090 break;
1091 default:
1092 rv = 0;
1093 break;
1094 };
1095
1096 fin:
1097 TEST_DATA_DESTROY(hostent, &td_snap);
1098 TEST_DATA_DESTROY(hostent, &td_addr);
1099 TEST_DATA_DESTROY(hostent, &td);
1100 free(hostlist_file);
1101 free(snapshot_file);
1102
1103 return (rv);
1104 }
1105
1106