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

Reply via email to