ip-address-access: minimize IP address lists
authorLennart Poettering <lennart@poettering.net>
Tue, 5 Sep 2017 15:41:34 +0000 (17:41 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Sep 2017 13:24:55 +0000 (15:24 +0200)
Let's drop redundant items from the IP address list after parsing. Let's
also mask out redundant bits hidden by the prefixlength.

src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/core/dbus-cgroup.c
src/core/ip-address-access.c
src/core/ip-address-access.h

index 94f0625..e27faba 100644 (file)
@@ -465,6 +465,30 @@ int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen)
         return -EAFNOSUPPORT;
 }
 
+int in_addr_prefix_covers(int family,
+                          const union in_addr_union *prefix,
+                          unsigned char prefixlen,
+                          const union in_addr_union *address) {
+
+        union in_addr_union masked_prefix, masked_address;
+        int r;
+
+        assert(prefix);
+        assert(address);
+
+        masked_prefix = *prefix;
+        r = in_addr_mask(family, &masked_prefix, prefixlen);
+        if (r < 0)
+                return r;
+
+        masked_address = *address;
+        r = in_addr_mask(family, &masked_address, prefixlen);
+        if (r < 0)
+                return r;
+
+        return in_addr_equal(family, &masked_prefix, &masked_address);
+}
+
 int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
         uint8_t u;
         int r;
index bb57c08..d129bf5 100644 (file)
@@ -60,6 +60,7 @@ struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned cha
 int in4_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen);
 int in4_addr_default_subnet_mask(const struct in_addr *addr, struct in_addr *mask);
 int in_addr_mask(int family, union in_addr_union *addr, unsigned char prefixlen);
+int in_addr_prefix_covers(int family, const union in_addr_union *prefix, unsigned char prefixlen, const union in_addr_union *address);
 int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret);
 int in_addr_prefix_from_string(const char *p, int family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
 int in_addr_prefix_from_string_auto(const char *p, int *ret_family, union in_addr_union *ret_prefix, unsigned char *ret_prefixlen);
index 3bb4108..42381ec 100644 (file)
@@ -1288,6 +1288,8 @@ int bus_cgroup_set_property(
                 if (r < 0)
                         return r;
 
+                *list = ip_address_access_reduce(*list);
+
                 if (mode != UNIT_CHECK) {
                         _cleanup_free_ char *buf = NULL;
                         _cleanup_fclose_ FILE *f = NULL;
index 6a89bb2..18d2870 100644 (file)
@@ -148,6 +148,8 @@ int config_parse_ip_address_access(
                 a = NULL;
         }
 
+        *list = ip_address_access_reduce(*list);
+
         return 0;
 }
 
@@ -163,3 +165,43 @@ IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) {
 
         return NULL;
 }
+
+IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first) {
+        IPAddressAccessItem *a, *b, *tmp;
+        int r;
+
+        /* Drops all entries from the list that are covered by another entry in full, thus removing all redundant
+         * entries. */
+
+        LIST_FOREACH_SAFE(items, a, tmp, first) {
+
+                /* Drop irrelevant bits */
+                (void) in_addr_mask(a->family, &a->address, a->prefixlen);
+
+                LIST_FOREACH(items, b, first) {
+
+                        if (a == b)
+                                continue;
+
+                        if (a->family != b->family)
+                                continue;
+
+                        if (b->prefixlen > a->prefixlen)
+                                continue;
+
+                        r = in_addr_prefix_covers(b->family,
+                                                  &b->address,
+                                                  b->prefixlen,
+                                                  &a->address);
+                        if (r <= 0)
+                                continue;
+
+                        /* b covers a fully, then let's drop a */
+
+                        LIST_REMOVE(items, first, a);
+                        free(a);
+                }
+        }
+
+        return first;
+}
index eea20b4..9aeab1f 100644 (file)
@@ -34,3 +34,5 @@ struct IPAddressAccessItem {
 int config_parse_ip_address_access(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 
 IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first);
+
+IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first);