]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: fix infinite lifetime handling
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 13 Jul 2022 17:52:48 +0000 (02:52 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Jul 2022 11:56:41 +0000 (20:56 +0900)
src/network/networkd-address.c
src/network/networkd-dhcp-prefix-delegation.c
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-ndisc.c
src/network/networkd-route.c
src/network/networkd-util.h

index 7131b0e04c8dc1be1fcbd18c23d66eed3acb5114..ba936d932a4526eec449887943fec7032760d1ab 100644 (file)
@@ -222,8 +222,8 @@ static struct ifa_cacheinfo *address_set_cinfo(Manager *m, const Address *a, str
         assert_se(sd_event_now(m->event, CLOCK_BOOTTIME, &now_usec) >= 0);
 
         *cinfo = (struct ifa_cacheinfo) {
-                .ifa_valid = MIN(usec_sub_unsigned(a->lifetime_valid_usec, now_usec) / USEC_PER_SEC, UINT32_MAX),
-                .ifa_prefered = MIN(usec_sub_unsigned(a->lifetime_preferred_usec, now_usec) / USEC_PER_SEC, UINT32_MAX),
+                .ifa_valid = usec_to_sec(a->lifetime_valid_usec, now_usec),
+                .ifa_prefered = usec_to_sec(a->lifetime_preferred_usec, now_usec),
         };
 
         return cinfo;
@@ -238,15 +238,8 @@ static void address_set_lifetime(Manager *m, Address *a, const struct ifa_cachei
 
         assert_se(sd_event_now(m->event, CLOCK_BOOTTIME, &now_usec) >= 0);
 
-        if (cinfo->ifa_valid == UINT32_MAX)
-                a->lifetime_valid_usec = USEC_INFINITY;
-        else
-                a->lifetime_valid_usec = usec_add(cinfo->ifa_valid * USEC_PER_SEC, now_usec);
-
-        if (cinfo->ifa_prefered == UINT32_MAX)
-                a->lifetime_preferred_usec = USEC_INFINITY;
-        else
-                a->lifetime_preferred_usec = usec_add(cinfo->ifa_prefered * USEC_PER_SEC, now_usec);
+        a->lifetime_valid_usec = sec_to_usec(cinfo->ifa_valid, now_usec);
+        a->lifetime_preferred_usec = sec_to_usec(cinfo->ifa_prefered, now_usec);
 }
 
 static uint32_t address_prefix(const Address *a) {
index 89ff59abe0bddec3eb7c183958481d03cc592d0b..62f0192bcbb0a0f8aeeded717bb462501201da6c 100644 (file)
@@ -871,7 +871,7 @@ static int dhcp4_pd_assign_subnet_prefix(Link *link, Link *uplink) {
                 return log_link_warning_errno(uplink, r, "Failed to get lifetime of DHCPv4 lease: %m");
 
         assert_se(sd_event_now(uplink->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
-        lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec);
+        lifetime_usec = sec_to_usec(lifetime_sec, now_usec);
 
         r = sd_dhcp_lease_get_6rd(uplink->dhcp_lease, &ipv4masklen, &sixrd_prefixlen, &sixrd_prefix, &br_addresses, NULL);
         if (r < 0)
@@ -945,7 +945,7 @@ int dhcp4_pd_prefix_acquired(Link *uplink) {
                 return log_link_warning_errno(uplink, r, "Failed to get lifetime of DHCPv4 lease: %m");
 
         assert_se(sd_event_now(uplink->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
-        lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec);
+        lifetime_usec = sec_to_usec(lifetime_sec, now_usec);
 
         r = sd_dhcp_lease_get_server_identifier(uplink->dhcp_lease, &server_address.in);
         if (r < 0)
@@ -1036,7 +1036,6 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) {
 
         for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) {
                 uint32_t lifetime_preferred_sec, lifetime_valid_sec;
-                usec_t lifetime_preferred_usec, lifetime_valid_usec;
                 struct in6_addr pd_prefix;
                 uint8_t pd_prefix_len;
 
@@ -1053,11 +1052,9 @@ static int dhcp6_pd_assign_subnet_prefixes(Link *link, Link *uplink) {
                 if (r < 0)
                         return r;
 
-                lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
-                lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
-
                 r = dhcp_pd_assign_subnet_prefix(link, &pd_prefix, pd_prefix_len,
-                                                 lifetime_preferred_usec, lifetime_valid_usec,
+                                                 sec_to_usec(lifetime_preferred_sec, timestamp_usec),
+                                                 sec_to_usec(lifetime_valid_sec, timestamp_usec),
                                                  /* is_uplink = */ link == uplink);
                 if (r < 0)
                         return r;
@@ -1086,7 +1083,6 @@ int dhcp6_pd_prefix_acquired(Link *uplink) {
         /* First, logs acquired prefixes and request unreachable routes. */
         for (sd_dhcp6_lease_reset_pd_prefix_iter(uplink->dhcp6_lease);;) {
                 uint32_t lifetime_preferred_sec, lifetime_valid_sec;
-                usec_t lifetime_valid_usec;
                 struct in6_addr pd_prefix;
                 uint8_t pd_prefix_len;
 
@@ -1100,13 +1096,13 @@ int dhcp6_pd_prefix_acquired(Link *uplink) {
                 if (r < 0)
                         return log_link_error_errno(uplink, r, "Failed to mask DHCPv6 delegated prefix: %m");
 
-                lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
-
                 r = dhcp_pd_prefix_add(uplink, &pd_prefix, pd_prefix_len);
                 if (r < 0)
                         return r;
 
-                r = dhcp6_request_unreachable_route(uplink, &pd_prefix, pd_prefix_len, lifetime_valid_usec, &server_address);
+                r = dhcp6_request_unreachable_route(uplink, &pd_prefix, pd_prefix_len,
+                                                    sec_to_usec(lifetime_valid_sec, timestamp_usec),
+                                                    &server_address);
                 if (r < 0)
                         return r;
         }
index 86d167e628c26758c9882f11b75f2eb15cd446af..f1412ad35229c3225f66d5e22520e4c3890d4a5d 100644 (file)
@@ -822,7 +822,7 @@ static int dhcp4_request_address(Link *link, bool announce) {
                         return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
 
                 assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
-                lifetime_usec = usec_add(lifetime_sec * USEC_PER_SEC, now_usec);
+                lifetime_usec = sec_to_usec(lifetime_sec, now_usec);
         } else
                 lifetime_usec = USEC_INFINITY;
 
index 3dc34f0e52c6bdbd8bc889e834a3987e0966b6a8..be7bdd6a43c888ff89a88a8db4b19ed9cc62ae11 100644 (file)
@@ -266,8 +266,8 @@ static int dhcp6_address_acquired(Link *link) {
                         break;
 
                 r = dhcp6_request_address(link, &server_address, &ip6_addr,
-                                          usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec),
-                                          usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec));
+                                          sec_to_usec(lifetime_preferred_sec, timestamp_usec),
+                                          sec_to_usec(lifetime_valid_sec, timestamp_usec));
                 if (r < 0)
                         return r;
         }
index b76b9608f32fc9c2bda8298a3e91498a3f00a453..ed33f0817fdd86aa7bdbdaf3677ab3cc3078a30f 100644 (file)
@@ -320,7 +320,7 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Failed to get RA timestamp: %m");
 
-        lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
+        lifetime_usec = sec16_to_usec(lifetime_sec, timestamp_usec);
 
         r = sd_ndisc_router_get_address(rt, &gateway);
         if (r < 0)
@@ -442,8 +442,8 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
         if (lifetime_preferred_sec > lifetime_valid_sec)
                 return 0;
 
-        lifetime_valid_usec = usec_add(lifetime_valid_sec * USEC_PER_SEC, timestamp_usec);
-        lifetime_preferred_usec = usec_add(lifetime_preferred_sec * USEC_PER_SEC, timestamp_usec);
+        lifetime_valid_usec = sec_to_usec(lifetime_valid_sec, timestamp_usec);
+        lifetime_preferred_usec = sec_to_usec(lifetime_preferred_sec, timestamp_usec);
 
         r = ndisc_generate_addresses(link, &prefix, prefixlen, &addresses);
         if (r < 0)
@@ -519,7 +519,7 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
         route->family = AF_INET6;
         route->flags = RTM_F_PREFIX;
         route->dst_prefixlen = prefixlen;
-        route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
+        route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
 
         r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
         if (r < 0)
@@ -652,7 +652,7 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
         route->gw_family = AF_INET6;
         route->dst.in6 = dst;
         route->dst_prefixlen = prefixlen;
-        route->lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
+        route->lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
 
         r = ndisc_request_route(TAKE_PTR(route), link, rt);
         if (r < 0)
@@ -706,7 +706,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
         if (lifetime_sec == 0)
                 return 0;
 
-        lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
+        lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
 
         n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
         if (n < 0)
@@ -800,7 +800,7 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
         if (lifetime_sec == 0)
                 return 0;
 
-        lifetime_usec = usec_add(timestamp_usec, lifetime_sec * USEC_PER_SEC);
+        lifetime_usec = sec_to_usec(lifetime_sec, timestamp_usec);
 
         r = sd_ndisc_router_dnssl_get_domains(rt, &l);
         if (r < 0)
index adc4660cfd45ce1e9fa841b4fa0265ae3d1bc445..8ab5aaf0dbe35b4e9e0d9b4cb0c9bcbca29a2748 100644 (file)
@@ -1181,12 +1181,15 @@ static int route_configure(const Route *route, Link *link, Request *req) {
 
         if (route->lifetime_usec != USEC_INFINITY) {
                 usec_t now_usec;
+                uint32_t sec;
 
                 assert_se(sd_event_now(link->manager->event, CLOCK_BOOTTIME, &now_usec) >= 0);
-                r = sd_netlink_message_append_u32(m, RTA_EXPIRES,
-                        MIN(DIV_ROUND_UP(usec_sub_unsigned(route->lifetime_usec, now_usec), USEC_PER_SEC), UINT32_MAX));
-                if (r < 0)
-                        return r;
+                sec = usec_to_sec(route->lifetime_usec, now_usec);
+                if (sec != UINT32_MAX) {
+                        r = sd_netlink_message_append_u32(m, RTA_EXPIRES, sec);
+                        if (r < 0)
+                                return r;
+                }
         }
 
         if (route->ttl_propagate >= 0) {
index 0a627588aa2e5c617dcad43f846098ab4fd23c1c..373184a3ed71b903fd78797619faa355db03c7d8 100644 (file)
@@ -37,6 +37,18 @@ typedef enum NetworkConfigState {
         NETWORK_CONFIG_STATE_REMOVING    = 1 << 5, /* e.g. address_remove() is called, but no response is received yet */
 } NetworkConfigState;
 
+static inline usec_t sec16_to_usec(uint16_t sec, usec_t timestamp_usec) {
+        return sec == UINT16_MAX ? USEC_INFINITY : usec_add(timestamp_usec, sec * USEC_PER_SEC);
+}
+
+static inline usec_t sec_to_usec(uint32_t sec, usec_t timestamp_usec) {
+        return sec == UINT32_MAX ? USEC_INFINITY : usec_add(timestamp_usec, sec * USEC_PER_SEC);
+}
+
+static inline uint32_t usec_to_sec(usec_t usec, usec_t now_usec) {
+        return MIN(DIV_ROUND_UP(usec_sub_unsigned(usec, now_usec), USEC_PER_SEC), UINT32_MAX);
+}
+
 CONFIG_PARSER_PROTOTYPE(config_parse_link_local_address_family);
 CONFIG_PARSER_PROTOTYPE(config_parse_address_family_with_kernel);
 CONFIG_PARSER_PROTOTYPE(config_parse_ip_masquerade);