diff -urN linux/net/ipv4/arp.c linux.detectarpdupe/net/ipv4/arp.c --- linux/net/ipv4/arp.c Thu Jul 6 22:05:08 2000 +++ linux-2.2.4-test5-arpdupe/net/ipv4/arp.c Thu Sep 14 09:16:10 2000 @@ -68,6 +68,8 @@ * Krzysztof Halasa: Added Frame Relay ARP support. * Julian Anastasov: "hidden" flag: hide the * interface and don't reply for it + * Marc Merlin : Added duplicate IP and MAC address + * detection (99/10/11) */ /* RFC1122 Status: @@ -121,6 +123,8 @@ #include #include + +#undef IDONTRECEIVEMYOWNPACKETSBACK /* * Interface to generic neighbour cache. @@ -129,6 +133,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 = { @@ -680,6 +685,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 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) { @@ -986,21 +1040,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>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"); @@ -1019,44 +1113,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;kaddr_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/CREDITS linux.detectarpdupe/CREDITS --- linux/CREDITS Wed Aug 30 14:33:24 2000 +++ linux.detectarpdupe/CREDITS Thu Sep 14 09:12:34 2000 @@ -1386,6 +1386,14 @@ S: 80220-320 Curitiba - Parana 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 When you access an NFS server, which has IP aliases, through NAT over UDP, sunrpc in kernel has to make sure to use its IP address, where the client sent a UDP packet, when sending reply back to the client. Otherwise, the reply may not go through NAT. This patch tries to fix this problem.