summaryrefslogtreecommitdiff
path: root/src/libsystemd-network/sd-dhcp-server.c
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2017-06-09 16:18:25 +0100
committerRichard Maw <richard.maw@codethink.co.uk>2017-06-12 16:54:42 +0100
commit45a9eac9a0c85c0c76b46388a530edd335ae44af (patch)
tree17549add403c49048202acb0fcd2eddb22c0a91f /src/libsystemd-network/sd-dhcp-server.c
parentc1835a427fddac41dcc780cf733b53e01721e8f2 (diff)
downloadsystemd-45a9eac9a0c85c0c76b46388a530edd335ae44af.tar.gz
networkd: Allow DHCP servers to be re-configured on carrier gain
In normal operation this would trigger an assertion when a DHCP server is configured every time the link goes up. This change makes sd_dhcp_server_configure_pool idempotent and stops the DHCP server when the link loses carrier. In addition to this stopping the assertion being triggered, this has the useful side-effect of allowing the link to be taken down and then brought back up as a way to have it use DNS from an "upstream" interface that got its DNS configuration via DHCP after the downstream link was configured.
Diffstat (limited to 'src/libsystemd-network/sd-dhcp-server.c')
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 315cbf1ac5..5a59c377f8 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -34,6 +34,14 @@
#define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR
#define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12)
+static void dhcp_lease_free(DHCPLease *lease) {
+ if (!lease)
+ return;
+
+ free(lease->client_id.data);
+ free(lease);
+}
+
/* configures the server's address and subnet, and optionally the pool's size and offset into the subnet
* the whole pool must fit into the subnet, and may not contain the first (any) nor last (broadcast) address
* moreover, the server's own address may be in the pool, and is in that case reserved in order not to
@@ -47,7 +55,6 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *addres
assert_return(address, -EINVAL);
assert_return(address->s_addr != INADDR_ANY, -EINVAL);
assert_return(prefixlen <= 32, -ERANGE);
- assert_return(server->address == INADDR_ANY, -EBUSY);
assert_se(in_addr_prefixlen_to_netmask(&netmask_addr, prefixlen));
netmask = netmask_addr.s_addr;
@@ -78,19 +85,28 @@ int sd_dhcp_server_configure_pool(sd_dhcp_server *server, struct in_addr *addres
else
size = size_max;
- server->bound_leases = new0(DHCPLease*, size);
- if (!server->bound_leases)
- return -ENOMEM;
+ if (server->address != address->s_addr || server->netmask != netmask || server->pool_size != size || server->pool_offset != offset) {
+ DHCPLease *lease;
+
+ free(server->bound_leases);
+ server->bound_leases = new0(DHCPLease*, size);
+ if (!server->bound_leases)
+ return -ENOMEM;
- server->pool_offset = offset;
- server->pool_size = size;
+ server->pool_offset = offset;
+ server->pool_size = size;
- server->address = address->s_addr;
- server->netmask = netmask;
- server->subnet = address->s_addr & netmask;
+ server->address = address->s_addr;
+ server->netmask = netmask;
+ server->subnet = address->s_addr & netmask;
- if (server_off >= offset && server_off - offset < size)
- server->bound_leases[server_off - offset] = &server->invalid_lease;
+ if (server_off >= offset && server_off - offset < size)
+ server->bound_leases[server_off - offset] = &server->invalid_lease;
+
+ /* Drop any leases associated with the old address range */
+ while ((lease = hashmap_steal_first(server->leases_by_client_id)))
+ dhcp_lease_free(lease);
+ }
return 0;
}
@@ -143,14 +159,6 @@ static const struct hash_ops client_id_hash_ops = {
.compare = client_id_compare_func
};
-static void dhcp_lease_free(DHCPLease *lease) {
- if (!lease)
- return;
-
- free(lease->client_id.data);
- free(lease);
-}
-
sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
DHCPLease *lease;