#include "log.h"
#include "resolved-dns-query.h"
#include "resolved-dns-rr.h"
+#include "resolved-dns-scope.h"
+#include "resolved-dns-server.h"
+#include "resolved-link.h"
#include "resolved-manager.h"
#include "tests.h"
dns_resource_key_unref(key);
}
+/* ================================================================
+ * dns_query_go()
+ * ================================================================ */
+
+/* Testing this function is somewhat problematic since, in addition to setting up the state for query
+ * candidates, their scopes and transactions, it also directly initiates I/O to files and the network. In
+ * particular:
+ *
+ * - The very first thing it does is try to respond to the query by reading the system /etc/hosts file, which
+ * may be symlinked to a SystemD resource. Ideally we could test this without accessing global files.
+ *
+ * - dns_scope_get_dns_server() calls manager_get_dns_server(), which tries to read /etc/resolv.conf.
+ *
+ * - A potential solution to these issues would be to let these file paths be configured instead of
+ * hard-coded into the source.
+ *
+ * - dns_scope_good_domain(), by checking dns_scope_get_dns_server(), will not match with a scope that does
+ * not have a server configured, either on the scope's link (if it has one) or the manager's main/fallback
+ * server. Configuring a server means that dns_query_candidate_go() and then dns_transaction_go() will send
+ * UDP/TCP traffic to that server. Ideally we'd like to test that we can set up all the candidate and
+ * transaction state without actually causing any requests to be sent.
+ */
+
+static void dns_scope_freep(DnsScope **s) {
+ dns_scope_free(*s);
+}
+
+typedef struct GoConfig {
+ bool use_link;
+} GoConfig;
+
+static GoConfig mk_go_config(void) {
+ return (GoConfig) {
+ .use_link = false
+ };
+}
+
+static void exercise_dns_query_go(GoConfig *cfg) {
+ Manager manager = {};
+ Link *link = NULL;
+ _cleanup_(dns_server_unrefp) DnsServer *server = NULL;
+ _cleanup_(dns_scope_freep) DnsScope *scope = NULL;
+
+ _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
+ _cleanup_(dns_query_freep) DnsQuery *query = NULL;
+
+ DnsProtocol protocol = DNS_PROTOCOL_DNS;
+ int family = AF_INET;
+ int flags = SD_RESOLVED_FLAGS_MAKE(protocol, family, false, false);
+ int ifindex;
+
+ union in_addr_union server_addr = { .in.s_addr = htobe32(0x7f000001) };
+ const char *server_name = "localhost";
+ uint16_t port = 53;
+ DnsServerType type;
+
+ if (cfg->use_link) {
+ ifindex = 1;
+ ASSERT_OK(link_new(&manager, &link, ifindex));
+ ASSERT_NOT_NULL(link);
+ type = DNS_SERVER_LINK;
+ } else {
+ ifindex = 0;
+ link = NULL;
+ type = DNS_SERVER_FALLBACK;
+ }
+
+ ASSERT_OK(sd_event_new(&manager.event));
+ ASSERT_NOT_NULL(manager.event);
+
+ ASSERT_OK(dns_server_new(&manager, &server, type, link, family, &server_addr,
+ port, ifindex, server_name, RESOLVE_CONFIG_SOURCE_DBUS));
+
+ ASSERT_NOT_NULL(server);
+
+ ASSERT_OK(dns_scope_new(&manager, &scope, link, protocol, family));
+ ASSERT_NOT_NULL(scope);
+
+ ASSERT_OK(dns_question_new_address(&question, AF_INET, "www.example.com", false));
+ ASSERT_NOT_NULL(question);
+
+ ASSERT_OK(dns_query_new(&manager, &query, question, question, NULL, ifindex, flags));
+ ASSERT_NOT_NULL(query);
+
+ ASSERT_OK(dns_query_go(query));
+
+ dns_server_unref(server);
+ sd_event_unref(manager.event);
+}
+
+TEST(dns_query_go) {
+ GoConfig cfg1 = mk_go_config();
+ exercise_dns_query_go(&cfg1);
+
+ GoConfig cfg2 = mk_go_config();
+ cfg2.use_link = true;
+ exercise_dns_query_go(&cfg2);
+}
+
DEFINE_TEST_MAIN(LOG_DEBUG);