Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F165043983
D58585.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D58585.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
@@ -459,6 +459,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,54 @@
return (nh ? nh->nh_ifp : NULL);
}
+#ifdef INET
+/*
+ * Perform sockopt mreq argument conversion for IPv4-mapped groups.
+ *
+ * This function is required to support an extension to the behaviour
+ * in RFC 3493 Sec 3.7, which was never formally proposed by any
+ * contemporary IPv6 normative reference, but which is now required
+ * by much application software using IPv6 sockets as a convenience.
+ * Refer to manual page ip6(4) for further information.
+ *
+ * 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;
+ }
+
+ /*
+ * Here, we do not compare the ifnet's primary IPv4 address with
+ * INADDR_ANY, to permit its use during system initialization.
+ * If this is not required, an appropriate check to screen it out
+ * should be added, e.g. in_nullhost(ia->ia_addr.sin_addr.s_addr).
+ */
+ ia = in_ifprimaryaddr(ifp);
+ 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 +1981,35 @@
sizeof(struct ipv6_mreq));
if (error)
return (error);
+#ifdef INET
+ /*
+ * Support for the non-IETF-ratified extension to RFC 3493 to
+ * join IPv4 groups as IPv4 mapped addresses on IPv6 sockets.
+ */
+ 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 +2323,35 @@
sizeof(struct ipv6_mreq));
if (error)
return (error);
+#ifdef INET
+ /*
+ * Support for the non-IETF-ratified extension to RFC 3493 to
+ * leave IPv4 groups as IPv4 mapped addresses on IPv6 sockets.
+ */
+ 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, Aug 6, 12:40 PM (6 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36118456
Default Alt Text
D58585.diff (5 KB)
Attached To
Mode
D58585: netinet6: Pass IPv4-mapped ASM multicast joins/leaves to netinet.
Attached
Detach File
Event Timeline
Log In to Comment