[resend] Problem with IP address deletion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Dave,

Long time back, I had posted about an issue with ip address deletion.

Summary of the problem :

I added the dummy device addresses in the following sequence:

ip addr add 10.3.3.3/8 dev dummy0
ip addr add 10.3.3.3/32 dev dummy0

ifconfig dummy0 10.3.3.3/32 down
ip addr show dummy0
2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noqueue
   link/ether 8a:d8:bd:26:14:ab brd ff:ff:ff:ff:ff:ff
   inet 10.3.3.3/32 scope global dummy0

The prefixes doesn't matter. Original post can be found here -> http://www.uwsg.iu.edu/hypermail/linux/net/0503.2/0000.html

Thomas Graf had pointed to a patch which was queued by you, which could fix the issue -> http://www.uwsg.iu.edu/hypermail/linux/net/0503.2/0002.html ( The patch has been moved from the link given in the mail. I have attached it here for convenience. )

But, the patch hasn't gone in and I am still seeing the problem on 2.6.19 :(.. I have tested this patch on 2.6.19 and if fixes the issue there.

Could you please push this patch ?


Thanks,

Suzuki






diff -Nru linux-2.6.11-bk3.orig/include/linux/inetdevice.h linux-2.6.11-bk3/include/linux/inetdevice.h
--- linux-2.6.11-bk3.orig/include/linux/inetdevice.h	2005-03-08 13:10:37.000000000 +0100
+++ linux-2.6.11-bk3/include/linux/inetdevice.h	2005-03-08 16:29:27.000000000 +0100
@@ -7,6 +7,7 @@
 #include <linux/netdevice.h>
 #include <linux/rcupdate.h>
 #include <linux/timer.h>
+#include <linux/rtnetlink.h>
 
 struct ipv4_devconf
 {
@@ -131,6 +132,25 @@
 	return 0;
 }
 
+static inline int inet_ifa_match_local_prefixlen(struct ifaddrmsg *ifm,
+						 struct in_ifaddr *ifa)
+{
+	int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
+
+	/*
+	 * Since the prefix length hasn't been taken into account in
+	 * previous kernel versions, parts of the userspace rely on the fact
+	 * that the deletion of an address without specifying a prefix works.
+	 * We cannot break this and thus a prefix length of 32 still represents
+	 * a wildcard if no exact match is requested.
+	 */
+	if (real_prefixlen != 32 || ifm->ifa_prefixlen & IFA_PREFIX_EXACT_DEL)
+		if (real_prefixlen != ifa->ifa_prefixlen)
+			return 0;
+
+	return 1;
+}
+
 #define for_primary_ifa(in_dev)	{ struct in_ifaddr *ifa; \
   for (ifa = (in_dev)->ifa_list; ifa && !(ifa->ifa_flags&IFA_F_SECONDARY); ifa = ifa->ifa_next)
 
diff -Nru linux-2.6.11-bk3.orig/include/linux/rtnetlink.h linux-2.6.11-bk3/include/linux/rtnetlink.h
--- linux-2.6.11-bk3.orig/include/linux/rtnetlink.h	2005-03-08 16:28:04.000000000 +0100
+++ linux-2.6.11-bk3/include/linux/rtnetlink.h	2005-03-08 14:17:49.000000000 +0100
@@ -396,6 +396,19 @@
 
 #define IFA_MAX (__IFA_MAX - 1)
 
+/*
+ * Quirk for IPv4 address deletion to allow exact deletion of equal
+ * addresses varying only in prefix length. A explicit exact comparison
+ * of the prefix length will only be done if IFA_PREFIX_EXACT_DEL is
+ * ORed to ifa_prefixlen.
+ *
+ * Note: This special treatment is only understood while deleting
+ *       addresses and will lead to unexpected behaviour if used
+ *       otherwise.
+ */
+#define IFA_PREFIX_EXACT_DEL	0x40
+#define IFA_REAL_DEL_PREFIX(l)	((l) & 0x3f)
+
 /* ifa_flags */
 
 #define IFA_F_SECONDARY		0x01
diff -Nru linux-2.6.11-bk3.orig/net/ipv4/devinet.c linux-2.6.11-bk3/net/ipv4/devinet.c
--- linux-2.6.11-bk3.orig/net/ipv4/devinet.c	2005-03-08 13:10:44.000000000 +0100
+++ linux-2.6.11-bk3/net/ipv4/devinet.c	2005-03-08 16:29:49.000000000 +0100
@@ -389,6 +389,7 @@
 	struct in_device *in_dev;
 	struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
 	struct in_ifaddr *ifa, **ifap;
+	int real_prefixlen = IFA_REAL_DEL_PREFIX(ifm->ifa_prefixlen);
 
 	ASSERT_RTNL();
 
@@ -399,12 +400,13 @@
 	for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 	     ifap = &ifa->ifa_next) {
 		if ((rta[IFA_LOCAL - 1] &&
+		    (!inet_ifa_match_local_prefixlen(ifm, ifa) ||
 		     memcmp(RTA_DATA(rta[IFA_LOCAL - 1]),
-			    &ifa->ifa_local, 4)) ||
+			    &ifa->ifa_local, 4))) ||
 		    (rta[IFA_LABEL - 1] &&
 		     rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||
 		    (rta[IFA_ADDRESS - 1] &&
-		     (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
+		     (real_prefixlen != ifa->ifa_prefixlen ||
 		      !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
 			      	      ifa))))
 			continue;

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux