mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 08:56:15 +09:00
Merge pull request #3432 from poettering/resolved-ll-ipv6
resolved: support IPv6 DNS servers on the local link
This commit is contained in:
17
CODING_STYLE
17
CODING_STYLE
@@ -382,3 +382,20 @@
|
||||
tools, and we should continue to do so, as it makes it easy to
|
||||
identify command line parameter variables, and makes it clear why it
|
||||
is OK that they are global variables.
|
||||
|
||||
- When exposing public C APIs, be careful what function parameters you make
|
||||
"const". For example, a parameter taking a context object should probably not
|
||||
be "const", even if you are writing an other-wise read-only accessor function
|
||||
for it. The reason is that making it "const" fixates the contract that your
|
||||
call won't alter the object ever, as part of the API. However, that's often
|
||||
quite a promise, given that this even prohibits object-internal caching or
|
||||
lazy initialization of object variables. Moreover it's usually not too useful
|
||||
for client applications. Hence: please be careful and avoid "const" on object
|
||||
parameters, unless you are very sure "const" is appropriate.
|
||||
|
||||
- Make sure to enforce limits on every user controllable resource. If the user
|
||||
can allocate resources in your code, your code must enforce some form of
|
||||
limits after which it will refuse operation. It's fine if it is hardcoded (at
|
||||
least initially), but it needs to be there. This is particularly important
|
||||
for objects that unprivileged users may allocate, but also matters for
|
||||
everything else any user may allocated.
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "util.h"
|
||||
|
||||
bool in4_addr_is_null(const struct in_addr *a) {
|
||||
@@ -232,6 +234,48 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
|
||||
size_t l;
|
||||
char *x;
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
assert(ret);
|
||||
|
||||
/* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly
|
||||
* handle IPv6 link-local addresses. */
|
||||
|
||||
if (family != AF_INET6)
|
||||
goto fallback;
|
||||
if (ifindex <= 0)
|
||||
goto fallback;
|
||||
|
||||
r = in_addr_is_link_local(family, u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
goto fallback;
|
||||
|
||||
l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1;
|
||||
x = new(char, l);
|
||||
if (!x)
|
||||
return -ENOMEM;
|
||||
|
||||
errno = 0;
|
||||
if (!inet_ntop(family, u, x, l)) {
|
||||
free(x);
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
}
|
||||
|
||||
sprintf(strchr(x, 0), "%%%i", ifindex);
|
||||
*ret = x;
|
||||
|
||||
return 0;
|
||||
|
||||
fallback:
|
||||
return in_addr_to_string(family, u, ret);
|
||||
}
|
||||
|
||||
int in_addr_from_string(int family, const char *s, union in_addr_union *ret) {
|
||||
|
||||
assert(s);
|
||||
@@ -269,6 +313,47 @@ int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *re
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) {
|
||||
const char *suffix;
|
||||
int r, ifi = 0;
|
||||
|
||||
assert(s);
|
||||
assert(family);
|
||||
assert(ret);
|
||||
|
||||
/* Similar to in_addr_from_string_auto() but also parses an optionally appended IPv6 zone suffix ("scope id")
|
||||
* if one is found. */
|
||||
|
||||
suffix = strchr(s, '%');
|
||||
if (suffix) {
|
||||
|
||||
if (ifindex) {
|
||||
/* If we shall return the interface index, try to parse it */
|
||||
r = parse_ifindex(suffix + 1, &ifi);
|
||||
if (r < 0) {
|
||||
unsigned u;
|
||||
|
||||
u = if_nametoindex(suffix + 1);
|
||||
if (u <= 0)
|
||||
return -errno;
|
||||
|
||||
ifi = (int) u;
|
||||
}
|
||||
}
|
||||
|
||||
s = strndupa(s, suffix - s);
|
||||
}
|
||||
|
||||
r = in_addr_from_string_auto(s, family, ret);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ifindex)
|
||||
*ifindex = ifi;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr) {
|
||||
assert(addr);
|
||||
|
||||
|
||||
@@ -46,8 +46,10 @@ int in_addr_equal(int family, const union in_addr_union *a, const union in_addr_
|
||||
int in_addr_prefix_intersect(int family, const union in_addr_union *a, unsigned aprefixlen, const union in_addr_union *b, unsigned bprefixlen);
|
||||
int in_addr_prefix_next(int family, union in_addr_union *u, unsigned prefixlen);
|
||||
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
|
||||
int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret);
|
||||
int in_addr_from_string(int family, const char *s, union in_addr_union *ret);
|
||||
int in_addr_from_string_auto(const char *s, int *family, union in_addr_union *ret);
|
||||
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex);
|
||||
unsigned char in_addr_netmask_to_prefixlen(const struct in_addr *addr);
|
||||
struct in_addr* in_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen);
|
||||
int in_addr_default_prefixlen(const struct in_addr *addr, unsigned char *prefixlen);
|
||||
|
||||
@@ -1221,7 +1221,7 @@ int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex
|
||||
return r;
|
||||
|
||||
if (with_ifindex) {
|
||||
r = sd_bus_message_append(reply, "i", s->link ? s->link->ifindex : 0);
|
||||
r = sd_bus_message_append(reply, "i", dns_server_ifindex(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -27,18 +27,18 @@
|
||||
|
||||
int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
|
||||
union in_addr_union address;
|
||||
int family, r;
|
||||
int family, r, ifindex = 0;
|
||||
DnsServer *s;
|
||||
|
||||
assert(m);
|
||||
assert(word);
|
||||
|
||||
r = in_addr_from_string_auto(word, &family, &address);
|
||||
r = in_addr_ifindex_from_string_auto(word, &family, &address, &ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Filter out duplicates */
|
||||
s = dns_server_find(manager_get_first_dns_server(m, type), family, &address);
|
||||
s = dns_server_find(manager_get_first_dns_server(m, type), family, &address, ifindex);
|
||||
if (s) {
|
||||
/*
|
||||
* Drop the marker. This is used to find the servers
|
||||
@@ -50,7 +50,7 @@ int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dns_server_new(m, NULL, type, NULL, family, &address);
|
||||
return dns_server_new(m, NULL, type, NULL, family, &address, ifindex);
|
||||
}
|
||||
|
||||
int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) {
|
||||
@@ -70,7 +70,7 @@ int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, con
|
||||
|
||||
r = manager_add_dns_server_by_string(m, type, word);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to add DNS server address '%s', ignoring.", word);
|
||||
log_warning_errno(r, "Failed to add DNS server address '%s', ignoring: %m", word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -125,7 +125,7 @@ int manager_parse_search_domains_and_warn(Manager *m, const char *string) {
|
||||
|
||||
r = manager_add_search_domain_by_string(m, word);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to add search domain '%s', ignoring.", word);
|
||||
log_warning_errno(r, "Failed to add search domain '%s', ignoring: %m", word);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -307,7 +307,7 @@ static int dns_scope_socket(
|
||||
union sockaddr_union sa = {};
|
||||
socklen_t salen;
|
||||
static const int one = 1;
|
||||
int ret, r;
|
||||
int ret, r, ifindex;
|
||||
|
||||
assert(s);
|
||||
|
||||
@@ -315,6 +315,8 @@ static int dns_scope_socket(
|
||||
assert(family == AF_UNSPEC);
|
||||
assert(!address);
|
||||
|
||||
ifindex = dns_server_ifindex(server);
|
||||
|
||||
sa.sa.sa_family = server->family;
|
||||
if (server->family == AF_INET) {
|
||||
sa.in.sin_port = htobe16(port);
|
||||
@@ -323,7 +325,7 @@ static int dns_scope_socket(
|
||||
} else if (server->family == AF_INET6) {
|
||||
sa.in6.sin6_port = htobe16(port);
|
||||
sa.in6.sin6_addr = server->address.in6;
|
||||
sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
|
||||
sa.in6.sin6_scope_id = ifindex;
|
||||
salen = sizeof(sa.in6);
|
||||
} else
|
||||
return -EAFNOSUPPORT;
|
||||
@@ -332,6 +334,7 @@ static int dns_scope_socket(
|
||||
assert(address);
|
||||
|
||||
sa.sa.sa_family = family;
|
||||
ifindex = s->link ? s->link->ifindex : 0;
|
||||
|
||||
if (family == AF_INET) {
|
||||
sa.in.sin_port = htobe16(port);
|
||||
@@ -340,7 +343,7 @@ static int dns_scope_socket(
|
||||
} else if (family == AF_INET6) {
|
||||
sa.in6.sin6_port = htobe16(port);
|
||||
sa.in6.sin6_addr = address->in6;
|
||||
sa.in6.sin6_scope_id = s->link ? s->link->ifindex : 0;
|
||||
sa.in6.sin6_scope_id = ifindex;
|
||||
salen = sizeof(sa.in6);
|
||||
} else
|
||||
return -EAFNOSUPPORT;
|
||||
@@ -357,14 +360,14 @@ static int dns_scope_socket(
|
||||
}
|
||||
|
||||
if (s->link) {
|
||||
uint32_t ifindex = htobe32(s->link->ifindex);
|
||||
be32_t ifindex_be = htobe32(ifindex);
|
||||
|
||||
if (sa.sa.sa_family == AF_INET) {
|
||||
r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
|
||||
r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
} else if (sa.sa.sa_family == AF_INET6) {
|
||||
r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
|
||||
r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ int dns_server_new(
|
||||
DnsServerType type,
|
||||
Link *l,
|
||||
int family,
|
||||
const union in_addr_union *in_addr) {
|
||||
const union in_addr_union *in_addr,
|
||||
int ifindex) {
|
||||
|
||||
DnsServer *s;
|
||||
|
||||
@@ -75,6 +76,7 @@ int dns_server_new(
|
||||
s->type = type;
|
||||
s->family = family;
|
||||
s->address = *in_addr;
|
||||
s->ifindex = ifindex;
|
||||
s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
|
||||
|
||||
switch (type) {
|
||||
@@ -518,11 +520,24 @@ int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeature
|
||||
return dns_packet_append_opt(packet, packet_size, edns_do, NULL);
|
||||
}
|
||||
|
||||
int dns_server_ifindex(const DnsServer *s) {
|
||||
assert(s);
|
||||
|
||||
/* The link ifindex always takes precedence */
|
||||
if (s->link)
|
||||
return s->link->ifindex;
|
||||
|
||||
if (s->ifindex > 0)
|
||||
return s->ifindex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *dns_server_string(DnsServer *server) {
|
||||
assert(server);
|
||||
|
||||
if (!server->server_string)
|
||||
(void) in_addr_to_string(server->family, &server->address, &server->server_string);
|
||||
(void) in_addr_ifindex_to_string(server->family, &server->address, dns_server_ifindex(server), &server->server_string);
|
||||
|
||||
return strna(server->server_string);
|
||||
}
|
||||
@@ -571,17 +586,28 @@ static void dns_server_hash_func(const void *p, struct siphash *state) {
|
||||
|
||||
siphash24_compress(&s->family, sizeof(s->family), state);
|
||||
siphash24_compress(&s->address, FAMILY_ADDRESS_SIZE(s->family), state);
|
||||
siphash24_compress(&s->ifindex, sizeof(s->ifindex), state);
|
||||
}
|
||||
|
||||
static int dns_server_compare_func(const void *a, const void *b) {
|
||||
const DnsServer *x = a, *y = b;
|
||||
int r;
|
||||
|
||||
if (x->family < y->family)
|
||||
return -1;
|
||||
if (x->family > y->family)
|
||||
return 1;
|
||||
|
||||
return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
|
||||
r = memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (x->ifindex < y->ifindex)
|
||||
return -1;
|
||||
if (x->ifindex > y->ifindex)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct hash_ops dns_server_hash_ops = {
|
||||
@@ -623,11 +649,11 @@ void dns_server_mark_all(DnsServer *first) {
|
||||
dns_server_mark_all(first->servers_next);
|
||||
}
|
||||
|
||||
DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr) {
|
||||
DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex) {
|
||||
DnsServer *s;
|
||||
|
||||
LIST_FOREACH(servers, s, first)
|
||||
if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0)
|
||||
if (s->family == family && in_addr_equal(family, &s->address, in_addr) > 0 && s->ifindex == ifindex)
|
||||
return s;
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -62,6 +62,7 @@ struct DnsServer {
|
||||
|
||||
int family;
|
||||
union in_addr_union address;
|
||||
int ifindex; /* for IPv6 link-local DNS servers */
|
||||
|
||||
char *server_string;
|
||||
|
||||
@@ -101,7 +102,8 @@ int dns_server_new(
|
||||
DnsServerType type,
|
||||
Link *link,
|
||||
int family,
|
||||
const union in_addr_union *address);
|
||||
const union in_addr_union *address,
|
||||
int ifindex);
|
||||
|
||||
DnsServer* dns_server_ref(DnsServer *s);
|
||||
DnsServer* dns_server_unref(DnsServer *s);
|
||||
@@ -121,12 +123,13 @@ DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s);
|
||||
int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level);
|
||||
|
||||
const char *dns_server_string(DnsServer *server);
|
||||
int dns_server_ifindex(const DnsServer *s);
|
||||
|
||||
bool dns_server_dnssec_supported(DnsServer *server);
|
||||
|
||||
void dns_server_warn_downgrade(DnsServer *server);
|
||||
|
||||
DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr);
|
||||
DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, int ifindex);
|
||||
|
||||
void dns_server_unlink_all(DnsServer *first);
|
||||
void dns_server_unlink_marked(DnsServer *first);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "resolve-util.h"
|
||||
#include "resolved-bus.h"
|
||||
#include "resolved-link-bus.h"
|
||||
#include "resolved-resolv-conf.h"
|
||||
#include "strv.h"
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_resolve_support, resolve_support, ResolveSupport);
|
||||
@@ -218,11 +219,11 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_
|
||||
for (i = 0; i < n; i++) {
|
||||
DnsServer *s;
|
||||
|
||||
s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address);
|
||||
s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address, 0);
|
||||
if (s)
|
||||
dns_server_move_back_and_unmark(s);
|
||||
else {
|
||||
r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address);
|
||||
r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
}
|
||||
@@ -232,6 +233,8 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_
|
||||
dns_server_unlink_marked(l->dns_servers);
|
||||
link_allocate_scopes(l);
|
||||
|
||||
(void) manager_write_resolv_conf(l->manager);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
|
||||
clear:
|
||||
@@ -306,6 +309,9 @@ int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_
|
||||
goto clear;
|
||||
|
||||
dns_search_domain_unlink_marked(l->search_domains);
|
||||
|
||||
(void) manager_write_resolv_conf(l->manager);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
|
||||
clear:
|
||||
@@ -444,6 +450,8 @@ int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error
|
||||
link_allocate_scopes(l);
|
||||
link_add_rrs(l, false);
|
||||
|
||||
(void) manager_write_resolv_conf(l->manager);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -216,11 +216,11 @@ static int link_update_dns_servers(Link *l) {
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
|
||||
s = dns_server_find(l->dns_servers, family, &a);
|
||||
s = dns_server_find(l->dns_servers, family, &a, 0);
|
||||
if (s)
|
||||
dns_server_move_back_and_unmark(s);
|
||||
else {
|
||||
r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a);
|
||||
r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -284,9 +284,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
|
||||
log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
|
||||
}
|
||||
|
||||
r = manager_write_resolv_conf(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m");
|
||||
(void) manager_write_resolv_conf(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -903,7 +901,7 @@ int manager_send(Manager *m, int fd, int ifindex, int family, const union in_add
|
||||
|
||||
if (family == AF_INET)
|
||||
return manager_ipv4_send(m, fd, ifindex, &addr->in, port, p);
|
||||
else if (family == AF_INET6)
|
||||
if (family == AF_INET6)
|
||||
return manager_ipv6_send(m, fd, ifindex, &addr->in6, port, p);
|
||||
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
@@ -92,7 +92,7 @@ int manager_read_resolv_conf(Manager *m) {
|
||||
|
||||
a = first_word(l, "nameserver");
|
||||
if (a) {
|
||||
r = manager_add_dns_server_by_string(m, DNS_SERVER_SYSTEM, a);
|
||||
r = manager_parse_dns_server_string_and_warn(m, DNS_SERVER_SYSTEM, a);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a);
|
||||
|
||||
@@ -149,9 +149,7 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
|
||||
assert(f);
|
||||
assert(count);
|
||||
|
||||
(void) dns_server_string(s);
|
||||
|
||||
if (!s->server_string) {
|
||||
if (!dns_server_string(s)) {
|
||||
log_warning("Our of memory, or invalid DNS address. Ignoring server.");
|
||||
return;
|
||||
}
|
||||
@@ -160,7 +158,7 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
|
||||
fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
|
||||
(*count)++;
|
||||
|
||||
fprintf(f, "nameserver %s\n", s->server_string);
|
||||
fprintf(f, "nameserver %s\n", dns_server_string(s));
|
||||
}
|
||||
|
||||
static void write_resolv_conf_search(
|
||||
@@ -227,29 +225,31 @@ int manager_write_resolv_conf(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* Read the system /etc/resolv.conf first */
|
||||
manager_read_resolv_conf(m);
|
||||
(void) manager_read_resolv_conf(m);
|
||||
|
||||
/* Add the full list to a set, to filter out duplicates */
|
||||
r = manager_compile_dns_servers(m, &dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_warning_errno(r, "Failed to compile list of DNS servers: %m");
|
||||
|
||||
r = manager_compile_search_domains(m, &domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_warning_errno(r, "Failed to compile list of search domains: %m");
|
||||
|
||||
r = fopen_temporary_label(PRIVATE_RESOLV_CONF, PRIVATE_RESOLV_CONF, &f, &temp_path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_warning_errno(r, "Failed to open private resolv.conf file for writing: %m");
|
||||
|
||||
fchmod(fileno(f), 0644);
|
||||
(void) fchmod(fileno(f), 0644);
|
||||
|
||||
r = write_resolv_conf_contents(f, dns, domains);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to write private resolv.conf contents: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (rename(temp_path, PRIVATE_RESOLV_CONF) < 0) {
|
||||
r = -errno;
|
||||
r = log_error_errno(errno, "Failed to move private resolv.conf file into place: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -258,5 +258,6 @@ int manager_write_resolv_conf(Manager *m) {
|
||||
fail:
|
||||
(void) unlink(PRIVATE_RESOLV_CONF);
|
||||
(void) unlink(temp_path);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -85,11 +85,8 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* Write finish default resolv.conf to avoid a dangling
|
||||
* symlink */
|
||||
r = manager_write_resolv_conf(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Could not create "PRIVATE_RESOLV_CONF": %m");
|
||||
/* Write finish default resolv.conf to avoid a dangling symlink */
|
||||
(void) manager_write_resolv_conf(m);
|
||||
|
||||
sd_notify(false,
|
||||
"READY=1\n"
|
||||
|
||||
@@ -286,6 +286,55 @@ static void test_in_addr_to_string(void) {
|
||||
test_in_addr_to_string_one(AF_INET6, "fe80::");
|
||||
}
|
||||
|
||||
static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) {
|
||||
_cleanup_free_ char *r = NULL;
|
||||
union in_addr_union ua, uuaa;
|
||||
int ff, ifindex2;
|
||||
|
||||
assert_se(in_addr_from_string(f, a, &ua) >= 0);
|
||||
assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0);
|
||||
printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r);
|
||||
assert_se(streq(b, r));
|
||||
|
||||
assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0);
|
||||
assert_se(ff == f);
|
||||
assert_se(in_addr_equal(f, &ua, &uuaa));
|
||||
assert_se(ifindex2 == ifindex || ifindex2 == 0);
|
||||
}
|
||||
|
||||
static void test_in_addr_ifindex_to_string(void) {
|
||||
test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15");
|
||||
test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1");
|
||||
}
|
||||
|
||||
static void test_in_addr_ifindex_from_string_auto(void) {
|
||||
int family, ifindex;
|
||||
union in_addr_union ua;
|
||||
|
||||
/* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */
|
||||
|
||||
assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0);
|
||||
assert_se(family == AF_INET6);
|
||||
assert_se(ifindex == 0);
|
||||
|
||||
assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0);
|
||||
assert_se(family == AF_INET6);
|
||||
assert_se(ifindex == 19);
|
||||
|
||||
assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0);
|
||||
assert_se(family == AF_INET6);
|
||||
assert_se(ifindex == LOOPBACK_IFINDEX);
|
||||
|
||||
assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
|
||||
}
|
||||
|
||||
static void *connect_thread(void *arg) {
|
||||
union sockaddr_union *sa = arg;
|
||||
_cleanup_close_ int fd = -1;
|
||||
@@ -398,6 +447,8 @@ int main(int argc, char *argv[]) {
|
||||
test_in_addr_prefix_intersect();
|
||||
test_in_addr_prefix_next();
|
||||
test_in_addr_to_string();
|
||||
test_in_addr_ifindex_to_string();
|
||||
test_in_addr_ifindex_from_string_auto();
|
||||
|
||||
test_nameinfo_pretty();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user