UDP nat bug-fix
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||||
|
|
||||||
|
. /etc/default/smartdns
|
||||||
SMARTDNS=/usr/sbin/smartdns
|
SMARTDNS=/usr/sbin/smartdns
|
||||||
PIDFILE=/var/run/smartdns.pid
|
PIDFILE=/var/run/smartdns.pid
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ test -x $SMARTDNS || exit 5
|
|||||||
|
|
||||||
case $1 in
|
case $1 in
|
||||||
start)
|
start)
|
||||||
$SMARTDNS $JAIL_SHELL_OPTS
|
$SMARTDNS $SMART_DNS_OPTS
|
||||||
while true; do
|
while true; do
|
||||||
if [ -e "$PIDFILE" ]; then
|
if [ -e "$PIDFILE" ]; then
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
|
|
||||||
# bind
|
# bind
|
||||||
bind [::]:53
|
bind [::]:53
|
||||||
|
|
||||||
cache-size 1024
|
cache-size 1024
|
||||||
loglevel error
|
loglevel error
|
||||||
|
|
||||||
#server 8.8.8.8
|
#server 8.8.8.8
|
||||||
server 114.114.114.114
|
server 114.114.114.114
|
||||||
server 123.207.137.88
|
server 123.207.137.88
|
||||||
server 119.29.29.29
|
server 119.29.29.29
|
||||||
server 223.5.5.5
|
server 223.5.5.5
|
||||||
#BAU DNS
|
#BAU DNS
|
||||||
server 223.113.97.99
|
server 223.113.97.99
|
||||||
server 208.67.222.222:5353
|
server 208.67.222.222:5353
|
||||||
server 202.141.178.13:5353
|
server 202.141.178.13:5353
|
||||||
#server 77.88.8.8:53
|
#server 77.88.8.8:53
|
||||||
server 202.141.162.123:53
|
server 202.141.162.123:53
|
||||||
#server 101.132.183.99:53
|
#server 101.132.183.99:53
|
||||||
|
|||||||
198
src/dns_client.c
198
src/dns_client.c
@@ -67,6 +67,9 @@ struct dns_client {
|
|||||||
|
|
||||||
/* client socket */
|
/* client socket */
|
||||||
int udp;
|
int udp;
|
||||||
|
|
||||||
|
time_t last_send;
|
||||||
|
time_t last_recv;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* dns server information */
|
/* dns server information */
|
||||||
@@ -188,6 +191,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
|
|||||||
struct dns_server_info *server_info = NULL;
|
struct dns_server_info *server_info = NULL;
|
||||||
|
|
||||||
if (_dns_client_server_exist(gai, server_type) == 0) {
|
if (_dns_client_server_exist(gai, server_type) == 0) {
|
||||||
|
tlog(TLOG_WARN, "server exists.");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,10 +210,13 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ
|
|||||||
memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen);
|
memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen);
|
||||||
|
|
||||||
/* start ping task */
|
/* start ping task */
|
||||||
|
#if 0
|
||||||
server_info->ping_host = fast_ping_start(server_ip, 0, 60000, 1000, NULL, server_info);
|
server_info->ping_host = fast_ping_start(server_ip, 0, 60000, 1000, NULL, server_info);
|
||||||
if (server_info->ping_host == NULL) {
|
if (server_info->ping_host == NULL) {
|
||||||
|
tlog(TLOG_ERROR, "start ping failed.");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* add to list */
|
/* add to list */
|
||||||
pthread_mutex_lock(&client.server_list_lock);
|
pthread_mutex_lock(&client.server_list_lock);
|
||||||
@@ -236,8 +243,10 @@ void _dns_client_server_remove_all(void)
|
|||||||
{
|
{
|
||||||
list_del(&server_info->list);
|
list_del(&server_info->list);
|
||||||
/* stop ping task */
|
/* stop ping task */
|
||||||
if (fast_ping_stop(server_info->ping_host) != 0) {
|
if (server_info->ping_host) {
|
||||||
tlog(TLOG_ERROR, "stop ping failed.\n");
|
if (fast_ping_stop(server_info->ping_host) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "stop ping failed.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(server_info);
|
free(server_info);
|
||||||
}
|
}
|
||||||
@@ -280,6 +289,7 @@ int _dns_client_server_operate(char *server_ip, int port, dns_server_type_t serv
|
|||||||
struct addrinfo *gai = NULL;
|
struct addrinfo *gai = NULL;
|
||||||
|
|
||||||
if (server_type >= DNS_SERVER_TYPE_END) {
|
if (server_type >= DNS_SERVER_TYPE_END) {
|
||||||
|
tlog(TLOG_ERROR, "server type is invalid.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,6 +409,107 @@ void _dns_client_query_get(struct dns_query_struct *query)
|
|||||||
atomic_inc(&query->refcnt);
|
atomic_inc(&query->refcnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct addrinfo *_dns_server_getaddr(const char *host, const char *port, int type, int protocol)
|
||||||
|
{
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *result = NULL;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
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));
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
errout:
|
||||||
|
if (result) {
|
||||||
|
freeaddrinfo(result);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_client_start(void)
|
||||||
|
{
|
||||||
|
struct epoll_event event;
|
||||||
|
memset(&event, 0, sizeof(event));
|
||||||
|
event.events = EPOLLIN;
|
||||||
|
event.data.fd = client.udp;
|
||||||
|
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, client.udp, &event) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_client_socket(void)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
struct addrinfo *gai = NULL;
|
||||||
|
|
||||||
|
/* create udp socket */
|
||||||
|
gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0);
|
||||||
|
if (gai == NULL) {
|
||||||
|
tlog(TLOG_ERROR, "get address failed.\n");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol);
|
||||||
|
if (fd < 0) {
|
||||||
|
tlog(TLOG_ERROR, "create socket failed.\n");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.udp = fd;
|
||||||
|
freeaddrinfo(gai);
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
errout:
|
||||||
|
if (fd > 0) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gai) {
|
||||||
|
freeaddrinfo(gai);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dns_client_recreate_socket(void)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
int oldfd = client.udp;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&client.server_list_lock);
|
||||||
|
fd = dns_client_socket();
|
||||||
|
if (fd < 0) {
|
||||||
|
tlog(TLOG_ERROR, "create socket failed.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_client_start() != 0) {
|
||||||
|
tlog(TLOG_ERROR, "start socket failed.");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.udp = fd;
|
||||||
|
close(oldfd);
|
||||||
|
pthread_mutex_unlock(&client.server_list_lock);
|
||||||
|
return;
|
||||||
|
errout:
|
||||||
|
if (fd > 0) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
client.udp = oldfd;
|
||||||
|
pthread_mutex_unlock(&client.server_list_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void _dns_client_period_run(void)
|
void _dns_client_period_run(void)
|
||||||
{
|
{
|
||||||
struct dns_query_struct *query, *tmp;
|
struct dns_query_struct *query, *tmp;
|
||||||
@@ -423,7 +534,18 @@ void _dns_client_period_run(void)
|
|||||||
list_del_init(&query->period_list);
|
list_del_init(&query->period_list);
|
||||||
_dns_client_query_remove(query);
|
_dns_client_query_remove(query);
|
||||||
_dns_client_query_release(query);
|
_dns_client_query_release(query);
|
||||||
|
|
||||||
|
/* For udp nat case.
|
||||||
|
* when router reconnect to internet, udp port may always marked as UNREPLIED.
|
||||||
|
* dns query will timeout, and cannot reconnect again,
|
||||||
|
* create a new socket to communicate.
|
||||||
|
*/
|
||||||
|
if (client.last_send - 5 > client.last_recv) {
|
||||||
|
_dns_client_recreate_socket();
|
||||||
|
client.last_recv = client.last_send;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,6 +697,7 @@ static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long
|
|||||||
|
|
||||||
tlog(TLOG_DEBUG, "recv from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len));
|
tlog(TLOG_DEBUG, "recv from %s", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len));
|
||||||
|
|
||||||
|
time(&client.last_recv);
|
||||||
if (_dns_client_recv(inpacket, len, &from, from_len) != 0) {
|
if (_dns_client_recv(inpacket, len, &from, from_len) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -676,6 +799,7 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
|||||||
atomic_dec(&query->dns_request_sent);
|
atomic_dec(&query->dns_request_sent);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
time(&client.last_send);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&client.server_list_lock);
|
pthread_mutex_unlock(&client.server_list_lock);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -771,76 +895,6 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct addrinfo *_dns_server_getaddr(const char *host, const char *port, int type, int protocol)
|
|
||||||
{
|
|
||||||
struct addrinfo hints;
|
|
||||||
struct addrinfo *result = NULL;
|
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = AF_UNSPEC;
|
|
||||||
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));
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
errout:
|
|
||||||
if (result) {
|
|
||||||
freeaddrinfo(result);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dns_client_start(void)
|
|
||||||
{
|
|
||||||
struct epoll_event event;
|
|
||||||
memset(&event, 0, sizeof(event));
|
|
||||||
event.events = EPOLLIN;
|
|
||||||
event.data.fd = client.udp;
|
|
||||||
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, client.udp, &event) != 0) {
|
|
||||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dns_client_socket(void)
|
|
||||||
{
|
|
||||||
int fd = -1;
|
|
||||||
struct addrinfo *gai = NULL;
|
|
||||||
|
|
||||||
/* create udp socket */
|
|
||||||
gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0);
|
|
||||||
if (gai == NULL) {
|
|
||||||
tlog(TLOG_ERROR, "get address failed.\n");
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol);
|
|
||||||
if (fd < 0) {
|
|
||||||
tlog(TLOG_ERROR, "create socket failed.\n");
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.udp = fd;
|
|
||||||
freeaddrinfo(gai);
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
errout:
|
|
||||||
if (fd > 0) {
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gai) {
|
|
||||||
freeaddrinfo(gai);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dns_client_init()
|
int dns_client_init()
|
||||||
{
|
{
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 Ruilin Peng (Nick) <pymumu@gmail.com>
|
* Copyright (C) 2018 Ruilin Peng (Nick) <pymumu@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
#define _GNU_SOURCE
|
||||||
#include "tlog.h"
|
#include "tlog.h"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ After=network.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
PIDFile=/var/run/smartdns.pid
|
PIDFile=/var/run/smartdns.pid
|
||||||
EnvironmentFile=/etc/default/smartdns
|
EnvironmentFile=-/etc/default/smartdns
|
||||||
ExecStart=/usr/sbin/smartdns $SMART_DNS_OPTS
|
ExecStart=/usr/sbin/smartdns $SMART_DNS_OPTS
|
||||||
KillMode=process
|
KillMode=process
|
||||||
Restart=on-failure
|
Restart=always
|
||||||
|
RestartSec=0
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|||||||
Reference in New Issue
Block a user