From 8eb9058dc1f99a5eb9b8726a978fcc0720837a10 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 19:19:32 +0200 Subject: dhcp,network: implement RFC 4833 (DHCP Timezone option) This one is simply to add: encode the tzdata timezone in the DHCP options and optionally make use of it. --- src/libsystemd-network/sd-dhcp-server.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index faeab0fd30..730d95e2c0 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -136,6 +136,8 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) { sd_event_unref(server->event); + free(server->timezone); + while ((lease = hashmap_steal_first(server->leases_by_client_id))) dhcp_lease_free(lease); hashmap_free(server->leases_by_client_id); @@ -474,6 +476,15 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req, if (r < 0) return r; + if (server->timezone) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + DHCP_OPTION_NEW_TZDB_TIMEZONE, + strlen(server->timezone), server->timezone); + if (r < 0) + return r; + } + r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset); if (r < 0) return r; @@ -993,3 +1004,19 @@ int sd_dhcp_server_forcerenew(sd_dhcp_server *server) { return r; } + +int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone) { + int r; + + assert_return(server, -EINVAL); + assert_return(timezone_is_valid(timezone), -EINVAL); + + if (streq_ptr(timezone, server->timezone)) + return 0; + + r = free_and_strdup(&server->timezone, timezone); + if (r < 0) + return r; + + return 1; +} -- cgit v1.2.3-54-g00ecf From 3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 21:05:53 +0200 Subject: dhcp: stop using refcnt.h No need to invole atomic ops in single-threaded APIs, let's simplify this. --- src/libsystemd-network/dhcp-lease-internal.h | 3 +- src/libsystemd-network/dhcp-server-internal.h | 3 +- src/libsystemd-network/dhcp6-lease-internal.h | 4 +-- src/libsystemd-network/sd-dhcp-client.c | 44 ++++++++++++++---------- src/libsystemd-network/sd-dhcp-lease.c | 49 +++++++++++++++++---------- src/libsystemd-network/sd-dhcp-server.c | 15 +++++--- src/libsystemd-network/sd-dhcp6-client.c | 35 ++++++++++++------- src/libsystemd-network/sd-dhcp6-lease.c | 36 +++++++++++++------- 8 files changed, 118 insertions(+), 71 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index d6b8aaa2d1..e1d2555505 100644 --- a/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -25,7 +25,6 @@ #include #include -#include "refcnt.h" #include "util.h" #include "list.h" @@ -48,7 +47,7 @@ struct sd_dhcp_raw_option { }; struct sd_dhcp_lease { - RefCount n_ref; + int n_ref; int32_t time_offset; uint32_t t1; diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 24f99f801d..a5d3554e12 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -26,7 +26,6 @@ #include "sd-dhcp-server.h" #include "hashmap.h" -#include "refcnt.h" #include "util.h" #include "log.h" @@ -47,7 +46,7 @@ typedef struct DHCPLease { } DHCPLease; struct sd_dhcp_server { - RefCount n_ref; + unsigned n_ref; sd_event *event; int event_priority; diff --git a/src/libsystemd-network/dhcp6-lease-internal.h b/src/libsystemd-network/dhcp6-lease-internal.h index 037f580eb6..4edecf7711 100644 --- a/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/libsystemd-network/dhcp6-lease-internal.h @@ -24,13 +24,11 @@ #include -#include "refcnt.h" - #include "sd-dhcp6-lease.h" #include "dhcp6-internal.h" struct sd_dhcp6_lease { - RefCount n_ref; + unsigned n_ref; uint8_t *serverid; size_t serverid_len; diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 46104afded..32af9aa3da 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -27,7 +27,6 @@ #include #include "util.h" -#include "refcnt.h" #include "random-util.h" #include "async.h" @@ -41,7 +40,7 @@ #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN) struct sd_dhcp_client { - RefCount n_ref; + unsigned n_ref; DHCPState state; sd_event *event; @@ -1676,30 +1675,41 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) { } sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client) { - if (client) - assert_se(REFCNT_INC(client->n_ref) >= 2); + + if (!client) + return NULL; + + assert(client->n_ref >= 1); + client->n_ref++; return client; } sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) { - if (client && REFCNT_DEC(client->n_ref) == 0) { - log_dhcp_client(client, "FREE"); - client_initialize(client); + if (!client) + return NULL; - client->receive_message = - sd_event_source_unref(client->receive_message); + assert(client->n_ref >= 1); + client->n_ref--; - sd_dhcp_client_detach_event(client); + if (client->n_ref > 0) + return NULL; - sd_dhcp_lease_unref(client->lease); + log_dhcp_client(client, "FREE"); - free(client->req_opts); - free(client->hostname); - free(client->vendor_class_identifier); - free(client); - } + client_initialize(client); + + client->receive_message = sd_event_source_unref(client->receive_message); + + sd_dhcp_client_detach_event(client); + + sd_dhcp_lease_unref(client->lease); + + free(client->req_opts); + free(client->hostname); + free(client->vendor_class_identifier); + free(client); return NULL; } @@ -1713,7 +1723,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) { if (!client) return -ENOMEM; - client->n_ref = REFCNT_INIT; + client->n_ref = 1; client->state = DHCP_STATE_INIT; client->index = -1; client->fd = -1; diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 482c36ec97..75989951cf 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -195,32 +195,45 @@ int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data } sd_dhcp_lease *sd_dhcp_lease_ref(sd_dhcp_lease *lease) { - if (lease) - assert_se(REFCNT_INC(lease->n_ref) >= 2); + + if (!lease) + return NULL; + + assert(lease->n_ref >= 1); + lease->n_ref++; return lease; } sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { - if (lease && REFCNT_DEC(lease->n_ref) == 0) { - while (lease->private_options) { - struct sd_dhcp_raw_option *option = lease->private_options; - LIST_REMOVE(options, lease->private_options, option); + if (!lease) + return NULL; - free(option->data); - free(option); - } - free(lease->hostname); - free(lease->domainname); - free(lease->dns); - free(lease->ntp); - free(lease->static_route); - free(lease->client_id); - free(lease->vendor_specific); - free(lease); + assert(lease->n_ref >= 1); + lease->n_ref--; + + if (lease->n_ref > 0) + return NULL; + + while (lease->private_options) { + struct sd_dhcp_raw_option *option = lease->private_options; + + LIST_REMOVE(options, lease->private_options, option); + + free(option->data); + free(option); } + free(lease->hostname); + free(lease->domainname); + free(lease->dns); + free(lease->ntp); + free(lease->static_route); + free(lease->client_id); + free(lease->vendor_specific); + free(lease); + return NULL; } @@ -643,7 +656,7 @@ int dhcp_lease_new(sd_dhcp_lease **ret) { return -ENOMEM; lease->router = INADDR_ANY; - lease->n_ref = REFCNT_INIT; + lease->n_ref = 1; LIST_HEAD_INIT(lease->private_options); *ret = lease; diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 730d95e2c0..e2cd52ac0c 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -73,8 +73,12 @@ bool sd_dhcp_server_is_running(sd_dhcp_server *server) { } sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) { - if (server) - assert_se(REFCNT_INC(server->n_ref) >= 2); + + if (!server) + return NULL; + + assert(server->n_ref >= 1); + server->n_ref++; return server; } @@ -127,7 +131,10 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) { if (!server) return NULL; - if (REFCNT_DEC(server->n_ref) > 0) + assert(server->n_ref >= 1); + server->n_ref--; + + if (server->n_ref > 0) return NULL; log_dhcp_server(server, "UNREF"); @@ -158,7 +165,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { if (!server) return -ENOMEM; - server->n_ref = REFCNT_INIT; + server->n_ref = 1; server->fd_raw = -1; server->fd = -1; server->address = htobe32(INADDR_ANY); diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 10c3654020..7075a42f43 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -27,7 +27,6 @@ #include "udev.h" #include "udev-util.h" #include "util.h" -#include "refcnt.h" #include "random-util.h" #include "network-internal.h" @@ -40,7 +39,7 @@ #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN struct sd_dhcp6_client { - RefCount n_ref; + unsigned n_ref; enum DHCP6State state; sd_event *event; @@ -1222,26 +1221,36 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) { } sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client) { - if (client) - assert_se(REFCNT_INC(client->n_ref) >= 2); + + if (!client) + return NULL; + + assert(client->n_ref >= 1); + client->n_ref++; return client; } sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client) { - if (client && REFCNT_DEC(client->n_ref) == 0) { - client_reset(client); - sd_dhcp6_client_detach_event(client); - sd_dhcp6_lease_unref(client->lease); + if (!client) + return NULL; - free(client->req_opts); - free(client); + assert(client->n_ref >= 1); + client->n_ref--; + if (client->n_ref > 0) return NULL; - } - return client; + client_reset(client); + + sd_dhcp6_client_detach_event(client); + sd_dhcp6_lease_unref(client->lease); + + free(client->req_opts); + free(client); + + return NULL; } int sd_dhcp6_client_new(sd_dhcp6_client **ret) @@ -1255,7 +1264,7 @@ int sd_dhcp6_client_new(sd_dhcp6_client **ret) if (!client) return -ENOMEM; - client->n_ref = REFCNT_INIT; + client->n_ref = 1; client->ia_na.type = DHCP6_OPTION_IA_NA; diff --git a/src/libsystemd-network/sd-dhcp6-lease.c b/src/libsystemd-network/sd-dhcp6-lease.c index f0494b3c91..cf317408b7 100644 --- a/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/libsystemd-network/sd-dhcp6-lease.c @@ -361,26 +361,38 @@ int sd_dhcp6_lease_get_ntp_fqdn(sd_dhcp6_lease *lease, char ***ntp_fqdn) { } sd_dhcp6_lease *sd_dhcp6_lease_ref(sd_dhcp6_lease *lease) { - if (lease) - assert_se(REFCNT_INC(lease->n_ref) >= 2); + + if (!lease) + return NULL; + + assert(lease->n_ref >= 1); + lease->n_ref++; return lease; } sd_dhcp6_lease *sd_dhcp6_lease_unref(sd_dhcp6_lease *lease) { - if (lease && REFCNT_DEC(lease->n_ref) == 0) { - free(lease->serverid); - dhcp6_lease_free_ia(&lease->ia); - free(lease->dns); + if (!lease) + return NULL; - lease->domains = strv_free(lease->domains); + assert(lease->n_ref >= 1); + lease->n_ref--; - free(lease->ntp); + if (lease->n_ref > 0) + return NULL; - lease->ntp_fqdn = strv_free(lease->ntp_fqdn); - free(lease); - } + free(lease->serverid); + dhcp6_lease_free_ia(&lease->ia); + + free(lease->dns); + + lease->domains = strv_free(lease->domains); + + free(lease->ntp); + + lease->ntp_fqdn = strv_free(lease->ntp_fqdn); + free(lease); return NULL; } @@ -392,7 +404,7 @@ int dhcp6_lease_new(sd_dhcp6_lease **ret) { if (!lease) return -ENOMEM; - lease->n_ref = REFCNT_INIT; + lease->n_ref = 1; LIST_HEAD_INIT(lease->ia.addresses); -- cgit v1.2.3-54-g00ecf From 89ca10c6a61309d84d54c5dc5a295387ce39e610 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 22:47:53 +0200 Subject: network: s/user_data/userdata/ Everywhere else we call the generic user data pointer just "userdata", rather than "user_data". Let's do this here, too. --- src/libsystemd-network/dhcp-internal.h | 4 ++-- src/libsystemd-network/dhcp-lease-internal.h | 2 +- src/libsystemd-network/dhcp-option.c | 12 ++++++------ src/libsystemd-network/sd-dhcp-server.c | 4 ++-- src/libsystemd-network/test-dhcp-client.c | 2 +- src/libsystemd-network/test-dhcp-option.c | 4 ++-- src/libsystemd-network/test-ipv4ll.c | 6 +++--- 7 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h index 7c60ef123c..0df14f8051 100644 --- a/src/libsystemd-network/dhcp-internal.h +++ b/src/libsystemd-network/dhcp-internal.h @@ -45,10 +45,10 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_ uint8_t code, size_t optlen, const void *optval); typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len, - const uint8_t *option, void *user_data); + const uint8_t *option, void *userdata); int dhcp_option_parse(DHCPMessage *message, size_t len, - dhcp_option_cb_t cb, void *user_data); + dhcp_option_cb_t cb, void *userdata); int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type, uint16_t arp_type, size_t optlen, diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index e1d2555505..1765fabd4b 100644 --- a/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -88,7 +88,7 @@ struct sd_dhcp_lease { int dhcp_lease_new(sd_dhcp_lease **ret); int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, - void *user_data); + void *userdata); int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, const uint8_t *data, uint8_t len); diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c index b6110c5f16..36be7d54ed 100644 --- a/src/libsystemd-network/dhcp-option.c +++ b/src/libsystemd-network/dhcp-option.c @@ -140,7 +140,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overload, uint8_t *message_type, dhcp_option_cb_t cb, - void *user_data) { + void *userdata) { uint8_t code, len; size_t offset = 0; @@ -199,7 +199,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo return -EINVAL; if (cb) - cb(code, len, &options[offset], user_data); + cb(code, len, &options[offset], userdata); offset += len; @@ -214,7 +214,7 @@ static int parse_options(const uint8_t options[], size_t buflen, uint8_t *overlo } int dhcp_option_parse(DHCPMessage *message, size_t len, - dhcp_option_cb_t cb, void *user_data) { + dhcp_option_cb_t cb, void *userdata) { uint8_t overload = 0; uint8_t message_type = 0; int r; @@ -228,20 +228,20 @@ int dhcp_option_parse(DHCPMessage *message, size_t len, len -= sizeof(DHCPMessage); r = parse_options(message->options, len, &overload, &message_type, - cb, user_data); + cb, userdata); if (r < 0) return r; if (overload & DHCP_OVERLOAD_FILE) { r = parse_options(message->file, sizeof(message->file), - NULL, &message_type, cb, user_data); + NULL, &message_type, cb, userdata); if (r < 0) return r; } if (overload & DHCP_OVERLOAD_SNAME) { r = parse_options(message->sname, sizeof(message->sname), - NULL, &message_type, cb, user_data); + NULL, &message_type, cb, userdata); if (r < 0) return r; } diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index e2cd52ac0c..df74d9f3ae 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -551,8 +551,8 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, } static int parse_request(uint8_t code, uint8_t len, const uint8_t *option, - void *user_data) { - DHCPRequest *req = user_data; + void *userdata) { + DHCPRequest *req = userdata; assert(req); diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index 200499d613..1e0df634a4 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -127,7 +127,7 @@ static void test_checksum(void) } static int check_options(uint8_t code, uint8_t len, const uint8_t *option, - void *user_data) + void *userdata) { switch(code) { case DHCP_OPTION_CLIENT_IDENTIFIER: diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c index a63a4ea738..37f46c8c56 100644 --- a/src/libsystemd-network/test-dhcp-option.c +++ b/src/libsystemd-network/test-dhcp-option.c @@ -145,8 +145,8 @@ static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen) { } } -static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, void *user_data) { - struct option_desc *desc = user_data; +static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, void *userdata) { + struct option_desc *desc = userdata; uint8_t *descoption = NULL; int *desclen = NULL, *descpos = NULL; uint8_t optcode = 0; diff --git a/src/libsystemd-network/test-ipv4ll.c b/src/libsystemd-network/test-ipv4ll.c index 5677bfb2d2..d60ee98b25 100644 --- a/src/libsystemd-network/test-ipv4ll.c +++ b/src/libsystemd-network/test-ipv4ll.c @@ -39,9 +39,9 @@ static int test_fd[2]; static int basic_request_handler_bind = 0; static int basic_request_handler_stop = 0; -static void* basic_request_handler_user_data = (void*)0xCABCAB; +static void* basic_request_handler_userdata = (void*)0xCABCAB; static void basic_request_handler(sd_ipv4ll *ll, int event, void *userdata) { - assert_se(userdata == basic_request_handler_user_data); + assert_se(userdata == basic_request_handler_userdata); switch(event) { case IPV4LL_EVENT_STOP: @@ -175,7 +175,7 @@ static void test_basic_request(sd_event *e) { assert_se(sd_ipv4ll_start(ll) == -EINVAL); assert_se(sd_ipv4ll_set_callback(ll, basic_request_handler, - basic_request_handler_user_data) == 0); + basic_request_handler_userdata) == 0); assert_se(sd_ipv4ll_start(ll) == -EINVAL); assert_se(sd_ipv4ll_set_index(ll, 1) == 0); -- cgit v1.2.3-54-g00ecf From e473522841f630bfd25725b06605462e5e30587f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 23:05:34 +0200 Subject: dhcp: generic data should be void*, not uint8_t* If we handly arbitrary data we should use "void*" pointers, not "uint8_t*", how go intended C to be used. --- src/libsystemd-network/dhcp-internal.h | 2 +- src/libsystemd-network/dhcp-lease-internal.h | 10 +++++----- src/libsystemd-network/network-internal.c | 4 ++-- src/libsystemd-network/network-internal.h | 4 ++-- src/libsystemd-network/sd-dhcp-lease.c | 14 +++++++------- src/libsystemd-network/sd-dhcp-server.c | 2 +- src/libsystemd-network/test-dhcp-client.c | 8 ++++---- src/libsystemd-network/test-dhcp-option.c | 6 +++--- src/systemd/sd-dhcp-lease.h | 6 +++--- 9 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h index 0df14f8051..df6f882af5 100644 --- a/src/libsystemd-network/dhcp-internal.h +++ b/src/libsystemd-network/dhcp-internal.h @@ -45,7 +45,7 @@ int dhcp_option_append(DHCPMessage *message, size_t size, size_t *offset, uint8_ uint8_t code, size_t optlen, const void *optval); typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len, - const uint8_t *option, void *userdata); + const void *option, void *userdata); int dhcp_option_parse(DHCPMessage *message, size_t len, dhcp_option_cb_t cb, void *userdata); diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index 1765fabd4b..ebe6c2f7e7 100644 --- a/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -78,23 +78,23 @@ struct sd_dhcp_lease { char *domainname; char *hostname; char *root_path; - uint8_t *client_id; + void *client_id; size_t client_id_len; - uint8_t *vendor_specific; + void *vendor_specific; size_t vendor_specific_len; char *timezone; LIST_HEAD(struct sd_dhcp_raw_option, private_options); }; int dhcp_lease_new(sd_dhcp_lease **ret); -int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, +int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata); int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, - const uint8_t *data, uint8_t len); + const void *data, uint8_t len); int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease); -int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id, +int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len); DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_lease*, sd_dhcp_lease_unref); diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index d8357c687e..26bd4088d9 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -525,7 +525,7 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t return 0; } -int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size) { +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) { _cleanup_free_ char *hex_buf = NULL; assert(f); @@ -541,7 +541,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t return 0; } -int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string) { +int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) { assert(data); assert(data_len); assert(string); diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index dca82646ce..d5d4ef42f2 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -77,5 +77,5 @@ struct sd_dhcp_route; void serialize_dhcp_routes(FILE *f, const char *key, struct sd_dhcp_route *routes, size_t size); int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); -int serialize_dhcp_option(FILE *f, const char *key, const uint8_t *data, size_t size); -int deserialize_dhcp_option(uint8_t **data, size_t *data_len, const char *string); +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); +int deserialize_dhcp_option(void **data, size_t *data_len, const char *string); diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 75989951cf..328ab152b8 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -179,7 +179,7 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes return 0; } -int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data, +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) { assert_return(lease, -EINVAL); assert_return(data, -EINVAL); @@ -436,7 +436,7 @@ static int lease_parse_classless_routes(const uint8_t *option, size_t len, struc return 0; } -int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, void *userdata) { +int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void *userdata) { sd_dhcp_lease *lease = userdata; int r; @@ -619,7 +619,7 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const uint8_t *option, v } int dhcp_lease_insert_private_option(sd_dhcp_lease *lease, uint8_t tag, - const uint8_t *data, uint8_t len) { + const void *data, uint8_t len) { struct sd_dhcp_raw_option *cur, *option; LIST_FOREACH(options, cur, lease->private_options) { @@ -669,7 +669,7 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { struct sd_dhcp_raw_option *option; struct in_addr address; const struct in_addr *addresses; - const uint8_t *client_id, *data; + const void *client_id, *data; size_t client_id_len, data_len; const char *string; uint16_t mtu; @@ -950,7 +950,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { } for (i = 0; i <= DHCP_OPTION_PRIVATE_LAST - DHCP_OPTION_PRIVATE_BASE; i++) { - _cleanup_free_ uint8_t *data = NULL; + _cleanup_free_ void *data = NULL; size_t len; if (!options[i]) @@ -990,7 +990,7 @@ int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) { return 0; } -int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id, +int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) { assert_return(lease, -EINVAL); assert_return(client_id, -EINVAL); @@ -1001,7 +1001,7 @@ int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id, return 0; } -int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const uint8_t *client_id, +int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t client_id_len) { assert_return(lease, -EINVAL); assert_return((!client_id && !client_id_len) || diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index df74d9f3ae..968df1f43d 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -550,7 +550,7 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, return 0; } -static int parse_request(uint8_t code, uint8_t len, const uint8_t *option, +static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) { DHCPRequest *req = userdata; diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index 1e0df634a4..b2a0d3bb8b 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -126,7 +126,7 @@ static void test_checksum(void) assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae)); } -static int check_options(uint8_t code, uint8_t len, const uint8_t *option, +static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) { switch(code) { @@ -141,10 +141,10 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option, assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len); assert_se(len == 19); - assert_se(option[0] == 0xff); + assert_se(((uint8_t*) option)[0] == 0xff); - assert_se(memcmp(&option[1], &iaid, sizeof(iaid)) == 0); - assert_se(memcmp(&option[5], &duid, duid_len) == 0); + assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0); + assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0); break; } diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c index 37f46c8c56..b1ef174849 100644 --- a/src/libsystemd-network/test-dhcp-option.c +++ b/src/libsystemd-network/test-dhcp-option.c @@ -145,7 +145,7 @@ static void test_ignore_opts(uint8_t *descoption, int *descpos, int *desclen) { } } -static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, void *userdata) { +static int test_options_cb(uint8_t code, uint8_t len, const void *option, void *userdata) { struct option_desc *desc = userdata; uint8_t *descoption = NULL; int *desclen = NULL, *descpos = NULL; @@ -207,10 +207,10 @@ static int test_options_cb(uint8_t code, uint8_t len, const uint8_t *option, voi for (i = 0; i < len; i++) { if (verbose) - printf("0x%02x(0x%02x) ", option[i], + printf("0x%02x(0x%02x) ", ((uint8_t*) option)[i], descoption[*descpos + 2 + i]); - assert_se(option[i] == descoption[*descpos + 2 + i]); + assert_se(((uint8_t*) option)[i] == descoption[*descpos + 2 + i]); } if (verbose) diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h index e142ae03bb..7fa126d198 100644 --- a/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/sd-dhcp-lease.h @@ -44,10 +44,10 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname); int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); -int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routesgn); -int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const uint8_t **data, +int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, struct sd_dhcp_route **routes); +int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len); -int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const uint8_t **client_id, +int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len); int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone); -- cgit v1.2.3-54-g00ecf From 966d74c043098e12d4d5b101aa7650244c14b815 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 23:26:01 +0200 Subject: dhcp: properly handle error from ioctl() --- src/libsystemd-network/sd-dhcp-server.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 968df1f43d..8f6da4bc00 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -901,13 +901,12 @@ static int server_receive_message(sd_event_source *s, int fd, .msg_controllen = sizeof(cmsgbuf), }; struct cmsghdr *cmsg; - int buflen = 0, len, r; + int buflen = 0, len; assert(server); - r = ioctl(fd, FIONREAD, &buflen); - if (r < 0) - return r; + if (ioctl(fd, FIONREAD, &buflen) < 0) + return -errno; if (buflen < 0) return -EIO; -- cgit v1.2.3-54-g00ecf From 9a0f246fcdb1238e6b3397169a10095f4df89210 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 23:30:27 +0200 Subject: dhcp: store client id as void*, since we dont know what it is --- src/libsystemd-network/dhcp-server-internal.h | 2 +- src/libsystemd-network/sd-dhcp-server.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index a5d3554e12..52e2c9308b 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -33,7 +33,7 @@ typedef struct DHCPClientId { size_t length; - uint8_t *data; + void *data; } DHCPClientId; typedef struct DHCPLease { diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 8f6da4bc00..92276af233 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -617,22 +617,23 @@ static int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) { /* set client id based on MAC address if client did not send an explicit one */ if (!req->client_id.data) { - uint8_t *data; + void *data; - data = new0(uint8_t, ETH_ALEN + 1); + data = malloc0(ETH_ALEN + 1); if (!data) return -ENOMEM; + ((uint8_t*) data)[0] = 0x01; + memcpy((uint8_t*) data + 1, &message->chaddr, ETH_ALEN); + req->client_id.length = ETH_ALEN + 1; req->client_id.data = data; - req->client_id.data[0] = 0x01; - memcpy(&req->client_id.data[1], &message->chaddr, ETH_ALEN); } if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE) req->max_optlen = DHCP_MIN_OPTIONS_SIZE; - if (!req->lifetime) + if (req->lifetime <= 0) req->lifetime = DHCP_DEFAULT_LEASE_TIME; return 0; @@ -683,8 +684,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, &req->client_id); switch(type) { - case DHCP_DISCOVER: - { + + case DHCP_DISCOVER: { be32_t address = INADDR_ANY; unsigned i; @@ -734,9 +735,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, return 1; - break; - case DHCP_REQUEST: - { + case DHCP_REQUEST: { be32_t address; bool init_reboot = false; int pool_offset; @@ -858,6 +857,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, break; } + case DHCP_RELEASE: { int pool_offset; -- cgit v1.2.3-54-g00ecf From b3ec603ce8053ba3f95da1d36f15ea762c83d1e1 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 26 Aug 2015 23:31:47 +0200 Subject: dhcp: rename index to ifindex This avoids confusion what this is, in particular as libc knows an index() function. --- src/libsystemd-network/dhcp-server-internal.h | 2 +- src/libsystemd-network/sd-dhcp-server.c | 26 ++++++++------------------ 2 files changed, 9 insertions(+), 19 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 52e2c9308b..74b09d6f37 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -54,7 +54,7 @@ struct sd_dhcp_server { int fd; int fd_raw; - int index; + int ifindex; be32_t address; be32_t netmask; be32_t pool_start; diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 92276af233..bfb799a63d 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -170,7 +170,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { server->fd = -1; server->address = htobe32(INADDR_ANY); server->netmask = htobe32(INADDR_ANY); - server->index = ifindex; + server->ifindex = ifindex; server->leases_by_client_id = hashmap_new(&client_id_hash_ops); *ret = server; @@ -232,13 +232,12 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server, union sockaddr_union link = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htons(ETH_P_IP), - .ll.sll_ifindex = server->index, + .ll.sll_ifindex = server->ifindex, .ll.sll_halen = ETH_ALEN, }; - int r; assert(server); - assert(server->index > 0); + assert(server->ifindex > 0); assert(server->address); assert(packet); assert(len > sizeof(DHCPPacket)); @@ -249,11 +248,7 @@ static int dhcp_server_send_unicast_raw(sd_dhcp_server *server, packet->dhcp.yiaddr, DHCP_PORT_CLIENT, len); - r = dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len); - if (r < 0) - return r; - - return 0; + return dhcp_network_send_raw_socket(server->fd_raw, &link, packet, len); } static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination, @@ -299,7 +294,7 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination, pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg); assert(pktinfo); - pktinfo->ipi_ifindex = server->index; + pktinfo->ipi_ifindex = server->ifindex; pktinfo->ipi_spec_dst.s_addr = server->address; r = sendmsg(server->fd, &msg, 0); @@ -508,11 +503,7 @@ static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) { if (r < 0) return r; - r = dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset); - if (r < 0) - return r; - - return 0; + return dhcp_server_send_packet(server, req, packet, DHCP_NAK, offset); } static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, @@ -550,8 +541,7 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, return 0; } -static int parse_request(uint8_t code, uint8_t len, const void *option, - void *userdata) { +static int parse_request(uint8_t code, uint8_t len, const void *option, void *userdata) { DHCPRequest *req = userdata; assert(req); @@ -931,7 +921,7 @@ static int server_receive_message(sd_event_source *s, int fd, /* TODO figure out if this can be done as a filter on * the socket, like for IPv6 */ - if (server->index != info->ipi_ifindex) + if (server->ifindex != info->ipi_ifindex) return 0; break; -- cgit v1.2.3-54-g00ecf From 586ac6f711e2eccceb12421df22fca4f117226c4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Aug 2015 01:47:42 +0200 Subject: networkd: make DHCP lease timeouts configurable --- src/libsystemd-network/dhcp-server-internal.h | 4 +++- src/libsystemd-network/sd-dhcp-server.c | 34 +++++++++++++++++++++++---- src/network/networkd-link.c | 16 +++++++++++++ src/network/networkd-network-gperf.gperf | 2 ++ src/network/networkd.h | 1 + src/systemd/sd-dhcp-server.h | 3 +++ 6 files changed, 55 insertions(+), 5 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 74b09d6f37..4f562c73ef 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -65,6 +65,8 @@ struct sd_dhcp_server { Hashmap *leases_by_client_id; DHCPLease **bound_leases; + + uint32_t max_lease_time, default_lease_time; }; typedef struct DHCPRequest { @@ -76,7 +78,7 @@ typedef struct DHCPRequest { size_t max_optlen; be32_t server_id; be32_t requested_ip; - int lifetime; + uint32_t lifetime; } DHCPRequest; DEFINE_TRIVIAL_CLEANUP_FUNC(sd_dhcp_server*, sd_dhcp_server_unref); diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index bfb799a63d..35564d8317 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -28,7 +28,8 @@ #include "dhcp-server-internal.h" #include "dhcp-internal.h" -#define DHCP_DEFAULT_LEASE_TIME 3600 /* one hour */ +#define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR +#define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12) int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *address, @@ -172,6 +173,8 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) { server->netmask = htobe32(INADDR_ANY); server->ifindex = ifindex; server->leases_by_client_id = hashmap_new(&client_id_hash_ops); + server->default_lease_time = DIV_ROUND_UP(DHCP_DEFAULT_LEASE_TIME_USEC, USEC_PER_SEC); + server->max_lease_time = DIV_ROUND_UP(DHCP_MAX_LEASE_TIME_USEC, USEC_PER_SEC); *ret = server; server = NULL; @@ -598,7 +601,7 @@ static void dhcp_request_free(DHCPRequest *req) { DEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free); #define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep) -static int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) { +static int ensure_sane_request(sd_dhcp_server *server, DHCPRequest *req, DHCPMessage *message) { assert(req); assert(message); @@ -624,7 +627,10 @@ static int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) { req->max_optlen = DHCP_MIN_OPTIONS_SIZE; if (req->lifetime <= 0) - req->lifetime = DHCP_DEFAULT_LEASE_TIME; + req->lifetime = MAX(1ULL, server->default_lease_time); + + if (server->max_lease_time > 0 && req->lifetime > server->max_lease_time) + req->lifetime = server->max_lease_time; return 0; } @@ -665,7 +671,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, if (type < 0) return 0; - r = ensure_sane_request(req, message); + r = ensure_sane_request(server, req, message); if (r < 0) /* this only fails on critical errors */ return r; @@ -1016,3 +1022,23 @@ int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone) { return 1; } + +int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t) { + assert_return(server, -EINVAL); + + if (t == server->max_lease_time) + return 0; + + server->max_lease_time = t; + return 1; +} + +int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) { + assert_return(server, -EINVAL); + + if (t == server->default_lease_time) + return 0; + + server->default_lease_time = t; + return 1; +} diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 09c27de22b..5b7ebfb79d 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -673,6 +673,22 @@ static int link_enter_set_addresses(Link *link) { return r; */ + if (link->network->dhcp_server_max_lease_time_usec > 0) { + r = sd_dhcp_server_set_max_lease_time( + link->dhcp_server, + DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC)); + if (r < 0) + return r; + } + + if (link->network->dhcp_server_default_lease_time_usec > 0) { + r = sd_dhcp_server_set_default_lease_time( + link->dhcp_server, + DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC)); + if (r < 0) + return r; + } + if (link->network->dhcp_server_emit_timezone) { _cleanup_free_ char *buffer = NULL; const char *tz; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index c8c612d4eb..21e33efb42 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -74,6 +74,8 @@ DHCP.CriticalConnection, config_parse_bool, 0 DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_timezone) +DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) +DHCPServer.DefaultLeaseTimeSec,config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone) DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone) Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost) diff --git a/src/network/networkd.h b/src/network/networkd.h index a337ea7bf0..d5da764bab 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -152,6 +152,7 @@ struct Network { bool dhcp_server; char *dhcp_server_timezone; bool dhcp_server_emit_timezone; + usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec; bool use_bpdu; bool hairpin; diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index a2e1995cf9..e070174a88 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -49,5 +49,8 @@ int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *start, int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone); +int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t); +int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t); + int sd_dhcp_server_forcerenew(sd_dhcp_server *server); #endif -- cgit v1.2.3-54-g00ecf From 1a04db0fc9d08fffe80d6d7b5b60459295922b11 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 27 Aug 2015 14:48:37 +0200 Subject: dhcp,network: support emitting DNS/NTP server information from DHCP server For now, this is very simple and IP addresses have to be configured manually. --- src/libsystemd-network/dhcp-server-internal.h | 3 + src/libsystemd-network/sd-dhcp-server.c | 72 ++++++++++++++++++++ src/network/networkd-link.c | 21 ++++++ src/network/networkd-network-gperf.gperf | 4 ++ src/network/networkd-network.c | 96 +++++++++++++++++++++++++++ src/network/networkd-network.h | 10 ++- src/systemd/sd-dhcp-server.h | 7 +- 7 files changed, 210 insertions(+), 3 deletions(-) (limited to 'src/libsystemd-network/sd-dhcp-server.c') diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 4f562c73ef..6cc794c937 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -63,6 +63,9 @@ struct sd_dhcp_server { char *timezone; + struct in_addr *ntp, *dns; + unsigned n_ntp, n_dns; + Hashmap *leases_by_client_id; DHCPLease **bound_leases; diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 35564d8317..a46858258b 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -145,6 +145,8 @@ sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) { sd_event_unref(server->event); free(server->timezone); + free(server->dns); + free(server->ntp); while ((lease = hashmap_steal_first(server->leases_by_client_id))) dhcp_lease_free(lease); @@ -481,6 +483,24 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req, if (r < 0) return r; + if (server->n_dns > 0) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + DHCP_OPTION_DOMAIN_NAME_SERVER, + sizeof(struct in_addr) * server->n_dns, server->dns); + if (r < 0) + return r; + } + + if (server->n_ntp > 0) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + DHCP_OPTION_NTP_SERVER, + sizeof(struct in_addr) * server->n_ntp, server->ntp); + if (r < 0) + return r; + } + if (server->timezone) { r = dhcp_option_append( &packet->dhcp, req->max_optlen, &offset, 0, @@ -1042,3 +1062,55 @@ int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t) { server->default_lease_time = t; return 1; } + +int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n) { + assert_return(server, -EINVAL); + assert_return(dns || n <= 0, -EINVAL); + + if (server->n_dns == n && + memcmp(server->dns, dns, sizeof(struct in_addr) * n) == 0) + return 0; + + if (n <= 0) { + server->dns = mfree(server->dns); + server->n_dns = 0; + } else { + struct in_addr *c; + + c = newdup(struct in_addr, dns, n); + if (!c) + return -ENOMEM; + + free(server->dns); + server->dns = c; + server->n_dns = n; + } + + return 1; +} + +int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n) { + assert_return(server, -EINVAL); + assert_return(ntp || n <= 0, -EINVAL); + + if (server->n_ntp == n && + memcmp(server->ntp, ntp, sizeof(struct in_addr) * n) == 0) + return 0; + + if (n <= 0) { + server->ntp = mfree(server->ntp); + server->n_ntp = 0; + } else { + struct in_addr *c; + + c = newdup(struct in_addr, ntp, n); + if (!c) + return -ENOMEM; + + free(server->ntp); + server->ntp = c; + server->n_ntp = n; + } + + return 1; +} diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0a72c14469..0d85005c8c 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -691,6 +691,27 @@ static int link_enter_set_addresses(Link *link) { return r; } + if (link->network->dhcp_server_emit_dns) { + + if (link->network->n_dhcp_server_dns > 0) { + r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); + if (r < 0) + log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); + } else + log_link_warning_errno(link, r, "DNS server emitting enabled, but no DNS servers set, ignoring: %m"); + } + + + if (link->network->dhcp_server_emit_ntp) { + + if (link->network->n_dhcp_server_ntp > 0) { + r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); + if (r < 0) + log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); + } else + log_link_warning_errno(link, r, "NTP server emitting enabled, but no NTP servers set, ignoring: %m"); + } + if (link->network->dhcp_server_emit_timezone) { _cleanup_free_ char *buffer = NULL; const char *tz; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 21e33efb42..108e892fb8 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -76,6 +76,10 @@ DHCP.RouteMetric, config_parse_unsigned, 0 DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_timezone) DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) DHCPServer.DefaultLeaseTimeSec,config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) +DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns) +DHCPServer.DNS, config_parse_dhcp_server_dns, 0, 0 +DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_ntp) +DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0 DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone) DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone) Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 11671b500d..848ec66151 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -260,6 +260,8 @@ void network_free(Network *network) { condition_free_list(network->match_arch); free(network->dhcp_server_timezone); + free(network->dhcp_server_dns); + free(network->dhcp_server_ntp); free(network); } @@ -802,3 +804,97 @@ int config_parse_timezone( return 0; } + +int config_parse_dhcp_server_dns( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + struct in_addr a, *m; + + r = extract_first_word(&p, &w, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + + if (r == 0) + return 0; + + if (inet_pton(AF_INET, w, &a) <= 0) { + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server address, ignoring: %s", w); + continue; + } + + m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[n->n_dhcp_server_dns++] = a; + n->dhcp_server_dns = m; + } +} + +int config_parse_dhcp_server_ntp( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *n = data; + const char *p = rvalue; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + + for (;;) { + _cleanup_free_ char *w = NULL; + struct in_addr a, *m; + + r = extract_first_word(&p, &w, NULL, 0); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, r, line, "Failed to extract word, ignoring: %s", rvalue); + return 0; + } + + if (r == 0) + return 0; + + if (inet_pton(AF_INET, w, &a) <= 0) { + log_syntax(unit, LOG_ERR, filename, r, line, "Failed to parse NTP server address, ignoring: %s", w); + continue; + } + + m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr)); + if (!m) + return log_oom(); + + m[n->n_dhcp_server_ntp++] = a; + n->dhcp_server_ntp = m; + } +} diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 7d2add300f..d691cc3a45 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -93,8 +93,14 @@ struct Network { /* DHCP Server Support */ bool dhcp_server; - char *dhcp_server_timezone; + bool dhcp_server_emit_dns; + struct in_addr *dhcp_server_dns; + unsigned n_dhcp_server_dns; + bool dhcp_server_emit_ntp; + struct in_addr *dhcp_server_ntp; + unsigned n_dhcp_server_ntp; bool dhcp_server_emit_timezone; + char *dhcp_server_timezone; usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec; /* IPV4LL Support */ @@ -156,6 +162,8 @@ int config_parse_ipv6token(const char *unit, const char *filename, unsigned line int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_timezone(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); /* Legacy IPv4LL support */ int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index e070174a88..7e4f2ffb30 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -30,11 +30,11 @@ typedef struct sd_dhcp_server sd_dhcp_server; +int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex); + sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server); sd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server); -int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex); - int sd_dhcp_server_attach_event(sd_dhcp_server *client, sd_event *event, int priority); int sd_dhcp_server_detach_event(sd_dhcp_server *client); sd_event *sd_dhcp_server_get_event(sd_dhcp_server *client); @@ -48,9 +48,12 @@ int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address, int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *start, size_t size); int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone); +int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n); +int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr dns[], unsigned n); int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint32_t t); int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint32_t t); int sd_dhcp_server_forcerenew(sd_dhcp_server *server); + #endif -- cgit v1.2.3-54-g00ecf