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