diff options
Diffstat (limited to 'src/resolve/resolved-dns-scope.c')
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 127 |
1 files changed, 68 insertions, 59 deletions
diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 66e4585c18..ed0c6aa105 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -232,7 +232,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; @@ -257,7 +257,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; @@ -307,7 +307,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); @@ -315,6 +315,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); @@ -323,7 +325,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; @@ -332,6 +334,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); @@ -340,7 +343,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; @@ -357,14 +360,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; } @@ -575,6 +578,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; @@ -583,6 +587,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; @@ -601,15 +606,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); @@ -628,35 +632,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; @@ -665,25 +654,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); @@ -705,7 +694,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; } @@ -715,10 +704,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; @@ -735,9 +724,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; @@ -759,12 +760,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; + } } } @@ -1026,3 +1026,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; +} |