Merge pull request #3432 from poettering/resolved-ll-ipv6
resolved: support IPv6 DNS servers on the local link
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user