resolved: add "confidential" flag for replies passed to clients

Let's introduce a new flag that indicates whether the response was
acquired in "confidential" mode, i.e. via encrypted DNS-over-TLS, or
synthesized locally.

Fixes: #12859
This commit is contained in:
Lennart Poettering
2021-02-16 10:03:43 +01:00
parent 6f055e43b8
commit 43fc4baa26
13 changed files with 95 additions and 41 deletions
+5 -2
View File
@@ -155,9 +155,12 @@ static void print_source(uint64_t flags, usec_t rtt) {
assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
printf(" in %s.%s\n"
"%s-- Data is authenticated: %s%s\n",
"%s-- Data is authenticated: %s; Data was acquired via local or encrypted transport: %s%s\n",
rtt_str, ansi_normal(),
ansi_grey(), yes_no(flags & SD_RESOLVED_AUTHENTICATED), ansi_normal());
ansi_grey(),
yes_no(flags & SD_RESOLVED_AUTHENTICATED),
yes_no(flags & SD_RESOLVED_CONFIDENTIAL),
ansi_normal());
}
static void print_ifindex_comment(int printed_so_far, int ifindex) {
+5 -5
View File
@@ -252,7 +252,7 @@ static void bus_method_resolve_hostname_complete(DnsQuery *q) {
r = sd_bus_message_append(
reply, "st",
normalized,
SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
@@ -367,7 +367,7 @@ static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname
return r;
r = sd_bus_message_append(reply, "st", canonical,
SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true));
SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true, true));
if (r < 0)
return r;
@@ -510,7 +510,7 @@ static void bus_method_resolve_address_complete(DnsQuery *q) {
if (r < 0)
goto finish;
r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
@@ -672,7 +672,7 @@ static void bus_method_resolve_record_complete(DnsQuery *q) {
if (r < 0)
goto finish;
r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
@@ -1048,7 +1048,7 @@ static void resolve_service_all_complete(DnsQuery *q) {
reply,
"ssst",
name, type, domain,
SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
dns_query_reply_flags_make(q));
if (r < 0)
goto finish;
+3
View File
@@ -52,6 +52,9 @@
/* Input: If reply is answered from cache, the TTLs will be adjusted by age of cache entry */
#define SD_RESOLVED_CLAMP_TTL (UINT64_C(1) << 17)
/* Output: Result was only sent via encrypted channels, or never left this system */
#define SD_RESOLVED_CONFIDENTIAL (UINT64_C(1) << 18)
#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
+18 -7
View File
@@ -22,7 +22,7 @@
* now) */
#define CACHE_TTL_STRANGE_RCODE_USEC (10 * USEC_PER_SEC)
#define CACHEABLE_QUERY_FLAGS (SD_RESOLVED_AUTHENTICATED)
#define CACHEABLE_QUERY_FLAGS (SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL)
typedef enum DnsCacheItemType DnsCacheItemType;
typedef struct DnsCacheItem DnsCacheItem;
@@ -44,7 +44,7 @@ struct DnsCacheItem {
usec_t until;
bool shared_owner:1;
uint64_t query_flags; /* SD_RESOLVED_AUTHENTICATED */
uint64_t query_flags; /* SD_RESOLVED_AUTHENTICATED and/or SD_RESOLVED_CONFIDENTIAL */
DnssecResult dnssec_result;
int ifindex;
@@ -497,8 +497,9 @@ static int dns_cache_put_positive(
(void) in_addr_to_string(i->owner_family, &i->owner_address, &t);
log_debug("Added positive %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s",
log_debug("Added positive %s %s%s cache entry for %s "USEC_FMT"s on %s/%s/%s",
FLAGS_SET(i->query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unauthenticated",
FLAGS_SET(i->query_flags, SD_RESOLVED_CONFIDENTIAL) ? "confidential" : "non-confidential",
i->shared_owner ? " shared" : "",
dns_resource_key_to_string(i->key, key_str, sizeof key_str),
(i->until - timestamp) / USEC_PER_SEC,
@@ -763,7 +764,8 @@ int dns_cache_put(
item->rr,
primary ? answer : NULL,
primary ? full_packet : NULL,
(item->flags & DNS_ANSWER_AUTHENTICATED) ? SD_RESOLVED_AUTHENTICATED : 0,
((item->flags & DNS_ANSWER_AUTHENTICATED) ? SD_RESOLVED_AUTHENTICATED : 0) |
(query_flags & SD_RESOLVED_CONFIDENTIAL),
item->flags & DNS_ANSWER_SHARED_OWNER,
dnssec_result,
timestamp,
@@ -964,7 +966,7 @@ int dns_cache_lookup(
int r;
bool nxdomain = false;
DnsCacheItem *j, *first, *nsec = NULL;
bool have_authenticated = false, have_non_authenticated = false;
bool have_authenticated = false, have_non_authenticated = false, have_confidential = false, have_non_confidential = false;
usec_t current;
int found_rcode = -1;
DnssecResult dnssec_result = -1;
@@ -1021,6 +1023,11 @@ int dns_cache_lookup(
else
have_non_authenticated = true;
if (FLAGS_SET(j->query_flags, SD_RESOLVED_CONFIDENTIAL))
have_confidential = true;
else
have_non_confidential = true;
if (j->dnssec_result < 0) {
have_dnssec_result = false; /* an entry without dnssec result? then invalidate things for good */
dnssec_result = _DNSSEC_RESULT_INVALID;
@@ -1138,7 +1145,9 @@ int dns_cache_lookup(
if (ret_full_packet)
*ret_full_packet = TAKE_PTR(full_packet);
if (ret_query_flags)
*ret_query_flags = (have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0;
*ret_query_flags =
((have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0) |
((have_confidential && !have_non_confidential) ? SD_RESOLVED_CONFIDENTIAL : 0);
if (ret_dnssec_result)
*ret_dnssec_result = dnssec_result;
@@ -1154,7 +1163,9 @@ int dns_cache_lookup(
if (ret_full_packet)
*ret_full_packet = TAKE_PTR(full_packet);
if (ret_query_flags)
*ret_query_flags = (have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0;
*ret_query_flags =
((have_authenticated && !have_non_authenticated) ? SD_RESOLVED_AUTHENTICATED : 0) |
((have_confidential && !have_non_confidential) ? SD_RESOLVED_CONFIDENTIAL : 0);
if (ret_dnssec_result)
*ret_dnssec_result = dnssec_result;
+7 -2
View File
@@ -269,12 +269,17 @@ DnsProtocol dns_protocol_from_string(const char *s) _pure_;
extern const struct hash_ops dns_packet_hash_ops;
static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) {
static inline uint64_t SD_RESOLVED_FLAGS_MAKE(
DnsProtocol protocol,
int family,
bool authenticated,
bool confidential) {
uint64_t f;
/* Converts a protocol + family into a flags field as used in queries and responses */
f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0;
f = (authenticated ? SD_RESOLVED_AUTHENTICATED : 0) |
(confidential ? SD_RESOLVED_CONFIDENTIAL : 0);
switch (protocol) {
case DNS_PROTOCOL_DNS:
+18 -4
View File
@@ -630,7 +630,7 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
q->answer_rcode = DNS_RCODE_NXDOMAIN;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED;
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL;
*state = DNS_TRANSACTION_RCODE_FAILURE;
return 0;
@@ -644,7 +644,7 @@ static int dns_query_synthesize_reply(DnsQuery *q, DnsTransactionState *state) {
q->answer_rcode = DNS_RCODE_SUCCESS;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED;
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL;
*state = DNS_TRANSACTION_SUCCESS;
@@ -676,7 +676,7 @@ static int dns_query_try_etc_hosts(DnsQuery *q) {
q->answer_rcode = DNS_RCODE_SUCCESS;
q->answer_protocol = dns_synthesize_protocol(q->flags);
q->answer_family = dns_synthesize_family(q->flags);
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED;
q->answer_query_flags = SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL;
return 1;
}
@@ -795,7 +795,7 @@ fail:
static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
DnsTransactionState state = DNS_TRANSACTION_NO_SERVERS;
bool has_authenticated = false, has_non_authenticated = false;
bool has_authenticated = false, has_non_authenticated = false, has_confidential = false, has_non_confidential = false;
DnssecResult dnssec_result_authenticated = _DNSSEC_RESULT_INVALID, dnssec_result_non_authenticated = _DNSSEC_RESULT_INVALID;
DnsTransaction *t;
int r;
@@ -853,6 +853,11 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
dnssec_result_non_authenticated = t->answer_dnssec_result;
}
if (FLAGS_SET(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL))
has_confidential = true;
else
has_non_confidential = true;
state = DNS_TRANSACTION_SUCCESS;
break;
}
@@ -890,6 +895,7 @@ static void dns_query_accept(DnsQuery *q, DnsQueryCandidate *c) {
if (state == DNS_TRANSACTION_SUCCESS) {
SET_FLAG(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED, has_authenticated && !has_non_authenticated);
SET_FLAG(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, has_confidential && !has_non_confidential);
q->answer_dnssec_result = FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? dnssec_result_authenticated : dnssec_result_non_authenticated;
}
@@ -1052,6 +1058,8 @@ int dns_query_process_cname(DnsQuery *q) {
if (!FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED))
q->previous_redirect_unauthenticated = true;
if (!FLAGS_SET(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL))
q->previous_redirect_non_confidential = true;
/* OK, let's actually follow the CNAME */
r = dns_query_cname_redirect(q, cname);
@@ -1122,3 +1130,9 @@ bool dns_query_fully_authenticated(DnsQuery *q) {
return FLAGS_SET(q->answer_query_flags, SD_RESOLVED_AUTHENTICATED) && !q->previous_redirect_unauthenticated;
}
bool dns_query_fully_confidential(DnsQuery *q) {
assert(q);
return FLAGS_SET(q->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) && !q->previous_redirect_non_confidential;
}
+11
View File
@@ -72,6 +72,7 @@ struct DnsQuery {
DnsSearchDomain *answer_search_domain;
int answer_errno; /* if state is DNS_TRANSACTION_ERRNO */
bool previous_redirect_unauthenticated;
bool previous_redirect_non_confidential;
DnsPacket *answer_full_packet;
/* Bus + Varlink client information */
@@ -132,3 +133,13 @@ const char *dns_query_string(DnsQuery *q);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuery*, dns_query_free);
bool dns_query_fully_authenticated(DnsQuery *q);
bool dns_query_fully_confidential(DnsQuery *q);
static inline uint64_t dns_query_reply_flags_make(DnsQuery *q) {
assert(q);
return SD_RESOLVED_FLAGS_MAKE(q->answer_protocol,
q->answer_family,
dns_query_fully_authenticated(q),
dns_query_fully_confidential(q));
}
+1 -1
View File
@@ -505,7 +505,7 @@ DnsScopeMatch dns_scope_good_domain(
if (ifindex != 0 && (!s->link || s->link->ifindex != ifindex))
return DNS_SCOPE_NO;
if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, 0) & flags) == 0)
if ((SD_RESOLVED_FLAGS_MAKE(s->protocol, s->family, false, false) & flags) == 0)
return DNS_SCOPE_NO;
/* Never resolve any loopback hostname or IP address via DNS, LLMNR or mDNS. Instead, always rely on
+18 -11
View File
@@ -410,7 +410,7 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
else
st = dns_transaction_state_to_string(state);
log_debug("%s transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s).",
log_debug("%s transaction %" PRIu16 " for <%s> on scope %s on %s/%s now complete with <%s> from %s (%s; %s).",
t->bypass ? "Bypass" : "Regular",
t->id,
dns_resource_key_to_string(dns_transaction_key(t), key_str, sizeof key_str),
@@ -420,7 +420,8 @@ void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state) {
st,
t->answer_source < 0 ? "none" : dns_transaction_source_to_string(t->answer_source),
FLAGS_SET(t->query_flags, SD_RESOLVED_NO_VALIDATE) ? "not validated" :
(FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unsigned"));
(FLAGS_SET(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED) ? "authenticated" : "unsigned"),
FLAGS_SET(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL) ? "confidential" : "non-confidential");
t->state = state;
@@ -561,10 +562,15 @@ static void on_transaction_stream_error(DnsTransaction *t, int error) {
dns_transaction_complete_errno(t, error);
}
static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsStream *s, DnsPacket *p) {
bool encrypted;
assert(t);
assert(s);
assert(p);
encrypted = s->encrypted;
dns_transaction_close_connection(t, true);
if (dns_packet_validate_reply(p) <= 0) {
@@ -576,7 +582,7 @@ static int dns_transaction_on_stream_packet(DnsTransaction *t, DnsPacket *p) {
dns_scope_check_conflicts(t->scope, p);
t->block_gc++;
dns_transaction_process_reply(t, p);
dns_transaction_process_reply(t, p, encrypted);
t->block_gc--;
/* If the response wasn't useful, then complete the transition
@@ -621,12 +627,11 @@ static int on_stream_packet(DnsStream *s) {
assert(s);
/* Take ownership of packet to be able to receive new packets */
p = dns_stream_take_read_packet(s);
assert(p);
assert_se(p = dns_stream_take_read_packet(s));
t = hashmap_get(s->manager->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
if (t)
return dns_transaction_on_stream_packet(t, p);
return dns_transaction_on_stream_packet(t, s, p);
/* Ignore incorrect transaction id as an old transaction can have been canceled. */
log_debug("Received unexpected TCP reply packet with id %" PRIu16 ", ignoring.", DNS_PACKET_ID(p));
@@ -990,7 +995,7 @@ static int dns_transaction_fix_rcode(DnsTransaction *t) {
return 0;
}
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypted) {
int r;
assert(t);
@@ -1232,6 +1237,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
t->answer_rcode = DNS_PACKET_RCODE(p);
t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, encrypted);
r = dns_transaction_fix_rcode(t);
if (r < 0)
@@ -1315,7 +1321,7 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
return 0;
}
dns_transaction_process_reply(t, p);
dns_transaction_process_reply(t, p, false);
return 0;
}
@@ -1519,7 +1525,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
if (r > 0) {
t->answer_rcode = DNS_RCODE_SUCCESS;
t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
return 0;
}
@@ -1539,6 +1545,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
t->answer_rcode = DNS_RCODE_SUCCESS;
t->answer_source = DNS_TRANSACTION_TRUST_ANCHOR;
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, false);
SET_FLAG(t->answer_query_flags, SD_RESOLVED_CONFIDENTIAL, true);
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
} else
/* If we are not in downgrade mode, then fail the lookup, because we cannot
@@ -1559,7 +1566,7 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
if (r > 0) {
t->answer_rcode = DNS_RCODE_SUCCESS;
t->answer_source = DNS_TRANSACTION_ZONE;
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED, true);
SET_FLAG(t->answer_query_flags, SD_RESOLVED_AUTHENTICATED|SD_RESOLVED_CONFIDENTIAL, true);
dns_transaction_complete(t, DNS_TRANSACTION_SUCCESS);
return 0;
}
+1 -1
View File
@@ -145,7 +145,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsTransaction*, dns_transaction_gc);
int dns_transaction_go(DnsTransaction *t);
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p);
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p, bool encrypted);
void dns_transaction_complete(DnsTransaction *t, DnsTransactionState state);
void dns_transaction_notify(DnsTransaction *t, DnsTransaction *source);
+1 -1
View File
@@ -99,7 +99,7 @@ static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *u
t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
if (t)
dns_transaction_process_reply(t, p);
dns_transaction_process_reply(t, p, false);
} else if (dns_packet_validate_query(p) > 0) {
log_debug("Got LLMNR UDP query packet for id %u", DNS_PACKET_ID(p));
+4 -4
View File
@@ -303,20 +303,20 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
t = dns_scope_find_transaction(scope, rr->key, SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
dns_transaction_process_reply(t, p);
dns_transaction_process_reply(t, p, false);
/* Also look for the various types of ANY transactions */
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(rr->key->class, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
dns_transaction_process_reply(t, p);
dns_transaction_process_reply(t, p, false);
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, rr->key->type, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
dns_transaction_process_reply(t, p);
dns_transaction_process_reply(t, p, false);
t = dns_scope_find_transaction(scope, &DNS_RESOURCE_KEY_CONST(DNS_CLASS_ANY, DNS_TYPE_ANY, dns_resource_key_name(rr->key)), SD_RESOLVED_NO_CACHE|SD_RESOLVED_NO_ZONE);
if (t)
dns_transaction_process_reply(t, p);
dns_transaction_process_reply(t, p, false);
}
dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, NULL, false, _DNSSEC_RESULT_INVALID, (uint32_t) -1, p->family, &p->sender);
+3 -3
View File
@@ -222,7 +222,7 @@ static void vl_method_resolve_hostname_complete(DnsQuery *q) {
JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("addresses", JSON_BUILD_VARIANT(array)),
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(normalized)),
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))))));
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(dns_query_reply_flags_make(q)))));
finish:
if (r < 0) {
log_error_errno(r, "Failed to send hostname reply: %m");
@@ -267,7 +267,7 @@ static int parse_as_address(Varlink *link, LookupParameters *p) {
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(ff)),
JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(&parsed, FAMILY_ADDRESS_SIZE(ff)))))),
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(canonical)),
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(p->flags), ff, true)))));
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(p->flags), ff, true, true)))));
}
static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
@@ -440,7 +440,7 @@ static void vl_method_resolve_address_complete(DnsQuery *q) {
r = varlink_replyb(q->varlink_request,
JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("names", JSON_BUILD_VARIANT(array)),
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q))))));
JSON_BUILD_PAIR("flags", JSON_BUILD_INTEGER(dns_query_reply_flags_make(q)))));
finish:
if (r < 0) {
log_error_errno(r, "Failed to send address reply: %m");