network: support port number and SNI in [Network] DNS=
This commit is contained in:
parent
8aa5afd20f
commit
e77bd3fdff
|
@ -61,10 +61,10 @@ static int link_push_uplink_to_dhcp_server(
|
|||
struct in_addr ia;
|
||||
|
||||
/* Only look for IPv4 addresses */
|
||||
if (link->network->dns[i].family != AF_INET)
|
||||
if (link->network->dns[i]->family != AF_INET)
|
||||
continue;
|
||||
|
||||
ia = link->network->dns[i].address.in;
|
||||
ia = link->network->dns[i]->address.in;
|
||||
|
||||
/* Never propagate obviously borked data */
|
||||
if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "networkd-manager.h"
|
||||
#include "parse-util.h"
|
||||
#include "resolve-util.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
|
||||
|
@ -114,7 +115,7 @@ int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_
|
|||
}
|
||||
|
||||
int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_free_ struct in_addr_data *dns = NULL;
|
||||
struct in_addr_full **dns = NULL;
|
||||
size_t allocated = 0, n = 0;
|
||||
Link *l = userdata;
|
||||
int r;
|
||||
|
@ -131,6 +132,7 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_
|
|||
return r;
|
||||
|
||||
for (;;) {
|
||||
union in_addr_union a;
|
||||
int family;
|
||||
size_t sz;
|
||||
const void *d;
|
||||
|
@ -139,50 +141,67 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_
|
|||
|
||||
r = sd_bus_message_enter_container(message, 'r', "iay");
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto finalize;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto finalize;
|
||||
|
||||
if (!IN_SET(family, AF_INET, AF_INET6))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
|
||||
if (!IN_SET(family, AF_INET, AF_INET6)) {
|
||||
r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read_array(message, 'y', &d, &sz);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (sz != FAMILY_ADDRESS_SIZE(family))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
|
||||
goto finalize;
|
||||
if (sz != FAMILY_ADDRESS_SIZE(family)) {
|
||||
r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
if (!dns_server_address_valid(family, d))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
|
||||
if (!dns_server_address_valid(family, d)) {
|
||||
r = sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto finalize;
|
||||
|
||||
if (!GREEDY_REALLOC(dns, allocated, n+1))
|
||||
return -ENOMEM;
|
||||
if (!GREEDY_REALLOC(dns, allocated, n+1)) {
|
||||
r = -ENOMEM;
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
memcpy(&a, d, sz);
|
||||
r = in_addr_full_new(family, &a, 0, 0, NULL, dns + n);
|
||||
if (r < 0)
|
||||
goto finalize;
|
||||
|
||||
dns[n].family = family;
|
||||
memcpy(&dns[n].address, d, sz);
|
||||
n++;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
goto finalize;
|
||||
|
||||
r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
|
||||
"org.freedesktop.network1.set-dns-servers",
|
||||
NULL, true, UID_INVALID,
|
||||
&l->manager->polkit_registry, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 1; /* Polkit will call us back */
|
||||
goto finalize;
|
||||
if (r == 0) {
|
||||
r = 1; /* Polkit will call us back */
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
if (l->n_dns != (unsigned) -1)
|
||||
for (unsigned i = 0; i < l->n_dns; i++)
|
||||
in_addr_full_free(l->dns[i]);
|
||||
|
||||
free_and_replace(l->dns, dns);
|
||||
l->n_dns = n;
|
||||
|
@ -190,6 +209,13 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_
|
|||
(void) link_dirty(l);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
|
||||
finalize:
|
||||
for (size_t i = 0; i < n; i++)
|
||||
in_addr_full_free(dns[i]);
|
||||
free(dns);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
|
|
|
@ -666,6 +666,9 @@ void link_ntp_settings_clear(Link *link) {
|
|||
}
|
||||
|
||||
void link_dns_settings_clear(Link *link) {
|
||||
if (link->n_dns != (unsigned) -1)
|
||||
for (unsigned i = 0; i < link->n_dns; i++)
|
||||
in_addr_full_free(link->dns[i]);
|
||||
link->dns = mfree(link->dns);
|
||||
link->n_dns = (unsigned) -1;
|
||||
|
||||
|
@ -4108,20 +4111,17 @@ static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) {
|
|||
fputc('\n', f);
|
||||
}
|
||||
|
||||
static void link_save_dns(FILE *f, struct in_addr_data *dns, unsigned n_dns, bool *space) {
|
||||
static void link_save_dns(FILE *f, struct in_addr_full **dns, unsigned n_dns, bool *space) {
|
||||
for (unsigned j = 0; j < n_dns; j++) {
|
||||
_cleanup_free_ char *b = NULL;
|
||||
int r;
|
||||
const char *str;
|
||||
|
||||
r = in_addr_to_string(dns[j].family, &dns[j].address, &b);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to format address, ignoring: %m");
|
||||
str = in_addr_full_to_string(dns[j]);
|
||||
if (!str)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*space)
|
||||
fputc(' ', f);
|
||||
fputs(b, f);
|
||||
fputs(str, f);
|
||||
*space = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ typedef struct Link {
|
|||
bool stats_updated;
|
||||
|
||||
/* All kinds of DNS configuration the user configured via D-Bus */
|
||||
struct in_addr_data *dns;
|
||||
struct in_addr_full **dns;
|
||||
unsigned n_dns;
|
||||
OrderedSet *search_domains, *route_domains;
|
||||
|
||||
|
|
|
@ -1425,33 +1425,33 @@ static int manager_connect_rtnl(Manager *m) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in_addr_data(OrderedSet *s, const struct in_addr_data *address) {
|
||||
char *p;
|
||||
static int ordered_set_put_dns_server(OrderedSet *s, struct in_addr_full *dns) {
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
assert(dns);
|
||||
|
||||
r = in_addr_to_string(address->family, &address->address, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
p = in_addr_full_to_string(dns);
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
r = ordered_set_consume(s, p);
|
||||
r = ordered_set_put_strdup(s, p);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ordered_set_put_in_addr_datav(OrderedSet *s, const struct in_addr_data *addresses, unsigned n) {
|
||||
static int ordered_set_put_dns_servers(OrderedSet *s, struct in_addr_full **dns, unsigned n) {
|
||||
int r, c = 0;
|
||||
unsigned i;
|
||||
|
||||
assert(s);
|
||||
assert(addresses || n == 0);
|
||||
assert(dns || n == 0);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
r = ordered_set_put_in_addr_data(s, addresses+i);
|
||||
r = ordered_set_put_dns_server(s, dns[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -1558,7 +1558,7 @@ static int manager_save(Manager *m) {
|
|||
continue;
|
||||
|
||||
/* First add the static configured entries */
|
||||
r = ordered_set_put_in_addr_datav(dns, link->network->dns, link->network->n_dns);
|
||||
r = ordered_set_put_dns_servers(dns, link->network->dns, link->network->n_dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -682,6 +682,8 @@ static Network *network_free(Network *network) {
|
|||
sd_ipv4acd_unref(network->dhcp_acd);
|
||||
|
||||
strv_free(network->ntp);
|
||||
for (unsigned i = 0; i < network->n_dns; i++)
|
||||
in_addr_full_free(network->dns[i]);
|
||||
free(network->dns);
|
||||
ordered_set_free_free(network->search_domains);
|
||||
ordered_set_free_free(network->route_domains);
|
||||
|
@ -1194,16 +1196,17 @@ int config_parse_dns(
|
|||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
for (unsigned i = 0; i < n->n_dns; i++)
|
||||
in_addr_full_free(n->dns[i]);
|
||||
n->dns = mfree(n->dns);
|
||||
n->n_dns = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const char *p = rvalue;;) {
|
||||
_cleanup_(in_addr_full_freep) struct in_addr_full *dns = NULL;
|
||||
_cleanup_free_ char *w = NULL;
|
||||
union in_addr_union a;
|
||||
struct in_addr_data *m;
|
||||
int family;
|
||||
struct in_addr_full **m;
|
||||
|
||||
r = extract_first_word(&p, &w, NULL, 0);
|
||||
if (r == -ENOMEM)
|
||||
|
@ -1216,22 +1219,21 @@ int config_parse_dns(
|
|||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
r = in_addr_from_string_auto(w, &family, &a);
|
||||
r = in_addr_full_new_from_string(w, &dns);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to parse dns server address, ignoring: %s", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_data));
|
||||
if (IN_SET(dns->port, 53, 853))
|
||||
dns->port = 0;
|
||||
|
||||
m = reallocarray(n->dns, n->n_dns + 1, sizeof(struct in_addr_full*));
|
||||
if (!m)
|
||||
return log_oom();
|
||||
|
||||
m[n->n_dns++] = (struct in_addr_data) {
|
||||
.family = family,
|
||||
.address = a,
|
||||
};
|
||||
|
||||
m[n->n_dns++] = TAKE_PTR(dns);
|
||||
n->dns = m;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "networkd-util.h"
|
||||
#include "ordered-set.h"
|
||||
#include "resolve-util.h"
|
||||
#include "socket-netlink.h"
|
||||
|
||||
typedef enum IPv6PrivacyExtensions {
|
||||
/* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */
|
||||
|
@ -316,7 +317,7 @@ struct Network {
|
|||
OrderedHashmap *sr_iov_by_section;
|
||||
|
||||
/* All kinds of DNS configuration */
|
||||
struct in_addr_data *dns;
|
||||
struct in_addr_full **dns;
|
||||
unsigned n_dns;
|
||||
OrderedSet *search_domains, *route_domains;
|
||||
|
||||
|
|
|
@ -463,10 +463,10 @@ static int radv_get_ip6dns(Network *network, struct in6_addr **dns,
|
|||
for (i = 0; i < network->n_dns; i++) {
|
||||
union in_addr_union *addr;
|
||||
|
||||
if (network->dns[i].family != AF_INET6)
|
||||
if (network->dns[i]->family != AF_INET6)
|
||||
continue;
|
||||
|
||||
addr = &network->dns[i].address;
|
||||
addr = &network->dns[i]->address;
|
||||
|
||||
if (in_addr_is_null(AF_INET6, addr) ||
|
||||
in_addr_is_link_local(AF_INET6, addr) ||
|
||||
|
|
Loading…
Reference in a new issue