patch-2.1.9 linux/net/ipv6/addrconf.c

Next file: linux/net/ipv6/datagram.c
Previous file: linux/net/ipv4/tcp_timer.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.8/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
@@ -492,6 +492,7 @@
 	else
 	{
 		rtmsg.rtmsg_prefixlen = 128;
+		rtmsg.rtmsg_dst.s6_addr32[0] = __constant_htonl(0xfe800000);
 		rtmsg.rtmsg_dst.s6_addr32[3] = dev->pa_dstaddr;
 		rtmsg.rtmsg_metric = 1;
 		rtmsg.rtmsg_flags = RTF_HOST|RTF_UP;
@@ -773,6 +774,62 @@
 
 }
 
+static void addrconf_ifdown(struct device *dev)
+{
+	struct inet6_dev *idev, **bidev;
+	struct inet6_ifaddr *ifa, **bifa;
+	int i;
+
+	start_bh_atomic();
+
+	bidev = &inet6_dev_lst;
+
+	for (idev = inet6_dev_lst; idev; idev = idev->next)
+	{
+		if (idev->dev == dev)
+		{
+			*bidev = idev->next;
+			break;
+		}
+		bidev = &idev;
+	}
+
+	if (idev == NULL)
+	{
+		printk(KERN_DEBUG "addrconf_ifdown: device not found\n"); 
+		return;
+	}
+	
+	/*
+	 *	FIXME: clear multicast group membership
+	 */
+
+	/*
+	 *	clean addr_list
+	 */
+
+	for (i=0; i<16; i++)
+	{
+		bifa = &inet6_addr_lst[i];
+		
+		for (ifa=inet6_addr_lst[i]; ifa; )
+		{
+			if (ifa->idev == idev)
+			{
+				*bifa = ifa->lst_next;
+				kfree(ifa);
+				ifa = *bifa;
+				continue;
+			}
+			bifa = &ifa;
+			ifa = ifa->lst_next;
+		}
+	}
+
+	kfree(idev);
+	end_bh_atomic();
+}
+
 /*
  *	Set destination address.
  *	Special case for SIT interfaces where we create a new "virtual"
@@ -848,6 +905,8 @@
 	if (ifp == NULL)
 		return -ENOMEM;
 
+	ifp->prefix_len = 128;
+
 	if (dev->flags & IFF_MULTICAST)
 	{
 		struct in6_addr maddr;
@@ -874,24 +933,26 @@
 	struct inet6_ifaddr * ifp;
 	struct in6_addr addr;
 	struct device *dev;
-	int flag;
+	int scope;
 
 	memset(&addr, 0, sizeof(struct in6_addr));
 
 	if (idev->dev->pa_dstaddr)
 	{
 		addr.s6_addr32[0] = __constant_htonl(0xfe800000);
-		flag = IFA_LINK;
+		scope = IFA_LINK;
 	}
 	else
 	{
-		flag = IFA_GLOBAL | IPV6_ADDR_COMPATv4;
+		scope = IPV6_ADDR_COMPATv4;
 	}
 
         for (dev = dev_base; dev != NULL; dev = dev->next) 
         {
 		if (dev->family == AF_INET && (dev->flags & IFF_UP))
 		{
+			int flag = scope;
+			
 			addr.s6_addr32[3] = dev->pa_addr;
 
 			if (dev->flags & IFF_LOOPBACK)
@@ -899,7 +960,7 @@
 				if (idev->dev->pa_dstaddr)
 					continue;
 				
-				flag = IFA_HOST | IPV6_ADDR_COMPATv4;
+				flag |= IFA_HOST;
 			}
 
 			ifp = ipv6_add_addr(idev, &addr, flag);
@@ -963,6 +1024,8 @@
 		 *	Remove all addresses from this interface
 		 *	and take the interface out of the list.
 		 */
+		addrconf_ifdown(dev);
+		rt6_ifdown(dev);
 		rt6_sndmsg(RTMSG_NEWDEVICE, NULL, NULL, 0, 0, dev->name, 0);
 
 		break;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov