Add TCP DNS server
This commit is contained in:
@@ -260,10 +260,10 @@ Download the matching version of the SmartDNS installation package. The correspo
|
|||||||
Log in to the router, click `Network`->`DHCP and DNS`, and modify `DNS forwardings` to:
|
Log in to the router, click `Network`->`DHCP and DNS`, and modify `DNS forwardings` to:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/#/127.0.0.1#5353
|
/#/127.0.0.1#5053
|
||||||
```
|
```
|
||||||
|
|
||||||
Where `#5353` is the service port number of smartdns. If it is not modified, the default is 5353.
|
Where `#5053` is the service port number of smartdns. If it is not modified, the default is 5053.
|
||||||
|
|
||||||
* **Check if the service is configured successfully**
|
* **Check if the service is configured successfully**
|
||||||
|
|
||||||
@@ -371,7 +371,9 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
|||||||
|--|--|--|--|--|
|
|--|--|--|--|--|
|
||||||
|server-name|DNS name|host name/smartdns|any string like hosname|server-name smartdns
|
|server-name|DNS name|host name/smartdns|any string like hosname|server-name smartdns
|
||||||
|bind|DNS bind port|[::]:53|IP:PORT|bind 192.168.1.1:53
|
|bind|DNS bind port|[::]:53|IP:PORT|bind 192.168.1.1:53
|
||||||
|
|bind-tcp|TCP mode DNS bind port|[::]:53|IP:PORT|bind-tcp 192.168.1.1:53
|
||||||
|cache-size|Domain name result cache number|512|integer|cache-size 512
|
|cache-size|Domain name result cache number|512|integer|cache-size 512
|
||||||
|
|tcp-idle-time|TCP connection idle timeout|120|integer|tcp-idle-time 120
|
||||||
|rr-ttl|Domain name TTL|Remote query result|number greater than 0|rr-ttl 600
|
|rr-ttl|Domain name TTL|Remote query result|number greater than 0|rr-ttl 600
|
||||||
|rr-ttl-min|Domain name Minimum TTL|Remote query result|number greater than 0|rr-ttl-min 60
|
|rr-ttl-min|Domain name Minimum TTL|Remote query result|number greater than 0|rr-ttl-min 60
|
||||||
|rr-ttl-max|Domain name Maximum TTL|Remote query result|number greater than 0|rr-ttl-max 600
|
|rr-ttl-max|Domain name Maximum TTL|Remote query result|number greater than 0|rr-ttl-max 600
|
||||||
@@ -382,6 +384,7 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
|||||||
|conf-file|additional conf file|None|File path|conf-file /etc/smartdns/smartdns.more.conf
|
|conf-file|additional conf file|None|File path|conf-file /etc/smartdns/smartdns.more.conf
|
||||||
|server|Upstream UDP DNS server|None|[ip][:port], Repeatable| server 8.8.8.8:53
|
|server|Upstream UDP DNS server|None|[ip][:port], Repeatable| server 8.8.8.8:53
|
||||||
|server-tcp|Upstream TCP DNS server|None|[IP][:port], Repeatable| server-tcp 8.8.8.8:53
|
|server-tcp|Upstream TCP DNS server|None|[IP][:port], Repeatable| server-tcp 8.8.8.8:53
|
||||||
|
|server-tls|Upstream TLS DNS server|None|[IP][:port], Repeatable| server-tls 8.8.8.8:853
|
||||||
|address|Domain IP address|None|address /domain/ip| address /www.example.com/1.2.3.4
|
|address|Domain IP address|None|address /domain/ip| address /www.example.com/1.2.3.4
|
||||||
|bogus-nxdomain|bogus IP address|None|[IP],Repeatable| bogus-nxdomain 1.2.3.4
|
|bogus-nxdomain|bogus IP address|None|[IP],Repeatable| bogus-nxdomain 1.2.3.4
|
||||||
|force-AAAA-SOA|force AAAA query return SOA|no|[yes\|no]|force-AAAA-SOA yes
|
|force-AAAA-SOA|force AAAA query return SOA|no|[yes\|no]|force-AAAA-SOA yes
|
||||||
|
|||||||
@@ -260,10 +260,10 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
登录路由器,点击`Network`->`DHCP and DNS`,修改`DNS forwardings(DNS转发)`为:
|
登录路由器,点击`Network`->`DHCP and DNS`,修改`DNS forwardings(DNS转发)`为:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
/#/127.0.0.1#5353
|
/#/127.0.0.1#5053
|
||||||
```
|
```
|
||||||
|
|
||||||
其中`#5353`为smartdns的服务端口号,未修改的情况下,默认为5353。
|
其中`#5053`为smartdns的服务端口号,未修改的情况下,默认为5053。
|
||||||
|
|
||||||
* **检测上游服务是否配置成功**
|
* **检测上游服务是否配置成功**
|
||||||
|
|
||||||
@@ -371,7 +371,9 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
|--|--|--|--|--|
|
|--|--|--|--|--|
|
||||||
|server-name|DNS服务器名称|操作系统主机名/smartdns|符合主机名规格的字符串|server-name smartdns
|
|server-name|DNS服务器名称|操作系统主机名/smartdns|符合主机名规格的字符串|server-name smartdns
|
||||||
|bind|DNS监听端口号|[::]:53|IP:PORT|bind 192.168.1.1:53
|
|bind|DNS监听端口号|[::]:53|IP:PORT|bind 192.168.1.1:53
|
||||||
|
|bind-tcp|TCP模式DNS监听端口号|[::]:53|IP:PORT|bind-tcp 192.168.1.1:53
|
||||||
|cache-size|域名结果缓存个数|512|数字|cache-size 512
|
|cache-size|域名结果缓存个数|512|数字|cache-size 512
|
||||||
|
|tcp-idle-time|TCP链接空闲超时时间|120|数字|tcp-idle-time 120
|
||||||
|rr-ttl|域名结果TTL|远程查询结果|大于0的数字|rr-ttl 600
|
|rr-ttl|域名结果TTL|远程查询结果|大于0的数字|rr-ttl 600
|
||||||
|rr-ttl-min|允许的最小TTL值|远程查询结果|大于0的数字|rr-ttl-min 60
|
|rr-ttl-min|允许的最小TTL值|远程查询结果|大于0的数字|rr-ttl-min 60
|
||||||
|rr-ttl-max|允许的最大TTL值|远程查询结果|大于0的数字|rr-ttl-max 600
|
|rr-ttl-max|允许的最大TTL值|远程查询结果|大于0的数字|rr-ttl-max 600
|
||||||
@@ -382,6 +384,7 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
|conf-file|附加配置文件|无|文件路径|conf-file /etc/smartdns/smartdns.more.conf
|
|conf-file|附加配置文件|无|文件路径|conf-file /etc/smartdns/smartdns.more.conf
|
||||||
|server|上游UDP DNS|无|[ip][:port],可重复| server 8.8.8.8:53
|
|server|上游UDP DNS|无|[ip][:port],可重复| server 8.8.8.8:53
|
||||||
|server-tcp|上游TCP DNS|无|[IP][:port],可重复| server-tcp 8.8.8.8:53
|
|server-tcp|上游TCP DNS|无|[IP][:port],可重复| server-tcp 8.8.8.8:53
|
||||||
|
|server-tls|上游TLS DNS|无|[IP][:port],可重复| server-tls 8.8.8.8:853
|
||||||
|address|指定域名IP地址|无|address /domain/ip| address /www.example.com/1.2.3.4
|
|address|指定域名IP地址|无|address /domain/ip| address /www.example.com/1.2.3.4
|
||||||
|bogus-nxdomain|假冒IP地址过滤|无|[ip],可重复| bogus-nxdomain 1.2.3.4
|
|bogus-nxdomain|假冒IP地址过滤|无|[ip],可重复| bogus-nxdomain 1.2.3.4
|
||||||
|force-AAAA-SOA|强制AAAA地址返回SOA|no|[yes\|no]|force-AAAA-SOA yes
|
|force-AAAA-SOA|强制AAAA地址返回SOA|no|[yes\|no]|force-AAAA-SOA yes
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ msgstr "IPV4 53端口重定向失败"
|
|||||||
msgid "IPV6 53 Port Redirect Failure"
|
msgid "IPV6 53 Port Redirect Failure"
|
||||||
msgstr "IPV6 53端口重定向失败"
|
msgstr "IPV6 53端口重定向失败"
|
||||||
|
|
||||||
|
msgid "TCP Server"
|
||||||
|
msgstr "TCP服务器"
|
||||||
|
|
||||||
|
msgid "Enable TCP DNS Server"
|
||||||
|
msgstr "启用TCP服务器"
|
||||||
|
|
||||||
msgid "IPV6 Server"
|
msgid "IPV6 Server"
|
||||||
msgstr "IPV6服务器"
|
msgstr "IPV6服务器"
|
||||||
|
|
||||||
|
|||||||
@@ -31,11 +31,19 @@ o.rempty = false
|
|||||||
|
|
||||||
---- Port
|
---- Port
|
||||||
o = s:taboption("settings", Value, "port", translate("Local Port"), translate("Smartdns local server port"))
|
o = s:taboption("settings", Value, "port", translate("Local Port"), translate("Smartdns local server port"))
|
||||||
o.placeholder = 5353
|
o.placeholder = 5053
|
||||||
o.default = 5353
|
o.default = 5053
|
||||||
o.datatype = "port"
|
o.datatype = "port"
|
||||||
o.rempty = false
|
o.rempty = false
|
||||||
|
|
||||||
|
---- Enable TCP server
|
||||||
|
o = s:taboption("settings", Flag, "tcp_server", translate("TCP Server"), translate("Enable TCP DNS Server"))
|
||||||
|
o.rmempty = false
|
||||||
|
o.default = o.enabled
|
||||||
|
o.cfgvalue = function(...)
|
||||||
|
return Flag.cfgvalue(...) or "1"
|
||||||
|
end
|
||||||
|
|
||||||
---- Support IPV6
|
---- Support IPV6
|
||||||
o = s:taboption("settings", Flag, "ipv6_server", translate("IPV6 Server"), translate("Enable IPV6 DNS Server"))
|
o = s:taboption("settings", Flag, "ipv6_server", translate("IPV6 Server"), translate("Enable IPV6 DNS Server"))
|
||||||
o.rmempty = false
|
o.rmempty = false
|
||||||
|
|||||||
@@ -100,13 +100,22 @@ start_service() {
|
|||||||
conf_append "server-name" "$server_name"
|
conf_append "server-name" "$server_name"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
config_get "port" "$section" "port" "5353"
|
config_get "port" "$section" "port" "5053"
|
||||||
config_get "ipv6_server" "$section" "ipv6_server" "1"
|
config_get "ipv6_server" "$section" "ipv6_server" "1"
|
||||||
|
config_get "tcp_server" "$section" "tcp_server" "1"
|
||||||
if [ "$ipv6_server" = "1" ]; then
|
if [ "$ipv6_server" = "1" ]; then
|
||||||
conf_append "bind" "[::]:$port"
|
conf_append "bind" "[::]:$port"
|
||||||
else
|
else
|
||||||
conf_append "bind" ":$port"
|
conf_append "bind" ":$port"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$tcp_server" = "1" ]; then
|
||||||
|
if [ "$ipv6_server" = "1" ]; then
|
||||||
|
conf_append "bind-tcp" "[::]:$port"
|
||||||
|
else
|
||||||
|
conf_append "bind-tcp" ":$port"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
SMARTDNS_PORT="$port"
|
SMARTDNS_PORT="$port"
|
||||||
|
|
||||||
mkdir -p $(dirname $SMARTDNS_CONF)
|
mkdir -p $(dirname $SMARTDNS_CONF)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ build()
|
|||||||
|
|
||||||
sed -i "s/^Architecture.*/Architecture: $ARCH/g" $ROOT/control/control
|
sed -i "s/^Architecture.*/Architecture: $ARCH/g" $ROOT/control/control
|
||||||
sed -i "s/Version:.*/Version: $VER/" $ROOT/control/control
|
sed -i "s/Version:.*/Version: $VER/" $ROOT/control/control
|
||||||
sed -i "s/^\(bind .*\):53/\1:5353/g" $ROOT/root/etc/smartdns/smartdns.conf
|
sed -i "s/^\(bind .*\):53/\1:5053/g" $ROOT/root/etc/smartdns/smartdns.conf
|
||||||
if [ ! -z "$INST_SIZE" ]; then
|
if [ ! -z "$INST_SIZE" ]; then
|
||||||
echo "Installed-Size: $INST_SIZE" >> $ROOT/control/control
|
echo "Installed-Size: $INST_SIZE" >> $ROOT/control/control
|
||||||
fi
|
fi
|
||||||
|
|||||||
25
src/conf.c
25
src/conf.c
@@ -14,6 +14,8 @@
|
|||||||
#define DEFAULT_DNS_CACHE_SIZE 512
|
#define DEFAULT_DNS_CACHE_SIZE 512
|
||||||
|
|
||||||
char dns_conf_server_ip[DNS_MAX_IPLEN];
|
char dns_conf_server_ip[DNS_MAX_IPLEN];
|
||||||
|
char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
|
||||||
|
int dns_conf_tcp_idle_time = 120;
|
||||||
int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
|
int dns_conf_cachesize = DEFAULT_DNS_CACHE_SIZE;
|
||||||
int dns_conf_prefetch = 0;
|
int dns_conf_prefetch = 0;
|
||||||
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
|
struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
|
||||||
@@ -45,6 +47,14 @@ int config_bind(char *value)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_bind_tcp(char *value)
|
||||||
|
{
|
||||||
|
/* server bind address */
|
||||||
|
strncpy(dns_conf_server_tcp_ip, value, DNS_MAX_IPLEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int config_server_name(char *value)
|
int config_server_name(char *value)
|
||||||
{
|
{
|
||||||
strncpy(dns_conf_server_name, value, DNS_MAX_CONF_CNAME_LEN);
|
strncpy(dns_conf_server_name, value, DNS_MAX_CONF_CNAME_LEN);
|
||||||
@@ -199,6 +209,19 @@ int config_server_tcp(char *value)
|
|||||||
return config_server(value, DNS_SERVER_TCP, DEFAULT_DNS_PORT);
|
return config_server(value, DNS_SERVER_TCP, DEFAULT_DNS_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_tcp_idle_time(char *value)
|
||||||
|
{
|
||||||
|
/* read dns cache size */
|
||||||
|
int idle_time = atoi(value);
|
||||||
|
if (idle_time < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_conf_tcp_idle_time = idle_time;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int config_server_tls(char *value)
|
int config_server_tls(char *value)
|
||||||
{
|
{
|
||||||
return config_server(value, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT);
|
return config_server(value, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT);
|
||||||
@@ -527,9 +550,11 @@ struct config_item {
|
|||||||
struct config_item config_item[] = {
|
struct config_item config_item[] = {
|
||||||
{"server-name", config_server_name},
|
{"server-name", config_server_name},
|
||||||
{"bind", config_bind},
|
{"bind", config_bind},
|
||||||
|
{"bind-tcp", config_bind_tcp},
|
||||||
{"server", config_server_udp},
|
{"server", config_server_udp},
|
||||||
{"address", config_address},
|
{"address", config_address},
|
||||||
{"server-tcp", config_server_tcp},
|
{"server-tcp", config_server_tcp},
|
||||||
|
{"tcp-idle-time", config_tcp_idle_time},
|
||||||
{"server-tls", config_server_tls},
|
{"server-tls", config_server_tls},
|
||||||
{"cache-size", config_cache_size},
|
{"cache-size", config_cache_size},
|
||||||
{"prefetch-domain", config_cache_prefetch_domain},
|
{"prefetch-domain", config_cache_prefetch_domain},
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ struct dns_bogus_nxdomain {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern char dns_conf_server_ip[DNS_MAX_IPLEN];
|
extern char dns_conf_server_ip[DNS_MAX_IPLEN];
|
||||||
|
extern char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
|
||||||
|
extern int dns_conf_tcp_idle_time;
|
||||||
extern int dns_conf_cachesize;
|
extern int dns_conf_cachesize;
|
||||||
extern int dns_conf_prefetch;
|
extern int dns_conf_prefetch;
|
||||||
extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
|
extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
|
||||||
|
|||||||
@@ -1290,8 +1290,6 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tlog(TLOG_DEBUG, "decode opt.");
|
|
||||||
while (context->ptr - start < rr_len) {
|
while (context->ptr - start < rr_len) {
|
||||||
opt_code = dns_read_short(&context->ptr);
|
opt_code = dns_read_short(&context->ptr);
|
||||||
opt_len = dns_read_short(&context->ptr);
|
opt_len = dns_read_short(&context->ptr);
|
||||||
|
|||||||
538
src/dns_server.c
538
src/dns_server.c
@@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#define _GNU_SOURCE
|
||||||
#include "dns_server.h"
|
#include "dns_server.h"
|
||||||
#include "atomic.h"
|
#include "atomic.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
@@ -50,18 +50,42 @@
|
|||||||
|
|
||||||
#define DNS_MAX_EVENTS 256
|
#define DNS_MAX_EVENTS 256
|
||||||
#define DNS_SERVER_TMOUT_TTL (3 * 60)
|
#define DNS_SERVER_TMOUT_TTL (3 * 60)
|
||||||
|
#define DNS_CONN_BUFF_SIZE 4096
|
||||||
|
|
||||||
|
struct dns_conn_buf {
|
||||||
|
char buf[DNS_CONN_BUFF_SIZE];
|
||||||
|
int buffsize;
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dns_server_conn {
|
||||||
|
struct list_head list;
|
||||||
|
atomic_t refcnt;
|
||||||
|
dns_server_type_t type;
|
||||||
|
int fd;
|
||||||
|
struct dns_conn_buf recvbuff;
|
||||||
|
struct dns_conn_buf sndbuff;
|
||||||
|
|
||||||
|
socklen_t addr_len;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
|
||||||
|
time_t last_request_time;
|
||||||
|
};
|
||||||
|
|
||||||
/* dns server data */
|
/* dns server data */
|
||||||
struct dns_server {
|
struct dns_server {
|
||||||
int run;
|
int run;
|
||||||
int epoll_fd;
|
int epoll_fd;
|
||||||
int fd;
|
struct dns_server_conn udp_server;
|
||||||
|
struct dns_server_conn tcp_server;
|
||||||
|
|
||||||
/* dns request list */
|
/* dns request list */
|
||||||
pthread_mutex_t request_list_lock;
|
pthread_mutex_t request_list_lock;
|
||||||
struct list_head request_list;
|
struct list_head request_list;
|
||||||
|
struct list_head client_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* ip address lists of domain */
|
/* ip address lists of domain */
|
||||||
struct dns_ip_address {
|
struct dns_ip_address {
|
||||||
struct hlist_node node;
|
struct hlist_node node;
|
||||||
@@ -75,6 +99,8 @@ struct dns_ip_address {
|
|||||||
|
|
||||||
struct dns_request {
|
struct dns_request {
|
||||||
atomic_t refcnt;
|
atomic_t refcnt;
|
||||||
|
|
||||||
|
struct dns_server_conn *client;
|
||||||
/* dns request list */
|
/* dns request list */
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
|
||||||
@@ -127,6 +153,7 @@ struct dns_request {
|
|||||||
int prefetch;
|
int prefetch;
|
||||||
|
|
||||||
pthread_mutex_t ip_map_lock;
|
pthread_mutex_t ip_map_lock;
|
||||||
|
|
||||||
int ip_map_num;
|
int ip_map_num;
|
||||||
DECLARE_HASHTABLE(ip_map, 4);
|
DECLARE_HASHTABLE(ip_map, 4);
|
||||||
};
|
};
|
||||||
@@ -242,14 +269,86 @@ static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpacket, int inpacket_len)
|
static void _dns_server_client_release(struct dns_server_conn *client)
|
||||||
|
{
|
||||||
|
int refcnt = atomic_dec_return(&client->refcnt);
|
||||||
|
|
||||||
|
if (refcnt) {
|
||||||
|
if (refcnt < 0) {
|
||||||
|
tlog(TLOG_ERROR, "BUG: refcnt is %d", refcnt);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client->fd > 0) {
|
||||||
|
close(client->fd);
|
||||||
|
client->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_del_init(&client->list);
|
||||||
|
free(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _dns_server_client_get(struct dns_server_conn *client)
|
||||||
|
{
|
||||||
|
atomic_inc(&client->refcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_reply_tcp_to_buffer(struct dns_server_conn *client, void *packet, int len)
|
||||||
|
{
|
||||||
|
struct epoll_event event;
|
||||||
|
|
||||||
|
if (sizeof(client->sndbuff.buf) - client->sndbuff.size < len) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(client->sndbuff.buf + client->sndbuff.size, packet, len);
|
||||||
|
client->sndbuff.size += len;
|
||||||
|
|
||||||
|
memset(&event, 0, sizeof(event));
|
||||||
|
event.events = EPOLLIN | EPOLLOUT;
|
||||||
|
event.data.ptr = client;
|
||||||
|
if (epoll_ctl(server.epoll_fd, EPOLL_CTL_MOD, client->fd, &event) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_reply_tcp(struct dns_server_conn *client, void *packet, unsigned short len)
|
||||||
{
|
{
|
||||||
int send_len = 0;
|
int send_len = 0;
|
||||||
unsigned short *id = (unsigned short *)inpacket;
|
unsigned char inpacket_data[DNS_IN_PACKSIZE];
|
||||||
|
unsigned char *inpacket = inpacket_data;
|
||||||
|
|
||||||
*id = htons(request->id);
|
/* TCP query format
|
||||||
|
* | len (short) | dns query data |
|
||||||
|
*/
|
||||||
|
*((unsigned short *)(inpacket)) = htons(len);
|
||||||
|
memcpy(inpacket + 2, packet, len);
|
||||||
|
len += 2;
|
||||||
|
|
||||||
send_len = sendto(server.fd, inpacket, inpacket_len, 0, &request->addr, request->addr_len);
|
send_len = send(client->fd, inpacket, len, MSG_NOSIGNAL);
|
||||||
|
if (send_len < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
/* save data to buffer, and retry when EPOLLOUT is available */
|
||||||
|
return _dns_server_reply_tcp_to_buffer(client, inpacket, len);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
} else if (send_len < len) {
|
||||||
|
/* save remain data to buffer, and retry when EPOLLOUT is available */
|
||||||
|
return _dns_server_reply_tcp_to_buffer(client, inpacket + send_len, len - send_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_reply_udp(struct dns_request *request, struct dns_server_conn *client, unsigned char *inpacket, int inpacket_len)
|
||||||
|
{
|
||||||
|
int send_len = 0;
|
||||||
|
send_len = sendto(client->fd, inpacket, inpacket_len, 0, &request->addr, request->addr_len);
|
||||||
if (send_len != inpacket_len) {
|
if (send_len != inpacket_len) {
|
||||||
tlog(TLOG_ERROR, "send failed.");
|
tlog(TLOG_ERROR, "send failed.");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -258,6 +357,26 @@ static int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpac
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpacket, int inpacket_len)
|
||||||
|
{
|
||||||
|
struct dns_server_conn *client = request->client;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (client->type == DNS_SERVER_UDP) {
|
||||||
|
ret = _dns_server_reply_udp(request, client, inpacket, inpacket_len);
|
||||||
|
} else if (client->type == DNS_SERVER_TCP) {
|
||||||
|
ret = _dns_server_reply_tcp(client, inpacket, inpacket_len);
|
||||||
|
} else if (client->type == DNS_SERVER_TLS) {
|
||||||
|
ret = -1;
|
||||||
|
} else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dns_server_client_release(client);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_reply(struct dns_request *request)
|
static int _dns_reply(struct dns_request *request)
|
||||||
{
|
{
|
||||||
unsigned char inpacket[DNS_IN_PACKSIZE];
|
unsigned char inpacket[DNS_IN_PACKSIZE];
|
||||||
@@ -980,7 +1099,7 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len)
|
static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len)
|
||||||
{
|
{
|
||||||
int decode_len;
|
int decode_len;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@@ -994,6 +1113,8 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
|
|||||||
int qclass;
|
int qclass;
|
||||||
int qtype;
|
int qtype;
|
||||||
|
|
||||||
|
_dns_server_client_get(client);
|
||||||
|
|
||||||
decode_len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
|
decode_len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
|
||||||
if (decode_len < 0) {
|
if (decode_len < 0) {
|
||||||
tlog(TLOG_ERROR, "decode failed.\n");
|
tlog(TLOG_ERROR, "decode failed.\n");
|
||||||
@@ -1016,6 +1137,7 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
|
|||||||
request->ping_ttl_v6 = -1;
|
request->ping_ttl_v6 = -1;
|
||||||
request->prefetch = 0;
|
request->prefetch = 0;
|
||||||
request->rcode = DNS_RC_SERVFAIL;
|
request->rcode = DNS_RC_SERVFAIL;
|
||||||
|
request->client = client;
|
||||||
|
|
||||||
if (_dns_recv_addr(request, from, from_len) != 0) {
|
if (_dns_recv_addr(request, from, from_len) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -1091,6 +1213,8 @@ errout:
|
|||||||
ret = _dns_server_forward_request(inpacket, inpacket_len);
|
ret = _dns_server_forward_request(inpacket, inpacket_len);
|
||||||
free(request);
|
free(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dns_server_client_release(client);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1133,20 +1257,252 @@ errout:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _dns_server_process(unsigned long now)
|
static int _dns_server_process_udp(struct dns_server_conn *dnsserver, struct epoll_event *event, unsigned long now)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
unsigned char inpacket[DNS_IN_PACKSIZE];
|
unsigned char inpacket[DNS_IN_PACKSIZE];
|
||||||
struct sockaddr_storage from;
|
struct sockaddr_storage from;
|
||||||
socklen_t from_len = sizeof(from);
|
socklen_t from_len = sizeof(from);
|
||||||
|
|
||||||
len = recvfrom(server.fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len);
|
len = recvfrom(dnsserver->fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
tlog(TLOG_ERROR, "recvfrom failed, %s\n", strerror(errno));
|
tlog(TLOG_ERROR, "recvfrom failed, %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _dns_server_recv(inpacket, len, &from, from_len);
|
return _dns_server_recv(dnsserver, inpacket, len, &from, from_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _dns_server_client_touch(struct dns_server_conn *client)
|
||||||
|
{
|
||||||
|
time(&client->last_request_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_client_close(struct dns_server_conn *client)
|
||||||
|
{
|
||||||
|
if (client->fd > 0) {
|
||||||
|
close(client->fd);
|
||||||
|
client->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_del_init(&client->list);
|
||||||
|
|
||||||
|
_dns_server_client_release(client);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_accept(struct dns_server_conn *dnsserver, struct epoll_event *event, unsigned long now)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
struct dns_server_conn *client = NULL;
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
fd = accept4(dnsserver->fd, (struct sockaddr *)&addr, &addr_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
||||||
|
if (fd < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = malloc(sizeof(*client));
|
||||||
|
if (client == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(client, 0, sizeof(*client));
|
||||||
|
struct epoll_event event_client;
|
||||||
|
memset(&event_client, 0, sizeof(event_client));
|
||||||
|
event_client.data.ptr = client;
|
||||||
|
event_client.events = EPOLLIN;
|
||||||
|
if (epoll_ctl(server.epoll_fd, EPOLL_CTL_ADD, fd, &event_client) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "epoll add failed, %s", strerror(errno));
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->fd = fd;
|
||||||
|
client->type = DNS_SERVER_TCP;
|
||||||
|
atomic_set(&client->refcnt, 0);
|
||||||
|
memcpy(&client->addr, &addr, addr_len);
|
||||||
|
client->addr_len = addr_len;
|
||||||
|
|
||||||
|
_dns_server_client_touch(client);
|
||||||
|
|
||||||
|
list_add(&client->list, &server.client_list);
|
||||||
|
_dns_server_client_get(client);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
if (fd > 0) {
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
if (client) {
|
||||||
|
free(client);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _dns_server_tcp_recv(struct dns_server_conn *dnsserver)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
while (dnsserver->recvbuff.size < sizeof(dnsserver->recvbuff.buf)) {
|
||||||
|
if (dnsserver->recvbuff.size == sizeof(dnsserver->recvbuff.buf)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = recv(dnsserver->fd, dnsserver->recvbuff.buf + dnsserver->recvbuff.size,
|
||||||
|
sizeof(dnsserver->recvbuff.buf) - dnsserver->recvbuff.size, 0);
|
||||||
|
if (len < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
} else if (len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsserver->recvbuff.size += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _dns_server_tcp_process_one_request(struct dns_server_conn *dnsserver)
|
||||||
|
{
|
||||||
|
int request_len = 0;
|
||||||
|
int total_len = dnsserver->recvbuff.size;
|
||||||
|
int proceed_len = 0;
|
||||||
|
unsigned char *request_data = NULL;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((total_len - proceed_len) <= sizeof(unsigned short)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_len = ntohs(*((unsigned short *)(dnsserver->recvbuff.buf + proceed_len)));
|
||||||
|
if (request_len > (total_len - proceed_len)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request_len > 4096) {
|
||||||
|
tlog(TLOG_ERROR, "request length is invalid.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_data = (unsigned char *)(dnsserver->recvbuff.buf + proceed_len + sizeof(unsigned short));
|
||||||
|
|
||||||
|
if (_dns_server_recv(dnsserver, request_data, request_len, &dnsserver->addr, dnsserver->addr_len) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "process tcp request failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proceed_len += sizeof(unsigned short) + request_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_len > proceed_len && proceed_len > 0) {
|
||||||
|
memmove(dnsserver->recvbuff.buf, dnsserver->recvbuff.buf + proceed_len, total_len - proceed_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsserver->recvbuff.size -= proceed_len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _dns_server_tcp_process_requests(struct dns_server_conn *client)
|
||||||
|
{
|
||||||
|
int recv_ret = 0;
|
||||||
|
int request_ret = 0;
|
||||||
|
int is_eof = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
recv_ret = _dns_server_tcp_recv(client);
|
||||||
|
if (recv_ret < 0) {
|
||||||
|
if (client->recvbuff.size > 0) {
|
||||||
|
is_eof = 1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request_ret = _dns_server_tcp_process_one_request(client);
|
||||||
|
if (request_ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request_ret == 1 && is_eof == 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recv_ret == 1 && request_ret == 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _dns_server_tcp_send(struct dns_server_conn *client)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
while (client->sndbuff.size > 0) {
|
||||||
|
len = send(client->fd, client->sndbuff.buf, client->sndbuff.size, MSG_NOSIGNAL);
|
||||||
|
if (len < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
} else if (len == 0 ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->sndbuff.size -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct epoll_event event_client;
|
||||||
|
event_client.data.ptr = client;
|
||||||
|
event_client.events = EPOLLIN;
|
||||||
|
if (epoll_ctl(server.epoll_fd, EPOLL_CTL_MOD, client->fd, &event_client) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "epoll add failed, %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_process_tcp(struct dns_server_conn *dnsserver, struct epoll_event *event, unsigned long now)
|
||||||
|
{
|
||||||
|
if (dnsserver == &server.tcp_server) {
|
||||||
|
return _dns_server_accept(dnsserver, event, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->events & EPOLLIN) {
|
||||||
|
if (_dns_server_tcp_process_requests(dnsserver) != 0) {
|
||||||
|
_dns_server_client_close(dnsserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->events & EPOLLOUT) {
|
||||||
|
if (_dns_server_tcp_send(dnsserver) != 0) {
|
||||||
|
_dns_server_client_close(dnsserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _dns_server_process(struct dns_server_conn *dnsserver, struct epoll_event *event, unsigned long now)
|
||||||
|
{
|
||||||
|
_dns_server_client_touch(dnsserver);
|
||||||
|
if (dnsserver->type == DNS_SERVER_UDP) {
|
||||||
|
return _dns_server_process_udp(dnsserver, event, now);
|
||||||
|
} else if (dnsserver->type == DNS_SERVER_TCP) {
|
||||||
|
return _dns_server_process_tcp(dnsserver, event, now);
|
||||||
|
} else if (dnsserver->type == DNS_SERVER_TLS) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dns_server_tcp_ping_check(struct dns_request *request)
|
void _dns_server_tcp_ping_check(struct dns_request *request)
|
||||||
@@ -1203,6 +1559,27 @@ void _dns_server_prefetch_domain(struct dns_cache *dns_cache)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _dns_server_tcp_idle_check(void)
|
||||||
|
{
|
||||||
|
struct dns_server_conn *client, *tmp;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
if (dns_conf_tcp_idle_time <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
list_for_each_entry_safe(client, tmp, &server.client_list, list)
|
||||||
|
{
|
||||||
|
if (client->last_request_time > now - dns_conf_tcp_idle_time) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dns_server_client_close(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _dns_server_period_run_second(void)
|
void _dns_server_period_run_second(void)
|
||||||
{
|
{
|
||||||
static unsigned int sec = 0;
|
static unsigned int sec = 0;
|
||||||
@@ -1215,6 +1592,8 @@ void _dns_server_period_run_second(void)
|
|||||||
dns_cache_invalidate(NULL, 0);
|
dns_cache_invalidate(NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dns_server_tcp_idle_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dns_server_period_run(void)
|
void _dns_server_period_run(void)
|
||||||
@@ -1269,6 +1648,7 @@ int dns_server_run(void)
|
|||||||
sleep_time = sleep - (now - expect_time);
|
sleep_time = sleep - (now - expect_time);
|
||||||
if (sleep_time < 0) {
|
if (sleep_time < 0) {
|
||||||
sleep_time = 0;
|
sleep_time = 0;
|
||||||
|
expect_time = now;
|
||||||
}
|
}
|
||||||
expect_time += sleep;
|
expect_time += sleep;
|
||||||
}
|
}
|
||||||
@@ -1284,12 +1664,13 @@ int dns_server_run(void)
|
|||||||
}
|
}
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
struct epoll_event *event = &events[i];
|
struct epoll_event *event = &events[i];
|
||||||
if (event->data.fd != server.fd) {
|
struct dns_server_conn *dnsserver = event->data.ptr;
|
||||||
|
if (dnsserver == NULL) {
|
||||||
tlog(TLOG_ERROR, "invalid fd\n");
|
tlog(TLOG_ERROR, "invalid fd\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dns_server_process(now) != 0) {
|
if (_dns_server_process(dnsserver, event, now) != 0) {
|
||||||
tlog(TLOG_ERROR, "dns server process failed.");
|
tlog(TLOG_ERROR, "dns server process failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1324,13 +1705,18 @@ errout:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_server_start(void)
|
int _dns_server_start_udp(void)
|
||||||
{
|
{
|
||||||
struct epoll_event event;
|
struct epoll_event event;
|
||||||
|
|
||||||
|
if (server.udp_server.fd <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&event, 0, sizeof(event));
|
memset(&event, 0, sizeof(event));
|
||||||
event.events = EPOLLIN;
|
event.events = EPOLLIN;
|
||||||
event.data.fd = server.fd;
|
event.data.ptr = &server.udp_server;
|
||||||
if (epoll_ctl(server.epoll_fd, EPOLL_CTL_ADD, server.fd, &event) != 0) {
|
if (epoll_ctl(server.epoll_fd, EPOLL_CTL_ADD, server.udp_server.fd, &event) != 0) {
|
||||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1338,7 +1724,41 @@ int dns_server_start(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_server_socket(void)
|
int _dns_server_start_tcp(void)
|
||||||
|
{
|
||||||
|
struct epoll_event event;
|
||||||
|
|
||||||
|
if (server.tcp_server.fd <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&event, 0, sizeof(event));
|
||||||
|
event.events = EPOLLIN;
|
||||||
|
event.data.ptr = &server.tcp_server;
|
||||||
|
if (epoll_ctl(server.epoll_fd, EPOLL_CTL_ADD, server.tcp_server.fd, &event) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dns_server_start(void)
|
||||||
|
{
|
||||||
|
if (_dns_server_start_udp() != 0) {
|
||||||
|
tlog(TLOG_ERROR, "start udp server failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dns_server_start_tcp() != 0) {
|
||||||
|
tlog(TLOG_ERROR, "start tcp server failed.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int _dns_create_socket(const char *host_ip, int type)
|
||||||
{
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct addrinfo *gai = NULL;
|
struct addrinfo *gai = NULL;
|
||||||
@@ -1348,7 +1768,7 @@ int dns_server_socket(void)
|
|||||||
char *host = NULL;
|
char *host = NULL;
|
||||||
int optval = 1;
|
int optval = 1;
|
||||||
|
|
||||||
if (parse_ip(dns_conf_server_ip, ip, &port) == 0) {
|
if (parse_ip(host_ip, ip, &port) == 0) {
|
||||||
host = ip;
|
host = ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1357,7 +1777,7 @@ int dns_server_socket(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
snprintf(port_str, sizeof(port_str), "%d", port);
|
snprintf(port_str, sizeof(port_str), "%d", port);
|
||||||
gai = _dns_server_getaddr(host, port_str, SOCK_DGRAM, 0);
|
gai = _dns_server_getaddr(host, port_str, type, 0);
|
||||||
if (gai == NULL) {
|
if (gai == NULL) {
|
||||||
tlog(TLOG_ERROR, "get address failed.\n");
|
tlog(TLOG_ERROR, "get address failed.\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -1379,7 +1799,13 @@ int dns_server_socket(void)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
server.fd = fd;
|
if (type == SOCK_STREAM) {
|
||||||
|
if (listen(fd, 16) != 0) {
|
||||||
|
tlog(TLOG_ERROR, "listen failed.\n");
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
freeaddrinfo(gai);
|
freeaddrinfo(gai);
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
@@ -1394,6 +1820,60 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _dns_server_socket(void)
|
||||||
|
{
|
||||||
|
int fd_udp = -1;
|
||||||
|
int fd_tcp = -1;
|
||||||
|
|
||||||
|
if (dns_conf_server_ip[0] != 0) {
|
||||||
|
fd_udp = _dns_create_socket(dns_conf_server_ip, SOCK_DGRAM);
|
||||||
|
if (fd_udp < 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dns_conf_server_tcp_ip[0] != 0) {
|
||||||
|
fd_tcp = _dns_create_socket(dns_conf_server_tcp_ip, SOCK_STREAM);
|
||||||
|
if (fd_tcp < 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
server.udp_server.fd = fd_udp;
|
||||||
|
server.udp_server.type = DNS_SERVER_UDP;
|
||||||
|
_dns_server_client_get(&server.udp_server);
|
||||||
|
INIT_LIST_HEAD(&server.udp_server.list);
|
||||||
|
server.tcp_server.fd = fd_tcp;
|
||||||
|
server.tcp_server.type = DNS_SERVER_TCP;
|
||||||
|
INIT_LIST_HEAD(&server.tcp_server.list);
|
||||||
|
_dns_server_client_get(&server.tcp_server);
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
if (fd_udp > 0) {
|
||||||
|
close(fd_udp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd_tcp > 0) {
|
||||||
|
close(fd_tcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dns_server_close_socket(void)
|
||||||
|
{
|
||||||
|
if (server.udp_server.fd > 0) {
|
||||||
|
close(server.udp_server.fd);
|
||||||
|
server.udp_server.fd = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.tcp_server.fd > 0) {
|
||||||
|
close(server.tcp_server.fd);
|
||||||
|
server.tcp_server.fd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int _dns_server_audit_init(void)
|
int _dns_server_audit_init(void)
|
||||||
{
|
{
|
||||||
char *audit_file = SMARTDNS_AUDIT_FILE;
|
char *audit_file = SMARTDNS_AUDIT_FILE;
|
||||||
@@ -1417,7 +1897,7 @@ int dns_server_init(void)
|
|||||||
{
|
{
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
int epollfd = -1;
|
int epollfd = -1;
|
||||||
int fd = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (server.epoll_fd > 0) {
|
if (server.epoll_fd > 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1435,6 +1915,7 @@ int dns_server_init(void)
|
|||||||
|
|
||||||
memset(&server, 0, sizeof(server));
|
memset(&server, 0, sizeof(server));
|
||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
|
INIT_LIST_HEAD(&server.client_list);
|
||||||
|
|
||||||
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
||||||
if (epollfd < 0) {
|
if (epollfd < 0) {
|
||||||
@@ -1442,8 +1923,8 @@ int dns_server_init(void)
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = dns_server_socket();
|
ret = _dns_server_socket();
|
||||||
if (fd < 0) {
|
if (ret != 0) {
|
||||||
tlog(TLOG_ERROR, "create server socket failed.\n");
|
tlog(TLOG_ERROR, "create server socket failed.\n");
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -1451,7 +1932,6 @@ int dns_server_init(void)
|
|||||||
pthread_mutex_init(&server.request_list_lock, 0);
|
pthread_mutex_init(&server.request_list_lock, 0);
|
||||||
INIT_LIST_HEAD(&server.request_list);
|
INIT_LIST_HEAD(&server.request_list);
|
||||||
server.epoll_fd = epollfd;
|
server.epoll_fd = epollfd;
|
||||||
server.fd = fd;
|
|
||||||
server.run = 1;
|
server.run = 1;
|
||||||
|
|
||||||
if (dns_server_start() != 0) {
|
if (dns_server_start() != 0) {
|
||||||
@@ -1463,14 +1943,11 @@ int dns_server_init(void)
|
|||||||
errout:
|
errout:
|
||||||
server.run = 0;
|
server.run = 0;
|
||||||
|
|
||||||
if (fd > 0) {
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (epollfd) {
|
if (epollfd) {
|
||||||
close(epollfd);
|
close(epollfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dns_server_close_socket();
|
||||||
pthread_mutex_destroy(&server.request_list_lock);
|
pthread_mutex_destroy(&server.request_list_lock);
|
||||||
|
|
||||||
dns_cache_destroy();
|
dns_cache_destroy();
|
||||||
@@ -1489,12 +1966,7 @@ void dns_server_exit(void)
|
|||||||
LIST_HEAD(remove_list);
|
LIST_HEAD(remove_list);
|
||||||
|
|
||||||
server.run = 0;
|
server.run = 0;
|
||||||
|
_dns_server_close_socket();
|
||||||
if (server.fd > 0) {
|
|
||||||
close(server.fd);
|
|
||||||
server.fd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&server.request_list_lock);
|
pthread_mutex_lock(&server.request_list_lock);
|
||||||
list_for_each_entry_safe(request, tmp, &server.request_list, list)
|
list_for_each_entry_safe(request, tmp, &server.request_list, list)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
|
|||||||
case FAST_PING_ICMP:
|
case FAST_PING_ICMP:
|
||||||
fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
tlog(TLOG_ERROR, "create icmp socket failed.\n");
|
tlog(TLOG_ERROR, "create icmp socket failed, %s\n", strerror(errno));
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
_fast_ping_install_filter_v4(fd);
|
_fast_ping_install_filter_v4(fd);
|
||||||
@@ -483,7 +483,7 @@ static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
|
|||||||
case FAST_PING_ICMP6:
|
case FAST_PING_ICMP6:
|
||||||
fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
tlog(TLOG_ERROR, "create icmp socket failed.\n");
|
tlog(TLOG_ERROR, "create icmp socket failed, %s\n", strerror(errno));
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
_fast_ping_install_filter_v6(fd);
|
_fast_ping_install_filter_v6(fd);
|
||||||
@@ -1032,6 +1032,7 @@ static void *_fast_ping_work(void *arg)
|
|||||||
sleep_time = sleep - (now - expect_time);
|
sleep_time = sleep - (now - expect_time);
|
||||||
if (sleep_time < 0) {
|
if (sleep_time < 0) {
|
||||||
sleep_time = 0;
|
sleep_time = 0;
|
||||||
|
expect_time = now;
|
||||||
}
|
}
|
||||||
expect_time += sleep;
|
expect_time += sleep;
|
||||||
}
|
}
|
||||||
|
|||||||
38
src/tlog.c
38
src/tlog.c
@@ -835,6 +835,11 @@ static int _tlog_write_log(struct tlog_log *log, char *buff, int bufflen)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* output log to screen */
|
||||||
|
if (log->logscreen) {
|
||||||
|
write(STDOUT_FILENO, buff, bufflen);
|
||||||
|
}
|
||||||
|
|
||||||
/* if log file size exceeds threshold, start to compress */
|
/* if log file size exceeds threshold, start to compress */
|
||||||
if (log->multi_log) {
|
if (log->multi_log) {
|
||||||
log->filesize = lseek(log->fd, 0, SEEK_END);
|
log->filesize = lseek(log->fd, 0, SEEK_END);
|
||||||
@@ -854,8 +859,18 @@ static int _tlog_write_log(struct tlog_log *log, char *buff, int bufflen)
|
|||||||
|
|
||||||
if (log->fd <= 0) {
|
if (log->fd <= 0) {
|
||||||
/* open a new log file to write */
|
/* open a new log file to write */
|
||||||
char logfile[PATH_MAX * 2];
|
static time_t last_try = 0;
|
||||||
if (_tlog_mkdir(log->logdir) != 0) {
|
static int print_errmsg = 1;
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
if (now == last_try) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
last_try = now;
|
||||||
|
|
||||||
|
char logfile[PATH_MAX * 2];
|
||||||
|
if (_tlog_mkdir(log->logdir) != 0) {
|
||||||
fprintf(stderr, "create log dir %s failed.\n", log->logdir);
|
fprintf(stderr, "create log dir %s failed.\n", log->logdir);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -863,17 +878,18 @@ static int _tlog_write_log(struct tlog_log *log, char *buff, int bufflen)
|
|||||||
log->filesize = 0;
|
log->filesize = 0;
|
||||||
log->fd = open(logfile, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, 0640);
|
log->fd = open(logfile, O_APPEND | O_CREAT | O_WRONLY | O_CLOEXEC, 0640);
|
||||||
if (log->fd < 0) {
|
if (log->fd < 0) {
|
||||||
fprintf(stderr, "open log file %s failed, %s\n", logfile, strerror(errno));
|
if (print_errmsg == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get log file size */
|
fprintf(stderr, "open log file %s failed, %s\n", logfile, strerror(errno));
|
||||||
log->filesize = lseek(log->fd, 0, SEEK_END);
|
print_errmsg = 0;
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* output log to screen */
|
print_errmsg = 1;
|
||||||
if (log->logscreen) {
|
/* get log file size */
|
||||||
write(STDOUT_FILENO, buff, bufflen);
|
log->filesize = lseek(log->fd, 0, SEEK_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write log to file */
|
/* write log to file */
|
||||||
|
|||||||
Reference in New Issue
Block a user