[patch] 2.4 version of my duplicate IP and MAC detection patch

From: Marc MERLIN (marc@merlins.org)
Date: Thu Sep 21 2000 - 18:09:41 EST


I updated my duplicate IP detection patch to work with 2.4.

I announced the 2.2 version here last year, and several people expressed
interest in it, but it never made it into the kernel unfortunately. I asked
a few times and eventually gave up as I didn't want to appear overly pushy
and it got included in the kernels that I use (kernels from VA).

I didn't receive any negative comments, except for Alexey who believed the
check should be done in user space.

The patches (2.2/2.4) and discussion can be found here:
http://marc.merlins.org/linux/arppatch/

Here are two excerpts:
----------------------------------------------------------------------------
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 in a while.
The big plus of this approach is that it's passive

It will get your system to output this:
Uh Oh, MAC address 00:A0:C9:EE:9C:8A claims to have our IP addresses
(192.168.205.9) (duplicate IP conflict likely)
or this:
Uh Oh, I received an ARP packet claiming to be from our MAC address
00:80:C8:47:37:72, but with an IP I don't own (192.168.205.1). Someone has
apparently stolen our MAC address
----------------------------------------------------------------------------

----------------------------------------------------------------------------
But then why not write the whole thing in user space?

Well, the line has to be drawn somewhere... The whole IP stack could be in
user space if we wanted... In this case, the actual added code (I'm not
talking about the existing code which I turned into a function) is about 20
lines, it's trivial and it uses much less resources on a slow machine (386)
than a user space solution which forces a context switches, system calls,
and memory for that user process.
Also, not that others are always right, but do you know any OS that does
duplicate IP checking by inspecting ARP requests in user space?
----------------------------------------------------------------------------

I'm attaching the 2.4 version which I'd really like to see included in the
main tree. While I don't see a good reason to disable this, if what it takes
is a config option, experimental or not, disabled by default or not (I'd
rather have it non experimental since it's a year old, and enabled by
default, but I'll settle), I'll do what it takes.

I'm attaching the 2.4 version and you can find the 2.2 version, as well as
more info on my page:
http://marc.merlins.org/linux/arppatch/

Thanks,
Marc

diff -urN linux-2.2.4-test5/net/ipv4/arp.c linux-2.2.4-test5-detectarpdupe/net/ipv4/arp.c
--- linux-2.2.4-test5/net/ipv4/arp.c Fri Jul 21 21:54:29 2000
+++ linux-2.2.4-test5-detectarpdupe/net/ipv4/arp.c Sun Sep 17 19:19:49 2000
@@ -65,6 +65,8 @@
  * 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 and MAC address
+ * detection (2000/09/17)
  */
 
 /* RFC1122 Status:
@@ -121,6 +123,8 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
+
+#undef IDONTRECEIVEMYOWNPACKETSBACK
 
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 static char *ax2asc2(ax25_address *a, char *buf);
@@ -135,6 +139,7 @@
 static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb);
 static void arp_error_report(struct neighbour *neigh, struct sk_buff *skb);
 static void parp_redo(struct sk_buff *skb);
+static char *mac2asc(unsigned char *sha, unsigned char addr_len);
 
 static struct neigh_ops arp_generic_ops =
 {
@@ -716,6 +721,55 @@
                 goto out;
         }
 
+ if (!memcmp(sha,dev->dev_addr,dev->addr_len))
+ {
+ char ourip=0;
+ struct in_device *idev=dev->ip_ptr;
+ struct in_ifaddr *adlist=idev->ifa_list;
+
+ while (adlist != NULL)
+ {
+ if (adlist->ifa_address == sip) {
+
+ ourip=1;
+ break;
+ }
+ adlist=adlist->ifa_next;
+ }
+
+ if (net_ratelimit()) {
+ if (ourip) {
+#ifdef IDONTRECEIVEMYOWNPACKETSBACK
+/* This is an attempt at detecting that someone stole your MAC and your IP, but
+ * in some network configurations and with some switches, you will get your
+ * own packets back, so this warning would be triggered by error for too many
+ * people.
+ * It's disabled by default but I have left it there in case it's useful to
+ * someone -- Marc <marcsoft@merlins.org> */
+ printk(KERN_WARNING "We either got one of our ARP packets back because of a switch or the network configuration, or some machine is using our MAC address %s and our IP address %s\n",mac2asc(sha,dev->addr_len),in_ntoa(sip));
+#endif
+ } else {
+ printk(KERN_WARNING "Uh Oh, I received an ARP packet claiming to be from our MAC address %s, but with an IP I don't own (%s). Someone has apparently stolen our MAC address\n",mac2asc(sha,dev->addr_len),in_ntoa(sip));
+ }
+ }
+ }
+ else 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) {
+
+ if (net_ratelimit())
+ printk (KERN_WARNING "Uh Oh, MAC address %s claims to have our IP addresses (%s) (duplicate IP conflict likely)\n", mac2asc(sha,dev->addr_len), 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) {
 
@@ -1009,22 +1063,51 @@
         return err;
 }
 
+
+
+#define HBUFFERLEN 30
+/*
+ * Convert Mac Address to ASCII
+ */
+char *mac2asc(unsigned char *sha, unsigned char addr_len) {
+ static 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)
+ ax2asc2((ax25_address *)sha, hbuffer);
+ else {
+#endif
+ for (k=0,j=0;k<HBUFFERLEN-3 && j<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
+
+ return hbuffer;
+}
+
+
 /*
  * Write the contents of the ARP cache to a PROCfs file.
  */
 #ifndef CONFIG_PROC_FS
 static int arp_get_info(char *buffer, char **start, off_t offset, int length) { return 0; }
 #else
-#define HBUFFERLEN 30
+
 
 static int arp_get_info(char *buffer, char **start, off_t offset, int length)
 {
         int len=0;
         off_t pos=0;
         int size;
- char hbuffer[HBUFFERLEN];
- int i,j,k;
- const char hexbuf[] = "0123456789ABCDEF";
+ int i;
 
         size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n");
 
@@ -1044,24 +1127,6 @@
 
                         read_lock(&n->lock);
 
-/*
- * Convert hardware address to XX:XX:XX:XX ... form.
- */
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
- ax2asc2((ax25_address *)n->ha, hbuffer);
- else {
-#endif
- for (k=0,j=0;k<HBUFFERLEN-3 && j<dev->addr_len;j++) {
- hbuffer[k++]=hexbuf[(n->ha[j]>>4)&15 ];
- hbuffer[k++]=hexbuf[n->ha[j]&15 ];
- hbuffer[k++]=':';
- }
- hbuffer[--k]=0;
-
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- }
-#endif
 
                         {
                                 char tbuf[16];
@@ -1071,7 +1136,7 @@
                                         tbuf,
                                         hatype,
                                         arp_state_to_flags(n),
- hbuffer);
+ mac2asc(n->ha,dev->addr_len));
 
                                 size += sprintf(buffer+len+size,
                                          " %-8s %s\n",
diff -urN linux-2.2.4-test5/CREDITS linux-2.2.4-test5-detectarpdupe/CREDITS
--- linux-2.2.4-test5/CREDITS Sat Jul 29 15:58:05 2000
+++ linux-2.2.4-test5-detectarpdupe/CREDITS Sun Sep 17 17:17:19 2000
@@ -1730,6 +1730,14 @@
 S: 80050-430 - Curitiba - Paraná
 S: Brazil
 
+N: Marc Merlin
+E: marcsoft@merlins.org
+E: marc_bts@valinux.com
+D: Passive duplicate IP and MAC address 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: Sunnyvale, 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.kernel.org
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sat Sep 23 2000 - 21:00:25 EST