]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/network/networkd-address.c
network: free address when it is removed
[thirdparty/systemd.git] / src / network / networkd-address.c
index 169d0e4829e0612e06c86869f57d7452519784f0..aeadb7b01bf3992508497f923d1b3c958e888751 100644 (file)
 #define ADDRESSES_PER_LINK_MAX 2048U
 #define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
 
+int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret) {
+        assert(link);
+        assert(ret);
+
+        /* see RFC4291 section 2.5.1 */
+        ret->s6_addr[8]  = link->mac.ether_addr_octet[0];
+        ret->s6_addr[8] ^= 1 << 1;
+        ret->s6_addr[9]  = link->mac.ether_addr_octet[1];
+        ret->s6_addr[10] = link->mac.ether_addr_octet[2];
+        ret->s6_addr[11] = 0xff;
+        ret->s6_addr[12] = 0xfe;
+        ret->s6_addr[13] = link->mac.ether_addr_octet[3];
+        ret->s6_addr[14] = link->mac.ether_addr_octet[4];
+        ret->s6_addr[15] = link->mac.ether_addr_octet[5];
+
+        return 0;
+}
+
 int address_new(Address **ret) {
         _cleanup_(address_freep) Address *address = NULL;
 
@@ -187,7 +205,7 @@ static int address_compare_func(const Address *a1, const Address *a2) {
         }
 }
 
-DEFINE_PRIVATE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
+DEFINE_HASH_OPS(address_hash_ops, Address, address_hash_func, address_compare_func);
 
 bool address_equal(Address *a1, Address *a2) {
         if (a1 == a2)
@@ -248,11 +266,7 @@ static int address_add_internal(Link *link, Set **addresses,
         /* Consider address tentative until we get the real flags from the kernel */
         address->flags = IFA_F_TENTATIVE;
 
-        r = set_ensure_allocated(addresses, &address_hash_ops);
-        if (r < 0)
-                return r;
-
-        r = set_put(*addresses, address);
+        r = set_ensure_put(addresses, &address_hash_ops, address);
         if (r < 0)
                 return r;
         if (r == 0)
@@ -262,9 +276,7 @@ static int address_add_internal(Link *link, Set **addresses,
 
         if (ret)
                 *ret = address;
-
-        address = NULL;
-
+        TAKE_PTR(address);
         return 0;
 }
 
@@ -284,11 +296,7 @@ int address_add(Link *link, int family, const union in_addr_union *in_addr, unsi
                         return r;
         } else if (r == 0) {
                 /* Take over a foreign address */
-                r = set_ensure_allocated(&link->addresses, &address_hash_ops);
-                if (r < 0)
-                        return r;
-
-                r = set_put(link->addresses, address);
+                r = set_ensure_put(&link->addresses, &address_hash_ops, address);
                 if (r < 0)
                         return r;
 
@@ -436,6 +444,8 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
         r = sd_netlink_message_get_errno(m);
         if (r < 0 && r != -EADDRNOTAVAIL)
                 log_link_message_warning_errno(link, m, r, "Could not drop address");
+        else
+                (void) manager_rtnl_process_address(rtnl, m, link->manager);
 
         return 1;
 }
@@ -668,7 +678,7 @@ int address_configure(
                         _cleanup_free_ char *pretty = NULL;
 
                         (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
-                        log_debug("Starting IPv4ACD client. Probing address %s", strna(pretty));
+                        log_link_debug(link, "Starting IPv4ACD client. Probing address %s", strna(pretty));
                 }
 
                 r = sd_ipv4acd_start(address->acd, true);
@@ -936,7 +946,7 @@ int config_parse_lifetime(const char *unit,
                           void *userdata) {
         Network *network = userdata;
         _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
-        unsigned k;
+        uint32_t k;
         int r;
 
         assert(filename);
@@ -949,8 +959,8 @@ int config_parse_lifetime(const char *unit,
         if (r < 0)
                 return r;
 
-        /* We accept only "forever", "infinity", or "0". */
-        if (STR_IN_SET(rvalue, "forever", "infinity"))
+        /* We accept only "forever", "infinity", empty, or "0". */
+        if (STR_IN_SET(rvalue, "forever", "infinity", ""))
                 k = CACHE_INFO_INFINITY_LIFE_TIME;
         else if (streq(rvalue, "0"))
                 k = 0;
@@ -961,7 +971,7 @@ int config_parse_lifetime(const char *unit,
         }
 
         n->cinfo.ifa_prefered = k;
-        n = NULL;
+        TAKE_PTR(n);
 
         return 0;
 }
@@ -1053,6 +1063,7 @@ int config_parse_address_scope(const char *unit,
                 }
         }
 
+        n->scope_set = true;
         n = NULL;
         return 0;
 }
@@ -1125,5 +1136,8 @@ int address_section_verify(Address *address) {
                                          address->section->filename, address->section->line);
         }
 
+        if (!address->scope_set && in_addr_is_localhost(address->family, &address->in_addr) > 0)
+                address->scope = RT_SCOPE_HOST;
+
         return 0;
 }