summaryrefslogtreecommitdiff
path: root/src/grp-resolve/systemd-resolved/resolved-dns-scope.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/grp-resolve/systemd-resolved/resolved-dns-scope.c')
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-scope.c127
1 files changed, 68 insertions, 59 deletions
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-scope.c b/src/grp-resolve/systemd-resolved/resolved-dns-scope.c
index cf878cc783..9da091b5e9 100644
--- a/src/grp-resolve/systemd-resolved/resolved-dns-scope.c
+++ b/src/grp-resolve/systemd-resolved/resolved-dns-scope.c
@@ -233,7 +233,7 @@ static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
if (fd < 0)
return fd;
- r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, p);
+ r = manager_send(s->manager, fd, ifindex, family, &addr, LLMNR_PORT, NULL, p);
if (r < 0)
return r;
@@ -258,7 +258,7 @@ static int dns_scope_emit_one(DnsScope *s, int fd, DnsPacket *p) {
if (fd < 0)
return fd;
- r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, p);
+ r = manager_send(s->manager, fd, ifindex, family, &addr, MDNS_PORT, NULL, p);
if (r < 0)
return r;
@@ -308,7 +308,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);
@@ -316,6 +316,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);
@@ -324,7 +326,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;
@@ -333,6 +335,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);
@@ -341,7 +344,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;
@@ -358,14 +361,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;
}
@@ -576,6 +579,7 @@ static int dns_scope_multicast_membership(DnsScope *s, bool b, struct in_addr in
}
int dns_scope_llmnr_membership(DnsScope *s, bool b) {
+ assert(s);
if (s->protocol != DNS_PROTOCOL_LLMNR)
return 0;
@@ -584,6 +588,7 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) {
}
int dns_scope_mdns_membership(DnsScope *s, bool b) {
+ assert(s);
if (s->protocol != DNS_PROTOCOL_MDNS)
return 0;
@@ -602,15 +607,14 @@ static int dns_scope_make_reply_packet(
DnsPacket **ret) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- unsigned i;
int r;
assert(s);
assert(ret);
- if ((!q || q->n_keys <= 0)
- && (!answer || answer->n_rrs <= 0)
- && (!soa || soa->n_rrs <= 0))
+ if (dns_question_isempty(q) &&
+ dns_answer_isempty(answer) &&
+ dns_answer_isempty(soa))
return -EINVAL;
r = dns_packet_new(&p, s->protocol, 0);
@@ -629,35 +633,20 @@ static int dns_scope_make_reply_packet(
0 /* (cd) */,
rcode));
- if (q) {
- for (i = 0; i < q->n_keys; i++) {
- r = dns_packet_append_key(p, q->keys[i], NULL);
- if (r < 0)
- return r;
- }
-
- DNS_PACKET_HEADER(p)->qdcount = htobe16(q->n_keys);
- }
-
- if (answer) {
- for (i = 0; i < answer->n_rrs; i++) {
- r = dns_packet_append_rr(p, answer->items[i].rr, NULL, NULL);
- if (r < 0)
- return r;
- }
-
- DNS_PACKET_HEADER(p)->ancount = htobe16(answer->n_rrs);
- }
+ r = dns_packet_append_question(p, q);
+ if (r < 0)
+ return r;
+ DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(q));
- if (soa) {
- for (i = 0; i < soa->n_rrs; i++) {
- r = dns_packet_append_rr(p, soa->items[i].rr, NULL, NULL);
- if (r < 0)
- return r;
- }
+ r = dns_packet_append_answer(p, answer);
+ if (r < 0)
+ return r;
+ DNS_PACKET_HEADER(p)->ancount = htobe16(dns_answer_size(answer));
- DNS_PACKET_HEADER(p)->arcount = htobe16(soa->n_rrs);
- }
+ r = dns_packet_append_answer(p, soa);
+ if (r < 0)
+ return r;
+ DNS_PACKET_HEADER(p)->arcount = htobe16(dns_answer_size(soa));
*ret = p;
p = NULL;
@@ -666,25 +655,25 @@ static int dns_scope_make_reply_packet(
}
static void dns_scope_verify_conflicts(DnsScope *s, DnsPacket *p) {
- unsigned n;
+ DnsResourceRecord *rr;
+ DnsResourceKey *key;
assert(s);
assert(p);
- if (p->question)
- for (n = 0; n < p->question->n_keys; n++)
- dns_zone_verify_conflicts(&s->zone, p->question->keys[n]);
- if (p->answer)
- for (n = 0; n < p->answer->n_rrs; n++)
- dns_zone_verify_conflicts(&s->zone, p->answer->items[n].rr->key);
+ DNS_QUESTION_FOREACH(key, p->question)
+ dns_zone_verify_conflicts(&s->zone, key);
+
+ DNS_ANSWER_FOREACH(rr, p->answer)
+ dns_zone_verify_conflicts(&s->zone, rr->key);
}
void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
- _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
_cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL, *soa = NULL;
+ _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
DnsResourceKey *key = NULL;
bool tentative = false;
- int r, fd;
+ int r;
assert(s);
assert(p);
@@ -706,7 +695,7 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
r = dns_packet_extract(p);
if (r < 0) {
- log_debug_errno(r, "Failed to extract resources from incoming packet: %m");
+ log_debug_errno(r, "Failed to extract resource records from incoming packet: %m");
return;
}
@@ -716,10 +705,10 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
return;
}
- assert(p->question->n_keys == 1);
+ assert(dns_question_size(p->question) == 1);
key = p->question->keys[0];
- r = dns_zone_lookup(&s->zone, key, &answer, &soa, &tentative);
+ r = dns_zone_lookup(&s->zone, key, 0, &answer, &soa, &tentative);
if (r < 0) {
log_debug_errno(r, "Failed to lookup key: %m");
return;
@@ -736,9 +725,21 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
return;
}
- if (stream)
+ if (stream) {
r = dns_stream_write_packet(stream, reply);
- else {
+ if (r < 0) {
+ log_debug_errno(r, "Failed to enqueue reply packet: %m");
+ return;
+ }
+
+ /* Let's take an extra reference on this stream, so that it stays around after returning. The reference
+ * will be dangling until the stream is disconnected, and the default completion handler of the stream
+ * will then unref the stream and destroy it */
+ if (DNS_STREAM_QUEUED(stream))
+ dns_stream_ref(stream);
+ } else {
+ int fd;
+
if (!ratelimit_test(&s->ratelimit))
return;
@@ -760,12 +761,11 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) {
* verified uniqueness for all records. Also see RFC
* 4795, Section 2.7 */
- r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, reply);
- }
-
- if (r < 0) {
- log_debug_errno(r, "Failed to send reply packet: %m");
- return;
+ r = manager_send(s->manager, fd, p->ifindex, p->family, &p->sender, p->sender_port, NULL, reply);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to send reply packet: %m");
+ return;
+ }
}
}
@@ -1027,3 +1027,12 @@ bool dns_scope_network_good(DnsScope *s) {
return manager_routable(s->manager, AF_UNSPEC);
}
+
+int dns_scope_ifindex(DnsScope *s) {
+ assert(s);
+
+ if (s->link)
+ return s->link->ifindex;
+
+ return 0;
+}