patch-2.4.21 linux-2.4.21/net/ipv6/mcast.c

Next file: linux-2.4.21/net/ipv6/ndisc.c
Previous file: linux-2.4.21/net/ipv6/ipv6_sockglue.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/net/ipv6/mcast.c linux-2.4.21/net/ipv6/mcast.c
@@ -18,9 +18,14 @@
 /* Changes:
  *
  *	yoshfuji	: fix format of router-alert option
+ *	YOSHIFUJI Hideaki @USAGI:
+ *		Fixed source address for MLD message based on
+ *		<draft-ietf-magma-mld-source-02.txt>.
+ *	YOSHIFUJI Hideaki @USAGI:
+ *		- Ignore Queries for invalid addresses.
+ *		- MLD for link-local addresses.
  */
 
-#define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -405,6 +410,7 @@
 	unsigned long resptime;
 	struct inet6_dev *idev;
 	struct icmp6hdr *hdr;
+	int addr_type;
 
 	if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
 		return -EINVAL;
@@ -420,6 +426,11 @@
 	resptime = (resptime<<10)/(1024000/HZ);
 
 	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);
 
@@ -427,7 +438,7 @@
 		return 0;
 
 	read_lock(&idev->lock);
-	if (ipv6_addr_any(addrp)) {
+	if (addr_type == IPV6_ADDR_ANY) {
 		for (ma = idev->mc_list; ma; ma=ma->next)
 			igmp6_group_queried(ma, resptime);
 	} else {
@@ -451,6 +462,7 @@
 	struct in6_addr *addrp;
 	struct inet6_dev *idev;
 	struct icmp6hdr *hdr;
+	int addr_type;
 
 	/* Our own report looped back. Ignore it. */
 	if (skb->pkt_type == PACKET_LOOPBACK)
@@ -462,7 +474,9 @@
 	hdr = (struct icmp6hdr*) skb->h.raw;
 
 	/* Drop reports with not link local source */
-	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
+	addr_type = ipv6_addr_type(&skb->nh.ipv6h->saddr);
+	if (addr_type != IPV6_ADDR_ANY && 
+	    !(addr_type&IPV6_ADDR_LINKLOCAL))
 		return -EINVAL;
 
 	addrp = (struct in6_addr *) (hdr + 1);
@@ -529,11 +543,11 @@
 	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
-#if MCAST_DEBUG >= 1
-		printk(KERN_DEBUG "igmp6: %s no linklocal address\n",
-		       dev->name);
-#endif
-		goto out;
+		/* <draft-ietf-magma-mld-source-02.txt>:
+		 * use unspecified address as the source address 
+		 * when a valid link-local address is not available.
+		 */
+		memset(&addr_buf, 0, sizeof(addr_buf));
 	}
 
 	ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
@@ -566,11 +580,9 @@
 static void igmp6_join_group(struct ifmcaddr6 *ma)
 {
 	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;
 
 	igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
@@ -591,11 +603,8 @@
 
 static void igmp6_leave_group(struct ifmcaddr6 *ma)
 {
-	int addr_type;
-
-	addr_type = ipv6_addr_type(&ma->mca_addr);
-
-	if ((addr_type & IPV6_ADDR_LINKLOCAL))
+	if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
+	    ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
 		return;
 
 	if (ma->mca_flags & MAF_LAST_REPORTER)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)