]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-ipv4ll/networkd: Try to select an IPv4 link-local start address
authorAndre Kalb <andre.kalb@sma.de>
Thu, 30 Jun 2022 08:27:27 +0000 (10:27 +0200)
committerAndre Kalb <andre.kalb@sma.de>
Thu, 14 Jul 2022 12:35:42 +0000 (14:35 +0200)
src/libsystemd-network/test-ipv4ll-manual.c
src/libsystemd-network/test-ipv4ll.c
src/network/networkd-dhcp4.c
src/network/networkd-link.c

index e79758c5f5c56cce075c20c87032596b37c626a5..d5ef3535ea8dbe1770ca89efe3c85cb40e1d8744 100644 (file)
@@ -39,7 +39,7 @@ static void ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
         }
 }
 
-static int client_run(int ifindex, const char *seed_str, const struct ether_addr *ha, sd_event *e) {
+static int client_run(int ifindex, const char *seed_str, const struct in_addr *start_address, const struct ether_addr *ha, sd_event *e) {
         sd_ipv4ll *ll;
 
         assert_se(sd_ipv4ll_new(&ll) >= 0);
@@ -57,6 +57,9 @@ static int client_run(int ifindex, const char *seed_str, const struct ether_addr
                 assert_se(sd_ipv4ll_set_address_seed(ll, seed) >= 0);
         }
 
+        if (start_address && in4_addr_is_set(start_address))
+                assert_se(sd_ipv4ll_set_address(ll, start_address) >= 0);
+
         log_info("starting IPv4LL client");
 
         assert_se(sd_ipv4ll_start(ll) >= 0);
@@ -68,7 +71,7 @@ static int client_run(int ifindex, const char *seed_str, const struct ether_addr
         return EXIT_SUCCESS;
 }
 
-static int test_ll(const char *ifname, const char *seed) {
+static int test_ll(const char *ifname, const char *seed, const struct in_addr *start_address) {
         _cleanup_(sd_event_unrefp) sd_event *e = NULL;
         _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
@@ -87,7 +90,7 @@ static int test_ll(const char *ifname, const char *seed) {
         assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0);
         assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0);
 
-        client_run(ifindex, seed, &ha, e);
+        client_run(ifindex, seed, start_address, &ha, e);
 
         return EXIT_SUCCESS;
 }
@@ -96,12 +99,19 @@ int main(int argc, char *argv[]) {
         test_setup_logging(LOG_DEBUG);
 
         if (argc == 2)
-                return test_ll(argv[1], NULL);
-        else if (argc == 3)
-                return test_ll(argv[1], argv[2]);
-        else {
+                return test_ll(argv[1], NULL, NULL);
+        else if (argc == 3) {
+                int r;
+                union in_addr_union a;
+
+                r = in_addr_from_string(AF_INET, argv[2], &a);
+                if (r < 0)
+                        return test_ll(argv[1], argv[2], NULL);
+                else
+                        return test_ll(argv[1], NULL, &a.in);
+        } else {
                 log_error("This program takes one or two arguments.\n"
-                          "\t %s <ifname> [<seed>]", program_invocation_short_name);
+                          "\t %s <ifname> [<seed>|<start_address>]", program_invocation_short_name);
                 return EXIT_FAILURE;
         }
 }
index 44d0bfe17c3038f0571614ac3834af64ff091c7c..2a078a502e70e1acd3462ee4ed6cdea898ef5d51 100644 (file)
@@ -122,7 +122,7 @@ static void test_public_api_setters(sd_event *e) {
         assert_se(sd_ipv4ll_unref(ll) == NULL);
 }
 
-static void test_basic_request(sd_event *e) {
+static void test_basic_request(sd_event *e, const struct in_addr *start_address) {
 
         sd_ipv4ll *ll;
         struct ether_arp arp;
@@ -133,6 +133,8 @@ static void test_basic_request(sd_event *e) {
                 printf("* %s\n", __func__);
 
         assert_se(sd_ipv4ll_new(&ll) == 0);
+        if (in4_addr_is_set(start_address))
+                assert_se(sd_ipv4ll_set_address(ll, start_address) >= 0);
         assert_se(sd_ipv4ll_start(ll) == -EINVAL);
 
         assert_se(sd_ipv4ll_attach_event(ll, e, 0) == 0);
@@ -168,6 +170,13 @@ static void test_basic_request(sd_event *e) {
 
                 sd_event_run(e, UINT64_MAX);
                 assert_se(basic_request_handler_bind == 1);
+
+                if (in4_addr_is_set(start_address)) {
+                        struct in_addr address;
+
+                        assert_se(sd_ipv4ll_get_address(ll, &address) >= 0);
+                        assert_se(start_address->s_addr == address.s_addr);
+                }
         }
 
         sd_ipv4ll_stop(ll);
@@ -179,6 +188,7 @@ static void test_basic_request(sd_event *e) {
 }
 
 int main(int argc, char *argv[]) {
+        struct in_addr start_address = {};
         _cleanup_(sd_event_unrefp) sd_event *e = NULL;
 
         test_setup_logging(LOG_DEBUG);
@@ -186,7 +196,12 @@ int main(int argc, char *argv[]) {
         assert_se(sd_event_new(&e) >= 0);
 
         test_public_api_setters(e);
-        test_basic_request(e);
+        test_basic_request(e, &start_address);
+
+        basic_request_handler_bind = 0;
+        basic_request_handler_stop = 0;
+        start_address.s_addr = htobe32(169U << 24 | 254U << 16 | 1U << 8 | 2U);
+        test_basic_request(e, &start_address);
 
         return 0;
 }
index 5770b48767e9ba626e714041af205d8d5771e466..5c74dcef6f815f39916336ead468abc92a739430 100644 (file)
@@ -1071,6 +1071,12 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         if (link->ipv4ll) {
                                 log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
 
+                                if (in4_addr_is_set(&link->network->ipv4ll_start_address)) {
+                                        r = sd_ipv4ll_set_address(link->ipv4ll, &link->network->ipv4ll_start_address);
+                                        if (r < 0)
+                                                return log_link_warning_errno(link, r, "Could not set IPv4 link-local start address: %m");;
+                                }
+
                                 r = sd_ipv4ll_start(link->ipv4ll);
                                 if (r < 0)
                                         return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
@@ -1154,6 +1160,12 @@ static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         if (link->ipv4ll && !sd_ipv4ll_is_running(link->ipv4ll)) {
                                 log_link_debug(link, "Problems acquiring DHCP lease, acquiring IPv4 link-local address");
 
+                                if (in4_addr_is_set(&link->network->ipv4ll_start_address)) {
+                                        r = sd_ipv4ll_set_address(link->ipv4ll, &link->network->ipv4ll_start_address);
+                                        if (r < 0)
+                                                return log_link_warning_errno(link, r, "Could not set IPv4 link-local start address: %m");;
+                                }
+
                                 r = sd_ipv4ll_start(link->ipv4ll);
                                 if (r < 0)
                                         return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
index 29a5609483a5ab3921c58978654d461980f4f2d0..f3ef5035ffd069ced9cc963351a2dc6c017ac83a 100644 (file)
@@ -611,6 +611,12 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) {
                 log_link_debug(link, "Acquiring DHCPv4 lease.");
 
         } else if (link->ipv4ll) {
+                if (in4_addr_is_set(&link->network->ipv4ll_start_address)) {
+                        r = sd_ipv4ll_set_address(link->ipv4ll, &link->network->ipv4ll_start_address);
+                        if (r < 0)
+                                return log_link_warning_errno(link, r, "Could not set IPv4 link-local start address: %m");
+                }
+
                 r = sd_ipv4ll_start(link->ipv4ll);
                 if (r < 0)
                         return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");