mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-22 22:03:43 +03:00
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. https://github.com/systemd/systemd/pull/22274#issuecomment-1023708449. Closes #22266. (cherry picked from commit a5e2a488e83fabf6d8ade7621c2fc3574a8faaa7)
This commit is contained in:
parent
d65808ef7e
commit
9c710c66c3
@ -446,17 +446,25 @@ static int on_stream_io_impl(DnsStream *s, uint32_t revents) {
|
||||
r = dns_stream_update_io(s);
|
||||
if (r < 0)
|
||||
return dns_stream_complete(s, -r);
|
||||
|
||||
s->packet_received = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (s->type == DNS_STREAM_LLMNR_SEND && s->packet_received) {
|
||||
uint32_t events;
|
||||
|
||||
/* Complete the stream if finished reading and writing one packet, and there's nothing
|
||||
* else left to write. */
|
||||
|
||||
r = sd_event_source_get_io_events(s->io_event_source, &events);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!FLAGS_SET(events, EPOLLOUT))
|
||||
return dns_stream_complete(s, 0);
|
||||
}
|
||||
|
||||
/* If we did something, let's restart the timeout event source */
|
||||
if (progressed && s->timeout_event_source) {
|
||||
|
@ -60,6 +60,7 @@ struct DnsStream {
|
||||
int ifindex;
|
||||
uint32_t ttl;
|
||||
bool identified;
|
||||
bool packet_received; /* At least one packet is received. Used by LLMNR. */
|
||||
|
||||
/* only when using TCP fast open */
|
||||
union sockaddr_union tfo_address;
|
||||
|
@ -294,7 +294,6 @@ static int on_llmnr_stream_packet(DnsStream *s, DnsPacket *p) {
|
||||
} else
|
||||
log_debug("Invalid LLMNR TCP packet, ignoring.");
|
||||
|
||||
dns_stream_unref(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -311,8 +310,7 @@ static int on_llmnr_stream(sd_event_source *s, int fd, uint32_t revents, void *u
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* We don't configure a "complete" handler here, we rely on the default handler than simply drops the
|
||||
* reference to the stream, thus freeing it */
|
||||
/* We don't configure a "complete" handler here, we rely on the default handler, thus freeing it */
|
||||
r = dns_stream_new(m, &stream, DNS_STREAM_LLMNR_RECV, DNS_PROTOCOL_LLMNR, cfd, NULL,
|
||||
on_llmnr_stream_packet, NULL, DNS_STREAM_DEFAULT_TIMEOUT_USEC);
|
||||
if (r < 0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user