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

Reply via email to