diff -urN misckernels/linux-2.4.14-lvm1.0.1rc4-ext3/CREDITS linux-2.4.14-lvm1.0.1rc4-ext3-misc/CREDITS --- misckernels/linux-2.4.14-lvm1.0.1rc4-ext3/CREDITS Sun Nov 4 09:31:57 2001 +++ linux-2.4.14-lvm1.0.1rc4-ext3-misc/CREDITS Tue Nov 13 11:15:37 2001 @@ -1984,6 +1984,14 @@ D: DECstation framebuffer drivers S: Germany +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 diff -urN linux-2.4.19/net/ipv4/arp.c linux-2.4.19-grsec-1.9.7rc4-marc1/net/ipv4/arp.c --- linux-2.4.19/net/ipv4/arp.c Fri Aug 2 17:39:46 2002 +++ linux-2.4.19-grsec-1.9.7rc4-marc1/net/ipv4/arp.c Sun Sep 8 08:24:16 2002 @@ -66,6 +66,8 @@ * Alexey Kuznetsov: new arp state machine; * now it is in net/core/neighbour.c. * Krzysztof Halasa: Added Frame Relay ARP support. + * Marc Merlin : Added duplicate IP and MAC address + * detection (2000/09/22) */ #include @@ -111,6 +113,9 @@ #include #include + +#undef IDONTRECEIVEMYOWNPACKETSBACK +#define HBUFFERLEN 30 #include @@ -122,6 +127,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, @@ -190,6 +196,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) { @@ -616,6 +637,7 @@ u16 dev_type = dev->type; int addr_type; struct neighbour *n; + char hbuffer[HBUFFERLEN]; /* arp_rcv below verifies the ARP header, verifies the device * is ARP'able, and linearizes the SKB (if needed). @@ -760,6 +782,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(hbuffer,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(hbuffer,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(hbuffer,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) { @@ -1096,16 +1155,44 @@ #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) static char *ax2asc2(ax25_address *a, char *buf); #endif -#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 int arp_get_info(char *buffer, char **start, off_t offset, int length) { int len=0; off_t pos=0; int size; + int i; char hbuffer[HBUFFERLEN]; - int i,j,k; - const char hexbuf[] = "0123456789ABCDEF"; size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n"); @@ -1125,24 +1212,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]; @@ -1152,7 +1221,7 @@ tbuf, hatype, arp_state_to_flags(n), - hbuffer, + mac2asc(hbuffer,n->ha,dev->addr_len), dev->name); }