From d7c9c21f18704580f66a1ce73fb6b506fdf40732 Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 23 Sep 2015 13:51:53 +0300 Subject: sd-dhcp6-client: Prevent setting and restarting of DHCPv6 client Prevent modifications to index, MAC address, DUID and Information Request while the DHCPv6 client is running. Require the DHCPv6 client to be stopped first instead of always unconditionally restarting it if the caller calls sd_dhcp6_client_start() more than once. With this change, handling of for example incoming Router Advertisments becomes much easier. --- src/libsystemd-network/sd-dhcp6-client.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/libsystemd-network') diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 2367509693..1ab3640c6b 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -125,6 +125,8 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) { assert_return(client, -EINVAL); assert_return(interface_index >= -1, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + client->index = interface_index; return 0; @@ -140,6 +142,8 @@ int sd_dhcp6_client_set_mac( assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); assert_return(arp_type > 0, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + if (arp_type == ARPHRD_ETHER) assert_return(addr_len == ETH_ALEN, -EINVAL); else if (arp_type == ARPHRD_INFINIBAND) @@ -173,6 +177,8 @@ int sd_dhcp6_client_set_duid( assert_return(duid, -EINVAL); assert_return(duid_len > 0 && duid_len <= MAX_DUID_LEN, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + switch (type) { case DHCP6_DUID_LLT: if (duid_len <= sizeof(client->duid.llt)) @@ -205,6 +211,8 @@ int sd_dhcp6_client_set_duid( int sd_dhcp6_client_set_information_request(sd_dhcp6_client *client, bool enabled) { assert_return(client, -EINVAL); + assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); + client->information_request = enabled; return 0; @@ -1126,6 +1134,9 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { assert_return(client->event, -EINVAL); assert_return(client->index > 0, -EINVAL); + if (!IN_SET(client->state, DHCP6_STATE_STOPPED)) + return -EALREADY; + r = client_reset(client); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 44598572da523f66872f593be7139b9a0f97deee Mon Sep 17 00:00:00 2001 From: Patrik Flykt Date: Wed, 23 Sep 2015 14:00:03 +0300 Subject: test-dhcp6-client: Update test case due to changed semantics Update the test case to stop the ongoing Information Request exchange before unsetting its state. To keep the test case callback verification simpler, temporarily unset the callback function before stopping. --- src/libsystemd-network/test-dhcp6-client.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/libsystemd-network') diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c index 178f536337..0c131a9897 100644 --- a/src/libsystemd-network/test-dhcp6-client.c +++ b/src/libsystemd-network/test-dhcp6-client.c @@ -581,7 +581,11 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event, if (verbose) printf(" got DHCPv6 event %d\n", event); + assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY); + assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0); + assert_se(sd_dhcp6_client_stop(client) >= 0); assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0); + assert_se(sd_dhcp6_client_set_callback(client, test_client_solicit_cb, e) >= 0); -- cgit v1.2.3-54-g00ecf