Commit 69dda393 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji Committed by David S. Miller

[IPV6]: Several MLD fixes

- Ignore queries for invalid addresses
- MLD for link-local addresses
parent 435712af
...@@ -191,5 +191,21 @@ static inline int ipv6_addr_is_multicast(struct in6_addr *addr) ...@@ -191,5 +191,21 @@ static inline int ipv6_addr_is_multicast(struct in6_addr *addr)
return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000); return (addr->s6_addr32[0] & __constant_htonl(0xFF000000)) == __constant_htonl(0xFF000000);
} }
static inline int ipv6_addr_is_ll_all_nodes(const struct in6_addr *addr)
{
return (addr->s6_addr32[0] == htonl(0xff020000) &&
addr->s6_addr32[1] == 0 &&
addr->s6_addr32[2] == 0 &&
addr->s6_addr32[3] == htonl(0x00000001));
}
static inline int ipv6_addr_is_ll_all_routers(const struct in6_addr *addr)
{
return (addr->s6_addr32[0] == htonl(0xff020000) &&
addr->s6_addr32[1] == 0 &&
addr->s6_addr32[2] == 0 &&
addr->s6_addr32[3] == htonl(0x00000002));
}
#endif #endif
#endif #endif
...@@ -73,6 +73,20 @@ ...@@ -73,6 +73,20 @@
#define IPV6_ADDR_MAPPED 0x1000U #define IPV6_ADDR_MAPPED 0x1000U
#define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */ #define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */
/*
* Addr scopes
*/
#ifdef __KERNEL__
#define IPV6_ADDR_MC_SCOPE(a) \
((a)->s6_addr[1] & 0x0f) /* nonstandard */
#define __IPV6_ADDR_SCOPE_INVALID -1
#endif
#define IPV6_ADDR_SCOPE_NODELOCAL 0x01
#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02
#define IPV6_ADDR_SCOPE_SITELOCAL 0x05
#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08
#define IPV6_ADDR_SCOPE_GLOBAL 0x0e
/* /*
* fragmentation header * fragmentation header
*/ */
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
* YOSHIFUJI Hideaki @USAGI: * YOSHIFUJI Hideaki @USAGI:
* Fixed source address for MLD message based on * Fixed source address for MLD message based on
* <draft-ietf-magma-mld-source-02.txt>. * <draft-ietf-magma-mld-source-02.txt>.
* YOSHIFUJI Hideaki @USAGI:
* - Ignore Queries for invalid addresses.
* - MLD for link-local addresses.
*/ */
#define __NO_VERSION__ #define __NO_VERSION__
...@@ -409,6 +412,7 @@ int igmp6_event_query(struct sk_buff *skb) ...@@ -409,6 +412,7 @@ int igmp6_event_query(struct sk_buff *skb)
unsigned long resptime; unsigned long resptime;
struct inet6_dev *idev; struct inet6_dev *idev;
struct icmp6hdr *hdr; struct icmp6hdr *hdr;
int addr_type;
if (!pskb_may_pull(skb, sizeof(struct in6_addr))) if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
return -EINVAL; return -EINVAL;
...@@ -424,6 +428,11 @@ int igmp6_event_query(struct sk_buff *skb) ...@@ -424,6 +428,11 @@ int igmp6_event_query(struct sk_buff *skb)
resptime = (resptime<<10)/(1024000/HZ); resptime = (resptime<<10)/(1024000/HZ);
addrp = (struct in6_addr *) (hdr + 1); addrp = (struct in6_addr *) (hdr + 1);
addr_type = ipv6_addr_type(addrp);
if (addr_type != IPV6_ADDR_ANY &&
!(addr_type&IPV6_ADDR_MULTICAST))
return -EINVAL;
idev = in6_dev_get(skb->dev); idev = in6_dev_get(skb->dev);
...@@ -431,7 +440,7 @@ int igmp6_event_query(struct sk_buff *skb) ...@@ -431,7 +440,7 @@ int igmp6_event_query(struct sk_buff *skb)
return 0; return 0;
read_lock(&idev->lock); read_lock(&idev->lock);
if (ipv6_addr_any(addrp)) { if (addr_type == IPV6_ADDR_ANY) {
for (ma = idev->mc_list; ma; ma=ma->next) for (ma = idev->mc_list; ma; ma=ma->next)
igmp6_group_queried(ma, resptime); igmp6_group_queried(ma, resptime);
} else { } else {
...@@ -573,11 +582,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -573,11 +582,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
static void igmp6_join_group(struct ifmcaddr6 *ma) static void igmp6_join_group(struct ifmcaddr6 *ma)
{ {
unsigned long delay; unsigned long delay;
int addr_type;
addr_type = ipv6_addr_type(&ma->mca_addr);
if ((addr_type & (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_LOOPBACK))) if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
return; return;
igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT); igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
...@@ -600,9 +607,8 @@ static void igmp6_leave_group(struct ifmcaddr6 *ma) ...@@ -600,9 +607,8 @@ static void igmp6_leave_group(struct ifmcaddr6 *ma)
{ {
int addr_type; int addr_type;
addr_type = ipv6_addr_type(&ma->mca_addr); if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
if ((addr_type & IPV6_ADDR_LINKLOCAL))
return; return;
if (ma->mca_flags & MAF_LAST_REPORTER) if (ma->mca_flags & MAF_LAST_REPORTER)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment