From nobody Mon Aug 3 15:47:40 2026 X-Original-To: dev-commits-src-all@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 4hDLfT3rPKz6mPMp for ; Mon, 03 Aug 2026 15:47:45 +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 "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hDLfT2dTkz3Kfk for ; Mon, 03 Aug 2026 15:47:45 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785772065; 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=q+li+wr206DjlUcMVmrIKT2I5SgNw+GdLwIPThtV2rA=; b=pkyEpjLcjY5ErNH0xsTTRLkkVzTSJvMYjQQzw8Ew2wcizzS4qgmhbfNUzIBM+HDeihmyyv /L7d1Y48vhPMEgMGtYvnfU20497KSkY7E+PgtFZ/Iaf1z3i1TFLf3QcL+JOWTKmVqAHJX9 wdHeEq73zbBThpcWMzOFZ62/vjOdOS421tUiEP91cv0c0HUr8AJP52ib/JHSLDFF13mAJ4 ZwxybGshBCKGARFeK4pA3wcWRmy4UvC0U6Yjw59ZKYKrqptPVuf5zKHVDZi0a7iw9CvtFe gWklH0SPly2Nu0SNQZ5EQaVR4YRf9v5HoEL7J11LW0+mTTUY7l97FICQHljGJg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785772065; a=rsa-sha256; cv=none; b=DIWdq3TbUOeY4rxAxPTWEDjkRmOasxXeAt4oNbmKy0p9+pMxvdRYVipGp3gLI8pSmBTP1r q8QuoERtMjAM3IFtkaVfJg07h3WwdRyk3VSd3SzSBKXfAbCG6w6zEz5nk5JoOpbsyaXgK7 MvlFradoCInqX02gQxdf968dN6gEYhmH9/SrvO3RHXNVhHw61WrQfSXqMFlW4kyiKb2GrO kSNoo5R3XM7IIfhcI2pEB9HuudlRDRnPfhmi1QO9/BOwpt2PKrCwKvLkC6clpSGFPbZfU2 hkjqz3SZ/Ry4rB82N+SDkudI9sE+7B9WIaDbdRAwKfjy+NDHeSNMrSHGE7OIog== 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=1785772065; 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=q+li+wr206DjlUcMVmrIKT2I5SgNw+GdLwIPThtV2rA=; b=pbu6CtojHIyojvRrZLdHgqnuHCFH77wENPfubwud6Qhg5jFnxSEFkXT+DPfiSwgI4I9p2u V2D1G4nIWHXuHUE1lESMOCaQfyrzkGGTtMhLj0h7KIO3pO1ITuHfZBfBeMF/kLgPt5RDer LTIUkLr9etuV59mtKX3g1KxHb+/32Il6LT1jkyahEs1Iv6/7sfqqUAftpT3K5rz1ip2ANW i6y9lBN6ReEhOnyvLx4xqHOhIzQ+bWg7HSXbjvdpYIhky0JV21s0gwonn7eJDMd4cZril4 fZSrJLiWN76yTiCttBGF9ATUV5czRou7lximD6Ddx4tRC4nsHFmGQsEnJxkO1w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hDLfT1JNDz16Sn for ; Mon, 03 Aug 2026 15:47:45 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3e2d0 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 03 Aug 2026 15:47:40 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Bruce M Simpson Subject: git: c8d4287e30d6 - main - mtest: Add support for exercising IPv4-mapped groups on IPv6 sockets. List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bms X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c8d4287e30d6dc2ed3d4378133758adabc0030a3 Auto-Submitted: auto-generated Date: Mon, 03 Aug 2026 15:47:40 +0000 Message-Id: <6a70b81c.3e2d0.a134af1@gitrepo.freebsd.org> The branch main has been updated by bms: URL: https://cgit.FreeBSD.org/src/commit/?id=c8d4287e30d6dc2ed3d4378133758adabc0030a3 commit c8d4287e30d6dc2ed3d4378133758adabc0030a3 Author: Bruce M Simpson AuthorDate: 2026-08-02 08:00:19 +0000 Commit: Bruce M Simpson CommitDate: 2026-08-03 15:47:24 +0000 mtest: Add support for exercising IPv4-mapped groups on IPv6 sockets. This is in lieu of a full Kyua/ATF regression test, as this is an optional feature that was beyond the scope of IETF's normative references for IPv6 multicast; support has been strictly on a best-effort basis. Two new commands are added to mtest(8): u mcast-addr ifname - join IPv4-mapped group on IPv6 socket v mcast-addr ifname - leave IPv4-mapped group on IPv6 socket Add an internal helper function __in6_v4_to_v4mapped() to perform the converse of the IN6_IS_ADDR_V4MAPPED() check to support this use case. Whilst __in6_v4_to_v4mapped() returns its first argument as a convenience, avoid the temptation to dereference a pointer to that which we already hold. Strictly the use of sockunion_t within mtest(8) more generally is a form of controlled type punning (aliasing). Use a temporary as we overwrite contents of su; the resultant write would overlap memory locations. PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=193246 Differential Revision: https://reviews.freebsd.org/D58589 --- usr.sbin/mtest/mtest.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/usr.sbin/mtest/mtest.c b/usr.sbin/mtest/mtest.c index 941379b01bc9..e15068644043 100644 --- a/usr.sbin/mtest/mtest.c +++ b/usr.sbin/mtest/mtest.c @@ -104,6 +104,10 @@ typedef union mrequnion mrequnion_t; #ifdef INET static int __ifindex_to_primary_ip(const uint32_t, struct in_addr *); #endif +#if defined(INET) && defined(INET6) +static struct in6_addr * + __in6_v4_to_v4mapped(struct in6_addr *, struct in_addr *); +#endif static uint32_t parse_cmd_args(sockunion_t *, sockunion_t *, const char *, const char *, const char *); static void process_file(char *, int, int); @@ -143,6 +147,23 @@ su_cmp(const void *a, const void *b) return (memcmp(sua, sub, sua->sa.sa_len)); } +#if defined(INET) && defined(INET6) +/* + * Internal: Express an IPv4 address within IPv6 as IPv4-mapped. + * Converse of IN6_IS_ADDR_V4MAPPED(a). + */ +static struct in6_addr * +__in6_v4_to_v4mapped(struct in6_addr *a6 , struct in_addr *a4) +{ + + a6->s6_addr32[0] = 0; + a6->s6_addr32[1] = 0; + a6->s6_addr32[2] = ntohl(0x0000ffff); + a6->s6_addr32[3] = a4->s_addr; + return (a6); +} +#endif /* defined(INET) && defined(INET6) */ + #ifdef INET /* * Internal: Map an interface index to primary IPv4 address. @@ -518,6 +539,55 @@ process_cmd(char *cmd, int s, int s6, FILE *fp __unused) printf("-1\n"); break; + /* + * Exercise the non-IETF-ratified extension to RFC 3493 to + * join IPv4 groups as IPv4 mapped addresses on IPv6 sockets. + * Only ASM joins are supported; further use of the full-state API + * may result in undefined behaviour. + */ + case 'u': + case 'v': + toptname = ""; + sscanf(line, "%s %s", str1, str2); + ifindex = parse_cmd_args(&su, NULL, str1, str2, NULL); + if (ifindex == 0) { + printf("-1\n"); + break; + } + af = su.sa.sa_family; +#if defined(INET) && defined(INET6) + if (af == AF_INET) { + struct in_addr gaddr; + + gaddr = su.sin.sin_addr; + __in6_v4_to_v4mapped(&su.sin6.sin6_addr, &gaddr); + mr.mr6.ipv6mr_multiaddr = su.sin6.sin6_addr; + mr.mr6.ipv6mr_interface = ifindex; + optname = (*cmd == 'u') ? + IPV6_JOIN_GROUP : + IPV6_LEAVE_GROUP; + toptname = (*cmd == 'u') ? + "IPV6_JOIN_GROUP" : + "IPV6_LEAVE_GROUP"; + level = IPPROTO_IPV6; + optval = (void *)&mr.mr6; + optlen = sizeof(mr.mr6); + if (s6 < 0) { + warnc(EPROTONOSUPPORT, "setsockopt %s", + toptname); + } else if (setsockopt(s6, level, optname, optval, + optlen) == 0) { + printf("ok\n"); + break; + } else { + warn("setsockopt %s", toptname); + } + } +#endif /* defined(INET) && defined(INET6) */ + /* FALLTHROUGH */ + printf("-1\n"); + break; + /* * Set the socket to include or exclude filter mode, and * add some sources to the filterlist, using the full-state API. @@ -833,6 +903,8 @@ usage(void) printf("j mcast-addr ifname [src-addr] - join IP multicast group\n"); printf("l mcast-addr ifname [src-addr] - leave IP multicast group\n"); + printf("u mcast-addr ifname - join IPv4-mapped group on IPv6 socket\n"); + printf("v mcast-addr ifname - leave IPv4-mapped group on IPv6 socket\n"); printf( "i mcast-addr ifname n - set n include mode src filter\n"); printf(