lkml.org 
[lkml]   [2000]   [Sep]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: [patch] 2.4 version of my duplicate IP and MAC detection patch
[Cc to  kernel inclusion folks  removed since the  revised patch is  new and
therefore open for comments. I'll make another post once people are
reasonably happy with this one]

On Fri, Sep 22, 2000 at 01:31:06AM +0200, Andi Kleen wrote:
> You added a linear IP search to fast path ARP processing. The people running

Sorry, but it's not a fast path, that extra code only gets run when you
receive an ARP packet with your own MAC address or when you receive a
broadcast or directed ARP request, which isn't more than a few times a
minute on a busy net.
I've now even wrapped the whole thing around net_ratelimit() so that the
checks aren't even done if a network message was outputed recently (I did
call net_ratelimit before, but after the checks)

> thousands of IP aliases will surely love you. You could at least use the
> ip_route_input output instead that arp_rcv computes anyways and check
> for RTN_LOCAL.

Point taken, I made the change and attached a new patch (I also cleaned up
the code a little as a result)

> BTW, the idea of doing it in user space is not to have a daemon running
> but just to do DAD once when you configure the ip address, like most other
> OSes do [as easily done with arping and a small script, see ipcfg from
> iproute2].

I've updated http://marc.merlins.org/linux/arppatch/ to make this argument a
little more clear.
----------------------------------------------------------------------------
So what else can you do?
Well, while the patch below will actually catch most of everyday conflicts,
you also want to check that your IP isn't used when you bring your interface
up (you can use arping or something similar).
Better yet, you can also have a small daemon that does an ARP query for your
IP every so often and makes sure there is no answer. The problem with this
approach is that it's intrusive and it can generate a lot of traffic if all
the machines on a big net do this
Because both of these can be done trivially in user space (use arping), it
shouldn't be in the kernel. That said, doing those checks only supplement my
patch, they do not replace it (unless you want to be really invasive and
arping your IP every 10sec or so, but I'm not sure you want the associated
network overhead)
----------------------------------------------------------------------------

Thanks for pointing me to ip_route_input (can't believe I didn't see it), it
did make the patch better.

Comments on this patch welcome.

Thanks,
Marc

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 <asm/system.h>
#include <asm/uaccess.h>
+
+#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 <marcsoft@merlins.org> */
+ 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<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
+
+ 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;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

{
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
--
Microsoft is to software what McDonalds is to gourmet cooking
Home page: http://marc.merlins.org/ (friendly to non IE browsers)
Finger marc_f@merlins.org for PGP key and other contact information
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 12:38    [W:0.090 / U:3.832 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site