From nobody Fri Mar 28 21:37:49 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ZPYly1F2hz5rT1s; Fri, 28 Mar 2025 21:37:50 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZPYlx55gQz44Q6; Fri, 28 Mar 2025 21:37:49 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1743197869; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=uj7CvXQ4qtnsUBY9PoZ8Kq9gNJXauXx0kbvPLJSyGeY=; b=vTQbed5fwGlCKC+I40kQLlNOOv8UuMAN1ElrL4oODE8jSUwW5DJGCnPEaWxdYL7L9VY1w6 Y+3CrYJIONXRz8ToC8Z6xqi4uRxHthnDw/SfH1Irn771EwK4nb7o1xrFgkbnF1/+qNvO4j 52u2R7Yp2MNhbZPqs+3o3zIjJaL6XhR/RUMnuY+xyznhOXAjQC561Z4+hDUucdC5jvTftB 4bKV+OThFSA9t8mjKMOO7z9L+TJEa2zpzfw6dZwe9Dq/rFY74GcnrTKMXvWVtOac2+Cohx wyLbGqO5Wa9okmzCV0abSLlT+zy3WQa3QJym0vCmihGurSdwtBsvnPP1xko/Og== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1743197869; a=rsa-sha256; cv=none; b=k8fpik/2W/FJbKD3VfOCKR3UKAb/ui0AVu82LY5o/UiHODZv/Mp72/+auP00wtHIB7FW1/ eAz95XSQcMFa5hwgUpJaLyla200KCYy8lBa9Xu2pDcfbeHTUnhHT+2gjvDVG+OUag9TyBZ vGpbhRDq3ThWN94xGJVbScK9w2e/Nx3PHya5NHgChuAPtFpoxda6qVWjQPS85fucoVy/Ae IheUMTZ1BLAopqIRUGvZKsOOjN0G1zpzY2wkgcmvA1QDZDIuyEI3WhwYjtUsYWyDyMs5dN efl9t1zz0lFHcQbkBcjNNSDwNfJqvCN5dwlKhq5dIkmX5C5jle5vfs9RJGadQQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1743197869; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=uj7CvXQ4qtnsUBY9PoZ8Kq9gNJXauXx0kbvPLJSyGeY=; b=wSGEGLJ2dzNEkhmdKWCTPHyVHU3uGS04fixg6uCqBkhEsbideA5w41sCdMgNXiSiExwfh8 BiC6+wxXO820FXdS4BtLqoKXlMkqVMqgZMY5bCK623lNeQO9Fp1eju0YLjr9VfK3ELa4je mpnWIl4mFhWKNmo2xOWj10p1clfs7DI7FHkFlOPkjv2jT0KiRKDayzDJLc2aRRY6W+ugUd TgrON8dsIM0E5Ii/ibZvUia0t9SjOlYwZrL8uGEnNPGRmUu468WnSqvr4NjDULBGTeNHkP t4mKq7X3VIUNnLqeJ/QhJ4o9iPkh6j09vbkOaQAwJSoJMvMm8Q6pTd7vxWJHTw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ZPYlx4gqtz10m0; Fri, 28 Mar 2025 21:37:49 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 52SLbnSo003487; Fri, 28 Mar 2025 21:37:49 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 52SLbnkN003484; Fri, 28 Mar 2025 21:37:49 GMT (envelope-from git) Date: Fri, 28 Mar 2025 21:37:49 GMT Message-Id: <202503282137.52SLbnkN003484@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 531345778067 - main - libc/tests: add getaddrinfo test List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 53134577806796c8c12119c854a30ed4faf5a73e Auto-Submitted: auto-generated The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=53134577806796c8c12119c854a30ed4faf5a73e commit 53134577806796c8c12119c854a30ed4faf5a73e Author: Gleb Smirnoff AuthorDate: 2025-03-28 21:34:55 +0000 Commit: Gleb Smirnoff CommitDate: 2025-03-28 21:36:40 +0000 libc/tests: add getaddrinfo test A test suite for getaddrinfo(3) written in C. Unlike NetBSD test, this one will be mostly focused on what the API should return when something isn't good with your DNS. Test emulates bad DNS servers in resolv.conf intercepting fopen(2) and emulates downed network intercepting send(2). Initial version covers three main scenarios: all good, server(s) timed out, network down. For each scenario we test hostname with trailing dot and without, since libc resolver uses quite different code paths, sometimes even yielding with different error codes. All current error codes in the test are what our libc returns right now, meaning the test documents what we have, not what there should be. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D49410 --- lib/libc/tests/net/getaddrinfo/Makefile | 1 + lib/libc/tests/net/getaddrinfo/getaddrinfo.c | 267 +++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) diff --git a/lib/libc/tests/net/getaddrinfo/Makefile b/lib/libc/tests/net/getaddrinfo/Makefile index 19c7ccbe0030..1c8d68d8cc25 100644 --- a/lib/libc/tests/net/getaddrinfo/Makefile +++ b/lib/libc/tests/net/getaddrinfo/Makefile @@ -7,6 +7,7 @@ TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libc/net/${.CURDIR:T} BINDIR= ${TESTSDIR} NETBSD_ATF_TESTS_SH= getaddrinfo_test +ATF_TESTS_C= getaddrinfo PROGS= h_gai diff --git a/lib/libc/tests/net/getaddrinfo/getaddrinfo.c b/lib/libc/tests/net/getaddrinfo/getaddrinfo.c new file mode 100644 index 000000000000..9d8575232d2a --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/getaddrinfo.c @@ -0,0 +1,267 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Gleb Smirnoff + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include + +static const char goodname[] = "www.freebsd.org"; +static const char goodname_dot[] = "www.freebsd.org."; +static const char badname[] = "does-not-exist.freebsd.org"; +static const char badname_dot[] = "does-not-exist.freebsd.org."; +static const char ipv6onlyname[] = "beefy15.nyi.freebsd.org"; +static const char ipv6onlyname_dot[] = "beefy15.nyi.freebsd.org."; +static const char ipv4onlyname[] = "ipv4only.arpa"; +static const char ipv4onlyname_dot[] = "ipv4only.arpa."; +/* + * We need an IP address that doesn't exist, but not reported with ICMP + * unreachable by the nearest router. Let's try TEST-NET-3. + */ +static char badresolvconf[] = "nameserver 203.0.113.1"; +static char badresolvconf2[] = "nameserver 203.0.113.1\n" + "nameserver 203.0.113.2"; +static char *resconf = NULL; +FILE * +fopen(const char * restrict path, const char * restrict mode) +{ + static FILE *(*orig)(const char *, const char *); + + if (orig == NULL && (orig = dlsym(RTLD_NEXT, "fopen")) == NULL) + atf_libc_error(ENOENT, "dlsym(fopen): %s", dlerror()); + if (resconf != NULL && strcmp(path, _PATH_RESCONF) == 0) + return (fmemopen(resconf, strlen(resconf), mode)); + else + return (orig(path, mode)); +} + +static int send_error = 0; +ssize_t +send(int s, const void *msg, size_t len, int flags) +{ + static ssize_t (*orig)(int, const void *, size_t, int); + + if (orig == NULL && (orig = dlsym(RTLD_NEXT, "send")) == NULL) + atf_libc_error(ENOENT, "dlsym(send): %s", dlerror()); + if (send_error != 0) { + errno = send_error; + return (-1); + } else { + return (orig(s, msg, len, flags)); + } +} + +ATF_TC_WITHOUT_HEAD(basic); +ATF_TC_BODY(basic, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + rv = getaddrinfo(goodname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == 0, + "Expected 0, got %d (%s)", rv, gai_strerror(rv)); + freeaddrinfo(res); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == 0, + "Expected 0, got %d (%s)", rv, gai_strerror(rv)); + freeaddrinfo(res); + + rv = getaddrinfo(badname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); + + rv = getaddrinfo(badname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); +} + +ATF_TC_WITHOUT_HEAD(timeout); +ATF_TC_BODY(timeout, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + resconf = badresolvconf; + rv = getaddrinfo(goodname, NULL, &hints, &res); + /* + * XXXGL: EAI_ADDRFAMILY is most likely a regression from 144361386696. + * Error code on timeout used to be EAI_NONAME for many years and IMHO + * this is not correct either. Should be EAI_AGAIN. + */ + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); +} + +ATF_TC_WITHOUT_HEAD(timeout_specific); +ATF_TC_BODY(timeout_specific, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + resconf = badresolvconf; + rv = getaddrinfo(goodname, "666", &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, "666", &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); +} + +ATF_TC_WITHOUT_HEAD(timeout2); +ATF_TC_BODY(timeout2, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + resconf = badresolvconf2; + rv = getaddrinfo(goodname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); +} + +/* + * Emulate interface/network down. + */ +ATF_TC_WITHOUT_HEAD(netdown); +ATF_TC_BODY(netdown, tc) +{ + static const struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + send_error = ENETDOWN; + rv = getaddrinfo(goodname, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); + + rv = getaddrinfo(goodname_dot, NULL, &hints, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); +} + +/* + * See https://reviews.freebsd.org/D37139. + */ +ATF_TC_WITHOUT_HEAD(nofamily); +ATF_TC_BODY(nofamily, tc) +{ + static const struct addrinfo hints4 = { + .ai_family = AF_INET, + .ai_flags = AI_CANONNAME, + }, hints6 = { + .ai_family = AF_INET6, + .ai_flags = AI_CANONNAME, + }; + struct addrinfo *res; + int rv; + + rv = getaddrinfo(ipv6onlyname, NULL, &hints4, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(ipv6onlyname_dot, NULL, &hints4, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(ipv4onlyname, NULL, &hints6, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(ipv4onlyname_dot, NULL, &hints6, &res); + ATF_REQUIRE_MSG(rv == EAI_ADDRFAMILY, + "Expected %d (EAI_ADDRFAMILY), got %d (%s)", + EAI_ADDRFAMILY, rv, gai_strerror(rv)); + + rv = getaddrinfo(badname, NULL, &hints4, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); + + rv = getaddrinfo(badname_dot, NULL, &hints6, &res); + ATF_REQUIRE_MSG(rv == EAI_NONAME, + "Expected %d (EAI_NONAME), got %d (%s)", + EAI_NONAME, rv, gai_strerror(rv)); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, basic); + ATF_TP_ADD_TC(tp, timeout); + ATF_TP_ADD_TC(tp, timeout_specific); + ATF_TP_ADD_TC(tp, timeout2); + ATF_TP_ADD_TC(tp, netdown); + ATF_TP_ADD_TC(tp, nofamily); + + return (atf_no_error()); +}