1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-03 17:47:28 +03:00

resolvectl: implement SVCB and HTTPS presentation format

This commit is contained in:
Ronan Pigott 2023-12-29 11:30:18 -07:00
parent b699f5f2cd
commit f0d261a714

View File

@ -15,6 +15,7 @@
#include "string-util.h"
#include "strv.h"
#include "terminal-util.h"
#include "unaligned.h"
DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
DnsResourceKey *k;
@ -826,6 +827,107 @@ static char *format_txt(DnsTxtItem *first) {
return s;
}
static char *format_svc_param_value(DnsSvcParam *i) {
_cleanup_free_ char *value = NULL;
assert(i);
switch (i->key) {
case DNS_SVC_PARAM_KEY_ALPN: {
size_t offset = 0;
_cleanup_strv_free_ char **values_strv = NULL;
while (offset < i->length) {
size_t sz = (uint8_t) i->value[offset++];
char *alpn = cescape_length((char *)&i->value[offset], sz);
if (!alpn)
return NULL;
if (strv_push(&values_strv, alpn) < 0)
return NULL;
offset += sz;
}
value = strv_join(values_strv, ",");
if (!value)
return NULL;
break;
}
case DNS_SVC_PARAM_KEY_PORT: {
uint16_t port = unaligned_read_be16(i->value);
if (asprintf(&value, "%" PRIu16, port) < 0)
return NULL;
return TAKE_PTR(value);
}
case DNS_SVC_PARAM_KEY_IPV4HINT: {
const struct in_addr *addrs = i->value_in_addr;
_cleanup_strv_free_ char **values_strv = NULL;
for (size_t n = 0; n < i->length / sizeof (struct in_addr); n++) {
char *addr;
if (in_addr_to_string(AF_INET, (const union in_addr_union*) &addrs[n], &addr) < 0)
return NULL;
if (strv_push(&values_strv, addr) < 0)
return NULL;
}
return strv_join(values_strv, ",");
}
case DNS_SVC_PARAM_KEY_IPV6HINT: {
const struct in6_addr *addrs = i->value_in6_addr;
_cleanup_strv_free_ char **values_strv = NULL;
for (size_t n = 0; n < i->length / sizeof (struct in6_addr); n++) {
char *addr;
if (in_addr_to_string(AF_INET6, (const union in_addr_union*) &addrs[n], &addr) < 0)
return NULL;
if (strv_push(&values_strv, addr) < 0)
return NULL;
}
return strv_join(values_strv, ",");
}
default: {
value = decescape((char *)&i->value, " ,", i->length);
if (!value)
return NULL;
break;
}
}
char *qvalue;
if (asprintf(&qvalue, "\"%s\"", value) < 0)
return NULL;
return qvalue;
}
static char *format_svc_param(DnsSvcParam *i) {
const char *key = FORMAT_DNS_SVC_PARAM_KEY(i->key);
_cleanup_free_ char *value = NULL;
assert(i);
if (i->length == 0)
return strdup(key);
value = format_svc_param_value(i);
if (!value)
return NULL;
return strjoin(key, "=", value);
}
static char *format_svc_params(DnsSvcParam *first) {
_cleanup_strv_free_ char **params = NULL;
LIST_FOREACH(params, i, first) {
char *param = format_svc_param(i);
if (!param)
return NULL;
if (strv_push(&params, param) < 0)
return NULL;
}
return strv_join(params, " ");
}
const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
_cleanup_free_ char *s = NULL, *t = NULL;
char k[DNS_RESOURCE_KEY_STRING_MAX];
@ -1136,6 +1238,19 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
break;
case DNS_TYPE_SVCB:
case DNS_TYPE_HTTPS:
t = format_svc_params(rr->svcb.params);
if (!t)
return NULL;
r = asprintf(&s, "%s %d %s %s", k, rr->svcb.priority,
isempty(rr->svcb.target_name) ? "." : rr->svcb.target_name,
t);
if (r < 0)
return NULL;
break;
case DNS_TYPE_OPENPGPKEY:
r = asprintf(&s, "%s", k);
if (r < 0)