X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fresolve%2Fresolved-dns-stream.c;h=12f69aef382ced4ac07a7365de8c2d422896ae6d;hb=39cf0351c529584aa8f270e3b418d7ab9461b622;hp=ecc7e9fa091516b8bbf0fced5877666d8ab7501a;hpb=5971dffd4a420bb10be0d07a3c1b0e1e55554262;p=thirdparty%2Fsystemd.git diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index ecc7e9fa091..12f69aef382 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -1,16 +1,20 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include +#include #include "alloc-util.h" #include "fd-util.h" #include "io-util.h" -#include "missing.h" +#include "missing_network.h" #include "resolved-dns-stream.h" +#include "resolved-manager.h" #define DNS_STREAM_TIMEOUT_USEC (10 * USEC_PER_SEC) #define DNS_STREAMS_MAX 128 +#define DNS_QUERIES_PER_STREAM 32 + static void dns_stream_stop(DnsStream *s) { assert(s); @@ -36,7 +40,11 @@ static int dns_stream_update_io(DnsStream *s) { s->n_written = 0; f |= EPOLLOUT; } - if (!s->read_packet || s->n_read < sizeof(s->read_size) + s->read_packet->size) + + /* Let's read a packet if we haven't queued any yet. Except if we already hit a limit of parallel + * queries for this connection. */ + if ((!s->read_packet || s->n_read < sizeof(s->read_size) + s->read_packet->size) && + set_size(s->queries) < DNS_QUERIES_PER_STREAM) f |= EPOLLIN; #if ENABLE_DNS_OVER_TLS @@ -52,6 +60,10 @@ static int dns_stream_complete(DnsStream *s, int error) { _cleanup_(dns_stream_unrefp) _unused_ DnsStream *ref = dns_stream_ref(s); /* Protect stream while we process it */ assert(s); + assert(error >= 0); + + /* Error is > 0 when the connection failed for some reason in the network stack. It's == 0 if we sent + * and received exactly one packet each (in the LLMNR client case). */ #if ENABLE_DNS_OVER_TLS if (s->encrypted) { @@ -75,11 +87,9 @@ static int dns_stream_complete(DnsStream *s, int error) { } static int dns_stream_identify(DnsStream *s) { - union { - struct cmsghdr header; /* For alignment */ - uint8_t buffer[CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo)) - + EXTRA_CMSG_SPACE /* kernel appears to require extra space */]; - } control; + CMSG_BUFFER_TYPE(CMSG_SPACE(MAXSIZE(struct in_pktinfo, struct in6_pktinfo)) + + CMSG_SPACE(int) + /* for the TTL */ + + EXTRA_CMSG_SPACE /* kernel appears to require extra space */) control; struct msghdr mh = {}; struct cmsghdr *cmsg; socklen_t sl; @@ -180,7 +190,7 @@ static int dns_stream_identify(DnsStream *s) { s->ifindex = manager_find_ifindex(s->manager, s->local.sa.sa_family, s->local.sa.sa_family == AF_INET ? (union in_addr_union*) &s->local.in.sin_addr : (union in_addr_union*) &s->local.in6.sin6_addr); if (s->protocol == DNS_PROTOCOL_LLMNR && s->ifindex > 0) { - uint32_t ifindex = htobe32(s->ifindex); + be32_t ifindex = htobe32(s->ifindex); /* Make sure all packets for this connection are sent on the same interface */ if (s->local.sa.sa_family == AF_INET) { @@ -425,13 +435,17 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use } } - if ((s->write_packet && s->n_written >= sizeof(s->write_size) + s->write_packet->size) && + /* Call "complete" callback if finished reading and writing one packet, and there's nothing else left + * to write. */ + if (s->type == DNS_STREAM_LLMNR_SEND && + (s->write_packet && s->n_written >= sizeof(s->write_size) + s->write_packet->size) && + ordered_set_isempty(s->write_queue) && (s->read_packet && s->n_read >= sizeof(s->read_size) + s->read_packet->size)) return dns_stream_complete(s, 0); /* If we did something, let's restart the timeout event source */ if (progressed && s->timeout_event_source) { - r = sd_event_source_set_time(s->timeout_event_source, now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC); + r = sd_event_source_set_time_relative(s->timeout_event_source, DNS_STREAM_TIMEOUT_USEC); if (r < 0) log_warning_errno(errno, "Couldn't restart TCP connection timeout, ignoring: %m"); } @@ -501,6 +515,7 @@ int dns_stream_new( .n_ref = 1, .fd = -1, .protocol = protocol, + .type = type, }; r = ordered_set_ensure_allocated(&s->write_queue, &dns_packet_hash_ops); @@ -513,11 +528,11 @@ int dns_stream_new( (void) sd_event_source_set_description(s->io_event_source, "dns-stream-io"); - r = sd_event_add_time( + r = sd_event_add_time_relative( m->event, &s->timeout_event_source, clock_boottime_or_monotonic(), - now(clock_boottime_or_monotonic()) + DNS_STREAM_TIMEOUT_USEC, 0, + DNS_STREAM_TIMEOUT_USEC, 0, on_stream_timeout, s); if (r < 0) return r;