network: Add serialization for DoT resolvers

For now only DoT is supported, so DoT resolvers are represented using
the existing configuration format.
This commit is contained in:
Ronan Pigott 2024-02-23 17:24:40 -07:00
parent 9fcc5d2d78
commit 169f90c158
3 changed files with 99 additions and 0 deletions

View file

@ -14,6 +14,7 @@
#include "log.h"
#include "network-internal.h"
#include "parse-util.h"
#include "strv.h"
size_t serialize_in_addrs(FILE *f,
const struct in_addr *addresses,
@ -131,6 +132,99 @@ int deserialize_in6_addrs(struct in6_addr **ret, const char *string) {
return size;
}
int serialize_dnr(FILE *f, const sd_dns_resolver *dnr, size_t n_dnr, bool *with_leading_space) {
int r;
bool _space = false;
if (!with_leading_space)
with_leading_space = &_space;
int n = 0;
_cleanup_strv_free_ char **names = NULL;
r = dns_resolvers_to_dot_strv(dnr, n_dnr, &names);
if (r < 0)
return r;
if (r > 0)
fputstrv(f, names, NULL, with_leading_space);
n += r;
return n;
}
static int coalesce_dnr(sd_dns_resolver *dnr, size_t n_dnr, int family, const char *auth_name,
union in_addr_union *addr) {
assert(dnr || n_dnr == 0);
assert(auth_name);
assert(addr);
/* Look through list of DNR for matching resolvers to add our addr to. Since DoT is assumed, no need
* to compare transports/dohpath/etc. */
FOREACH_ARRAY(res, dnr, n_dnr) {
if (family == res->family && streq(auth_name, res->auth_name)) {
if (!GREEDY_REALLOC(res->addrs, res->n_addrs + 1))
return -ENOMEM;
res->addrs[res->n_addrs++] = *addr;
return true;
}
}
return false;
}
/* Deserialized resolvers are assumed to offer DoT service. */
int deserialize_dnr(sd_dns_resolver **ret, const char *string) {
int r;
assert(ret);
assert(string);
sd_dns_resolver *dnr = NULL;
size_t n = 0;
CLEANUP_ARRAY(dnr, n, dns_resolver_done_many);
int priority = 0;
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&string, &word, NULL, 0);
if (r < 0)
return r;
if (r == 0)
break;
uint16_t port;
int family;
_cleanup_free_ union in_addr_union *addr = new(union in_addr_union, 1);
_cleanup_free_ char *auth_name = NULL;
r = in_addr_port_ifindex_name_from_string_auto(word, &family, addr, &port, NULL, &auth_name);
if (r < 0)
return r;
r = coalesce_dnr(dnr, n, family, auth_name, addr);
if (r < 0)
return r;
if (r > 0)
continue;
if (!GREEDY_REALLOC(dnr, n+1))
return -ENOMEM;
priority = n+1;
dnr[n++] = (sd_dns_resolver) {
.priority = priority, /* not serialized, but this will preserve the order */
.auth_name = TAKE_PTR(auth_name),
.family = family,
.addrs = TAKE_PTR(addr),
.n_addrs = 1,
.transports = SD_DNS_ALPN_DOT,
.port = port,
};
}
*ret = TAKE_PTR(dnr);
return n;
}
void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) {
assert(f);
assert(key);

View file

@ -17,6 +17,9 @@ void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses,
bool *with_leading_space);
int deserialize_in6_addrs(struct in6_addr **addresses, const char *string);
int serialize_dnr(FILE *f, const sd_dns_resolver *dnr, size_t n_dnr, bool *with_leading_space);
int deserialize_dnr(sd_dns_resolver **ret, const char *string);
/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */
struct sd_dhcp_route;
struct sd_dhcp_lease;

View file

@ -3,6 +3,8 @@
#include <netinet/in.h>
#include <linux/if.h>
#include "dns-resolver-internal.h"
#include "alloc-util.h"
#include "dns-domain.h"
#include "escape.h"