Module Name:    src
Committed By:   christos
Date:           Sat Oct 11 20:53:16 UTC 2014

Modified Files:
        src/sys/netinet6: in6_pcb.c in6_pcb.h ip6_output.c udp6_output.c

Log Message:
Make IPV4 mapped addresses able to do IPV4 multicast. Fixes needed:

        - allow binding to mapped v4 multicast addresses
        - define v4moptions, allow setting it via ioctl, pass it to ip_output,
          free it when killing the pcb.

Ideally we would allow the IPV6 multicast setsockopts work on mapped addresses
too, but this is a lot more work and linux does not do it either.


To generate a diff of this commit:
cvs rdiff -u -r1.129 -r1.130 src/sys/netinet6/in6_pcb.c
cvs rdiff -u -r1.39 -r1.40 src/sys/netinet6/in6_pcb.h
cvs rdiff -u -r1.158 -r1.159 src/sys/netinet6/ip6_output.c
cvs rdiff -u -r1.44 -r1.45 src/sys/netinet6/udp6_output.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/in6_pcb.c
diff -u src/sys/netinet6/in6_pcb.c:1.129 src/sys/netinet6/in6_pcb.c:1.130
--- src/sys/netinet6/in6_pcb.c:1.129	Sat Sep  6 20:50:56 2014
+++ src/sys/netinet6/in6_pcb.c	Sat Oct 11 16:53:16 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_pcb.c,v 1.129 2014/09/07 00:50:56 rmind Exp $	*/
+/*	$NetBSD: in6_pcb.c,v 1.130 2014/10/11 20:53:16 christos Exp $	*/
 /*	$KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.129 2014/09/07 00:50:56 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.130 2014/10/11 20:53:16 christos Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -229,7 +229,8 @@ in6_pcbbind_addr(struct in6pcb *in6p, st
 			sin.sin_family = AF_INET;
 			bcopy(&sin6->sin6_addr.s6_addr32[3],
 			    &sin.sin_addr, sizeof(sin.sin_addr));
-			if (ifa_ifwithaddr((struct sockaddr *)&sin) == 0)
+			if (!IN_MULTICAST(sin.sin_addr.s_addr) &&
+			    ifa_ifwithaddr((struct sockaddr *)&sin) == 0)
 				return EADDRNOTAVAIL;
 		}
 	} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
@@ -618,6 +619,7 @@ in6_pcbdetach(struct in6pcb *in6p)
 	}
 	rtcache_free(&in6p->in6p_route);
 	ip6_freemoptions(in6p->in6p_moptions);
+	ip_freemoptions(in6p->in6p_v4moptions);
 	sofree(so);				/* drops the socket's lock */
 
 	pool_put(&in6pcb_pool, in6p);

Index: src/sys/netinet6/in6_pcb.h
diff -u src/sys/netinet6/in6_pcb.h:1.39 src/sys/netinet6/in6_pcb.h:1.40
--- src/sys/netinet6/in6_pcb.h:1.39	Tue Aug  5 01:24:27 2014
+++ src/sys/netinet6/in6_pcb.h	Sat Oct 11 16:53:16 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_pcb.h,v 1.39 2014/08/05 05:24:27 rtr Exp $	*/
+/*	$NetBSD: in6_pcb.h,v 1.40 2014/10/11 20:53:16 christos Exp $	*/
 /*	$KAME: in6_pcb.h,v 1.45 2001/02/09 05:59:46 itojun Exp $	*/
 
 /*
@@ -100,6 +100,7 @@ struct	in6pcb {
 	struct icmp6_filter *in6p_icmp6filt;
 	int	in6p_cksum;		/* IPV6_CHECKSUM setsockopt */
 	bool    in6p_bindportonsend;
+	struct ip_moptions *in6p_v4moptions;/* IP4 multicast options */
 };
 
 #define in6p_faddr	in6p_ip6.ip6_dst

Index: src/sys/netinet6/ip6_output.c
diff -u src/sys/netinet6/ip6_output.c:1.158 src/sys/netinet6/ip6_output.c:1.159
--- src/sys/netinet6/ip6_output.c:1.158	Sat Aug 16 13:27:09 2014
+++ src/sys/netinet6/ip6_output.c	Sat Oct 11 16:53:16 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip6_output.c,v 1.158 2014/08/16 17:27:09 maxv Exp $	*/
+/*	$NetBSD: ip6_output.c,v 1.159 2014/10/11 20:53:16 christos Exp $	*/
 /*	$KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.158 2014/08/16 17:27:09 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.159 2014/10/11 20:53:16 christos Exp $");
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -86,6 +86,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_output.c
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 #include <netinet/ip6.h>
+#include <netinet/ip_var.h>
 #include <netinet/icmp6.h>
 #include <netinet/in_offload.h>
 #include <netinet/portalgo.h>
@@ -1264,6 +1265,7 @@ ip6_ctloutput(int op, struct socket *so,
 	int optdatalen, uproto;
 	void *optdata;
 	struct in6pcb *in6p = sotoin6pcb(so);
+	struct ip_moptions **mopts;
 	int error, optval;
 	int level, optname;
 
@@ -1275,7 +1277,29 @@ ip6_ctloutput(int op, struct socket *so,
 	error = optval = 0;
 	uproto = (int)so->so_proto->pr_protocol;
 
-	if (level != IPPROTO_IPV6) {
+	switch (level) {
+	case IPPROTO_IP:
+		switch (optname) {
+		case IP_ADD_MEMBERSHIP:
+		case IP_DROP_MEMBERSHIP:
+		case IP_MULTICAST_IF:
+		case IP_MULTICAST_LOOP:
+		case IP_MULTICAST_TTL:
+			mopts = &in6p->in6p_v4moptions;
+			switch (op) {
+			case PRCO_GETOPT:
+				return ip_getmoptions(*mopts, sopt);
+			case PRCO_SETOPT:
+				return ip_setmoptions(mopts, sopt);
+			default:
+				return EINVAL;
+			}
+		default:
+			return ENOPROTOOPT;
+		}
+	case IPPROTO_IPV6:
+		break;
+	default:
 		return ENOPROTOOPT;
 	}
 	switch (op) {

Index: src/sys/netinet6/udp6_output.c
diff -u src/sys/netinet6/udp6_output.c:1.44 src/sys/netinet6/udp6_output.c:1.45
--- src/sys/netinet6/udp6_output.c:1.44	Sat Jan  5 19:17:13 2013
+++ src/sys/netinet6/udp6_output.c	Sat Oct 11 16:53:16 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: udp6_output.c,v 1.44 2013/01/06 00:17:13 christos Exp $	*/
+/*	$NetBSD: udp6_output.c,v 1.45 2014/10/11 20:53:16 christos Exp $	*/
 /*	$KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.44 2013/01/06 00:17:13 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.45 2014/10/11 20:53:16 christos Exp $");
 
 #include "opt_inet.h"
 
@@ -404,7 +404,7 @@ udp6_output(struct in6pcb * const in6p, 
 
 		UDP_STATINC(UDP_STAT_OPACKETS);
 		error = ip_output(m, NULL, &in6p->in6p_route, flags /* XXX */,
-		    NULL, (struct socket *)in6p->in6p_socket);
+		    in6p->in6p_v4moptions, (struct socket *)in6p->in6p_socket);
 		break;
 #else
 		error = EAFNOSUPPORT;

Reply via email to