]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dhcp,network: support emitting DNS/NTP server information from DHCP server
authorLennart Poettering <lennart@poettering.net>
Thu, 27 Aug 2015 12:48:37 +0000 (14:48 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 27 Aug 2015 12:48:37 +0000 (14:48 +0200)
For now, this is very simple and IP addresses have to be configured
manually.

src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/sd-dhcp-server.c
src/network/networkd-link.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/systemd/sd-dhcp-server.h

index 4f562c73ef2c8bd4a7af27654aaf31c38ab91ff5..6cc794c937777790d140d43695d24be14982ea69 100644 (file)
@@ -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;
 
index 35564d83179c0be92ef752f85fa27e56d39bed09..a46858258b3affc2c254bd3fbf206acd7f8c7af4 100644 (file)
@@ -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;
+}
index 0a72c14469bf466284632ef8762bf14dcfe62e0d..0d85005c8cc10b54250aea51d33d9b4625885f66 100644 (file)
@@ -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;
index 21e33efb426fc710e1c2c56d9bd8fe1c9f686b2b..108e892fb8623b7804e167914dbfce8327acfff8 100644 (file)
@@ -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)
index 11671b500d8a55716feba8426c4eaf9cc9524aea..848ec661510ae12ffef9c83ac5c570f0dfbc5995 100644 (file)
@@ -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;
+        }
+}
index 7d2add300f3362a383de96ca4fdb367ad7f71ce3..d691cc3a45a99f7a9ad78075ce201ad77d6a3c38 100644 (file)
@@ -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);
index e070174a88887e3bf04d52819ac391d181ddf96b..7e4f2ffb3027189571ad7752ac82593355db7e86 100644 (file)
 
 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