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); |
