aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce M Simpson <bms@FreeBSD.org>2026-08-02 13:09:57 +0000
committerBruce M Simpson <bms@FreeBSD.org>2026-08-03 15:47:24 +0000
commit459af94e43b0fe2ef91e14aa867c3b1aa1fb9690 (patch)
treeafac17b8764f680f01da290305f711b0ac10366c
parentc8d4287e30d6dc2ed3d4378133758adabc0030a3 (diff)
netinet6: Fix some issues with passing v4-mapped groups to IPv6 sockets.
1. EFAULT was happening because sooptcopyin() from inp_join_group() was seeing the user-space thread descriptor in the faked-up sockopt. So, do not attempt a user copyin(); defer to C99 initialization nulling sopt_td for us to force a KVA memcpy(). 2. It seems necessary to byte-swap ipv6mr_multiaddr.s6_addr32[3] on amd64 for similar reasons as to how the user-space initialization needed for passing an IPv4-mapped group address also requires byte-swapping of the 0x0000FFFF field for s6_addr32[2]; it is a direct assignment to a integer member of a struct, NOT a memcpy(). 3. The assignment to imr_interface within in6_v6_mreq_to_v4() was obfuscated by a cast back to its own type due to use of the IA_SIN() macro. Elided. With this change, the feature gap seems to be closed; tested with a simple link-scope IPv4 group under 224.0.0.0/24 with an mlx5(4) SR-IOV VF in bhyve. PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=193246 Differential Revision: https://reviews.freebsd.org/D58590
-rw-r--r--sys/netinet6/in6_mcast.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c
index bc7da2d14a04..036d58e5bd92 100644
--- a/sys/netinet6/in6_mcast.c
+++ b/sys/netinet6/in6_mcast.c
@@ -1924,7 +1924,7 @@ in6_v6_mreq_to_v4(struct ipv6_mreq *mreq, struct ip_mreq *mreq_v4)
error = EADDRNOTAVAIL;
goto out;
}
- mreq_v4->imr_interface.s_addr = IA_SIN(ia)->sin_addr.s_addr;
+ mreq_v4->imr_interface.s_addr = ia->ia_addr.sin_addr.s_addr;
error = 0;
out:
@@ -1991,12 +1991,11 @@ in6p_join_group(struct inpcb *inp, struct sockopt *sopt)
.sopt_name = IP_ADD_MEMBERSHIP,
.sopt_val = &mreq_v4,
.sopt_valsize = sizeof(mreq_v4),
- .sopt_rights = sopt->sopt_rights,
- .sopt_td = sopt->sopt_td
+ .sopt_rights = sopt->sopt_rights
};
mreq_v4.imr_multiaddr.s_addr =
- mreq.ipv6mr_multiaddr.s6_addr32[3];
+ htonl(mreq.ipv6mr_multiaddr.s6_addr32[3]);
if (mreq.ipv6mr_interface == 0)
mreq_v4.imr_interface.s_addr = INADDR_ANY;
else
@@ -2333,12 +2332,11 @@ in6p_leave_group(struct inpcb *inp, struct sockopt *sopt)
.sopt_name = IP_DROP_MEMBERSHIP,
.sopt_val = &mreq_v4,
.sopt_valsize = sizeof(mreq_v4),
- .sopt_rights = sopt->sopt_rights,
- .sopt_td = sopt->sopt_td
+ .sopt_rights = sopt->sopt_rights
};
mreq_v4.imr_multiaddr.s_addr =
- mreq.ipv6mr_multiaddr.s6_addr32[3];
+ htonl(mreq.ipv6mr_multiaddr.s6_addr32[3]);
if (mreq.ipv6mr_interface == 0)
mreq_v4.imr_interface.s_addr = INADDR_ANY;
else