]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-address.c
network: make address/route_configure optionally return created Address/Route object
[thirdparty/systemd.git] / src / network / networkd-address.c
index 6f1ee3b534970e416cdb60b558f89926ced3dcb0..19a007906b7f600cf3bd68a3cc79efeb69754957 100644 (file)
@@ -205,7 +205,7 @@ static int address_compare_func(const Address *a1, const Address *a2) {
         }
 }
 
-DEFINE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
+DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free);
 
 bool address_equal(Address *a1, Address *a2) {
         if (a1 == a2)
@@ -359,15 +359,21 @@ int address_update(
         link_update_operstate(address->link, true);
         link_check_ready(address->link);
 
-        if (!ready &&
-            address_is_ready(address) &&
-            address->family == AF_INET6 &&
-            in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
-            in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
+        if (!ready && address_is_ready(address)) {
+                if (address->callback) {
+                        r = address->callback(address);
+                        if (r < 0)
+                                return r;
+                }
 
-                r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
-                if (r < 0)
-                        return r;
+                if (address->family == AF_INET6 &&
+                    in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
+                    IN6_IS_ADDR_UNSPECIFIED(&address->link->ipv6ll_address) > 0) {
+
+                        r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         return 0;
@@ -431,6 +437,32 @@ int address_get(Link *link,
         return -ENOENT;
 }
 
+static bool address_exists_internal(Set *addresses, int family, const union in_addr_union *in_addr) {
+        Address *address;
+        Iterator i;
+
+        SET_FOREACH(address, addresses, i) {
+                if (address->family != family)
+                        continue;
+                if (in_addr_equal(address->family, &address->in_addr, in_addr))
+                        return true;
+        }
+
+        return false;
+}
+
+bool address_exists(Link *link, int family, const union in_addr_union *in_addr) {
+        assert(link);
+        assert(IN_SET(family, AF_INET, AF_INET6));
+        assert(in_addr);
+
+        if (address_exists_internal(link->addresses, family, in_addr))
+                return true;
+        if (address_exists_internal(link->addresses_foreign, family, in_addr))
+                return true;
+        return false;
+}
+
 static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -560,9 +592,11 @@ int address_configure(
                 Address *address,
                 Link *link,
                 link_netlink_message_handler_t callback,
-                bool update) {
+                bool update,
+                Address **ret) {
 
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        Address *a;
         int r;
 
         assert(address);
@@ -583,6 +617,13 @@ int address_configure(
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
 
+        if (DEBUG_LOGGING) {
+                _cleanup_free_ char *str = NULL;
+
+                (void) in_addr_to_string(address->family, &address->in_addr, &str);
+                log_link_debug(link, "%s address: %s", update ? "Updating" : "Configuring", strna(str));
+        }
+
         if (update)
                 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
                                                     link->ifindex, address->family);
@@ -664,9 +705,9 @@ int address_configure(
         link_ref(link);
 
         if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer))
-                r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, NULL);
+                r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a);
         else
-                r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL);
+                r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a);
         if (r < 0) {
                 address_release(address);
                 return log_link_error_errno(link, r, "Could not add address: %m");
@@ -686,6 +727,9 @@ int address_configure(
                         log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m");
         }
 
+        if (ret)
+                *ret = a;
+
         return 1;
 }