mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-12 09:17:44 +03:00
Merge pull request #15460 from elmarco/network-dhcp-resolve1
network: fallback on resolve1 DNS for DHCP
This commit is contained in:
commit
2d5996c175
@ -2,14 +2,17 @@
|
||||
|
||||
#include "sd-dhcp-server.h"
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "networkd-dhcp-server.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-network.h"
|
||||
#include "parse-util.h"
|
||||
#include "strv.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
static Address* link_find_dhcp_server_address(Link *link) {
|
||||
Address *address;
|
||||
@ -174,6 +177,87 @@ static int link_push_uplink_to_dhcp_server(
|
||||
return sd_dhcp_server_set_servers(s, what, addresses, n_addresses);
|
||||
}
|
||||
|
||||
static int dhcp4_server_parse_dns_server_string_and_warn(Link *l, const char *string, struct in_addr **addresses, size_t *n_allocated, size_t *n_addresses) {
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL, *server_name = NULL;
|
||||
union in_addr_union address;
|
||||
int family, r, ifindex = 0;
|
||||
|
||||
r = extract_first_word(&string, &word, NULL, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = in_addr_ifindex_name_from_string_auto(word, &family, &address, &ifindex, &server_name);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring: %m", word);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Only look for IPv4 addresses */
|
||||
if (family != AF_INET)
|
||||
continue;
|
||||
|
||||
/* Never propagate obviously borked data */
|
||||
if (in4_addr_is_null(&address.in) || in4_addr_is_localhost(&address.in))
|
||||
continue;
|
||||
|
||||
if (!GREEDY_REALLOC(*addresses, *n_allocated, *n_addresses + 1))
|
||||
return log_oom();
|
||||
|
||||
(*addresses)[(*n_addresses)++] = address.in;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp4_server_set_dns_from_resolve_conf(Link *link) {
|
||||
_cleanup_free_ struct in_addr *addresses = NULL;
|
||||
size_t n_addresses = 0, n_allocated = 0;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
int n = 0, r;
|
||||
|
||||
f = fopen(PRIVATE_UPLINK_RESOLV_CONF, "re");
|
||||
if (!f) {
|
||||
if (errno == ENOENT)
|
||||
return 0;
|
||||
|
||||
return log_warning_errno(errno, "Failed to open " PRIVATE_UPLINK_RESOLV_CONF ": %m");
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *line = NULL;
|
||||
const char *a;
|
||||
char *l;
|
||||
|
||||
r = read_line(f, LONG_LINE_MAX, &line);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read " PRIVATE_UPLINK_RESOLV_CONF ": %m");
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
n++;
|
||||
|
||||
l = strstrip(line);
|
||||
if (IN_SET(*l, '#', ';', 0))
|
||||
continue;
|
||||
|
||||
a = first_word(l, "nameserver");
|
||||
if (!a)
|
||||
continue;
|
||||
|
||||
r = dhcp4_server_parse_dns_server_string_and_warn(link, a, &addresses, &n_allocated, &n_addresses);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a);
|
||||
}
|
||||
|
||||
if (n_addresses <= 0)
|
||||
return 0;
|
||||
|
||||
return sd_dhcp_server_set_dns(link->dhcp_server, addresses, n_addresses);
|
||||
}
|
||||
|
||||
int dhcp4_server_configure(Link *link) {
|
||||
bool acquired_uplink = false;
|
||||
sd_dhcp_option *p;
|
||||
@ -267,8 +351,10 @@ int dhcp4_server_configure(Link *link) {
|
||||
"Not emitting %s on link, couldn't find suitable uplink.",
|
||||
dhcp_lease_info_to_string(n));
|
||||
r = 0;
|
||||
} else
|
||||
} else if (uplink->network)
|
||||
r = link_push_uplink_to_dhcp_server(uplink, n, link->dhcp_server);
|
||||
else if (n == SD_DHCP_LEASE_DNS_SERVERS)
|
||||
r = dhcp4_server_set_dns_from_resolve_conf(link);
|
||||
}
|
||||
if (r < 0)
|
||||
log_link_warning_errno(link, r,
|
||||
|
@ -64,8 +64,6 @@ systemd_resolved_sources = files('''
|
||||
resolved-etc-hosts.h
|
||||
resolved-etc-hosts.c
|
||||
resolved-dnstls.h
|
||||
resolved-util.c
|
||||
resolved-util.h
|
||||
'''.split())
|
||||
|
||||
resolvectl_sources = files('''
|
||||
@ -230,10 +228,4 @@ tests += [
|
||||
[],
|
||||
[],
|
||||
'ENABLE_RESOLVE', 'manual'],
|
||||
|
||||
[['src/resolve/test-resolved-util.c',
|
||||
'src/resolve/resolved-util.c',
|
||||
'src/resolve/resolved-util.h'],
|
||||
[],
|
||||
[]],
|
||||
]
|
||||
|
@ -8,10 +8,10 @@
|
||||
#include "parse-util.h"
|
||||
#include "resolved-conf.h"
|
||||
#include "resolved-dnssd.h"
|
||||
#include "resolved-util.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "dns-domain.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "specifier.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "macro.h"
|
||||
#include "resolved-util.h"
|
||||
#include "socket-netlink.h"
|
||||
|
||||
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name) {
|
||||
_cleanup_free_ char *buf = NULL, *name = NULL;
|
||||
const char *m;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
m = strchr(s, '#');
|
||||
if (m) {
|
||||
name = strdup(m+1);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
buf = strndup(s, m - s);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
s = buf;
|
||||
}
|
||||
|
||||
r = in_addr_ifindex_from_string_auto(s, family, ret, ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (server_name)
|
||||
*server_name = TAKE_PTR(name);
|
||||
|
||||
return r;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "in-addr-util.h"
|
||||
|
||||
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name);
|
@ -1,32 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "log.h"
|
||||
#include "resolved-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
|
||||
int family, ifindex;
|
||||
union in_addr_union ua;
|
||||
_cleanup_free_ char *server_name = NULL;
|
||||
|
||||
assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
|
||||
assert_se(streq_ptr(server_name, expected));
|
||||
}
|
||||
|
||||
static void test_in_addr_ifindex_name_from_string_auto(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
|
||||
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
|
||||
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
|
||||
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_in_addr_ifindex_name_from_string_auto();
|
||||
return 0;
|
||||
}
|
@ -362,3 +362,33 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name) {
|
||||
_cleanup_free_ char *buf = NULL, *name = NULL;
|
||||
const char *m;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
m = strchr(s, '#');
|
||||
if (m) {
|
||||
name = strdup(m+1);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
buf = strndup(s, m - s);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
s = buf;
|
||||
}
|
||||
|
||||
r = in_addr_ifindex_from_string_auto(s, family, ret, ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (server_name)
|
||||
*server_name = TAKE_PTR(name);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -21,3 +21,4 @@ bool socket_address_is(const SocketAddress *a, const char *s, int type);
|
||||
bool socket_address_is_netlink(const SocketAddress *a, const char *s);
|
||||
|
||||
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex);
|
||||
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name);
|
||||
|
@ -245,6 +245,24 @@ static void test_in_addr_ifindex_from_string_auto(void) {
|
||||
assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
|
||||
}
|
||||
|
||||
static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
|
||||
int family, ifindex;
|
||||
union in_addr_union ua;
|
||||
_cleanup_free_ char *server_name = NULL;
|
||||
|
||||
assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
|
||||
assert_se(streq_ptr(server_name, expected));
|
||||
}
|
||||
|
||||
static void test_in_addr_ifindex_name_from_string_auto(void) {
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
|
||||
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
|
||||
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
|
||||
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
|
||||
}
|
||||
|
||||
static void test_sockaddr_equal(void) {
|
||||
union sockaddr_union a = {
|
||||
.in.sin_family = AF_INET,
|
||||
@ -676,6 +694,7 @@ int main(int argc, char *argv[]) {
|
||||
test_in_addr_to_string();
|
||||
test_in_addr_ifindex_to_string();
|
||||
test_in_addr_ifindex_from_string_auto();
|
||||
test_in_addr_ifindex_name_from_string_auto();
|
||||
|
||||
test_sockaddr_equal();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user