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.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user