On 10/10/2016 20:15, Claudio Jeker wrote:
So rn_refines() is a function from the deep underbelly of radix code.
In my opinion if.c should not use this function especially now that we
use
art for routing table lookups. Instead I implemented a simple
ifa_netmask_cmp() function that does what the code expects and compares
the two netmasks. It is a bit more complictated than a simple memcmp()
because netmasks can be encoded in a few ways (more or less padding
bytes). Also the code assumes consecutive netmasks since that is the
only
thing we allow on interfaces and IP routes anyway.
It might be easier to stop using ifa_ifwithnet() and kill it.
OK?
--
:wq Claudio
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.454
diff -u -p -r1.454 if.c
--- net/if.c 9 Oct 2016 20:05:10 -0000 1.454
+++ net/if.c 10 Oct 2016 17:52:08 -0000
@@ -93,7 +93,6 @@
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
-#include <net/radix.h> /* for rn_refines */
#include <net/netisr.h>
#include <netinet/in.h>
@@ -156,6 +155,8 @@ void if_watchdog_task(void *);
void if_input_process(void *);
void if_netisr(void *);
+int ifa_netmask_cmp(struct sockaddr *, struct sockaddr *);
+
#ifdef DDB
void ifa_print_all(void);
#endif
@@ -1279,6 +1280,36 @@ ifa_ifwithdstaddr(struct sockaddr *addr,
return (NULL);
}
+int
+ifa_netmask_cmp(struct sockaddr *sa1, struct sockaddr *sa2)
+{
+ int len, rv, diff, i;
+ char *cp;
+
+ len = sa1->sa_len > sa2->sa_len ? sa2->sa_len : sa1->sa_len;
+ len -= offsetof(struct sockaddr, sa_data);
+
+ rv = memcmp(sa1->sa_data, sa2->sa_data, len);
+ if (rv != 0)
+ return (0);
+ /* if sa_len is different make sure the longer is only 0 padded */
+ diff = sa1->sa_len - sa2->sa_len;
+ if (diff > 0) {
+ cp = sa1->sa_data;
+ for (i = 0; i < diff; i++) {
+ if (cp[len + i] != 0)
+ return (0);
+ }
+ } else if (diff < 0) {
+ cp = sa2->sa_data;
+ for (i = 0; i < -diff; i++) {
+ if (cp[len + i] != 0)
+ return (0);
+ }
+ }
+ return (1);
+}
+
/*
* Find an interface on a specific network. If many, choice
* is most specific found.
@@ -1311,9 +1342,8 @@ ifa_ifwithnet(struct sockaddr *sa, u_int
if ((*cp++ ^ *cp2++) & *cp3++)
/* want to continue for() loop */
goto next;
- if (ifa_maybe == 0 ||
- rn_refines((caddr_t)ifa->ifa_netmask,
- (caddr_t)ifa_maybe->ifa_netmask))
+ if (ifa_maybe == 0 || ifa_netmask_cmp(ifa->ifa_netmask,
+ ifa_maybe->ifa_netmask))
ifa_maybe = ifa;
}
}