Message ID | 1301388053-6083-1-git-send-email-timo.teras@iki.fi |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Le mardi 29 mars 2011 à 11:40 +0300, Timo Teräs a écrit : > My commit 6d55cb91a0020ac0 (gre: fix hard header destination > address checking) broke multicast. > > The reason is that ip_gre used to get ipgre_header() calls with > zero destination if we have NOARP or multicast destination. Instead > the actual target was decided at ipgre_tunnel_xmit() time based on > per-protocol dissection. > > Instead of allowing the "abuse" of ->header() calls with invalid > destination, this creates multicast mappings for ip_gre. This also > fixes "ip neigh show nud noarp" to display the proper multicast > mappings used by the gre device. > > Reported-by: Doug Kehn <rdkehn@yahoo.com> > Signed-off-by: Timo Teräs <timo.teras@iki.fi> > --- > Compile tested only. Doug tested IPv4 side with the earlier patch. > +static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr, > + const unsigned char *broadcast, char *buf) > +{ > + if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) { > + memcpy(buf, broadcast, 4); > + } else { > + /* v4mapped? */ > + if ((addr->s6_addr32[0] | addr->s6_addr32[1] | > + (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0) > + return -EINVAL; if (ipv6_addr_v4mapped(addr)) > + memcpy(buf, &addr->s6_addr32[3], 4); > + } > + return 0; > +} -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 03/29/2011 12:11 PM, Eric Dumazet wrote: > Le mardi 29 mars 2011 à 11:40 +0300, Timo Teräs a écrit : >> My commit 6d55cb91a0020ac0 (gre: fix hard header destination >> address checking) broke multicast. >> >> The reason is that ip_gre used to get ipgre_header() calls with >> zero destination if we have NOARP or multicast destination. Instead >> the actual target was decided at ipgre_tunnel_xmit() time based on >> per-protocol dissection. >> >> Instead of allowing the "abuse" of ->header() calls with invalid >> destination, this creates multicast mappings for ip_gre. This also >> fixes "ip neigh show nud noarp" to display the proper multicast >> mappings used by the gre device. >> >> Reported-by: Doug Kehn <rdkehn@yahoo.com> >> Signed-off-by: Timo Teräs <timo.teras@iki.fi> >> --- >> Compile tested only. Doug tested IPv4 side with the earlier patch. > > >> +static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr, >> + const unsigned char *broadcast, char *buf) >> +{ >> + if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) { >> + memcpy(buf, broadcast, 4); >> + } else { >> + /* v4mapped? */ >> + if ((addr->s6_addr32[0] | addr->s6_addr32[1] | >> + (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0) >> + return -EINVAL; > > if (ipv6_addr_v4mapped(addr)) > > >> + memcpy(buf, &addr->s6_addr32[3], 4); >> + } >> + return 0; >> +} I wanted to put the function same header as all other similar ones: net/if_inet6.h. However, ipv6_addr_v4mapped() is defined in net/ipv6.h which includes net/if_inet6.h. So I can't really use that function there. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
--- On Tue, 3/29/11, Timo Teräs <timo.teras@iki.fi> wrote: > From: Timo Teräs <timo.teras@iki.fi> > Subject: [PATCH] net: gre: provide multicast mappings for ipv4 and ipv6 > To: netdev@vger.kernel.org > Cc: "Doug Kehn" <rdkehn@yahoo.com>, "Timo Teräs" <timo.teras@iki.fi> > Date: Tuesday, March 29, 2011, 4:40 AM > My commit 6d55cb91a0020ac0 (gre: fix > hard header destination > address checking) broke multicast. > > The reason is that ip_gre used to get ipgre_header() calls > with > zero destination if we have NOARP or multicast destination. > Instead > the actual target was decided at ipgre_tunnel_xmit() time > based on > per-protocol dissection. > > Instead of allowing the "abuse" of ->header() calls with > invalid > destination, this creates multicast mappings for ip_gre. > This also > fixes "ip neigh show nud noarp" to display the proper > multicast > mappings used by the gre device. > > Reported-by: Doug Kehn <rdkehn@yahoo.com> > Signed-off-by: Timo Teräs <timo.teras@iki.fi> Acked-by: Doug Kehn <rdkehn@yahoo.com> > --- > Compile tested only. Doug tested IPv4 side with the earlier > patch. This patch set [still] works with IPv4. > > The IPv6 side needs a review. I'm not sure if mapped IPv4 > multicast > addresses are intrepreted as multicast addresses by ndisc > code or > if we could map real IPv6 multicast addresses to IPv4 > multicast > addresses. > > include/net/if_inet6.h | 16 > ++++++++++++++++ > include/net/ip.h | > 8 ++++++++ > net/ipv4/arp.c > | 3 +++ > net/ipv6/ndisc.c | > 2 ++ > 4 files changed, 29 insertions(+), 0 deletions(-) > > diff --git a/include/net/if_inet6.h > b/include/net/if_inet6.h > index 04977ee..fccc218 100644 > --- a/include/net/if_inet6.h > +++ b/include/net/if_inet6.h > @@ -286,5 +286,21 @@ static inline void > ipv6_ib_mc_map(const struct in6_addr *addr, > buf[9] = broadcast[9]; > memcpy(buf + 10, addr->s6_addr + 6, > 10); > } > + > +static inline int ipv6_ipgre_mc_map(const struct in6_addr > *addr, > + > const unsigned char > *broadcast, char *buf) > +{ > + if ((broadcast[0] | broadcast[1] | > broadcast[2] | broadcast[3]) != 0) { > + memcpy(buf, > broadcast, 4); > + } else { > + /* v4mapped? */ > + if > ((addr->s6_addr32[0] | addr->s6_addr32[1] | > + > (addr->s6_addr32[2] ^ > htonl(0x0000ffff))) != 0) > + > return -EINVAL; > + memcpy(buf, > &addr->s6_addr32[3], 4); > + } > + return 0; > +} > + > #endif > #endif > diff --git a/include/net/ip.h b/include/net/ip.h > index a4f6311..7c41658 100644 > --- a/include/net/ip.h > +++ b/include/net/ip.h > @@ -339,6 +339,14 @@ static inline void ip_ib_mc_map(__be32 > naddr, const unsigned char *broadcast, ch > buf[16] = addr & 0x0f; > } > > +static inline void ip_ipgre_mc_map(__be32 naddr, const > unsigned char *broadcast, char *buf) > +{ > + if ((broadcast[0] | broadcast[1] | > broadcast[2] | broadcast[3]) != 0) > + memcpy(buf, > broadcast, 4); > + else > + memcpy(buf, > &naddr, sizeof(naddr)); > +} > + > #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) > #include <linux/ipv6.h> > #endif > diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c > index 090d273..1b74d3b 100644 > --- a/net/ipv4/arp.c > +++ b/net/ipv4/arp.c > @@ -215,6 +215,9 @@ int arp_mc_map(__be32 addr, u8 *haddr, > struct net_device *dev, int dir) > case ARPHRD_INFINIBAND: > ip_ib_mc_map(addr, > dev->broadcast, haddr); > return 0; > + case ARPHRD_IPGRE: > + > ip_ipgre_mc_map(addr, dev->broadcast, haddr); > + return 0; > default: > if (dir) { > > memcpy(haddr, dev->broadcast, dev->addr_len); > diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c > index 0e49c9d..92f952d 100644 > --- a/net/ipv6/ndisc.c > +++ b/net/ipv6/ndisc.c > @@ -341,6 +341,8 @@ int ndisc_mc_map(struct in6_addr *addr, > char *buf, struct net_device *dev, int d > case ARPHRD_INFINIBAND: > ipv6_ib_mc_map(addr, > dev->broadcast, buf); > return 0; > + case ARPHRD_IPGRE: > + return > ipv6_ipgre_mc_map(addr, dev->broadcast, buf); > default: > if (dir) { > > memcpy(buf, dev->broadcast, dev->addr_len); > -- > 1.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe > netdev" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Doug Kehn <rdkehn@yahoo.com> Date: Tue, 29 Mar 2011 13:26:02 -0700 (PDT) > > --- On Tue, 3/29/11, Timo Teräs <timo.teras@iki.fi> wrote: > >> From: Timo Teräs <timo.teras@iki.fi> >> Subject: [PATCH] net: gre: provide multicast mappings for ipv4 and ipv6 >> To: netdev@vger.kernel.org >> Cc: "Doug Kehn" <rdkehn@yahoo.com>, "Timo Teräs" <timo.teras@iki.fi> >> Date: Tuesday, March 29, 2011, 4:40 AM >> My commit 6d55cb91a0020ac0 (gre: fix >> hard header destination >> address checking) broke multicast. >> >> The reason is that ip_gre used to get ipgre_header() calls >> with >> zero destination if we have NOARP or multicast destination. >> Instead >> the actual target was decided at ipgre_tunnel_xmit() time >> based on >> per-protocol dissection. >> >> Instead of allowing the "abuse" of ->header() calls with >> invalid >> destination, this creates multicast mappings for ip_gre. >> This also >> fixes "ip neigh show nud noarp" to display the proper >> multicast >> mappings used by the gre device. >> >> Reported-by: Doug Kehn <rdkehn@yahoo.com> >> Signed-off-by: Timo Teräs <timo.teras@iki.fi> > > Acked-by: Doug Kehn <rdkehn@yahoo.com> Applied. Timo, if updates are necessary for the ipv4 mapped handling in ipv6, please send that as a follow-up fix. Thanks. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 04977ee..fccc218 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -286,5 +286,21 @@ static inline void ipv6_ib_mc_map(const struct in6_addr *addr, buf[9] = broadcast[9]; memcpy(buf + 10, addr->s6_addr + 6, 10); } + +static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr, + const unsigned char *broadcast, char *buf) +{ + if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) { + memcpy(buf, broadcast, 4); + } else { + /* v4mapped? */ + if ((addr->s6_addr32[0] | addr->s6_addr32[1] | + (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0) + return -EINVAL; + memcpy(buf, &addr->s6_addr32[3], 4); + } + return 0; +} + #endif #endif diff --git a/include/net/ip.h b/include/net/ip.h index a4f6311..7c41658 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -339,6 +339,14 @@ static inline void ip_ib_mc_map(__be32 naddr, const unsigned char *broadcast, ch buf[16] = addr & 0x0f; } +static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) +{ + if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) + memcpy(buf, broadcast, 4); + else + memcpy(buf, &naddr, sizeof(naddr)); +} + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #include <linux/ipv6.h> #endif diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 090d273..1b74d3b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -215,6 +215,9 @@ int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) case ARPHRD_INFINIBAND: ip_ib_mc_map(addr, dev->broadcast, haddr); return 0; + case ARPHRD_IPGRE: + ip_ipgre_mc_map(addr, dev->broadcast, haddr); + return 0; default: if (dir) { memcpy(haddr, dev->broadcast, dev->addr_len); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0e49c9d..92f952d 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -341,6 +341,8 @@ int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int d case ARPHRD_INFINIBAND: ipv6_ib_mc_map(addr, dev->broadcast, buf); return 0; + case ARPHRD_IPGRE: + return ipv6_ipgre_mc_map(addr, dev->broadcast, buf); default: if (dir) { memcpy(buf, dev->broadcast, dev->addr_len);
My commit 6d55cb91a0020ac0 (gre: fix hard header destination address checking) broke multicast. The reason is that ip_gre used to get ipgre_header() calls with zero destination if we have NOARP or multicast destination. Instead the actual target was decided at ipgre_tunnel_xmit() time based on per-protocol dissection. Instead of allowing the "abuse" of ->header() calls with invalid destination, this creates multicast mappings for ip_gre. This also fixes "ip neigh show nud noarp" to display the proper multicast mappings used by the gre device. Reported-by: Doug Kehn <rdkehn@yahoo.com> Signed-off-by: Timo Teräs <timo.teras@iki.fi> --- Compile tested only. Doug tested IPv4 side with the earlier patch. The IPv6 side needs a review. I'm not sure if mapped IPv4 multicast addresses are intrepreted as multicast addresses by ndisc code or if we could map real IPv6 multicast addresses to IPv4 multicast addresses. include/net/if_inet6.h | 16 ++++++++++++++++ include/net/ip.h | 8 ++++++++ net/ipv4/arp.c | 3 +++ net/ipv6/ndisc.c | 2 ++ 4 files changed, 29 insertions(+), 0 deletions(-)