[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <360171.1620.qm@web39305.mail.mud.yahoo.com>
Date: Tue, 29 Mar 2011 13:26:02 -0700 (PDT)
From: Doug Kehn <rdkehn@...oo.com>
To: netdev@...r.kernel.org,
Timo Teräs <timo.teras@....fi>
Cc: Timo Teräs <timo.teras@....fi>
Subject: Re: [PATCH] net: gre: provide multicast mappings for ipv4 and ipv6
--- On Tue, 3/29/11, Timo Teräs <timo.teras@....fi> wrote:
> From: Timo Teräs <timo.teras@....fi>
> Subject: [PATCH] net: gre: provide multicast mappings for ipv4 and ipv6
> To: netdev@...r.kernel.org
> Cc: "Doug Kehn" <rdkehn@...oo.com>, "Timo Teräs" <timo.teras@....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@...oo.com>
> Signed-off-by: Timo Teräs <timo.teras@....fi>
Acked-by: Doug Kehn <rdkehn@...oo.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@...r.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@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists