[LWN Logo]

Date:   Wed, 13 Oct 1999 18:11:17 -0700
From:   Marc Merlin <marc_news@merlins.org>
To:     torvalds@transmeta.com, alan@lxorguk.ukuu.org.uk, davem@redhat.com
Subject: PATCH: duplicate IP detection

Short Version:
Attached is a patch to passively detect duplicate IP conflicts. I sent it to
l-k two weeks ago and got feedback  from Rogier Wolff who seemed to like it.
This patch  has been tested with  machines with multiple interfaces,  and is
now being used at VA Linux Systems, and has been included in the standard VA
kernel.

When a conflict is detected, the kernel prints the following:
Uh Oh, MAC address 00:90:27:1D:5F:40 claims to have our IP addresses (10.1.0.142) (duplicate IP conflict likely)

----------------------------------------------------------------------------

Longer Version and discussion:
After wondering  why linux doesn't detect  when someone steals its  IP, just
like Solaris, Irix, and windows to name only a few, do, I decided to write a
kernel patch to fix this.

What does the patch do?
It looks at all the broadcast ARP  requests and checks that the source IP of
the request is different from the  interface's IP. This will catch a machine
that is using your IP and is trying to talk to a machine on your net for the
first time or the first time since a while.

Why only the first time?
Once the first ARP request gets an  answer, the MAC address is cached and at
least some  versions of linux will  freshen their cache by  doing a directed
ARP request  (not broadcast) to ask  the remote machine if  it's still using
that IP. You will not see those ARP requests as they are not broadcast.

But you could put the interface in promiscuous mode
You don't  want to  force people to  turn on promiscuous  mode on  all their
interfaces. It will  load up machines  with interrupts, and make  some buggy
NICs unhappy (among other things)

Is it correct  that you will also miss  a machine that has your  IP on let's
say eth0:0, or that just put your IP with a different MAC address in its ARP
cache and is also answering ARP queries for your IP?
Yes

Why not send ARP queries with your IP?
That's what I originally thought about  doing. I wanted to send an ARP query
for my  IP each  time I answered  such a  query, and make  sure no  one else
answered that query.
This would  have been a  big mistake however because  it will create  an ARP
loop between two machines using the same IP and the patch that would do that
extra ARP query. Rogier also pointed out to  me that he didn't like the idea
of linux sending extra ARP packets when a passive solution exists.

So what else can you do?
Well, while the patch below will  actually catch most of everyday conflicts,
an added security would be to have a small daemon that does an ARP query for
your IP every so often and makes sure there is no answer.
Because this can be implemented in user space, it shouldn't be in the kernel

----------------------------------------------------------------------------

Patch:
This is against 2.2.12. 
I've  looked at  2.3.21 and  it needs  a few  simple modifications  to apply
properly. While I don't run  2.3.x, if you tell me you'll  include it, I can
fix the patch and find some machine to  boot 2.3.x on to make sure the patch
still works.

----------------------------------------------------------------------------
diff -urN linux-2.2.12/net/ipv4/arp.c linux-arp/net/ipv4/arp.c
--- linux-2.2.12/net/ipv4/arp.c	Mon Aug  9 12:04:41 1999
+++ linux-arp/net/ipv4/arp.c	Tue Oct 12 09:26:57 1999
@@ -65,6 +65,7 @@
  *					clean up the APFDDI & gen. FDDI bits.
  *		Alexey Kuznetsov:	new arp state machine;
  *					now it is in net/core/neighbour.c.
+ *		Marc Merlin     :	Added duplicate IP detection (99/10/11)
  */
 
 /* RFC1122 Status:
@@ -119,6 +120,9 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#define HBUFFERLEN 30
+
+
 /*
  *	Interface to generic neighbour cache.
  */
@@ -606,7 +610,7 @@
 #endif
 	}
 
-	/* Undertsand only these message types */
+	/* Understand only these message types */
 
 	if (arp->ar_op != __constant_htons(ARPOP_REPLY) &&
 	    arp->ar_op != __constant_htons(ARPOP_REQUEST))
@@ -654,6 +658,42 @@
 		goto out;
 	}
 
+	if (arp->ar_op == __constant_htons(ARPOP_REQUEST)) {
+		struct in_device *idev=dev->ip_ptr;
+		struct in_ifaddr *adlist=idev->ifa_list;
+
+		while (adlist != NULL)
+		{
+		    if (adlist->ifa_address == sip) {
+			char hbuffer[HBUFFERLEN];
+			const char hexbuf[] =  "0123456789ABCDEF";
+			int j,k;
+
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+			if (hatype == ARPHRD_AX25 || 
+					    hatype == ARPHRD_NETROM)
+			     strcpy(hbuffer,ax2asc((ax25_address *)sha));
+			else {
+#endif
+			for (k=0,j=0;k<HBUFFERLEN-3 && j<dev->addr_len;j++) {
+			    hbuffer[k++]=hexbuf[(sha[j]>>4)&15 ];
+			    hbuffer[k++]=hexbuf[sha[j]&15     ];
+			    hbuffer[k++]=':';
+			}
+			hbuffer[--k]=0;
+	
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+			}
+#endif
+
+			printk (KERN_WARNING "Uh Oh, MAC address %s claims to have our IP addresses (%s) (duplicate IP conflict likely)\n", hbuffer, in_ntoa(sip));
+			break;
+		    }
+		    adlist=adlist->ifa_next;
+		}
+	}
+
+	
 	if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
 	    ip_route_input(skb, tip, sip, 0, dev) == 0) {
 
@@ -950,8 +990,6 @@
  *	Write the contents of the ARP cache to a PROCfs file.
  */
 #ifdef CONFIG_PROC_FS
-
-#define HBUFFERLEN 30
 
 int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
diff -urN linux-2.2.12/CREDITS linux-arp/CREDITS
--- linux-2.2.12/CREDITS	Wed Aug 25 17:29:45 1999
+++ linux-arp/CREDITS	Wed Oct 13 15:57:22 1999
@@ -1366,6 +1366,13 @@
 S: 80220-320 Curitiba - Parana
 S: Brazil
 
+N: Marc Merlin
+E: marcsoft@merlins.org
+D: Passive duplicate IP detection through ARP packet watching
+W: http://marc.merlins.org/
+P: 1024/763BE901 A1 9F 94 B7 78 01 E5 21  21 E0 F1 2E A2 85 E2 77
+S: Mountain View, California, USA
+
 N: Michael Meskes
 E: meskes@debian.org
 P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
----------------------------------------------------------------------------

-- 
Microsoft is to software what McDonalds is to gourmet cooking
 
Home page: http://marc.merlins.org/ (friendly to non IE browsers)
Finger marc_f@merlins.org for PGP key and other contact information

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/