Systemd/src/resolve/resolved-dns-stream.h
Lennart Poettering 0354029bf5 resolved: don't store udp/tcp fd in DnsPacket object
DnsPacket should better be a "dead" object, i.e. list facts, not track
resources. By including an fd in its fields it started tracking
resources however, without actually taking a ref to the fd (i.e. no
dup() or so was called on it).

Let's hence rework things so that we don#t have to keep track of the fd
a packet came in from. Instead, pass around the DnsStubListenerExtra
object wherever we need to.

This should be useful as soon as we start caching whole DnsPacket
objects to allow replying to DNSSEC/CO packets, i.e. where we have to
keep a copy of the original DnsPacket around for a long time in cache,
potentially much longer than the fds the packet was received on.
2020-09-08 19:47:30 +02:00

108 lines
3.1 KiB
C

/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-event.h"
#include "ordered-set.h"
#include "socket-util.h"
typedef struct DnsServer DnsServer;
typedef struct DnsStream DnsStream;
typedef struct DnsTransaction DnsTransaction;
typedef struct Manager Manager;
typedef struct DnsStubListenerExtra DnsStubListenerExtra;
#include "resolved-dns-packet.h"
#include "resolved-dnstls.h"
typedef enum DnsStreamType {
DNS_STREAM_LOOKUP, /* Outgoing connection to a classic DNS server */
DNS_STREAM_LLMNR_SEND, /* Outgoing LLMNR TCP lookup */
DNS_STREAM_LLMNR_RECV, /* Incoming LLMNR TCP lookup */
DNS_STREAM_STUB, /* Incoming DNS stub connection */
_DNS_STREAM_TYPE_MAX,
_DNS_STREAM_TYPE_INVALID = -1,
} DnsStreamType;
#define DNS_STREAM_WRITE_TLS_DATA 1
/* Streams are used by three subsystems:
*
* 1. The normal transaction logic when doing a DNS or LLMNR lookup via TCP
* 2. The LLMNR logic when accepting a TCP-based lookup
* 3. The DNS stub logic when accepting a TCP-based lookup
*/
struct DnsStream {
Manager *manager;
unsigned n_ref;
DnsStreamType type;
DnsProtocol protocol;
int fd;
union sockaddr_union peer;
socklen_t peer_salen;
union sockaddr_union local;
socklen_t local_salen;
int ifindex;
uint32_t ttl;
bool identified;
/* only when using TCP fast open */
union sockaddr_union tfo_address;
socklen_t tfo_salen;
#if ENABLE_DNS_OVER_TLS
DnsTlsStreamData dnstls_data;
int dnstls_events;
#endif
sd_event_source *io_event_source;
sd_event_source *timeout_event_source;
be16_t write_size, read_size;
DnsPacket *write_packet, *read_packet;
size_t n_written, n_read;
OrderedSet *write_queue;
int (*on_packet)(DnsStream *s);
int (*complete)(DnsStream *s, int error);
LIST_HEAD(DnsTransaction, transactions); /* when used by the transaction logic */
DnsServer *server; /* when used by the transaction logic */
Set *queries; /* when used by the DNS stub logic */
/* used when DNS-over-TLS is enabled */
bool encrypted:1;
DnsStubListenerExtra *stub_listener_extra;
LIST_FIELDS(DnsStream, streams);
};
int dns_stream_new(Manager *m, DnsStream **s, DnsStreamType type, DnsProtocol protocol, int fd, const union sockaddr_union *tfo_address);
#if ENABLE_DNS_OVER_TLS
int dns_stream_connect_tls(DnsStream *s, void *tls_session);
#endif
DnsStream *dns_stream_unref(DnsStream *s);
DnsStream *dns_stream_ref(DnsStream *s);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsStream*, dns_stream_unref);
int dns_stream_write_packet(DnsStream *s, DnsPacket *p);
ssize_t dns_stream_writev(DnsStream *s, const struct iovec *iov, size_t iovcnt, int flags);
static inline bool DNS_STREAM_QUEUED(DnsStream *s) {
assert(s);
if (s->fd < 0) /* already stopped? */
return false;
return !!s->write_packet;
}
DnsPacket *dns_stream_take_read_packet(DnsStream *s);
void dns_stream_detach(DnsStream *s);