Path: blob/main/lib/libc/tests/nss/getaddrinfo_test.c
39500 views
/*-1* Copyright (c) 2006 Michael Bushkov <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*25*/2627#include <sys/param.h>28#include <sys/socket.h>29#include <arpa/inet.h>30#include <netinet/in.h>31#include <errno.h>32#include <netdb.h>33#include <resolv.h>34#include <stdio.h>35#include <stdlib.h>36#include <string.h>37#include <stringlist.h>38#include <unistd.h>3940#include <atf-c.h>4142#include "freebsd_test_suite/macros.h"43#include "testutil.h"4445enum test_methods {46TEST_GETADDRINFO,47TEST_BUILD_SNAPSHOT48};4950static struct addrinfo hints;51static enum test_methods method = TEST_GETADDRINFO;5253DECLARE_TEST_DATA(addrinfo)54DECLARE_TEST_FILE_SNAPSHOT(addrinfo)55DECLARE_2PASS_TEST(addrinfo)5657static void clone_addrinfo(struct addrinfo *, struct addrinfo const *);58static int compare_addrinfo(struct addrinfo *, struct addrinfo *, void *);59static void dump_addrinfo(struct addrinfo *);6061static void sdump_addrinfo(struct addrinfo *, char *, size_t);6263IMPLEMENT_TEST_DATA(addrinfo)64IMPLEMENT_TEST_FILE_SNAPSHOT(addrinfo)65IMPLEMENT_2PASS_TEST(addrinfo)6667static void68clone_addrinfo(struct addrinfo *dest, struct addrinfo const *src)69{7071ATF_REQUIRE(dest != NULL);72ATF_REQUIRE(src != NULL);7374memcpy(dest, src, sizeof(struct addrinfo));75if (src->ai_canonname != NULL)76dest->ai_canonname = strdup(src->ai_canonname);7778if (src->ai_addr != NULL) {79dest->ai_addr = malloc(src->ai_addrlen);80ATF_REQUIRE(dest->ai_addr != NULL);81memcpy(dest->ai_addr, src->ai_addr, src->ai_addrlen);82}8384if (src->ai_next != NULL) {85dest->ai_next = malloc(sizeof(struct addrinfo));86ATF_REQUIRE(dest->ai_next != NULL);87clone_addrinfo(dest->ai_next, src->ai_next);88}89}9091static int92compare_addrinfo_(struct addrinfo *ai1, struct addrinfo *ai2)93{9495if ((ai1 == NULL) || (ai2 == NULL))96return (-1);9798if (ai1->ai_flags != ai2->ai_flags ||99ai1->ai_family != ai2->ai_family ||100ai1->ai_socktype != ai2->ai_socktype ||101ai1->ai_protocol != ai2->ai_protocol ||102ai1->ai_addrlen != ai2->ai_addrlen ||103((ai1->ai_addr == NULL || ai2->ai_addr == NULL) &&104ai1->ai_addr != ai2->ai_addr) ||105((ai1->ai_canonname == NULL || ai2->ai_canonname == NULL) &&106ai1->ai_canonname != ai2->ai_canonname))107return (-1);108109if (ai1->ai_canonname != NULL &&110strcmp(ai1->ai_canonname, ai2->ai_canonname) != 0)111return (-1);112113if (ai1->ai_addr != NULL &&114memcmp(ai1->ai_addr, ai2->ai_addr, ai1->ai_addrlen) != 0)115return (-1);116117if (ai1->ai_next == NULL && ai2->ai_next == NULL)118return (0);119else120return (compare_addrinfo_(ai1->ai_next, ai2->ai_next));121}122123static int124compare_addrinfo(struct addrinfo *ai1, struct addrinfo *ai2,125void *mdata __unused)126{127int rv;128129printf("testing equality of 2 addrinfo structures\n");130131rv = compare_addrinfo_(ai1, ai2);132133if (rv == 0)134printf("equal\n");135else {136dump_addrinfo(ai1);137dump_addrinfo(ai2);138printf("not equal\n");139}140141return (rv);142}143144static void145free_addrinfo(struct addrinfo *ai)146{147if (ai == NULL)148return;149150free(ai->ai_addr);151free(ai->ai_canonname);152free_addrinfo(ai->ai_next);153}154155void156sdump_addrinfo(struct addrinfo *ai, char *buffer, size_t buflen)157{158int written, i;159160written = snprintf(buffer, buflen, "%d %d %d %d %d ",161ai->ai_flags, ai->ai_family, ai->ai_socktype, ai->ai_protocol,162ai->ai_addrlen);163buffer += written;164if (written > (int)buflen)165return;166buflen -= written;167168written = snprintf(buffer, buflen, "%s ",169ai->ai_canonname == NULL ? "(null)" : ai->ai_canonname);170buffer += written;171if (written > (int)buflen)172return;173buflen -= written;174175if (ai->ai_addr == NULL) {176written = snprintf(buffer, buflen, "(null)");177buffer += written;178if (written > (int)buflen)179return;180buflen -= written;181} else {182for (i = 0; i < (int)ai->ai_addrlen; i++) {183written = snprintf(buffer, buflen,184i + 1 != (int)ai->ai_addrlen ? "%d." : "%d",185((unsigned char *)ai->ai_addr)[i]);186buffer += written;187if (written > (int)buflen)188return;189buflen -= written;190191if (buflen == 0)192return;193}194}195196if (ai->ai_next != NULL) {197written = snprintf(buffer, buflen, ":");198buffer += written;199if (written > (int)buflen)200return;201buflen -= written;202203sdump_addrinfo(ai->ai_next, buffer, buflen);204}205}206207void208dump_addrinfo(struct addrinfo *result)209{210if (result != NULL) {211char buffer[2048];212sdump_addrinfo(result, buffer, sizeof(buffer));213printf("%s\n", buffer);214} else215printf("(null)\n");216}217218static int219addrinfo_read_snapshot_addr(char *addr, unsigned char *result, size_t len)220{221char *s, *ps, *ts;222223ps = addr;224while ((s = strsep(&ps, ".")) != NULL) {225if (len == 0)226return (-1);227228*result = (unsigned char)strtol(s, &ts, 10);229++result;230if (*ts != '\0')231return (-1);232233--len;234}235if (len != 0)236return (-1);237else238return (0);239}240241static int242addrinfo_read_snapshot_ai(struct addrinfo *ai, char *line)243{244char *s, *ps, *ts;245int i, rv, *pi;246247rv = 0;248i = 0;249ps = line;250memset(ai, 0, sizeof(struct addrinfo));251while ((s = strsep(&ps, " ")) != NULL) {252switch (i) {253case 0:254case 1:255case 2:256case 3:257pi = &ai->ai_flags + i;258*pi = (int)strtol(s, &ts, 10);259if (*ts != '\0')260goto fin;261break;262case 4:263ai->ai_addrlen = (socklen_t)strtol(s, &ts, 10);264if (*ts != '\0')265goto fin;266break;267case 5:268if (strcmp(s, "(null)") != 0) {269ai->ai_canonname = strdup(s);270ATF_REQUIRE(ai->ai_canonname != NULL);271}272break;273case 6:274if (strcmp(s, "(null)") != 0) {275ai->ai_addr = calloc(1, ai->ai_addrlen);276ATF_REQUIRE(ai->ai_addr != NULL);277rv = addrinfo_read_snapshot_addr(s,278(unsigned char *)ai->ai_addr,279ai->ai_addrlen);280281if (rv != 0)282goto fin;283}284break;285default:286/* NOTE: should not be reachable */287rv = -1;288goto fin;289}290291++i;292}293294fin:295if (i != 7 || rv != 0) {296free_addrinfo(ai);297ai = NULL;298return (-1);299}300301return (0);302}303304static int305addrinfo_read_snapshot_func(struct addrinfo *ai, char *line)306{307struct addrinfo *ai2;308char *s, *ps;309int rv;310311printf("1 line read from snapshot:\n%s\n", line);312313rv = 0;314ps = line;315316s = strsep(&ps, ":");317if (s == NULL)318return (-1);319320rv = addrinfo_read_snapshot_ai(ai, s);321if (rv != 0)322return (-1);323324ai2 = ai;325while ((s = strsep(&ps, ":")) != NULL) {326ai2->ai_next = calloc(1, sizeof(struct addrinfo));327ATF_REQUIRE(ai2->ai_next != NULL);328329rv = addrinfo_read_snapshot_ai(ai2->ai_next, s);330if (rv != 0) {331free_addrinfo(ai);332ai = NULL;333return (-1);334}335336ai2 = ai2->ai_next;337}338339return (0);340}341342static int343addrinfo_test_correctness(struct addrinfo *ai, void *mdata __unused)344{345346printf("testing correctness with the following data:\n");347dump_addrinfo(ai);348349if (ai == NULL)350goto errfin;351352if (!(ai->ai_family >= 0 && ai->ai_family < AF_MAX))353goto errfin;354355if (ai->ai_socktype != 0 && ai->ai_socktype != SOCK_STREAM &&356ai->ai_socktype != SOCK_DGRAM && ai->ai_socktype != SOCK_RAW)357goto errfin;358359if (ai->ai_protocol != 0 && ai->ai_protocol != IPPROTO_UDP &&360ai->ai_protocol != IPPROTO_TCP)361goto errfin;362363if ((ai->ai_flags & ~(AI_CANONNAME | AI_NUMERICHOST | AI_PASSIVE)) != 0)364goto errfin;365366if (ai->ai_addrlen != ai->ai_addr->sa_len ||367ai->ai_family != ai->ai_addr->sa_family)368goto errfin;369370printf("correct\n");371372return (0);373errfin:374printf("incorrect\n");375376return (-1);377}378379static int380addrinfo_read_hostlist_func(struct addrinfo *ai, char *line)381{382struct addrinfo *result;383int rv;384385printf("resolving %s: ", line);386rv = getaddrinfo(line, NULL, &hints, &result);387if (rv == 0) {388printf("found\n");389390rv = addrinfo_test_correctness(result, NULL);391if (rv != 0) {392freeaddrinfo(result);393result = NULL;394return (rv);395}396397clone_addrinfo(ai, result);398freeaddrinfo(result);399result = NULL;400} else {401printf("not found\n");402403memset(ai, 0, sizeof(struct addrinfo));404}405return (0);406}407408static void409run_tests(char *hostlist_file, const char *snapshot_file, int ai_family)410{411struct addrinfo_test_data td, td_snap;412char *snapshot_file_copy;413int rv;414415if (snapshot_file == NULL)416snapshot_file_copy = NULL;417else {418snapshot_file_copy = strdup(snapshot_file);419ATF_REQUIRE(snapshot_file_copy != NULL);420}421422memset(&hints, 0, sizeof(struct addrinfo));423hints.ai_family = ai_family;424hints.ai_flags = AI_CANONNAME;425426if (snapshot_file != NULL)427method = TEST_BUILD_SNAPSHOT;428429TEST_DATA_INIT(addrinfo, &td, clone_addrinfo, free_addrinfo);430TEST_DATA_INIT(addrinfo, &td_snap, clone_addrinfo, free_addrinfo);431432ATF_REQUIRE_MSG(access(hostlist_file, R_OK) == 0,433"can't access the hostlist file %s\n", hostlist_file);434435printf("building host lists from %s\n", hostlist_file);436437rv = TEST_SNAPSHOT_FILE_READ(addrinfo, hostlist_file, &td,438addrinfo_read_hostlist_func);439if (rv != 0)440goto fin;441442if (snapshot_file != NULL) {443if (access(snapshot_file, W_OK | R_OK) != 0) {444if (errno == ENOENT)445method = TEST_BUILD_SNAPSHOT;446else {447printf("can't access the snapshot "448"file %s\n", snapshot_file);449450rv = -1;451goto fin;452}453} else {454rv = TEST_SNAPSHOT_FILE_READ(addrinfo, snapshot_file,455&td_snap, addrinfo_read_snapshot_func);456if (rv != 0) {457printf("error reading snapshot file: %s\n",458strerror(errno));459goto fin;460}461}462}463464switch (method) {465case TEST_GETADDRINFO:466if (snapshot_file != NULL)467ATF_CHECK(DO_2PASS_TEST(addrinfo, &td, &td_snap,468compare_addrinfo, NULL) == 0);469break;470case TEST_BUILD_SNAPSHOT:471if (snapshot_file != NULL) {472ATF_CHECK(TEST_SNAPSHOT_FILE_WRITE(addrinfo,473snapshot_file, &td, sdump_addrinfo) == 0);474}475break;476default:477break;478}479480fin:481TEST_DATA_DESTROY(addrinfo, &td_snap);482TEST_DATA_DESTROY(addrinfo, &td);483484free(snapshot_file_copy);485}486487#define HOSTLIST_FILE "mach"488#define RUN_TESTS(tc, snapshot_file, ai_family) do { \489char *_hostlist_file; \490ATF_REQUIRE(0 < asprintf(&_hostlist_file, "%s/%s", \491atf_tc_get_config_var(tc, "srcdir"), HOSTLIST_FILE)); \492run_tests(_hostlist_file, snapshot_file, ai_family); \493free(_hostlist_file); \494} while (0)495496ATF_TC_WITHOUT_HEAD(pf_unspec);497ATF_TC_BODY(pf_unspec, tc)498{499500RUN_TESTS(tc, NULL, AF_UNSPEC);501}502503ATF_TC_WITHOUT_HEAD(pf_unspec_with_snapshot);504ATF_TC_BODY(pf_unspec_with_snapshot, tc)505{506507RUN_TESTS(tc, "snapshot_ai", AF_UNSPEC);508}509510ATF_TC_WITHOUT_HEAD(pf_inet);511ATF_TC_BODY(pf_inet, tc)512{513514ATF_REQUIRE_FEATURE("inet");515RUN_TESTS(tc, NULL, AF_INET);516}517518ATF_TC_WITHOUT_HEAD(pf_inet_with_snapshot);519ATF_TC_BODY(pf_inet_with_snapshot, tc)520{521522ATF_REQUIRE_FEATURE("inet");523RUN_TESTS(tc, "snapshot_ai4", AF_INET);524}525526ATF_TC_WITHOUT_HEAD(pf_inet6);527ATF_TC_BODY(pf_inet6, tc)528{529530ATF_REQUIRE_FEATURE("inet6");531RUN_TESTS(tc, NULL, AF_INET6);532}533534ATF_TC_WITHOUT_HEAD(pf_inet6_with_snapshot);535ATF_TC_BODY(pf_inet6_with_snapshot, tc)536{537538ATF_REQUIRE_FEATURE("inet6");539RUN_TESTS(tc, "snapshot_ai6", AF_INET6);540}541542ATF_TP_ADD_TCS(tp)543{544545ATF_TP_ADD_TC(tp, pf_unspec);546ATF_TP_ADD_TC(tp, pf_unspec_with_snapshot);547ATF_TP_ADD_TC(tp, pf_inet);548ATF_TP_ADD_TC(tp, pf_inet_with_snapshot);549ATF_TP_ADD_TC(tp, pf_inet6);550ATF_TP_ADD_TC(tp, pf_inet6_with_snapshot);551552return (atf_no_error());553}554555556