--- linux-2.2.14/net/ipv4/arp.c.arp	Fri Feb 18 15:53:34 2000
+++ linux-2.2.14/net/ipv4/arp.c	Fri Feb 18 15:57:28 2000
@@ -67,6 +67,8 @@
  *					now it is in net/core/neighbour.c.
  *		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:
@@ -128,6 +130,7 @@ static int arp_constructor(struct neighb
 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 =
 {
@@ -618,7 +621,7 @@ int arp_rcv(struct sk_buff *skb, struct 
 #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))
@@ -672,6 +675,45 @@ int arp_rcv(struct sk_buff *skb, struct 
 		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) {
+				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) {
 
@@ -978,21 +1020,61 @@ out:
 	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");
 
@@ -1011,44 +1093,12 @@ int arp_get_info(char *buffer, char **st
 			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);
--- linux-2.2.14/CREDITS.arp	Fri Feb 18 15:53:34 2000
+++ linux-2.2.14/CREDITS	Fri Feb 18 15:53:46 2000
@@ -1370,6 +1370,14 @@ S: R. Prof. Rubens Elke Braga, 558 - Par
 S: 80220-320 Curitiba - Parana
 S: Brazil
 
+N: Marc Merlin
+E: marcsoft@merlins.org
+E: merlin_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
