Re: PATCH: duplicate IP detection (new version)

Marc Merlin (marc_news@merlins.org)
Wed, 27 Oct 1999 02:25:57 -0700


[Alan, Dave, others, tell me whether you'd consider including the new
version of my patch (net_ratelimit + from MAC check) or whether you agree
with Alexey, and I'll then stop submitting the patch. The new version
outputs:

Uh Oh, MAC address 00:A0:C9:EE:9C:8A claims to have our IP addresses (192.168.205.9) (duplicate IP conflict likely)

Uh Oh, I received an ARP packet claiming to be from our MAC address 00:A0:CC:3C:40:DB, but with an IP I don't own (192.168.205.1). Someone has apparently stolen our MAC address

We either got one of our ARP packets back because of a bad switch or something similar, or some machine is using our MAC address 00:A0:CC:3C:40:DB and our IP address 192.168.205.9

]

On dim, oct 17, 1999 at 11:22:07 +0400, kuznet@ms2.inr.ac.ru wrote:

Sorry for answering late, it turns out that my day job has been keeping me
busy at night also :-)

For people who forgot (or didn't see) the original message, the discussion
is here:
http://www.mail-archive.com/linux-kernel%40vger.rutgers.edu/msg85483.html
In short, all my patch does is printk warnings, it does _not_ disable the
interface (that would be bad)
The new patch is attached at the end of the message.

> I understand this. Please, understand me correctly too: you can improve
> this patch so that it will be valid, but you have no reasons to make
> this task in kernel.

Actually, on a low powered 386 (with little memory) doing network
monitoring, the overhead of running some user level program that looks at
all the packets in non promiscuous mode is not negligible. The load incurred
on my machine is much greater than the 10 line kernel patch I proposed (and
I'm not even mentionning memory usage). I happen to be running such 386
systems.

Lots of things can be ripped out the kernel and done in user space. For some
of them, doing so makes the task noticeably slower, and in some cases (mine
for instance), the additional memory needed is much greater (a couple
hundred bytes of kernel code vs tens of KB of user space memory)
The cost from putting things in user space makes sense when the kernel code
would be big, complex and has good chances of making it more unstable
(example, Xwindow), but I'm not sure I buy the argument that every little
thing should be run in user space, when a better equivalent can be done in
only a few lines of kernel code.

I mean, if we go this way, we can also rip let's say ARP out, and have it
run in user space, and yet it's in the kernel...

> > (arpwatch, but it works in promiscuous mode)
>
> Well, then improve it! Use PF_PACKET, LSF. They were made exaclty
> to avoid making in kernel simple tasks, which can be made in user space.

I did realize from the beginning that you could achieve similar results
(although at greater cost) in user space, but I believe that for this
specific task, it's the wrong way to go. My patch works, and it's already
solving my problem better than what you propose, so I have no incentive to
write a user space version, sorry :-)
(VA Linux Systems is now including my patch in their standard kernels, and
it fits our needs just fine)

A few comments about the patch here:
- It uses net_ratelimit, but yet I can get the kernel to output more than
one message every 5 sec. I have no idea why, comments are welcome.
- I won't be upset if people want enable IMAYHAVEABROKENNETWORK. I've never
gotten my own ARP packets back, but if I were to, I'd like the patch to
tell me, even if I choose to comment the messages out later.
I however with a suggestion from Wolf: I'd like at least one report from
someone who tells me that he has a non fixable network that does send
packets back before I make this a fully configurable option.

----------------------------------------------------------------------------
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 Wed Oct 27 01:40:38 1999
@@ -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 (99/10/11)
*/

/* RFC1122 Status:
@@ -118,6 +120,8 @@

#include <asm/system.h>
#include <asm/uaccess.h>
+
+#undef IMAYHAVEABROKENNETWORK

/*
* Interface to generic neighbour cache.
@@ -126,6 +130,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 =
{
@@ -606,7 +611,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 +659,53 @@
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) {
+#ifndef IMAYHAVEABROKENNETWORK
+/* If you ever get this warning and no one stole your MAC address (i.e. you
+ * have some odd network that sends your packets back to you, you can disable
+ * this warning). Please send me Email to let me know that such a configuration
+ * does exist -- Marc <marcsoft@merlins.org) */
+ printk(KERN_WARNING "We either got one of our ARP packets back because of a bad switch or something similar, 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) {

@@ -946,21 +998,61 @@
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;
+
+ /* I'd get great pleasure deleting
+ this ugly code. Let's output it in hexadecimal format.
+ "arp" utility will eventually repaired --ANK
+ This is also used for outputting IP/Mac conflicts, but if Alexey
+ wants to change the output in /proc, it can also be changed for
+ warning printks -- Marc
+ */
+#if 1 /* UGLY CODE */
+#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<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
+#else
+ if (addr_len) {
+ int j;
+ for (j=0; j < addr_len; j++)
+ sprintf(hbuffer+2*j, "%02x", sha[j]);
+ } else
+ sprintf(hbuffer, "0");
+#endif
+ return hbuffer;
+}
+
/*
* 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)
{
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");

@@ -979,44 +1071,12 @@
if (!(n->nud_state&~NUD_NOARP))
continue;

- /* I'd get great pleasure deleting
- this ugly code. Let's output it in hexadecimal format.
- "arp" utility will eventually repaired --ANK
- */
-#if 1 /* UGLY CODE */
-/*
- * Convert hardware address to XX:XX:XX:XX ... form.
- */
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
- if (hatype == ARPHRD_AX25 || hatype == ARPHRD_NETROM)
- strcpy(hbuffer,ax2asc((ax25_address *)n->ha));
- 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
-#else
- if ((neigh->nud_state&NUD_VALID) && dev->addr_len) {
- int j;
- for (j=0; j < dev->addr_len; j++)
- sprintf(hbuffer+2*j, "%02x", neigh->ha[j]);
- } else
- sprintf(hbuffer, "0");
-#endif
-
size = sprintf(buffer+len,
"%-17s0x%-10x0x%-10x%s",
in_ntoa(*(u32*)n->primary_key),
hatype,
arp_state_to_flags(n),
- hbuffer);
+ mac2asc(n->ha,dev->addr_len));
size += sprintf(buffer+len+size,
" %-17s %s\n",
"*", dev->name);
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 27 01:02:46 1999
@@ -1366,6 +1366,14 @@
S: 80220-320 Curitiba - Parana
S: Brazil

+N: Marc Merlin
+E: marcsoft@merlins.org
+E: merlin@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: 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
----------------------------------------------------------------------------

Marc

-- 
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/