--- linux-2.6.14.orig/arp.c Fri Oct 28 10:02:08 2005 +++ linux-2.6.14.dupedetect/arp.c Sat Jan 21 21:22:30 2006 @@ -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) * Krzysztof Halasa: Added Frame Relay ARP support. * Arnaldo C. Melo : convert /proc/net/arp to seq_file * Shmulik Hen: Split arp_send to arp_create and @@ -123,6 +125,9 @@ #include #include + +#undef IDONTRECEIVEMYOWNPACKETSBACK +#define HBUFFERLEN 30 #include @@ -134,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(char *, unsigned char *sha, unsigned char addr_len); static struct neigh_ops arp_generic_ops = { .family = AF_INET, @@ -202,6 +208,21 @@ .gc_thresh3 = 1024, }; +/* + * Display an IP address in readable format. + */ + +char *in_ntoa(__u32 in) +{ + static char buff[18]; + char *p; + + p = (char *) ∈ + sprintf(buff, "%d.%d.%d.%d", + (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255)); + return(buff); +} + int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir) { switch (dev->type) { @@ -713,6 +734,7 @@ u16 dev_type = dev->type; int addr_type; struct neighbour *n; + char hbuffer[HBUFFERLEN]; /* arp_rcv below verifies the ARP header and verifies the device * is ARP'able. @@ -821,6 +843,46 @@ * cache. */ + /* The patch initially checked for duplicate IPs, but it's easy to check + * for duplicate MACs at the same time too. -- Marc */ + 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 */ + if (net_ratelimit()) { + 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(hbuffer,sha,dev->addr_len),in_ntoa(sip)); + } +#endif + goto gotdupemac; + } + } + if (net_ratelimit()) { + 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(hbuffer,sha,dev->addr_len),in_ntoa(sip)); + } + } + else if (arp->ar_op == 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) { + if (net_ratelimit()) { + printk (KERN_WARNING "Uh Oh, MAC address %s claims to have our IP address (%s) (duplicate IP conflict likely)\n", mac2asc(hbuffer,sha,dev->addr_len), in_ntoa(sip)); + } + } + } + } +gotdupemac: + /* Special case: IPv4 duplicate address detection packet (RFC2131) */ if (sip == 0) { if (arp->ar_op == htons(ARPOP_REQUEST) && @@ -1285,37 +1347,47 @@ } #endif /* CONFIG_AX25 */ -#define HBUFFERLEN 30 +/* + * Convert Mac Address to ASCII + * Use a buffer[HBUFFERLEN] for buffer + */ +char *mac2asc(char *buffer, unsigned char *ha, unsigned char addr_len) { + 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 *)ha, buffer); + else { +#endif + for (k=0,j=0;k>4)&15 ]; + buffer[k++]=hexbuf[ha[j]&15 ]; + buffer[k++]=':'; + } + buffer[--k]=0; + +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) + } +#endif + return buffer; +} + + static void arp_format_neigh_entry(struct seq_file *seq, struct neighbour *n) { char hbuffer[HBUFFERLEN]; - const char hexbuf[] = "0123456789ABCDEF"; - int k, j; char tbuf[16]; struct net_device *dev = n->dev; int hatype = dev->type; 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 sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key)); seq_printf(seq, "%-16s 0x%-10x0x%-10x%s * %s\n", - tbuf, hatype, arp_state_to_flags(n), hbuffer, dev->name); + tbuf, hatype, arp_state_to_flags(n), + mac2asc(hbuffer,n->ha,dev->addr_len), dev->name); read_unlock(&n->lock); } --- linux-2.6.14.orig/CREDITS Fri Oct 28 10:02:08 2005 +++ linux-2.6.14.dupedetect/CREDITS Sat Jan 21 21:22:30 2006 @@ -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