Index: netinet/ip_output.c =================================================================== RCS file: /cvsroot/src/sys/netinet/ip_output.c,v retrieving revision 1.230 diff -u -p -r1.230 ip_output.c --- netinet/ip_output.c 6 Jun 2014 00:11:19 -0000 1.230 +++ netinet/ip_output.c 11 Oct 2014 15:54:11 -0000 @@ -136,8 +136,6 @@ static struct mbuf *ip_insertoptions(str static struct ifnet *ip_multicast_if(struct in_addr *, int *); static void ip_mloopback(struct ifnet *, struct mbuf *, const struct sockaddr_in *); -static int ip_setmoptions(struct inpcb *, const struct sockopt *); -static int ip_getmoptions(struct inpcb *, struct sockopt *); extern pfil_head_t *inet_pfil_hook; /* XXX */ @@ -1003,7 +1001,7 @@ ip_ctloutput(int op, struct socket *so, case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: - error = ip_setmoptions(inp, sopt); + error = ip_setmoptions(&inp->inp_moptions, sopt); break; case IP_PORTRANGE: @@ -1151,7 +1149,7 @@ ip_ctloutput(int op, struct socket *so, case IP_MULTICAST_LOOP: case IP_ADD_MEMBERSHIP: case IP_DROP_MEMBERSHIP: - error = ip_getmoptions(inp, sopt); + error = ip_getmoptions(inp->inp_moptions, sopt); break; case IP_PORTRANGE: @@ -1364,10 +1362,10 @@ ip_getoptval(const struct sockopt *sopt, /* * Set the IP multicast options in response to user setsockopt(). */ -static int -ip_setmoptions(struct inpcb *inp, const struct sockopt *sopt) +int +ip_setmoptions(struct ip_moptions **pimo, const struct sockopt *sopt) { - struct ip_moptions *imo = inp->inp_moptions; + struct ip_moptions *imo = *pimo; struct in_addr addr; struct ip_mreq lmreq, *mreq; struct ifnet *ifp; @@ -1387,7 +1385,7 @@ ip_setmoptions(struct inpcb *inp, const imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; imo->imo_num_memberships = 0; - inp->inp_moptions = imo; + *pimo = imo; } switch (sopt->sopt_name) { @@ -1583,7 +1581,7 @@ ip_setmoptions(struct inpcb *inp, const imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP && imo->imo_num_memberships == 0) { kmem_free(imo, sizeof(*imo)); - inp->inp_moptions = NULL; + *pimo = NULL; } return error; @@ -1592,10 +1590,9 @@ ip_setmoptions(struct inpcb *inp, const /* * Return the IP multicast options in response to user getsockopt(). */ -static int -ip_getmoptions(struct inpcb *inp, struct sockopt *sopt) +int +ip_getmoptions(struct ip_moptions *imo, struct sockopt *sopt) { - struct ip_moptions *imo = inp->inp_moptions; struct in_addr addr; struct in_ifaddr *ia; uint8_t optval; Index: netinet/ip_var.h =================================================================== RCS file: /cvsroot/src/sys/netinet/ip_var.h,v retrieving revision 1.106 diff -u -p -r1.106 ip_var.h --- netinet/ip_var.h 5 Jun 2014 23:48:16 -0000 1.106 +++ netinet/ip_var.h 11 Oct 2014 15:54:12 -0000 @@ -234,6 +234,9 @@ int rip_output(struct mbuf *, ...); int rip_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); +int ip_setmoptions(struct ip_moptions **, const struct sockopt *sopt); +int ip_getmoptions(struct ip_moptions *, struct sockopt *sopt); + /* IP Flow interface. */ void ipflow_init(void); void ipflow_poolinit(void); Index: netinet6/in6_pcb.h =================================================================== RCS file: /cvsroot/src/sys/netinet6/in6_pcb.h,v retrieving revision 1.39 diff -u -p -r1.39 in6_pcb.h --- netinet6/in6_pcb.h 5 Aug 2014 05:24:27 -0000 1.39 +++ netinet6/in6_pcb.h 11 Oct 2014 15:54:13 -0000 @@ -96,7 +96,10 @@ struct in6pcb { struct ip6_hdr in6p_ip6; /* header prototype */ struct mbuf *in6p_options; /* IP6 options */ struct ip6_pktopts *in6p_outputopts; /* IP6 options for outgoing packets */ - struct ip6_moptions *in6p_moptions; /* IP6 multicast options */ + union { + struct ip6_moptions *in6p_moptions; /* IP6 multicast options */ + struct ip_moptions *in6p_v4moptions; + }; struct icmp6_filter *in6p_icmp6filt; int in6p_cksum; /* IPV6_CHECKSUM setsockopt */ bool in6p_bindportonsend; Index: netinet6/ip6_output.c =================================================================== RCS file: /cvsroot/src/sys/netinet6/ip6_output.c,v retrieving revision 1.158 diff -u -p -r1.158 ip6_output.c --- netinet6/ip6_output.c 16 Aug 2014 17:27:09 -0000 1.158 +++ netinet6/ip6_output.c 11 Oct 2014 15:54:13 -0000 @@ -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,9 +1277,32 @@ 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) { case PRCO_SETOPT: switch (optname) { Index: netinet6/udp6_output.c =================================================================== RCS file: /cvsroot/src/sys/netinet6/udp6_output.c,v retrieving revision 1.44 diff -u -p -r1.44 udp6_output.c --- netinet6/udp6_output.c 6 Jan 2013 00:17:13 -0000 1.44 +++ netinet6/udp6_output.c 11 Oct 2014 15:54:13 -0000 @@ -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;