Skip to content

Commit a5e2a48

Browse files
committed
resolve: llmnr: fix never hit condition
Previously, the condition in on_stream_io_impl() never hit, as the read packet is always taken from the stream in the few lines above. Instead of the dns_stream_complete() under the condition, the stream is unref()ed in the on_packet callback for LLMNR stream, unlike the other on_packet callbacks. That's quite tricky. Also, potentially, the stream may still have queued packets to write. This fix the condition, and drops the unref() in the on_packet callback. C.f. systemd#22274 (comment). Closes systemd#22266.
1 parent 4aa6129 commit a5e2a48

File tree

3 files changed

+17
-10
lines changed

3 files changed

+17
-10
lines changed

src/resolve/resolved-dns-stream.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -446,17 +446,25 @@ static int on_stream_io_impl(DnsStream *s, uint32_t revents) {
446446
r = dns_stream_update_io(s);
447447
if (r < 0)
448448
return dns_stream_complete(s, -r);
449+
450+
s->packet_received = true;
449451
}
450452
}
451453
}
452454

453-
/* Call "complete" callback if finished reading and writing one packet, and there's nothing else left
454-
* to write. */
455-
if (s->type == DNS_STREAM_LLMNR_SEND &&
456-
(s->write_packet && s->n_written >= sizeof(s->write_size) + s->write_packet->size) &&
457-
ordered_set_isempty(s->write_queue) &&
458-
(s->read_packet && s->n_read >= sizeof(s->read_size) + s->read_packet->size))
459-
return dns_stream_complete(s, 0);
455+
if (s->type == DNS_STREAM_LLMNR_SEND && s->packet_received) {
456+
uint32_t events;
457+
458+
/* Complete the stream if finished reading and writing one packet, and there's nothing
459+
* else left to write. */
460+
461+
r = sd_event_source_get_io_events(s->io_event_source, &events);
462+
if (r < 0)
463+
return r;
464+
465+
if (!FLAGS_SET(events, EPOLLOUT))
466+
return dns_stream_complete(s, 0);
467+
}
460468

461469
/* If we did something, let's restart the timeout event source */
462470
if (progressed && s->timeout_event_source) {

src/resolve/resolved-dns-stream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct DnsStream {
6060
int ifindex;
6161
uint32_t ttl;
6262
bool identified;
63+
bool packet_received; /* At least one packet is received. Used by LLMNR. */
6364

6465
/* only when using TCP fast open */
6566
union sockaddr_union tfo_address;

src/resolve/resolved-llmnr.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,6 @@ static int on_llmnr_stream_packet(DnsStream *s, DnsPacket *p) {
294294
} else
295295
log_debug("Invalid LLMNR TCP packet, ignoring.");
296296

297-
dns_stream_unref(s);
298297
return 0;
299298
}
300299

@@ -311,8 +310,7 @@ static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *u
311310
return -errno;
312311
}
313312

314-
/* We don't configure a "complete" handler here, we rely on the default handler than simply drops the
315-
* reference to the stream, thus freeing it */
313+
/* We don't configure a "complete" handler here, we rely on the default handler, thus freeing it */
316314
r = dns_stream_new(m, &stream, DNS_STREAM_LLMNR_RECV, DNS_PROTOCOL_LLMNR, cfd, NULL,
317315
on_llmnr_stream_packet, NULL, DNS_STREAM_DEFAULT_TIMEOUT_USEC);
318316
if (r < 0) {

0 commit comments

Comments
 (0)