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.
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;
}
}