Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148470409
D55031.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D55031.diff
View Options
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -158,8 +158,6 @@
static struct ip_moptions *
inp_findmoptions(struct inpcb *);
static int inp_get_source_filters(struct inpcb *, struct sockopt *);
-static int inp_join_group(struct inpcb *, struct sockopt *);
-static int inp_leave_group(struct inpcb *, struct sockopt *);
static int inp_block_unblock_source(struct inpcb *, struct sockopt *);
static int inp_set_multicast_if(struct inpcb *, struct sockopt *);
static int inp_set_source_filters(struct inpcb *, struct sockopt *);
@@ -1884,7 +1882,7 @@
/*
* Join an IPv4 multicast group, possibly with a source.
*/
-static int
+int
inp_join_group(struct inpcb *inp, struct sockopt *sopt)
{
struct group_source_req gsr;
@@ -2208,7 +2206,7 @@
/*
* Leave an IPv4 multicast group on an inpcb, possibly with a source.
*/
-static int
+int
inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
{
struct epoch_tracker et;
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -477,6 +477,11 @@
void in_detachhead(struct rib_head *rh);
#endif
+struct sockopt;
+
+int inp_join_group(struct inpcb *, struct sockopt *);
+int inp_leave_group(struct inpcb *, struct sockopt *);
+
#endif /* _KERNEL */
/* INET6 stuff */
diff --git a/sys/netinet6/in6_mcast.c b/sys/netinet6/in6_mcast.c
--- a/sys/netinet6/in6_mcast.c
+++ b/sys/netinet6/in6_mcast.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright (c) 2009 Bruce Simpson.
+ * Copyright (c) 2009-2026 Bruce Simpson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@
* Normative references: RFC 2292, RFC 3492, RFC 3542, RFC 3678, RFC 3810.
*/
+#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/param.h>
@@ -162,6 +163,9 @@
static int in6p_block_unblock_source(struct inpcb *, struct sockopt *);
static int in6p_set_multicast_if(struct inpcb *, struct sockopt *);
static int in6p_set_source_filters(struct inpcb *, struct sockopt *);
+#ifdef INET
+static int in6_v6_mreq_to_v4(struct ipv6_mreq *, struct ip_mreq *);
+#endif
static int sysctl_ip6_mcast_filters(SYSCTL_HANDLER_ARGS);
SYSCTL_DECL(_net_inet6_ip6); /* XXX Not in any common header. */
@@ -1881,6 +1885,51 @@
return (nh ? nh->nh_ifp : NULL);
}
+#ifdef INET
+/*
+ * Perform sockopt mreq argument conversion for IPv4-mapped groups.
+ *
+ * NOTE: Only required to support an extension to the behaviour in
+ * RFC 3493 Sec 3.7, which is used by OpenJDK and other software
+ * which assumes AF_INET joins are possible on AF_INET6 sockets.
+ * This support is limited to simple ASM mode joins/leaves only.
+ *
+ * FUTURE: Use IPv4 source-address selection.
+ */
+static int
+in6_v6_mreq_to_v4(struct ipv6_mreq *mreq, struct ip_mreq *mreq_v4)
+{
+ int error;
+ struct epoch_tracker et;
+ struct ifnet *ifp;
+ struct in_ifaddr *ia;
+
+ NET_EPOCH_ENTER(et);
+
+ ifp = ifnet_byindex(mreq->ipv6mr_interface);
+ if (ifp == NULL) {
+ error = EADDRNOTAVAIL;
+ goto out;
+ }
+
+ /*
+ * XXX: Allow the primary IP to be 0.0.0.0 for bootstrap;
+ * otherwise, check in_nullhost(ia->ia_addr.sin_addr.s_addr).
+ */
+ IFP_TO_IA(ifp, ia);
+ if (ia == NULL) {
+ error = EADDRNOTAVAIL;
+ goto out;
+ }
+ mreq_v4->imr_interface.s_addr = IA_SIN(ia)->sin_addr.s_addr;
+ error = 0;
+
+out:
+ NET_EPOCH_EXIT(et);
+ return (error);
+}
+#endif /* INET */
+
/*
* Join an IPv6 multicast group, possibly with a source.
*
@@ -1929,6 +1978,33 @@
sizeof(struct ipv6_mreq));
if (error)
return (error);
+#ifdef INET
+ if (IN6_IS_ADDR_V4MAPPED(&mreq.ipv6mr_multiaddr)) {
+ struct ip_mreq mreq_v4;
+ struct sockopt sopt_v4 = {
+ .sopt_dir = SOPT_SET,
+ .sopt_level = sopt->sopt_level,
+ .sopt_name = IP_ADD_MEMBERSHIP,
+ .sopt_val = &mreq_v4,
+ .sopt_valsize = sizeof(mreq_v4),
+ .sopt_rights = sopt->sopt_rights,
+ .sopt_td = sopt->sopt_td
+ };
+
+ mreq_v4.imr_multiaddr.s_addr =
+ mreq.ipv6mr_multiaddr.s6_addr32[3];
+ if (mreq.ipv6mr_interface == 0) {
+ mreq_v4.imr_interface.s_addr = INADDR_ANY;
+ } else {
+ error = in6_v6_mreq_to_v4(&mreq, &mreq_v4);
+ }
+ if (error) {
+ return error;
+ }
+
+ return (inp_join_group(inp, &sopt_v4));
+ }
+#endif /* INET */
gsa->sin6.sin6_family = AF_INET6;
gsa->sin6.sin6_len = sizeof(struct sockaddr_in6);
@@ -2242,6 +2318,33 @@
sizeof(struct ipv6_mreq));
if (error)
return (error);
+#ifdef INET
+ if (IN6_IS_ADDR_V4MAPPED(&mreq.ipv6mr_multiaddr)) {
+ struct ip_mreq mreq_v4;
+ struct sockopt sopt_v4 = {
+ .sopt_dir = SOPT_SET,
+ .sopt_level = sopt->sopt_level,
+ .sopt_name = IP_DROP_MEMBERSHIP,
+ .sopt_val = &mreq_v4,
+ .sopt_valsize = sizeof(mreq_v4),
+ .sopt_rights = sopt->sopt_rights,
+ .sopt_td = sopt->sopt_td
+ };
+
+ mreq_v4.imr_multiaddr.s_addr =
+ mreq.ipv6mr_multiaddr.s6_addr32[3];
+ if (mreq.ipv6mr_interface == 0) {
+ mreq_v4.imr_interface.s_addr = INADDR_ANY;
+ } else {
+ error = in6_v6_mreq_to_v4(&mreq, &mreq_v4);
+ }
+ if (error) {
+ return error;
+ }
+
+ return (inp_leave_group(inp, &sopt_v4));
+ }
+#endif /* INET */
gsa->sin6.sin6_family = AF_INET6;
gsa->sin6.sin6_len = sizeof(struct sockaddr_in6);
gsa->sin6.sin6_addr = mreq.ipv6mr_multiaddr;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 19, 2:54 AM (13 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29940876
Default Alt Text
D55031.diff (6 KB)
Attached To
Mode
D55031: netinet6: Pass IPv4-mapped ASM multicast joins/leaves to netinet.
Attached
Detach File
Event Timeline
Log In to Comment