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 Fri Sep 22 00:51:01 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/22) */ /* RFC1122 Status: @@ -121,6 +123,8 @@ #include #include + +#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,43 @@ goto out; } + /* The patch initially checked for duplicate IPs, but it's easy to check + * for duplicate MACs at the same time too. Let's also not even check + * anything if net_ratelimit wouldn't allow us to printk -- Marc */ + if (net_ratelimit()) { + if (!memcmp(sha,dev->dev_addr,dev->addr_len)) { + if (ip_route_input(skb, sip, tip, 0, dev) == 0) { + rt = (struct rtable*)skb->dst; + addr_type = rt->rt_type; + + if (addr_type == RTN_LOCAL) { +#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 */ + 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 + goto gotdupemac; + } + } + 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)) { + if (ip_route_input(skb, sip, tip, 0, dev) == 0) { + rt = (struct rtable*)skb->dst; + addr_type = rt->rt_type; + + if (addr_type == RTN_LOCAL) { + 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)); + } + } + } + } +gotdupemac: + if (arp->ar_op == __constant_htons(ARPOP_REQUEST) && ip_route_input(skb, tip, sip, 0, dev) == 0) { @@ -1009,22 +1051,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>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 +1115,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;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 { char tbuf[16]; @@ -1071,7 +1124,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