]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Make fr_ipaddr_cmp more efficient by only comparing used bytes
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Fri, 10 Jun 2022 23:58:02 +0000 (18:58 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 12 Jun 2022 01:07:25 +0000 (20:07 -0500)
src/lib/util/inet.c

index 061009aef816cb5f7083ed026ff139b2052316f1..7f5c235768f15e4c611284e4c8df005cae3465c8 100644 (file)
@@ -1321,33 +1321,45 @@ int fr_ipaddr_from_ifindex(fr_ipaddr_t *out, int fd, int af, int ifindex)
 
 /** Compare two ip addresses
  *
+ * @param[in] a                First ip to compare.
+ * @param[in] b                Second ip to compare.
+ * @return
+ *     - 1 if a > b
+ *     - 0 if a == b
+ *     - -1 if a < b
+ *     - -2 on error.
  */
 int8_t fr_ipaddr_cmp(fr_ipaddr_t const *a, fr_ipaddr_t const *b)
 {
        int ret;
+       size_t len;
 
        CMP_RETURN(a, b, af);
        CMP_RETURN(a, b, prefix);
 
+       /*
+        *      We only care about prefix bytes.
+        *
+        *      Host bytes should be masked on ingestion
+        *      for prefix types.
+        */
+       len = ((a->prefix + 7) & -8) >> 3;
        switch (a->af) {
        case AF_INET:
-               ret = memcmp(&a->addr.v4,
-                            &b->addr.v4,
-                            sizeof(a->addr.v4));
+               ret = memcmp(&a->addr.v4, &b->addr.v4, len);
                return CMP(ret, 0);
 
 #ifdef HAVE_STRUCT_SOCKADDR_IN6
        case AF_INET6:
                CMP_RETURN(a, b, scope_id);
-               ret = memcmp(&a->addr.v6, &b->addr.v6, sizeof(a->addr.v6));
+               ret = memcmp(&a->addr.v6, &b->addr.v6, len);
                return CMP(ret, 0);
 #endif
 
        default:
-               break;
+               fr_strerror_printf("Invalid address family %u", a->af);
+               return -2;
        }
-
-       return -1;
 }
 
 /** Convert our internal ip address representation to a sockaddr