Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21ba047075 | ||
|
|
9f3926e048 | ||
|
|
e8b920fb18 | ||
|
|
a1150a7ceb | ||
|
|
e1ffe29fca | ||
|
|
d9dd02c9b0 | ||
|
|
c7d304423e | ||
|
|
87d8739ecd | ||
|
|
452438a0af | ||
|
|
0085abdfdd | ||
|
|
46d3acdb8f | ||
|
|
36ddca0491 | ||
|
|
f02dffdf95 | ||
|
|
10ea3e6f3f | ||
|
|
7add2b82ae | ||
|
|
05a24264aa | ||
|
|
8e73eea8ec | ||
|
|
c3ac0c2f17 | ||
|
|
210e0a9a6f | ||
|
|
9092d9f683 | ||
|
|
5057a8e45d | ||
|
|
1600eaed1f | ||
|
|
65ede47cf7 | ||
|
|
6e5fc54439 | ||
|
|
71e110748b | ||
|
|
0112d12693 | ||
|
|
0a236acc56 | ||
|
|
050aedadd4 | ||
|
|
7241b24a57 | ||
|
|
5e12611157 | ||
|
|
7f5e0ef4e0 | ||
|
|
bb1c4d2bfa | ||
|
|
dd4372a961 | ||
|
|
73d4e9f822 | ||
|
|
95a5b1e5e3 | ||
|
|
143d82ce1a | ||
|
|
4028887167 | ||
|
|
1674c3d8c9 |
76
ReadMe.md
76
ReadMe.md
@@ -85,8 +85,8 @@ From the comparison, smartdns found the fastest IP address to visit www.baidu.co
|
|||||||
5. **Domain name high performance rule filtering**
|
5. **Domain name high performance rule filtering**
|
||||||
Support domain name suffix matching mode, simplify filtering configuration, filter 200,000 recording and take time <1ms.
|
Support domain name suffix matching mode, simplify filtering configuration, filter 200,000 recording and take time <1ms.
|
||||||
|
|
||||||
6. **Linux multi-platform support**
|
6. **Linux/Windows multi-platform support**
|
||||||
Support standard Linux system (Raspberry Pi), openwrt system various firmware, ASUS router native firmware.
|
Support standard Linux system (Raspberry Pi), openwrt system various firmware, ASUS router native firmware. Support Windows 10 WSL (Windows Subsystem for Linux).
|
||||||
|
|
||||||
7. **Support IPV4, IPV6 dual stack**
|
7. **Support IPV4, IPV6 dual stack**
|
||||||
Support IPV4, IPV6 network, support query A, AAAA record, dual-stack IP selection.
|
Support IPV4, IPV6 network, support query A, AAAA record, dual-stack IP selection.
|
||||||
@@ -114,14 +114,17 @@ Download the matching version of the SmartDNS installation package. The correspo
|
|||||||
|system |package|Description
|
|system |package|Description
|
||||||
|-----|-----|-----
|
|-----|-----|-----
|
||||||
|Standard Linux system (Raspberry Pi)| smartdns.xxxxxxxx.armhf.deb|Support Raspberry Pi Raspbian stretch, Debian 9 system.
|
|Standard Linux system (Raspberry Pi)| smartdns.xxxxxxxx.armhf.deb|Support Raspberry Pi Raspbian stretch, Debian 9 system.
|
||||||
|Standard Linux system (x86_64)| smartdns.xxxxxxxx.x86_64.tar.gz|Support for x86_64 systems.
|
|Standard Linux system (x86_64)| smartdns.xxxxxxxx.x86_64.tar.gz|Support for x86_64 Linux systems.
|
||||||
|
|Windows 10 WSL (Ubuntu)| smartdns.xxxxxxxx.x86_64.tar.gz|Windows 10 WSL ubuntu.
|
||||||
|Standard Linux system (x86)| smartdns.xxxxxxxx.x86.tar.gz|Support for x86_64 systems.
|
|Standard Linux system (x86)| smartdns.xxxxxxxx.x86.tar.gz|Support for x86_64 systems.
|
||||||
|ASUS native firmware (optware)|smartdns.xxxxxxx.mipsbig.ipk|Systems that support the MIPS big-end architecture, such as RT-AC55U, RT-AC66U.
|
|ASUS native firmware (optware)|smartdns.xxxxxxx.mipsbig.ipk|Systems that support the MIPS big-end architecture, such as RT-AC55U, RT-AC66U.
|
||||||
|ASUS native firmware (optware)|smartdns.xxxxxxx.mipsel.ipk|System that supports the MIPS little endian architecture, such as the RT-AC68U.
|
|ASUS native firmware (optware)|smartdns.xxxxxxx.mipsel.ipk|System that supports the MIPS little endian architecture.
|
||||||
|ASUS native firmware (optware)|smartdns.xxxxxxx.arm.ipk|System that supports the ARM small endian architecture, such as the RT-AC88U.
|
|ASUS native firmware (optware)|smartdns.xxxxxxx.arm.ipk|System that supports the ARM small endian architecture, such as the RT-AC88U, RT-AC68U.
|
||||||
|
|Padavan|smartdns.xxxxxxx.mipselsf.ipk|padavan Firmware.
|
||||||
|openwrt 15.01|smartdns.xxxxxxxx.ar71xx.ipk|Support AR71XX MIPS system.
|
|openwrt 15.01|smartdns.xxxxxxxx.ar71xx.ipk|Support AR71XX MIPS system.
|
||||||
|openwrt 15.01|smartdns.xxxxxxxx.ramips_24kec.ipk|Support small-end routers such as MT762X
|
|openwrt 15.01|smartdns.xxxxxxxx.ramips_24kec.ipk|Support small-end routers such as MT762X
|
||||||
|openwrt 15.01(Pandora)|smartdns.xxxxxxxx.mipsel_24kec_dsp.ipk|Support for Pandora firmware of MT7620 series
|
|openwrt 15.01(Pandora)|smartdns.xxxxxxxx.mipsel_24kec_dsp.ipk|Support for Pandora firmware of MT7620 series
|
||||||
|
|openwrt 15.01(Pandora)|smartdns.xxxxxxxx.mips_74kc_dsp2.ipk|Support for Pandora firmware of AR71xx series
|
||||||
|openwrt 18.06|smartdns.xxxxxxxx.mips_24kc.ipk|Support AR71XX MIPS system.
|
|openwrt 18.06|smartdns.xxxxxxxx.mips_24kc.ipk|Support AR71XX MIPS system.
|
||||||
|openwrt 18.06|smartdns.xxxxxxxx.mipsel_24kc.ipk|Support small-end routers such as MT726X
|
|openwrt 18.06|smartdns.xxxxxxxx.mipsel_24kc.ipk|Support small-end routers such as MT726X
|
||||||
|openwrt 18.06|smartdns.xxxxxxxx.x86_64.ipk|Support x86_64 router
|
|openwrt 18.06|smartdns.xxxxxxxx.x86_64.ipk|Support x86_64 router
|
||||||
@@ -367,6 +370,61 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
|||||||
\\192.168.1.1\sda1\asusware.mipsbig\etc\init.d
|
\\192.168.1.1\sda1\asusware.mipsbig\etc\init.d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Windows 10 WSL Installation(WSL ubuntu)
|
||||||
|
|
||||||
|
--------------
|
||||||
|
|
||||||
|
1. Install Windows 10 WSL ubuntu
|
||||||
|
|
||||||
|
Install the Windows 10 WSL environment and select Ubuntu as default distribution. Please refer to [WSL installation instructions](https://docs.microsoft.com/en-us/windows/wsl/install-win10) for installation steps
|
||||||
|
|
||||||
|
1. Install smartdns
|
||||||
|
|
||||||
|
download install package `smartdns.xxxxxxxx.x86_64.tar.gz`,and unzip to the `D:\` directory, after decompression, the directory is as follows:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
D:\SMARTDNS
|
||||||
|
├─etc
|
||||||
|
│ ├─default
|
||||||
|
│ ├─init.d
|
||||||
|
│ └─smartdns
|
||||||
|
├─package
|
||||||
|
│ └─windows
|
||||||
|
├─src
|
||||||
|
└─systemd
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Double-click `install.bat` in the `D:\smartdns\package\windows` directory for installation. Please enter the password for `WLS ubuntu` when input password.
|
||||||
|
|
||||||
|
1. Configuration
|
||||||
|
|
||||||
|
Edit `smartdns.conf` configuration file in `D:\smartdns\etc\smartdns` directory, you can configure the upstream server to smartdns. Refer to the `Configuration Parameters` for specific configuration parameters.
|
||||||
|
In general, you only need to add `server [IP]:port`, `server-tcp [IP]:port` configuration items.
|
||||||
|
Configure as many upstream DNS servers as possible, including servers at home and abroad. Please refer to the `Configuration Parameters` section for configuration parameters.
|
||||||
|
|
||||||
|
1. Start Service
|
||||||
|
|
||||||
|
Double-click `reload.bat` in the `D:\smartdns\package\windows` directory for reload.
|
||||||
|
|
||||||
|
1. Forwarding DNS request to SmartDNS
|
||||||
|
|
||||||
|
Modify the default DNS server for Windows to `127.0.0.1`, with these steps referred to [IP configuration](https://support.microsoft.com/en-us/help/15089/windows-change-tcp-ip-settings)
|
||||||
|
|
||||||
|
1. Check if the service is configured successfully
|
||||||
|
|
||||||
|
Query domain name with `nslookup -querytype=ptr 0.0.0.0`
|
||||||
|
Check if the `name` item in the command result is displayed as `smartdns` or `hostname`, such as `smartdns`
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pi@raspberrypi:~/code/smartdns_build $ nslookup -querytype=ptr 0.0.0.0
|
||||||
|
Server: 192.168.1.1
|
||||||
|
Address: 192.168.1.1#53
|
||||||
|
|
||||||
|
Non-authoritative answer:
|
||||||
|
0.0.0.0.in-addr.arpa name = smartdns.
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration parameter
|
## Configuration parameter
|
||||||
|
|
||||||
|parameter|Parameter function|Default value|Value type|Example|
|
|parameter|Parameter function|Default value|Value type|Example|
|
||||||
@@ -391,13 +449,15 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
|||||||
|server|Upstream UDP DNS server|None|[ip][:port] [-blacklist-ip][-check-edns], Repeatable, blacklist-ip parameter represents filtering the result of IPs with blacklist-ip configuration.| server 8.8.8.8:53 -blacklist-ip -check-edns
|
|server|Upstream UDP DNS server|None|[ip][:port] [-blacklist-ip][-check-edns], Repeatable, blacklist-ip parameter represents filtering the result of IPs with blacklist-ip configuration.| server 8.8.8.8:53 -blacklist-ip -check-edns
|
||||||
|server-tcp|Upstream TCP DNS server|None|[IP][:port] [-blacklist-ip][-check-edns], Repeatable, blacklist-ip parameter represents filtering the result of IPs with blacklist-ip configuration.| server-tcp 8.8.8.8:53
|
|server-tcp|Upstream TCP DNS server|None|[IP][:port] [-blacklist-ip][-check-edns], Repeatable, blacklist-ip parameter represents filtering the result of IPs with blacklist-ip configuration.| server-tcp 8.8.8.8:53
|
||||||
|server-tls|Upstream TLS DNS server|None|[IP][:port] [-blacklist-ip][-check-edns], Repeatable, blacklist-ip parameter represents filtering the result of IPs with blacklist-ip configuration.| server-tls 8.8.8.8:853
|
|server-tls|Upstream TLS DNS server|None|[IP][:port] [-blacklist-ip][-check-edns], Repeatable, blacklist-ip parameter represents filtering the result of IPs with blacklist-ip configuration.| 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\|-\|-4\|-6\|#\|#4\|#6], `-` for ignore, `#` for return SOA, `4` for IPV4, `6` for IPV6| address /www.example.com/1.2.3.4
|
||||||
|ipset|Domain IPSet|None|ipset /domain/ipset|ipset /www.example.com/pass
|
|ipset|Domain IPSet|None|ipset /domain/[ipset\|-], `-` for ignore|ipset /www.example.com/pass
|
||||||
|
|ipset-timeout|ipset timeout enable|auto|[yes]|ipset-timeout yes
|
||||||
|bogus-nxdomain|bogus IP address|None|[IP/subnet], Repeatable| bogus-nxdomain 1.2.3.4/16
|
|bogus-nxdomain|bogus IP address|None|[IP/subnet], Repeatable| bogus-nxdomain 1.2.3.4/16
|
||||||
|
|ignore-ip|ignore ip address|None|[ip/subnet], Repeatable| ignore-ip 1.2.3.4/16
|
||||||
|blacklist-ip|ip blacklist|None|[ip/subnet], Repeatable,When the filtering server responds IPs in the IP blacklist, The result will be discarded directly| blacklist-ip 1.2.3.4/16
|
|blacklist-ip|ip blacklist|None|[ip/subnet], Repeatable,When the filtering server responds IPs in the IP blacklist, The result will be discarded directly| blacklist-ip 1.2.3.4/16
|
||||||
|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
|
||||||
|dualstack-ip-selection|Dualstack ip selection|no|[yes\|no]|dualstack-ip-selection yes
|
|dualstack-ip-selection|Dualstack ip selection|no|[yes\|no]|dualstack-ip-selection yes
|
||||||
|dualstack-ip-selection-threshold|Dualstack ip select threadhold|100ms|millisecond|dualstack-ip-selection-threshold [1-1000]
|
|dualstack-ip-selection-threshold|Dualstack ip select threadhold|30ms|millisecond|dualstack-ip-selection-threshold [0-1000]
|
||||||
|
|
||||||
## [Donate](#Donate)
|
## [Donate](#Donate)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# SmartDNS
|
# SmartDNS
|
||||||
|
|
||||||

|

|
||||||
SmartDNS是一个运行在本地的DNS服务器,SmartDNS接受本地客户端的DNS查询请求,从多个上游DNS服务器获取DNS查询结果,并将访问速度最快的结果返回个客户端,避免DNS污染,提高网络访问速度。
|
SmartDNS是一个运行在本地的DNS服务器,SmartDNS接受本地客户端的DNS查询请求,从多个上游DNS服务器获取DNS查询结果,并将访问速度最快的结果返回给客户端,避免DNS污染,提高网络访问速度。
|
||||||
同时支持指定特定域名IP地址,并高性匹配,达到过滤广告的效果。
|
同时支持指定特定域名IP地址,并高性匹配,达到过滤广告的效果。
|
||||||
与dnsmasq的all-servers不同,smartdns返回的是访问速度最快的解析结果。
|
与dnsmasq的all-servers不同,smartdns返回的是访问速度最快的解析结果。
|
||||||
|
|
||||||
@@ -85,8 +85,8 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
5. **域名高性能后缀匹配**
|
5. **域名高性能后缀匹配**
|
||||||
支持域名后缀匹配模式,简化过滤配置,过滤20万条记录时间<1ms
|
支持域名后缀匹配模式,简化过滤配置,过滤20万条记录时间<1ms
|
||||||
|
|
||||||
6. **Linux多平台支持**
|
6. **Linux/Windows多平台支持**
|
||||||
支持标准Linux系统(树莓派),openwrt系统各种固件,华硕路由器原生固件。
|
支持标准Linux系统(树莓派),openwrt系统各种固件,华硕路由器原生固件。以及支持Windows 10 WSL (Windows Subsystem for Linux)。
|
||||||
|
|
||||||
7. **支持IPV4, IPV6双栈**
|
7. **支持IPV4, IPV6双栈**
|
||||||
支持IPV4,IPV6网络,支持查询A, AAAA记录,支持双栈IP速度优化。
|
支持IPV4,IPV6网络,支持查询A, AAAA记录,支持双栈IP速度优化。
|
||||||
@@ -114,14 +114,17 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
|系统 |安装包|说明
|
|系统 |安装包|说明
|
||||||
|-----|-----|-----
|
|-----|-----|-----
|
||||||
|标准Linux系统(树莓派)| smartdns.xxxxxxxx.armhf.deb|支持树莓派Raspbian stretch,Debian 9系统。
|
|标准Linux系统(树莓派)| smartdns.xxxxxxxx.armhf.deb|支持树莓派Raspbian stretch,Debian 9系统。
|
||||||
|标准Linux系统(x86_64)| smartdns.xxxxxxxx.x86_64.tar.gz|支持x86_64系统。
|
|标准Linux系统(x86_64)| smartdns.xxxxxxxx.x86_64.tar.gz|支持x86_64 Linux 系统。
|
||||||
|
|Windows 10 WSL (ubuntu)| smartdns.xxxxxxxx.x86_64.tar.gz|支持Windows 10 WSL ubuntu系统。
|
||||||
|标准Linux系统(x86)| smartdns.xxxxxxxx.x86.tar.gz|支持x86系统。
|
|标准Linux系统(x86)| smartdns.xxxxxxxx.x86.tar.gz|支持x86系统。
|
||||||
|华硕原生固件(optware)|smartdns.xxxxxxx.mipsbig.ipk|支持MIPS大端架构的系统,如RT-AC55U, RT-AC66U.
|
|华硕原生固件(optware)|smartdns.xxxxxxx.mipsbig.ipk|支持MIPS大端架构的系统,如RT-AC55U, RT-AC66U.
|
||||||
|华硕原生固件(optware)|smartdns.xxxxxxx.mipsel.ipk|支持MIPS小端架构的系统,如RT-AC68U。
|
|华硕原生固件(optware)|smartdns.xxxxxxx.mipsel.ipk|支持MIPS小端架构的系统。
|
||||||
|华硕原生固件(optware)|smartdns.xxxxxxx.arm.ipk|支持arm小端架构的系统,如RT-AC88U。
|
|华硕原生固件(optware)|smartdns.xxxxxxx.arm.ipk|支持arm小端架构的系统,如RT-AC68U。
|
||||||
|
|Padavan|smartdns.xxxxxxx.mipselsf.ipk|padavan固件。
|
||||||
|openwrt 15.01|smartdns.xxxxxxxx.ar71xx.ipk|支持AR71XX MIPS系统。
|
|openwrt 15.01|smartdns.xxxxxxxx.ar71xx.ipk|支持AR71XX MIPS系统。
|
||||||
|openwrt 15.01|smartdns.xxxxxxxx.ramips_24kec.ipk|支持MT762X等小端路由器
|
|openwrt 15.01|smartdns.xxxxxxxx.ramips_24kec.ipk|支持MT762X等小端路由器
|
||||||
|openwrt 15.01(潘多拉)|smartdns.xxxxxxxx.mipsel_24kec_dsp.ipk|支持MT7620系列的潘多拉固件
|
|openwrt 15.01(潘多拉)|smartdns.xxxxxxxx.mipsel_24kec_dsp.ipk|支持MT7620系列的潘多拉固件
|
||||||
|
|openwrt 15.01(潘多拉)|smartdns.xxxxxxxx.mips_74kc_dsp2.ipk|支持AR71xx系列的潘多拉固件
|
||||||
|openwrt 18.06|smartdns.xxxxxxxx.mips_24kc.ipk|支持AR71XX MIPS系统。
|
|openwrt 18.06|smartdns.xxxxxxxx.mips_24kc.ipk|支持AR71XX MIPS系统。
|
||||||
|openwrt 18.06|smartdns.xxxxxxxx.mipsel_24kc.ipk|支持MT726X等小端路由器
|
|openwrt 18.06|smartdns.xxxxxxxx.mipsel_24kc.ipk|支持MT726X等小端路由器
|
||||||
|openwrt 18.06|smartdns.xxxxxxxx.x86_64.ipk|支持x86_64路由器
|
|openwrt 18.06|smartdns.xxxxxxxx.x86_64.ipk|支持x86_64路由器
|
||||||
@@ -367,6 +370,62 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
\\192.168.1.1\sda1\asusware.mipsbig\etc\init.d
|
\\192.168.1.1\sda1\asusware.mipsbig\etc\init.d
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Windows 10 WSL安装(WSL ubuntu)
|
||||||
|
|
||||||
|
--------------
|
||||||
|
|
||||||
|
1. 安装Windows 10 WSL ubuntu系统
|
||||||
|
|
||||||
|
安装Windows 10 WSL运行环境,发行版本选择ubuntu系统。安装步骤请参考[WSL安装说明](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
|
||||||
|
|
||||||
|
1. 安装smartdns
|
||||||
|
|
||||||
|
下载安装包`smartdns.xxxxxxxx.x86_64.tar.gz`,并解压到D盘根目录。解压后目录如下:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
D:\SMARTDNS
|
||||||
|
├─etc
|
||||||
|
│ ├─default
|
||||||
|
│ ├─init.d
|
||||||
|
│ └─smartdns
|
||||||
|
├─package
|
||||||
|
│ └─windows
|
||||||
|
├─src
|
||||||
|
└─systemd
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
双击`D:\smartdns\package\windows`目录下的`install.bat`进行安装。要求输入密码时,请输入`WLS ubuntu`的密码。
|
||||||
|
|
||||||
|
1. 修改配置
|
||||||
|
|
||||||
|
记事本打开`D:\smartdns\etc\smartdns`目录中的`smartdns.conf`配置文件配置smartdns。具体配置参数参考`配置参数`说明。
|
||||||
|
一般情况下,只需要增加`server [IP]:port`, `server-tcp [IP]:port`配置项,
|
||||||
|
尽可能配置多个上游DNS服务器,包括国内外的服务器。配置参数请查看`配置参数`章节。
|
||||||
|
|
||||||
|
1. 重新加载配置
|
||||||
|
|
||||||
|
双击`D:\smartdns\package\windows`目录下的`reload.bat`进行安装。要求输入密码时,请输入`WLS ubuntu`的密码。
|
||||||
|
|
||||||
|
1. 将DNS请求转发的SmartDNS解析。
|
||||||
|
|
||||||
|
将Windows的默认DNS服务器修改为`127.0.0.1`,具体步骤参考[IP配置](https://support.microsoft.com/zh-cn/help/15089/windows-change-tcp-ip-settings)
|
||||||
|
|
||||||
|
1. 检测服务是否配置成功。
|
||||||
|
|
||||||
|
使用`nslookup -querytype=ptr 0.0.0.0`查询域名
|
||||||
|
看命令结果中的`name`项目是否显示为`smartdns`或`主机名`,如`smartdns`则表示生效
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pi@raspberrypi:~/code/smartdns_build $ nslookup -querytype=ptr 0.0.0.0
|
||||||
|
Server: 192.168.1.1
|
||||||
|
Address: 192.168.1.1#53
|
||||||
|
|
||||||
|
Non-authoritative answer:
|
||||||
|
0.0.0.0.in-addr.arpa name = smartdns.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## 配置参数
|
## 配置参数
|
||||||
|
|
||||||
|参数|功能|默认值|配置值|例子|
|
|参数|功能|默认值|配置值|例子|
|
||||||
@@ -391,13 +450,15 @@ rtt min/avg/max/mdev = 5.954/6.133/6.313/0.195 ms
|
|||||||
|server|上游UDP DNS|无|[ip][:port] [-blacklist-ip][-check-edns],可重复,blacklist-ip参数指定使用blacklist-ip配置IP过滤结果| server 8.8.8.8:53 -blacklist-ip -check-edns
|
|server|上游UDP DNS|无|[ip][:port] [-blacklist-ip][-check-edns],可重复,blacklist-ip参数指定使用blacklist-ip配置IP过滤结果| server 8.8.8.8:53 -blacklist-ip -check-edns
|
||||||
|server-tcp|上游TCP DNS|无|[IP][:port] [-blacklist-ip][-check-edns],可重复,blacklist-ip参数指定使用blacklist-ip配置IP过滤结果| server-tcp 8.8.8.8:53
|
|server-tcp|上游TCP DNS|无|[IP][:port] [-blacklist-ip][-check-edns],可重复,blacklist-ip参数指定使用blacklist-ip配置IP过滤结果| server-tcp 8.8.8.8:53
|
||||||
|server-tls|上游TLS DNS|无|[IP][:port] [-blacklist-ip][-check-edns],可重复,blacklist-ip参数指定使用blacklist-ip配置IP过滤结果| server-tls 8.8.8.8:853
|
|server-tls|上游TLS DNS|无|[IP][:port] [-blacklist-ip][-check-edns],可重复,blacklist-ip参数指定使用blacklist-ip配置IP过滤结果| 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\|-\|-4\|-6\|#\|#4\|#6], `-`表示忽略, `#`表示返回SOA, `4`表示IPV4, `6`表示IPV6| address /www.example.com/1.2.3.4
|
||||||
|ipset|域名IPSET|None|ipset /domain/ipset|ipset /www.example.com/pass
|
|ipset|域名IPSET|None|ipset /domain/[ipset\|-], `-`表示忽略|ipset /www.example.com/pass
|
||||||
|
|ipset-timeout|设置IPSET超时功能启用|auto|[yes]|ipset-timeout yes
|
||||||
|bogus-nxdomain|假冒IP地址过滤|无|[ip/subnet],可重复| bogus-nxdomain 1.2.3.4/16
|
|bogus-nxdomain|假冒IP地址过滤|无|[ip/subnet],可重复| bogus-nxdomain 1.2.3.4/16
|
||||||
|
|ignore-ip|忽略IP地址|无|[ip/subnet],可重复| ignore-ip 1.2.3.4/16
|
||||||
|blacklist-ip|黑名单IP地址|无|[ip/subnet],可重复| blacklist-ip 1.2.3.4/16
|
|blacklist-ip|黑名单IP地址|无|[ip/subnet],可重复| blacklist-ip 1.2.3.4/16
|
||||||
|force-AAAA-SOA|强制AAAA地址返回SOA|no|[yes\|no]|force-AAAA-SOA yes
|
|force-AAAA-SOA|强制AAAA地址返回SOA|no|[yes\|no]|force-AAAA-SOA yes
|
||||||
|dualstack-ip-selection|双栈IP优选|no|[yes\|no]|dualstack-ip-selection yes
|
|dualstack-ip-selection|双栈IP优选|no|[yes\|no]|dualstack-ip-selection yes
|
||||||
|dualstack-ip-selection-threshold|双栈IP优选阈值|100ms|毫秒|dualstack-ip-selection-threshold [1-1000]
|
|dualstack-ip-selection-threshold|双栈IP优选阈值|30ms|毫秒|dualstack-ip-selection-threshold [0-1000]
|
||||||
|
|
||||||
## [Donate](#Donate)
|
## [Donate](#Donate)
|
||||||
|
|
||||||
|
|||||||
@@ -36,18 +36,21 @@ cache-size 512
|
|||||||
# List of IPs that will be filtered when nameserver is configured -blacklist-ip parameter
|
# List of IPs that will be filtered when nameserver is configured -blacklist-ip parameter
|
||||||
# blacklist-ip [ip/subnet]
|
# blacklist-ip [ip/subnet]
|
||||||
|
|
||||||
|
# List of IPs that will be ignored
|
||||||
|
# ignore-ip [ip/subnet]
|
||||||
|
|
||||||
# force AAAA query return SOA
|
# force AAAA query return SOA
|
||||||
# force-AAAA-SOA [yes|no]
|
# force-AAAA-SOA [yes|no]
|
||||||
|
|
||||||
# Enable IPV4, IPV6 dual stack IP optimization selection strategy
|
# Enable IPV4, IPV6 dual stack IP optimization selection strategy
|
||||||
# dualstack-ip-selection-threshold [num] (1~1000)
|
# dualstack-ip-selection-threshold [num] (0~1000)
|
||||||
# dualstack-ip-selection [yes|no]
|
# dualstack-ip-selection [yes|no]
|
||||||
# dualstack-ip-selection yes
|
# dualstack-ip-selection yes
|
||||||
|
|
||||||
# edns client subnet
|
# edns client subnet
|
||||||
# edns-client-subnet-ipv4 [ip/subnet]
|
# edns-client-subnet [ip/subnet]
|
||||||
# edns-client-subnet-ipv6 [ip/subnet]
|
# edns-client-subnet 192.168.1.1/24
|
||||||
# edns-client-subnet-ipv4 192.168.1.1/24
|
# edns-client-subnet [8::8]/56
|
||||||
|
|
||||||
# ttl for all resource record
|
# ttl for all resource record
|
||||||
# rr-ttl: ttl for all record
|
# rr-ttl: ttl for all record
|
||||||
@@ -94,9 +97,15 @@ log-level info
|
|||||||
# server-tls 1.0.0.1
|
# server-tls 1.0.0.1
|
||||||
|
|
||||||
# specific address to domain
|
# specific address to domain
|
||||||
# address /domain/ip
|
# address /domain/[ip|-|-4|-6|#|#4|#6]
|
||||||
# address /www.example.com/1.2.3.4
|
# address /www.example.com/1.2.3.4, return ip 1.2.3.4 to client
|
||||||
|
# address /www.example.com/-, ignore address, query from upstream, suffix 4, for ipv4, 6 for ipv6, none for all
|
||||||
|
# address /www.example.com/#, return SOA to client, suffix 4, for ipv4, 6 for ipv6, none for all
|
||||||
|
|
||||||
|
# enable ipset timeout by ttl feature
|
||||||
|
# ipset-timeout [yes]
|
||||||
|
|
||||||
# specific ipset to domain
|
# specific ipset to domain
|
||||||
# ipset /domain/ipset
|
# ipset /domain/[ipset|-]
|
||||||
# ipset /www.example.com/block
|
# ipset /www.example.com/block, set ipset with ipset name of block
|
||||||
|
# ipset /www.example.com/-, ignore this domain
|
||||||
40
install
40
install
@@ -4,6 +4,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
INST_DIR=$(cd $(dirname $0);pwd)
|
INST_DIR=$(cd $(dirname $0);pwd)
|
||||||
|
ISWSL=1 # 1 means not WSL, 0 means wsl
|
||||||
|
|
||||||
showhelp()
|
showhelp()
|
||||||
{
|
{
|
||||||
@@ -18,7 +19,7 @@ showhelp()
|
|||||||
start_service()
|
start_service()
|
||||||
{
|
{
|
||||||
if [ $ISSYSTEMD -ne 0 ]; then
|
if [ $ISSYSTEMD -ne 0 ]; then
|
||||||
chkconfig smartdns on
|
chkconfig smartdns on >/dev/null 2>&1
|
||||||
service smartdns start
|
service smartdns start
|
||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
@@ -32,7 +33,7 @@ stop_service()
|
|||||||
{
|
{
|
||||||
if [ $ISSYSTEMD -ne 0 ]; then
|
if [ $ISSYSTEMD -ne 0 ]; then
|
||||||
service smartdns stop
|
service smartdns stop
|
||||||
chkconfig smartdns off
|
chkconfig smartdns off >/dev/null 2>&1
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -101,13 +102,17 @@ install_files()
|
|||||||
uninstall_smartdns()
|
uninstall_smartdns()
|
||||||
{
|
{
|
||||||
if [ -z "$PREFIX" ]; then
|
if [ -z "$PREFIX" ]; then
|
||||||
stop_service
|
stop_service 2>/dev/null
|
||||||
fi
|
fi
|
||||||
rm -f $PREFIX$SMARTDNS_CONF_DIR/smartdns.conf
|
rm -f $PREFIX$SMARTDNS_CONF_DIR/smartdns.conf
|
||||||
rmdir $PREFIX$SMARTDNS_CONF_DIR
|
rmdir $PREFIX$SMARTDNS_CONF_DIR 2>/dev/null
|
||||||
rm -f $PREFIX/usr/sbin/smartdns
|
rm -f $PREFIX/usr/sbin/smartdns
|
||||||
rm -f $PREFIX/etc/default/smartdns
|
rm -f $PREFIX/etc/default/smartdns
|
||||||
|
|
||||||
|
if [ $ISWSL -eq 0 ]; then
|
||||||
|
sed -i '\#%sudo ALL=NOPASSWD: /etc/init.d/smartdns#d' /etc/sudoers 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
if [ $ISSYSTEMD -eq 0 ]; then
|
if [ $ISSYSTEMD -eq 0 ]; then
|
||||||
SYSTEM_UNIT_PATH="`get_systemd_path`"
|
SYSTEM_UNIT_PATH="`get_systemd_path`"
|
||||||
if [ ! -z "$SYSTEM_UNIT_PATH" ]; then
|
if [ ! -z "$SYSTEM_UNIT_PATH" ]; then
|
||||||
@@ -125,6 +130,12 @@ install_smartdns()
|
|||||||
{
|
{
|
||||||
local ret
|
local ret
|
||||||
|
|
||||||
|
which smartdns >/dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo "Already installed."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
install_files
|
install_files
|
||||||
ret=$?
|
ret=$?
|
||||||
if [ $ret -ne 0 ]; then
|
if [ $ret -ne 0 ]; then
|
||||||
@@ -136,17 +147,34 @@ install_smartdns()
|
|||||||
start_service
|
start_service
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $ISWSL -eq 0 ]; then
|
||||||
|
grep "%sudo ALL=NOPASSWD: /etc/init.d/smartdns" /etc/sudoers >/dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "%sudo ALL=NOPASSWD: /etc/init.d/smartdns" >> /etc/sudoers
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init_dir()
|
init_dir()
|
||||||
{
|
{
|
||||||
|
local ID=`id -u`
|
||||||
|
if [ $ID -ne 0 ]; then
|
||||||
|
echo "Please run as root."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
SMARTDNS_CONF_DIR=$PREFIX/etc/smartdns
|
SMARTDNS_CONF_DIR=$PREFIX/etc/smartdns
|
||||||
SMARTDNS_INIT_DIR=$PREFIX/etc/init.d
|
SMARTDNS_INIT_DIR=$PREFIX/etc/init.d
|
||||||
which systemctl >/dev/null 2>&1
|
which systemctl >/dev/null 2>&1
|
||||||
ISSYSTEMD="$?"
|
ISSYSTEMD="$?"
|
||||||
|
# Running under WSL (Windows Subsystem for Linux)?
|
||||||
|
cat /proc/version | grep Microsoft >/dev/null 2>&1;
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
ISSYSTEMD=1
|
||||||
|
ISWSL=0
|
||||||
|
fi
|
||||||
|
|
||||||
cd $INST_DIR
|
cd $INST_DIR
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ msgstr "双栈IP优选"
|
|||||||
msgid "Enable IP selection between IPV4 and IPV6"
|
msgid "Enable IP selection between IPV4 and IPV6"
|
||||||
msgstr "启用或禁用IPV4,IPV6间的IP优选策略。"
|
msgstr "启用或禁用IPV4,IPV6间的IP优选策略。"
|
||||||
|
|
||||||
|
msgid "Domain prefetch"
|
||||||
|
msgstr "域名预加载"
|
||||||
|
|
||||||
|
msgid "Enable domain prefetch, accelerate domain response speed."
|
||||||
|
msgstr "启用域名预加载,加速域名响应速度。"
|
||||||
|
|
||||||
msgid "Redirect"
|
msgid "Redirect"
|
||||||
msgstr "重定向"
|
msgstr "重定向"
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,14 @@ o.cfgvalue = function(...)
|
|||||||
return Flag.cfgvalue(...) or "0"
|
return Flag.cfgvalue(...) or "0"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---- Domain prefetch load
|
||||||
|
o = s:taboption("settings", Flag, "prefetch_domain", translate("Domain prefetch"), translate("Enable domain prefetch, accelerate domain response speed."))
|
||||||
|
o.rmempty = false
|
||||||
|
o.default = o.disabled
|
||||||
|
o.cfgvalue = function(...)
|
||||||
|
return Flag.cfgvalue(...) or "0"
|
||||||
|
end
|
||||||
|
|
||||||
---- Redirect
|
---- Redirect
|
||||||
o = s:taboption("settings", ListValue, "redirect", translate("Redirect"), translate("SmartDNS redirect mode"))
|
o = s:taboption("settings", ListValue, "redirect", translate("Redirect"), translate("SmartDNS redirect mode"))
|
||||||
o.placeholder = "none"
|
o.placeholder = "none"
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ build()
|
|||||||
tar zcf $ROOT/data.tar.gz -C root .
|
tar zcf $ROOT/data.tar.gz -C root .
|
||||||
tar zcf $OUTPUTDIR/luci-app-smartdns.$VER.$ARCH.ipk control.tar.gz data.tar.gz debian-binary
|
tar zcf $OUTPUTDIR/luci-app-smartdns.$VER.$ARCH.ipk control.tar.gz data.tar.gz debian-binary
|
||||||
|
|
||||||
#rm -fr $ROOT/
|
rm -fr $ROOT/
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
# Add domains which you want to force to an IP address here.
|
# Add domains which you want to force to an IP address here.
|
||||||
# The example below send any host in example.com to a local webserver.
|
# The example below send any host in example.com to a local webserver.
|
||||||
# address /example.com/127.0.0.1
|
# address /domain/[ip|-|-4|-6|#|#4|#6]
|
||||||
|
# address /www.example.com/1.2.3.4, return ip 1.2.3.4 to client
|
||||||
|
# address /www.example.com/-, ignore address, query from upstream, suffix 4, for ipv4, 6 for ipv6, none for all
|
||||||
|
# address /www.example.com/#, return SOA to client, suffix 4, for ipv4, 6 for ipv6, none for all
|
||||||
|
|
||||||
|
# specific ipset to domain
|
||||||
|
# ipset /domain/[ipset|-]
|
||||||
|
# ipset /www.example.com/block, set ipset with ipset name of block
|
||||||
|
# ipset /www.example.com/-, ignore this domain
|
||||||
@@ -217,6 +217,11 @@ load_service() {
|
|||||||
conf_append "dualstack-ip-selection" "yes"
|
conf_append "dualstack-ip-selection" "yes"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
config_get "prefetch_domain" "$section" "prefetch_domain" "0"
|
||||||
|
if [ "$prefetch_domain" = "1" ]; then
|
||||||
|
conf_append "prefetch-domain" "yes"
|
||||||
|
fi
|
||||||
|
|
||||||
SMARTDNS_PORT="$port"
|
SMARTDNS_PORT="$port"
|
||||||
|
|
||||||
config_get "cache_size" "$section" "cache_size" ""
|
config_get "cache_size" "$section" "cache_size" ""
|
||||||
|
|||||||
@@ -2,8 +2,20 @@
|
|||||||
|
|
||||||
SMARTDNS_BIN=/opt/usr/sbin/smartdns
|
SMARTDNS_BIN=/opt/usr/sbin/smartdns
|
||||||
SMARTDNS_CONF=/opt/etc/smartdns/smartdns.conf
|
SMARTDNS_CONF=/opt/etc/smartdns/smartdns.conf
|
||||||
|
DNSMASQ_CONF=/etc/dnsmasq.conf
|
||||||
SMARTDNS_PID="/var/run/smartdns.pid"
|
SMARTDNS_PID="/var/run/smartdns.pid"
|
||||||
SMARTDNS_PORT=535
|
SMARTDNS_PORT=535
|
||||||
|
SMARTDNS_OPT=/opt/etc/smartdns/smartdns-opt.conf
|
||||||
|
# workmode
|
||||||
|
# 0: run as port only
|
||||||
|
# 1: redirect port
|
||||||
|
# 2: replace
|
||||||
|
SMARTDNS_WORKMODE="1"
|
||||||
|
|
||||||
|
if [ -f "$SMARTDNS_OPT" ]; then
|
||||||
|
. $SMARTDNS_OPT
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
set_iptable()
|
set_iptable()
|
||||||
{
|
{
|
||||||
@@ -38,16 +50,165 @@ clear_iptable()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restart_dnsmasq()
|
||||||
|
{
|
||||||
|
CMD="`ps | grep " dnsmasq" | grep -v grep`"
|
||||||
|
if [ -z "$CMD" ]; then
|
||||||
|
CMD="`ps ax | grep dnsmasq | grep -v grep`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$CMD" ]; then
|
||||||
|
echo "cannot find dnsmasq"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PID=`echo "$CMD" | awk '{print $1}'`
|
||||||
|
if [ ! -d "/proc/$PID" ]; then
|
||||||
|
echo "dnsmasq is not running"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill -9 $PID
|
||||||
|
|
||||||
|
DNSMASQ_CMD="`echo $CMD | awk '{for(i=5; i<=NF;i++)printf \$i " "}'`"
|
||||||
|
|
||||||
|
$DNSMASQ_CMD
|
||||||
|
}
|
||||||
|
|
||||||
|
get_server_ip()
|
||||||
|
{
|
||||||
|
IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}'`"
|
||||||
|
LOCAL_SERVER_IP=""
|
||||||
|
for IP in $IPS
|
||||||
|
do
|
||||||
|
N=3
|
||||||
|
while [ $N -gt 0 ]
|
||||||
|
do
|
||||||
|
ADDR=`echo $IP | awk -F. "{for(i=1;i<=$N;i++)printf \\$i\".\"}"`
|
||||||
|
grep "dhcp-range=" $DNSMASQ_CONF | grep $ADDR >/dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
SERVER_TAG="`grep "^dhcp-range *=" $DNSMASQ_CONF | grep $ADDR | awk -F= '{print $2}' | awk -F, '{print $1}'`"
|
||||||
|
LOCAL_SERVER_IP="$IP"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
N="`expr $N - 1`"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
set_dnsmasq()
|
||||||
|
{
|
||||||
|
local RESTART_DNSMASQ=0
|
||||||
|
local LOCAL_SERVER_IP=""
|
||||||
|
local SERVER_TAG=""
|
||||||
|
get_server_ip
|
||||||
|
if [ "$LOCAL_SERVER_IP" ] && [ "$SERVER_TAG" ]; then
|
||||||
|
grep "dhcp-option *=" $DNSMASQ_CONF | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $DNSMASQ_CONF
|
||||||
|
echo "dhcp-option=$SERVER_TAG,6,$LOCAL_SERVER_IP" >> $DNSMASQ_CONF
|
||||||
|
RESTART_DNSMASQ=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
grep "^port *=0" $DNSMASQ_CONF > /dev/null 2>&1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
sed -i "/^port *=/d" $DNSMASQ_CONF
|
||||||
|
echo "port=0" >> $DNSMASQ_CONF
|
||||||
|
RESTART_DNSMASQ=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $RESTART_DNSMASQ -ne 0 ]; then
|
||||||
|
restart_dnsmasq
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_dnsmasq()
|
||||||
|
{
|
||||||
|
local RESTART_DNSMASQ=0
|
||||||
|
local LOCAL_SERVER_IP=""
|
||||||
|
local SERVER_TAG=""
|
||||||
|
get_server_ip
|
||||||
|
if [ "$LOCAL_SERVER_IP" ] && [ "$SERVER_TAG" ]; then
|
||||||
|
grep "dhcp-option *=" $DNSMASQ_CONF | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $DNSMASQ_CONF
|
||||||
|
RESTART_DNSMASQ=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
grep "^port *=" $DNSMASQ_CONF > /dev/null 2>&1
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
sed -i "/^port *=/d" $DNSMASQ_CONF
|
||||||
|
RESTART_DNSMASQ=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $RESTART_DNSMASQ -ne 0 ]; then
|
||||||
|
restart_dnsmasq
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set_smartdns_port()
|
||||||
|
{
|
||||||
|
if [ "$SMARTDNS_WORKMODE" = "0" ]; then
|
||||||
|
return 0
|
||||||
|
elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
|
||||||
|
sed -i "s/^\(bind .*\):53 *\(.*\)\$/\1:$SMARTDNS_PORT \2/g" $SMARTDNS_CONF
|
||||||
|
sed -i "s/^\(bind-tcp .*\):53 *\(.*\)\$/\1:$SMARTDNS_PORT \2/g" $SMARTDNS_CONF
|
||||||
|
elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
|
||||||
|
sed -i "s/^\(bind .*\):$SMARTDNS_PORT *\(.*\)\$/\1:53 \2/g" $SMARTDNS_CONF
|
||||||
|
sed -i "s/^\(bind-tcp .*\):$SMARTDNS_PORT *\(.*\)\$/\1:53 \2/g" $SMARTDNS_CONF
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
set_rule()
|
||||||
|
{
|
||||||
|
if [ "$SMARTDNS_WORKMODE" = "0" ]; then
|
||||||
|
return 0
|
||||||
|
elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
|
||||||
|
set_iptable
|
||||||
|
return $?
|
||||||
|
elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
|
||||||
|
set_dnsmasq
|
||||||
|
return $?
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_rule()
|
||||||
|
{
|
||||||
|
if [ "$SMARTDNS_WORKMODE" = "0" ]; then
|
||||||
|
return 0
|
||||||
|
elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
|
||||||
|
clear_iptable
|
||||||
|
return $?
|
||||||
|
elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
|
||||||
|
clear_dnsmasq
|
||||||
|
return $?
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
set_iptable
|
set_rule
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
set_smartdns_port
|
||||||
$SMARTDNS_BIN -c $SMARTDNS_CONF -p $SMARTDNS_PID
|
$SMARTDNS_BIN -c $SMARTDNS_CONF -p $SMARTDNS_PID
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
clear_iptable
|
clear_rule
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
status)
|
status)
|
||||||
@@ -65,7 +226,7 @@ case "$1" in
|
|||||||
return 0;
|
return 0;
|
||||||
;;
|
;;
|
||||||
stop)
|
stop)
|
||||||
clear_iptable
|
clear_rule
|
||||||
pid="`cat $SMARTDNS_PID | head -n 1 2>/dev/null`"
|
pid="`cat $SMARTDNS_PID | head -n 1 2>/dev/null`"
|
||||||
if [ -z "$pid" ]; then
|
if [ -z "$pid" ]; then
|
||||||
echo "smartdns not running."
|
echo "smartdns not running."
|
||||||
@@ -78,7 +239,7 @@ case "$1" in
|
|||||||
|
|
||||||
kill -9 $pid 2>/dev/null
|
kill -9 $pid 2>/dev/null
|
||||||
;;
|
;;
|
||||||
force-reload|restart)
|
restart)
|
||||||
$0 stop
|
$0 stop
|
||||||
$0 start
|
$0 start
|
||||||
;;
|
;;
|
||||||
@@ -89,7 +250,7 @@ case "$1" in
|
|||||||
nvram set apps_state_action=install
|
nvram set apps_state_action=install
|
||||||
nvram set apps_u2ec_ex=2
|
nvram set apps_u2ec_ex=2
|
||||||
;;
|
;;
|
||||||
firewall-start)
|
firewall-start|reload|force-reload|reconfigure)
|
||||||
$0 restart
|
$0 restart
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
/opt/etc/smartdns/smartdns.conf
|
/opt/etc/smartdns/smartdns.conf
|
||||||
|
/opt/etc/smartdns/smartdns-opt.conf
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ VER="`date +"1.%Y.%m.%d-%H%M"`"
|
|||||||
SMARTDNS_DIR=$CURR_DIR/../../
|
SMARTDNS_DIR=$CURR_DIR/../../
|
||||||
SMARTDNS_BIN=$SMARTDNS_DIR/src/smartdns
|
SMARTDNS_BIN=$SMARTDNS_DIR/src/smartdns
|
||||||
SMARTDNS_CONF=$SMARTDNS_DIR/etc/smartdns/smartdns.conf
|
SMARTDNS_CONF=$SMARTDNS_DIR/etc/smartdns/smartdns.conf
|
||||||
|
SMARTDNS_OPT=$CURR_DIR/smartdns-opt.conf
|
||||||
|
|
||||||
showhelp()
|
showhelp()
|
||||||
{
|
{
|
||||||
@@ -29,10 +30,10 @@ build()
|
|||||||
mkdir $ROOT/opt/etc/smartdns/ -p
|
mkdir $ROOT/opt/etc/smartdns/ -p
|
||||||
|
|
||||||
cp $SMARTDNS_CONF $ROOT/opt/etc/smartdns/
|
cp $SMARTDNS_CONF $ROOT/opt/etc/smartdns/
|
||||||
|
cp $SMARTDNS_OPT $ROOT/opt/etc/smartdns/
|
||||||
cp $CURR_DIR/S50smartdns $ROOT/opt/etc/init.d/
|
cp $CURR_DIR/S50smartdns $ROOT/opt/etc/init.d/
|
||||||
cp $SMARTDNS_BIN $ROOT/opt/usr/sbin
|
cp $SMARTDNS_BIN $ROOT/opt/usr/sbin
|
||||||
|
|
||||||
sed -i "s/^\(bind .*\):53/\1:535/g" $ROOT/opt/etc/smartdns/smartdns.conf
|
|
||||||
sed -i "s/# *server-name smartdns/server-name smartdns/g" $ROOT/opt/etc/smartdns/smartdns.conf
|
sed -i "s/# *server-name smartdns/server-name smartdns/g" $ROOT/opt/etc/smartdns/smartdns.conf
|
||||||
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
|
||||||
|
|||||||
8
package/optware/smartdns-opt.conf
Normal file
8
package/optware/smartdns-opt.conf
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# workmode
|
||||||
|
# 0: run as port only
|
||||||
|
# 1: redirect port
|
||||||
|
# 2: replace
|
||||||
|
SMARTDNS_WORKMODE="1"
|
||||||
|
|
||||||
|
# smartdns port
|
||||||
|
SMARTDNS_PORT="535"
|
||||||
21
package/windows/install.bat
Normal file
21
package/windows/install.bat
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
@echo off
|
||||||
|
set "CURR_PATH=%~dp0"
|
||||||
|
set "STARTUP_PATH=%userprofile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
|
||||||
|
FOR /F %%i IN ('wsl pwd') DO @set DIR_IN_WSL=%%i
|
||||||
|
|
||||||
|
wsl sudo %DIR_IN_WSL%/../../install -i
|
||||||
|
IF NOT %ERRORLEVEL% == 0 (
|
||||||
|
echo Install smartdns failed.
|
||||||
|
pause
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
copy %CURR_PATH%\wsl-run.vbs "%STARTUP_PATH%/"
|
||||||
|
IF NOT %ERRORLEVEL% == 0 (
|
||||||
|
echo Install startupt script failed.
|
||||||
|
pause
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Install smartdns success
|
||||||
|
pause
|
||||||
21
package/windows/reload.bat
Normal file
21
package/windows/reload.bat
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
@echo off
|
||||||
|
set "CURR_PATH=%~dp0"
|
||||||
|
set "STARTUP_PATH=%userprofile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
|
||||||
|
FOR /F %%i IN ('wsl pwd') DO @set DIR_IN_WSL=%%i
|
||||||
|
|
||||||
|
wsl sudo cp -avf %DIR_IN_WSL%/../../etc/smartdns/* /etc/smartdns/
|
||||||
|
IF NOT %ERRORLEVEL% == 0 (
|
||||||
|
echo copy smartdns configuration file failed.
|
||||||
|
pause
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
wsl sudo /etc/init.d/smartdns restart
|
||||||
|
IF NOT %ERRORLEVEL% == 0 (
|
||||||
|
echo reload smartdns failed.
|
||||||
|
pause
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo reload smartdns success
|
||||||
|
pause
|
||||||
22
package/windows/uninstall.bat
Normal file
22
package/windows/uninstall.bat
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
@echo off
|
||||||
|
set "CURR_PATH=%~dp0"
|
||||||
|
set "STARTUP_PATH=%userprofile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"
|
||||||
|
FOR /F %%i IN ('wsl pwd') DO @set DIR_IN_WSL=%%i
|
||||||
|
|
||||||
|
wsl sudo %DIR_IN_WSL%/../../install -u
|
||||||
|
IF NOT %ERRORLEVEL% == 0 (
|
||||||
|
echo Uninstall smartdns failed.
|
||||||
|
pause
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
del "%STARTUP_PATH%\wsl-run.vbs"
|
||||||
|
IF NOT %ERRORLEVEL% == 0 (
|
||||||
|
echo Uninstall startup script failed.
|
||||||
|
pause
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo uninstall success
|
||||||
|
|
||||||
|
pause
|
||||||
2
package/windows/wsl-run.vbs
Normal file
2
package/windows/wsl-run.vbs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Set ws = WScript.CreateObject("WScript.Shell")
|
||||||
|
ws.run "wsl sudo /etc/init.d/smartdns restart", vbhide
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
BIN=smartdns
|
BIN=smartdns
|
||||||
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o
|
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o
|
||||||
OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o $(OBJS_LIB)
|
OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o $(OBJS_LIB)
|
||||||
CFLAGS +=-O2 -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing
|
CFLAGS +=-O2 -g -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing
|
||||||
CFLAGS +=-Iinclude
|
CFLAGS +=-Iinclude
|
||||||
CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\"
|
CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\"
|
||||||
CXXFLAGS=-O2 -Wall -std=c++11
|
CXXFLAGS=-O2 -g -Wall -std=c++11
|
||||||
CXXFLAGS +=-Iinclude
|
CXXFLAGS +=-Iinclude
|
||||||
LDFLAGS += -lpthread -lssl -lcrypto
|
LDFLAGS += -lpthread -lssl -lcrypto
|
||||||
|
|
||||||
|
|||||||
62
src/dns.c
62
src/dns.c
@@ -144,8 +144,8 @@ unsigned char *_dns_add_rrs_start(struct dns_packet *packet, int *maxlen)
|
|||||||
unsigned char *end = packet->data + packet->len;
|
unsigned char *end = packet->data + packet->len;
|
||||||
|
|
||||||
rrs = (struct dns_rrs *)end;
|
rrs = (struct dns_rrs *)end;
|
||||||
*maxlen = packet->size - packet->len - sizeof(*packet);
|
*maxlen = packet->size - packet->len - sizeof(*packet) - sizeof(*rrs);
|
||||||
if (packet->len >= packet->size - sizeof(*packet)) {
|
if (*maxlen <= 0) {
|
||||||
/* if size exceeds max packet size, return NULL */
|
/* if size exceeds max packet size, return NULL */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ int dns_rr_add_end(struct dns_packet *packet, int type, dns_type_t rtype, int le
|
|||||||
unsigned short *start;
|
unsigned short *start;
|
||||||
|
|
||||||
rrs = (struct dns_rrs *)end;
|
rrs = (struct dns_rrs *)end;
|
||||||
if (packet->len + len > packet->size - sizeof(*packet)) {
|
if (packet->len + len > packet->size - sizeof(*packet) - sizeof(*rrs)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ int _dns_add_qr_head(struct dns_data_context *data_context, char *domain, int qt
|
|||||||
* |qtype | qclass |
|
* |qtype | qclass |
|
||||||
*/
|
*/
|
||||||
while (1) {
|
while (1) {
|
||||||
if (_dns_data_left_len(data_context) < 1) {
|
if (_dns_data_left_len(data_context) < 4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*data_context->ptr = *domain;
|
*data_context->ptr = *domain;
|
||||||
@@ -259,8 +259,8 @@ int _dns_get_qr_head(struct dns_data_context *data_context, char *domain, int ma
|
|||||||
/* |domain |
|
/* |domain |
|
||||||
* |qtype | qclass |
|
* |qtype | qclass |
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < maxsize; i++) {
|
for (i = 0; i < maxsize - 1; i++) {
|
||||||
if (_dns_data_left_len(data_context) < 1) {
|
if (_dns_data_left_len(data_context) < 4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*domain = *data_context->ptr;
|
*domain = *data_context->ptr;
|
||||||
@@ -275,6 +275,8 @@ int _dns_get_qr_head(struct dns_data_context *data_context, char *domain, int ma
|
|||||||
data_context->ptr++;
|
data_context->ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*domain = '\0';
|
||||||
|
|
||||||
if (_dns_data_left_len(data_context) < 4) {
|
if (_dns_data_left_len(data_context) < 4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -841,10 +843,11 @@ static int _dns_decode_domain(struct dns_context *context, char *output, int siz
|
|||||||
int len = *(context->ptr);
|
int len = *(context->ptr);
|
||||||
unsigned char *ptr = context->ptr;
|
unsigned char *ptr = context->ptr;
|
||||||
int is_compressed = 0;
|
int is_compressed = 0;
|
||||||
|
int ptr_jump = 0;
|
||||||
|
|
||||||
/*[len]string[len]string...[0]0 */
|
/*[len]string[len]string...[0]0 */
|
||||||
while (1) {
|
while (1) {
|
||||||
if (ptr > context->data + context->maxsize || ptr < context->data) {
|
if (ptr > context->data + context->maxsize || ptr < context->data || output_len >= size - 1 || ptr_jump > 4) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,13 +880,17 @@ static int _dns_decode_domain(struct dns_context *context, char *output, int siz
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
is_compressed = 1;
|
is_compressed = 1;
|
||||||
|
ptr_jump++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptr_jump = 0;
|
||||||
|
|
||||||
/* change [len] to '.' */
|
/* change [len] to '.' */
|
||||||
if (output_len > 0) {
|
if (output_len > 0) {
|
||||||
*output = '.';
|
*output = '.';
|
||||||
output++;
|
output++;
|
||||||
|
output_len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr > context->data + context->maxsize) {
|
if (ptr > context->data + context->maxsize) {
|
||||||
@@ -1422,6 +1429,12 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
|
|||||||
}
|
}
|
||||||
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);
|
||||||
|
|
||||||
|
if (_dns_left_len(context) < opt_len) {
|
||||||
|
tlog(TLOG_ERROR, "read opt data failed, opt_code = %d, opt_le = %d", opt_code, opt_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
tlog(TLOG_DEBUG, "opt type %d", opt_code);
|
tlog(TLOG_DEBUG, "opt type %d", opt_code);
|
||||||
switch (opt_code) {
|
switch (opt_code) {
|
||||||
case DNS_OPT_T_ECS: {
|
case DNS_OPT_T_ECS: {
|
||||||
@@ -1586,6 +1599,10 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
|
|||||||
dns_set_OPT_payload_size(packet, qclass);
|
dns_set_OPT_payload_size(packet, qclass);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
|
if (_dns_left_len(context) < rr_len) {
|
||||||
|
tlog(TLOG_DEBUG, "length mitchmatch\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
context->ptr += rr_len;
|
context->ptr += rr_len;
|
||||||
tlog(TLOG_DEBUG, "DNS type = %d not supported", qtype);
|
tlog(TLOG_DEBUG, "DNS type = %d not supported", qtype);
|
||||||
break;
|
break;
|
||||||
@@ -1661,41 +1678,46 @@ static int _dns_decode_body(struct dns_context *context)
|
|||||||
struct dns_head *head = &packet->head;
|
struct dns_head *head = &packet->head;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
for (i = 0; i < head->qdcount; i++) {
|
count = head->qdcount;
|
||||||
|
head->qdcount = 0;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
ret = _dns_decode_qd(context);
|
ret = _dns_decode_qd(context);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
tlog(TLOG_DEBUG, "decode qd failed.");
|
tlog(TLOG_DEBUG, "decode qd failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
head->qdcount--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < head->ancount; i++) {
|
count = head->ancount;
|
||||||
|
head->ancount = 0;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
ret = _dns_decode_an(context, DNS_RRS_AN);
|
ret = _dns_decode_an(context, DNS_RRS_AN);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
tlog(TLOG_DEBUG, "decode an failed.");
|
tlog(TLOG_DEBUG, "decode an failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
head->ancount--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < head->nscount; i++) {
|
count = head->nscount;
|
||||||
|
head->nscount = 0;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
ret = _dns_decode_an(context, DNS_RRS_NS);
|
ret = _dns_decode_an(context, DNS_RRS_NS);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
tlog(TLOG_DEBUG, "decode ns failed.");
|
tlog(TLOG_DEBUG, "decode ns failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
head->nscount--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < head->nrcount; i++) {
|
count = head->nrcount;
|
||||||
|
head->nrcount = 0;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
ret = _dns_decode_an(context, DNS_RRS_NR);
|
ret = _dns_decode_an(context, DNS_RRS_NR);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
tlog(TLOG_DEBUG, "decode nr failed.");
|
tlog(TLOG_DEBUG, "decode nr failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
head->nrcount--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1761,6 +1783,10 @@ static int _dns_encode_body(struct dns_context *context)
|
|||||||
int dns_packet_init(struct dns_packet *packet, int size, struct dns_head *head)
|
int dns_packet_init(struct dns_packet *packet, int size, struct dns_head *head)
|
||||||
{
|
{
|
||||||
struct dns_head *init_head = &packet->head;
|
struct dns_head *init_head = &packet->head;
|
||||||
|
if (size < sizeof(*packet)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(packet, 0, size);
|
memset(packet, 0, size);
|
||||||
packet->size = size;
|
packet->size = size;
|
||||||
init_head->id = head->id;
|
init_head->id = head->id;
|
||||||
@@ -1796,7 +1822,11 @@ int dns_decode(struct dns_packet *packet, int maxsize, unsigned char *data, int
|
|||||||
context.ptr = data;
|
context.ptr = data;
|
||||||
context.maxsize = size;
|
context.maxsize = size;
|
||||||
|
|
||||||
dns_packet_init(packet, maxsize, head);
|
ret = dns_packet_init(packet, maxsize, head);
|
||||||
|
if (ret != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ret = _dns_decode_head(&context);
|
ret = _dns_decode_head(&context);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ struct dns_cache *_dns_cache_last(void)
|
|||||||
|
|
||||||
struct dns_cache *_dns_cache_first(void)
|
struct dns_cache *_dns_cache_first(void)
|
||||||
{
|
{
|
||||||
return list_first_entry(&dns_cache_head.cache_list, struct dns_cache, list);
|
return list_first_entry_or_null(&dns_cache_head.cache_list, struct dns_cache, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dns_cache_delete(struct dns_cache *dns_cache)
|
void _dns_cache_delete(struct dns_cache *dns_cache)
|
||||||
@@ -59,6 +59,13 @@ void dns_cache_release(struct dns_cache *dns_cache)
|
|||||||
_dns_cache_delete(dns_cache);
|
_dns_cache_delete(dns_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _dns_cache_remove(struct dns_cache *dns_cache)
|
||||||
|
{
|
||||||
|
hash_del(&dns_cache->node);
|
||||||
|
list_del_init(&dns_cache->list);
|
||||||
|
dns_cache_release(dns_cache);
|
||||||
|
}
|
||||||
|
|
||||||
int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len)
|
int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len)
|
||||||
{
|
{
|
||||||
struct dns_cache *dns_cache = NULL;
|
struct dns_cache *dns_cache = NULL;
|
||||||
@@ -72,10 +79,17 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ttl < DNS_CACHE_TTL_MIN) {
|
||||||
|
ttl = DNS_CACHE_TTL_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&dns_cache_head.lock);
|
||||||
dns_cache->ttl = ttl;
|
dns_cache->ttl = ttl;
|
||||||
dns_cache->qtype = qtype;
|
dns_cache->qtype = qtype;
|
||||||
dns_cache->ttl = ttl;
|
dns_cache->ttl = ttl;
|
||||||
|
dns_cache->del_pending = 0;
|
||||||
time(&dns_cache->insert_time);
|
time(&dns_cache->insert_time);
|
||||||
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
if (qtype == DNS_T_A) {
|
if (qtype == DNS_T_A) {
|
||||||
if (addr_len != DNS_RR_A_LEN) {
|
if (addr_len != DNS_RR_A_LEN) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -116,6 +130,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
|
|||||||
|
|
||||||
dns_cache = dns_cache_lookup(domain, qtype);
|
dns_cache = dns_cache_lookup(domain, qtype);
|
||||||
if (dns_cache) {
|
if (dns_cache) {
|
||||||
|
dns_cache_delete(dns_cache);
|
||||||
dns_cache_release(dns_cache);
|
dns_cache_release(dns_cache);
|
||||||
dns_cache = NULL;
|
dns_cache = NULL;
|
||||||
}
|
}
|
||||||
@@ -125,12 +140,18 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ttl < DNS_CACHE_TTL_MIN) {
|
||||||
|
ttl = DNS_CACHE_TTL_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
key = hash_string(domain);
|
key = hash_string(domain);
|
||||||
key = jhash(&qtype, sizeof(qtype), key);
|
key = jhash(&qtype, sizeof(qtype), key);
|
||||||
strncpy(dns_cache->domain, domain, DNS_MAX_CNAME_LEN);
|
strncpy(dns_cache->domain, domain, DNS_MAX_CNAME_LEN);
|
||||||
dns_cache->cname[0] = 0;
|
dns_cache->cname[0] = 0;
|
||||||
dns_cache->qtype = qtype;
|
dns_cache->qtype = qtype;
|
||||||
dns_cache->ttl = ttl;
|
dns_cache->ttl = ttl;
|
||||||
|
dns_cache->hitnum = 2;
|
||||||
|
dns_cache->del_pending = 0;
|
||||||
atomic_set(&dns_cache->ref, 1);
|
atomic_set(&dns_cache->ref, 1);
|
||||||
time(&dns_cache->insert_time);
|
time(&dns_cache->insert_time);
|
||||||
if (qtype == DNS_T_A) {
|
if (qtype == DNS_T_A) {
|
||||||
@@ -161,7 +182,9 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
|
|||||||
if (dns_cache_head.num > dns_cache_head.size) {
|
if (dns_cache_head.num > dns_cache_head.size) {
|
||||||
struct dns_cache *del_cache;
|
struct dns_cache *del_cache;
|
||||||
del_cache = _dns_cache_first();
|
del_cache = _dns_cache_first();
|
||||||
dns_cache_release(del_cache);
|
if (del_cache) {
|
||||||
|
_dns_cache_remove(del_cache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
|
|
||||||
@@ -206,10 +229,10 @@ struct dns_cache *dns_cache_lookup(char *domain, dns_type_t qtype)
|
|||||||
|
|
||||||
if (dns_cache_ret) {
|
if (dns_cache_ret) {
|
||||||
if (now - dns_cache_ret->insert_time > dns_cache_ret->ttl) {
|
if (now - dns_cache_ret->insert_time > dns_cache_ret->ttl) {
|
||||||
_dns_cache_delete(dns_cache_ret);
|
_dns_cache_remove(dns_cache_ret);
|
||||||
dns_cache_ret = NULL;
|
dns_cache_ret = NULL;
|
||||||
} else {
|
} else {
|
||||||
atomic_inc(&dns_cache_ret->ref);
|
dns_cache_get(dns_cache_ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,10 +258,8 @@ int dns_cache_get_ttl(struct dns_cache *dns_cache)
|
|||||||
void dns_cache_delete(struct dns_cache *dns_cache)
|
void dns_cache_delete(struct dns_cache *dns_cache)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&dns_cache_head.lock);
|
pthread_mutex_lock(&dns_cache_head.lock);
|
||||||
hash_del(&dns_cache->node);
|
_dns_cache_remove(dns_cache);
|
||||||
list_del_init(&dns_cache->list);
|
|
||||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
dns_cache_release(dns_cache);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dns_cache_update(struct dns_cache *dns_cache)
|
void dns_cache_update(struct dns_cache *dns_cache)
|
||||||
@@ -247,6 +268,7 @@ void dns_cache_update(struct dns_cache *dns_cache)
|
|||||||
if (!list_empty(&dns_cache->list)) {
|
if (!list_empty(&dns_cache->list)) {
|
||||||
list_del_init(&dns_cache->list);
|
list_del_init(&dns_cache->list);
|
||||||
list_add_tail(&dns_cache->list, &dns_cache_head.cache_list);
|
list_add_tail(&dns_cache->list, &dns_cache_head.cache_list);
|
||||||
|
dns_cache->hitnum++;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
}
|
}
|
||||||
@@ -268,31 +290,26 @@ void dns_cache_invalidate(dns_cache_preinvalid_callback callback, int ttl_pre)
|
|||||||
list_for_each_entry_safe(dns_cache, tmp, &dns_cache_head.cache_list, list)
|
list_for_each_entry_safe(dns_cache, tmp, &dns_cache_head.cache_list, list)
|
||||||
{
|
{
|
||||||
ttl = dns_cache->insert_time + dns_cache->ttl - now;
|
ttl = dns_cache->insert_time + dns_cache->ttl - now;
|
||||||
if (ttl > 0) {
|
if (ttl > 0 && ttl < ttl_pre) {
|
||||||
if (ttl < ttl_pre) {
|
if (callback && dns_cache->del_pending == 0) {
|
||||||
if (callback) {
|
list_add_tail(&dns_cache->check_list, &checklist);
|
||||||
list_add_tail(&dns_cache->check_list, &checklist);
|
dns_cache_get(dns_cache);
|
||||||
dns_cache_get(dns_cache);
|
dns_cache->del_pending = 1;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callback) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_del(&dns_cache->node);
|
if (ttl < 0) {
|
||||||
list_del_init(&dns_cache->list);
|
_dns_cache_remove(dns_cache);
|
||||||
dns_cache_release(dns_cache);
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||||
|
|
||||||
list_for_each_entry_safe(dns_cache, tmp, &checklist, check_list)
|
list_for_each_entry_safe(dns_cache, tmp, &checklist, check_list)
|
||||||
{
|
{
|
||||||
callback(dns_cache);
|
if (callback) {
|
||||||
list_del_init(&dns_cache->check_list);
|
callback(dns_cache);
|
||||||
|
}
|
||||||
dns_cache_release(dns_cache);
|
dns_cache_release(dns_cache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#define DNS_CACHE_TTL_MIN 30
|
||||||
|
|
||||||
struct dns_cache {
|
struct dns_cache {
|
||||||
struct hlist_node node;
|
struct hlist_node node;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -17,6 +19,8 @@ struct dns_cache {
|
|||||||
char cname[DNS_MAX_CNAME_LEN];
|
char cname[DNS_MAX_CNAME_LEN];
|
||||||
unsigned int cname_ttl;
|
unsigned int cname_ttl;
|
||||||
unsigned int ttl;
|
unsigned int ttl;
|
||||||
|
int hitnum;
|
||||||
|
int del_pending;
|
||||||
time_t insert_time;
|
time_t insert_time;
|
||||||
dns_type_t qtype;
|
dns_type_t qtype;
|
||||||
union {
|
union {
|
||||||
|
|||||||
728
src/dns_client.c
728
src/dns_client.c
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ typedef enum {
|
|||||||
DNS_SERVER_UDP,
|
DNS_SERVER_UDP,
|
||||||
DNS_SERVER_TCP,
|
DNS_SERVER_TCP,
|
||||||
DNS_SERVER_TLS,
|
DNS_SERVER_TLS,
|
||||||
|
DNS_SERVER_HTTPS,
|
||||||
DNS_SERVER_TYPE_END,
|
DNS_SERVER_TYPE_END,
|
||||||
} dns_server_type_t;
|
} dns_server_type_t;
|
||||||
|
|
||||||
|
|||||||
275
src/dns_conf.c
275
src/dns_conf.c
@@ -8,6 +8,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
#define DEFAULT_DNS_CACHE_SIZE 512
|
#define DEFAULT_DNS_CACHE_SIZE 512
|
||||||
|
|
||||||
@@ -34,16 +35,18 @@ size_t dns_conf_audit_size = 1024 * 1024;
|
|||||||
int dns_conf_audit_num = 2;
|
int dns_conf_audit_num = 2;
|
||||||
|
|
||||||
art_tree dns_conf_domain_rule;
|
art_tree dns_conf_domain_rule;
|
||||||
radix_tree_t *dns_conf_address_rule;
|
struct dns_conf_address_rule dns_conf_address_rule;
|
||||||
|
|
||||||
int dns_conf_dualstack_ip_selection;
|
int dns_conf_dualstack_ip_selection;
|
||||||
int dns_conf_dualstack_ip_selection_threshold = 100;
|
int dns_conf_dualstack_ip_selection_threshold = 30;
|
||||||
|
|
||||||
int dns_conf_rr_ttl;
|
int dns_conf_rr_ttl;
|
||||||
int dns_conf_rr_ttl_min;
|
int dns_conf_rr_ttl_min;
|
||||||
int dns_conf_rr_ttl_max;
|
int dns_conf_rr_ttl_max;
|
||||||
int dns_conf_force_AAAA_SOA;
|
int dns_conf_force_AAAA_SOA;
|
||||||
|
|
||||||
|
int dns_conf_ipset_timeout_enable;
|
||||||
|
|
||||||
struct dns_edns_client_subnet dns_conf_ipv4_ecs;
|
struct dns_edns_client_subnet dns_conf_ipv4_ecs;
|
||||||
struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
||||||
|
|
||||||
@@ -92,7 +95,7 @@ int config_server(int argc, char *argv[], dns_server_type_t type, int default_po
|
|||||||
}
|
}
|
||||||
|
|
||||||
ttl = atoi(optarg);
|
ttl = atoi(optarg);
|
||||||
if (ttl < 0 || ttl > 255) {
|
if (ttl < -255 || ttl > 255) {
|
||||||
tlog(TLOG_ERROR, "ttl value is invalid.");
|
tlog(TLOG_ERROR, "ttl value is invalid.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -213,7 +216,59 @@ errout:
|
|||||||
free(add_domain_rule);
|
free(add_domain_rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog(TLOG_ERROR, "add doamin %s failed", domain);
|
tlog(TLOG_ERROR, "add doamin %s rule failed", domain);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_domain_rule_flag_set(char *domain, unsigned int flag)
|
||||||
|
{
|
||||||
|
struct dns_domain_rule *domain_rule = NULL;
|
||||||
|
struct dns_domain_rule *old_domain_rule = NULL;
|
||||||
|
struct dns_domain_rule *add_domain_rule = NULL;
|
||||||
|
struct dns_rule_flags *rule_flags = NULL;
|
||||||
|
|
||||||
|
char domain_key[DNS_MAX_CONF_CNAME_LEN];
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
len = strlen(domain);
|
||||||
|
reverse_string(domain_key, domain, len);
|
||||||
|
domain_key[len] = '.';
|
||||||
|
len++;
|
||||||
|
domain_key[len] = 0;
|
||||||
|
|
||||||
|
domain_rule = art_search(&dns_conf_domain_rule, (unsigned char *)domain_key, len);
|
||||||
|
if (domain_rule == NULL) {
|
||||||
|
add_domain_rule = malloc(sizeof(*add_domain_rule));
|
||||||
|
if (add_domain_rule == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
memset(add_domain_rule, 0, sizeof(*add_domain_rule));
|
||||||
|
domain_rule = add_domain_rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (domain_rule->rules[DOMAIN_RULE_FLAGS] == NULL) {
|
||||||
|
rule_flags = malloc(sizeof(*rule_flags));
|
||||||
|
rule_flags->flags = 0;
|
||||||
|
domain_rule->rules[DOMAIN_RULE_FLAGS] = rule_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_flags = domain_rule->rules[DOMAIN_RULE_FLAGS];
|
||||||
|
rule_flags->flags |= flag;
|
||||||
|
|
||||||
|
if (add_domain_rule) {
|
||||||
|
old_domain_rule = art_insert(&dns_conf_domain_rule, (unsigned char *)domain_key, len, add_domain_rule);
|
||||||
|
if (old_domain_rule) {
|
||||||
|
free(old_domain_rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
errout:
|
||||||
|
if (add_domain_rule) {
|
||||||
|
free(add_domain_rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
tlog(TLOG_ERROR, "add doamin %s rule failed", domain);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,18 +356,26 @@ int config_ipset(void *data, int argc, char *argv[])
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
|
if (strncmp(end + 1, "-", sizeof("-")) != 0) {
|
||||||
ipset = dns_conf_get_ipset(ipsetname);
|
strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
|
||||||
if (ipset == NULL) {
|
ipset = dns_conf_get_ipset(ipsetname);
|
||||||
goto errout;
|
if (ipset == NULL) {
|
||||||
}
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
ipset_rule = malloc(sizeof(*ipset_rule));
|
ipset_rule = malloc(sizeof(*ipset_rule));
|
||||||
if (ipset_rule == NULL) {
|
if (ipset_rule == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ipset_rule->ipsetname = ipset;
|
ipset_rule->ipsetname = ipset;
|
||||||
|
} else {
|
||||||
|
if (config_domain_rule_flag_set(domain, DOMAIN_FLAG_IPSET_IGNORE) != 0 ) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (config_domain_rule_add(domain, DOMAIN_RULE_IPSET, ipset_rule) != 0) {
|
if (config_domain_rule_add(domain, DOMAIN_RULE_IPSET, ipset_rule) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -343,6 +406,7 @@ int config_address(void *data, int argc, char *argv[])
|
|||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
enum domain_rule type = 0;
|
enum domain_rule type = 0;
|
||||||
|
unsigned int flag = 0;
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -368,51 +432,85 @@ int config_address(void *data, int argc, char *argv[])
|
|||||||
memcpy(domain, begin, len);
|
memcpy(domain, begin, len);
|
||||||
domain[len] = 0;
|
domain[len] = 0;
|
||||||
|
|
||||||
if (parse_ip(end + 1, ip, &port) != 0) {
|
if (*(end + 1) == '#') {
|
||||||
goto errout;
|
if (strncmp(end + 1, "#4", sizeof("#4")) == 0) {
|
||||||
}
|
flag = DOMAIN_FLAG_ADDR_IPV4_SOA;
|
||||||
|
} else if (strncmp(end + 1, "#6", sizeof("#6")) == 0) {
|
||||||
if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
|
flag = DOMAIN_FLAG_ADDR_IPV6_SOA;
|
||||||
goto errout;
|
} else if (strncmp(end + 1, "#", sizeof("#")) == 0) {
|
||||||
}
|
flag = DOMAIN_FLAG_ADDR_SOA;
|
||||||
|
} else {
|
||||||
switch (addr.ss_family) {
|
|
||||||
case AF_INET: {
|
|
||||||
struct sockaddr_in *addr_in;
|
|
||||||
address_ipv4 = malloc(sizeof(*address_ipv4));
|
|
||||||
if (address_ipv4 == NULL) {
|
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_in = (struct sockaddr_in *)&addr;
|
if (config_domain_rule_flag_set(domain, flag) != 0 ) {
|
||||||
memcpy(address_ipv4->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
goto errout;
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV4;
|
}
|
||||||
address = address_ipv4;
|
|
||||||
} break;
|
return 0;
|
||||||
case AF_INET6: {
|
} else if (*(end + 1) == '-') {
|
||||||
struct sockaddr_in6 *addr_in6;
|
if (strncmp(end + 1, "-4", sizeof("-4")) == 0) {
|
||||||
addr_in6 = (struct sockaddr_in6 *)&addr;
|
flag = DOMAIN_FLAG_ADDR_IPV4_IGN;
|
||||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
} else if (strncmp(end + 1, "-6", sizeof("-6")) == 0) {
|
||||||
|
flag = DOMAIN_FLAG_ADDR_IPV6_IGN;
|
||||||
|
} else if (strncmp(end + 1, "-", sizeof("-")) == 0) {
|
||||||
|
flag = DOMAIN_FLAG_ADDR_IGN;
|
||||||
|
} else {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_domain_rule_flag_set(domain, flag) != 0 ) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if (parse_ip(end + 1, ip, &port) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len) != 0) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (addr.ss_family) {
|
||||||
|
case AF_INET: {
|
||||||
|
struct sockaddr_in *addr_in;
|
||||||
address_ipv4 = malloc(sizeof(*address_ipv4));
|
address_ipv4 = malloc(sizeof(*address_ipv4));
|
||||||
if (address_ipv4 == NULL) {
|
if (address_ipv4 == NULL) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
memcpy(address_ipv4->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
|
||||||
|
addr_in = (struct sockaddr_in *)&addr;
|
||||||
|
memcpy(address_ipv4->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV4;
|
type = DOMAIN_RULE_ADDRESS_IPV4;
|
||||||
address = address_ipv4;
|
address = address_ipv4;
|
||||||
} else {
|
} break;
|
||||||
address_ipv6 = malloc(sizeof(*address_ipv6));
|
case AF_INET6: {
|
||||||
if (address_ipv6 == NULL) {
|
struct sockaddr_in6 *addr_in6;
|
||||||
goto errout;
|
addr_in6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||||
|
address_ipv4 = malloc(sizeof(*address_ipv4));
|
||||||
|
if (address_ipv4 == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
memcpy(address_ipv4->ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||||
|
type = DOMAIN_RULE_ADDRESS_IPV4;
|
||||||
|
address = address_ipv4;
|
||||||
|
} else {
|
||||||
|
address_ipv6 = malloc(sizeof(*address_ipv6));
|
||||||
|
if (address_ipv6 == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
memcpy(address_ipv6->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||||
|
type = DOMAIN_RULE_ADDRESS_IPV6;
|
||||||
|
address = address_ipv6;
|
||||||
}
|
}
|
||||||
memcpy(address_ipv6->ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
} break;
|
||||||
type = DOMAIN_RULE_ADDRESS_IPV6;
|
default:
|
||||||
address = address_ipv6;
|
goto errout;
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
default:
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_domain_rule_add(domain, type, address) != 0) {
|
if (config_domain_rule_add(domain, type, address) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -443,18 +541,28 @@ int config_server_tls(void *data, int argc, char *argv[])
|
|||||||
return config_server(argc, argv, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT);
|
return config_server(argc, argv, DNS_SERVER_TLS, DEFAULT_DNS_TLS_PORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
radix_node_t *create_addr_node(radix_tree_t *tree, char *addr)
|
radix_node_t *create_addr_node(char *addr)
|
||||||
{
|
{
|
||||||
radix_node_t *node;
|
radix_node_t *node;
|
||||||
void *p;
|
void *p;
|
||||||
prefix_t prefix;
|
prefix_t prefix;
|
||||||
const char *errmsg = NULL;
|
const char *errmsg = NULL;
|
||||||
|
radix_tree_t *tree = NULL;
|
||||||
|
|
||||||
p = prefix_pton(addr, -1, &prefix, &errmsg);
|
p = prefix_pton(addr, -1, &prefix, &errmsg);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (prefix.family) {
|
||||||
|
case AF_INET:
|
||||||
|
tree = dns_conf_address_rule.ipv4;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
tree = dns_conf_address_rule.ipv6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
node = radix_lookup(tree, &prefix);
|
node = radix_lookup(tree, &prefix);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -464,7 +572,7 @@ int config_iplist_rule(char *subnet, enum address_rule rule)
|
|||||||
radix_node_t *node = NULL;
|
radix_node_t *node = NULL;
|
||||||
struct dns_ip_address_rule *ip_rule = NULL;
|
struct dns_ip_address_rule *ip_rule = NULL;
|
||||||
|
|
||||||
node = create_addr_node(dns_conf_address_rule, subnet);
|
node = create_addr_node(subnet);
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -488,6 +596,8 @@ int config_iplist_rule(char *subnet, enum address_rule rule)
|
|||||||
case ADDRESS_RULE_BOGUS:
|
case ADDRESS_RULE_BOGUS:
|
||||||
ip_rule->bogus = 1;
|
ip_rule->bogus = 1;
|
||||||
break;
|
break;
|
||||||
|
case ADDRESS_RULE_IP_IGNORE:
|
||||||
|
ip_rule->ip_ignore = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -511,12 +621,21 @@ int conf_bogus_nxdomain(void *data, int argc, char *argv[])
|
|||||||
return config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS);
|
return config_iplist_rule(argv[1], ADDRESS_RULE_BOGUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int conf_ip_ignore(void *data, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc <= 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config_iplist_rule(argv[1], ADDRESS_RULE_IP_IGNORE);
|
||||||
|
}
|
||||||
|
|
||||||
int conf_edns_client_subnet(void *data, int argc, char *argv[])
|
int conf_edns_client_subnet(void *data, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *slash = NULL;
|
char *slash = NULL;
|
||||||
char *value = NULL;
|
char *value = NULL;
|
||||||
int subnet = 0;
|
int subnet = 0;
|
||||||
struct dns_edns_client_subnet *ecs = data;
|
struct dns_edns_client_subnet *ecs = NULL;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
|
||||||
@@ -540,6 +659,17 @@ int conf_edns_client_subnet(void *data, int argc, char *argv[])
|
|||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (addr.ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
ecs = &dns_conf_ipv4_ecs;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
ecs = &dns_conf_ipv6_ecs;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
strncpy(ecs->ip, value, DNS_MAX_IPLEN);
|
strncpy(ecs->ip, value, DNS_MAX_IPLEN);
|
||||||
ecs->subnet = subnet;
|
ecs->subnet = subnet;
|
||||||
ecs->enable = 1;
|
ecs->enable = 1;
|
||||||
@@ -578,12 +708,13 @@ struct config_item config_item[] = {
|
|||||||
CONF_CUSTOM("server-tcp", config_server_tcp, NULL),
|
CONF_CUSTOM("server-tcp", config_server_tcp, NULL),
|
||||||
CONF_CUSTOM("server-tls", config_server_tls, NULL),
|
CONF_CUSTOM("server-tls", config_server_tls, NULL),
|
||||||
CONF_CUSTOM("address", config_address, NULL),
|
CONF_CUSTOM("address", config_address, NULL),
|
||||||
|
CONF_YESNO("ipset-timeout", &dns_conf_ipset_timeout_enable),
|
||||||
CONF_CUSTOM("ipset", config_ipset, NULL),
|
CONF_CUSTOM("ipset", config_ipset, NULL),
|
||||||
CONF_INT("tcp-idle-time", &dns_conf_tcp_idle_time, 0, 3600),
|
CONF_INT("tcp-idle-time", &dns_conf_tcp_idle_time, 0, 3600),
|
||||||
CONF_INT("cache-size", &dns_conf_cachesize, 0, CONF_INT_MAX),
|
CONF_INT("cache-size", &dns_conf_cachesize, 0, CONF_INT_MAX),
|
||||||
CONF_YESNO("prefetch-domain", &dns_conf_prefetch),
|
CONF_YESNO("prefetch-domain", &dns_conf_prefetch),
|
||||||
CONF_YESNO("dualstack-ip-selection", &dns_conf_dualstack_ip_selection),
|
CONF_YESNO("dualstack-ip-selection", &dns_conf_dualstack_ip_selection),
|
||||||
CONF_INT("dualstack-ip-selection-threshold", &dns_conf_dualstack_ip_selection_threshold, 1, 1000),
|
CONF_INT("dualstack-ip-selection-threshold", &dns_conf_dualstack_ip_selection_threshold, 0, 1000),
|
||||||
CONF_CUSTOM("log-level", config_log_level, NULL),
|
CONF_CUSTOM("log-level", config_log_level, NULL),
|
||||||
CONF_STRING("log-file", (char *)dns_conf_log_file, DNS_MAX_PATH),
|
CONF_STRING("log-file", (char *)dns_conf_log_file, DNS_MAX_PATH),
|
||||||
CONF_SIZE("log-size", &dns_conf_log_size, 0, 1024 * 1024 * 1024),
|
CONF_SIZE("log-size", &dns_conf_log_size, 0, 1024 * 1024 * 1024),
|
||||||
@@ -598,12 +729,27 @@ struct config_item config_item[] = {
|
|||||||
CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA),
|
CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA),
|
||||||
CONF_CUSTOM("blacklist-ip", config_blacklist_ip, NULL),
|
CONF_CUSTOM("blacklist-ip", config_blacklist_ip, NULL),
|
||||||
CONF_CUSTOM("bogus-nxdomain", conf_bogus_nxdomain, NULL),
|
CONF_CUSTOM("bogus-nxdomain", conf_bogus_nxdomain, NULL),
|
||||||
CONF_CUSTOM("edns-client-subnet-ipv4", conf_edns_client_subnet, &dns_conf_ipv6_ecs),
|
CONF_CUSTOM("ignore-ip", conf_ip_ignore, NULL),
|
||||||
CONF_CUSTOM("edns-client-subnet-ipv6", conf_edns_client_subnet, &dns_conf_ipv6_ecs),
|
CONF_CUSTOM("edns-client-subnet", conf_edns_client_subnet, NULL),
|
||||||
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
|
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
|
||||||
CONF_END(),
|
CONF_END(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int conf_printf(const char *file, int lineno, int ret)
|
||||||
|
{
|
||||||
|
if (ret == CONF_RET_ERR) {
|
||||||
|
tlog(TLOG_ERROR, "process config file '%s' failed at line %d.", file, lineno);
|
||||||
|
syslog(LOG_NOTICE, "process config file '%s' failed at line %d.", file, lineno);
|
||||||
|
return -1;
|
||||||
|
} else if (ret == CONF_RET_WARN) {
|
||||||
|
tlog(TLOG_WARN, "process config file '%s' failed at line %d.", file, lineno);
|
||||||
|
syslog(LOG_NOTICE, "process config file '%s' failed at line %d.", file, lineno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int config_addtional_file(void *data, int argc, char *argv[])
|
int config_addtional_file(void *data, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char *file_path = argv[1];
|
char *file_path = argv[1];
|
||||||
@@ -613,17 +759,20 @@ int config_addtional_file(void *data, int argc, char *argv[])
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return load_conf(file_path, config_item);
|
return load_conf(file_path, config_item, conf_printf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _dns_server_load_conf_init(void)
|
int _dns_server_load_conf_init(void)
|
||||||
{
|
{
|
||||||
dns_conf_address_rule = New_Radix();
|
dns_conf_address_rule.ipv4 = New_Radix();
|
||||||
art_tree_init(&dns_conf_domain_rule);
|
dns_conf_address_rule.ipv6 = New_Radix();
|
||||||
if (dns_conf_address_rule == NULL) {
|
if (dns_conf_address_rule.ipv4 == NULL || dns_conf_address_rule.ipv6 == NULL) {
|
||||||
|
tlog(TLOG_WARN, "init radix tree failed.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
art_tree_init(&dns_conf_domain_rule);
|
||||||
|
|
||||||
hash_init(dns_ipset_table.ipset);
|
hash_init(dns_ipset_table.ipset);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -632,13 +781,17 @@ int _dns_server_load_conf_init(void)
|
|||||||
void dns_server_load_exit(void)
|
void dns_server_load_exit(void)
|
||||||
{
|
{
|
||||||
config_domain_destroy();
|
config_domain_destroy();
|
||||||
Destroy_Radix(dns_conf_address_rule, config_address_destroy, NULL);
|
Destroy_Radix(dns_conf_address_rule.ipv4, config_address_destroy, NULL);
|
||||||
|
Destroy_Radix(dns_conf_address_rule.ipv6, config_address_destroy, NULL);
|
||||||
config_ipset_table_destroy();
|
config_ipset_table_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
int dns_server_load_conf(const char *file)
|
int dns_server_load_conf(const char *file)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
_dns_server_load_conf_init();
|
_dns_server_load_conf_init();
|
||||||
|
openlog ("smartdns", LOG_CONS | LOG_NDELAY, LOG_LOCAL1);
|
||||||
return load_conf(file, config_item);
|
ret = load_conf(file, config_item, conf_printf);
|
||||||
|
closelog();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,25 @@
|
|||||||
#define SMARTDNS_AUDIT_FILE "/var/log/smartdns-audit.log"
|
#define SMARTDNS_AUDIT_FILE "/var/log/smartdns-audit.log"
|
||||||
|
|
||||||
enum domain_rule {
|
enum domain_rule {
|
||||||
DOMAIN_RULE_ADDRESS_IPV4 = 1,
|
DOMAIN_RULE_FLAGS = 0,
|
||||||
DOMAIN_RULE_ADDRESS_IPV6 = 2,
|
DOMAIN_RULE_ADDRESS_IPV4,
|
||||||
DOMAIN_RULE_IPSET = 3,
|
DOMAIN_RULE_ADDRESS_IPV6,
|
||||||
|
DOMAIN_RULE_IPSET,
|
||||||
DOMAIN_RULE_MAX,
|
DOMAIN_RULE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DOMAIN_FLAG_ADDR_SOA (1 << 0)
|
||||||
|
#define DOMAIN_FLAG_ADDR_IPV4_SOA (1 << 1)
|
||||||
|
#define DOMAIN_FLAG_ADDR_IPV6_SOA (1 << 2)
|
||||||
|
#define DOMAIN_FLAG_ADDR_IGN (1 << 3)
|
||||||
|
#define DOMAIN_FLAG_ADDR_IPV4_IGN (1 << 4)
|
||||||
|
#define DOMAIN_FLAG_ADDR_IPV6_IGN (1 << 5)
|
||||||
|
#define DOMAIN_FLAG_IPSET_IGNORE (1 << 6)
|
||||||
|
|
||||||
|
struct dns_rule_flags {
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
struct dns_address_IPV4 {
|
struct dns_address_IPV4 {
|
||||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||||
};
|
};
|
||||||
@@ -71,11 +84,13 @@ struct dns_bogus_ip_address {
|
|||||||
enum address_rule {
|
enum address_rule {
|
||||||
ADDRESS_RULE_BLACKLIST = 1,
|
ADDRESS_RULE_BLACKLIST = 1,
|
||||||
ADDRESS_RULE_BOGUS = 2,
|
ADDRESS_RULE_BOGUS = 2,
|
||||||
|
ADDRESS_RULE_IP_IGNORE = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_ip_address_rule {
|
struct dns_ip_address_rule {
|
||||||
unsigned int blacklist : 1;
|
unsigned int blacklist : 1;
|
||||||
unsigned int bogus : 1;
|
unsigned int bogus : 1;
|
||||||
|
unsigned int ip_ignore : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dns_edns_client_subnet {
|
struct dns_edns_client_subnet {
|
||||||
@@ -84,6 +99,11 @@ struct dns_edns_client_subnet {
|
|||||||
int subnet;
|
int subnet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dns_conf_address_rule {
|
||||||
|
radix_tree_t *ipv4;
|
||||||
|
radix_tree_t *ipv6;
|
||||||
|
};
|
||||||
|
|
||||||
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 char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
|
||||||
extern int dns_conf_tcp_idle_time;
|
extern int dns_conf_tcp_idle_time;
|
||||||
@@ -104,7 +124,7 @@ extern int dns_conf_audit_num;
|
|||||||
|
|
||||||
extern char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN];
|
extern char dns_conf_server_name[DNS_MAX_CONF_CNAME_LEN];
|
||||||
extern art_tree dns_conf_domain_rule;
|
extern art_tree dns_conf_domain_rule;
|
||||||
extern radix_tree_t *dns_conf_address_rule;
|
extern struct dns_conf_address_rule dns_conf_address_rule;
|
||||||
|
|
||||||
extern int dns_conf_dualstack_ip_selection;
|
extern int dns_conf_dualstack_ip_selection;
|
||||||
extern int dns_conf_dualstack_ip_selection_threshold;
|
extern int dns_conf_dualstack_ip_selection_threshold;
|
||||||
@@ -113,6 +133,7 @@ extern int dns_conf_rr_ttl;
|
|||||||
extern int dns_conf_rr_ttl_min;
|
extern int dns_conf_rr_ttl_min;
|
||||||
extern int dns_conf_rr_ttl_max;
|
extern int dns_conf_rr_ttl_max;
|
||||||
extern int dns_conf_force_AAAA_SOA;
|
extern int dns_conf_force_AAAA_SOA;
|
||||||
|
extern int dns_conf_ipset_timeout_enable;
|
||||||
|
|
||||||
extern struct dns_edns_client_subnet dns_conf_ipv4_ecs;
|
extern struct dns_edns_client_subnet dns_conf_ipv4_ecs;
|
||||||
extern struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
extern struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
||||||
|
|||||||
267
src/dns_server.c
267
src/dns_server.c
@@ -93,6 +93,7 @@ struct dns_server {
|
|||||||
struct dns_ip_address {
|
struct dns_ip_address {
|
||||||
struct hlist_node node;
|
struct hlist_node node;
|
||||||
int hitnum;
|
int hitnum;
|
||||||
|
unsigned long recv_tick;
|
||||||
dns_type_t addr_type;
|
dns_type_t addr_type;
|
||||||
union {
|
union {
|
||||||
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
unsigned char ipv4_addr[DNS_RR_A_LEN];
|
||||||
@@ -185,13 +186,15 @@ static void _dns_server_audit_log(struct dns_request *request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->qtype == DNS_T_AAAA) {
|
if (request->qtype == DNS_T_AAAA && request->has_ipv6) {
|
||||||
snprintf(req_result, sizeof(req_result), "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->ipv6_addr[0],
|
snprintf(req_result, sizeof(req_result), "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->ipv6_addr[0],
|
||||||
request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6],
|
request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6],
|
||||||
request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12],
|
request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12],
|
||||||
request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||||
} else if (request->qtype == DNS_T_A) {
|
} else if (request->qtype == DNS_T_A && request->has_ipv4) {
|
||||||
snprintf(req_result, sizeof(req_result), "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
snprintf(req_result, sizeof(req_result), "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||||
|
} else if (request->has_soa) {
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -378,6 +381,11 @@ static int _dns_reply_inpacket(struct dns_request *request, unsigned char *inpac
|
|||||||
struct dns_server_conn *client = request->client;
|
struct dns_server_conn *client = request->client;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
if (client == NULL) {
|
||||||
|
tlog(TLOG_ERROR, "client is invalid, domain: %s", request->domain);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (client->type == DNS_SERVER_UDP) {
|
if (client->type == DNS_SERVER_UDP) {
|
||||||
ret = _dns_server_reply_udp(request, client, inpacket, inpacket_len);
|
ret = _dns_server_reply_udp(request, client, inpacket, inpacket_len);
|
||||||
} else if (client->type == DNS_SERVER_TCP) {
|
} else if (client->type == DNS_SERVER_TCP) {
|
||||||
@@ -400,6 +408,10 @@ static int _dns_reply(struct dns_request *request)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
int encode_len = 0;
|
int encode_len = 0;
|
||||||
|
|
||||||
|
if (request->client == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
_dns_server_audit_log(request);
|
_dns_server_audit_log(request);
|
||||||
|
|
||||||
memset(&head, 0, sizeof(head));
|
memset(&head, 0, sizeof(head));
|
||||||
@@ -462,26 +474,34 @@ static int _dns_server_reply_SOA(int rcode, struct dns_request *request, struct
|
|||||||
static int _dns_setup_ipset(struct dns_request *request)
|
static int _dns_setup_ipset(struct dns_request *request)
|
||||||
{
|
{
|
||||||
struct dns_ipset_rule *ipset_rule = NULL;
|
struct dns_ipset_rule *ipset_rule = NULL;
|
||||||
|
struct dns_rule_flags *rule_flags = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (request->domain_rule == NULL) {
|
if (request->domain_rule == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rule_flags = request->domain_rule->rules[DOMAIN_RULE_FLAGS];
|
||||||
|
if (rule_flags) {
|
||||||
|
if (rule_flags->flags & DOMAIN_FLAG_IPSET_IGNORE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ipset_rule = request->domain_rule->rules[DOMAIN_RULE_IPSET];
|
ipset_rule = request->domain_rule->rules[DOMAIN_RULE_IPSET];
|
||||||
if (ipset_rule == NULL) {
|
if (ipset_rule == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->has_ipv4 && request->qtype == DNS_T_A) {
|
if (request->has_ipv4 && request->qtype == DNS_T_A) {
|
||||||
ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN);
|
ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->has_ipv6 && request->qtype == DNS_T_AAAA) {
|
if (request->has_ipv6 && request->qtype == DNS_T_AAAA) {
|
||||||
if (request->has_ipv4) {
|
if (request->has_ipv4) {
|
||||||
ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN);
|
ret |= ipset_add(ipset_rule->ipsetname, request->ipv4_addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
|
||||||
}
|
}
|
||||||
ret |= ipset_add(ipset_rule->ipsetname, request->ipv6_addr, DNS_RR_AAAA_LEN);
|
ret |= ipset_add(ipset_rule->ipsetname, request->ipv6_addr, DNS_RR_AAAA_LEN, request->ttl_v6 * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog(TLOG_DEBUG, "IPSET-MATCH: domain:%s, ipset:%s, result: %d", request->domain, ipset_rule->ipsetname, ret);
|
tlog(TLOG_DEBUG, "IPSET-MATCH: domain:%s, ipset:%s, result: %d", request->domain, ipset_rule->ipsetname, ret);
|
||||||
@@ -508,10 +528,10 @@ int _dns_server_request_complete(struct dns_request *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (request->qtype == DNS_T_A) {
|
if (request->qtype == DNS_T_A) {
|
||||||
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
|
|
||||||
request->ipv4_addr[2], request->ipv4_addr[3]);
|
|
||||||
|
|
||||||
if (request->has_ipv4) {
|
if (request->has_ipv4) {
|
||||||
|
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
|
||||||
|
request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||||
|
|
||||||
if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) {
|
if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) {
|
||||||
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
|
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
|
||||||
}
|
}
|
||||||
@@ -521,25 +541,34 @@ int _dns_server_request_complete(struct dns_request *request)
|
|||||||
} else {
|
} else {
|
||||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
|
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request->has_soa = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (request->qtype == DNS_T_AAAA) {
|
} else if (request->qtype == DNS_T_AAAA) {
|
||||||
tlog(TLOG_INFO, "result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode,
|
if (request->has_ipv4 && request->ping_ttl_v4 > 0) {
|
||||||
|
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
|
||||||
|
request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||||
|
|
||||||
|
if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) {
|
||||||
|
tlog(TLOG_DEBUG, "Force IPV4 perfered.");
|
||||||
|
if (request->prefetch) {
|
||||||
|
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
|
||||||
|
} else {
|
||||||
|
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->has_ipv6) {
|
||||||
|
tlog(TLOG_INFO, "result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode,
|
||||||
request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
|
request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
|
||||||
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
|
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
|
||||||
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||||
|
|
||||||
if (request->has_ipv4) {
|
|
||||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_AAAA, request->ipv4_addr, DNS_RR_A_LEN);
|
|
||||||
|
|
||||||
if (((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10) < request->ping_ttl_v6) && (request->ping_ttl_v4 > 0)) ||
|
|
||||||
(request->ping_ttl_v6 == -1)) {
|
|
||||||
tlog(TLOG_DEBUG, "Force IPV4 perfered.");
|
|
||||||
return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request->has_ipv6) {
|
|
||||||
if (request->has_ping_result == 0 && request->ttl_v6 > DNS_SERVER_TMOUT_TTL) {
|
if (request->has_ping_result == 0 && request->ttl_v6 > DNS_SERVER_TMOUT_TTL) {
|
||||||
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
|
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
|
||||||
}
|
}
|
||||||
@@ -549,14 +578,22 @@ int _dns_server_request_complete(struct dns_request *request)
|
|||||||
} else {
|
} else {
|
||||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN);
|
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request->has_ipv4 = 0;
|
||||||
|
request->has_soa = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request->has_soa) {
|
||||||
|
tlog(TLOG_INFO, "result: %s, qtype: %d, SOA", request->domain, request->qtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
_dns_setup_ipset(request);
|
||||||
|
|
||||||
if (request->prefetch) {
|
if (request->prefetch) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dns_setup_ipset(request);
|
|
||||||
_dns_reply(request);
|
_dns_reply(request);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -575,12 +612,15 @@ void _dns_server_request_remove(struct dns_request *request)
|
|||||||
_dns_server_request_release(request);
|
_dns_server_request_release(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dns_server_select_maxhit_ipaddress(struct dns_request *request)
|
void _dns_server_select_possible_ipaddress(struct dns_request *request)
|
||||||
{
|
{
|
||||||
int maxhit = 0;
|
int maxhit = 0;
|
||||||
int bucket = 0;
|
int bucket = 0;
|
||||||
|
unsigned long max_recv_tick = 0;
|
||||||
struct dns_ip_address *addr_map;
|
struct dns_ip_address *addr_map;
|
||||||
struct dns_ip_address *maxhit_addr_map = NULL;
|
struct dns_ip_address *maxhit_addr_map = NULL;
|
||||||
|
struct dns_ip_address *last_recv_addr_map = NULL;
|
||||||
|
struct dns_ip_address *selected_addr_map = NULL;
|
||||||
struct hlist_node *tmp;
|
struct hlist_node *tmp;
|
||||||
|
|
||||||
if (atomic_read(&request->notified) > 0) {
|
if (atomic_read(&request->notified) > 0) {
|
||||||
@@ -593,27 +633,42 @@ void _dns_server_select_maxhit_ipaddress(struct dns_request *request)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr_map->hitnum <= maxhit) {
|
if (addr_map->recv_tick - request->send_tick > max_recv_tick) {
|
||||||
continue;
|
max_recv_tick = addr_map->recv_tick - request->send_tick;
|
||||||
|
last_recv_addr_map = addr_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
maxhit = addr_map->hitnum;
|
if (addr_map->hitnum > maxhit) {
|
||||||
maxhit_addr_map = addr_map;
|
maxhit = addr_map->hitnum;
|
||||||
|
maxhit_addr_map = addr_map;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxhit_addr_map == NULL || maxhit == 1) {
|
if (maxhit_addr_map && maxhit > 1) {
|
||||||
|
selected_addr_map = maxhit_addr_map;
|
||||||
|
} else if (last_recv_addr_map) {
|
||||||
|
selected_addr_map = last_recv_addr_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected_addr_map == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog(TLOG_DEBUG, "select best ip address, %s", request->domain);
|
tlog(TLOG_DEBUG, "select best ip address, %s", request->domain);
|
||||||
switch (request->qtype) {
|
switch (request->qtype) {
|
||||||
case DNS_T_A: {
|
case DNS_T_A: {
|
||||||
memcpy(request->ipv4_addr, maxhit_addr_map->ipv4_addr, DNS_RR_A_LEN);
|
memcpy(request->ipv4_addr, selected_addr_map->ipv4_addr, DNS_RR_A_LEN);
|
||||||
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
|
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
|
||||||
|
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
|
||||||
|
request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||||
} break;
|
} break;
|
||||||
case DNS_T_AAAA: {
|
case DNS_T_AAAA: {
|
||||||
memcpy(request->ipv6_addr, maxhit_addr_map->ipv6_addr, DNS_RR_AAAA_LEN);
|
memcpy(request->ipv6_addr, selected_addr_map->ipv6_addr, DNS_RR_AAAA_LEN);
|
||||||
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
|
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
|
||||||
|
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode,
|
||||||
|
request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
|
||||||
|
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
|
||||||
|
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -640,7 +695,7 @@ void _dns_server_request_release(struct dns_request *request)
|
|||||||
pthread_mutex_unlock(&server.request_list_lock);
|
pthread_mutex_unlock(&server.request_list_lock);
|
||||||
|
|
||||||
/* Select max hit ip address, and return to client */
|
/* Select max hit ip address, and return to client */
|
||||||
_dns_server_select_maxhit_ipaddress(request);
|
_dns_server_select_possible_ipaddress(request);
|
||||||
|
|
||||||
_dns_server_request_complete(request);
|
_dns_server_request_complete(request);
|
||||||
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
|
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
|
||||||
@@ -677,6 +732,8 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
_dns_server_request_release(request);
|
_dns_server_request_release(request);
|
||||||
fast_ping_stop(ping_host);
|
fast_ping_stop(ping_host);
|
||||||
return;
|
return;
|
||||||
|
} else if (result == PING_RESULT_TIMEOUT) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
|
unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
|
||||||
@@ -691,8 +748,10 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
memcpy(request->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
memcpy(request->ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dns_conf_dualstack_ip_selection == 1 && request->qtype == DNS_T_AAAA) {
|
if (request->qtype == DNS_T_AAAA && dns_conf_dualstack_ip_selection == 1) {
|
||||||
threshold = dns_conf_dualstack_ip_selection_threshold * 10;
|
if (request->ping_ttl_v6 < 0 && request->has_soa == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case AF_INET6: {
|
case AF_INET6: {
|
||||||
@@ -717,9 +776,9 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
}
|
}
|
||||||
if (result == PING_RESULT_RESPONSE) {
|
if (result == PING_RESULT_RESPONSE) {
|
||||||
request->has_ping_result = 1;
|
request->has_ping_result = 1;
|
||||||
tlog(TLOG_DEBUG, "from %15s: seq=%d time=%d\n", host, seqno, rtt);
|
tlog(TLOG_DEBUG, "from %s: seq=%d time=%d\n", host, seqno, rtt);
|
||||||
} else {
|
} else {
|
||||||
tlog(TLOG_DEBUG, "from %15s: seq=%d timeout\n", host, seqno);
|
tlog(TLOG_DEBUG, "from %s: seq=%d timeout\n", host, seqno);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtt < threshold) {
|
if (rtt < threshold) {
|
||||||
@@ -727,7 +786,7 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
|
|||||||
} else if (rtt < (get_tick_count() - request->send_tick) * 10) {
|
} else if (rtt < (get_tick_count() - request->send_tick) * 10) {
|
||||||
may_complete = 1;
|
may_complete = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (may_complete && request->has_ping_result == 1) {
|
if (may_complete && request->has_ping_result == 1) {
|
||||||
_dns_server_request_complete(request);
|
_dns_server_request_complete(request);
|
||||||
_dns_server_request_remove(request);
|
_dns_server_request_remove(request);
|
||||||
@@ -764,12 +823,14 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
|
|||||||
if (addr_type == DNS_T_A) {
|
if (addr_type == DNS_T_A) {
|
||||||
if (memcmp(addr_map->ipv4_addr, addr, addr_len) == 0) {
|
if (memcmp(addr_map->ipv4_addr, addr, addr_len) == 0) {
|
||||||
addr_map->hitnum++;
|
addr_map->hitnum++;
|
||||||
|
addr_map->recv_tick = get_tick_count();
|
||||||
pthread_mutex_unlock(&request->ip_map_lock);
|
pthread_mutex_unlock(&request->ip_map_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if (addr_type == DNS_T_AAAA) {
|
} else if (addr_type == DNS_T_AAAA) {
|
||||||
if (memcmp(addr_map->ipv6_addr, addr, addr_len) == 0) {
|
if (memcmp(addr_map->ipv6_addr, addr, addr_len) == 0) {
|
||||||
addr_map->hitnum++;
|
addr_map->hitnum++;
|
||||||
|
addr_map->recv_tick = get_tick_count();
|
||||||
pthread_mutex_unlock(&request->ip_map_lock);
|
pthread_mutex_unlock(&request->ip_map_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -786,6 +847,7 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
|
|||||||
|
|
||||||
addr_map->addr_type = addr_type;
|
addr_map->addr_type = addr_type;
|
||||||
addr_map->hitnum = 1;
|
addr_map->hitnum = 1;
|
||||||
|
addr_map->recv_tick = get_tick_count();
|
||||||
memcpy(addr_map->addr, addr, addr_len);
|
memcpy(addr_map->addr, addr, addr_len);
|
||||||
hash_add(request->ip_map, &addr_map->node, key);
|
hash_add(request->ip_map, &addr_map->node, key);
|
||||||
pthread_mutex_unlock(&request->ip_map_lock);
|
pthread_mutex_unlock(&request->ip_map_lock);
|
||||||
@@ -817,7 +879,17 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = radix_search_best(dns_conf_address_rule, &prefix);
|
switch (prefix.family) {
|
||||||
|
case AF_INET:
|
||||||
|
node = radix_search_best(dns_conf_address_rule.ipv4, &prefix);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
node = radix_search_best(dns_conf_address_rule.ipv6, &prefix);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -837,8 +909,13 @@ static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
if (rule->ip_ignore) {
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
skip:
|
||||||
|
return -2;
|
||||||
match:
|
match:
|
||||||
if (request->rcode == DNS_RC_SERVFAIL) {
|
if (request->rcode == DNS_RC_SERVFAIL) {
|
||||||
request->rcode = DNS_RC_NXDOMAIN;
|
request->rcode = DNS_RC_NXDOMAIN;
|
||||||
@@ -857,6 +934,7 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
|||||||
struct dns_rrs *rrs = NULL;
|
struct dns_rrs *rrs = NULL;
|
||||||
int ping_timeout = DNS_PING_TIMEOUT;
|
int ping_timeout = DNS_PING_TIMEOUT;
|
||||||
unsigned long now = get_tick_count();
|
unsigned long now = get_tick_count();
|
||||||
|
int ip_check_result = 0;
|
||||||
|
|
||||||
if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
|
if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
|
||||||
if (request->rcode == DNS_RC_SERVFAIL) {
|
if (request->rcode == DNS_RC_SERVFAIL) {
|
||||||
@@ -893,9 +971,13 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
|||||||
tlog(TLOG_DEBUG, "domain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
|
tlog(TLOG_DEBUG, "domain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]);
|
||||||
|
|
||||||
/* ip rule check */
|
/* ip rule check */
|
||||||
if (_dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag) == 0) {
|
ip_check_result = _dns_server_ip_rule_check(request, addr, 4, DNS_T_A, result_flag);
|
||||||
|
if (ip_check_result == 0) {
|
||||||
_dns_server_request_release(request);
|
_dns_server_request_release(request);
|
||||||
break;
|
break;
|
||||||
|
} else if (ip_check_result == -2) {
|
||||||
|
_dns_server_request_release(request);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
||||||
@@ -944,9 +1026,13 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
|||||||
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", name, ttl, addr[0], addr[1],
|
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", name, ttl, addr[0], addr[1],
|
||||||
addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||||
|
|
||||||
if (_dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag) == 0) {
|
ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
|
||||||
|
if (ip_check_result == 0) {
|
||||||
_dns_server_request_release(request);
|
_dns_server_request_release(request);
|
||||||
break;
|
break;
|
||||||
|
} else if (ip_check_result == -2) {
|
||||||
|
_dns_server_request_release(request);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) != 0 && strncmp(request->cname, name, DNS_MAX_CNAME_LEN) != 0) {
|
||||||
@@ -995,11 +1081,11 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
|||||||
request->has_soa = 1;
|
request->has_soa = 1;
|
||||||
request->rcode = packet->head.rcode;
|
request->rcode = packet->head.rcode;
|
||||||
dns_get_SOA(rrs, name, 128, &ttl, &request->soa);
|
dns_get_SOA(rrs, name, 128, &ttl, &request->soa);
|
||||||
tlog(TLOG_INFO, "SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: %d, minimum: %d", request->soa.mname,
|
tlog(TLOG_DEBUG, "domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: %d, minimum: %d", domain, request->qtype,
|
||||||
request->soa.rname, request->soa.serial, request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
|
request->soa.mname, request->soa.rname, request->soa.serial, request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
tlog(TLOG_INFO, "%s, qtype: %d", name, rrs->type);
|
tlog(TLOG_DEBUG, "%s, qtype: %d", name, rrs->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1022,6 +1108,20 @@ static int dns_server_update_reply_packet_id(struct dns_request *request, unsign
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (atomic_inc_return(&request->notified) != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
|
||||||
|
ret = _dns_reply_inpacket(request, inpacket, inpacket_len);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsigned int result_flag, struct dns_packet *packet, unsigned char *inpacket,
|
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsigned int result_flag, struct dns_packet *packet, unsigned char *inpacket,
|
||||||
int inpacket_len, void *user_ptr)
|
int inpacket_len, void *user_ptr)
|
||||||
{
|
{
|
||||||
@@ -1035,9 +1135,7 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsi
|
|||||||
|
|
||||||
if (rtype == DNS_QUERY_RESULT) {
|
if (rtype == DNS_QUERY_RESULT) {
|
||||||
if (request->passthrough) {
|
if (request->passthrough) {
|
||||||
dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
|
return _dns_server_reply_passthrouth(request, packet, inpacket, inpacket_len);
|
||||||
_dns_reply_inpacket(request, inpacket, inpacket_len);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_dns_server_process_answer(request, domain, packet, result_flag);
|
_dns_server_process_answer(request, domain, packet, result_flag);
|
||||||
@@ -1119,7 +1217,7 @@ static int _dns_server_process_ptr(struct dns_request *request, struct dns_packe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr(request->domain, "0.0.0.0") != NULL) {
|
if (strstr(request->domain, "0.0.0.0.in-addr.arpa") != NULL) {
|
||||||
found = 1;
|
found = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1187,6 +1285,59 @@ static struct dns_domain_rule *_dns_server_get_domain_rule(char *domain)
|
|||||||
return domain_rule;
|
return domain_rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _dns_server_pre_process_rule_flags(struct dns_request *request, struct dns_packet *packet)
|
||||||
|
{
|
||||||
|
struct dns_rule_flags *rule_flag = NULL;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
if (request->domain_rule == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_flag = request->domain_rule->rules[DOMAIN_RULE_FLAGS];
|
||||||
|
if (rule_flag == NULL) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = rule_flag->flags;
|
||||||
|
if (flags & DOMAIN_FLAG_ADDR_IGN) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DOMAIN_FLAG_ADDR_SOA) {
|
||||||
|
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (request->qtype) {
|
||||||
|
case DNS_T_A:
|
||||||
|
if (flags & DOMAIN_FLAG_ADDR_IPV4_IGN) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DOMAIN_FLAG_ADDR_IPV4_SOA) {
|
||||||
|
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DNS_T_AAAA:
|
||||||
|
if (flags & DOMAIN_FLAG_ADDR_IPV6_IGN) {
|
||||||
|
goto errout;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & DOMAIN_FLAG_ADDR_IPV6_SOA) {
|
||||||
|
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto errout;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
errout:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
|
static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
|
||||||
{
|
{
|
||||||
struct dns_address_IPV4 *address_ipv4 = NULL;
|
struct dns_address_IPV4 *address_ipv4 = NULL;
|
||||||
@@ -1270,6 +1421,9 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
errout:
|
errout:
|
||||||
|
if (dns_cache) {
|
||||||
|
dns_cache_release(dns_cache);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1289,6 +1443,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
|
|||||||
|
|
||||||
_dns_server_client_get(client);
|
_dns_server_client_get(client);
|
||||||
|
|
||||||
|
tlog(TLOG_DEBUG, "recv query packet from %s, len = %d", gethost_by_addr(name, (struct sockaddr *)from, from_len), inpacket_len);
|
||||||
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");
|
||||||
@@ -1360,6 +1515,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
|
|||||||
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
|
_dns_server_reply_SOA(DNS_RC_NOERROR, request, packet);
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tlog(TLOG_DEBUG, "unsupport qtype: %d, domain: %s", qtype, request->domain);
|
tlog(TLOG_DEBUG, "unsupport qtype: %d, domain: %s", qtype, request->domain);
|
||||||
@@ -1367,6 +1523,10 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dns_server_pre_process_rule_flags(request, packet) == 0) {
|
||||||
|
goto clean_exit;
|
||||||
|
}
|
||||||
|
|
||||||
if (_dns_server_process_address(request, packet) == 0) {
|
if (_dns_server_process_address(request, packet) == 0) {
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
@@ -1375,7 +1535,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac
|
|||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, gethost_by_addr(name, (struct sockaddr *)from, from_len), qtype);
|
tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, name, qtype);
|
||||||
|
|
||||||
_dns_server_request_get(request);
|
_dns_server_request_get(request);
|
||||||
pthread_mutex_lock(&server.request_list_lock);
|
pthread_mutex_lock(&server.request_list_lock);
|
||||||
@@ -1444,6 +1604,8 @@ static int _dns_server_prefetch_request(char *domain, dns_type_t qtype)
|
|||||||
hash_init(request->ip_map);
|
hash_init(request->ip_map);
|
||||||
strncpy(request->domain, domain, DNS_MAX_CNAME_LEN);
|
strncpy(request->domain, domain, DNS_MAX_CNAME_LEN);
|
||||||
|
|
||||||
|
request->domain_rule = _dns_server_get_domain_rule(request->domain);
|
||||||
|
|
||||||
tlog(TLOG_INFO, "prefetch domain %s, qtype = %d\n", request->domain, qtype);
|
tlog(TLOG_INFO, "prefetch domain %s, qtype = %d\n", request->domain, qtype);
|
||||||
|
|
||||||
_dns_server_request_get(request);
|
_dns_server_request_get(request);
|
||||||
@@ -1718,7 +1880,6 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
|
|||||||
{
|
{
|
||||||
struct dns_ip_address *addr_map;
|
struct dns_ip_address *addr_map;
|
||||||
int bucket = 0;
|
int bucket = 0;
|
||||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
|
||||||
char ip[DNS_MAX_CNAME_LEN] = {0};
|
char ip[DNS_MAX_CNAME_LEN] = {0};
|
||||||
|
|
||||||
if (request->has_ping_result) {
|
if (request->has_ping_result) {
|
||||||
@@ -1742,7 +1903,7 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
|
|||||||
} break;
|
} break;
|
||||||
case DNS_T_AAAA: {
|
case DNS_T_AAAA: {
|
||||||
_dns_server_request_get(request);
|
_dns_server_request_get(request);
|
||||||
sprintf(name, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]:80", addr_map->ipv6_addr[0], addr_map->ipv6_addr[1],
|
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]:80", addr_map->ipv6_addr[0], addr_map->ipv6_addr[1],
|
||||||
addr_map->ipv6_addr[2], addr_map->ipv6_addr[3], addr_map->ipv6_addr[4], addr_map->ipv6_addr[5], addr_map->ipv6_addr[6],
|
addr_map->ipv6_addr[2], addr_map->ipv6_addr[3], addr_map->ipv6_addr[4], addr_map->ipv6_addr[5], addr_map->ipv6_addr[6],
|
||||||
addr_map->ipv6_addr[7], addr_map->ipv6_addr[8], addr_map->ipv6_addr[9], addr_map->ipv6_addr[10], addr_map->ipv6_addr[11],
|
addr_map->ipv6_addr[7], addr_map->ipv6_addr[8], addr_map->ipv6_addr[9], addr_map->ipv6_addr[10], addr_map->ipv6_addr[11],
|
||||||
addr_map->ipv6_addr[12], addr_map->ipv6_addr[13], addr_map->ipv6_addr[14], addr_map->ipv6_addr[15]);
|
addr_map->ipv6_addr[12], addr_map->ipv6_addr[13], addr_map->ipv6_addr[14], addr_map->ipv6_addr[15]);
|
||||||
@@ -1762,7 +1923,13 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
|
|||||||
|
|
||||||
void _dns_server_prefetch_domain(struct dns_cache *dns_cache)
|
void _dns_server_prefetch_domain(struct dns_cache *dns_cache)
|
||||||
{
|
{
|
||||||
tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d", dns_cache->domain, dns_cache->qtype, dns_cache->ttl);
|
if (dns_cache->hitnum <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_cache->hitnum--;
|
||||||
|
|
||||||
|
tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->domain, dns_cache->qtype, dns_cache->ttl, dns_cache->hitnum);
|
||||||
if (_dns_server_prefetch_request(dns_cache->domain, dns_cache->qtype) != 0) {
|
if (_dns_server_prefetch_request(dns_cache->domain, dns_cache->qtype) != 0) {
|
||||||
tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->domain, dns_cache->qtype);
|
tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->domain, dns_cache->qtype);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -351,6 +351,7 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
|
|||||||
icmp6->icmp6_seq = htons(ping_host->seq);
|
icmp6->icmp6_seq = htons(ping_host->seq);
|
||||||
|
|
||||||
gettimeofday(&packet->msg.tv, 0);
|
gettimeofday(&packet->msg.tv, 0);
|
||||||
|
gettimeofday(&ping_host->last, 0);
|
||||||
packet->msg.sid = ping_host->sid;
|
packet->msg.sid = ping_host->sid;
|
||||||
packet->msg.cookie = ping_host->cookie;
|
packet->msg.cookie = ping_host->cookie;
|
||||||
packet->msg.seq = ping_host->seq;
|
packet->msg.seq = ping_host->seq;
|
||||||
@@ -397,6 +398,7 @@ static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host)
|
|||||||
icmp->icmp_seq = htons(ping_host->seq);
|
icmp->icmp_seq = htons(ping_host->seq);
|
||||||
|
|
||||||
gettimeofday(&packet->msg.tv, 0);
|
gettimeofday(&packet->msg.tv, 0);
|
||||||
|
gettimeofday(&ping_host->last, 0);
|
||||||
packet->msg.sid = ping_host->sid;
|
packet->msg.sid = ping_host->sid;
|
||||||
packet->msg.seq = ping_host->seq;
|
packet->msg.seq = ping_host->seq;
|
||||||
packet->msg.cookie = ping_host->cookie;
|
packet->msg.cookie = ping_host->cookie;
|
||||||
@@ -425,6 +427,7 @@ static int _fast_ping_sendping_udp(struct ping_host_struct *ping_host)
|
|||||||
struct ping_dns_head dns_head;
|
struct ping_dns_head dns_head;
|
||||||
int len;
|
int len;
|
||||||
int flag = 0;
|
int flag = 0;
|
||||||
|
int fd = 0;
|
||||||
|
|
||||||
flag |= (0 << 15) & 0x8000;
|
flag |= (0 << 15) & 0x8000;
|
||||||
flag |= (2 << 11) & 0x7800;
|
flag |= (2 << 11) & 0x7800;
|
||||||
@@ -434,11 +437,20 @@ static int _fast_ping_sendping_udp(struct ping_host_struct *ping_host)
|
|||||||
flag |= (0 << 7) & 0x0080;
|
flag |= (0 << 7) & 0x0080;
|
||||||
flag |= (0 << 0) & 0x000F;
|
flag |= (0 << 0) & 0x000F;
|
||||||
|
|
||||||
|
if (ping_host->type == FAST_PING_UDP) {
|
||||||
|
fd = ping.fd_udp;
|
||||||
|
} else if (ping_host->type == FAST_PING_UDP6) {
|
||||||
|
fd = ping.fd_udp6;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ping_host->seq++;
|
ping_host->seq++;
|
||||||
memset(&dns_head, 0, sizeof(dns_head));
|
memset(&dns_head, 0, sizeof(dns_head));
|
||||||
dns_head.id = htons(ping_host->sid);
|
dns_head.id = htons(ping_host->sid);
|
||||||
dns_head.flag = flag;
|
dns_head.flag = flag;
|
||||||
len = sendto(ping.fd_udp, &dns_head, sizeof(dns_head), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
gettimeofday(&ping_host->last, 0);
|
||||||
|
len = sendto(fd, &dns_head, sizeof(dns_head), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
||||||
if (len < 0 || len != sizeof(dns_head)) {
|
if (len < 0 || len != sizeof(dns_head)) {
|
||||||
int err = errno;
|
int err = errno;
|
||||||
if (errno == ENETUNREACH || errno == EINVAL) {
|
if (errno == ENETUNREACH || errno == EINVAL) {
|
||||||
@@ -493,9 +505,10 @@ static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gettimeofday(&ping_host->last, 0);
|
||||||
ping_host->fd = fd;
|
ping_host->fd = fd;
|
||||||
memset(&event, 0, sizeof(event));
|
memset(&event, 0, sizeof(event));
|
||||||
event.events = EPOLLIN | EPOLLOUT;
|
event.events = EPOLLIN | EPOLLOUT | EPOLLERR;
|
||||||
event.data.ptr = ping_host;
|
event.data.ptr = ping_host;
|
||||||
if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
|
if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
|
||||||
ping_host->fd = -1;
|
ping_host->fd = -1;
|
||||||
@@ -515,6 +528,7 @@ errout:
|
|||||||
static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
gettimeofday(&ping_host->last, 0);
|
||||||
|
|
||||||
if (ping_host->type == FAST_PING_ICMP) {
|
if (ping_host->type == FAST_PING_ICMP) {
|
||||||
ret = _fast_ping_sendping_v4(ping_host);
|
ret = _fast_ping_sendping_v4(ping_host);
|
||||||
@@ -522,12 +536,11 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
|||||||
ret = _fast_ping_sendping_v6(ping_host);
|
ret = _fast_ping_sendping_v6(ping_host);
|
||||||
} else if (ping_host->type == FAST_PING_TCP) {
|
} else if (ping_host->type == FAST_PING_TCP) {
|
||||||
ret = _fast_ping_sendping_tcp(ping_host);
|
ret = _fast_ping_sendping_tcp(ping_host);
|
||||||
} else if (ping_host->type == FAST_PING_UDP) {
|
} else if (ping_host->type == FAST_PING_UDP || ping_host->type == FAST_PING_UDP6) {
|
||||||
ret = _fast_ping_sendping_udp(ping_host);
|
ret = _fast_ping_sendping_udp(ping_host);
|
||||||
}
|
}
|
||||||
|
|
||||||
ping_host->send = 1;
|
ping_host->send = 1;
|
||||||
gettimeofday(&ping_host->last, 0);
|
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -652,6 +665,7 @@ static int _fast_ping_create_udp_sock(FAST_PING_TYPE type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
udp_host = &ping.udp_host;
|
udp_host = &ping.udp_host;
|
||||||
|
udp_host->type = FAST_PING_UDP;
|
||||||
break;
|
break;
|
||||||
case FAST_PING_UDP6:
|
case FAST_PING_UDP6:
|
||||||
fd = socket(AF_INET6, SOCK_DGRAM, 0);
|
fd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
@@ -661,6 +675,10 @@ static int _fast_ping_create_udp_sock(FAST_PING_TYPE type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
udp_host = &ping.udp6_host;
|
udp_host = &ping.udp6_host;
|
||||||
|
udp_host->type = FAST_PING_UDP6;
|
||||||
|
setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
|
||||||
|
setsockopt(fd, IPPROTO_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on));
|
||||||
|
setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
@@ -677,7 +695,6 @@ static int _fast_ping_create_udp_sock(FAST_PING_TYPE type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
udp_host->fd = fd;
|
udp_host->fd = fd;
|
||||||
udp_host->type = FAST_PING_UDP;
|
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
@@ -829,7 +846,6 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
|
|||||||
socktype = SOCK_DGRAM;
|
socktype = SOCK_DGRAM;
|
||||||
snprintf(port_str, MAX_IP_LEN, "%d", port);
|
snprintf(port_str, MAX_IP_LEN, "%d", port);
|
||||||
service = port_str;
|
service = port_str;
|
||||||
ping_type = FAST_PING_UDP;
|
|
||||||
|
|
||||||
if (_fast_ping_create_udp(ping_type) < 0) {
|
if (_fast_ping_create_udp(ping_type) < 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
@@ -1136,6 +1152,7 @@ static int _fast_ping_process_tcp(struct ping_host_struct *ping_host, struct epo
|
|||||||
if (getsockopt(ping_host->fd, SOL_SOCKET, SO_ERROR, (char *)&connect_error, &len) != 0) {
|
if (getsockopt(ping_host->fd, SOL_SOCKET, SO_ERROR, (char *)&connect_error, &len) != 0) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect_error != 0 && connect_error != ECONNREFUSED) {
|
if (connect_error != 0 && connect_error != ECONNREFUSED) {
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -1148,6 +1165,8 @@ static int _fast_ping_process_tcp(struct ping_host_struct *ping_host, struct epo
|
|||||||
|
|
||||||
ping_host->send = 0;
|
ping_host->send = 0;
|
||||||
|
|
||||||
|
_fast_ping_close_host_sock(ping_host);
|
||||||
|
|
||||||
if (ping_host->count == 1) {
|
if (ping_host->count == 1) {
|
||||||
_fast_ping_host_remove(ping_host);
|
_fast_ping_host_remove(ping_host);
|
||||||
}
|
}
|
||||||
@@ -1194,9 +1213,15 @@ static int _fast_ping_process_udp(struct ping_host_struct *ping_host, struct tim
|
|||||||
|
|
||||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||||
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) {
|
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) {
|
||||||
uint8_t *ttlPtr = (uint8_t *)CMSG_DATA(cmsg);
|
if (cmsg->cmsg_len >= sizeof(int)) {
|
||||||
ttl = *ttlPtr;
|
int *ttlPtr = (int *)CMSG_DATA(cmsg);
|
||||||
break;
|
ttl = *ttlPtr;
|
||||||
|
}
|
||||||
|
} else if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) {
|
||||||
|
if (cmsg->cmsg_len >= sizeof(int)) {
|
||||||
|
int *ttlPtr = (int *)CMSG_DATA(cmsg);
|
||||||
|
ttl = *ttlPtr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1256,6 +1281,7 @@ static int _fast_ping_process(struct ping_host_struct *ping_host, struct epoll_e
|
|||||||
case FAST_PING_TCP:
|
case FAST_PING_TCP:
|
||||||
ret = _fast_ping_process_tcp(ping_host, event, now);
|
ret = _fast_ping_process_tcp(ping_host, event, now);
|
||||||
break;
|
break;
|
||||||
|
case FAST_PING_UDP6:
|
||||||
case FAST_PING_UDP:
|
case FAST_PING_UDP:
|
||||||
ret = _fast_ping_process_udp(ping_host, now);
|
ret = _fast_ping_process_udp(ping_host, now);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
#define CONF_INT_MAX (~(1 << 31))
|
#define CONF_INT_MAX (~(1 << 31))
|
||||||
#define CONF_INT_MIN (1 << 31)
|
#define CONF_INT_MIN (1 << 31)
|
||||||
|
|
||||||
|
#define CONF_RET_OK 0
|
||||||
|
#define CONF_RET_ERR -1
|
||||||
|
#define CONF_RET_WARN -2
|
||||||
|
#define CONF_RET_NOENT -3
|
||||||
|
|
||||||
struct config_item {
|
struct config_item {
|
||||||
const char *item;
|
const char *item;
|
||||||
int (*item_func)(const char *item, void *data, int argc, char *argv[]);
|
int (*item_func)(const char *item, void *data, int argc, char *argv[]);
|
||||||
@@ -107,9 +112,9 @@ extern int conf_size(const char *item, void *data, int argc, char *argv[]);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int load_conf(const char *file, struct config_item items[]);
|
typedef int(conf_error_handler)(const char *file, int lineno, int ret);
|
||||||
|
|
||||||
int load_conf_get_line_count(void);
|
int load_conf(const char *file, struct config_item items[], conf_error_handler handler);
|
||||||
|
|
||||||
void load_exit(void);
|
void load_exit(void);
|
||||||
|
|
||||||
|
|||||||
@@ -1027,7 +1027,6 @@ void *art_substring(const art_tree *t, const unsigned char *str, int str_len, un
|
|||||||
// Check if the expanded path matches
|
// Check if the expanded path matches
|
||||||
if (!str_prefix_matches((art_leaf*)n, str, str_len)) {
|
if (!str_prefix_matches((art_leaf*)n, str, str_len)) {
|
||||||
found = (art_leaf*)n;
|
found = (art_leaf*)n;
|
||||||
art_copy_key(found, key, key_len);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1040,7 +1039,6 @@ void *art_substring(const art_tree *t, const unsigned char *str, int str_len, un
|
|||||||
// Check if the expanded path matches
|
// Check if the expanded path matches
|
||||||
if (!str_prefix_matches((art_leaf*)m, str, str_len)) {
|
if (!str_prefix_matches((art_leaf*)m, str, str_len)) {
|
||||||
found = (art_leaf*)m;
|
found = (art_leaf*)m;
|
||||||
art_copy_key(found, key, key_len);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1062,5 +1060,7 @@ void *art_substring(const art_tree *t, const unsigned char *str, int str_len, un
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
art_copy_key(found, key, key_len);
|
||||||
|
|
||||||
return found->value;
|
return found->value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
__thread int line_no;
|
|
||||||
|
|
||||||
int conf_custom(const char *item, void *data, int argc, char *argv[])
|
int conf_custom(const char *item, void *data, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct config_item_custom *item_custom = data;
|
struct config_item_custom *item_custom = data;
|
||||||
@@ -182,12 +180,21 @@ void load_exit(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_conf_get_line_count(void)
|
int load_conf_printf(const char *file, int lineno, int ret)
|
||||||
{
|
{
|
||||||
return line_no;
|
if (ret != CONF_RET_OK) {
|
||||||
|
printf("process config file '%s' failed at line %d.", file, lineno);
|
||||||
|
if (ret == CONF_RET_ERR || ret == CONF_RET_NOENT) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_conf_file(const char *file, struct config_item *items)
|
int load_conf_file(const char *file, struct config_item *items, conf_error_handler handler)
|
||||||
{
|
{
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
char line[MAX_LINE_LEN];
|
char line[MAX_LINE_LEN];
|
||||||
@@ -197,6 +204,13 @@ int load_conf_file(const char *file, struct config_item *items)
|
|||||||
int i;
|
int i;
|
||||||
int argc;
|
int argc;
|
||||||
char *argv[1024];
|
char *argv[1024];
|
||||||
|
int ret = 0;
|
||||||
|
int call_ret = 0;
|
||||||
|
int line_no = 0;
|
||||||
|
|
||||||
|
if (handler == NULL) {
|
||||||
|
handler = load_conf_printf;
|
||||||
|
}
|
||||||
|
|
||||||
fp = fopen(file, "r");
|
fp = fopen(file, "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
@@ -223,6 +237,7 @@ int load_conf_file(const char *file, struct config_item *items)
|
|||||||
|
|
||||||
for (i = 0;; i++) {
|
for (i = 0;; i++) {
|
||||||
if (items[i].item == NULL) {
|
if (items[i].item == NULL) {
|
||||||
|
handler(file, line_no, CONF_RET_NOENT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +251,9 @@ int load_conf_file(const char *file, struct config_item *items)
|
|||||||
|
|
||||||
conf_getopt_reset();
|
conf_getopt_reset();
|
||||||
/* call item function */
|
/* call item function */
|
||||||
if (items[i].item_func(items[i].item, items[i].data, argc, argv) != 0) {
|
call_ret = items[i].item_func(items[i].item, items[i].data, argc, argv);
|
||||||
|
ret = handler(file, line_no, call_ret);
|
||||||
|
if (ret != 0) {
|
||||||
conf_getopt_reset();
|
conf_getopt_reset();
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
@@ -257,7 +274,7 @@ errout:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_conf(const char *file, struct config_item items[])
|
int load_conf(const char *file, struct config_item items[], conf_error_handler handler)
|
||||||
{
|
{
|
||||||
return load_conf_file(file, items);
|
return load_conf_file(file, items, handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,6 +221,9 @@ Clear_Radix(radix_tree_t *radix, rdx_cb_t func, void *cbctx)
|
|||||||
void
|
void
|
||||||
Destroy_Radix(radix_tree_t *radix, rdx_cb_t func, void *cbctx)
|
Destroy_Radix(radix_tree_t *radix, rdx_cb_t func, void *cbctx)
|
||||||
{
|
{
|
||||||
|
if (radix == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Clear_Radix(radix, func, cbctx);
|
Clear_Radix(radix, func, cbctx);
|
||||||
free(radix);
|
free(radix);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,12 +200,14 @@ int smartdns_init_ssl(void)
|
|||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
OpenSSL_add_all_algorithms();
|
OpenSSL_add_all_algorithms();
|
||||||
|
SSL_CRYPTO_thread_setup();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int smartdns_destroy_ssl(void)
|
int smartdns_destroy_ssl(void)
|
||||||
{
|
{
|
||||||
|
SSL_CRYPTO_thread_cleanup();
|
||||||
ERR_free_strings();
|
ERR_free_strings();
|
||||||
EVP_cleanup();
|
EVP_cleanup();
|
||||||
|
|
||||||
@@ -384,6 +386,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dns_server_load_conf(config_file) != 0) {
|
if (dns_server_load_conf(config_file) != 0) {
|
||||||
|
fprintf(stderr, "load config failed.\n");
|
||||||
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_pid_file(pid_file) != 0) {
|
if (create_pid_file(pid_file) != 0) {
|
||||||
|
|||||||
94
src/util.c
94
src/util.c
@@ -1,4 +1,5 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "dns_conf.h"
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -7,6 +8,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#define NFNL_SUBSYS_IPSET 6
|
#define NFNL_SUBSYS_IPSET 6
|
||||||
|
|
||||||
@@ -16,6 +20,7 @@
|
|||||||
#define IPSET_ATTR_IPADDR_IPV6 2
|
#define IPSET_ATTR_IPADDR_IPV6 2
|
||||||
#define IPSET_ATTR_PROTOCOL 1
|
#define IPSET_ATTR_PROTOCOL 1
|
||||||
#define IPSET_ATTR_SETNAME 2
|
#define IPSET_ATTR_SETNAME 2
|
||||||
|
#define IPSET_ATTR_TIMEOUT 6
|
||||||
#define IPSET_ADD 9
|
#define IPSET_ADD 9
|
||||||
#define IPSET_DEL 10
|
#define IPSET_DEL 10
|
||||||
#define IPSET_MAXNAMELEN 32
|
#define IPSET_MAXNAMELEN 32
|
||||||
@@ -243,11 +248,20 @@ static int _ipset_socket_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int addr_len, int operate)
|
static int _ipset_support_timeout(const char *ipsetname)
|
||||||
|
{
|
||||||
|
if (dns_conf_ipset_timeout_enable) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int addr_len, unsigned long timeout, int operate)
|
||||||
{
|
{
|
||||||
struct nlmsghdr *netlink_head;
|
struct nlmsghdr *netlink_head;
|
||||||
struct ipset_netlink_msg *netlink_msg;
|
struct ipset_netlink_msg *netlink_msg;
|
||||||
struct ipset_netlink_attr *nested[2];
|
struct ipset_netlink_attr *nested[3];
|
||||||
char buffer[BUFF_SZ];
|
char buffer[BUFF_SZ];
|
||||||
uint8_t proto;
|
uint8_t proto;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
@@ -282,7 +296,7 @@ static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int
|
|||||||
netlink_head = (struct nlmsghdr *)buffer;
|
netlink_head = (struct nlmsghdr *)buffer;
|
||||||
netlink_head->nlmsg_len = NETLINK_ALIGN(sizeof(struct nlmsghdr));
|
netlink_head->nlmsg_len = NETLINK_ALIGN(sizeof(struct nlmsghdr));
|
||||||
netlink_head->nlmsg_type = operate | (NFNL_SUBSYS_IPSET << 8);
|
netlink_head->nlmsg_type = operate | (NFNL_SUBSYS_IPSET << 8);
|
||||||
netlink_head->nlmsg_flags = NLM_F_REQUEST;
|
netlink_head->nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE;
|
||||||
|
|
||||||
netlink_msg = (struct ipset_netlink_msg *)(buffer + netlink_head->nlmsg_len);
|
netlink_msg = (struct ipset_netlink_msg *)(buffer + netlink_head->nlmsg_len);
|
||||||
netlink_head->nlmsg_len += NETLINK_ALIGN(sizeof(struct ipset_netlink_msg));
|
netlink_head->nlmsg_len += NETLINK_ALIGN(sizeof(struct ipset_netlink_msg));
|
||||||
@@ -300,9 +314,15 @@ static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int
|
|||||||
nested[1] = (struct ipset_netlink_attr *)(buffer + NETLINK_ALIGN(netlink_head->nlmsg_len));
|
nested[1] = (struct ipset_netlink_attr *)(buffer + NETLINK_ALIGN(netlink_head->nlmsg_len));
|
||||||
netlink_head->nlmsg_len += NETLINK_ALIGN(sizeof(struct ipset_netlink_attr));
|
netlink_head->nlmsg_len += NETLINK_ALIGN(sizeof(struct ipset_netlink_attr));
|
||||||
nested[1]->type = NLA_F_NESTED | IPSET_ATTR_IP;
|
nested[1]->type = NLA_F_NESTED | IPSET_ATTR_IP;
|
||||||
_ipset_add_attr(netlink_head, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER, addr_len, addr);
|
|
||||||
|
|
||||||
|
_ipset_add_attr(netlink_head, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER, addr_len, addr);
|
||||||
nested[1]->len = (void *)buffer + NETLINK_ALIGN(netlink_head->nlmsg_len) - (void *)nested[1];
|
nested[1]->len = (void *)buffer + NETLINK_ALIGN(netlink_head->nlmsg_len) - (void *)nested[1];
|
||||||
|
|
||||||
|
if (timeout > 0 && _ipset_support_timeout(ipsetname) == 0) {
|
||||||
|
timeout = htonl(timeout);
|
||||||
|
_ipset_add_attr(netlink_head, IPSET_ATTR_TIMEOUT | NLA_F_NET_BYTEORDER, sizeof(timeout), &timeout);
|
||||||
|
}
|
||||||
|
|
||||||
nested[0]->len = (void *)buffer + NETLINK_ALIGN(netlink_head->nlmsg_len) - (void *)nested[0];
|
nested[0]->len = (void *)buffer + NETLINK_ALIGN(netlink_head->nlmsg_len) - (void *)nested[0];
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@@ -323,12 +343,70 @@ static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipset_add(const char *ipsetname, const unsigned char addr[], int addr_len)
|
int ipset_add(const char *ipsetname, const unsigned char addr[], int addr_len, unsigned long timeout)
|
||||||
{
|
{
|
||||||
return _ipset_operate(ipsetname, addr, addr_len, IPSET_ADD);
|
return _ipset_operate(ipsetname, addr, addr_len, timeout, IPSET_ADD);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipset_del(const char *ipsetname, const unsigned char addr[], int addr_len)
|
int ipset_del(const char *ipsetname, const unsigned char addr[], int addr_len)
|
||||||
{
|
{
|
||||||
return _ipset_operate(ipsetname, addr, addr_len, IPSET_DEL);
|
return _ipset_operate(ipsetname, addr, addr_len, 0, IPSET_DEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define THREAD_STACK_SIZE (16*1024)
|
||||||
|
static pthread_mutex_t *lock_cs;
|
||||||
|
static long *lock_count;
|
||||||
|
|
||||||
|
void pthreads_locking_callback(int mode, int type, const char *file, int line)
|
||||||
|
{
|
||||||
|
if (mode & CRYPTO_LOCK) {
|
||||||
|
pthread_mutex_lock(&(lock_cs[type]));
|
||||||
|
lock_count[type]++;
|
||||||
|
} else {
|
||||||
|
pthread_mutex_unlock(&(lock_cs[type]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long pthreads_thread_id(void)
|
||||||
|
{
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
ret = (unsigned long)pthread_self();
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSL_CRYPTO_thread_setup(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
|
||||||
|
lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
|
||||||
|
if (!lock_cs || !lock_count) {
|
||||||
|
/* Nothing we can do about this...void function! */
|
||||||
|
if (lock_cs)
|
||||||
|
OPENSSL_free(lock_cs);
|
||||||
|
if (lock_count)
|
||||||
|
OPENSSL_free(lock_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < CRYPTO_num_locks(); i++) {
|
||||||
|
lock_count[i] = 0;
|
||||||
|
pthread_mutex_init(&(lock_cs[i]), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
CRYPTO_set_id_callback(pthreads_thread_id);
|
||||||
|
CRYPTO_set_locking_callback(pthreads_locking_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSL_CRYPTO_thread_cleanup(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
CRYPTO_set_locking_callback(NULL);
|
||||||
|
for (i = 0; i < CRYPTO_num_locks(); i++) {
|
||||||
|
pthread_mutex_destroy(&(lock_cs[i]));
|
||||||
|
}
|
||||||
|
OPENSSL_free(lock_cs);
|
||||||
|
OPENSSL_free(lock_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,12 @@ char *reverse_string(char *output, char *input, int len);
|
|||||||
|
|
||||||
void print_stack(void);
|
void print_stack(void);
|
||||||
|
|
||||||
int ipset_add(const char *ipsetname, const unsigned char addr[], int addr_len);
|
int ipset_add(const char *ipsetname, const unsigned char addr[], int addr_len, unsigned long timeout);
|
||||||
|
|
||||||
int ipset_del(const char *ipsetname, const unsigned char addr[], int addr_len);
|
int ipset_del(const char *ipsetname, const unsigned char addr[], int addr_len);
|
||||||
|
|
||||||
|
void SSL_CRYPTO_thread_setup(void);
|
||||||
|
|
||||||
|
void SSL_CRYPTO_thread_cleanup(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user