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 50enum 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 59static int use_ipnode_functions = 0; 60static int use_ipv6_mapping = 0; 61static int ipnode_flags = 0; 62static int debug = 0; 63static int af_type = AF_INET; 64static enum test_methods method = TEST_BUILD_SNAPSHOT; 65 66DECLARE_TEST_DATA(hostent) 67DECLARE_TEST_FILE_SNAPSHOT(hostent) 68DECLARE_1PASS_TEST(hostent) 69DECLARE_2PASS_TEST(hostent) 70 71/* These stubs will use gethostby***() or getipnodeby***() functions, 72 * depending on the use_ipnode_functions global variable value */ 73static struct hostent *__gethostbyname2(const char *, int); 74static struct hostent *__gethostbyaddr(const void *, socklen_t, int); 75static void __freehostent(struct hostent *); 76 77static void clone_hostent(struct hostent *, struct hostent const *); 78static int compare_hostent(struct hostent *, struct hostent *, void *); 79static void dump_hostent(struct hostent *); 80static void free_hostent(struct hostent *); 81 82static int is_hostent_equal(struct hostent *, struct addrinfo *); 83 84static void sdump_hostent(struct hostent *, char *, size_t); 85static int hostent_read_hostlist_func(struct hostent *, char *); 86static int hostent_read_snapshot_addr(char *, unsigned char *, size_t); 87static int hostent_read_snapshot_func(struct hostent *, char *); 88 89static int hostent_test_correctness(struct hostent *, void *); 90static int hostent_test_gethostbyaddr(struct hostent *, void *); 91static int hostent_test_getaddrinfo_eq(struct hostent *, void *); 92static int hostent_test_getnameinfo_eq(struct hostent *, void *); 93 94static void usage(void) __attribute__((__noreturn__)); 95 96IMPLEMENT_TEST_DATA(hostent) 97IMPLEMENT_TEST_FILE_SNAPSHOT(hostent) 98IMPLEMENT_1PASS_TEST(hostent) 99IMPLEMENT_2PASS_TEST(hostent) 100 101static 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 119static 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 137static 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 145static void 146clone_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 205static void 206free_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 227static int 228compare_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 335errfin: 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 345static int 346check_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 358static int 359check_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 389static int 390is_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 423static void 424sdump_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 510static int 511hostent_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 542static int 543hostent_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 565static int 566hostent_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 660fin: 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 682static void 683dump_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 693static int 694hostent_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); 724errfin: 725 if (debug) 726 printf("incorrect\n"); 727 728 return (-1); 729} 730 731static int 732hostent_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 771static int 772hostent_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 814static int 815hostent_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 912static void 913usage(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 921int 922main(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 1096fin: 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