]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/regression/lib/libc/nss/test-gethostby.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / regression / lib / libc / nss / test-gethostby.c
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$");
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)
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 *
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
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
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 
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 
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
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
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 
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
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
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
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
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 
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
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
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
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 
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
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
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