Compare commits

..

11 Commits
quic ... master

Author SHA1 Message Date
Nick Peng
52ee66973a dns_server: ignore non-matched record. 2023-12-22 23:55:18 +08:00
Nick Peng
c67031eb7c feature: support lookup local network host name or ip via mDNS 2023-12-22 22:39:14 +08:00
Nick Peng
33ee73cbf2 test: fix test issue. 2023-12-20 22:04:45 +08:00
Nick Peng
ba2cad4b44 dns_client: disable server when upstream returns failure 2023-12-19 22:35:26 +08:00
Nick Peng
1d46fa6208 dns_client: retry when upstream result is empty. 2023-12-19 22:29:44 +08:00
Nick Peng
a19ac7eb07 dns-server: simple support proxy dnssec 2023-12-16 18:47:46 +08:00
Nick Peng
a0f82eabcd dns_server: Optimize the processing of upstream returns to SOA. 2023-12-15 23:05:17 +08:00
Nick Peng
1a17da726d address: force anoter A/AAAA SOA when ip is set. 2023-12-15 23:03:43 +08:00
Nick Peng
c6e28d6087 Makefile: update make file. 2023-12-15 22:18:42 +08:00
Nick Peng
43b5d6a63d tlog: update tlog 2023-12-11 22:52:27 +08:00
Nguyễn Gia Phong
577fc35827 dns_server: log addrinfo nonsystem error 2023-12-10 19:27:14 +08:00
47 changed files with 1195 additions and 641 deletions

View File

@@ -199,13 +199,12 @@ log-level info
# g|-group [group]: set server to group, use with nameserver /domain/group.
# e|-exclude-default-group: exclude this server from default group.
# p|-proxy [proxy-name]: use proxy to connect to server.
# -bootstrap-dns: set as bootstrap dns server.
# b|-bootstrap-dns: set as bootstrap dns server.
# -set-mark: set mark on packets.
# -subnet [ip/subnet]: set edns client subnet.
# -host-ip [ip]: set dns server host ip.
# server 8.8.8.8 -blacklist-ip -check-edns -group g1 -group g2
# server tls://dns.google:853
# server quic://dns.gooel.com:443
# server https://dns.google/dns-query
# remote tcp dns server list
@@ -227,20 +226,6 @@ log-level info
# server-tls 8.8.8.8
# server-tls 1.0.0.1
# remote quic dns server list
# server-quic [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# -spki-pin: TLS spki pin to verify.
# -tls-host-verify: cert hostname to verify.
# -host-name: TLS sni hostname.
# k|-no-check-certificate: no check certificate.
# p|-proxy [proxy-name]: use proxy to connect to server.
# -bootstrap-dns: set as bootstrap dns server.
# Get SPKI with this command:
# echo | openssl s_client -connect '[ip]:443' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
# default port is 443
# server-quic 8.8.8.8
# server-quic 1.0.0.1
# remote https dns server list
# server-https https://[host]:[port]/path [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# -spki-pin: TLS spki pin to verify.
@@ -322,6 +307,10 @@ log-level info
# set ddns domain
# ddns-domain domain
# lookup local network hostname or ip address from mdns
# mdns-lookup [yes|no]
# mdns-lookup no
# set domain rules
# domain-rules /domain/ [-speed-check-mode [...]]
# rules:

View File

@@ -350,6 +350,9 @@ msgstr "日志数量"
msgid "Log File"
msgstr "日志文件路径"
msgid "mDNS Lookup"
msgstr "mDNS查询"
msgid "Marking Packets"
msgstr "数据包标记"
@@ -434,6 +437,9 @@ msgstr "解析本地主机名"
msgid "Resolve local hostnames by reading Dnsmasq lease file."
msgstr "读取Dnsmasq的租约文件解析本地主机名。"
msgid "Resolve local network hostname via mDNS protocol."
msgstr "使用mDNS协议解析本地网络主机名。"
msgid "Response Mode"
msgstr "响应模式"

View File

@@ -239,7 +239,7 @@ o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "1"
end
-- cache-size
-- resolve local hostname
o = s:taboption("advanced", Flag, "resolve_local_hostnames", translate("Resolve Local Hostnames"), translate("Resolve local hostnames by reading Dnsmasq lease file."))
o.rmempty = false
o.default = o.enabled
@@ -247,6 +247,14 @@ o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "1"
end
-- resolve local network hostname via mDNS
o = s:taboption("advanced", Flag, "mdns_lookup", translate("mDNS Lookup"), translate("Resolve local network hostname via mDNS protocol."))
o.rmempty = true
o.default = o.disabled
o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "0"
end
-- Force AAAA SOA
o = s:taboption("advanced", Flag, "force_aaaa_soa", translate("Force AAAA SOA"), translate("Force AAAA SOA."))
o.rmempty = true

View File

@@ -393,6 +393,9 @@ msgstr "日志数量"
msgid "Log File"
msgstr "日志文件路径"
msgid "mDNS Lookup"
msgstr "mDNS查询"
msgid "Marking Packets"
msgstr "数据包标记"
@@ -483,6 +486,9 @@ msgstr "解析本地主机名"
msgid "Resolve local hostnames by reading Dnsmasq lease file."
msgstr "读取Dnsmasq的租约文件解析本地主机名。"
msgid "Resolve local network hostname via mDNS protocol."
msgstr "使用mDNS协议解析本地网络主机名。"
msgid "Response Mode"
msgstr "响应模式"

View File

@@ -311,11 +311,16 @@ return view.extend({
o.rmempty = false;
o.default = o.enabled;
// cache-size;
// resolve local hostname;
o = s.taboption("advanced", form.Flag, "resolve_local_hostnames", _("Resolve Local Hostnames"), _("Resolve local hostnames by reading Dnsmasq lease file."));
o.rmempty = false;
o.default = o.enabled;
// resolve local network hostname via mDNS;
o = s.taboption("advanced", form.Flag, "mdns_lookup", _("mDNS Lookup"), _("Resolve local network hostname via mDNS protocol."));
o.rmempty = true;
o.default = o.disabled;
// Force AAAA SOA
o = s.taboption("advanced", form.Flag, "force_aaaa_soa", _("Force AAAA SOA"), _("Force AAAA SOA."));
o.rmempty = true;

View File

@@ -644,6 +644,9 @@ load_service()
config_get dns64 "$section" "dns64" ""
[ -z "$dns64" ] || conf_append "dns64" "$dns64"
config_get_bool mdns_lookup "$section" "mdns_lookup" "0"
[ "$mdns_lookup" = "1" ] && conf_append "mdns-lookup" "yes"
config_get redirect "$section" "redirect" ""
config_get old_port "$section" "old_port" "0"
config_get old_enabled "$section" "old_enabled" "0"

View File

@@ -15,8 +15,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
BIN=smartdns
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/timer_wheel.o lib/idna.o lib/conf.o lib/nftset.o
OBJS_MAIN=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o http_parse.o proxy.o timer.o
OBJS_LIB=$(patsubst %.c,%.o,$(wildcard lib/*.c))
OBJS_MAIN=$(patsubst %.c,%.o,$(wildcard *.c))
OBJS=$(OBJS_MAIN) $(OBJS_LIB)
# cflags
@@ -26,13 +26,23 @@ ifndef CFLAGS
else
CFLAGS = -O2
endif
CFLAGS +=-Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing -funwind-tables -Wmissing-prototypes -Wshadow -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough
CFLAGS +=-Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing -funwind-tables -Wmissing-prototypes -Wshadow -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough
endif
override CFLAGS +=-Iinclude -I/home/rock/code/build/openssl/openssl-3.2.0/include
override CFLAGS +=-Iinclude
override CFLAGS += -DBASE_FILE_NAME='"$(notdir $<)"'
override CFLAGS += $(EXTRA_CFLAGS)
ifdef VER
override CFLAGS += -DSMARTDNS_VERION='"$(VER)"'
override CFLAGS += -DSMARTDNS_VERION='"$(VER)"'
else
HAS_GIT := $(shell command -v git 2> /dev/null)
ifdef HAS_GIT
IS_GIT_REPO := $(shell git rev-parse --is-inside-work-tree 2>/dev/null)
ifdef IS_GIT_REPO
override CFLAGS += -DSMARTDNS_VERION='"$(shell git describe --tags --always --dirty)"'
endif
endif
endif
CXXFLAGS=-O2 -g -Wall -std=c++11
@@ -40,9 +50,9 @@ override CXXFLAGS +=-Iinclude
# ldflags
ifeq ($(STATIC), yes)
override LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static -L/home/rock/code/build/openssl/openssl-3.2.0
override LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -lm -static
else
override LDFLAGS += -lssl -lcrypto -lpthread -ldl
override LDFLAGS += -lssl -lcrypto -lpthread -ldl -lm
endif
.PHONY: all clean

View File

@@ -34,6 +34,9 @@
#define TC_MASK 0x0200
#define RD_MASK 0x0100
#define RA_MASK 0x0080
#define Z_MASK 0x0040
#define AD_MASK 0x0020
#define CD_MASK 0x0010
#define RCODE_MASK 0x000F
#define DNS_RR_END (0XFFFF)
@@ -1011,6 +1014,17 @@ int dns_get_OPT_payload_size(struct dns_packet *packet)
return packet->payloadsize;
}
int dns_set_OPT_option(struct dns_packet *packet, unsigned int option)
{
packet->opt_option = option;
return 0;
}
unsigned int dns_get_OPT_option(struct dns_packet *packet)
{
return packet->opt_option;
}
int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
{
unsigned char opt_data[DNS_MAX_OPT_LEN];
@@ -1402,6 +1416,9 @@ static int _dns_decode_head(struct dns_context *context)
head->tc = (fields & TC_MASK) >> 9;
head->rd = (fields & RD_MASK) >> 8;
head->ra = (fields & RA_MASK) >> 7;
head->z = (fields & Z_MASK) >> 6;
head->ad = (fields & AD_MASK) >> 5;
head->cd = (fields & CD_MASK) >> 4;
head->rcode = (fields & RCODE_MASK) >> 0;
head->qdcount = _dns_read_short(&context->ptr);
head->ancount = _dns_read_short(&context->ptr);
@@ -1429,6 +1446,9 @@ static int _dns_encode_head(struct dns_context *context)
fields |= (head->tc << 9) & TC_MASK;
fields |= (head->rd << 8) & RD_MASK;
fields |= (head->ra << 7) & RA_MASK;
fields |= (head->z << 6) & Z_MASK;
fields |= (head->ad << 5) & AD_MASK;
fields |= (head->cd << 4) & CD_MASK;
fields |= (head->rcode << 0) & RCODE_MASK;
_dns_write_short(&context->ptr, fields);
@@ -1976,7 +1996,7 @@ static int _dns_encode_opts(struct dns_packet *packet, struct dns_context *conte
int i = 0;
int len = 0;
int ret = 0;
unsigned int rcode = 0;
unsigned int rcode = packet->opt_option;
int rr_len = 0;
int payloadsize = packet->payloadsize;
unsigned char *rr_len_ptr = NULL;
@@ -2429,7 +2449,7 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
tlog(TLOG_DEBUG, "opt length mismatch, %s\n", domain);
return -1;
}
dns_set_OPT_option(packet, ttl);
dns_set_OPT_payload_size(packet, qclass);
} break;
case DNS_T_HTTPS: {
@@ -2680,6 +2700,9 @@ int dns_packet_init(struct dns_packet *packet, int size, struct dns_head *head)
init_head->tc = head->tc;
init_head->rd = head->rd;
init_head->ra = head->ra;
init_head->z = head->z;
init_head->ad = head->ad;
init_head->cd = head->cd;
init_head->rcode = head->rcode;
packet->questions = DNS_RR_END;
packet->answers = DNS_RR_END;

View File

@@ -33,6 +33,8 @@ extern "C" {
#define DNS_MAX_ALPN_LEN 32
#define DNS_MAX_ECH_LEN 256
#define DNS_OPT_FLAG_DO 0x8000
#define DNS_ADDR_FAMILY_IP 1
#define DNS_ADDR_FAMILY_IPV6 2
@@ -132,6 +134,10 @@ struct dns_head {
unsigned char tc; /* Truncation Flag */
unsigned char rd; /* Recursion Desired */
unsigned char ra; /* Recursion Available */
unsigned char z; /* Reserved for future use. Must be Zero! */
unsigned char ad; /* Authentic Data Flag */
unsigned char cd; /* Checking Disabled Flag */
unsigned char padding; /* Padding */
unsigned short rcode; /* Response Code */
unsigned short qdcount; /* number of question entries */
unsigned short ancount; /* number of answer entries */
@@ -160,6 +166,7 @@ struct dns_packet {
unsigned short optcount;
unsigned short optional;
unsigned short payloadsize;
unsigned int opt_option;
struct dns_packet_dict namedict;
int size;
int len;
@@ -276,6 +283,9 @@ int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct
int dns_add_NS(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, const char *cname);
int dns_get_NS(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size);
int dns_set_OPT_option(struct dns_packet *packet, unsigned int option);
unsigned int dns_get_OPT_option(struct dns_packet *packet);
int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size);
int dns_get_OPT_payload_size(struct dns_packet *packet);

View File

@@ -33,7 +33,9 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <linux/filter.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/icmp6.h>
#include <netinet/ip.h>
@@ -50,6 +52,7 @@
#include <string.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -61,12 +64,15 @@
#define DNS_TCP_BUFFER (32 * 1024)
#define DNS_TCP_IDLE_TIMEOUT (60 * 10)
#define DNS_TCP_CONNECT_TIMEOUT (5)
#define DNS_QUERY_TIMEOUT (3000)
#define DNS_QUERY_TIMEOUT (500)
#define DNS_QUERY_RETRY (4)
#define DNS_PENDING_SERVER_RETRY 60
#define SOCKET_PRIORITY (6)
#define SOCKET_IP_TOS (IPTOS_LOWDELAY | IPTOS_RELIABILITY)
#define DNS_MDNS_IP "224.0.0.251"
#define DNS_MDNS_PORT 5353
/* ECS info */
struct dns_client_ecs {
int enable;
@@ -265,6 +271,9 @@ struct dns_query_struct {
/* ECS */
struct dns_client_ecs ecs;
/* EDNS0_DO */
int edns0_do;
/* replied hash table */
DECLARE_HASHTABLE(replied_map, 4);
};
@@ -397,6 +406,42 @@ int dns_client_get_server_port(struct dns_server_info *server_info)
return server_info->port;
}
static inline void _dns_server_inc_server_num(struct dns_server_info *server_info)
{
if (server_info->type == DNS_SERVER_MDNS) {
return;
}
atomic_inc(&client.dns_server_num);
}
static inline void _dns_server_dec_server_num(struct dns_server_info *server_info)
{
if (server_info->type == DNS_SERVER_MDNS) {
return;
}
atomic_dec(&client.dns_server_num);
}
static inline void _dns_server_inc_prohibit_server_num(struct dns_server_info *server_info)
{
if (server_info->type == DNS_SERVER_MDNS) {
return;
}
atomic_inc(&client.dns_server_prohibit_num);
}
static inline void _dns_server_dec_prohibit_server_num(struct dns_server_info *server_info)
{
if (server_info->type == DNS_SERVER_MDNS) {
return;
}
atomic_dec(&client.dns_server_prohibit_num);
}
dns_server_type_t dns_client_get_server_type(struct dns_server_info *server_info)
{
if (server_info == NULL) {
@@ -423,8 +468,8 @@ static const char *_dns_server_get_type_string(dns_server_type_t type)
case DNS_SERVER_HTTPS:
type_str = "https";
break;
case DNS_SERVER_QUIC:
type_str = "quic";
case DNS_SERVER_MDNS:
type_str = "mdns";
break;
default:
break;
@@ -760,8 +805,7 @@ int dns_client_add_group(const char *group_name)
}
if (_dns_client_get_group(group_name) != NULL) {
tlog(TLOG_ERROR, "add group %s failed, group already exists", group_name);
return -1;
return 0;
}
group = malloc(sizeof(*group));
@@ -866,13 +910,14 @@ static char *_dns_client_server_get_tls_host_verify(struct dns_server_info *serv
struct client_dns_server_flag_https *flag_https = &server_info->flags.https;
tls_host_verify = flag_https->tls_host_verify;
} break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
tls_host_verify = flag_tls->tls_host_verify;
} break;
case DNS_SERVER_TCP:
break;
case DNS_SERVER_MDNS:
break;
default:
return NULL;
break;
@@ -899,7 +944,6 @@ static char *_dns_client_server_get_spki(struct dns_server_info *server_info, in
spki = flag_https->spki;
*spki_len = flag_https->spi_len;
} break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
spki = flag_tls->spki;
@@ -907,6 +951,8 @@ static char *_dns_client_server_get_spki(struct dns_server_info *server_info, in
} break;
case DNS_SERVER_TCP:
break;
case DNS_SERVER_MDNS:
break;
default:
return NULL;
break;
@@ -960,7 +1006,7 @@ static int _dns_client_set_trusted_cert(SSL_CTX *ssl_ctx)
return 0;
}
static SSL_CTX *_ssl_ctx_get(int is_quic)
static SSL_CTX *_ssl_ctx_get(void)
{
pthread_mutex_lock(&client.server_list_lock);
SSL_CTX *ssl_ctx = client.ssl_ctx;
@@ -970,18 +1016,7 @@ static SSL_CTX *_ssl_ctx_get(int is_quic)
}
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
if (is_quic) {
ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
} else {
ssl_ctx = SSL_CTX_new(TLS_client_method());
}
#else
if (is_quic) {
return NULL;
}
ssl_ctx = SSL_CTX_new(TLS_client_method());
#endif
#else
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
#endif
@@ -1068,12 +1103,6 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
sock_type = SOCK_STREAM;
skip_check_cert = flag_https->skip_check_cert;
} break;
case DNS_SERVER_QUIC: {
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
spki_data_len = flag_tls->spi_len;
sock_type = SOCK_DGRAM;
skip_check_cert = flag_tls->skip_check_cert;
} break;
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
spki_data_len = flag_tls->spi_len;
@@ -1083,6 +1112,11 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
case DNS_SERVER_TCP:
sock_type = SOCK_STREAM;
break;
case DNS_SERVER_MDNS: {
struct client_dns_server_flag_mdns *flag_mdns = &flags->mdns;
safe_strncpy(flag_mdns->ifname, server_host, DNS_MAX_CNAME_LEN);
sock_type = SOCK_DGRAM;
} break;
default:
return -1;
break;
@@ -1146,12 +1180,8 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
}
/* if server type is TLS, create ssl context */
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS || server_type == DNS_SERVER_QUIC) {
if (server_type == DNS_SERVER_QUIC) {
server_info->ssl_ctx = _ssl_ctx_get(1);
} else {
server_info->ssl_ctx = _ssl_ctx_get(0);
}
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS) {
server_info->ssl_ctx = _ssl_ctx_get();
if (server_info->ssl_ctx == NULL) {
tlog(TLOG_ERROR, "init ssl failed.");
goto errout;
@@ -1191,9 +1221,8 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
list_add(&server_info->list, &client.dns_server_list);
pthread_mutex_unlock(&client.server_list_lock);
atomic_inc(&client.dns_server_num);
_dns_server_inc_server_num(server_info);
freeaddrinfo(gai);
tlog(TLOG_INFO, "add server %s:%d, type: %s", server_ip, port, _dns_server_get_type_string(server_info->type));
return 0;
@@ -1263,7 +1292,6 @@ static void _dns_client_shutdown_socket(struct dns_server_info *server_info)
shutdown(server_info->fd, SHUT_RDWR);
}
break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS:
case DNS_SERVER_HTTPS:
if (server_info->ssl) {
@@ -1274,6 +1302,8 @@ static void _dns_client_shutdown_socket(struct dns_server_info *server_info)
shutdown(server_info->fd, SHUT_RDWR);
}
break;
case DNS_SERVER_MDNS:
break;
default:
break;
}
@@ -1336,8 +1366,8 @@ static int _dns_client_server_remove(char *server_ip, int port, dns_server_type_
_dns_client_server_close(server_info);
pthread_mutex_unlock(&client.server_list_lock);
_dns_client_remove_server_from_groups(server_info);
_dns_server_dec_server_num(server_info);
free(server_info);
atomic_dec(&client.dns_server_num);
return 0;
}
pthread_mutex_unlock(&client.server_list_lock);
@@ -1609,7 +1639,7 @@ static void _dns_client_check_tcp(void)
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry(server_info, &client.dns_server_list, list)
{
if (server_info->type == DNS_SERVER_UDP) {
if (server_info->type == DNS_SERVER_UDP || server_info->type == DNS_SERVER_MDNS) {
/* no need to check udp server */
continue;
}
@@ -1698,6 +1728,26 @@ static int _dns_replied_check_add(struct dns_query_struct *dns_query, struct soc
return 0;
}
static void _dns_replied_check_remove(struct dns_query_struct *dns_query, struct sockaddr *addr, socklen_t addr_len)
{
uint32_t key = 0;
struct dns_query_replied *replied_map = NULL;
if (addr_len > sizeof(struct sockaddr_in6)) {
return;
}
key = jhash(addr, addr_len, 0);
hash_for_each_possible(dns_query->replied_map, replied_map, node, key)
{
if (memcmp(&replied_map->addr, addr, addr_len) == 0) {
hash_del(&replied_map->node);
free(replied_map);
return;
}
}
}
static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *inpacket, int inpacket_len,
struct sockaddr *from, socklen_t from_len)
{
@@ -1785,13 +1835,17 @@ static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *
if (query->callback) {
ret = query->callback(query->domain, DNS_QUERY_RESULT, server_info, packet, inpacket, inpacket_len,
query->user_ptr);
if (request_num == 0 || ret) {
if (request_num == 0 && ret == 0) {
/* if all server replied, or done, stop query, release resource */
_dns_client_query_remove(query);
}
if (ret == 0) {
query->has_result = 1;
} else {
/* remove this result */
_dns_replied_check_remove(query, from, from_len);
atomic_inc(&query->dns_request_sent);
}
}
@@ -1929,6 +1983,74 @@ errout:
return -1;
}
#include <net/if.h>
#include <sys/ioctl.h>
static int _dns_client_create_socket_udp_mdns(struct dns_server_info *server_info)
{
int fd = 0;
struct epoll_event event;
const int on = 1;
const int val = 1;
const int priority = SOCKET_PRIORITY;
const int ip_tos = SOCKET_IP_TOS;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
tlog(TLOG_ERROR, "create socket failed, %s", strerror(errno));
goto errout;
}
if (set_fd_nonblock(fd, 1) != 0) {
tlog(TLOG_ERROR, "set socket non block failed, %s", strerror(errno));
goto errout;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
safe_strncpy(ifr.ifr_name, server_info->flags.mdns.ifname, sizeof(ifr.ifr_name));
ioctl(fd, SIOCGIFINDEX, &ifr);
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(struct ifreq)) < 0) {
tlog(TLOG_ERROR, "bind socket to device %s failed, %s\n", ifr.ifr_name, strerror(errno));
goto errout;
}
server_info->fd = fd;
server_info->status = DNS_SERVER_STATUS_CONNECTIONLESS;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN;
event.data.ptr = server_info;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed.");
return -1;
}
setsockopt(server_info->fd, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
setsockopt(server_info->fd, SOL_IP, IP_TTL, &val, sizeof(val));
setsockopt(server_info->fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));
setsockopt(server_info->fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
setsockopt(server_info->fd, IPPROTO_IP, IP_MULTICAST_TTL, &val, sizeof(val));
if (server_info->ai_family == AF_INET6) {
/* for receiving ip ttl value */
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on));
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &val, sizeof(val));
}
return 0;
errout:
if (fd > 0) {
close(fd);
}
server_info->fd = -1;
server_info->status = DNS_SERVER_STATUS_DISCONNECTED;
return -1;
}
static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
{
int fd = 0;
@@ -2025,138 +2147,6 @@ errout:
return -1;
}
static int _DNS_client_create_socket_quic(struct dns_server_info *server_info, char *hostname)
{
#ifdef OSSL_QUIC1_VERSION
int fd = 0;
struct epoll_event event;
SSL *ssl = NULL;
struct proxy_conn *proxy = NULL;
int ret = -1;
if (server_info->ssl_ctx == NULL) {
tlog(TLOG_ERROR, "create ssl ctx failed, %s", server_info->ip);
goto errout;
}
if (server_info->proxy_name[0] != '\0') {
proxy = proxy_conn_new(server_info->proxy_name, server_info->ip, server_info->port, 1);
if (proxy == NULL) {
tlog(TLOG_ERROR, "create proxy failed, %s, proxy: %s", server_info->ip, server_info->proxy_name);
goto errout;
}
fd = proxy_conn_get_fd(proxy);
} else {
fd = socket(server_info->ai_family, SOCK_DGRAM, IPPROTO_UDP);
}
ssl = SSL_new(server_info->ssl_ctx);
if (ssl == NULL) {
tlog(TLOG_ERROR, "new ssl failed, %s", server_info->ip);
goto errout;
}
if (fd < 0) {
tlog(TLOG_ERROR, "create socket failed, %s", strerror(errno));
goto errout;
}
if (set_fd_nonblock(fd, 1) != 0) {
tlog(TLOG_ERROR, "set socket non block failed, %s", strerror(errno));
goto errout;
}
if (server_info->so_mark >= 0) {
unsigned int so_mark = server_info->so_mark;
if (setsockopt(fd, SOL_SOCKET, SO_MARK, &so_mark, sizeof(so_mark)) != 0) {
tlog(TLOG_DEBUG, "set socket mark failed, %s", strerror(errno));
}
}
if (proxy) {
ret = proxy_conn_connect(proxy);
} else {
ret = connect(fd, &server_info->addr, server_info->ai_addrlen);
}
if (ret != 0) {
if (errno != EINPROGRESS) {
tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
goto errout;
}
}
SSL_set_connect_state(ssl);
SSL_set_blocking_mode(ssl, 0);
if (SSL_set_fd(ssl, fd) == 0) {
tlog(TLOG_ERROR, "ssl set fd failed.");
goto errout;
}
/* reuse ssl session */
if (server_info->ssl_session) {
SSL_set_session(ssl, server_info->ssl_session);
}
SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
if (hostname[0] != 0) {
SSL_set_tlsext_host_name(ssl, hostname);
}
SSL_set1_host(ssl, hostname);
static const unsigned char alpn[] = {3, 'd', 'o', 'q'};
if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {
tlog(TLOG_INFO, "SSL_set_alpn_protos failed.");
goto errout;
}
server_info->fd = fd;
server_info->ssl = ssl;
server_info->ssl_write_len = -1;
server_info->status = DNS_SERVER_STATUS_CONNECTING;
server_info->proxy = proxy;
memset(&event, 0, sizeof(event));
event.events = EPOLLIN | EPOLLOUT;
event.data.ptr = server_info;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed.");
goto errout;
}
tlog(TLOG_DEBUG, "tls server %s connecting.\n", server_info->ip);
return 0;
errout:
if (server_info->fd > 0) {
server_info->fd = -1;
}
if (server_info->ssl) {
server_info->ssl = NULL;
}
server_info->status = DNS_SERVER_STATUS_INIT;
if (fd > 0 && proxy == NULL) {
close(fd);
}
if (ssl) {
SSL_free(ssl);
}
if (proxy) {
proxy_conn_free(proxy);
}
return -1;
#else
return -1;
#endif
}
static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, char *hostname)
{
int fd = 0;
@@ -2303,16 +2293,14 @@ static int _dns_client_create_socket(struct dns_server_info *server_info)
if (server_info->type == DNS_SERVER_UDP) {
return _dns_client_create_socket_udp(server_info);
} else if (server_info->type == DNS_SERVER_MDNS) {
return _dns_client_create_socket_udp_mdns(server_info);
} else if (server_info->type == DNS_SERVER_TCP) {
return _DNS_client_create_socket_tcp(server_info);
} else if (server_info->type == DNS_SERVER_TLS) {
struct client_dns_server_flag_tls *flag_tls = NULL;
flag_tls = &server_info->flags.tls;
return _DNS_client_create_socket_tls(server_info, flag_tls->hostname);
} else if (server_info->type == DNS_SERVER_QUIC) {
struct client_dns_server_flag_tls *flag_tls = NULL;
flag_tls = &server_info->flags.tls;
return _DNS_client_create_socket_quic(server_info, flag_tls->hostname);
} else if (server_info->type == DNS_SERVER_HTTPS) {
struct client_dns_server_flag_https *flag_https = NULL;
flag_https = &server_info->flags.https;
@@ -2623,7 +2611,8 @@ static int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *buf
}
#endif
tlog(TLOG_WARN, "SSL read fail error no: %s(%lx), reason: %d\n", ERR_reason_error_string(ssl_err), ssl_err, ssl_reason);
tlog(TLOG_WARN, "SSL read fail error no: %s(%lx), reason: %d\n", ERR_reason_error_string(ssl_err), ssl_err,
ssl_reason);
errno = EFAULT;
ret = -1;
break;
@@ -2675,8 +2664,7 @@ static int _dns_client_socket_send(struct dns_server_info *server_info)
return -1;
} else if (server_info->type == DNS_SERVER_TCP) {
return send(server_info->fd, server_info->send_buff.data, server_info->send_buff.len, MSG_NOSIGNAL);
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
server_info->type == DNS_SERVER_QUIC) {
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
int write_len = server_info->send_buff.len;
if (server_info->ssl_write_len > 0) {
write_len = server_info->ssl_write_len;
@@ -2692,6 +2680,8 @@ static int _dns_client_socket_send(struct dns_server_info *server_info)
}
}
return ret;
} else if (server_info->type == DNS_SERVER_MDNS) {
return -1;
} else {
return -1;
}
@@ -2704,8 +2694,7 @@ static int _dns_client_socket_recv(struct dns_server_info *server_info)
} else if (server_info->type == DNS_SERVER_TCP) {
return recv(server_info->fd, server_info->recv_buff.data + server_info->recv_buff.len,
DNS_TCP_BUFFER - server_info->recv_buff.len, 0);
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
server_info->type == DNS_SERVER_QUIC) {
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
int ret = _dns_client_socket_ssl_recv(server_info, server_info->recv_buff.data + server_info->recv_buff.len,
DNS_TCP_BUFFER - server_info->recv_buff.len);
if (ret == -SSL_ERROR_WANT_WRITE && errno == EAGAIN) {
@@ -2716,6 +2705,8 @@ static int _dns_client_socket_recv(struct dns_server_info *server_info)
}
return ret;
} else if (server_info->type == DNS_SERVER_MDNS) {
return -1;
} else {
return -1;
}
@@ -2751,6 +2742,7 @@ static int _dns_client_process_tcp_buff(struct dns_server_info *server_info)
tlog(TLOG_WARN, "http server query from %s:%d failed, server return http code : %d, %s",
server_info->ip, server_info->port, http_head_get_httpcode(http_head),
http_head_get_httpcode_msg(http_head));
server_info->prohibit = 1;
goto out;
}
@@ -3317,14 +3309,13 @@ static int _dns_client_process(struct dns_server_info *server_info, struct epoll
}
}
if (server_info->type == DNS_SERVER_UDP) {
if (server_info->type == DNS_SERVER_UDP || server_info->type == DNS_SERVER_MDNS) {
/* receive from udp */
return _dns_client_process_udp(server_info, event, now);
} else if (server_info->type == DNS_SERVER_TCP) {
/* receive from tcp */
return _dns_client_process_tcp(server_info, event, now);
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
server_info->type == DNS_SERVER_QUIC) {
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
/* receive from tls */
return _dns_client_process_tls(server_info, event, now);
} else {
@@ -3398,6 +3389,27 @@ errout:
return -1;
}
static int _dns_client_send_udp_mdns(struct dns_server_info *server_info, void *packet, int len)
{
int send_len = 0;
const struct sockaddr *addr = &server_info->addr;
socklen_t addrlen = server_info->ai_addrlen;
if (server_info->fd <= 0) {
return -1;
}
send_len = sendto(server_info->fd, packet, len, 0, addr, addrlen);
if (send_len != len) {
goto errout;
}
return 0;
errout:
return -1;
}
static int _dns_client_send_data_to_buffer(struct dns_server_info *server_info, void *packet, int len)
{
struct epoll_event event;
@@ -3560,11 +3572,6 @@ static int _dns_client_send_https(struct dns_server_info *server_info, void *pac
return 0;
}
static int _dns_client_send_quic(struct dns_server_info *server_info, void *packet, unsigned short len)
{
return _dns_client_send_tls(server_info, packet, len);
}
static int _dns_client_setup_server_packet(struct dns_server_info *server_info, struct dns_query_struct *query,
void *default_packet, int default_packet_len,
unsigned char *packet_data_buffer, void **packet_data, int *packet_data_len)
@@ -3601,6 +3608,7 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
head.aa = 0;
head.rd = 1;
head.ra = 0;
head.ad = query->edns0_do;
head.rcode = 0;
if (dns_packet_init(packet, DNS_PACKSIZE, &head) != 0) {
@@ -3620,8 +3628,11 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
}
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
if (query->edns0_do) {
dns_set_OPT_option(packet, DNS_OPT_FLAG_DO);
}
if (server_info->type != DNS_SERVER_UDP) {
if (server_info->type != DNS_SERVER_UDP && server_info->type != DNS_SERVER_MDNS) {
dns_add_OPT_TCP_KEEPALIVE(packet, 6000);
}
@@ -3668,6 +3679,7 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
void *packet_data = NULL;
int packet_data_len = 0;
unsigned char packet_data_buffer[DNS_IN_PACKSIZE];
int prohibit_time = 60;
query->send_tick = get_tick_count();
@@ -3675,6 +3687,10 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
atomic_inc(&query->dns_request_sent);
for (i = 0; i < 2; i++) {
total_server = 0;
if (i == 1) {
prohibit_time = 5;
}
pthread_mutex_lock(&client.server_list_lock);
list_for_each_entry_safe(group_member, tmp, &query->server_group->head, list)
{
@@ -3682,17 +3698,21 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
if (server_info->prohibit) {
if (server_info->is_already_prohibit == 0) {
server_info->is_already_prohibit = 1;
atomic_inc(&client.dns_server_prohibit_num);
_dns_server_inc_prohibit_server_num(server_info);
time(&server_info->last_send);
time(&server_info->last_recv);
tlog(TLOG_INFO, "server %s not alive, prohibit", server_info->ip);
_dns_client_shutdown_socket(server_info);
}
time_t now = 0;
time(&now);
if ((now - 60 < server_info->last_send) && (now - 5 > server_info->last_recv)) {
if ((now - prohibit_time < server_info->last_send)) {
continue;
}
server_info->prohibit = 0;
server_info->is_already_prohibit = 0;
atomic_dec(&client.dns_server_prohibit_num);
_dns_server_dec_prohibit_server_num(server_info);
if (now - 60 > server_info->last_send) {
_dns_client_close_socket(server_info);
}
@@ -3738,9 +3758,9 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
ret = _dns_client_send_https(server_info, packet_data, packet_data_len);
send_err = errno;
break;
case DNS_SERVER_QUIC:
/* quic query */
ret = _dns_client_send_quic(server_info, packet_data, packet_data_len);
case DNS_SERVER_MDNS:
/* mdns query */
ret = _dns_client_send_udp_mdns(server_info, packet_data, packet_data_len);
send_err = errno;
break;
default:
@@ -3765,8 +3785,6 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
time(&now);
if (now - 10 > server_info->last_recv || send_err != ENOMEM) {
server_info->prohibit = 1;
tlog(TLOG_INFO, "server %s not alive, prohibit", server_info->ip);
_dns_client_shutdown_socket(server_info);
}
atomic_dec(&query->dns_request_sent);
@@ -3827,6 +3845,7 @@ static int _dns_client_send_query(struct dns_query_struct *query)
head.aa = 0;
head.rd = 1;
head.ra = 0;
head.ad = query->edns0_do;
head.rcode = 0;
if (dns_packet_init(packet, DNS_PACKSIZE, &head) != 0) {
@@ -3841,6 +3860,9 @@ static int _dns_client_send_query(struct dns_query_struct *query)
}
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
if (query->edns0_do) {
dns_set_OPT_option(packet, DNS_OPT_FLAG_DO);
}
/* dns_add_OPT_TCP_KEEPALIVE(packet, 1200); */
if (_dns_client_dns_add_ecs(query, packet) != 0) {
tlog(TLOG_ERROR, "add ecs failed.");
@@ -3953,6 +3975,10 @@ static int _dns_client_query_parser_options(struct dns_query_struct *query, stru
_dns_client_query_setup_default_ecs(query);
}
if (options->enable_flag & DNS_QUEY_OPTION_EDNS0_DO) {
query->edns0_do = 1;
}
return 0;
}
@@ -4568,6 +4594,78 @@ static void _dns_client_do_wakeup_event(void)
unused = write(client.fd_wakeup, &val, sizeof(val));
}
static int _dns_client_add_mdns_server(void)
{
struct client_dns_server_flags server_flags;
int ret = 0;
struct ifaddrs *ifaddr = NULL;
struct ifaddrs *ifa = NULL;
if (dns_conf_mdns_lookup != 1) {
return 0;
}
memset(&server_flags, 0, sizeof(server_flags));
server_flags.server_flag |= SERVER_FLAG_EXCLUDE_DEFAULT | DOMAIN_FLAG_IPSET_IGN | DOMAIN_FLAG_NFTSET_INET_IGN;
if (dns_client_add_group(DNS_SERVER_GROUP_MDNS) != 0) {
tlog(TLOG_ERROR, "add default server group failed.");
goto errout;
}
if (getifaddrs(&ifaddr) == -1) {
goto errout;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
const unsigned char *addr = NULL;
int addr_len = 0;
if (ifa->ifa_addr == NULL) {
continue;
}
if (AF_INET != ifa->ifa_addr->sa_family) {
continue;
}
addr = (const unsigned char *)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
addr_len = sizeof(struct in_addr);
// Skip the local interface
if (strcmp(ifa->ifa_name, "lo") == 0 || strcmp(ifa->ifa_name, "localhost") == 0) {
continue;
}
if (is_private_addr(addr, addr_len) == 0) {
continue;
}
ret = _dns_client_server_add(DNS_MDNS_IP, ifa->ifa_name, DNS_MDNS_PORT, DNS_SERVER_MDNS, &server_flags);
if (ret != 0) {
tlog(TLOG_ERROR, "add mdns server failed.");
goto errout;
}
if (dns_client_add_to_group(DNS_SERVER_GROUP_MDNS, DNS_MDNS_IP, DNS_MDNS_PORT, DNS_SERVER_MDNS,
&server_flags) != 0) {
tlog(TLOG_ERROR, "add mdns server to group failed.");
goto errout;
}
}
freeifaddrs(ifaddr);
return 0;
errout:
if (ifaddr) {
freeifaddrs(ifaddr);
}
return -1;
}
int dns_client_init(void)
{
pthread_attr_t attr;
@@ -4608,6 +4706,11 @@ int dns_client_init(void)
goto errout;
}
if (_dns_client_add_mdns_server() != 0) {
tlog(TLOG_ERROR, "add mdns server failed.");
goto errout;
}
client.default_group = _dns_client_get_group(DNS_SERVER_GROUP_DEFAULT);
client.epoll_fd = epollfd;
atomic_set(&client.run, 1);

View File

@@ -27,13 +27,15 @@ extern "C" {
#define DNS_SERVER_SPKI_LEN 64
#define DNS_SERVER_GROUP_DEFAULT "default"
#define DNS_SERVER_GROUP_MDNS "mdns"
#define DNS_SERVER_GROUP_LOCAL "local"
typedef enum {
DNS_SERVER_UDP,
DNS_SERVER_TCP,
DNS_SERVER_TLS,
DNS_SERVER_HTTPS,
DNS_SERVER_QUIC,
DNS_SERVER_MDNS,
DNS_SERVER_TYPE_END,
} dns_server_type_t;
@@ -50,6 +52,7 @@ typedef enum dns_result_type {
#define DNS_QUEY_OPTION_ECS_DNS (1 << 0)
#define DNS_QUEY_OPTION_ECS_IP (1 << 1)
#define DNS_QUEY_OPTION_EDNS0_DO (1 << 2)
int dns_client_init(void);
@@ -90,6 +93,10 @@ struct client_dns_server_flag_udp {
int ttl;
};
struct client_dns_server_flag_mdns {
char ifname[DNS_MAX_CNAME_LEN];
};
struct client_dns_server_flag_tls {
char spki[DNS_SERVER_SPKI_LEN];
int spi_len;
@@ -129,6 +136,7 @@ struct client_dns_server_flags {
struct client_dns_server_flag_udp udp;
struct client_dns_server_flag_tls tls;
struct client_dns_server_flag_https https;
struct client_dns_server_flag_mdns mdns;
};
};

View File

@@ -26,7 +26,6 @@
#include <getopt.h>
#include <glob.h>
#include <libgen.h>
#include <openssl/ssl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -163,6 +162,7 @@ struct dns_ipset_names dns_conf_ipset_no_speed;
int dns_conf_nftset_timeout_enable;
struct dns_nftset_names dns_conf_nftset_no_speed;
int dns_conf_nftset_debug_enable;
int dns_conf_mdns_lookup;
char dns_conf_user[DNS_CONF_USERNAME_LEN];
@@ -601,9 +601,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
if (strcasecmp(scheme, "https") == 0) {
type = DNS_SERVER_HTTPS;
default_port = DEFAULT_DNS_HTTPS_PORT;
} else if (strcasecmp(scheme, "quic")) {
type = DNS_SERVER_QUIC;
default_port = DEFAULT_DNS_QUIC_PORT;
} else if (strcasecmp(scheme, "tls") == 0) {
type = DNS_SERVER_TLS;
default_port = DEFAULT_DNS_TLS_PORT;
@@ -619,13 +616,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
}
}
#ifndef OSSL_QUIC1_VERSION
if (type == DNS_SERVER_QUIC) {
tlog(TLOG_ERROR, "quic not support.");
return -1;
}
#endif
/* if port is not defined, set port to default 53 */
if (port == PORT_NOT_DEFINED) {
port = default_port;
@@ -2466,14 +2456,6 @@ static int _config_server_https(void *data, int argc, char *argv[])
return ret;
}
static int _config_server_quic(void *data, int argc, char *argv[])
{
int ret = 0;
ret = _config_server(argc, argv, DNS_SERVER_QUIC, DEFAULT_DNS_QUIC_PORT);
return ret;
}
static int _conf_domain_rule_nameserver(char *domain, const char *group_name)
{
struct dns_nameserver_rule *nameserver_rule = NULL;
@@ -3986,16 +3968,15 @@ static struct dns_hosts *_dns_conf_get_hosts(const char *hostname, int dns_type)
{
uint32_t key = 0;
struct dns_hosts *host = NULL;
char hostname_lower[DNS_MAX_CNAME_LEN];
key = hash_string(to_lower_case(hostname_lower, hostname, DNS_MAX_CNAME_LEN));
key = hash_string_case(hostname);
key = jhash(&dns_type, sizeof(dns_type), key);
hash_for_each_possible(dns_hosts_table.hosts, host, node, key)
{
if (host->dns_type != dns_type) {
continue;
}
if (strncmp(host->domain, hostname_lower, DNS_MAX_CNAME_LEN) != 0) {
if (strncasecmp(host->domain, hostname, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
@@ -4007,7 +3988,7 @@ static struct dns_hosts *_dns_conf_get_hosts(const char *hostname, int dns_type)
goto errout;
}
safe_strncpy(host->domain, hostname_lower, DNS_MAX_CNAME_LEN);
safe_strncpy(host->domain, hostname, DNS_MAX_CNAME_LEN);
host->dns_type = dns_type;
host->is_soa = 1;
hash_add(dns_hosts_table.hosts, &host->node, key);
@@ -4294,6 +4275,15 @@ static void _config_setup_smartdns_domain(void)
_config_domain_rule_flag_set("smartdns", DOMAIN_FLAG_SMARTDNS_DOMAIN, 0);
}
static int _dns_conf_setup_mdns(void)
{
if (dns_conf_mdns_lookup != 1) {
return 0;
}
return _conf_domain_rule_nameserver(DNS_SERVER_GROUP_LOCAL, DNS_SERVER_GROUP_MDNS);
}
static struct config_item _config_item[] = {
CONF_STRING("server-name", (char *)dns_conf_server_name, DNS_MAX_SERVER_NAME_LEN),
CONF_YESNO("resolv-hostname", &dns_conf_resolv_hostname),
@@ -4308,7 +4298,7 @@ static struct config_item _config_item[] = {
CONF_CUSTOM("server-tcp", _config_server_tcp, NULL),
CONF_CUSTOM("server-tls", _config_server_tls, NULL),
CONF_CUSTOM("server-https", _config_server_https, NULL),
CONF_CUSTOM("server-quic", _config_server_quic, NULL),
CONF_YESNO("mdns-lookup", &dns_conf_mdns_lookup),
CONF_CUSTOM("nameserver", _config_nameserver, NULL),
CONF_YESNO("expand-ptr-from-address", &dns_conf_expand_ptr_from_address),
CONF_CUSTOM("address", _config_address, NULL),
@@ -4748,6 +4738,8 @@ static int _dns_conf_load_post(void)
_dns_conf_auto_set_cache_size();
_dns_conf_setup_mdns();
if (dns_conf_cachesize == 0 && dns_conf_response_mode == DNS_RESPONSE_MODE_FASTEST_RESPONSE) {
dns_conf_response_mode = DNS_RESPONSE_MODE_FASTEST_IP;
tlog(TLOG_WARN, "force set response to %s as cache size is 0",

View File

@@ -56,7 +56,6 @@ extern "C" {
#define DEFAULT_DNS_PORT 53
#define DEFAULT_DNS_TLS_PORT 853
#define DEFAULT_DNS_HTTPS_PORT 443
#define DEFAULT_DNS_QUIC_PORT 853
#define DNS_MAX_CONF_CNAME_LEN 256
#define MAX_QTYPE_NUM 65535
#define DNS_MAX_REPLY_IP_NUM 8
@@ -579,6 +578,7 @@ extern int dns_conf_ipset_timeout_enable;
extern int dns_conf_nftset_timeout_enable;
extern int dns_conf_nftset_debug_enable;
extern int dns_conf_local_ttl;
extern int dns_conf_mdns_lookup;
extern int dns_conf_force_no_cname;

View File

@@ -35,6 +35,7 @@
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <math.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -75,6 +76,7 @@
#define PREFETCH_FLAGS_NO_DUALSTACK (1 << 0)
#define PREFETCH_FLAGS_EXPIRED (1 << 1)
#define PREFETCH_FLAGS_NOPREFETCH (1 << 2)
#define RECV_ERROR_AGAIN 1
#define RECV_ERROR_OK 0
@@ -255,6 +257,7 @@ struct dns_request {
struct sockaddr_storage localaddr;
int has_ecs;
struct dns_opt_ecs ecs;
int edns0_do;
dns_result_callback result_callback;
void *user_ptr;
@@ -277,6 +280,8 @@ struct dns_request {
int has_soa;
int force_soa;
int is_mdns_lookup;
struct dns_srv_records *srv_records;
atomic_t notified;
@@ -362,6 +367,7 @@ static int _dns_server_do_query(struct dns_request *request, int skip_notify_eve
static int _dns_request_post(struct dns_server_post_context *context);
static int _dns_server_reply_all_pending_list(struct dns_request *request, struct dns_server_post_context *context);
static void *_dns_server_get_dns_rule(struct dns_request *request, enum domain_rule rule);
static int _dns_server_get_local_ttl(struct dns_request *request);
static const char *_dns_server_get_request_groupname(struct dns_request *request);
static int _dns_server_tcp_socket_send(struct dns_server_conn_tcp_client *tcp_client, void *data, int data_len);
static int _dns_server_update_request_connection_timeout(struct dns_server_conn_head *conn, int timeout);
@@ -421,21 +427,6 @@ static void *_dns_server_get_bind_ipset_nftset_rule(struct dns_request *request,
return NULL;
}
static int _dns_server_get_reply_ttl(struct dns_request *request, int ttl)
{
int reply_ttl = ttl;
if ((request->passthrough == 0 || request->passthrough == 2) && dns_conf_cachesize > 0 &&
request->check_order_list->orders[0].type != DOMAIN_CHECK_NONE) {
reply_ttl = dns_conf_serve_expired_reply_ttl;
if (reply_ttl < 2) {
reply_ttl = 2;
}
}
return reply_ttl;
}
static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
{
int rr_ttl = dns_conf_rr_ttl;
@@ -482,6 +473,26 @@ static int _dns_server_get_conf_ttl(struct dns_request *request, int ttl)
return ttl;
}
static int _dns_server_get_reply_ttl(struct dns_request *request, int ttl)
{
int reply_ttl = ttl;
if ((request->passthrough == 0 || request->passthrough == 2) && dns_conf_cachesize > 0 &&
request->check_order_list->orders[0].type != DOMAIN_CHECK_NONE) {
reply_ttl = dns_conf_serve_expired_reply_ttl;
if (reply_ttl < 2) {
reply_ttl = 2;
}
}
int rr_ttl = _dns_server_get_conf_ttl(request, ttl);
if (reply_ttl > rr_ttl) {
reply_ttl = rr_ttl;
}
return reply_ttl;
}
static int _dns_server_epoll_ctl(struct dns_server_conn_head *head, int op, uint32_t events)
{
struct epoll_event event;
@@ -624,6 +635,16 @@ static int _dns_server_is_return_soa_qtype(struct dns_request *request, dns_type
if (_dns_server_has_bind_flag(request, BIND_FLAG_FORCE_AAAA_SOA) == 0 || dns_conf_force_AAAA_SOA == 1) {
return 1;
}
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV4] != NULL &&
request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6] == NULL) {
return 1;
}
} else if (qtype == DNS_T_A) {
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6] != NULL &&
request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV4] == NULL) {
return 1;
}
}
return 0;
@@ -743,8 +764,8 @@ static void _dns_server_audit_log(struct dns_server_post_context *context)
continue;
}
if (strncmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncasecmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
@@ -764,8 +785,8 @@ static void _dns_server_audit_log(struct dns_server_post_context *context)
continue;
}
if (strncmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncasecmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
@@ -1385,12 +1406,25 @@ static int _dns_cache_is_specify_packet(int qtype)
static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns_cache_key *cache_key, int ttl)
{
int timeout = 0;
int prefetch_time = 0;
if (request->rcode != DNS_RC_NOERROR) {
return ttl + 1;
}
if (dns_conf_prefetch && _dns_cache_is_specify_packet(request->qtype) != 0) {
prefetch_time = 1;
}
if ((request->prefetch_flags & PREFETCH_FLAGS_NOPREFETCH)) {
prefetch_time = 0;
}
if (request->edns0_do == 1) {
prefetch_time = 0;
}
if (prefetch_time == 1) {
if (dns_conf_serve_expired) {
timeout = dns_conf_serve_expired_prefetch_time;
if (timeout == 0) {
@@ -1420,6 +1454,8 @@ static int _dns_server_get_cache_timeout(struct dns_request *request, struct dns
if (dns_conf_serve_expired) {
timeout += dns_conf_serve_expired_ttl;
}
timeout += 3;
}
if (timeout <= 0) {
@@ -1526,7 +1562,7 @@ static int _dns_cache_cname_packet(struct dns_server_post_context *context)
continue;
}
if (strncmp(request->cname, name, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(request->cname, name, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
@@ -1542,7 +1578,7 @@ static int _dns_cache_cname_packet(struct dns_server_post_context *context)
continue;
}
if (strncmp(request->cname, name, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(request->cname, name, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
@@ -2737,6 +2773,9 @@ static void _dns_server_ping_result(struct ping_host_struct *ping_host, const ch
}
int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
if (rtt == 0) {
rtt = 1;
}
if (result == PING_RESULT_RESPONSE) {
tlog(TLOG_DEBUG, "from %s: seq=%d time=%d, lasttime=%d id=%d", host, seqno, rtt, last_rtt, request->id);
@@ -3081,9 +3120,7 @@ static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request
if (request->qtype != DNS_T_A) {
/* ignore non-matched query type */
if (request->dualstack_selection == 0) {
return 0;
}
return 0;
}
/* get A result */
@@ -3094,7 +3131,7 @@ static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
/* if domain is not match */
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
if (strncasecmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncasecmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
return -1;
}
@@ -3181,7 +3218,7 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
addr[11], addr[12], addr[13], addr[14], addr[15]);
/* if domain is not match */
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
if (strncasecmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncasecmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
return -1;
}
@@ -3255,6 +3292,7 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
struct dns_rrs *rrs = NULL;
int ret = 0;
int is_skip = 0;
int has_result = 0;
if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
if (request->rcode == DNS_RC_SERVFAIL) {
@@ -3269,6 +3307,7 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
for (j = 1; j < DNS_RRS_OPT; j++) {
rrs = dns_get_rrs_start(packet, j, &rr_count);
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
has_result = 1;
switch (rrs->type) {
case DNS_T_A: {
ret = _dns_server_process_answer_A(rrs, request, domain, cname, result_flag);
@@ -3303,8 +3342,8 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
char domain_name[DNS_MAX_CNAME_LEN] = {0};
char domain_cname[DNS_MAX_CNAME_LEN] = {0};
dns_get_CNAME(rrs, domain_name, DNS_MAX_CNAME_LEN, &ttl, domain_cname, DNS_MAX_CNAME_LEN);
if (strncmp(domain_name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncmp(domain_name, cname, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(domain_name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncasecmp(domain_name, cname, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
safe_strncpy(cname, domain_cname, DNS_MAX_CNAME_LEN);
@@ -3329,7 +3368,7 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
int soa_num = atomic_inc_return(&request->soa_num);
if ((soa_num >= (dns_server_alive_num() / 3) + 1 || soa_num > 4) &&
if ((soa_num >= ((int)ceil((float)dns_server_alive_num() / 3) + 1) || soa_num > 4) &&
atomic_read(&request->ip_map_num) <= 0) {
request->ip_ttl = ttl;
_dns_server_request_complete(request);
@@ -3347,6 +3386,12 @@ static int _dns_server_process_answer(struct dns_request *request, const char *d
request->rcode = packet->head.rcode;
}
if (has_result == 0 && request->rcode == DNS_RC_NOERROR) {
tlog(TLOG_DEBUG, "no result, %s qtype: %d, rcode: %d, id: %d, retry", domain, request->qtype,
packet->head.rcode, packet->head.id);
return -1;
}
return 0;
}
@@ -3390,7 +3435,8 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl_tmp, addr);
/* if domain is not match */
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
if (strncasecmp(name, domain, DNS_MAX_CNAME_LEN) != 0 &&
strncasecmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
_dns_server_request_release(request);
continue;
}
@@ -3429,7 +3475,8 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, const
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl_tmp, addr);
/* if domain is not match */
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
if (strncasecmp(name, domain, DNS_MAX_CNAME_LEN) != 0 &&
strncasecmp(cname, name, DNS_MAX_CNAME_LEN) != 0) {
_dns_server_request_release(request);
continue;
}
@@ -3511,8 +3558,8 @@ static int _dns_server_get_answer(struct dns_server_post_context *context)
/* get A result */
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
if (strncmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncasecmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
@@ -3543,8 +3590,8 @@ static int _dns_server_get_answer(struct dns_server_post_context *context)
}
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
if (strncmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncasecmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
@@ -3578,8 +3625,8 @@ static int _dns_server_get_answer(struct dns_server_post_context *context)
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
tlog(TLOG_DEBUG, "name: %s, ttl: %d, cname: %s\n", name, ttl, cname);
if (strncmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
if (strncasecmp(name, request->domain, DNS_MAX_CNAME_LEN - 1) != 0 &&
strncasecmp(name, request->cname, DNS_MAX_CNAME_LEN - 1) != 0) {
continue;
}
@@ -3657,6 +3704,13 @@ static void _dns_server_query_end(struct dns_request *request)
int ip_num = 0;
int request_wait = 0;
/* if mdns request timeout */
if (request->is_mdns_lookup == 1 && request->rcode == DNS_RC_SERVFAIL) {
request->rcode = DNS_RC_NOERROR;
request->force_soa = 1;
request->ip_ttl = _dns_server_get_local_ttl(request);
}
pthread_mutex_lock(&request->ip_map_lock);
ip_num = atomic_read(&request->ip_map_num);
request_wait = request->request_wait;
@@ -3755,9 +3809,9 @@ static int dns_server_resolve_callback(const char *domain, dns_result_type rtype
}
if (rtype == DNS_QUERY_RESULT) {
tlog(TLOG_DEBUG, "query result from server %s:%d, type: %d, rcode: %d, id: %d",
tlog(TLOG_DEBUG, "query result from server %s:%d, type: %d, domain: %s qtype: %d rcode: %d, id: %d",
dns_client_get_server_ip(server_info), dns_client_get_server_port(server_info),
dns_client_get_server_type(server_info), packet->head.rcode, request->id);
dns_client_get_server_type(server_info), domain, request->qtype, packet->head.rcode, request->id);
if (request->passthrough == 1 && atomic_read(&request->notified) == 0) {
struct dns_server_post_context context;
@@ -3804,9 +3858,9 @@ static int dns_server_resolve_callback(const char *domain, dns_result_type rtype
}
}
_dns_server_process_answer(request, domain, packet, result_flag);
ret = _dns_server_process_answer(request, domain, packet, result_flag);
_dns_server_passthrough_may_complete(request);
return 0;
return ret;
} else if (rtype == DNS_QUERY_ERR) {
tlog(TLOG_ERROR, "request failed, %s", domain);
return -1;
@@ -4059,7 +4113,7 @@ static int _dns_server_process_local_ptr(struct dns_request *request)
}
/* Determine if the smartdns service is in effect. */
if (found == 0 && strncmp(request->domain, "smartdns", sizeof("smartdns")) == 0) {
if (found == 0 && strncasecmp(request->domain, "smartdns", sizeof("smartdns")) == 0) {
found = 1;
}
@@ -4138,6 +4192,15 @@ static int _dns_server_get_local_ttl(struct dns_request *request)
return DNS_SERVER_ADDR_TTL;
}
static void _dns_server_set_request_mdns(struct dns_request *request)
{
if (dns_conf_mdns_lookup != 1) {
return;
}
request->is_mdns_lookup = 1;
}
static int _dns_server_process_private_ptr(struct dns_request *request)
{
int a, b, c, d;
@@ -4147,9 +4210,12 @@ static int _dns_server_process_private_ptr(struct dns_request *request)
}
if (d == 10 || (d == 172 && c >= 16 && c <= 31) || (d == 192 && c == 168)) {
request->has_soa = 1;
_dns_server_setup_soa(request);
return 0;
if (dns_conf_mdns_lookup == 0) {
request->has_soa = 1;
_dns_server_setup_soa(request);
return 0;
}
_dns_server_set_request_mdns(request);
}
return -1;
@@ -4212,7 +4278,7 @@ static int _dns_server_process_srv(struct dns_request *request)
static int _dns_server_process_svcb(struct dns_request *request)
{
if (strncmp("_dns.resolver.arpa", request->domain, DNS_MAX_CNAME_LEN) == 0) {
if (strncasecmp("_dns.resolver.arpa", request->domain, DNS_MAX_CNAME_LEN) == 0) {
return _dns_server_process_DDR(request);
}
@@ -4440,7 +4506,12 @@ static int _dns_server_pre_process_rule_flags(struct dns_request *request)
}
if (_dns_server_is_return_soa(request)) {
/* return SOA for A request */
/* if AAAA exists, return SOA with NOERROR*/
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV6] != NULL) {
goto soa;
}
/* if AAAA not exists, return SOA with NXDOMAIN */
if (_dns_server_is_return_soa_qtype(request, DNS_T_AAAA)) {
rcode = DNS_RC_NXDOMAIN;
}
@@ -4458,7 +4529,11 @@ static int _dns_server_pre_process_rule_flags(struct dns_request *request)
}
if (_dns_server_is_return_soa(request)) {
/* return SOA for A request */
/* if A exists, return SOA with NOERROR*/
if (request->domain_rule.rules[DOMAIN_RULE_ADDRESS_IPV4] != NULL) {
goto soa;
}
/* if A not exists, return SOA with NXDOMAIN */
if (_dns_server_is_return_soa_qtype(request, DNS_T_A)) {
rcode = DNS_RC_NXDOMAIN;
}
@@ -4792,7 +4867,7 @@ static int _dns_server_process_cname(struct dns_request *request)
struct dns_cname_rule *child_cname = _dns_server_get_dns_rule(child_request, DOMAIN_RULE_CNAME);
/* sub domain rule*/
if (child_cname != NULL && strncmp(child_request->domain, child_cname->cname, DNS_MAX_CNAME_LEN) == 0) {
if (child_cname != NULL && strncasecmp(child_request->domain, child_cname->cname, DNS_MAX_CNAME_LEN) == 0) {
child_request->domain_rule.rules[DOMAIN_RULE_CNAME] = NULL;
child_request->has_cname_loop = 1;
}
@@ -5046,6 +5121,13 @@ static int _dns_server_process_cache_packet(struct dns_request *request, struct
goto out;
}
/* Check if records in cache contain DNSSEC, if not exist, skip cache */
if (request->passthrough == 1) {
if ((dns_get_OPT_option(context.packet) & DNS_OPT_FLAG_DO) == 0 && request->edns0_do == 1) {
goto out;
}
}
request->rcode = context.packet->head.rcode;
context.do_cache = 0;
context.do_ipset = do_ipset;
@@ -5153,6 +5235,7 @@ reply_cache:
out_update_cache:
if (dns_cache_get_ttl(dns_cache) == 0) {
struct dns_server_query_option dns_query_options;
int prefetch_flags = 0;
dns_query_options.server_flags = request->server_flags;
dns_query_options.dns_group_name = request->dns_group_name;
if (request->conn == NULL) {
@@ -5166,7 +5249,12 @@ out_update_cache:
memcpy(&dns_query_options.ecs_dns, &request->ecs, sizeof(dns_query_options.ecs_dns));
}
_dns_server_prefetch_request(request->domain, request->qtype, &dns_query_options, 0);
if (request->edns0_do) {
dns_query_options.ecs_enable_flag |= DNS_QUEY_OPTION_EDNS0_DO;
prefetch_flags |= PREFETCH_FLAGS_NOPREFETCH;
}
_dns_server_prefetch_request(request->domain, request->qtype, &dns_query_options, prefetch_flags);
} else {
dns_cache_update(dns_cache);
}
@@ -5387,7 +5475,8 @@ static void _dns_server_check_set_passthrough(struct dns_request *request)
request->dualstack_selection = 0;
}
if (request->passthrough == 1 && (request->qtype == DNS_T_A || request->qtype == DNS_T_AAAA)) {
if (request->passthrough == 1 && (request->qtype == DNS_T_A || request->qtype == DNS_T_AAAA) &&
request->edns0_do == 0) {
request->passthrough = 2;
}
}
@@ -5398,13 +5487,12 @@ static int _dns_server_process_host(struct dns_request *request)
struct dns_hosts *host = NULL;
struct dns_hosts *host_tmp = NULL;
int dns_type = request->qtype;
char hostname_lower[DNS_MAX_CNAME_LEN];
if (dns_hosts_record_num <= 0) {
return -1;
}
key = hash_string(to_lower_case(hostname_lower, request->domain, DNS_MAX_CNAME_LEN));
key = hash_string_case(request->domain);
key = jhash(&dns_type, sizeof(dns_type), key);
hash_for_each_possible(dns_hosts_table.hosts, host_tmp, node, key)
{
@@ -5412,7 +5500,7 @@ static int _dns_server_process_host(struct dns_request *request)
continue;
}
if (strncmp(host_tmp->domain, hostname_lower, DNS_MAX_CNAME_LEN) != 0) {
if (strncasecmp(host_tmp->domain, request->domain, DNS_MAX_CNAME_LEN) != 0) {
continue;
}
@@ -5465,6 +5553,39 @@ static int _dns_server_setup_query_option(struct dns_request *request, struct dn
options->enable_flag |= DNS_QUEY_OPTION_ECS_DNS;
}
if (request->edns0_do) {
options->enable_flag |= DNS_QUEY_OPTION_EDNS0_DO;
}
return 0;
}
static int _dns_server_mdns_query_setup(struct dns_request *request, const char *group_name, char **request_domain,
char *domain_buffer, int domain_buffer_len)
{
if (dns_conf_mdns_lookup != 1) {
return 0;
}
switch (request->qtype) {
case DNS_T_A:
case DNS_T_AAAA:
case DNS_T_SRV:
if (request->domain[0] != '\0' && strstr(request->domain, ".") == NULL) {
snprintf(domain_buffer, domain_buffer_len, "%s.%s", request->domain, DNS_SERVER_GROUP_LOCAL);
*request_domain = domain_buffer;
_dns_server_set_request_mdns(request);
}
if (group_name != NULL && strncmp(group_name, DNS_SERVER_GROUP_MDNS, DNS_GROUP_NAME_LEN) == 0) {
_dns_server_set_request_mdns(request);
}
break;
default:
break;
}
return 0;
}
@@ -5530,6 +5651,8 @@ static int _dns_server_do_query(struct dns_request *request, int skip_notify_eve
const char *group_name = NULL;
const char *dns_group = NULL;
struct dns_query_options options;
char *request_domain = request->domain;
char domain_buffer[DNS_MAX_CNAME_LEN * 2];
if (request->conn) {
dns_group = request->conn->dns_group;
@@ -5623,10 +5746,19 @@ static int _dns_server_do_query(struct dns_request *request, int skip_notify_eve
list_add_tail(&request->list, &server.request_list);
pthread_mutex_unlock(&server.request_list_lock);
if (_dns_server_mdns_query_setup(request, group_name, &request_domain, domain_buffer, sizeof(domain_buffer)) != 0) {
goto errout;
}
/* if request MDNS */
if (request->is_mdns_lookup) {
group_name = DNS_SERVER_GROUP_MDNS;
}
// Get reference for DNS query
request->request_wait++;
_dns_server_request_get(request);
if (dns_client_query(request->domain, request->qtype, dns_server_resolve_callback, request, group_name, &options) !=
if (dns_client_query(request_domain, request->qtype, dns_server_resolve_callback, request, group_name, &options) !=
0) {
request->request_wait--;
_dns_server_request_release(request);
@@ -5698,6 +5830,10 @@ static int _dns_server_parser_request(struct dns_request *request, struct dns_pa
goto errout;
}
if ((dns_get_OPT_option(packet) & DNS_OPT_FLAG_DO) && packet->head.ad == 1) {
request->edns0_do = 1;
}
/* get request opts */
rr_count = 0;
rrs = dns_get_rrs_start(packet, DNS_RRS_OPT, &rr_count);
@@ -5816,6 +5952,10 @@ static int _dns_server_setup_server_query_options(struct dns_request *request,
memcpy(&request->ecs, &server_query_option->ecs_dns, sizeof(request->ecs));
}
if (server_query_option->ecs_enable_flag & DNS_QUEY_OPTION_EDNS0_DO) {
request->edns0_do = 1;
}
return 0;
}
@@ -6388,7 +6528,7 @@ static int _dns_server_tcp_process_one_request(struct dns_server_conn_tcp_client
const char *content_type = http_head_get_fields_value(http_head, "Content-Type");
if (content_type == NULL ||
strncmp(content_type, "application/dns-message", sizeof("application/dns-message")) != 0) {
strncasecmp(content_type, "application/dns-message", sizeof("application/dns-message")) != 0) {
tlog(TLOG_DEBUG, "content type not supported, %s", content_type);
goto errout;
}
@@ -7164,8 +7304,15 @@ static struct addrinfo *_dns_server_getaddr(const char *host, const char *port,
hints.ai_socktype = type;
hints.ai_protocol = protocol;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo(host, port, &hints, &result) != 0) {
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
const int s = getaddrinfo(host, port, &hints, &result);
if (s != 0) {
const char *error_str;
if (s == EAI_SYSTEM) {
error_str = strerror(errno);
} else {
error_str = gai_strerror(s);
}
tlog(TLOG_ERROR, "get addr info failed. %s.\n", error_str);
goto errout;
}

View File

@@ -134,6 +134,24 @@ struct http_head_fields *http_head_next_fields(struct http_head_fields *fields)
return next;
}
const char *http_head_fields_get_name(struct http_head_fields *fields)
{
if (fields == NULL) {
return NULL;
}
return fields->name;
}
const char *http_head_fields_get_value(struct http_head_fields *fields)
{
if (fields == NULL) {
return NULL;
}
return fields->value;
}
int http_head_lookup_fields(struct http_head_fields *fields, const char **name, const char **value)
{
if (fields == NULL) {

View File

@@ -67,6 +67,10 @@ struct http_head_fields *http_head_next_fields(struct http_head_fields *fields);
const char *http_head_get_fields_value(struct http_head *http_head, const char *name);
const char *http_head_fields_get_name(struct http_head_fields *fields);
const char *http_head_fields_get_value(struct http_head_fields *fields);
int http_head_lookup_fields(struct http_head_fields *fields, const char **name, const char **value);
/*

View File

@@ -268,7 +268,6 @@ static int _smartdns_prepare_server_flags(struct client_dns_server_flags *flags,
safe_strncpy(flag_http->tls_host_verify, server->tls_host_verify, sizeof(flag_http->tls_host_verify));
flag_http->skip_check_cert = server->skip_check_cert;
} break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
flag_tls->spi_len = dns_client_spki_decode(server->spki, (unsigned char *)flag_tls->spki);

View File

@@ -1168,7 +1168,7 @@ static int _tlog_write_screen(struct tlog_log *log, struct tlog_loginfo *info, c
const char *color = NULL;
switch (info->level) {
case TLOG_DEBUG:
color = "\033[0;90m";
color = "\033[0;94m";
break;
case TLOG_NOTICE:
color = "\033[0;97m";

View File

@@ -218,6 +218,33 @@ int generate_addr_map(const unsigned char *addr_from, const unsigned char *addr_
return 0;
}
int is_private_addr(const unsigned char *addr, int addr_len)
{
if (addr_len == IPV4_ADDR_LEN) {
if (addr[0] == 10) {
return 1;
}
if (addr[0] == 172 && addr[1] >= 16 && addr[1] <= 31) {
return 1;
}
if (addr[0] == 192 && addr[1] == 168) {
return 1;
}
} else if (addr_len == IPV6_ADDR_LEN) {
if (addr[0] == 0xFD) {
return 1;
}
if (addr[0] == 0xFE && addr[1] == 0x80) {
return 1;
}
}
return 0;
}
int getaddr_by_host(const char *host, struct sockaddr *addr, socklen_t *addr_len)
{
struct addrinfo hints;

View File

@@ -64,6 +64,8 @@ int generate_random_addr(unsigned char *addr, int addr_len, int mask);
int generate_addr_map(const unsigned char *addr_from, const unsigned char *addr_to, unsigned char *addr_out,
int addr_len, int mask);
int is_private_addr(const unsigned char *addr, int addr_len);
int getaddr_by_host(const char *host, struct sockaddr *addr, socklen_t *addr_len);
int getsocket_inet(int fd, struct sockaddr *addr, socklen_t *addr_len);

View File

@@ -23,9 +23,9 @@ CXXFLAGS += -g
CXXFLAGS += -DTEST
CXXFLAGS += -I./ -I../src -I../src/include
SMARTDNS_OBJS = lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o lib/nftset.o lib/timer_wheel.o lib/idna.o
SMARTDNS_OBJS += smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o http_parse.o proxy.o timer.o
OBJS = $(addprefix ../src/, $(SMARTDNS_OBJS))
OBJS_LIB=$(patsubst %.c,%.o,$(wildcard ../src/lib/*.c))
OBJS_MAIN=$(patsubst %.c,%.o,$(wildcard ../src/*.c))
OBJS = $(OBJS_LIB) $(OBJS_MAIN)
TEST_SOURCES := $(wildcard *.cc) $(wildcard */*.cc) $(wildcard */*/*.cc)
TEST_OBJECTS := $(patsubst %.cc, %.o, $(TEST_SOURCES))

View File

@@ -49,14 +49,11 @@ TEST_F(Address, soa)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /a.com/#4
address /b.com/#6
address /c.com/#
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -135,13 +132,10 @@ TEST_F(Address, ip)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /a.com/10.10.10.10
address /a.com/64:ff9b::1010:1010
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -180,13 +174,10 @@ TEST_F(Address, multiaddress)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /a.com/10.10.10.10,11.11.11.11,22.22.22.22
address /a.com/64:ff9b::1010:1010,64:ff9b::1111:1111,64:ff9b::2222:2222
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -271,13 +262,10 @@ TEST_F(Address, soa_sub_ip)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /a.com/192.168.1.1
address /com/#
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -291,10 +279,204 @@ cache-persist no)""");
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NXDOMAIN");
EXPECT_EQ(client.GetStatus(), "NOERROR");
ASSERT_TRUE(client.Query("b.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NXDOMAIN");
}
}
TEST_F(Address, set_ipv4_query_ipv6)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype == DNS_T_A) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 700);
return smartdns::SERVER_REQUEST_OK;
} else if (request->qtype == DNS_T_AAAA) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "64:ff9b::102:304", 700);
return smartdns::SERVER_REQUEST_OK;
}
return smartdns::SERVER_REQUEST_SOA;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
speed-check-mode none
address /a.com/192.168.1.1
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "A");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "192.168.1.1");
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NOERROR");
}
TEST_F(Address, set_ipv6_query_ipv4)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype == DNS_T_A) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 700);
return smartdns::SERVER_REQUEST_OK;
} else if (request->qtype == DNS_T_AAAA) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "64:ff9b::102:304", 700);
return smartdns::SERVER_REQUEST_OK;
}
return smartdns::SERVER_REQUEST_SOA;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
speed-check-mode none
address /a.com/64:ff9b::1010:1010
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NOERROR");
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::1010:1010");
}
TEST_F(Address, set_ipv4_allow_ipv6)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype == DNS_T_A) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 700);
return smartdns::SERVER_REQUEST_OK;
} else if (request->qtype == DNS_T_AAAA) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "64:ff9b::102:304", 700);
return smartdns::SERVER_REQUEST_OK;
}
return smartdns::SERVER_REQUEST_SOA;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
speed-check-mode none
address /a.com/192.168.1.1
address /b.a.com/-6
address /com/#
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "A");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "192.168.1.1");
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NOERROR");
ASSERT_TRUE(client.Query("c.a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NOERROR");
ASSERT_TRUE(client.Query("b.a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 700);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::102:304");
ASSERT_TRUE(client.Query("b.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NXDOMAIN");
}
TEST_F(Address, set_both_ipv4_ipv6)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype == DNS_T_A) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 700);
return smartdns::SERVER_REQUEST_OK;
} else if (request->qtype == DNS_T_AAAA) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "64:ff9b::102:304", 700);
return smartdns::SERVER_REQUEST_OK;
}
return smartdns::SERVER_REQUEST_SOA;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
speed-check-mode none
address /a.com/192.168.1.1
address /b.a.com/64:ff9b::1010:1010
address /com/#
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "A");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "192.168.1.1");
ASSERT_TRUE(client.Query("c.a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NOERROR");
ASSERT_TRUE(client.Query("b.a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "A");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "192.168.1.1");
ASSERT_TRUE(client.Query("b.a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::1010:1010");
ASSERT_TRUE(client.Query("b.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "NXDOMAIN");
}

View File

@@ -39,16 +39,10 @@ TEST(Bind, tls)
server.Start(R"""(bind [::]:61053
server-tls 127.0.0.1:60053 -no-check-certificate
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
server_wrap.Start(R"""(bind-tls [::]:60053
address /example.com/1.2.3.4
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("example.com", 61053));
ASSERT_EQ(client.GetAnswerNum(), 1);
@@ -69,16 +63,10 @@ TEST(Bind, https)
server.Start(R"""(bind [::]:61053
server https://127.0.0.1:60053 -no-check-certificate
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
server_wrap.Start(R"""(bind-https [::]:60053
address /example.com/1.2.3.4
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("example.com", 61053));
ASSERT_EQ(client.GetAnswerNum(), 1);
@@ -103,10 +91,7 @@ TEST(Bind, udp_tcp)
bind [::]:60053
bind-tcp [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com +tcp", 60053));
std::cout << client.GetResult() << std::endl;
@@ -141,10 +126,7 @@ bind [::]:60053 -group self
server 127.0.0.1:61053 -group self
bind [::]:61053 -group upstream
server 127.0.0.1:62053 -group upstream
log-num 0
log-console yes
log-level info
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
@@ -174,10 +156,7 @@ TEST(Bind, nocache)
bind [::]:60053 --no-cache
bind-tcp [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -213,10 +192,7 @@ TEST(Bind, device)
server.Start(R"""(
bind [::]:60053@lo
server 127.0.0.1:62053
log-num 0
log-console yes
log-level info
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
@@ -244,10 +220,8 @@ TEST(Bind, malformed_packet)
server.Start(R"""(
bind [::]:60053@lo
server 127.0.0.1:62053
log-num 0
log-console yes
log-level info
cache-persist no)""");
)""");
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
ASSERT_NE(sockfd, -1);
@@ -283,7 +257,6 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST(Bind, group)
{
smartdns::MockServer server_upstream;
@@ -324,10 +297,7 @@ bind [::]:60253 -group g2
server 127.0.0.1:61053
server 127.0.0.1:62053 -group g1 -exclude-default-group
server 127.0.0.1:63053 -group g2 -exclude-default-group
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -56,10 +56,7 @@ TEST_F(BootStrap, bootstrap)
server.Start(R"""(bind [::]:60053
server udp://127.0.0.1:62053 -bootstrap-dns
server udp://example.com:61053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
usleep(2500000);
ASSERT_TRUE(client.Query("a.com", 60053));

View File

@@ -65,14 +65,11 @@ TEST_F(Cache, min)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
cache-size 1
rr-ttl-min 1
speed-check-mode none
response-mode fastest-response
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -110,15 +107,12 @@ TEST_F(Cache, max_reply_ttl)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
cache-size 1
rr-ttl-min 600
rr-ttl-reply-max 5
speed-check-mode none
response-mode fastest-response
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -166,13 +160,10 @@ TEST_F(Cache, max_reply_ttl_expired)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
cache-size 1
rr-ttl-min 600
rr-ttl-reply-max 6
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -234,14 +225,10 @@ bind [::]:60153 -group g1
server 127.0.0.1:61053
server 127.0.0.1:62053 -group g1 -exclude-default-group
server 127.0.0.1:63053 -group g2
log-num 0
prefetch-domain yes
rr-ttl-max 2
serve-expired no
log-console yes
log-level debug
srv-record-selection no
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -303,14 +290,11 @@ TEST_F(Cache, nocache)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
cache-size 100
rr-ttl-min 600
rr-ttl-reply-max 5
log-console yes
log-level debug
domain-rules /a.com/ --no-cache
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -337,9 +321,6 @@ TEST_F(Cache, save_file)
std::string conf = R"""(
bind [::]:60053@lo
server 127.0.0.1:62053
log-num 0
log-console yes
log-level debug
cache-persist yes
dualstack-ip-selection no
)""";
@@ -390,9 +371,6 @@ TEST_F(Cache, corrupt_file)
std::string conf = R"""(
bind [::]:60053@lo
server 127.0.0.1:62053
log-num 0
log-console yes
log-level debug
dualstack-ip-selection no
cache-persist yes
)""";
@@ -455,4 +433,49 @@ cache-persist yes
server.Stop();
usleep(200 * 1000);
}
}
TEST_F(Cache, cname)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
std::string domain = request->domain;
std::string cname = "cname." + domain;
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
unsigned char addr[4] = {1, 2, 3, 4};
dns_add_domain(request->response_packet, domain.c_str(), DNS_T_A, DNS_C_IN);
dns_add_CNAME(request->response_packet, DNS_RRS_AN, domain.c_str(), 300, cname.c_str());
dns_add_A(request->response_packet, DNS_RRS_AN, cname.c_str(), 300, addr);
request->response_packet->head.rcode = DNS_RC_NOERROR;
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
cache-size 100
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 2);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_GE(client.GetAnswer()[0].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[0].GetData(), "cname.a.com.");
EXPECT_EQ(client.GetAnswer()[1].GetName(), "cname.a.com");
EXPECT_GE(client.GetAnswer()[1].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[1].GetData(), "1.2.3.4");
ASSERT_TRUE(client.Query("cname.a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "cname.a.com");
EXPECT_GE(client.GetAnswer()[0].GetTTL(), 590);
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}

View File

@@ -50,10 +50,7 @@ cname /b.com/c.com
cname /c.com/d.com
cname /d.com/e.com
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -86,10 +83,7 @@ TEST_F(Cname, subdomain1)
server.Start(R"""(bind [::]:60053
cname /a.com/s.a.com
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -123,10 +117,7 @@ TEST_F(Cname, subdomain2)
cname /a.com/s.a.com
cname /s.a.com/a.s.a.com
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -160,10 +151,7 @@ TEST_F(Cname, loop)
cname /a.com/c.a.com
cname /c.a.com/s.a.com
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -36,17 +36,13 @@ TEST_F(DDNS, smartdns)
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
return smartdns::SERVER_REQUEST_SOA;
});
server_upstream.Start("udp://0.0.0.0:61053",
[&](struct smartdns::ServerRequestContext *request) { return smartdns::SERVER_REQUEST_SOA; });
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("smartdns A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -72,19 +68,15 @@ TEST_F(DDNS, ddns)
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
return smartdns::SERVER_REQUEST_SOA;
});
server_upstream.Start("udp://0.0.0.0:61053",
[&](struct smartdns::ServerRequestContext *request) { return smartdns::SERVER_REQUEST_SOA; });
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
ddns-domain test.ddns.com
ddns-domain test.ddns.org
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("test.ddns.com A", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -53,10 +53,7 @@ TEST(DiscardBlockIP, first_ping)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
server 127.0.0.1:62053
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -91,11 +88,8 @@ TEST(DiscardBlockIP, first_response)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
server 127.0.0.1:62053
log-num 0
log-console yes
log-level debug
response-mode fastest-response
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -46,12 +46,9 @@ TEST_F(DNS64, no_dualstack)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
dns64 64:ff9b::/96
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -54,10 +54,7 @@ TEST_F(DomainRule, bogus_nxdomain)
server.Start(R"""(bind [::]:60053
server udp://127.0.0.1:61053 -blacklist-ip
bogus-nxdomain 10.0.0.0/8
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -41,10 +41,6 @@ TEST_F(DomainSet, set_add)
std::string config = "domain-set -name test-set -file " + file_set.GetPath() + "\n";
config += R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level info
cache-persist no
domain-rules /domain-set:test-set/ -c none --dualstack-ip-selection no -a 9.9.9.9
)""";

View File

@@ -56,11 +56,8 @@ TEST_F(DualStack, ipv4_prefer)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode ping
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
@@ -107,12 +104,9 @@ TEST_F(DualStack, ipv6_prefer_allow_force_AAAA)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode ping
dualstack-ip-allow-force-AAAA yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -134,7 +128,7 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[1].GetData(), "2001:db8::2");
}
TEST_F(DualStack, ipv6_prefer_must_exist_ipv4)
TEST_F(DualStack, ipv6_prefer_without_ipv4)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
@@ -159,12 +153,9 @@ TEST_F(DualStack, ipv6_prefer_must_exist_ipv4)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode ping
dualstack-ip-allow-force-AAAA yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -184,3 +175,97 @@ cache-persist no)""");
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 597);
EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1");
}
TEST_F(DualStack, ipv6_no_speed)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype == DNS_T_A) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
return smartdns::SERVER_REQUEST_OK;
} else if (request->qtype == DNS_T_AAAA) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
return smartdns::SERVER_REQUEST_OK;
}
return smartdns::SERVER_REQUEST_SOA;
});
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 100);
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 110);
server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 10000);
server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 10000);
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
speed-check-mode ping
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
usleep(220 * 1000);
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAuthorityNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
EXPECT_GT(client.GetAuthority()[0].GetTTL(), 597);
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
}
TEST_F(DualStack, ipv4_no_response)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype == DNS_T_A) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4");
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8");
return smartdns::SERVER_REQUEST_NO_RESPONSE;
} else if (request->qtype == DNS_T_AAAA) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::1");
smartdns::MockServer::AddIP(request, request->domain.c_str(), "2001:db8::2");
return smartdns::SERVER_REQUEST_OK;
}
return smartdns::SERVER_REQUEST_SOA;
});
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 10000);
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 10000);
server.MockPing(PING_TYPE_ICMP, "2001:db8::1", 60, 100);
server.MockPing(PING_TYPE_ICMP, "2001:db8::2", 60, 110);
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
dualstack-ip-selection yes
speed-check-mode ping
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "SERVFAIL");
usleep(220 * 1000);
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 2);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_LT(client.GetQueryTime(), 20);
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_GT(client.GetAnswer()[0].GetTTL(), 590);
EXPECT_EQ(client.GetAnswer()[0].GetData(), "2001:db8::1");
EXPECT_EQ(client.GetAnswer()[1].GetName(), "a.com");
EXPECT_GT(client.GetAnswer()[1].GetTTL(), 590);
EXPECT_EQ(client.GetAnswer()[1].GetData(), "2001:db8::2");
}

View File

@@ -49,13 +49,10 @@ TEST_F(IDNA, match)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /.com/10.10.10.10
address /.com/64:ff9b::1010:1010
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("xn--fiqs8s.com A", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -74,14 +74,11 @@ TEST(IPAlias, map_multiip_nospeed_check)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
dualstack-ip-selection no
speed-check-mode none
ip-alias 1.2.3.0/24 10.10.10.10,12.12.12.12,13.13.13.13,15.15.15.15
ip-alias 0102::/16 FFFF::0001,FFFF::0002,FFFF::0003,FFFF::0004
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -148,16 +145,13 @@ TEST(IPAlias, map_single_ip_nospeed_check)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
dualstack-ip-selection no
speed-check-mode none
ip-alias 1.2.3.4 10.10.10.10
ip-alias 5.6.7.8/32 11.11.11.11
ip-alias 0102:0304:0500:: ffff::1
ip-alias 0506:0708:0900:: ffff::2
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -222,15 +216,12 @@ TEST(IPAlias, mapip_withspeed_check)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
dualstack-ip-selection no
ip-alias 1.2.3.4 10.10.10.10
ip-alias 5.6.7.8/32 11.11.11.11
ip-alias 0102::/16 ffff::1
ip-alias 0506::/16 ffff::2
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -291,16 +282,13 @@ TEST(IPAlias, no_ip_alias)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
dualstack-ip-selection no
ip-alias 1.2.3.4 10.10.10.10
ip-alias 5.6.7.8/32 11.11.11.11
ip-alias 0102::/16 ffff::1
ip-alias 0506::/16 ffff::2
domain-rules /a.com/ -no-ip-alias
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -60,10 +60,7 @@ TEST_F(IPRule, white_list)
server udp://127.0.0.1:61053 -whitelist-ip
server udp://127.0.0.1:62053 -whitelist-ip
whitelist-ip 4.5.6.7/24
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -104,10 +101,7 @@ TEST_F(IPRule, white_list_not_in)
server udp://127.0.0.1:61053 -whitelist-ip
server udp://127.0.0.1:62053 -whitelist-ip
whitelist-ip 4.5.6.7/24
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -146,10 +140,7 @@ TEST_F(IPRule, black_list)
server udp://127.0.0.1:61053 -blacklist-ip
server udp://127.0.0.1:62053 -blacklist-ip
blacklist-ip 4.5.6.7/24
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -184,10 +175,7 @@ TEST_F(IPRule, ignore_ip)
server.Start(R"""(bind [::]:60053
server udp://127.0.0.1:61053 -blacklist-ip
ignore-ip 1.2.3.0/24
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -239,11 +227,8 @@ server udp://127.0.0.1:61053 -blacklist-ip
ip-set -name ip-list -file )""" +
file + R"""(
ignore-ip ip-set:ip-list
log-num 0
speed-check-mode none
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -308,11 +293,8 @@ ip-set -name ip-list -file )""" +
ip-set -name ip-list-ip -file )""" +
file_ip + R"""(
ip-alias ip-set:ip-list ip-set:ip-list-ip
log-num 0
speed-check-mode none
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -69,10 +69,7 @@ server 127.0.0.1:62053 -group g1 -exclude-default-group
server 127.0.0.1:63053 -group g2 -exclude-default-group
nameserver /a.com/g1
nameserver /b.com/g2
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -61,11 +61,9 @@ TEST_F(Perf, no_speed_check)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode none
log-level error
cache-persist no)""");
)""");
std::string file = "/tmp/smartdns-perftest-domain.list" + smartdns::GenerateRandomString(5);
std::string cmd = "dnsperf -p 60053";
cmd += " -d ";

View File

@@ -53,11 +53,8 @@ TEST_F(Ptr, query)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("4.3.2.1.in-addr.arpa PTR", 60053));
std::cout << client.GetResult() << std::endl;
@@ -87,14 +84,11 @@ TEST_F(Ptr, address_expand_ptr)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
expand-ptr-from-address yes
address /a.com/10.11.12.13
address /a.com/64:ff9b::1010:1010
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("13.12.11.10.in-addr.arpa PTR", 60053));
std::cout << client.GetResult() << std::endl;
@@ -139,11 +133,8 @@ TEST_F(Ptr, smartdns)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
server-name my-server
log-num 0
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("1.0.0.127.in-addr.arpa PTR", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -49,11 +49,8 @@ TEST_F(QtypeSOA, AAAA_HTTPS)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
force-qtype-SOA 28,65
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
@@ -95,13 +92,10 @@ TEST_F(QtypeSOA, AAAA_Except)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
dualstack-ip-selection no
force-qtype-SOA 28
address /a.com/-
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
@@ -132,13 +126,10 @@ TEST_F(QtypeSOA, force_AAAA_SOA_Except)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
dualstack-ip-selection no
force-AAAA-SOA yes
address /a.com/-
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
@@ -169,12 +160,9 @@ TEST_F(QtypeSOA, force_AAAA_SOA)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
force-AAAA-SOA yes
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -214,11 +202,8 @@ TEST_F(QtypeSOA, bind_force_AAAA_SOA)
bind [::]:60053
bind [::]:60153 -force-aaaa-soa
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -49,12 +49,9 @@ TEST_F(Rule, Match)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /a.com/5.6.7.8
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -102,12 +99,9 @@ TEST_F(Rule, PrefixWildcardMatch)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /*a.com/5.6.7.8
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -164,12 +158,9 @@ TEST_F(Rule, SubDomainMatchOnly)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /*.a.com/5.6.7.8
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -217,12 +208,9 @@ TEST_F(Rule, RootDomainMatchOnly)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /-.a.com/5.6.7.8
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -279,13 +267,10 @@ TEST_F(Rule, AAAA_SOA)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /-.a.com/#6
address /*.b.com/#6
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -68,11 +68,9 @@ TEST_F(SamePending, pending)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
cache-size 0
log-num 0
log-console yes
speed-check-mode none
log-level error
cache-persist no)""");
)""");
std::vector<std::thread> threads;
uint64_t tick = get_tick_count();

View File

@@ -50,10 +50,7 @@ bind-tcp [::]:60053
server tls://255.255.255.255
server https://255.255.255.255
server tcp://255.255.255.255
log-num 0
log-console yes
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -66,3 +63,98 @@ cache-persist no)""");
EXPECT_EQ(client.GetStatus(), "SERVFAIL");
EXPECT_EQ(client.GetAnswerNum(), 0);
}
TEST_F(Server, one_nxdomain)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream1;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
usleep(50000);
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
return smartdns::SERVER_REQUEST_OK;
});
server_upstream1.Start("udp://0.0.0.0:62053",
[](struct smartdns::ServerRequestContext *request) { return smartdns::SERVER_REQUEST_SOA; });
server.MockPing(PING_TYPE_ICMP, "2001::", 128, 10000);
server.Start(R"""(bind [::]:60053
bind-tcp [::]:60053
server 127.0.0.1:61053
server 127.0.0.1:62053
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST_F(Server, retry_no_result_with_NOERROR)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream1;
smartdns::Server server;
int count = 0;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
if (count++ < 2) {
dns_add_domain(request->response_packet, request->domain.c_str(), request->qtype, request->qclass);
return smartdns::SERVER_REQUEST_OK;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
bind-tcp [::]:60053
server 127.0.0.1:61053
dualstack-ip-selection no
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST_F(Server, retry_no_response)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream1;
smartdns::Server server;
int count = 0;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
count++;
return smartdns::SERVER_REQUEST_NO_RESPONSE;
});
server.Start(R"""(bind [::]:60053
bind-tcp [::]:60053
server 127.0.0.1:61053
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "SERVFAIL");
EXPECT_GE(client.GetQueryTime(), 1500);
EXPECT_GE(count, 4);
}

View File

@@ -47,12 +47,9 @@ TEST_F(SpeedCheck, response_mode)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
response-mode first-ping
domain-rules /a.com/ -r fastest-response
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("b.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -89,11 +86,8 @@ TEST_F(SpeedCheck, none)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode none
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("b.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -130,11 +124,8 @@ TEST_F(SpeedCheck, domain_rules_none)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
domain-rules /a.com/ -c none
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("b.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -171,11 +162,8 @@ TEST_F(SpeedCheck, only_ping)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode ping
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("b.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -204,11 +192,8 @@ TEST_F(SpeedCheck, no_ping_fallback_tcp)
server.MockPing(PING_TYPE_TCP, "5.6.7.8:80", 60, 100);
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode ping,tcp:80
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -238,11 +223,8 @@ TEST_F(SpeedCheck, tcp_faster_than_ping)
server.MockPing(PING_TYPE_TCP, "5.6.7.8:80", 60, 10);
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode ping,tcp:80
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -273,12 +255,9 @@ TEST_F(SpeedCheck, fastest_ip)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
speed-check-mode ping
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("b.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -332,12 +311,9 @@ TEST_F(SpeedCheck, unreach_best_ipv4)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
server 127.0.0.1:62053
log-num 0
log-console yes
speed-check-mode ping
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
@@ -380,12 +356,9 @@ TEST_F(SpeedCheck, unreach_best_ipv6)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
server 127.0.0.1:62053
log-num 0
log-console yes
speed-check-mode ping
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -50,11 +50,8 @@ TEST_F(SRV, query)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("_ldap._tcp.local.com SRV", 60053));
std::cout << client.GetResult() << std::endl;
@@ -85,14 +82,11 @@ TEST_F(SRV, match)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
srv-record /_ldap._tcp.local.com/www.a.com,443,1,1
srv-record /_ldap._tcp.local.com/www1.a.com,443,1,1
srv-record /_ldap._tcp.local.com/www2.a.com,443,1,1
speed-check-mode none
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("_ldap._tcp.local.com SRV", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -85,11 +85,8 @@ TEST_F(SubNet, pass_subnet)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A +subnet=8.8.8.8/24", 60053));
std::cout << client.GetResult() << std::endl;
@@ -155,12 +152,9 @@ TEST_F(SubNet, conf)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
edns-client-subnet 8.8.8.8/24
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;
@@ -228,12 +222,9 @@ TEST_F(SubNet, conf_v6)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
edns-client-subnet ffff:ffff:ffff:ffff:ffff::/64
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
@@ -299,12 +290,9 @@ TEST_F(SubNet, v4_server_subnet_txt)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053 -subnet 8.8.8.8/24
log-num 0
log-console yes
dualstack-ip-selection no
log-level debug
rr-ttl-min 0
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com TXT", 60053));
std::cout << client.GetResult() << std::endl;
@@ -369,13 +357,10 @@ TEST_F(SubNet, v6_default_subnet_txt)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
rr-ttl-min 0
edns-client-subnet ffff:ffff:ffff:ffff:ffff::/64
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com TXT", 60053));
std::cout << client.GetResult() << std::endl;
@@ -563,11 +548,8 @@ TEST_F(SubNet, per_server)
server.Start(R"""(bind [::]:60053
server 127.0.0.1:62053 -subnet=8.8.8.8/24 -subnet=ffff:ffff:ffff:ffff:ffff::/64
server 127.0.0.1:61053
log-num 0
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com A", 60053));
std::cout << client.GetResult() << std::endl;

View File

@@ -153,6 +153,8 @@ void MockServer::Run()
dns_add_domain(request.response_packet, request.domain.c_str(), request.qtype, request.qclass);
request.response_data_len =
dns_encode(request.response_data, request.response_data_max_len, request.response_packet);
} else if (callback_ret == SERVER_REQUEST_NO_RESPONSE) {
continue;
} else if (request.response_data_len == 0) {
if (callback_ret == SERVER_REQUEST_OK) {
request.response_data_len =
@@ -344,8 +346,16 @@ bool Server::Start(const std::string &conf, enum CONF_TYPE type)
}
};
const char *default_conf = R"""(
log-num 0
log-console yes
log-level debug
cache-persist no
)""";
if (type == CONF_TYPE_STRING) {
conf_temp_file_.SetPattern("/tmp/smartdns_conf.XXXXXX");
conf_temp_file_.Write(default_conf);
conf_temp_file_.Write(conf);
conf_file = conf_temp_file_.GetPath();
} else if (type == CONF_TYPE_FILE) {

View File

@@ -87,6 +87,7 @@ struct ServerRequestContext {
typedef enum {
SERVER_REQUEST_OK = 0,
SERVER_REQUEST_ERROR,
SERVER_REQUEST_NO_RESPONSE,
SERVER_REQUEST_SOA,
} ServerRequestResult;