X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fresolve%2Fresolved-dns-scope.c;h=f1de9bc2eb65ca1fada7d19afb714a01020a8f37;hb=d84b686f06a7f724c12dcace0ab5cb82d01885f9;hp=42a2fc4c774c3fbc923acc6f8075626c3901d703;hpb=4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4;p=elogind.git diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 42a2fc4c7..f1de9bc2e 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -85,7 +85,7 @@ DnsScope* dns_scope_free(DnsScope *s) { return NULL; } -DnsServer *dns_scope_get_server(DnsScope *s) { +DnsServer *dns_scope_get_dns_server(DnsScope *s) { assert(s); if (s->protocol != DNS_PROTOCOL_DNS) @@ -133,7 +133,7 @@ int dns_scope_send(DnsScope *s, DnsPacket *p) { if (DNS_PACKET_QDCOUNT(p) > 1) return -ENOTSUP; - srv = dns_scope_get_server(s); + srv = dns_scope_get_dns_server(s); if (!srv) return -ESRCH; @@ -197,7 +197,7 @@ int dns_scope_tcp_socket(DnsScope *s, int family, const union in_addr_union *add if (family == AF_UNSPEC) { DnsServer *srv; - srv = dns_scope_get_server(s); + srv = dns_scope_get_dns_server(s); if (!srv) return -ESRCH; @@ -353,6 +353,12 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) { if (fd < 0) return fd; + /* Always first try to drop membership before we add + * one. This is necessary on some devices, such as + * veth. */ + if (b) + setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)); + if (setsockopt(fd, IPPROTO_IP, b ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0) return -errno; @@ -366,6 +372,9 @@ int dns_scope_llmnr_membership(DnsScope *s, bool b) { if (fd < 0) return fd; + if (b) + setsockopt(fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); + if (setsockopt(fd, IPPROTO_IPV6, b ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) return -errno; } else @@ -384,7 +393,7 @@ int dns_scope_good_dns_server(DnsScope *s, int family, const union in_addr_union if (s->link) return !!link_find_dns_server(s->link, family, address); else - return manager_known_dns_server(s->manager, family, address); + return !!manager_find_dns_server(s->manager, family, address); } static int dns_scope_make_reply_packet( @@ -403,7 +412,9 @@ static int dns_scope_make_reply_packet( assert(s); - if (q->n_keys <= 0 && answer->n_rrs <= 0 && soa->n_rrs <= 0) + if ((!q || q->n_keys <= 0) + && (!answer || answer->n_rrs <= 0) + && (!soa || soa->n_rrs <= 0)) return -EINVAL; r = dns_packet_new(&p, s->protocol, 0); @@ -535,7 +546,7 @@ void dns_scope_process_query(DnsScope *s, DnsStream *stream, DnsPacket *p) { } } -DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsQuestion *question) { +DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsQuestion *question, bool cache_ok) { DnsTransaction *t; assert(scope); @@ -544,9 +555,19 @@ DnsTransaction *dns_scope_find_transaction(DnsScope *scope, DnsQuestion *questio /* Try to find an ongoing transaction that is a equal or a * superset of the specified question */ - LIST_FOREACH(transactions_by_scope, t, scope->transactions) + LIST_FOREACH(transactions_by_scope, t, scope->transactions) { + + /* Refuse reusing transactions that completed based on + * cached data instead of a real packet, if that's + * requested. */ + if (!cache_ok && + IN_SET(t->state, DNS_TRANSACTION_SUCCESS, DNS_TRANSACTION_FAILURE) && + !t->received) + continue; + if (dns_question_is_superset(t->question, question) > 0) return t; + } return NULL; }