diff options
-rw-r--r-- | include/net/if_inet6.h | 16 | ||||
-rw-r--r-- | include/net/ip.h | 8 | ||||
-rw-r--r-- | net/ipv4/arp.c | 3 | ||||
-rw-r--r-- | 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 04977eefb0ee..fccc2180c61b 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, | |||
286 | buf[9] = broadcast[9]; | 286 | buf[9] = broadcast[9]; |
287 | memcpy(buf + 10, addr->s6_addr + 6, 10); | 287 | memcpy(buf + 10, addr->s6_addr + 6, 10); |
288 | } | 288 | } |
289 | |||
290 | static inline int ipv6_ipgre_mc_map(const struct in6_addr *addr, | ||
291 | const unsigned char *broadcast, char *buf) | ||
292 | { | ||
293 | if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) { | ||
294 | memcpy(buf, broadcast, 4); | ||
295 | } else { | ||
296 | /* v4mapped? */ | ||
297 | if ((addr->s6_addr32[0] | addr->s6_addr32[1] | | ||
298 | (addr->s6_addr32[2] ^ htonl(0x0000ffff))) != 0) | ||
299 | return -EINVAL; | ||
300 | memcpy(buf, &addr->s6_addr32[3], 4); | ||
301 | } | ||
302 | return 0; | ||
303 | } | ||
304 | |||
289 | #endif | 305 | #endif |
290 | #endif | 306 | #endif |
diff --git a/include/net/ip.h b/include/net/ip.h index a4f631108c54..7c416583b710 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 | |||
339 | buf[16] = addr & 0x0f; | 339 | buf[16] = addr & 0x0f; |
340 | } | 340 | } |
341 | 341 | ||
342 | static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, char *buf) | ||
343 | { | ||
344 | if ((broadcast[0] | broadcast[1] | broadcast[2] | broadcast[3]) != 0) | ||
345 | memcpy(buf, broadcast, 4); | ||
346 | else | ||
347 | memcpy(buf, &naddr, sizeof(naddr)); | ||
348 | } | ||
349 | |||
342 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 350 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
343 | #include <linux/ipv6.h> | 351 | #include <linux/ipv6.h> |
344 | #endif | 352 | #endif |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 090d273d7865..1b74d3b64371 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) | |||
215 | case ARPHRD_INFINIBAND: | 215 | case ARPHRD_INFINIBAND: |
216 | ip_ib_mc_map(addr, dev->broadcast, haddr); | 216 | ip_ib_mc_map(addr, dev->broadcast, haddr); |
217 | return 0; | 217 | return 0; |
218 | case ARPHRD_IPGRE: | ||
219 | ip_ipgre_mc_map(addr, dev->broadcast, haddr); | ||
220 | return 0; | ||
218 | default: | 221 | default: |
219 | if (dir) { | 222 | if (dir) { |
220 | memcpy(haddr, dev->broadcast, dev->addr_len); | 223 | memcpy(haddr, dev->broadcast, dev->addr_len); |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 0e49c9db3c98..92f952d093db 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 | |||
341 | case ARPHRD_INFINIBAND: | 341 | case ARPHRD_INFINIBAND: |
342 | ipv6_ib_mc_map(addr, dev->broadcast, buf); | 342 | ipv6_ib_mc_map(addr, dev->broadcast, buf); |
343 | return 0; | 343 | return 0; |
344 | case ARPHRD_IPGRE: | ||
345 | return ipv6_ipgre_mc_map(addr, dev->broadcast, buf); | ||
344 | default: | 346 | default: |
345 | if (dir) { | 347 | if (dir) { |
346 | memcpy(buf, dev->broadcast, dev->addr_len); | 348 | memcpy(buf, dev->broadcast, dev->addr_len); |