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;