From nobody Wed Mar 25 19:59:05 2026 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 4fgyQy0wQXz6WjYq for ; Wed, 25 Mar 2026 19:59:06 +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 "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fgyQy0Mzkz3mVd for ; Wed, 25 Mar 2026 19:59:06 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1774468746; 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=9DIH6SxXbVOyjH+7Uq6FI5e2tZ5h2s/Ql4JsSz5ruw8=; b=S3OEtaSYr4Nf5KYBsr0k3GXqu/koc5A2KWWnjh+XWK/XTkdIuFQBHP9IoROs+5BdE623E7 mYBEbJeuDpDQTXor/nXKl3gLx5rLnAH5jTfFWm41eifxPFqJXj25afDCcesLUoLbJ90BzC jCMV1bCCQm2K+1QgX8I5OWgeUBndTsdjMsnG2GGE4NuZgqnukq5KxCMrPNWwtIUPUoqMnw zxs8L5NsTu7DdQ1HLP85mfT+aa6OcudBSJZhCaCf5mJ1proq8N2Hhh21JWKDjV1FvydXec RfMdvTJ66F/1SXvSLZXoApCkX4gCooGElYDJqdyTVzWMjXfYFl36Vcr63CDWqQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1774468746; a=rsa-sha256; cv=none; b=Llbeob6IGUUhVGPFqjr6RH6e+feFBbkn9e37x/WaEFkWWhBOoD474XgckDHO3FOu279CRT oyINorzH38nAyObzzxLJQ15AHLQIdFXihgujjhIRj+gVXCA3gqFSTW9ND+HEtEmNJYzuIK IO/sVIz3SAimVnOqnbsEXT79Z9zfKsAabERfhZv8NwgTs/vnlAvVPA1T5ef+DxKc0E7GfZ gz0pIy3I32lsX5jQlbJGUoNP3Sh6lw5zdhhzcul2MReS85HnEpaNvdmWytCMTwW9tALUjY yhbSPCvPaDgklzKoddrsJLTi9JH671ALMHwHcgclW69v8pBs+X7JfE6YRnUAeQ== 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=1774468746; 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=9DIH6SxXbVOyjH+7Uq6FI5e2tZ5h2s/Ql4JsSz5ruw8=; b=JWVgE5z+cXirg6lXk2t0ycJYFGBeoomQswtEgRDTPvfi3HCglpcPa/dVDeuW4l6Q7rDqYP 4gpZmPq70NcYxwn2eEhhMZ6XGHwxhM4hfKhUGJtxtjO8N+og5ga4pDx7RvEkUMnAEhghdO eRhslh1jfMylnBdF4PukEz45XUcNyO0sXXCbefjTGI5QzgkU/69Kp+OAz3Rj4hvTRHiRad cNlvY6cJ0s6F4E6a1P5P3PZIORY7jWLz3kNsKV96Y3MM2qbDJepOSEIEXIPjSDJIOMAO1C uuGh85kp8GlZZ3Vi+WbxP7PASTpq/0gZE+kR5NLjcUucsayLCmUyQ2JCgaCBkA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fgyQx6mM9z4Ns for ; Wed, 25 Mar 2026 19:59:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1f664 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 25 Mar 2026 19:59:05 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: f6989880841b - main - tests/netinet: add raw:reconnect 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: f6989880841b89d54ebcd5d12195c40a23627646 Auto-Submitted: auto-generated Date: Wed, 25 Mar 2026 19:59:05 +0000 Message-Id: <69c43e89.1f664.7cbd201f@gitrepo.freebsd.org> The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=f6989880841b89d54ebcd5d12195c40a23627646 commit f6989880841b89d54ebcd5d12195c40a23627646 Author: Gleb Smirnoff AuthorDate: 2026-03-25 18:53:44 +0000 Commit: Gleb Smirnoff CommitDate: 2026-03-25 19:58:28 +0000 tests/netinet: add raw:reconnect test It tests repetitive connect(2) on AF_INET/SOCK_RAW including connect(2) to INADDR_ANY that puts socket back into receive-all mode. --- tests/sys/netinet/raw.c | 237 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 168 insertions(+), 69 deletions(-) diff --git a/tests/sys/netinet/raw.c b/tests/sys/netinet/raw.c index 9c25b3ddbec2..d3feb315d5c4 100644 --- a/tests/sys/netinet/raw.c +++ b/tests/sys/netinet/raw.c @@ -36,6 +36,42 @@ #include +#define PROT1 253 /* RFC3692 */ +#define PROT2 254 /* RFC3692 */ +#define ADDR1 { htonl(0xc0000202) } /* RFC5737 */ +#define ADDR2 { htonl(0xc0000203) } /* RFC5737 */ +#define WILD { htonl(INADDR_ANY) } +#define LOOP(x) { htonl(INADDR_LOOPBACK + (x)) } +#define MULT(x) { htonl(INADDR_UNSPEC_GROUP + (x)) } + +static int +rawsender(bool mcast) +{ + int s; + + ATF_REQUIRE((s = socket(PF_INET, SOCK_RAW, 0)) != -1); + ATF_REQUIRE(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &(int){1}, + sizeof(int)) == 0); + /* + * Make sending socket connected. The socket API requires connected + * status to use send(2), even with IP_HDRINCL. + */ + ATF_REQUIRE(connect(s, + (struct sockaddr *)&(struct sockaddr_in){ + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_addr = { htonl(INADDR_ANY) }, + }, sizeof(struct sockaddr_in)) == 0); + + if (mcast) + ATF_REQUIRE(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, + &(struct ip_mreqn){ + .imr_ifindex = if_nametoindex("lo0"), + }, sizeof(struct ip_mreqn)) == 0); + + return (s); +} + /* * The 'input' test exercises logic of rip_input(). The best documentation * for raw socket input behavior is collected in Stevens's UNIX Network @@ -46,65 +82,56 @@ * The table tests[] describes our expectations. */ ATF_TC_WITHOUT_HEAD(input); -#define PROT1 253 /* RFC3692 */ -#define PROT2 254 /* RFC3692 */ -static const struct rcvr { - struct in_addr laddr, faddr, maddr; - uint8_t proto; -} rcvrs[] = { -#define WILD { htonl(INADDR_ANY) } -#define LOOP(x) { htonl(INADDR_LOOPBACK + (x)) } -#define MULT(x) { htonl(INADDR_UNSPEC_GROUP + (x)) } - { WILD, WILD, WILD, 0 }, - { WILD, WILD, WILD, PROT1 }, - { LOOP(0), WILD, WILD, 0 }, - { LOOP(0), WILD, WILD, PROT1 }, - { LOOP(1), WILD, WILD, 0 }, - { LOOP(1), WILD, WILD, PROT1 }, - { LOOP(0), LOOP(2), WILD, 0 }, - { LOOP(0), LOOP(2), WILD, PROT1 }, - { LOOP(0), LOOP(3), WILD, 0 }, - { LOOP(0), LOOP(3), WILD, PROT1 }, - { LOOP(1), LOOP(3), WILD, 0 }, - { LOOP(1), LOOP(3), WILD, PROT1 }, - { WILD, WILD, MULT(1), 0 }, -}; -static const struct test { - struct in_addr src, dst; - uint8_t proto; - bool results[nitems(rcvrs)]; -} tests[] = { +ATF_TC_BODY(input, tc) +{ + static const struct rcvr { + struct in_addr laddr, faddr, maddr; + uint8_t proto; + } rcvrs[] = { + { WILD, WILD, WILD, 0 }, + { WILD, WILD, WILD, PROT1 }, + { LOOP(0), WILD, WILD, 0 }, + { LOOP(0), WILD, WILD, PROT1 }, + { LOOP(1), WILD, WILD, 0 }, + { LOOP(1), WILD, WILD, PROT1 }, + { LOOP(0), LOOP(2), WILD, 0 }, + { LOOP(0), LOOP(2), WILD, PROT1 }, + { LOOP(0), LOOP(3), WILD, 0 }, + { LOOP(0), LOOP(3), WILD, PROT1 }, + { LOOP(1), LOOP(3), WILD, 0 }, + { LOOP(1), LOOP(3), WILD, PROT1 }, + { WILD, WILD, MULT(1), 0 }, + }; + static const struct test { + struct in_addr src, dst; + uint8_t proto; + bool results[nitems(rcvrs)]; + } tests[] = { #define x true #define o false - { LOOP(2), LOOP(0), PROT1, - { x, x, x, x, o, o, x, x, o, o, o, o, x } }, - { LOOP(2), LOOP(0), PROT2, - { x, o, x, o, o, o, x, o, o, o, o, o, x } }, - { LOOP(3), LOOP(0), PROT1, - { x, x, x, x, o, o, o, o, x, x, o, o, x } }, - { LOOP(3), LOOP(0), PROT2, - { x, o, x, o, o, o, o, o, x, o, o, o, x } }, - { LOOP(2), LOOP(1), PROT1, - { x, x, o, o, x, x, o, o, o, o, o, o, x } }, - { LOOP(2), LOOP(1), PROT2, - { x, o, o, o, x, o, o, o, o, o, o, o, x } }, - { LOOP(3), LOOP(1), PROT1, - { x, x, o, o, x, x, o, o, o, o, x, x, x } }, - { LOOP(3), LOOP(1), PROT2, - { x, o, o, o, x, o, o, o, o, o, x, o, x } }, - { LOOP(3), MULT(1), PROT1, - { x, x, o, o, o, o, o, o, o, o, o, o, x } }, - { LOOP(3), MULT(2), PROT1, - { x, x, o, o, o, o, o, o, o, o, o, o, o } }, -#undef WILD -#undef LOOP -#undef MULT + { LOOP(2), LOOP(0), PROT1, + { x, x, x, x, o, o, x, x, o, o, o, o, x } }, + { LOOP(2), LOOP(0), PROT2, + { x, o, x, o, o, o, x, o, o, o, o, o, x } }, + { LOOP(3), LOOP(0), PROT1, + { x, x, x, x, o, o, o, o, x, x, o, o, x } }, + { LOOP(3), LOOP(0), PROT2, + { x, o, x, o, o, o, o, o, x, o, o, o, x } }, + { LOOP(2), LOOP(1), PROT1, + { x, x, o, o, x, x, o, o, o, o, o, o, x } }, + { LOOP(2), LOOP(1), PROT2, + { x, o, o, o, x, o, o, o, o, o, o, o, x } }, + { LOOP(3), LOOP(1), PROT1, + { x, x, o, o, x, x, o, o, o, o, x, x, x } }, + { LOOP(3), LOOP(1), PROT2, + { x, o, o, o, x, o, o, o, o, o, x, o, x } }, + { LOOP(3), MULT(1), PROT1, + { x, x, o, o, o, o, o, o, o, o, o, o, x } }, + { LOOP(3), MULT(2), PROT1, + { x, x, o, o, o, o, o, o, o, o, o, o, o } }, #undef x #undef o -}; - -ATF_TC_BODY(input, tc) -{ + }; struct pkt { struct ip ip; char payload[100]; @@ -158,24 +185,11 @@ ATF_TC_BODY(input, tc) } } - ATF_REQUIRE((s = socket(PF_INET, SOCK_RAW, 0)) != -1); - ATF_REQUIRE(setsockopt(s, IPPROTO_IP, IP_HDRINCL, &(int){1}, - sizeof(int)) == 0); - /* - * Make sending socket connected. The socket API requires connected - * status to use send(2), even with IP_HDRINCL. Another side effect - * is that the sending socket won't receive own datagrams, which we - * don't drain out in this program. - */ - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK + 100); - ATF_REQUIRE(connect(s, (struct sockaddr *)&sin, sizeof(sin)) == 0); /* * Force multicast interface for the sending socket to be able to * send to MULT(x) destinations. */ - mreqn.imr_multiaddr.s_addr = 0; - ATF_REQUIRE(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, - sizeof(mreqn)) == 0); + s = rawsender(true); for (u_int i = 0; i < nitems(tests); i++) { arc4random_buf(&pkt.payload, sizeof(pkt.payload)); @@ -211,9 +225,94 @@ ATF_TC_BODY(input, tc) } } +/* + * Test input on the same socket that changes its connection status. We send + * packets with different sources in each iteration and check results. + * Check that connect(INADDR_ANY) is effectively a disconnect and turns socket + * back to receive-all mode. + */ +ATF_TC_WITHOUT_HEAD(reconnect); +ATF_TC_BODY(reconnect, tc) +{ + static const struct in_addr srcs[] = { ADDR1, ADDR2 }; + static const struct test { + struct in_addr faddr; + bool results[nitems(srcs)]; + } tests[] = { + { ADDR1, { true, false } }, + { ADDR2, { false, true } }, + { {INADDR_ANY}, { true, true } }, + }; + struct pkt { + struct ip ip; + char payload[100]; + } __packed pkt = { + .ip.ip_v = IPVERSION, + .ip.ip_hl = sizeof(struct ip) >> 2, + .ip.ip_len = htons(sizeof(struct pkt)), + .ip.ip_ttl = 16, + .ip.ip_p = PROT1, + .ip.ip_dst = LOOP(0), + }; + int r, s; + + /* XXX */ + system("/sbin/ifconfig lo0 127.0.0.1/32"); + + ATF_REQUIRE((r = socket(PF_INET, SOCK_RAW | SOCK_NONBLOCK, 0)) != -1); + s = rawsender(false); + + for (u_int i = 0; i < nitems(tests); i++) { + ATF_REQUIRE(connect(r, + (struct sockaddr *)&(struct sockaddr_in){ + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_addr = tests[i].faddr, + }, sizeof(struct sockaddr_in)) == 0); + + for (u_int j = 0; j < nitems(srcs); j++) { + char buf[sizeof(pkt)]; + char p[2][INET_ADDRSTRLEN]; + ssize_t ss; + + arc4random_buf(&pkt.payload, sizeof(pkt.payload)); + pkt.ip.ip_src = srcs[j]; + ATF_REQUIRE(send(s, &pkt, sizeof(pkt), 0) == + sizeof(pkt)); + + /* + * The sender is a blocking socket, so we first receive + * from the sender and when this read returns we are + * guaranteed that the test socket also received the + * datagram. + */ + ss = recv(s, buf, sizeof(buf), 0); + ATF_REQUIRE(ss == sizeof(buf) && + memcmp(buf + sizeof(struct ip), + pkt.payload, sizeof(pkt.payload)) == 0); + + ss = recv(r, buf, sizeof(buf), 0); + + ATF_REQUIRE_MSG((tests[i].results[j] == true && + ss == sizeof(buf) && memcmp(buf + sizeof(struct ip), + pkt.payload, sizeof(pkt.payload)) == 0) || + (tests[i].results[j] == false && ss == -1 && + errno == EAGAIN), + "test #%u src %s connect address %s unexpected " + "receive of %zd bytes errno %d", i, + inet_ntop(AF_INET, &srcs[j], p[0], + INET_ADDRSTRLEN), + inet_ntop(AF_INET, &tests[i].faddr, p[1], + INET_ADDRSTRLEN), + ss, errno); + } + } +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, input); + ATF_TP_ADD_TC(tp, reconnect); return (atf_no_error()); }