--- 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: [email protected]
+E: [email protected]
+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: [email protected]
P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D