Merge pull request #22132 from joanbm/main
resolved: Fix DoT timeout on multiple answer records (for CloudFlare, Google, etc. DoT servers)
This commit is contained in:
+10
-1
@@ -70,7 +70,6 @@ systemd_resolved_sources = files('''
|
||||
resolved-socket-graveyard.h
|
||||
resolved-varlink.c
|
||||
resolved-varlink.h
|
||||
resolved.c
|
||||
'''.split())
|
||||
|
||||
resolvectl_sources = files('''
|
||||
@@ -200,6 +199,14 @@ tests += [
|
||||
[lib_openssl_or_gcrypt,
|
||||
libm]],
|
||||
|
||||
[files('test-resolved-stream.c')
|
||||
+ basic_dns_sources + systemd_resolved_sources,
|
||||
[libshared],
|
||||
[lib_openssl_or_gcrypt,
|
||||
libm]
|
||||
+ systemd_resolved_dependencies,
|
||||
resolve_includes],
|
||||
|
||||
[files('test-dnssec.c'),
|
||||
[libsystemd_resolve_core,
|
||||
libshared],
|
||||
@@ -229,3 +236,5 @@ fuzzers += [
|
||||
[lib_openssl_or_gcrypt,
|
||||
libm]],
|
||||
]
|
||||
|
||||
systemd_resolved_sources += files('resolved.c')
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "io-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing_network.h"
|
||||
#include "resolved-dns-stream.h"
|
||||
#include "resolved-manager.h"
|
||||
@@ -280,13 +281,15 @@ static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) {
|
||||
return dns_stream_complete(s, ETIMEDOUT);
|
||||
}
|
||||
|
||||
static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
||||
_cleanup_(dns_stream_unrefp) DnsStream *s = dns_stream_ref(userdata); /* Protect stream while we process it */
|
||||
static int on_stream_io_impl(DnsStream *s, uint32_t revents) {
|
||||
bool progressed = false;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* This returns 1 when possible remaining stream exists, 0 on completed
|
||||
stream or recoverable error, and negative errno on failure. */
|
||||
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
if (s->encrypted) {
|
||||
r = dnstls_stream_on_io(s, revents);
|
||||
@@ -441,6 +444,44 @@ static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *use
|
||||
log_warning_errno(errno, "Couldn't restart TCP connection timeout, ignoring: %m");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
||||
_cleanup_(dns_stream_unrefp) DnsStream *s = dns_stream_ref(userdata); /* Protect stream while we process it */
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
r = on_stream_io_impl(s, revents);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
if (!s->encrypted)
|
||||
return 0;
|
||||
|
||||
/* When using DNS-over-TLS, the underlying TLS library may read the entire TLS record
|
||||
and buffer it internally. If this happens, we will not receive further EPOLLIN events,
|
||||
and unless there's some unrelated activity on the socket, we will hang until time out.
|
||||
To avoid this, if there's buffered TLS data, generate a "fake" EPOLLIN event.
|
||||
This is hacky, but it makes this case transparent to the rest of the IO code. */
|
||||
while (dnstls_stream_has_buffered_data(s)) {
|
||||
uint32_t events;
|
||||
|
||||
/* Make sure the stream still wants to process more data... */
|
||||
r = sd_event_source_get_io_events(s->io_event_source, &events);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!FLAGS_SET(events, EPOLLIN))
|
||||
break;
|
||||
|
||||
r = on_stream_io_impl(s, EPOLLIN);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -211,6 +211,14 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
|
||||
return ss;
|
||||
}
|
||||
|
||||
bool dnstls_stream_has_buffered_data(DnsStream *stream) {
|
||||
assert(stream);
|
||||
assert(stream->encrypted);
|
||||
assert(stream->dnstls_data.session);
|
||||
|
||||
return gnutls_record_check_pending(stream->dnstls_data.session) > 0;
|
||||
}
|
||||
|
||||
void dnstls_server_free(DnsServer *server) {
|
||||
assert(server);
|
||||
|
||||
|
||||
@@ -367,6 +367,14 @@ ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count) {
|
||||
return ss;
|
||||
}
|
||||
|
||||
bool dnstls_stream_has_buffered_data(DnsStream *stream) {
|
||||
assert(stream);
|
||||
assert(stream->encrypted);
|
||||
assert(stream->dnstls_data.ssl);
|
||||
|
||||
return SSL_has_pending(stream->dnstls_data.ssl) > 0;
|
||||
}
|
||||
|
||||
void dnstls_server_free(DnsServer *server) {
|
||||
assert(server);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct DnsServer DnsServer;
|
||||
@@ -28,6 +29,7 @@ int dnstls_stream_on_io(DnsStream *stream, uint32_t revents);
|
||||
int dnstls_stream_shutdown(DnsStream *stream, int error);
|
||||
ssize_t dnstls_stream_write(DnsStream *stream, const char *buf, size_t count);
|
||||
ssize_t dnstls_stream_read(DnsStream *stream, void *buf, size_t count);
|
||||
bool dnstls_stream_has_buffered_data(DnsStream *stream);
|
||||
|
||||
void dnstls_server_free(DnsServer *server);
|
||||
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "process-util.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
#include "resolved-dnstls.h"
|
||||
#endif
|
||||
#include "resolved-dns-server.h"
|
||||
#include "resolved-dns-stream.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "sd-event.h"
|
||||
#include "sparse-endian.h"
|
||||
#include "tests.h"
|
||||
|
||||
static struct sockaddr_in SERVER_ADDRESS;
|
||||
|
||||
/* Bytes of the questions & answers used in the test, including TCP DNS 2-byte length prefix */
|
||||
static const uint8_t QUESTION_A[] = {
|
||||
0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 'e',
|
||||
'x' , 'a' , 'm' , 'p' , 'l' , 'e' , 0x03, 'c' , 'o' , 'm' , 0x00, 0x00, 0x01, 0x00, 0x01
|
||||
};
|
||||
static const uint8_t QUESTION_AAAA[] = {
|
||||
0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 'e',
|
||||
'x' , 'a' , 'm' , 'p' , 'l' , 'e' , 0x03, 'c' , 'o' , 'm' , 0x00, 0x00, 0x1C, 0x00, 0x01
|
||||
};
|
||||
static const uint8_t ANSWER_A[] = {
|
||||
0x00, 0x2D, 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 'e',
|
||||
'x' , 'a' , 'm' , 'p' , 'l' , 'e' , 0x03, 'c' , 'o' , 'm' , 0x00, 0x00, 0x01, 0x00, 0x01, 0xC0,
|
||||
0x0C, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x52, 0x8D, 0x00, 0x04, 0x5D, 0xB8, 0xD8, 0x22,
|
||||
};
|
||||
static const uint8_t ANSWER_AAAA[] = {
|
||||
0x00, 0x39, 0x00, 0x00, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 'e',
|
||||
'x' , 'a' , 'm' , 'p' , 'l' , 'e' , 0x03, 'c' , 'o' , 'm' , 0x00, 0x00, 0x1C, 0x00, 0x01, 0xC0,
|
||||
0x0C, 0x00, 0x1C, 0x00, 0x01, 0x00, 0x00, 0x54, 0x4B, 0x00, 0x10, 0x26, 0x06, 0x28, 0x00, 0x02,
|
||||
0x20, 0x00, 0x01, 0x02, 0x48, 0x18, 0x93, 0x25, 0xC8, 0x19, 0x46,
|
||||
};
|
||||
|
||||
/**
|
||||
* A mock TCP DNS server that asserts certain questions are received
|
||||
* and replies with the same answer every time.
|
||||
*/
|
||||
static void receive_and_check_question(int fd, const uint8_t *expected_question,
|
||||
size_t question_size) {
|
||||
uint8_t *actual_question;
|
||||
size_t n_read = 0;
|
||||
|
||||
actual_question = newa(uint8_t, question_size);
|
||||
while (n_read < question_size) {
|
||||
ssize_t r = read(fd, actual_question + n_read, question_size - n_read);
|
||||
assert_se(r >= 0);
|
||||
n_read += (size_t)r;
|
||||
}
|
||||
assert_se(n_read == question_size);
|
||||
|
||||
assert_se(memcmp(expected_question, actual_question, question_size) == 0);
|
||||
}
|
||||
|
||||
static void send_answer(int fd, const uint8_t *answer, size_t answer_size) {
|
||||
assert_se(write(fd, answer, answer_size) == (ssize_t)answer_size);
|
||||
}
|
||||
|
||||
/* Sends two answers together in a single write operation,
|
||||
* so they hopefully end up in a single TCP packet / TLS record */
|
||||
static void send_answers_together(int fd,
|
||||
const uint8_t *answer1, size_t answer1_size,
|
||||
const uint8_t *answer2, size_t answer2_size) {
|
||||
uint8_t *answer;
|
||||
size_t answer_size = answer1_size + answer2_size;
|
||||
|
||||
answer = newa(uint8_t, answer_size);
|
||||
memcpy(answer, answer1, answer1_size);
|
||||
memcpy(answer + answer1_size, answer2, answer2_size);
|
||||
assert_se(write(fd, answer, answer_size) == (ssize_t)answer_size);
|
||||
}
|
||||
|
||||
static void server_handle(int fd) {
|
||||
receive_and_check_question(fd, QUESTION_A, sizeof(QUESTION_A));
|
||||
send_answer(fd, ANSWER_A, sizeof(ANSWER_A));
|
||||
|
||||
receive_and_check_question(fd, QUESTION_AAAA, sizeof(QUESTION_AAAA));
|
||||
send_answer(fd, ANSWER_AAAA, sizeof(ANSWER_AAAA));
|
||||
|
||||
receive_and_check_question(fd, QUESTION_A, sizeof(QUESTION_A));
|
||||
receive_and_check_question(fd, QUESTION_AAAA, sizeof(QUESTION_AAAA));
|
||||
send_answers_together(fd, ANSWER_A, sizeof(ANSWER_A),
|
||||
ANSWER_AAAA, sizeof(ANSWER_AAAA));
|
||||
}
|
||||
|
||||
static void *tcp_dns_server(void *p) {
|
||||
_cleanup_close_ int bindfd = -1, acceptfd = -1;
|
||||
|
||||
assert_se((bindfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) >= 0);
|
||||
assert_se(setsockopt(bindfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) >= 0);
|
||||
assert_se(bind(bindfd, &SERVER_ADDRESS, sizeof(SERVER_ADDRESS)) >= 0);
|
||||
assert_se(listen(bindfd, 1) >= 0);
|
||||
assert_se((acceptfd = accept(bindfd, NULL, NULL)) >= 0);
|
||||
server_handle(acceptfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
/*
|
||||
* Spawns a DNS TLS server using the command line "openssl s_server" tool.
|
||||
*/
|
||||
static void *tls_dns_server(void *p) {
|
||||
pid_t openssl_pid;
|
||||
int r;
|
||||
_cleanup_close_ int fd_server = -1, fd_tls = -1;
|
||||
_cleanup_free_ char *cert_path = NULL, *key_path = NULL;
|
||||
_cleanup_free_ char *ip_str = NULL, *bind_str = NULL;
|
||||
|
||||
assert_se(get_testdata_dir("test-resolve/selfsigned.cert", &cert_path) >= 0);
|
||||
assert_se(get_testdata_dir("test-resolve/selfsigned.key", &key_path) >= 0);
|
||||
|
||||
assert_se(in_addr_to_string(SERVER_ADDRESS.sin_family,
|
||||
&(union in_addr_union){.in = SERVER_ADDRESS.sin_addr},
|
||||
&ip_str) >= 0);
|
||||
asprintf(&bind_str, "%s:%d", ip_str, be16toh(SERVER_ADDRESS.sin_port));
|
||||
|
||||
/* We will hook one of the socketpair ends to OpenSSL's TLS server
|
||||
* stdin/stdout, so we will be able to read and write plaintext
|
||||
* from the other end's file descriptor like an usual TCP server */
|
||||
{
|
||||
int fd[2];
|
||||
assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) >= 0);
|
||||
fd_server = fd[0];
|
||||
fd_tls = fd[1];
|
||||
}
|
||||
|
||||
r = safe_fork_full("(test-resolved-stream-tls-openssl)", (int[]) { fd_server, fd_tls }, 2,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &openssl_pid);
|
||||
assert(r >= 0);
|
||||
if (r == 0) {
|
||||
/* Child */
|
||||
assert_se(dup2(fd_tls, STDIN_FILENO) >= 0);
|
||||
assert_se(dup2(fd_tls, STDOUT_FILENO) >= 0);
|
||||
close(TAKE_FD(fd_server));
|
||||
close(TAKE_FD(fd_tls));
|
||||
|
||||
execlp("openssl", "openssl", "s_server", "-accept", bind_str,
|
||||
"-key", key_path, "-cert", cert_path,
|
||||
"-quiet", "-naccept", "1", NULL);
|
||||
log_error("exec failed, is something wrong with the 'openssl' command?");
|
||||
_exit(EXIT_FAILURE);
|
||||
} else {
|
||||
pthread_mutex_t *server_lock = (pthread_mutex_t *)p;
|
||||
|
||||
server_handle(fd_server);
|
||||
|
||||
/* Once the test is done kill the TLS server to release the port */
|
||||
assert_se(pthread_mutex_lock(server_lock) == 0);
|
||||
assert_se(kill(openssl_pid, SIGTERM) >= 0);
|
||||
assert_se(waitpid(openssl_pid, NULL, 0) >= 0);
|
||||
assert_se(pthread_mutex_unlock(server_lock) == 0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *TEST_DOMAIN = "example.com";
|
||||
static const uint64_t EVENT_TIMEOUT_USEC = 5 * 1000 * 1000;
|
||||
|
||||
static void send_simple_question(DnsStream *stream, uint16_t type) {
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
|
||||
_cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
|
||||
|
||||
assert_se(dns_packet_new(&p, DNS_PROTOCOL_DNS, 0, DNS_PACKET_SIZE_MAX) >= 0);
|
||||
assert_se(question = dns_question_new(1));
|
||||
assert_se(key = dns_resource_key_new(DNS_CLASS_IN, type, TEST_DOMAIN));
|
||||
assert_se(dns_question_add(question, key, 0) >= 0);
|
||||
assert_se(dns_packet_append_question(p, question) >= 0);
|
||||
DNS_PACKET_HEADER(p)->qdcount = htobe16(dns_question_size(question));
|
||||
assert_se(dns_stream_write_packet(stream, p) >= 0);
|
||||
}
|
||||
|
||||
static const size_t MAX_RECEIVED_PACKETS = 2;
|
||||
static DnsPacket *received_packets[2] = {};
|
||||
static size_t n_received_packets = 0;
|
||||
|
||||
static int on_stream_packet(DnsStream *stream) {
|
||||
assert_se(n_received_packets < MAX_RECEIVED_PACKETS);
|
||||
assert_se(received_packets[n_received_packets++] = dns_stream_take_read_packet(stream));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_dns_stream(bool tls) {
|
||||
Manager manager = {};
|
||||
_cleanup_(dns_stream_unrefp) DnsStream *stream = NULL;
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
_cleanup_close_ int clientfd = -1;
|
||||
int r;
|
||||
|
||||
void *(*server_entrypoint)(void *);
|
||||
pthread_t server_thread;
|
||||
pthread_mutex_t server_lock;
|
||||
|
||||
log_info("test-resolved-stream: Started %s test", tls ? "TLS" : "TCP");
|
||||
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
if (tls) {
|
||||
/* For TLS mode, use DNS_OVER_TLS_OPPORTUNISTIC instead of
|
||||
* DNS_OVER_TLS_YES, just to make certificate validation more
|
||||
* lenient, allowing us to use self-signed certificates.
|
||||
* We never downgrade, everything we test always goes over TLS */
|
||||
manager.dns_over_tls_mode = DNS_OVER_TLS_OPPORTUNISTIC;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert_se(sd_event_new(&event) >= 0);
|
||||
manager.event = event;
|
||||
|
||||
/* Set up a mock DNS (over TCP or TLS) server */
|
||||
server_entrypoint = tcp_dns_server;
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
if (tls)
|
||||
server_entrypoint = tls_dns_server;
|
||||
#endif
|
||||
assert_se(pthread_mutex_init(&server_lock, NULL) == 0);
|
||||
assert_se(pthread_mutex_lock(&server_lock) == 0);
|
||||
assert_se(pthread_create(&server_thread, NULL, server_entrypoint, &server_lock) == 0);
|
||||
|
||||
/* Create a socket client and connect to the TCP or TLS server
|
||||
* The server may not be up immediately, so try to connect a few times before failing */
|
||||
assert_se((clientfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) >= 0);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
r = connect(clientfd, &SERVER_ADDRESS, sizeof(SERVER_ADDRESS));
|
||||
if (r >= 0)
|
||||
break;
|
||||
usleep(EVENT_TIMEOUT_USEC / 100);
|
||||
}
|
||||
assert_se(r >= 0);
|
||||
|
||||
/* systemd-resolved uses (and requires) the socket to be in nonblocking mode */
|
||||
assert_se(fcntl(clientfd, F_SETFL, O_NONBLOCK) >= 0);
|
||||
|
||||
/* Initialize DNS stream */
|
||||
assert_se(dns_stream_new(&manager, &stream, DNS_STREAM_LOOKUP, DNS_PROTOCOL_DNS,
|
||||
TAKE_FD(clientfd), NULL, DNS_STREAM_DEFAULT_TIMEOUT_USEC) >= 0);
|
||||
stream->on_packet = on_stream_packet;
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
if (tls) {
|
||||
DnsServer server = {
|
||||
.manager = &manager,
|
||||
.family = SERVER_ADDRESS.sin_family,
|
||||
.address.in = SERVER_ADDRESS.sin_addr
|
||||
};
|
||||
|
||||
assert_se(dnstls_manager_init(&manager) >= 0);
|
||||
assert_se(dnstls_stream_connect_tls(stream, &server) >= 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Test: Question of type A and associated answer */
|
||||
log_info("test-resolved-stream: A record");
|
||||
send_simple_question(stream, DNS_TYPE_A);
|
||||
while (n_received_packets != 1)
|
||||
assert_se(sd_event_run(event, EVENT_TIMEOUT_USEC) >= 1);
|
||||
assert_se(DNS_PACKET_DATA(received_packets[0]));
|
||||
assert_se(memcmp(DNS_PACKET_DATA(received_packets[0]),
|
||||
ANSWER_A + 2, sizeof(ANSWER_A) - 2) == 0);
|
||||
dns_packet_unref(TAKE_PTR(received_packets[0]));
|
||||
n_received_packets = 0;
|
||||
|
||||
/* Test: Question of type AAAA and associated answer */
|
||||
log_info("test-resolved-stream: AAAA record");
|
||||
send_simple_question(stream, DNS_TYPE_AAAA);
|
||||
while (n_received_packets != 1)
|
||||
assert_se(sd_event_run(event, EVENT_TIMEOUT_USEC) >= 1);
|
||||
assert_se(DNS_PACKET_DATA(received_packets[0]));
|
||||
assert_se(memcmp(DNS_PACKET_DATA(received_packets[0]),
|
||||
ANSWER_AAAA + 2, sizeof(ANSWER_AAAA) - 2) == 0);
|
||||
dns_packet_unref(TAKE_PTR(received_packets[0]));
|
||||
n_received_packets = 0;
|
||||
|
||||
/* Test: Question of type A and AAAA and associated answers
|
||||
* Both answers are sent back in a single packet or TLS record
|
||||
* (tests the fix of PR #22132: "Fix DoT timeout on multiple answer records") */
|
||||
log_info("test-resolved-stream: A + AAAA record");
|
||||
send_simple_question(stream, DNS_TYPE_A);
|
||||
send_simple_question(stream, DNS_TYPE_AAAA);
|
||||
|
||||
while (n_received_packets != 2)
|
||||
assert_se(sd_event_run(event, EVENT_TIMEOUT_USEC) >= 1);
|
||||
assert_se(DNS_PACKET_DATA(received_packets[0]));
|
||||
assert_se(DNS_PACKET_DATA(received_packets[1]));
|
||||
assert_se(memcmp(DNS_PACKET_DATA(received_packets[0]),
|
||||
ANSWER_A + 2, sizeof(ANSWER_A) - 2) == 0);
|
||||
assert_se(memcmp(DNS_PACKET_DATA(received_packets[1]),
|
||||
ANSWER_AAAA + 2, sizeof(ANSWER_AAAA) - 2) == 0);
|
||||
dns_packet_unref(TAKE_PTR(received_packets[0]));
|
||||
dns_packet_unref(TAKE_PTR(received_packets[1]));
|
||||
n_received_packets = 0;
|
||||
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
if (tls)
|
||||
dnstls_manager_free(&manager);
|
||||
#endif
|
||||
|
||||
/* Stop the DNS server */
|
||||
assert_se(pthread_mutex_unlock(&server_lock) == 0);
|
||||
assert_se(pthread_join(server_thread, NULL) == 0);
|
||||
assert_se(pthread_mutex_destroy(&server_lock) == 0);
|
||||
|
||||
log_info("test-resolved-stream: Finished %s test", tls ? "TLS" : "TCP");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
SERVER_ADDRESS = (struct sockaddr_in) {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htobe16(12345),
|
||||
.sin_addr.s_addr = htobe32(INADDR_LOOPBACK)
|
||||
};
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_dns_stream(false);
|
||||
#if ENABLE_DNS_OVER_TLS
|
||||
if (system("openssl version >/dev/null 2>&1") != 0)
|
||||
return log_tests_skipped("Skipping TLS test since the 'openssl' command does not seem to be available");
|
||||
test_dns_stream(true);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user