feature: support lookup local network host name or ip via mDNS

This commit is contained in:
Nick Peng
2023-12-22 22:39:14 +08:00
parent 33ee73cbf2
commit c67031eb7c
13 changed files with 425 additions and 46 deletions

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>
@@ -67,6 +70,9 @@
#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;
@@ -400,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) {
@@ -426,6 +468,9 @@ static const char *_dns_server_get_type_string(dns_server_type_t type)
case DNS_SERVER_HTTPS:
type_str = "https";
break;
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));
@@ -872,6 +916,8 @@ static char *_dns_client_server_get_tls_host_verify(struct dns_server_info *serv
} break;
case DNS_SERVER_TCP:
break;
case DNS_SERVER_MDNS:
break;
default:
return NULL;
break;
@@ -905,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;
@@ -1064,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;
@@ -1168,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;
@@ -1250,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;
}
@@ -1312,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);
@@ -1585,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;
}
@@ -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;
@@ -2171,6 +2293,8 @@ 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) {
@@ -2556,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;
}
@@ -2579,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;
}
@@ -3181,7 +3309,7 @@ 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) {
@@ -3261,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;
@@ -3483,7 +3632,7 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
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);
}
@@ -3549,7 +3698,7 @@ 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);
@@ -3563,7 +3712,7 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
}
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);
}
@@ -3609,6 +3758,11 @@ 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_MDNS:
/* mdns query */
ret = _dns_client_send_udp_mdns(server_info, packet_data, packet_data_len);
send_err = errno;
break;
default:
/* unsupported query type */
ret = -1;
@@ -4440,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;
@@ -4480,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,12 +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_MDNS,
DNS_SERVER_TYPE_END,
} dns_server_type_t;
@@ -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

@@ -162,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];
@@ -3967,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;
}
@@ -3988,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);
@@ -4275,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),
@@ -4289,6 +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_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),
@@ -4728,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

@@ -578,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

@@ -280,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;
@@ -365,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);
@@ -761,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;
}
@@ -782,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;
}
@@ -1559,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;
}
@@ -1575,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;
}
@@ -2770,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);
@@ -3127,7 +3133,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;
}
@@ -3214,7 +3220,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;
}
@@ -3338,8 +3344,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);
@@ -3431,7 +3437,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;
}
@@ -3470,7 +3477,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;
}
@@ -3552,8 +3560,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;
}
@@ -3584,8 +3592,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;
}
@@ -3619,8 +3627,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;
}
@@ -3698,6 +3706,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;
@@ -4100,7 +4115,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;
}
@@ -4179,6 +4194,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;
@@ -4188,9 +4212,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;
@@ -4253,7 +4280,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);
}
@@ -4842,7 +4869,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;
}
@@ -5462,13 +5489,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)
{
@@ -5476,7 +5502,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;
}
@@ -5536,6 +5562,35 @@ static int _dns_server_setup_query_option(struct dns_request *request, struct dn
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;
}
static int _dns_server_query_dualstack(struct dns_request *request)
{
int ret = -1;
@@ -5598,6 +5653,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;
@@ -5691,10 +5748,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);
@@ -6464,7 +6530,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;
}

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);