Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cbd926ede | ||
|
|
fb3b0a7245 | ||
|
|
64abad4077 | ||
|
|
c3501923db | ||
|
|
721c56cbec | ||
|
|
9213f898c3 | ||
|
|
65e8cd5e61 | ||
|
|
e05d1f9d17 | ||
|
|
c4b99a99e7 | ||
|
|
8c96081807 | ||
|
|
640efd7b86 | ||
|
|
add8eecead | ||
|
|
da9ef34588 | ||
|
|
87f04571b1 | ||
|
|
6291c17d6a | ||
|
|
f801023569 | ||
|
|
4e11c13ec0 | ||
|
|
273c2d5100 | ||
|
|
5082f1ae55 | ||
|
|
3f7bc30f65 | ||
|
|
77bce2e7c6 | ||
|
|
9a23bf6113 | ||
|
|
1f6e447f86 | ||
|
|
b1eafb6491 | ||
|
|
81468a3c4f | ||
|
|
9e928983e0 | ||
|
|
9b8d7de6d3 | ||
|
|
46742fc1d7 | ||
|
|
358994e431 | ||
|
|
7427d39476 | ||
|
|
751c1e3a98 | ||
|
|
90d5c7e396 | ||
|
|
0a0d0f001e | ||
|
|
bc953d0c9b | ||
|
|
44c854dfec | ||
|
|
301a60f6ed | ||
|
|
4db61f2677 | ||
|
|
7746ecb46d | ||
|
|
4357847641 | ||
|
|
e7e0a5d4af | ||
|
|
57aa9c013d | ||
|
|
7216dcf526 | ||
|
|
41e2067628 | ||
|
|
dda785ec5f | ||
|
|
99972c36ad | ||
|
|
ef50ea9c5e | ||
|
|
cb3656cb57 | ||
|
|
3ef325d75d | ||
|
|
a09e63d333 |
14
ReadMe.md
14
ReadMe.md
@@ -544,8 +544,8 @@ https://github.com/pymumu/smartdns/releases
|
||||
|参数| 功能 |默认值|配置值|例子|
|
||||
|--|--|--|--|--|
|
||||
|server-name|DNS服务器名称|操作系统主机名/smartdns|符合主机名规格的字符串|server-name smartdns
|
||||
|bind|DNS监听端口号|[::]:53|IP:PORT|bind 192.168.1.1:53
|
||||
|bind-tcp|TCP模式DNS监听端口号|[::]:53|IP:PORT|bind-tcp 192.168.1.1:53
|
||||
|bind|DNS监听端口号|[::]:53|可绑定多个端口<br>`IP:PORT`: 服务器IP,端口号。<br>`[-group]`: 请求时使用的DNS服务器组。<br>`[-no-rule-addr]`:跳过address规则。<br>`[-no-rule-nameserver]`:跳过Nameserver规则。<br>`[-no-rule-ipset]`:跳过Ipset规则。<br>`[no-rule-soa]`:跳过SOA(#)规则.<br>`[no-dualstack-selection]`:停用双栈测速。<br>`[-no-speed-check]`:停用测速。<br>`[-no-cache]`:停止缓存|bind :53
|
||||
|bind|TCP DNS监听端口号|[::]:53|可绑定多个端口<br>`IP:PORT`: 服务器IP,端口号。<br>`[-group]`: 请求时使用的DNS服务器组。<br>`[-no-rule-addr]`:跳过address规则。<br>`[-no-rule-nameserver]`:跳过Nameserver规则。<br>`[-no-rule-ipset]`:跳过Ipset规则。<br>`[no-rule-soa]`:跳过SOA(#)规则.<br>`[no-dualstack-selection]`:停用双栈测速。<br>`[-no-speed-check]`:停用测速。<br>`[-no-cache]`:停止缓存|bind-tcp :53
|
||||
|cache-size|域名结果缓存个数|512|数字|cache-size 512
|
||||
|tcp-idle-time|TCP链接空闲超时时间|120|数字|tcp-idle-time 120
|
||||
|rr-ttl|域名结果TTL|远程查询结果|大于0的数字|rr-ttl 600
|
||||
@@ -560,16 +560,18 @@ https://github.com/pymumu/smartdns/releases
|
||||
|audit-size|审计大小|128K|数字+K,M,G|audit-size 128K
|
||||
|audit-num|审计归档个数|2|数字|audit-num 2
|
||||
|conf-file|附加配置文件|无|文件路径|conf-file /etc/smartdns/smartdns.more.conf
|
||||
|server|上游UDP DNS|无|可重复<br>`[ip][:port]`:服务器IP,端口可选。<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server 8.8.8.8:53 -blacklist-ip -group g1
|
||||
|server-tcp|上游TCP DNS|无|可重复<br>`[ip][:port]`:服务器IP,端口可选。<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server-tcp 8.8.8.8:53
|
||||
|server-tls|上游TLS DNS|无|可重复<br>`[ip][:port]`:服务器IP,端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值,base64编码的sha256 SPKI pin值<br>`[host-name]`:TLS SNI名称<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server-tls 8.8.8.8:853
|
||||
|server-https|上游HTTPS DNS|无|可重复<br>`https://[host][:port]/path`:服务器IP,端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值,base64编码的sha256 SPKI pin值<br>`[host-name]`:TLS SNI名称<br>`[http-host]`:http协议头主机名<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server-https https://cloudflare-dns.com/dns-query
|
||||
|server|上游UDP DNS|无|可重复<br>`[ip][:port]`:服务器IP,端口可选。<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`:whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server 8.8.8.8:53 -blacklist-ip -group g1
|
||||
|server-tcp|上游TCP DNS|无|可重复<br>`[ip][:port]`:服务器IP,端口可选。<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`:whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server-tcp 8.8.8.8:53
|
||||
|server-tls|上游TLS DNS|无|可重复<br>`[ip][:port]`:服务器IP,端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值,base64编码的sha256 SPKI pin值<br>`[-host-name]`:TLS SNI名称。<br>`[-tls-host-verify]`: TLS证书主机名校验。<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`:whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server-tls 8.8.8.8:853
|
||||
|server-https|上游HTTPS DNS|无|可重复<br>`https://[host][:port]/path`:服务器IP,端口可选。<br>`[-spki-pin [sha256-pin]]`: TLS合法性校验SPKI值,base64编码的sha256 SPKI pin值<br>`[-host-name]`:TLS SNI名称<br>`[-http-host]`:http协议头主机名。<br>`[-tls-host-verify]`: TLS证书主机名校验。<br>`[-blacklist-ip]`:blacklist-ip参数指定使用blacklist-ip配置IP过滤结果。<br>`[-whitelist-ip]`:whitelist-ip参数指定仅接受whitelist-ip中配置IP范围。<br>`[-group [group] ...]`:DNS服务器所属组,比如office, foreign,和nameserver配套使用。<br>`[-exclude-default-group]`:将DNS服务器从默认组中排除| server-https https://cloudflare-dns.com/dns-query
|
||||
|speed-check-mode|测速模式选择|无|[ping\|tcp:[80]\|none]|speed-check-mode ping,tcp:80
|
||||
|address|指定域名IP地址|无|address /domain/[ip\|-\|-4\|-6\|#\|#4\|#6] <br>`-`表示忽略 <br>`#`表示返回SOA <br>`4`表示IPV4 <br>`6`表示IPV6| address /www.example.com/1.2.3.4
|
||||
|nameserver|指定域名使用server组解析|无|nameserver /domain/[group\|-], `group`为组名,`-`表示忽略此规则,配套server中的`-group`参数使用| nameserver /www.example.com/office
|
||||
|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
|
||||
|ignore-ip|忽略IP地址|无|[ip/subnet],可重复| ignore-ip 1.2.3.4/16
|
||||
|whitelist-ip|白名单IP地址|无|[ip/subnet],可重复| whitelist-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
|
||||
|prefetch-domain|域名预先获取功能|no|[yes\|no]|prefetch-domain yes
|
||||
|
||||
16
ReadMe_en.md
16
ReadMe_en.md
@@ -194,7 +194,7 @@ Download the matching version of the SmartDNS installation package. The correspo
|
||||
* **Please download from the Release page: [Download here](https://github.com/pymu/smartdns/releases)**
|
||||
|
||||
```shell
|
||||
https://github.com/pymu/smartdns/releases
|
||||
https://github.com/pymumu/smartdns/releases
|
||||
```
|
||||
|
||||
* For the installation procedure, please refer to the following sections.
|
||||
@@ -539,8 +539,8 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
||||
|parameter|Parameter function|Default value|Value type|Example|
|
||||
|--|--|--|--|--|
|
||||
|server-name|DNS name|host name/smartdns|any string like hosname|server-name smartdns
|
||||
|bind|DNS bind port|[::]:53|IP:PORT|bind 192.168.1.1:53
|
||||
|bind-tcp|TCP mode DNS bind port|[::]:53|IP:PORT|bind-tcp 192.168.1.1:53
|
||||
|bind|DNS listening port number|[::]:53|Support binding multiple ports<br>`IP:PORT`: server IP, port number. <br>`[-group]`: The DNS server group used when requesting. <br>`[-no-rule-addr]`: Skip the address rule. <br>`[-no-rule-nameserver]`: Skip the Nameserver rule. <br>`[-no-rule-ipset]`: Skip the Ipset rule. <br>`[-no-rule-soa]`: Skip address SOA(#) rules.<br>`[-no-dualstack-selection]`: Disable dualstack ip selection.<br>`[-no-speed-check]`: Disable speed measurement. <br>`[-no-cache]`: stop caching |bind :53
|
||||
|bind-tcp|TCP mode DNS listening port number|[::]:53|Support binding multiple ports<br>`IP:PORT`: server IP, port number. <br>`[-group]`: The DNS server group used when requesting. <br>`[-no-rule-addr]`: Skip the address rule. <br>`[-no-rule-nameserver]`: Skip the Nameserver rule. <br>`[-no-rule-ipset]`: Skip the Ipset rule. <br>`[-no-rule-soa]`: Skip address SOA(#) rules.<br>`[-no-dualstack-selection]`: Disable dualstack ip selection.<br>`[-no-speed-check]`: Disable speed measurement. <br>`[-no-cache]`: stop caching |bind-tcp :53
|
||||
|cache-size|Domain name result cache number|512|integer|cache-size 512
|
||||
|tcp-idle-time|TCP connection idle timeout|120|integer|tcp-idle-time 120
|
||||
|rr-ttl|Domain name TTL|Remote query result|number greater than 0|rr-ttl 600
|
||||
@@ -555,16 +555,18 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
||||
|audit-size|audit log size|128K|number+K,M,G|audit-size 128K
|
||||
|audit-num|archived audit log number|2|Integer|audit-num 2
|
||||
|conf-file|additional conf file|None|File path|conf-file /etc/smartdns/smartdns.more.conf
|
||||
|server|Upstream UDP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server 8.8.8.8:53 -blacklist-ip
|
||||
|server-tcp|Upstream TCP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tcp 8.8.8.8:53
|
||||
|server-tls|Upstream TLS DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[host-name]`:TLS Server name<br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tls 8.8.8.8:853
|
||||
|server-https|Upstream HTTPS DNS server|None|Repeatable <br>`https://[host][:port]/path`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[host-name]`:TLS Server name<br>`[http-host]`:http header host<br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-https https://cloudflare-dns.com/dns-query
|
||||
|server|Upstream UDP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server 8.8.8.8:53 -blacklist-ip
|
||||
|server-tcp|Upstream TCP DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tcp 8.8.8.8:53
|
||||
|server-tls|Upstream TLS DNS server|None|Repeatable <br>`[ip][:port]`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name. <br>`[-tls-host-verify]`: TLS cert hostname to verify.<br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-tls 8.8.8.8:853
|
||||
|server-https|Upstream HTTPS DNS server|None|Repeatable <br>`https://[host][:port]/path`: Server IP, port optional. <br>`[-spki-pin [sha256-pin]]`: TLS verify SPKI value, a base64 encoded SHA256 hash<br>`[-host-name]`:TLS Server name<br>`[-http-host]`:http header host. <br>`[-tls-host-verify]`: TLS cert hostname to verify.<br>`[-blacklist-ip]`: The "-blacklist-ip" parameter is to filtering IPs which is configured by "blacklist-ip". <br>`[-whitelist-ip]`: whitelist-ip parameter specifies that only the IP range configured in whitelist-ip is accepted. <br>`[-group [group] ...]`: The group to which the DNS server belongs, such as office, foreign, use with nameserver. <br>`[-exclude-default-group]`: Exclude DNS servers from the default group| server-https https://cloudflare-dns.com/dns-query
|
||||
|speed-check-mode|Speed mode|None|[ping\|tcp:[80]\|none]|speed-check-mode ping,tcp:443
|
||||
|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
|
||||
|nameserver|To query domain with specific server group|None|nameserver /domain/[group\|-], `group` is the group name, `-` means ignore this rule, use the `-group` parameter in the related server|nameserver /www.example.com/office
|
||||
|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
|
||||
|ignore-ip|ignore ip address|None|[ip/subnet], Repeatable| ignore-ip 1.2.3.4/16
|
||||
|whitelist-ip|ip whitelist|None|[ip/subnet], Repeatable,When the filtering server responds IPs in the IP whitelist, only result in whitelist will be accepted| whitelist-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
|
||||
|prefetch-domain|domain prefetch feature|no|[yes\|no]|prefetch-domain yes
|
||||
|
||||
@@ -8,14 +8,27 @@
|
||||
# conf-file [file]
|
||||
# conf-file blacklist-ip.conf
|
||||
|
||||
# dns server bind ip and port, default dns server port is 53.
|
||||
# bind [IP]:port, udp server
|
||||
# bind-tcp [IP]:port, tcp server
|
||||
# dns server bind ip and port, default dns server port is 53, support binding multi ip and port
|
||||
# bind udp server
|
||||
# bind [IP]:[port] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
|
||||
# bind tcp server
|
||||
# bind-tcp [IP]:[port] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
|
||||
# option:
|
||||
# -group: set domain request to use the appropriate server group.
|
||||
# -no-rule-addr: skip address rule.
|
||||
# -no-rule-nameserver: skip nameserver rule.
|
||||
# -no-rule-ipset: skip ipset rule.
|
||||
# -no-speed-check: do not check speed.
|
||||
# -no-cache: skip cache.
|
||||
# -no-rule-soa: Skip address SOA(#) rules.
|
||||
# -no-dualstack-selection: Disable dualstack ip selection.
|
||||
# example:
|
||||
# IPV4: :53
|
||||
# IPV6 [::]:53
|
||||
# bind-tcp [::]:53
|
||||
|
||||
# IPV4:
|
||||
# bind :53
|
||||
# bind :6053 -group office -no-speed-check
|
||||
# IPV6:
|
||||
# bind [::]:53
|
||||
# bind-tcp [::]:53
|
||||
bind [::]:53
|
||||
|
||||
# tcp connection idle timeout
|
||||
@@ -36,9 +49,19 @@ cache-size 512
|
||||
# List of IPs that will be filtered when nameserver is configured -blacklist-ip parameter
|
||||
# blacklist-ip [ip/subnet]
|
||||
|
||||
# List of IPs that will be accepted when nameserver is configured -whitelist-ip parameter
|
||||
# whitelist-ip [ip/subnet]
|
||||
|
||||
# List of IPs that will be ignored
|
||||
# ignore-ip [ip/subnet]
|
||||
|
||||
# speed check mode
|
||||
# speed-check-mode [ping|tcp:port|none|,]
|
||||
# example:
|
||||
# speed-check-mode ping,tcp:80
|
||||
# speed-check-mode tcp:443,ping
|
||||
# speed-check-mode none
|
||||
|
||||
# force AAAA query return SOA
|
||||
# force-AAAA-SOA [yes|no]
|
||||
|
||||
@@ -72,39 +95,46 @@ log-level info
|
||||
# log-num 2
|
||||
|
||||
# dns audit
|
||||
# audit-enable: enable or disable audit [yes|no]
|
||||
# audit-enable [yes|no]: enable or disable audit.
|
||||
# audit-enable yes
|
||||
# audit-SOA [yes|no]: enable or disalbe log soa result.
|
||||
# audit-size size of each audit file, support k,m,g
|
||||
# audit-file /var/log/smartdns-audit.log
|
||||
# audit-size 128k
|
||||
# audit-num 2
|
||||
|
||||
# remote udp dns server list
|
||||
# server [IP]:[PORT] [-blacklist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]
|
||||
# server [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]
|
||||
# default port is 53
|
||||
# -blacklist-ip: filter result with blacklist ip
|
||||
# -whitelist-ip: filter result whth whitelist ip, result in whitelist-ip will be accepted.
|
||||
# -check-edns: result must exist edns RR, or discard result.
|
||||
# -group [group]: set server to group, use with nameserver /domain/group.
|
||||
# -exclude-default-group: exclude this server from default group.
|
||||
# server 8.8.8.8 -blacklist-ip -check-edns -group g1 -group g2
|
||||
|
||||
# remote tcp dns server list
|
||||
# server-tcp [IP]:[PORT] [-blacklist-ip] [-group [group] ...] [-exclude-default-group]
|
||||
# server-tcp [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-group [group] ...] [-exclude-default-group]
|
||||
# default port is 53
|
||||
# server-tcp 8.8.8.8
|
||||
|
||||
# remote tls dns server list
|
||||
# server-tls [IP]:[PORT] [-blacklist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
|
||||
# server-tls [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
|
||||
# -spki-pin: TLS spki pin to verify.
|
||||
# Get SKPI with this command:
|
||||
# -tls-host-check: cert hostname to verify.
|
||||
# -hostname: TLS sni hostname.
|
||||
# Get SPKI with this command:
|
||||
# echo | openssl s_client -connect '[ip]:853' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
|
||||
# default port is 853
|
||||
# server-tls 8.8.8.8
|
||||
# server-tls 1.0.0.1
|
||||
|
||||
# remote https dns server list
|
||||
# server-https https://[host]:[port]/path [-blacklist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
|
||||
# server-https https://[host]:[port]/path [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
|
||||
# -spki-pin: TLS spki pin to verify.
|
||||
# -tls-host-check: cert hostname to verify.
|
||||
# -hostname: TLS sni hostname.
|
||||
# -http-host: http host.
|
||||
# default port is 443
|
||||
# server-https https://cloudflare-dns.com/dns-query
|
||||
|
||||
@@ -126,4 +156,3 @@ log-level info
|
||||
# ipset /domain/[ipset|-]
|
||||
# ipset /www.example.com/block, set ipset with ipset name of block
|
||||
# ipset /www.example.com/-, ignore this domain
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@ build()
|
||||
cp $SMARTDNS_DIR/src/smartdns $ROOT/usr/sbin
|
||||
chmod +x $ROOT/usr/sbin/smartdns
|
||||
|
||||
dpkg -b $ROOT $OUTPUTDIR/smartdns.$VER.$ARCH.deb
|
||||
dpkg -b $ROOT $OUTPUTDIR/smartdns.$VER.$FILEARCH.deb
|
||||
|
||||
rm -fr $ROOT/
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
OPTS=`getopt -o o:h --long arch:,ver: \
|
||||
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
|
||||
-n "" -- "$@"`
|
||||
|
||||
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
||||
@@ -59,6 +59,9 @@ main()
|
||||
--arch)
|
||||
ARCH="$2"
|
||||
shift 2;;
|
||||
--filearch)
|
||||
FILEARCH="$2"
|
||||
shift 2;;
|
||||
--ver)
|
||||
VER="$2"
|
||||
shift 2;;
|
||||
@@ -79,6 +82,10 @@ main()
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if [ -z "$FILEARCH" ]; then
|
||||
FILEARCH=$ARCH
|
||||
fi
|
||||
|
||||
if [ -z "$OUTPUTDIR" ]; then
|
||||
OUTPUTDIR=$CURR_DIR;
|
||||
fi
|
||||
|
||||
@@ -112,6 +112,60 @@ msgstr "设置所有域名的TTL最大值"
|
||||
msgid "smartdns custom settings"
|
||||
msgstr "smartdns 自定义设置,具体配置参数参考指导"
|
||||
|
||||
msgid "Second Server Settings"
|
||||
msgstr "第二DNS服务器"
|
||||
|
||||
msgid "Enable or disable second DNS server."
|
||||
msgstr "是否启用第二DNS服务器。"
|
||||
|
||||
msgid "Skip Speed Check"
|
||||
msgstr "跳过测速"
|
||||
|
||||
msgid "Do not check speed."
|
||||
msgstr "禁用测速。"
|
||||
|
||||
msgid "Server Group"
|
||||
msgstr "服务器组"
|
||||
|
||||
msgid "Query DNS through specific dns server group, such as office, home."
|
||||
msgstr "使用指定服务器组查询,比如office, home。"
|
||||
|
||||
msgid "Skip Address Rules"
|
||||
msgstr "跳过address规则"
|
||||
|
||||
msgid "Skip address rules."
|
||||
msgstr "跳过address规则。"
|
||||
|
||||
msgid "Skip Nameserver Rule"
|
||||
msgstr "跳过Nameserver规则"
|
||||
|
||||
msgid "Skip nameserver rules."
|
||||
msgstr "跳过Nameserver规则。"
|
||||
|
||||
msgid "Skip Ipset Rule"
|
||||
msgstr "跳过ipset规则"
|
||||
|
||||
msgid "Skip ipset rules."
|
||||
msgstr "跳过ipset规则。"
|
||||
|
||||
msgid "Skip SOA Address Rule"
|
||||
msgstr "跳过address SOA(#)规则"
|
||||
|
||||
msgid "Skip SOA address rules."
|
||||
msgstr "跳过address SOA(#)规则。"
|
||||
|
||||
msgid "Skip Dualstack Selection"
|
||||
msgstr "跳过双栈优选"
|
||||
|
||||
msgid "Skip Sualstack Selection."
|
||||
msgstr "跳过双栈优选。"
|
||||
|
||||
msgid "Skip Cache"
|
||||
msgstr "跳过cache"
|
||||
|
||||
msgid "Skip Cache."
|
||||
msgstr "跳过cache。"
|
||||
|
||||
msgid "Upstream Servers"
|
||||
msgstr "上游服务器"
|
||||
|
||||
@@ -139,14 +193,20 @@ msgstr "协议类型"
|
||||
msgid "Domain Address"
|
||||
msgstr "域名地址"
|
||||
|
||||
msgid "TLS Hostname Verify"
|
||||
msgstr "校验TLS主机名"
|
||||
|
||||
msgid "Set TLS hostname to verify."
|
||||
msgstr "设置校验TLS主机名。"
|
||||
|
||||
msgid "TLS SNI name"
|
||||
msgstr "TLS SNI名称"
|
||||
|
||||
msgid "HTTP Host"
|
||||
msgstr "HTTP主机"
|
||||
|
||||
msgid "Sets the server name indication"
|
||||
msgstr "设置服务器SNI名称"
|
||||
msgid "Sets the server name indication for query."
|
||||
msgstr "设置查询时使用的服务器SNI名称。"
|
||||
|
||||
msgid "Set the HTTP host used for the query. Use this parameter when the host of the URL address is an IP address."
|
||||
msgstr "设置查询时使用的HTTP主机,当URL地址的host是IP地址时,使用此参数。"
|
||||
@@ -154,7 +214,7 @@ msgstr "设置查询时使用的HTTP主机,当URL地址的host是IP地址时
|
||||
msgid "Server Group"
|
||||
msgstr "服务器组"
|
||||
|
||||
msgid "DNS Server group belongs to, used with nameserver, such as offlce, home."
|
||||
msgid "DNS Server group belongs to, used with nameserver, such as office, home."
|
||||
msgsr "DNS服务器所属组, 配合nameserver使用,例如:office,home。"
|
||||
|
||||
msgid "IP Blacklist Filtering"
|
||||
|
||||
@@ -16,6 +16,7 @@ s = m:section(TypedSection, "smartdns", translate("Settings"), translate("Genera
|
||||
s.anonymous = true
|
||||
|
||||
s:tab("settings", translate("General Settings"))
|
||||
s:tab("seconddns", translate("Second Server Settings"))
|
||||
s:tab("custom", translate("Custom Settings"))
|
||||
|
||||
---- Eanble
|
||||
@@ -92,10 +93,92 @@ o.placeholder = "300"
|
||||
o.default = 300
|
||||
o.optional = true
|
||||
|
||||
---- second dns server
|
||||
---- rr-ttl-max
|
||||
o = s:taboption("settings", Value, "rr_ttl_max", translate("Domain TTL Max"), translate("Maximum TTL for all domain result."))
|
||||
o.rempty = true
|
||||
|
||||
---- Eanble
|
||||
o = s:taboption("seconddns", Flag, "seconddns_enabled", translate("Enable"), translate("Enable or disable second DNS server."))
|
||||
o.default = o.disabled
|
||||
o.rempty = false
|
||||
|
||||
---- Port
|
||||
o = s:taboption("seconddns", Value, "seconddns_port", translate("Local Port"), translate("Smartdns local server port"))
|
||||
o.placeholder = 7053
|
||||
o.default = 7053
|
||||
o.datatype = "port"
|
||||
o.rempty = false
|
||||
|
||||
---- Enable TCP server
|
||||
o = s:taboption("seconddns", Flag, "seconddns_tcp_server", translate("TCP Server"), translate("Enable TCP DNS Server"))
|
||||
o.rmempty = false
|
||||
o.default = o.enabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "1"
|
||||
end
|
||||
|
||||
o = s:taboption("seconddns", Flag, "seconddns_no_speed_check", translate("Skip Speed Check"), translate("Do not check speed."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
---- dns server group
|
||||
o = s:taboption("seconddns", Value, "seconddns_server_group", translate("Server Group"), translate("Query DNS through specific dns server group, such as office, home."))
|
||||
o.rmempty = true
|
||||
o.placeholder = "default"
|
||||
o.datatype = "hostname"
|
||||
o.rempty = true
|
||||
|
||||
---- skip address rules
|
||||
o = s:taboption("seconddns", Flag, "seconddns_no_rule_addr", translate("Skip Address Rules"), translate("Skip address rules."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
---- skip name server rules
|
||||
o = s:taboption("seconddns", Flag, "seconddns_no_rule_nameserver", translate("Skip Nameserver Rule"), translate("Skip nameserver rules."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
---- skip ipset rules
|
||||
o = s:taboption("seconddns", Flag, "seconddns_no_rule_ipset", translate("Skip Ipset Rule"), translate("Skip ipset rules."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
---- skip soa address rule
|
||||
o = s:taboption("seconddns", Flag, "seconddns_no_rule_soa", translate("Skip SOA Address Rule"), translate("Skip SOA address rules."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
o = s:taboption("seconddns", Flag, "seconddns_no_dualstack_selection", translate("Skip Dualstack Selection"), translate("Skip Sualstack Selection."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
---- skip cache
|
||||
o = s:taboption("seconddns", Flag, "seconddns_no_cache", translate("Skip Cache"), translate("Skip Cache."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
----- custom settings
|
||||
custom = s:taboption("custom", Value, "Custom Settings",
|
||||
translate(""),
|
||||
|
||||
@@ -39,8 +39,16 @@ o:value("https", translate("https"))
|
||||
o.default = "udp"
|
||||
o.rempty = false
|
||||
|
||||
---- TLS host verify
|
||||
o = s:option(Value, "tls_host_verify", translate("TLS Hostname Verify"), translate("Set TLS hostname to verify."))
|
||||
o.default = ""
|
||||
o.datatype = "string"
|
||||
o.rempty = true
|
||||
o:depends("type", "tls")
|
||||
o:depends("type", "https")
|
||||
|
||||
---- SNI host name
|
||||
o = s:option(Value, "host_name", translate("TLS SNI name"), translate("Sets the server name indication"))
|
||||
o = s:option(Value, "host_name", translate("TLS SNI name"), translate("Sets the server name indication for query."))
|
||||
o.default = ""
|
||||
o.datatype = "hostname"
|
||||
o.rempty = true
|
||||
@@ -55,7 +63,7 @@ o.rempty = true
|
||||
o:depends("type", "https")
|
||||
|
||||
---- server group
|
||||
o = s:option(Value, "server_group", translate("Server Group"), translate("DNS Server group belongs to, used with nameserver, such as offlce, home."))
|
||||
o = s:option(Value, "server_group", translate("Server Group"), translate("DNS Server group belongs to, used with nameserver, such as office, home."))
|
||||
o.rmempty = true
|
||||
o.placeholder = "default"
|
||||
o.datatype = "hostname"
|
||||
|
||||
@@ -61,14 +61,14 @@ build()
|
||||
cd $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.$FILEARCH.ipk control.tar.gz data.tar.gz debian-binary
|
||||
|
||||
rm -fr $ROOT/
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
OPTS=`getopt -o o:h --long arch:,ver: \
|
||||
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
|
||||
-n "" -- "$@"`
|
||||
|
||||
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
||||
@@ -81,6 +81,9 @@ main()
|
||||
--arch)
|
||||
ARCH="$2"
|
||||
shift 2;;
|
||||
--filearch)
|
||||
FILEARCH="$2"
|
||||
shift 2;;
|
||||
--ver)
|
||||
VER="$2"
|
||||
shift 2;;
|
||||
@@ -101,6 +104,10 @@ main()
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if [ -z "$FILEARCH" ]; then
|
||||
FILEARCH=$ARCH
|
||||
fi
|
||||
|
||||
if [ -z "$OUTPUTDIR" ]; then
|
||||
OUTPUTDIR=$CURR_DIR;
|
||||
fi
|
||||
|
||||
@@ -126,6 +126,30 @@ conf_append()
|
||||
echo "$1 $2" >> $SMARTDNS_CONF_TMP
|
||||
}
|
||||
|
||||
get_tz()
|
||||
{
|
||||
SET_TZ=""
|
||||
|
||||
if [ -e "/etc/localtime" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
for tzfile in /etc/TZ /var/etc/TZ
|
||||
do
|
||||
if [ ! -e "$tzfile" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
tz="`cat $tzfile 2>/dev/null`"
|
||||
done
|
||||
|
||||
if [ -z "$tz" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
SET_TZ=$tz
|
||||
}
|
||||
|
||||
load_server()
|
||||
{
|
||||
local section="$1"
|
||||
@@ -136,6 +160,7 @@ load_server()
|
||||
config_get "port" "$section" "port" ""
|
||||
config_get "type" "$section" "type" "udp"
|
||||
config_get "ip" "$section" "ip" ""
|
||||
config_get "tls_host_verify" "$section" "tls_host_verify" ""
|
||||
config_get "host_name" "$section" "host_name" ""
|
||||
config_get "http_host" "$section" "http_host" ""
|
||||
config_get "server_group" "$section" "server_group" ""
|
||||
@@ -167,6 +192,10 @@ load_server()
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -z "$tls_host_verify" ]; then
|
||||
ADDITIONAL_ARGS="$ADDITIONAL_ARGS -tls-host-verify $tls_host_verify"
|
||||
fi
|
||||
|
||||
if [ ! -z "$host_name" ]; then
|
||||
ADDITIONAL_ARGS="$ADDITIONAL_ARGS -host-name $host_name"
|
||||
fi
|
||||
@@ -204,7 +233,75 @@ load_server()
|
||||
conf_append "$SERVER" "$DNS_ADDRESS $ADDITIONAL_ARGS $addition_arg"
|
||||
}
|
||||
|
||||
load_service() {
|
||||
load_second_server()
|
||||
{
|
||||
local section="$1"
|
||||
local ARGS=""
|
||||
local ADDR=""
|
||||
|
||||
config_get_bool "seconddns_enabled" "$section" "seconddns_enabled" "0"
|
||||
if [ "$seconddns_enabled" = "0" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
config_get "seconddns_port" "$section" "seconddns_port" "7053"
|
||||
|
||||
config_get_bool "seconddns_no_speed_check" "$section" "seconddns_no_speed_check" "0"
|
||||
if [ "$seconddns_no_speed_check" = "1" ]; then
|
||||
ARGS="$ARGS -no-speed-check"
|
||||
fi
|
||||
|
||||
config_get "seconddns_server_group" "$section" "seconddns_server_group" ""
|
||||
if [ ! -z "$seconddns_server_group" ]; then
|
||||
ARGS="$ARGS -group $seconddns_server_group"
|
||||
fi
|
||||
|
||||
config_get_bool "seconddns_no_rule_addr" "$section" "seconddns_no_rule_addr" "0"
|
||||
if [ "$seconddns_no_rule_addr" = "1" ]; then
|
||||
ARGS="$ARGS -no-rule-addr"
|
||||
fi
|
||||
|
||||
config_get_bool "seconddns_no_rule_nameserver" "$section" "seconddns_no_rule_nameserver" "0"
|
||||
if [ "$seconddns_no_rule_nameserver" = "1" ]; then
|
||||
ARGS="$ARGS -no-rule-nameserver"
|
||||
fi
|
||||
|
||||
config_get_bool "seconddns_no_rule_ipset" "$section" "seconddns_no_rule_ipset" "0"
|
||||
if [ "$seconddns_no_rule_ipset" = "1" ]; then
|
||||
ARGS="$ARGS -no-rule-ipset"
|
||||
fi
|
||||
|
||||
config_get_bool "seconddns_no_rule_soa" "$section" "seconddns_no_rule_soa" "0"
|
||||
if [ "$seconddns_no_rule_soa" = "1" ]; then
|
||||
ARGS="$ARGS -no-rule-soa"
|
||||
fi
|
||||
|
||||
config_get_bool "seconddns_no_dualstack_selection" "$section" "seconddns_no_dualstack_selection" "0"
|
||||
if [ "$seconddns_no_dualstack_selection" = "1" ]; then
|
||||
ARGS="$ARGS -no-dualstack-selection"
|
||||
fi
|
||||
|
||||
config_get_bool "seconddns_no_cache" "$section" "seconddns_no_cache" "0"
|
||||
if [ "$seconddns_no_cache" = "1" ]; then
|
||||
ARGS="$ARGS -no-cache"
|
||||
fi
|
||||
|
||||
config_get "ipv6_server" "$section" "ipv6_server" "1"
|
||||
if [ "$ipv6_server" = "1" ]; then
|
||||
ADDR="[::]"
|
||||
else
|
||||
ADDR=""
|
||||
fi
|
||||
|
||||
conf_append "bind" "$ADDR:$seconddns_port $ARGS"
|
||||
config_get_bool "seconddns_tcp_server" "$section" "seconddns_tcp_server" "1"
|
||||
if [ "$seconddns_tcp_server" = "1" ]; then
|
||||
conf_append "bind-tcp" "$ADDR:$seconddns_port $ARGS"
|
||||
fi
|
||||
}
|
||||
|
||||
load_service()
|
||||
{
|
||||
local section="$1"
|
||||
args=""
|
||||
|
||||
@@ -323,6 +420,8 @@ load_service() {
|
||||
set_forward_dnsmasq "$SMARTDNS_PORT"
|
||||
fi
|
||||
|
||||
load_second_server $section
|
||||
|
||||
config_foreach load_server "server"
|
||||
|
||||
echo "conf-file $ADDRESS_CONF" >> $SMARTDNS_CONF_TMP
|
||||
@@ -336,6 +435,11 @@ load_service() {
|
||||
procd_set_param limits core="unlimited"
|
||||
fi
|
||||
|
||||
get_tz
|
||||
if [ ! -z "$SET_TZ" ]; then
|
||||
procd_set_param env TZ="$SET_TZ"
|
||||
fi
|
||||
|
||||
procd_set_param command /usr/sbin/smartdns -f -c $SMARTDNS_CONF $args
|
||||
if [ "$RESPAWN" = "1" ]; then
|
||||
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
|
||||
@@ -344,12 +448,14 @@ load_service() {
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
start_service() {
|
||||
start_service()
|
||||
{
|
||||
config_load "smartdns"
|
||||
config_foreach load_service "smartdns"
|
||||
}
|
||||
|
||||
reload_service(){
|
||||
reload_service()
|
||||
{
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
@@ -55,13 +55,13 @@ build()
|
||||
cd $ROOT
|
||||
|
||||
tar zcf $ROOT/data.tar.gz -C root --owner=0 --group=0 .
|
||||
tar zcf $OUTPUTDIR/smartdns.$VER.$ARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
|
||||
tar zcf $OUTPUTDIR/smartdns.$VER.$FILEARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
|
||||
rm -fr $ROOT/
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
OPTS=`getopt -o o:h --long arch:,ver: \
|
||||
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
|
||||
-n "" -- "$@"`
|
||||
|
||||
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
||||
@@ -74,6 +74,9 @@ main()
|
||||
--arch)
|
||||
ARCH="$2"
|
||||
shift 2;;
|
||||
--filearch)
|
||||
FILEARCH="$2"
|
||||
shift 2;;
|
||||
--ver)
|
||||
VER="$2"
|
||||
shift 2;;
|
||||
@@ -94,6 +97,10 @@ main()
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if [ -z "$FILEARCH" ]; then
|
||||
FILEARCH=$ARCH
|
||||
fi
|
||||
|
||||
if [ -z "$OUTPUTDIR" ]; then
|
||||
OUTPUTDIR=$CURR_DIR;
|
||||
fi
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
SMARTDNS_BIN=/opt/usr/sbin/smartdns
|
||||
SMARTDNS_CONF=/opt/etc/smartdns/smartdns.conf
|
||||
DNSMASQ_CONF=/etc/dnsmasq.conf
|
||||
SMARTDNS_PID="/var/run/smartdns.pid"
|
||||
DNSMASQ_CONF="/etc/dnsmasq.conf /var/etc/dnsmasq.conf /etc/storage/dnsmasq/dnsmasq.conf"
|
||||
SMARTDNS_PID=/var/run/smartdns.pid
|
||||
SMARTDNS_PORT=535
|
||||
SMARTDNS_OPT=/opt/etc/smartdns/smartdns-opt.conf
|
||||
# workmode
|
||||
@@ -50,13 +50,44 @@ clear_iptable()
|
||||
|
||||
}
|
||||
|
||||
restart_dnsmasq()
|
||||
get_dnsmasq_cmd()
|
||||
{
|
||||
CMD="`ps | grep " dnsmasq" | grep -v grep 2>/dev/null`"
|
||||
if [ -z "$CMD" ]; then
|
||||
CMD="`ps ax | grep dnsmasq | grep -v grep 2>/dev/null`"
|
||||
CMD="`ps | grep -e '[a-zA-Z]\{0,2\} \{1,\}dnsmasq' | grep -v grep 2>/dev/null`"
|
||||
if [ ! -z "$CMD" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
CMD="`ps | grep '/usr/sbin/dnsmasq' | grep -v grep 2>/dev/null`"
|
||||
if [ ! -z "$CMD" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
CMD="`ps | grep 'dnsmasq' | grep -v grep 2>/dev/null`"
|
||||
if [ ! -z "$CMD" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
CMD="`ps ax | grep -e '[a-zA-Z]\{0,2\} \{1,\}dnsmasq' | grep -v grep 2>/dev/null`"
|
||||
if [ ! -z "$CMD" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
CMD="`ps ax | grep /usr/sbin/dnsmasq | grep -v grep 2>/dev/null`"
|
||||
if [ ! -z "$CMD" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
CMD="`ps ax | grep 'dnsmasq' | grep -v grep 2>/dev/null`"
|
||||
if [ ! -z "$CMD" ]; then
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
restart_dnsmasq()
|
||||
{
|
||||
local CMD=""
|
||||
|
||||
get_dnsmasq_cmd
|
||||
if [ -z "$CMD" ]; then
|
||||
echo "cannot find dnsmasq"
|
||||
return 1
|
||||
@@ -77,6 +108,7 @@ restart_dnsmasq()
|
||||
|
||||
get_server_ip()
|
||||
{
|
||||
CONF_FILE=$1
|
||||
IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}'`"
|
||||
LOCAL_SERVER_IP=""
|
||||
for IP in $IPS
|
||||
@@ -85,9 +117,9 @@ get_server_ip()
|
||||
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
|
||||
grep "dhcp-range=" $CONF_FILE | 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}'`"
|
||||
SERVER_TAG="`grep "^dhcp-range *=" $CONF_FILE | grep $ADDR | awk -F= '{print $2}' | awk -F, '{print $1}'`"
|
||||
LOCAL_SERVER_IP="$IP"
|
||||
return 0
|
||||
fi
|
||||
@@ -98,53 +130,82 @@ get_server_ip()
|
||||
return 1
|
||||
}
|
||||
|
||||
set_dnsmasq()
|
||||
set_dnsmasq_conf()
|
||||
{
|
||||
local RESTART_DNSMASQ=0
|
||||
local LOCAL_SERVER_IP=""
|
||||
local SERVER_TAG=""
|
||||
get_server_ip
|
||||
local CONF_FILE=$1
|
||||
|
||||
get_server_ip $CONF_FILE
|
||||
if [ "$LOCAL_SERVER_IP" ] && [ "$SERVER_TAG" ]; then
|
||||
grep "dhcp-option *=" $DNSMASQ_CONF | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
|
||||
grep "dhcp-option *=" $CONF_FILE | 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
|
||||
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $CONF_FILE
|
||||
echo "dhcp-option=$SERVER_TAG,6,$LOCAL_SERVER_IP" >> $CONF_FILE
|
||||
RESTART_DNSMASQ=1
|
||||
fi
|
||||
fi
|
||||
|
||||
grep "^port *=0" $DNSMASQ_CONF > /dev/null 2>&1
|
||||
grep "^port *=0" $CONF_FILE > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
sed -i "/^port *=/d" $DNSMASQ_CONF
|
||||
echo "port=0" >> $DNSMASQ_CONF
|
||||
sed -i "/^port *=/d" $CONF_FILE
|
||||
echo "port=0" >> $CONF_FILE
|
||||
RESTART_DNSMASQ=1
|
||||
fi
|
||||
}
|
||||
|
||||
set_dnsmasq()
|
||||
{
|
||||
local RESTART_DNSMASQ=0
|
||||
|
||||
for conf in $DNSMASQ_CONF
|
||||
do
|
||||
if [ ! -e "$conf" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
set_dnsmasq_conf $conf
|
||||
done
|
||||
|
||||
if [ $RESTART_DNSMASQ -ne 0 ]; then
|
||||
restart_dnsmasq
|
||||
fi
|
||||
}
|
||||
|
||||
clear_dnsmasq_conf()
|
||||
{
|
||||
local LOCAL_SERVER_IP=""
|
||||
local SERVER_TAG=""
|
||||
local CONF_FILE=$1
|
||||
|
||||
get_server_ip $CONF_FILE
|
||||
if [ "$LOCAL_SERVER_IP" ] && [ "$SERVER_TAG" ]; then
|
||||
grep "dhcp-option *=" $CONF_FILE | grep "$SERVER_TAG,6,$LOCAL_SERVER_IP" > /dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" $CONF_FILE
|
||||
RESTART_DNSMASQ=1
|
||||
fi
|
||||
fi
|
||||
|
||||
grep "^port *=" $CONF_FILE > /dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
sed -i "/^port *=/d" $CONF_FILE
|
||||
RESTART_DNSMASQ=1
|
||||
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
|
||||
for conf in $DNSMASQ_CONF
|
||||
do
|
||||
if [ ! -e "$conf" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
clear_dnsmasq_conf $conf
|
||||
done
|
||||
|
||||
if [ $RESTART_DNSMASQ -ne 0 ]; then
|
||||
restart_dnsmasq
|
||||
@@ -157,10 +218,10 @@ set_smartdns_port()
|
||||
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
|
||||
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
|
||||
sed -i "s/^\(bind-tcp .*\):$SMARTDNS_PORT *\(.*\)\$/\1:53 \2/g" $SMARTDNS_CONF
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
@@ -198,6 +259,28 @@ clear_rule()
|
||||
fi
|
||||
}
|
||||
|
||||
get_tz()
|
||||
{
|
||||
if [ -e "/etc/localtime" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
for tzfile in /etc/TZ /var/etc/TZ
|
||||
do
|
||||
if [ ! -e "$tzfile" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
tz="`cat $tzfile 2>/dev/null`"
|
||||
done
|
||||
|
||||
if [ -z "$tz" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
export TZ=$tz
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
set_rule
|
||||
@@ -206,6 +289,7 @@ case "$1" in
|
||||
fi
|
||||
|
||||
set_smartdns_port
|
||||
get_tz
|
||||
$SMARTDNS_BIN -c $SMARTDNS_CONF -p $SMARTDNS_PID
|
||||
if [ $? -ne 0 ]; then
|
||||
clear_rule
|
||||
|
||||
@@ -44,13 +44,13 @@ build()
|
||||
cd $ROOT
|
||||
|
||||
tar zcf data.tar.gz --owner=0 --group=0 opt
|
||||
tar zcf $OUTPUTDIR/smartdns.$VER.$ARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
|
||||
tar zcf $OUTPUTDIR/smartdns.$VER.$FILEARCH.ipk --owner=0 --group=0 control.tar.gz data.tar.gz debian-binary
|
||||
rm -fr $ROOT/
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
OPTS=`getopt -o o:h --long arch:,ver: \
|
||||
OPTS=`getopt -o o:h --long arch:,ver:,filearch: \
|
||||
-n "" -- "$@"`
|
||||
|
||||
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
||||
@@ -63,6 +63,9 @@ main()
|
||||
--arch)
|
||||
ARCH="$2"
|
||||
shift 2;;
|
||||
--filearch)
|
||||
FILEARCH="$2"
|
||||
shift 2;;
|
||||
--ver)
|
||||
VER="$2"
|
||||
shift 2;;
|
||||
@@ -83,6 +86,10 @@ main()
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if [ -z "$FILEARCH" ]; then
|
||||
FILEARCH=$ARCH
|
||||
fi
|
||||
|
||||
if [ -z "$OUTPUTDIR" ]; then
|
||||
OUTPUTDIR=$CURR_DIR;
|
||||
fi
|
||||
|
||||
@@ -5,9 +5,16 @@ OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_co
|
||||
CFLAGS +=-O2 -g -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing
|
||||
CFLAGS +=-Iinclude
|
||||
CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\"
|
||||
ifdef VER
|
||||
CFLAGS += -DSMARTDNS_VERION=\"$(VER)\"
|
||||
endif
|
||||
CXXFLAGS=-O2 -g -Wall -std=c++11
|
||||
CXXFLAGS +=-Iinclude
|
||||
LDFLAGS += -lpthread -lssl -lcrypto
|
||||
ifeq ($(STATIC), yes)
|
||||
LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static
|
||||
else
|
||||
LDFLAGS += -lssl -lcrypto -lpthread
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
|
||||
|
||||
20
src/dns.c
20
src/dns.c
@@ -19,6 +19,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "dns.h"
|
||||
#include "tlog.h"
|
||||
#include "stringutil.h"
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -264,6 +265,7 @@ static int _dns_add_qr_head(struct dns_data_context *data_context, char *domain,
|
||||
static int _dns_get_qr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass)
|
||||
{
|
||||
int i;
|
||||
int is_read_all = 0;
|
||||
/* question head */
|
||||
/* |domain |
|
||||
* |qtype | qclass |
|
||||
@@ -277,6 +279,7 @@ static int _dns_get_qr_head(struct dns_data_context *data_context, char *domain,
|
||||
domain++;
|
||||
data_context->ptr++;
|
||||
i++;
|
||||
is_read_all = 1;
|
||||
break;
|
||||
}
|
||||
*domain = *data_context->ptr;
|
||||
@@ -285,6 +288,9 @@ static int _dns_get_qr_head(struct dns_data_context *data_context, char *domain,
|
||||
}
|
||||
|
||||
*domain = '\0';
|
||||
if (is_read_all == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_dns_data_left_len(data_context) < 4) {
|
||||
return -1;
|
||||
@@ -612,9 +618,9 @@ int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int t
|
||||
unsigned char data[sizeof(*soa)];
|
||||
unsigned char *ptr = data;
|
||||
int len = 0;
|
||||
strncpy((char *)ptr, soa->mname, DNS_MAX_CNAME_LEN - 1);
|
||||
safe_strncpy((char *)ptr, soa->mname, DNS_MAX_CNAME_LEN);
|
||||
ptr += strnlen(soa->mname, DNS_MAX_CNAME_LEN - 1) + 1;
|
||||
strncpy((char *)ptr, soa->rname, DNS_MAX_CNAME_LEN - 1);
|
||||
safe_strncpy((char *)ptr, soa->rname, DNS_MAX_CNAME_LEN);
|
||||
ptr += strnlen(soa->rname, DNS_MAX_CNAME_LEN - 1) + 1;
|
||||
*((unsigned int *)ptr) = soa->serial;
|
||||
ptr += 4;
|
||||
@@ -650,12 +656,12 @@ int dns_get_SOA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(soa->mname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
|
||||
safe_strncpy(soa->mname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
|
||||
ptr += strnlen(soa->mname, DNS_MAX_CNAME_LEN - 1) + 1;
|
||||
if (ptr - data >= len) {
|
||||
return -1;
|
||||
}
|
||||
strncpy(soa->rname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
|
||||
safe_strncpy(soa->rname, (char *)ptr, DNS_MAX_CNAME_LEN - 1);
|
||||
ptr += strnlen(soa->rname, DNS_MAX_CNAME_LEN - 1) + 1;
|
||||
if (ptr - data + 20 > len) {
|
||||
return -1;
|
||||
@@ -955,7 +961,7 @@ static int _dns_decode_domain(struct dns_context *context, char *output, int siz
|
||||
}
|
||||
ptr = context->data + len;
|
||||
if (ptr > context->data + context->maxsize) {
|
||||
tlog(TLOG_DEBUG, "length is not enouth %u:%ld, %p, %p", context->maxsize, (long)(ptr - context->data), context->ptr, context->data);
|
||||
tlog(TLOG_DEBUG, "length is not enough %u:%ld, %p, %p", context->maxsize, (long)(ptr - context->data), context->ptr, context->data);
|
||||
return -1;
|
||||
}
|
||||
is_compressed = 1;
|
||||
@@ -973,7 +979,7 @@ static int _dns_decode_domain(struct dns_context *context, char *output, int siz
|
||||
}
|
||||
|
||||
if (ptr > context->data + context->maxsize) {
|
||||
tlog(TLOG_DEBUG, "length is not enouth %u:%ld, %p, %p", context->maxsize, (long)(ptr - context->data), context->ptr, context->data);
|
||||
tlog(TLOG_DEBUG, "length is not enough %u:%ld, %p, %p", context->maxsize, (long)(ptr - context->data), context->ptr, context->data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -982,7 +988,7 @@ static int _dns_decode_domain(struct dns_context *context, char *output, int siz
|
||||
/* copy sub string */
|
||||
copy_len = (len < size - output_len) ? len : size - 1 - output_len;
|
||||
if ((ptr + copy_len) > (context->data + context->maxsize)) {
|
||||
tlog(TLOG_DEBUG, "length is not enouth %u:%ld, %p, %p", context->maxsize, (long)(ptr - context->data), context->ptr, context->data);
|
||||
tlog(TLOG_DEBUG, "length is not enough %u:%ld, %p, %p", context->maxsize, (long)(ptr - context->data), context->ptr, context->data);
|
||||
return -1;
|
||||
}
|
||||
memcpy(output, ptr, copy_len);
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
#include "dns_cache.h"
|
||||
#include "stringutil.h"
|
||||
#include "tlog.h"
|
||||
#include <pthread.h>
|
||||
|
||||
#define DNS_CACHE_MAX_HITNUM 5000
|
||||
#define DNS_CACHE_HITNUM_STEP 2
|
||||
#define DNS_CACHE_HITNUM_STEP_MAX 6
|
||||
|
||||
struct dns_cache_head {
|
||||
DECLARE_HASHTABLE(cache_hash, 10);
|
||||
struct list_head cache_list;
|
||||
@@ -24,7 +29,7 @@ int dns_cache_init(int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __attribute__((unused)) struct dns_cache *_dns_cache_last(void)
|
||||
static __attribute__((unused)) struct dns_cache *_dns_cache_last(void)
|
||||
{
|
||||
return list_last_entry(&dns_cache_head.cache_list, struct dns_cache, list);
|
||||
}
|
||||
@@ -110,7 +115,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
|
||||
}
|
||||
|
||||
if (cname) {
|
||||
strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
dns_cache->cname_ttl = cname_ttl;
|
||||
}
|
||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||
@@ -119,7 +124,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
|
||||
return 0;
|
||||
errout_unlock:
|
||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||
//errout:
|
||||
// errout:
|
||||
if (dns_cache) {
|
||||
dns_cache_release(dns_cache);
|
||||
}
|
||||
@@ -154,11 +159,12 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
|
||||
|
||||
key = hash_string(domain);
|
||||
key = jhash(&qtype, sizeof(qtype), key);
|
||||
strncpy(dns_cache->domain, domain, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(dns_cache->domain, domain, DNS_MAX_CNAME_LEN);
|
||||
dns_cache->cname[0] = 0;
|
||||
dns_cache->qtype = qtype;
|
||||
dns_cache->ttl = ttl;
|
||||
atomic_set(&dns_cache->hitnum, 2);
|
||||
atomic_set(&dns_cache->hitnum, 3);
|
||||
dns_cache->hitnum_update_add = DNS_CACHE_HITNUM_STEP;
|
||||
dns_cache->del_pending = 0;
|
||||
dns_cache->speed = speed;
|
||||
atomic_set(&dns_cache->ref, 1);
|
||||
@@ -178,7 +184,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
|
||||
}
|
||||
|
||||
if (cname) {
|
||||
strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(dns_cache->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
dns_cache->cname_ttl = cname_ttl;
|
||||
}
|
||||
|
||||
@@ -273,13 +279,33 @@ void dns_cache_delete(struct dns_cache *dns_cache)
|
||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||
}
|
||||
|
||||
int dns_cache_hitnum_dec_get(struct dns_cache *dns_cache)
|
||||
{
|
||||
int hitnum = 0;
|
||||
pthread_mutex_lock(&dns_cache_head.lock);
|
||||
hitnum = atomic_dec_return(&dns_cache->hitnum);
|
||||
if (dns_cache->hitnum_update_add > DNS_CACHE_HITNUM_STEP) {
|
||||
dns_cache->hitnum_update_add--;
|
||||
}
|
||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||
|
||||
return hitnum;
|
||||
}
|
||||
|
||||
void dns_cache_update(struct dns_cache *dns_cache)
|
||||
{
|
||||
pthread_mutex_lock(&dns_cache_head.lock);
|
||||
if (!list_empty(&dns_cache->list)) {
|
||||
list_del_init(&dns_cache->list);
|
||||
list_add_tail(&dns_cache->list, &dns_cache_head.cache_list);
|
||||
atomic_inc(&dns_cache->hitnum);
|
||||
atomic_add(dns_cache->hitnum_update_add, &dns_cache->hitnum);
|
||||
if (atomic_read(&dns_cache->hitnum) > DNS_CACHE_MAX_HITNUM) {
|
||||
atomic_set(&dns_cache->hitnum, DNS_CACHE_MAX_HITNUM);
|
||||
}
|
||||
|
||||
if (dns_cache->hitnum_update_add < DNS_CACHE_HITNUM_STEP_MAX) {
|
||||
dns_cache->hitnum_update_add++;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&dns_cache_head.lock);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DNS_CACHE_TTL_MIN 30
|
||||
|
||||
struct dns_cache {
|
||||
@@ -19,9 +23,10 @@ struct dns_cache {
|
||||
char domain[DNS_MAX_CNAME_LEN];
|
||||
char cname[DNS_MAX_CNAME_LEN];
|
||||
unsigned int cname_ttl;
|
||||
unsigned int ttl;;
|
||||
unsigned int ttl;
|
||||
int speed;
|
||||
atomic_t hitnum;
|
||||
int hitnum_update_add;
|
||||
int del_pending;
|
||||
time_t insert_time;
|
||||
dns_type_t qtype;
|
||||
@@ -46,6 +51,8 @@ void dns_cache_get(struct dns_cache *dns_cache);
|
||||
|
||||
void dns_cache_release(struct dns_cache *dns_cache);
|
||||
|
||||
int dns_cache_hitnum_dec_get(struct dns_cache *dns_cache);
|
||||
|
||||
void dns_cache_update(struct dns_cache *dns_cache);
|
||||
|
||||
typedef void dns_cache_preinvalid_callback(struct dns_cache *dns_cache);
|
||||
@@ -56,4 +63,7 @@ int dns_cache_get_ttl(struct dns_cache *dns_cache);
|
||||
|
||||
void dns_cache_destroy(void);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
#endif // !_SMARTDNS_CACHE_H
|
||||
|
||||
310
src/dns_client.c
310
src/dns_client.c
@@ -16,6 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "dns_client.h"
|
||||
#include "atomic.h"
|
||||
#include "dns.h"
|
||||
@@ -29,6 +30,7 @@
|
||||
#include "util.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/filter.h>
|
||||
#include <netdb.h>
|
||||
@@ -44,6 +46,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -57,6 +60,8 @@
|
||||
#define DNS_TCP_CONNECT_TIMEOUT (5)
|
||||
#define DNS_QUERY_TIMEOUT (500)
|
||||
#define DNS_QUERY_RETRY (3)
|
||||
#define SOCKET_PRIORITY (6)
|
||||
#define SOCKET_IP_TOS (IPTOS_LOWDELAY | IPTOS_RELIABILITY)
|
||||
|
||||
#ifndef TCP_FASTOPEN_CONNECT
|
||||
#define TCP_FASTOPEN_CONNECT 30
|
||||
@@ -241,7 +246,7 @@ struct dns_query_struct {
|
||||
static struct dns_client client;
|
||||
static atomic_t dns_client_sid = ATOMIC_INIT(0);
|
||||
static LIST_HEAD(pending_servers);
|
||||
pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int dns_client_has_bootstrap_dns = 0;
|
||||
|
||||
/* get addr info */
|
||||
@@ -435,7 +440,7 @@ static int _dns_client_add_to_pending_group(char *group_name, char *server_ip, i
|
||||
goto errout;
|
||||
}
|
||||
memset(group, 0, sizeof(*group));
|
||||
strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
|
||||
safe_strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
|
||||
|
||||
pthread_mutex_lock(&pending_server_mutex);
|
||||
list_add_tail(&group->list, &pending->group_list);
|
||||
@@ -451,7 +456,7 @@ errout:
|
||||
}
|
||||
|
||||
/* add server to group */
|
||||
int _dns_client_add_to_group_pending(char *group_name, char *server_ip, int port, dns_server_type_t server_type, int ispending)
|
||||
static int _dns_client_add_to_group_pending(char *group_name, char *server_ip, int port, dns_server_type_t server_type, int ispending)
|
||||
{
|
||||
struct dns_server_info *server_info = NULL;
|
||||
|
||||
@@ -547,7 +552,7 @@ int dns_client_add_group(char *group_name)
|
||||
|
||||
memset(group, 0, sizeof(*group));
|
||||
INIT_LIST_HEAD(&group->head);
|
||||
strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
|
||||
safe_strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
|
||||
key = hash_string(group_name);
|
||||
hash_add(client.group, &group->node, key);
|
||||
|
||||
@@ -623,6 +628,37 @@ int dns_client_spki_decode(const char *spki, unsigned char *spki_data_out)
|
||||
return spki_data_len;
|
||||
}
|
||||
|
||||
static char *_dns_client_server_get_tls_host_verify(struct dns_server_info *server_info)
|
||||
{
|
||||
char *tls_host_verify = NULL;
|
||||
|
||||
switch (server_info->type) {
|
||||
case DNS_SERVER_UDP: {
|
||||
} break;
|
||||
case DNS_SERVER_HTTPS: {
|
||||
struct client_dns_server_flag_https *flag_https = &server_info->flags.https;
|
||||
tls_host_verify = flag_https->tls_host_verify;
|
||||
} break;
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
|
||||
tls_host_verify = flag_tls->tls_host_verify;
|
||||
} break;
|
||||
case DNS_SERVER_TCP:
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tls_host_verify) {
|
||||
if (tls_host_verify[0] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return tls_host_verify;
|
||||
}
|
||||
|
||||
static char *_dns_client_server_get_spki(struct dns_server_info *server_info, int *spki_len)
|
||||
{
|
||||
*spki_len = 0;
|
||||
@@ -640,7 +676,6 @@ static char *_dns_client_server_get_spki(struct dns_server_info *server_info, in
|
||||
spki = flag_tls->spki;
|
||||
*spki_len = flag_tls->spi_len;
|
||||
} break;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
break;
|
||||
default:
|
||||
@@ -660,7 +695,6 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
{
|
||||
struct dns_server_info *server_info = NULL;
|
||||
struct addrinfo *gai = NULL;
|
||||
unsigned char *spki_data = NULL;
|
||||
int spki_data_len = 0;
|
||||
int ttl = 0;
|
||||
char port_s[8];
|
||||
@@ -683,9 +717,9 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
spki_data_len = flag_https->spi_len;
|
||||
if (flag_https->httphost[0] == 0) {
|
||||
if (server_host) {
|
||||
strncpy(flag_https->httphost, server_host, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(flag_https->httphost, server_host, DNS_MAX_CNAME_LEN);
|
||||
} else {
|
||||
strncpy(flag_https->httphost, server_ip, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(flag_https->httphost, server_ip, DNS_MAX_CNAME_LEN);
|
||||
}
|
||||
}
|
||||
sock_type = SOCK_STREAM;
|
||||
@@ -695,7 +729,6 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
spki_data_len = flag_tls->spi_len;
|
||||
sock_type = SOCK_STREAM;
|
||||
} break;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
sock_type = SOCK_STREAM;
|
||||
break;
|
||||
@@ -731,7 +764,7 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
}
|
||||
|
||||
memset(server_info, 0, sizeof(*server_info));
|
||||
strncpy(server_info->ip, server_ip, sizeof(server_info->ip));
|
||||
safe_strncpy(server_info->ip, server_ip, sizeof(server_info->ip));
|
||||
server_info->port = port;
|
||||
server_info->ai_family = gai->ai_family;
|
||||
server_info->ai_addrlen = gai->ai_addrlen;
|
||||
@@ -752,7 +785,11 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
|
||||
/* if server type is TLS, create ssl context */
|
||||
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS) {
|
||||
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
|
||||
server_info->ssl_ctx = SSL_CTX_new(TLS_client_method());
|
||||
#else
|
||||
server_info->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
#endif
|
||||
if (server_info->ssl_ctx == NULL) {
|
||||
tlog(TLOG_ERROR, "init ssl failed.");
|
||||
goto errout;
|
||||
@@ -791,10 +828,6 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (spki_data) {
|
||||
free(spki_data);
|
||||
}
|
||||
|
||||
if (server_info) {
|
||||
if (server_info->ssl_ctx) {
|
||||
SSL_CTX_free(server_info->ssl_ctx);
|
||||
@@ -915,7 +948,7 @@ static int _dns_client_server_pending(char *server_ip, int port, dns_server_type
|
||||
}
|
||||
memset(pending, 0, sizeof(*pending));
|
||||
|
||||
strncpy(pending->host, server_ip, DNS_HOSTNAME_LEN);
|
||||
safe_strncpy(pending->host, server_ip, DNS_HOSTNAME_LEN);
|
||||
pending->port = port;
|
||||
pending->type = server_type;
|
||||
pending->ping_time_v4 = -1;
|
||||
@@ -939,7 +972,8 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _dns_client_add_server_pending(char *server_ip, char *server_host, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags, int ispending)
|
||||
static int _dns_client_add_server_pending(char *server_ip, char *server_host, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags,
|
||||
int ispending)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -1235,10 +1269,12 @@ static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *
|
||||
|
||||
/* get query reference */
|
||||
query = _dns_client_get_request(packet->head.id, domain);
|
||||
if (query == NULL || (query && has_opt == 0 && server_info->flags.result_flag & DNSSERVER_FLAG_CHECK_EDNS)) {
|
||||
if (query) {
|
||||
_dns_client_query_release(query);
|
||||
}
|
||||
if (query == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (has_opt == 0 && server_info->flags.result_flag & DNSSERVER_FLAG_CHECK_EDNS) {
|
||||
_dns_client_query_release(query);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1278,6 +1314,8 @@ static int _dns_client_create_socket_udp(struct dns_server_info *server_info)
|
||||
struct epoll_event event;
|
||||
const int on = 1;
|
||||
const int val = 255;
|
||||
const int priority = SOCKET_PRIORITY;
|
||||
const int ip_tos = SOCKET_IP_TOS;
|
||||
|
||||
fd = socket(server_info->ai_family, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
@@ -1297,6 +1335,8 @@ static int _dns_client_create_socket_udp(struct dns_server_info *server_info)
|
||||
server_info->status = DNS_SERVER_STATUS_CONNECTIONLESS;
|
||||
setsockopt(server_info->fd, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
|
||||
setsockopt(server_info->fd, SOL_IP, IP_TTL, &val, sizeof(val));
|
||||
setsockopt(server_info->fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));
|
||||
setsockopt(server_info->fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
|
||||
if (server_info->ai_family == AF_INET6) {
|
||||
/* for recving ip ttl value */
|
||||
setsockopt(server_info->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
|
||||
@@ -1318,6 +1358,8 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
|
||||
int fd = 0;
|
||||
struct epoll_event event;
|
||||
int yes = 1;
|
||||
const int priority = SOCKET_PRIORITY;
|
||||
const int ip_tos = SOCKET_IP_TOS;
|
||||
|
||||
fd = socket(server_info->ai_family, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
@@ -1336,6 +1378,8 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
|
||||
}
|
||||
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
|
||||
setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) {
|
||||
if (errno != EINPROGRESS) {
|
||||
@@ -1372,6 +1416,8 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
|
||||
struct epoll_event event;
|
||||
SSL *ssl = NULL;
|
||||
int yes = 1;
|
||||
const int priority = SOCKET_PRIORITY;
|
||||
const int ip_tos = SOCKET_IP_TOS;
|
||||
|
||||
if (server_info->ssl_ctx == NULL) {
|
||||
tlog(TLOG_ERROR, "create ssl ctx failed.");
|
||||
@@ -1401,6 +1447,8 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
|
||||
|
||||
// ? this cause ssl crash ?
|
||||
// setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
|
||||
setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) {
|
||||
if (errno != EINPROGRESS) {
|
||||
@@ -1571,17 +1619,17 @@ static int _dns_client_socket_ssl_send(SSL *ssl, const void *buf, int num)
|
||||
break;
|
||||
case SSL_ERROR_SSL:
|
||||
ssl_err = ERR_get_error();
|
||||
if (ERR_GET_REASON(ssl_err) == SSL_R_UNINITIALIZED) {
|
||||
if (ERR_GET_REASON(ssl_err) == SSL_R_UNINITIALIZED || ERR_GET_REASON(ssl_err) == SSL_R_PROTOCOL_IS_SHUTDOWN) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tlog(TLOG_ERROR, "SSL write fail error no: %s(%ld)\n", ERR_reason_error_string(ssl_err), ssl_err);
|
||||
tlog(TLOG_DEBUG, "SSL write fail error no: %s(%ld)\n", ERR_reason_error_string(ssl_err), ssl_err);
|
||||
errno = EFAULT;
|
||||
ret = -1;
|
||||
break;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
tlog(TLOG_ERROR, "SSL syscall failed, %s", strerror(errno));
|
||||
tlog(TLOG_DEBUG, "SSL syscall failed, %s", strerror(errno));
|
||||
return ret;
|
||||
default:
|
||||
errno = EFAULT;
|
||||
@@ -1678,13 +1726,91 @@ static int _dns_client_socket_recv(struct dns_server_info *server_info)
|
||||
}
|
||||
}
|
||||
|
||||
static int _dns_client_process_tcp_buff(struct dns_server_info *server_info)
|
||||
{
|
||||
int len = 0;
|
||||
int dns_packet_len = 0;
|
||||
struct http_head *http_head = NULL;
|
||||
unsigned char *inpacket_data = NULL;
|
||||
|
||||
while (1) {
|
||||
if (server_info->type == DNS_SERVER_HTTPS) {
|
||||
http_head = http_head_init(4096);
|
||||
if (http_head == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
len = http_head_parse(http_head, (char *)server_info->recv_buff.data, server_info->recv_buff.len);
|
||||
if (len < 0) {
|
||||
tlog(TLOG_DEBUG, "remote server not supported.");
|
||||
if (len == -1) {
|
||||
break;
|
||||
}
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (http_head_get_httpcode(http_head) != 200) {
|
||||
tlog(TLOG_WARN, "http server query failed, server return http code : %d, %s", http_head_get_httpcode(http_head),
|
||||
http_head_get_httpcode_msg(http_head));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
dns_packet_len = http_head_get_data_len(http_head);
|
||||
inpacket_data = (unsigned char *)http_head_get_data(http_head);
|
||||
} else {
|
||||
/* tcp result format
|
||||
* | len (short) | dns query result |
|
||||
*/
|
||||
inpacket_data = server_info->recv_buff.data;
|
||||
len = ntohs(*((unsigned short *)(inpacket_data)));
|
||||
if (len <= 0 || len >= DNS_IN_PACKSIZE) {
|
||||
/* data len is invalid */
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (len > server_info->recv_buff.len - 2) {
|
||||
/* len is not expceded, wait and recv */
|
||||
break;
|
||||
}
|
||||
|
||||
inpacket_data = server_info->recv_buff.data + 2;
|
||||
dns_packet_len = len;
|
||||
len += 2;
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "recv tcp packet from %s, len = %d", server_info->ip, len);
|
||||
/* process result */
|
||||
if (_dns_client_recv(server_info, inpacket_data, dns_packet_len, &server_info->addr, server_info->ai_addrlen) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (http_head) {
|
||||
http_head_destroy(http_head);
|
||||
http_head = NULL;
|
||||
}
|
||||
|
||||
server_info->recv_buff.len -= len;
|
||||
|
||||
/* move to next result */
|
||||
if (server_info->recv_buff.len > 0) {
|
||||
memmove(server_info->recv_buff.data, server_info->recv_buff.data + len, server_info->recv_buff.len);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (http_head) {
|
||||
http_head_destroy(http_head);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _dns_client_process_tcp(struct dns_server_info *server_info, struct epoll_event *event, unsigned long now)
|
||||
{
|
||||
int len;
|
||||
int dns_packet_len = 0;
|
||||
int ret = -1;
|
||||
struct http_head *http_head = NULL;
|
||||
unsigned char *inpacket_data = NULL;
|
||||
|
||||
if (event->events & EPOLLIN) {
|
||||
/* receive from tcp */
|
||||
@@ -1721,77 +1847,14 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
|
||||
}
|
||||
|
||||
time(&server_info->last_recv);
|
||||
|
||||
server_info->recv_buff.len += len;
|
||||
if (server_info->recv_buff.len < 2) {
|
||||
/* wait and recv */
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (server_info->type == DNS_SERVER_HTTPS) {
|
||||
http_head = http_head_init(4096);
|
||||
if (http_head == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
len = http_head_parse(http_head, (char *)server_info->recv_buff.data, server_info->recv_buff.len);
|
||||
if (len < 0) {
|
||||
http_head_destroy(http_head);
|
||||
if (len == -1) {
|
||||
break;
|
||||
}
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (http_head_get_httpcode(http_head) != 200) {
|
||||
tlog(TLOG_WARN, "http server query failed, server return http code : %d, %s", http_head_get_httpcode(http_head),
|
||||
http_head_get_httpcode_msg(http_head));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
dns_packet_len = http_head_get_data_len(http_head);
|
||||
inpacket_data = (unsigned char *)http_head_get_data(http_head);
|
||||
} else {
|
||||
/* tcp result format
|
||||
* | len (short) | dns query result |
|
||||
*/
|
||||
inpacket_data = server_info->recv_buff.data;
|
||||
len = ntohs(*((unsigned short *)(inpacket_data)));
|
||||
if (len <= 0 || len >= DNS_IN_PACKSIZE) {
|
||||
/* data len is invalid */
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (len > server_info->recv_buff.len - 2) {
|
||||
/* len is not expceded, wait and recv */
|
||||
break;
|
||||
}
|
||||
|
||||
inpacket_data = server_info->recv_buff.data + 2;
|
||||
dns_packet_len = len;
|
||||
len += 2;
|
||||
}
|
||||
tlog(TLOG_DEBUG, "recv tcp packet from %s, len = %d", server_info->ip, len);
|
||||
|
||||
/* process result */
|
||||
if (_dns_client_recv(server_info, inpacket_data, dns_packet_len, &server_info->addr, server_info->ai_addrlen) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (http_head) {
|
||||
http_head_destroy(http_head);
|
||||
http_head = NULL;
|
||||
}
|
||||
|
||||
server_info->recv_buff.len -= len;
|
||||
|
||||
/* move to next result */
|
||||
if (server_info->recv_buff.len > 0) {
|
||||
memmove(server_info->recv_buff.data, server_info->recv_buff.data + len, server_info->recv_buff.len);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (_dns_client_process_tcp_buff(server_info) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1807,6 +1870,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
|
||||
if (server_info->status != DNS_SERVER_STATUS_CONNECTED) {
|
||||
server_info->status = DNS_SERVER_STATUS_DISCONNECTED;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&client.server_list_lock);
|
||||
if (server_info->send_buff.len > 0) {
|
||||
/* send existing send_buffer data */
|
||||
@@ -1825,12 +1889,12 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
|
||||
memmove(server_info->send_buff.data, server_info->send_buff.data + len, server_info->send_buff.len);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
|
||||
/* still remain data, retry */
|
||||
if (server_info->send_buff.len > 0) {
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
return 0;
|
||||
}
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
|
||||
/* clear epllout event */
|
||||
memset(&event, 0, sizeof(event));
|
||||
@@ -1840,17 +1904,11 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
|
||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
if (http_head) {
|
||||
http_head_destroy(http_head);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&client.server_list_lock);
|
||||
server_info->recv_buff.len = 0;
|
||||
server_info->send_buff.len = 0;
|
||||
@@ -1869,6 +1927,34 @@ static inline int _dns_client_to_hex(int c)
|
||||
}
|
||||
}
|
||||
|
||||
static int _dns_client_tls_matchName(const char *host, const char *pattern, int size)
|
||||
{
|
||||
int match = -1;
|
||||
int i = 0, j = 0;
|
||||
|
||||
while (i < size && host[j] != '\0') {
|
||||
if (toupper(pattern[i]) == toupper(host[j])) {
|
||||
i++;
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
if (pattern[i] == '*') {
|
||||
while (host[j] != '.' && host[j] != '\0') {
|
||||
j++;
|
||||
}
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == size && host[j] == '\0') {
|
||||
match = 0;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
{
|
||||
X509 *cert = NULL;
|
||||
@@ -1881,6 +1967,7 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
unsigned char *key_sha256 = NULL;
|
||||
char *spki = NULL;
|
||||
int spki_len = 0;
|
||||
char *tls_host_verify = NULL;
|
||||
|
||||
cert = SSL_get_peer_certificate(server_info->ssl);
|
||||
if (cert == NULL) {
|
||||
@@ -1891,6 +1978,15 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, peer_CN, 256);
|
||||
tlog(TLOG_DEBUG, "peer CN: %s", peer_CN);
|
||||
|
||||
/* check tls host */
|
||||
tls_host_verify = _dns_client_server_get_tls_host_verify(server_info);
|
||||
if (tls_host_verify) {
|
||||
if (_dns_client_tls_matchName(peer_CN, tls_host_verify, strnlen(tls_host_verify, DNS_MAX_CNAME_LEN)) != 0) {
|
||||
tlog(TLOG_INFO, "server %s CN is invalid, peer CN: %s, expect CN: %s", server_info->ip, peer_CN, tls_host_verify);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* get spki pin */
|
||||
key_len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
|
||||
if (key_len <= 0) {
|
||||
@@ -1991,6 +2087,7 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
|
||||
tlog(TLOG_DEBUG, "reused session");
|
||||
} else {
|
||||
tlog(TLOG_DEBUG, "new session");
|
||||
pthread_mutex_lock(&client.server_list_lock);
|
||||
if (server_info->ssl_session) {
|
||||
/* free session */
|
||||
SSL_SESSION_free(server_info->ssl_session);
|
||||
@@ -1999,11 +2096,13 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
|
||||
|
||||
if (_dns_client_tls_verify(server_info) != 0) {
|
||||
tlog(TLOG_WARN, "peer %s verify failed.", server_info->ip);
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* save ssl session for next request */
|
||||
server_info->ssl_session = SSL_get1_session(server_info->ssl);
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
}
|
||||
|
||||
server_info->status = DNS_SERVER_STATUS_CONNECTED;
|
||||
@@ -2154,7 +2253,7 @@ static int _dns_client_send_tls(struct dns_server_info *server_info, void *packe
|
||||
|
||||
send_len = _dns_client_socket_ssl_send(server_info->ssl, inpacket, len);
|
||||
if (send_len < 0) {
|
||||
if (errno == EAGAIN || server_info->ssl == NULL) {
|
||||
if (errno == EAGAIN || errno == EPIPE || server_info->ssl == NULL ) {
|
||||
/* save data to buffer, and retry when EPOLLOUT is available */
|
||||
return _dns_client_send_data_to_buffer(server_info, inpacket, len);
|
||||
} else if (server_info->ssl && errno != ENOMEM) {
|
||||
@@ -2204,7 +2303,7 @@ static int _dns_client_send_https(struct dns_server_info *server_info, void *pac
|
||||
|
||||
send_len = _dns_client_socket_ssl_send(server_info->ssl, inpacket, http_len);
|
||||
if (send_len < 0) {
|
||||
if (errno == EAGAIN || server_info->ssl == NULL) {
|
||||
if (errno == EAGAIN || errno == EPIPE || server_info->ssl == NULL ) {
|
||||
/* save data to buffer, and retry when EPOLLOUT is available */
|
||||
return _dns_client_send_data_to_buffer(server_info, inpacket, http_len);
|
||||
} else if (server_info->ssl && errno != ENOMEM) {
|
||||
@@ -2375,7 +2474,7 @@ int dns_client_query(char *domain, int qtype, dns_client_callback callback, void
|
||||
atomic_set(&query->dns_request_sent, 0);
|
||||
atomic_set(&query->retry_count, DNS_QUERY_RETRY);
|
||||
hash_init(query->replied_map);
|
||||
strncpy(query->domain, domain, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(query->domain, domain, DNS_MAX_CNAME_LEN);
|
||||
query->user_ptr = user_ptr;
|
||||
query->callback = callback;
|
||||
query->qtype = qtype;
|
||||
@@ -2418,7 +2517,6 @@ errout_del_list:
|
||||
query = NULL;
|
||||
errout:
|
||||
if (query) {
|
||||
tlog(TLOG_ERROR, "release %p", query);
|
||||
free(query);
|
||||
}
|
||||
return -1;
|
||||
@@ -2460,14 +2558,14 @@ static int _dns_client_pending_server_resolve(char *domain, dns_rtcode_t rtcode,
|
||||
pending->ping_time_v4 = -1;
|
||||
if (rtcode == DNS_RC_NOERROR) {
|
||||
pending->ping_time_v4 = ping_time;
|
||||
strncpy(pending->ipv4, ip, DNS_HOSTNAME_LEN);
|
||||
safe_strncpy(pending->ipv4, ip, DNS_HOSTNAME_LEN);
|
||||
}
|
||||
} else if (addr_type == DNS_T_AAAA) {
|
||||
pending->has_v6 = 1;
|
||||
pending->ping_time_v6 = -1;
|
||||
if (rtcode == DNS_RC_NOERROR) {
|
||||
pending->ping_time_v6 = ping_time;
|
||||
strncpy(pending->ipv6, ip, DNS_HOSTNAME_LEN);
|
||||
safe_strncpy(pending->ipv6, ip, DNS_HOSTNAME_LEN);
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
@@ -2542,9 +2640,9 @@ static void _dns_client_add_pending_servers(void)
|
||||
/* if has no bootstrap DNS, just call getaddrinfo to get address */
|
||||
if (dns_client_has_bootstrap_dns == 0) {
|
||||
if (_dns_client_add_pendings(pending, pending->host) != 0) {
|
||||
pthread_mutex_unlock(&pending_server_mutex);
|
||||
tlog(TLOG_ERROR, "add pending DNS server %s failed", pending->host);
|
||||
exit(1);
|
||||
pthread_mutex_unlock(&pending_server_mutex);
|
||||
return;
|
||||
}
|
||||
list_del_init(&pending->list);
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
#define _SMART_DNS_CLIENT_H
|
||||
|
||||
#include "dns.h"
|
||||
#define DNS_SERVER_SPKI_LEN 64
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DNS_SERVER_SPKI_LEN 64
|
||||
#define DNS_SERVER_GROUP_DEFAULT "default"
|
||||
|
||||
typedef enum {
|
||||
@@ -20,8 +25,9 @@ typedef enum dns_result_type {
|
||||
} dns_result_type;
|
||||
|
||||
#define DNSSERVER_FLAG_BLACKLIST_IP (0x1 << 0)
|
||||
#define DNSSERVER_FLAG_CHECK_EDNS (0x1 << 1)
|
||||
#define DNSSERVER_FLAG_CHECK_TTL (0x1 << 2)
|
||||
#define DNSSERVER_FLAG_WHITELIST_IP (0x1 << 1)
|
||||
#define DNSSERVER_FLAG_CHECK_EDNS (0x1 << 2)
|
||||
#define DNSSERVER_FLAG_CHECK_TTL (0x1 << 3)
|
||||
|
||||
int dns_client_init(void);
|
||||
|
||||
@@ -44,6 +50,7 @@ struct client_dns_server_flag_tls {
|
||||
char spki[DNS_SERVER_SPKI_LEN];
|
||||
int spi_len;
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_verify[DNS_MAX_CNAME_LEN];
|
||||
};
|
||||
|
||||
struct client_dns_server_flag_https {
|
||||
@@ -52,6 +59,7 @@ struct client_dns_server_flag_https {
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char httphost[DNS_MAX_CNAME_LEN];
|
||||
char path[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_verify[DNS_MAX_CNAME_LEN];
|
||||
};
|
||||
|
||||
struct client_dns_server_flags {
|
||||
@@ -84,4 +92,7 @@ int dns_client_remove_group(char *group_name);
|
||||
|
||||
int dns_server_num(void);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
288
src/dns_conf.c
288
src/dns_conf.c
@@ -4,12 +4,12 @@
|
||||
#include "tlog.h"
|
||||
#include "util.h"
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#define DEFAULT_DNS_CACHE_SIZE 512
|
||||
|
||||
@@ -23,8 +23,8 @@ static struct dns_ipset_table dns_ipset_table;
|
||||
struct dns_group_table dns_group_table;
|
||||
|
||||
/* server ip/port */
|
||||
char dns_conf_server_ip[DNS_MAX_IPLEN];
|
||||
char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
|
||||
struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
|
||||
int dns_conf_bind_ip_num = 0;
|
||||
int dns_conf_tcp_idle_time = 120;
|
||||
|
||||
/* cache */
|
||||
@@ -36,6 +36,11 @@ struct dns_servers dns_conf_servers[DNS_MAX_SERVERS];
|
||||
char dns_conf_server_name[DNS_MAX_SERVER_NAME_LEN];
|
||||
int dns_conf_server_num;
|
||||
|
||||
struct dns_domain_check_order dns_conf_check_order = {
|
||||
.order = {DOMAIN_CHECK_ICMP, DOMAIN_CHECK_TCP},
|
||||
.tcp_port = 80,
|
||||
};
|
||||
|
||||
/* logging */
|
||||
int dns_conf_log_level = TLOG_ERROR;
|
||||
char dns_conf_log_file[DNS_MAX_PATH];
|
||||
@@ -44,6 +49,7 @@ int dns_conf_log_num = 8;
|
||||
|
||||
/* auditing */
|
||||
int dns_conf_audit_enable = 0;
|
||||
int dns_conf_audit_log_SOA;
|
||||
char dns_conf_audit_file[DNS_MAX_PATH];
|
||||
size_t dns_conf_audit_size = 1024 * 1024;
|
||||
int dns_conf_audit_num = 2;
|
||||
@@ -90,7 +96,7 @@ static struct dns_server_groups *_dns_conf_get_group(const char *group_name)
|
||||
}
|
||||
|
||||
memset(group, 0, sizeof(*group));
|
||||
strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
|
||||
safe_strncpy(group->group_name, group_name, DNS_GROUP_NAME_LEN);
|
||||
hash_add(dns_group_table.group, &group->node, key);
|
||||
|
||||
return group;
|
||||
@@ -168,13 +174,15 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
/* clang-format off */
|
||||
static struct option long_options[] = {
|
||||
{"blacklist-ip", no_argument, NULL, 'b'}, /* filtering with blacklist-ip */
|
||||
{"whitelist-ip", no_argument, NULL, 'w'}, /* filtering with whitelist-ip */
|
||||
#ifdef FEATURE_CHECK_EDNS
|
||||
/* experimental feature */
|
||||
{"check-edns", no_argument, NULL, 'e'}, /* check edns */
|
||||
#endif
|
||||
#endif
|
||||
{"spki-pin", required_argument, NULL, 'p'}, /* check SPKI pin */
|
||||
{"host-name", required_argument, NULL, 'h'}, /* host name */
|
||||
{"http-host", required_argument, NULL, 'H'}, /* http host */
|
||||
{"tls-host-verify", required_argument, NULL, 'V' }, /* verify tls hostname */
|
||||
{"group", required_argument, NULL, 'g'}, /* add to group */
|
||||
{"exclude-default-group", no_argument, NULL, 'E'}, /* ecluse this from default group */
|
||||
{NULL, no_argument, NULL, 0}
|
||||
@@ -195,6 +203,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
server->path[0] = '\0';
|
||||
server->hostname[0] = '\0';
|
||||
server->httphost[0] = '\0';
|
||||
server->tls_host_verify[0] = '\0';
|
||||
|
||||
ip = argv[1];
|
||||
|
||||
@@ -202,10 +211,10 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
if (parse_uri(ip, NULL, server->server, &port, server->path) != 0) {
|
||||
return -1;
|
||||
}
|
||||
strncpy(server->hostname, server->server, sizeof(server->hostname));
|
||||
strncpy(server->httphost, server->httphost, sizeof(server->hostname));
|
||||
safe_strncpy(server->hostname, server->server, sizeof(server->hostname));
|
||||
safe_strncpy(server->httphost, server->server, sizeof(server->httphost));
|
||||
if (server->path[0] == 0) {
|
||||
strcpy(server->path, "/");
|
||||
safe_strncpy(server->path, "/", sizeof(server->path));
|
||||
}
|
||||
} else {
|
||||
/* parse ip, port from ip */
|
||||
@@ -232,16 +241,20 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
result_flag |= DNSSERVER_FLAG_BLACKLIST_IP;
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
result_flag |= DNSSERVER_FLAG_WHITELIST_IP;
|
||||
break;
|
||||
}
|
||||
case 'e': {
|
||||
result_flag |= DNSSERVER_FLAG_CHECK_EDNS;
|
||||
break;
|
||||
}
|
||||
case 'h': {
|
||||
strncpy(server->hostname, optarg, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(server->hostname, optarg, DNS_MAX_CNAME_LEN);
|
||||
break;
|
||||
}
|
||||
case 'H': {
|
||||
strncpy(server->httphost, optarg, DNS_MAX_CNAME_LEN);
|
||||
safe_strncpy(server->httphost, optarg, DNS_MAX_CNAME_LEN);
|
||||
break;
|
||||
}
|
||||
case 'E': {
|
||||
@@ -256,7 +269,11 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
strncpy(server->spki, optarg, DNS_MAX_SPKI_LEN);
|
||||
safe_strncpy(server->spki, optarg, DNS_MAX_SPKI_LEN);
|
||||
break;
|
||||
}
|
||||
case 'V': {
|
||||
safe_strncpy(server->tls_host_verify, optarg, DNS_MAX_CNAME_LEN);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -339,7 +356,7 @@ static int _config_domain_rule_add(char *domain, enum domain_rule type, void *ru
|
||||
tlog(TLOG_ERROR, "domain name %s too long", domain);
|
||||
goto errout;
|
||||
}
|
||||
reverse_string(domain_key, domain, len);
|
||||
reverse_string(domain_key, domain, len, 1);
|
||||
domain_key[len] = '.';
|
||||
len++;
|
||||
domain_key[len] = 0;
|
||||
@@ -400,7 +417,7 @@ static int _config_domain_rule_flag_set(char *domain, unsigned int flag)
|
||||
tlog(TLOG_ERROR, "domain %s too long", domain);
|
||||
return -1;
|
||||
}
|
||||
reverse_string(domain_key, domain, len);
|
||||
reverse_string(domain_key, domain, len, 1);
|
||||
domain_key[len] = '.';
|
||||
len++;
|
||||
domain_key[len] = 0;
|
||||
@@ -476,7 +493,7 @@ static const char *_dns_conf_get_ipset(const char *ipsetname)
|
||||
}
|
||||
|
||||
key = hash_string(ipsetname);
|
||||
strncpy(ipset_name->ipsetname, ipsetname, DNS_MAX_IPSET_NAMELEN);
|
||||
safe_strncpy(ipset_name->ipsetname, ipsetname, DNS_MAX_IPSET_NAMELEN);
|
||||
hash_add(dns_ipset_table.ipset, &ipset_name->node, key);
|
||||
|
||||
return ipset_name->ipsetname;
|
||||
@@ -492,7 +509,7 @@ static int _config_ipset(void *data, int argc, char *argv[])
|
||||
{
|
||||
struct dns_ipset_rule *ipset_rule = NULL;
|
||||
char domain[DNS_MAX_CONF_CNAME_LEN];
|
||||
char ipsetname[DNS_MAX_CONF_CNAME_LEN];
|
||||
char ipsetname[DNS_MAX_IPSET_NAMELEN];
|
||||
const char *ipset = NULL;
|
||||
char *begin = NULL;
|
||||
char *end = NULL;
|
||||
@@ -539,7 +556,7 @@ static int _config_ipset(void *data, int argc, char *argv[])
|
||||
/* Process domain option */
|
||||
if (strncmp(end + 1, "-", sizeof("-")) != 0) {
|
||||
/* new ipset domain */
|
||||
strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
|
||||
safe_strncpy(ipsetname, end + 1, DNS_MAX_IPSET_NAMELEN);
|
||||
ipset = _dns_conf_get_ipset(ipsetname);
|
||||
if (ipset == NULL) {
|
||||
goto errout;
|
||||
@@ -722,6 +739,176 @@ errout:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _config_speed_check_mode(void *data, int argc, char *argv[])
|
||||
{
|
||||
char mode[DNS_MAX_OPT_LEN];
|
||||
char *field;
|
||||
char *ptr;
|
||||
int order = 0;
|
||||
int port = 80;
|
||||
int i = 0;
|
||||
|
||||
if (argc <= 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
safe_strncpy(mode, argv[1], sizeof(mode));
|
||||
ptr = mode;
|
||||
do {
|
||||
field = ptr;
|
||||
ptr = strstr(mode, ",");
|
||||
if (field == NULL || order >= DOMAIN_CHECK_NUM) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
*ptr = 0;
|
||||
}
|
||||
|
||||
if (strncmp(field, "ping", sizeof("ping")) == 0) {
|
||||
dns_conf_check_order.order[order] = DOMAIN_CHECK_ICMP;
|
||||
} else if (strstr(field, "tcp") == field) {
|
||||
char *port_str = strstr(field, ":");
|
||||
if (port_str) {
|
||||
port = atoi(port_str + 1);
|
||||
if (port <= 0 || port >= 65535) {
|
||||
port = 80;
|
||||
}
|
||||
}
|
||||
|
||||
dns_conf_check_order.order[order] = DOMAIN_CHECK_TCP;
|
||||
dns_conf_check_order.tcp_port = port;
|
||||
} else if (strncmp(field, "none", sizeof("none")) == 0) {
|
||||
dns_conf_check_order.order[order] = DOMAIN_CHECK_NONE;
|
||||
for (i = order + 1; i < DOMAIN_CHECK_NUM; i++) {
|
||||
dns_conf_check_order.order[i] = DOMAIN_CHECK_NONE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
order++;
|
||||
if (ptr) {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
|
||||
{
|
||||
int index = dns_conf_bind_ip_num;
|
||||
struct dns_bind_ip *bind_ip;
|
||||
char *ip = NULL;
|
||||
int opt = 0;
|
||||
char group_name[DNS_GROUP_NAME_LEN];
|
||||
const char *group = NULL;
|
||||
unsigned int server_flag = 0;
|
||||
|
||||
/* clang-format off */
|
||||
static struct option long_options[] = {
|
||||
{"group", required_argument, NULL, 'g'}, /* add to group */
|
||||
{"no-rule-addr", no_argument, NULL, 'A'},
|
||||
{"no-rule-nameserver", no_argument, NULL, 'N'},
|
||||
{"no-rule-ipset", no_argument, NULL, 'I'},
|
||||
{"no-rule-sni-proxy", no_argument, NULL, 'P'},
|
||||
{"no-rule-soa", no_argument, NULL, 'O'},
|
||||
{"no-speed-check", no_argument, NULL, 'S'},
|
||||
{"no-cache", no_argument, NULL, 'C'},
|
||||
{"no-dualstack-selection", no_argument, NULL, 'D'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
/* clang-format on */
|
||||
if (argc <= 1) {
|
||||
tlog(TLOG_ERROR, "invalid parameter.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (index >= DNS_MAX_SERVERS) {
|
||||
tlog(TLOG_WARN, "exceeds max server number, %s", ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bind_ip = &dns_conf_bind_ip[index];
|
||||
bind_ip->type = type;
|
||||
bind_ip->flags = 0;
|
||||
ip = argv[1];
|
||||
safe_strncpy(bind_ip->ip, ip, DNS_MAX_IPLEN);
|
||||
|
||||
/* process extra options */
|
||||
optind = 1;
|
||||
while (1) {
|
||||
opt = getopt_long_only(argc, argv, "", long_options, NULL);
|
||||
if (opt == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case 'g': {
|
||||
safe_strncpy(group_name, optarg, DNS_GROUP_NAME_LEN);
|
||||
group = _dns_conf_get_group_name(group_name);
|
||||
break;
|
||||
}
|
||||
case 'A': {
|
||||
server_flag |= BIND_FLAG_NO_RULE_ADDR;
|
||||
break;
|
||||
}
|
||||
case 'N': {
|
||||
server_flag |= BIND_FLAG_NO_RULE_NAMESERVER;
|
||||
break;
|
||||
}
|
||||
case 'I': {
|
||||
server_flag |= BIND_FLAG_NO_RULE_IPSET;
|
||||
break;
|
||||
}
|
||||
case 'P': {
|
||||
server_flag |= BIND_FLAG_NO_RULE_SNIPROXY;
|
||||
break;
|
||||
}
|
||||
case 'S': {
|
||||
server_flag |= BIND_FLAG_NO_SPEED_CHECK;
|
||||
break;
|
||||
}
|
||||
case 'C': {
|
||||
server_flag |= BIND_FLAG_NO_CACHE;
|
||||
break;
|
||||
}
|
||||
case 'O': {
|
||||
server_flag |= BIND_FLAG_NO_RULE_SOA;
|
||||
break;
|
||||
}
|
||||
case 'D': {
|
||||
server_flag |= BIND_FLAG_NO_DUALSTACK_SELECTION;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add new server */
|
||||
bind_ip->flags = server_flag;
|
||||
bind_ip->group = group;
|
||||
dns_conf_bind_ip_num++;
|
||||
tlog(TLOG_DEBUG, "bind ip %s, type:%d, flag: %X", ip, type, server_flag);
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _config_bind_ip_udp(void *data, int argc, char *argv[])
|
||||
{
|
||||
return _config_bind_ip(argc, argv, DNS_BIND_TYPE_UDP);
|
||||
}
|
||||
|
||||
static int _config_bind_ip_tcp(void *data, int argc, char *argv[])
|
||||
{
|
||||
return _config_bind_ip(argc, argv, DNS_BIND_TYPE_TCP);
|
||||
}
|
||||
|
||||
static int _config_server_udp(void *data, int argc, char *argv[])
|
||||
{
|
||||
return _config_server(argc, argv, DNS_SERVER_UDP, DEFAULT_DNS_PORT);
|
||||
@@ -794,7 +981,7 @@ static int _config_nameserver(void *data, int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (strncmp(end + 1, "-", sizeof("-")) != 0) {
|
||||
strncpy(group_name, end + 1, DNS_GROUP_NAME_LEN);
|
||||
safe_strncpy(group_name, end + 1, DNS_GROUP_NAME_LEN);
|
||||
group = _dns_conf_get_group_name(group_name);
|
||||
if (group == NULL) {
|
||||
goto errout;
|
||||
@@ -881,11 +1068,17 @@ static int _config_iplist_rule(char *subnet, enum address_rule rule)
|
||||
case ADDRESS_RULE_BLACKLIST:
|
||||
ip_rule->blacklist = 1;
|
||||
break;
|
||||
case ADDRESS_RULE_WHITELIST:
|
||||
ip_rule->whitelist = 1;
|
||||
break;
|
||||
case ADDRESS_RULE_BOGUS:
|
||||
ip_rule->bogus = 1;
|
||||
break;
|
||||
case ADDRESS_RULE_IP_IGNORE:
|
||||
ip_rule->ip_ignore = 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -918,6 +1111,15 @@ static int _conf_ip_ignore(void *data, int argc, char *argv[])
|
||||
return _config_iplist_rule(argv[1], ADDRESS_RULE_IP_IGNORE);
|
||||
}
|
||||
|
||||
static int _conf_whitelist_ip(void *data, int argc, char *argv[])
|
||||
{
|
||||
if (argc <= 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _config_iplist_rule(argv[1], ADDRESS_RULE_WHITELIST);
|
||||
}
|
||||
|
||||
static int _conf_edns_client_subnet(void *data, int argc, char *argv[])
|
||||
{
|
||||
char *slash = NULL;
|
||||
@@ -958,7 +1160,7 @@ static int _conf_edns_client_subnet(void *data, int argc, char *argv[])
|
||||
goto errout;
|
||||
}
|
||||
|
||||
strncpy(ecs->ip, value, DNS_MAX_IPLEN);
|
||||
safe_strncpy(ecs->ip, value, DNS_MAX_IPLEN);
|
||||
ecs->subnet = subnet;
|
||||
ecs->enable = 1;
|
||||
|
||||
@@ -985,7 +1187,7 @@ static int _config_log_level(void *data, int argc, char *argv[])
|
||||
dns_conf_log_level = TLOG_ERROR;
|
||||
} else if (strncmp("fatal", value, MAX_LINE_LEN) == 0) {
|
||||
dns_conf_log_level = TLOG_FATAL;
|
||||
}else {
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -994,8 +1196,8 @@ static int _config_log_level(void *data, int argc, char *argv[])
|
||||
|
||||
static struct config_item _config_item[] = {
|
||||
CONF_STRING("server-name", (char *)dns_conf_server_name, DNS_MAX_SERVER_NAME_LEN),
|
||||
CONF_STRING("bind", dns_conf_server_ip, DNS_MAX_IPLEN),
|
||||
CONF_STRING("bind-tcp", dns_conf_server_tcp_ip, DNS_MAX_IPLEN),
|
||||
CONF_CUSTOM("bind", _config_bind_ip_udp, NULL),
|
||||
CONF_CUSTOM("bind-tcp", _config_bind_ip_tcp, NULL),
|
||||
CONF_CUSTOM("server", _config_server_udp, NULL),
|
||||
CONF_CUSTOM("server-tcp", _config_server_tcp, NULL),
|
||||
CONF_CUSTOM("server-tls", _config_server_tls, NULL),
|
||||
@@ -1004,6 +1206,7 @@ static struct config_item _config_item[] = {
|
||||
CONF_CUSTOM("address", _config_address, NULL),
|
||||
CONF_YESNO("ipset-timeout", &dns_conf_ipset_timeout_enable),
|
||||
CONF_CUSTOM("ipset", _config_ipset, NULL),
|
||||
CONF_CUSTOM("speed-check-mode", _config_speed_check_mode, NULL),
|
||||
CONF_INT("tcp-idle-time", &dns_conf_tcp_idle_time, 0, 3600),
|
||||
CONF_INT("cache-size", &dns_conf_cachesize, 0, CONF_INT_MAX),
|
||||
CONF_YESNO("prefetch-domain", &dns_conf_prefetch),
|
||||
@@ -1014,6 +1217,7 @@ static struct config_item _config_item[] = {
|
||||
CONF_SIZE("log-size", &dns_conf_log_size, 0, 1024 * 1024 * 1024),
|
||||
CONF_INT("log-num", &dns_conf_log_num, 0, 1024),
|
||||
CONF_YESNO("audit-enable", &dns_conf_audit_enable),
|
||||
CONF_YESNO("audit-SOA", &dns_conf_audit_log_SOA),
|
||||
CONF_STRING("audit-file", (char *)&dns_conf_audit_file, DNS_MAX_PATH),
|
||||
CONF_SIZE("audit-size", &dns_conf_audit_size, 0, 1024 * 1024 * 1024),
|
||||
CONF_INT("audit-num", &dns_conf_audit_num, 0, 1024),
|
||||
@@ -1022,6 +1226,7 @@ static struct config_item _config_item[] = {
|
||||
CONF_INT("rr-ttl-max", &dns_conf_rr_ttl_max, 0, CONF_INT_MAX),
|
||||
CONF_YESNO("force-AAAA-SOA", &dns_conf_force_AAAA_SOA),
|
||||
CONF_CUSTOM("blacklist-ip", _config_blacklist_ip, NULL),
|
||||
CONF_CUSTOM("whitelist-ip", _conf_whitelist_ip, NULL),
|
||||
CONF_CUSTOM("bogus-nxdomain", _conf_bogus_nxdomain, NULL),
|
||||
CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
|
||||
CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
|
||||
@@ -1051,11 +1256,13 @@ int config_addtional_file(void *data, int argc, char *argv[])
|
||||
char file_path_dir[DNS_MAX_PATH];
|
||||
|
||||
if (conf_file[0] != '/') {
|
||||
strncpy(file_path_dir, conf_get_conf_file(), DNS_MAX_PATH);
|
||||
safe_strncpy(file_path_dir, conf_get_conf_file(), DNS_MAX_PATH);
|
||||
dirname(file_path_dir);
|
||||
snprintf(file_path, DNS_MAX_PATH, "%s/%s", file_path_dir, conf_file);
|
||||
if (snprintf(file_path, DNS_MAX_PATH, "%s/%s", file_path_dir, conf_file) < 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
strncpy(file_path, conf_file, DNS_MAX_PATH);
|
||||
safe_strncpy(file_path, conf_file, DNS_MAX_PATH);
|
||||
}
|
||||
|
||||
if (access(file_path, R_OK) != 0) {
|
||||
@@ -1093,6 +1300,38 @@ void dns_server_load_exit(void)
|
||||
_config_group_table_destroy();
|
||||
}
|
||||
|
||||
static int _dns_conf_speed_check_mode_verify(void)
|
||||
{
|
||||
int i, j;
|
||||
int has_cap = has_network_raw_cap();
|
||||
int print_log = 0;
|
||||
if (has_cap == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < DOMAIN_CHECK_NUM; i++) {
|
||||
if (dns_conf_check_order.order[i] == DOMAIN_CHECK_ICMP) {
|
||||
for (j = i + 1; j < DOMAIN_CHECK_NUM; j++) {
|
||||
dns_conf_check_order.order[j - 1] = dns_conf_check_order.order[j];
|
||||
}
|
||||
dns_conf_check_order.order[j - 1] = DOMAIN_CHECK_NONE;
|
||||
print_log = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (print_log) {
|
||||
tlog(TLOG_WARN, "speed check by ping is disabled because smartdns does not have network raw privileges");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_conf_load_post(void)
|
||||
{
|
||||
_dns_conf_speed_check_mode_verify();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_server_load_conf(const char *file)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1100,5 +1339,6 @@ int dns_server_load_conf(const char *file)
|
||||
openlog("smartdns", LOG_CONS | LOG_NDELAY, LOG_LOCAL1);
|
||||
ret = load_conf(file, _config_item, _conf_printf);
|
||||
closelog();
|
||||
_dns_conf_load_post();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
#include "list.h"
|
||||
#include "radix.h"
|
||||
|
||||
#ifdef __cpluscplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DNS_MAX_BIND_IP 16
|
||||
#define DNS_MAX_SERVERS 64
|
||||
#define DNS_MAX_SERVER_NAME_LEN 128
|
||||
#define DNS_MAX_IPSET_NAMELEN 32
|
||||
@@ -36,6 +41,17 @@ enum domain_rule {
|
||||
DOMAIN_RULE_MAX,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
DNS_BIND_TYPE_UDP,
|
||||
DNS_BIND_TYPE_TCP,
|
||||
DNS_BIND_TYPE_TLS,
|
||||
} DNS_BIND_TYPE;
|
||||
|
||||
#define DOMAIN_CHECK_NONE 0
|
||||
#define DOMAIN_CHECK_ICMP 1
|
||||
#define DOMAIN_CHECK_TCP 2
|
||||
#define DOMAIN_CHECK_NUM 2
|
||||
|
||||
#define DOMAIN_FLAG_ADDR_SOA (1 << 0)
|
||||
#define DOMAIN_FLAG_ADDR_IPV4_SOA (1 << 1)
|
||||
#define DOMAIN_FLAG_ADDR_IPV6_SOA (1 << 2)
|
||||
@@ -47,6 +63,15 @@ enum domain_rule {
|
||||
|
||||
#define SERVER_FLAG_EXCLUDE_DEFAULT (1 << 0)
|
||||
|
||||
#define BIND_FLAG_NO_RULE_ADDR (1 << 0)
|
||||
#define BIND_FLAG_NO_RULE_NAMESERVER (1 << 1)
|
||||
#define BIND_FLAG_NO_RULE_IPSET (1 << 2)
|
||||
#define BIND_FLAG_NO_RULE_SNIPROXY (1 << 3)
|
||||
#define BIND_FLAG_NO_RULE_SOA (1 << 4)
|
||||
#define BIND_FLAG_NO_SPEED_CHECK (1 << 5)
|
||||
#define BIND_FLAG_NO_CACHE (1 << 6)
|
||||
#define BIND_FLAG_NO_DUALSTACK_SELECTION (1 << 7)
|
||||
|
||||
struct dns_rule_flags {
|
||||
unsigned int flags;
|
||||
};
|
||||
@@ -83,6 +108,11 @@ struct dns_server_groups {
|
||||
struct dns_servers *servers[DNS_MAX_SERVERS];
|
||||
};
|
||||
|
||||
struct dns_domain_check_order {
|
||||
char order[DOMAIN_CHECK_NUM];
|
||||
unsigned short tcp_port;
|
||||
};
|
||||
|
||||
struct dns_group_table {
|
||||
DECLARE_HASHTABLE(group, 8);
|
||||
};
|
||||
@@ -98,6 +128,7 @@ struct dns_servers {
|
||||
char spki[DNS_MAX_SPKI_LEN];
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char httphost[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_verify[DNS_MAX_CNAME_LEN];
|
||||
char path[DNS_MAX_URL_LEN];
|
||||
};
|
||||
|
||||
@@ -114,12 +145,14 @@ struct dns_bogus_ip_address {
|
||||
|
||||
enum address_rule {
|
||||
ADDRESS_RULE_BLACKLIST = 1,
|
||||
ADDRESS_RULE_BOGUS = 2,
|
||||
ADDRESS_RULE_IP_IGNORE = 3,
|
||||
ADDRESS_RULE_WHITELIST = 2,
|
||||
ADDRESS_RULE_BOGUS = 3,
|
||||
ADDRESS_RULE_IP_IGNORE = 4,
|
||||
};
|
||||
|
||||
struct dns_ip_address_rule {
|
||||
unsigned int blacklist : 1;
|
||||
unsigned int whitelist : 1;
|
||||
unsigned int bogus : 1;
|
||||
unsigned int ip_ignore : 1;
|
||||
};
|
||||
@@ -135,8 +168,15 @@ struct dns_conf_address_rule {
|
||||
radix_tree_t *ipv6;
|
||||
};
|
||||
|
||||
extern char dns_conf_server_ip[DNS_MAX_IPLEN];
|
||||
extern char dns_conf_server_tcp_ip[DNS_MAX_IPLEN];
|
||||
struct dns_bind_ip {
|
||||
DNS_BIND_TYPE type;
|
||||
uint32_t flags;
|
||||
char ip[DNS_MAX_IPLEN];
|
||||
const char *group;
|
||||
};
|
||||
|
||||
extern struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
|
||||
extern int dns_conf_bind_ip_num;
|
||||
|
||||
extern int dns_conf_tcp_idle_time;
|
||||
extern int dns_conf_cachesize;
|
||||
@@ -149,10 +189,13 @@ extern char dns_conf_log_file[DNS_MAX_PATH];
|
||||
extern size_t dns_conf_log_size;
|
||||
extern int dns_conf_log_num;
|
||||
|
||||
extern struct dns_domain_check_order dns_conf_check_order;
|
||||
|
||||
extern struct dns_server_groups dns_conf_server_groups[DNS_NAX_GROUP_NUMBER];
|
||||
extern int dns_conf_server_group_num;
|
||||
|
||||
extern int dns_conf_audit_enable;
|
||||
extern int dns_conf_audit_log_SOA;
|
||||
extern char dns_conf_audit_file[DNS_MAX_PATH];
|
||||
extern size_t dns_conf_audit_size;
|
||||
extern int dns_conf_audit_num;
|
||||
@@ -180,5 +223,7 @@ void dns_server_load_exit(void);
|
||||
int dns_server_load_conf(const char *file);
|
||||
|
||||
extern int config_addtional_file(void *data, int argc, char *argv[]);
|
||||
|
||||
#ifdef __cpluscplus
|
||||
}
|
||||
#endif
|
||||
#endif // !_DNS_CONF
|
||||
|
||||
2064
src/dns_server.c
2064
src/dns_server.c
File diff suppressed because it is too large
Load Diff
415
src/fast_ping.c
415
src/fast_ping.c
@@ -30,6 +30,7 @@
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -43,6 +44,9 @@
|
||||
#define PING_MAX_HOSTLEN 128
|
||||
#define ICMP_PACKET_SIZE (1024 * 64)
|
||||
#define ICMP_INPACKET_SIZE 1024
|
||||
#define IPV4_ADDR_LEN 4
|
||||
#define IPV6_ADDR_LEN 16
|
||||
#define SOCKET_PRIORITY (6)
|
||||
|
||||
#ifndef ICMP_FILTER
|
||||
#define ICMP_FILTER 1
|
||||
@@ -215,17 +219,91 @@ static void _fast_ping_install_filter_v4(int sock)
|
||||
}
|
||||
}
|
||||
|
||||
static int _fast_ping_sockaddr_ip_cmp(struct sockaddr *first_addr, socklen_t first_addr_len, struct sockaddr *second_addr, socklen_t second_addr_len)
|
||||
{
|
||||
if (first_addr_len != second_addr_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (first_addr->sa_family != second_addr->sa_family) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (first_addr->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *first_addr_in = (struct sockaddr_in *)first_addr;
|
||||
struct sockaddr_in *second_addr_in = (struct sockaddr_in *)second_addr;
|
||||
if (memcmp(&first_addr_in->sin_addr.s_addr, &second_addr_in->sin_addr.s_addr, IPV4_ADDR_LEN) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *first_addr_in6 = (struct sockaddr_in6 *)first_addr;
|
||||
struct sockaddr_in6 *second_addr_in6 = (struct sockaddr_in6 *)second_addr;
|
||||
if (memcmp(&first_addr_in6->sin6_addr.s6_addr, &second_addr_in6->sin6_addr.s6_addr, IPV4_ADDR_LEN) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t _fast_ping_hash_key(unsigned int sid, struct sockaddr *addr)
|
||||
{
|
||||
uint32_t key = 0;
|
||||
void *sin_addr = NULL;
|
||||
unsigned int sin_addr_len = 0;
|
||||
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr_in;
|
||||
addr_in = (struct sockaddr_in *)addr;
|
||||
sin_addr = &addr_in->sin_addr.s_addr;
|
||||
sin_addr_len = IPV4_ADDR_LEN;
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6;
|
||||
addr_in6 = (struct sockaddr_in6 *)addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||
sin_addr = addr_in6->sin6_addr.s6_addr + 12;
|
||||
sin_addr_len = IPV4_ADDR_LEN;
|
||||
} else {
|
||||
sin_addr = addr_in6->sin6_addr.s6_addr;
|
||||
sin_addr_len = IPV6_ADDR_LEN;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
goto errout;
|
||||
break;
|
||||
}
|
||||
if (sin_addr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
key = jhash(sin_addr, sin_addr_len, 0);
|
||||
key = jhash(&sid, sizeof(sid), key);
|
||||
|
||||
return key;
|
||||
errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct addrinfo *_fast_ping_getaddr(const char *host, const char *port, int type, int protocol)
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result = NULL;
|
||||
int errcode = 0;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_protocol = protocol;
|
||||
if (getaddrinfo(host, port, &hints, &result) != 0) {
|
||||
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
|
||||
errcode = getaddrinfo(host, port, &hints, &result);
|
||||
if (errcode != 0) {
|
||||
tlog(TLOG_ERROR, "get addr info failed. host:%s, port: %s, error %s\n", host, port, gai_strerror(errcode));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -473,6 +551,9 @@ static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
|
||||
struct epoll_event event;
|
||||
int flags;
|
||||
int fd = -1;
|
||||
int yes = 1;
|
||||
const int priority = SOCKET_PRIORITY;
|
||||
const int ip_tos = IP_TOS;
|
||||
|
||||
_fast_ping_close_host_sock(ping_host);
|
||||
|
||||
@@ -483,6 +564,9 @@ static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
|
||||
setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &priority, sizeof(priority));
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
|
||||
|
||||
ping_host->seq++;
|
||||
if (connect(fd, (struct sockaddr *)&ping_host->addr, ping_host->addr_len) != 0) {
|
||||
@@ -558,6 +642,7 @@ static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
|
||||
socklen_t optlen = sizeof(buffsize);
|
||||
const int val = 255;
|
||||
const int on = 1;
|
||||
const int ip_tos = (IPTOS_LOWDELAY | IPTOS_RELIABILITY);
|
||||
|
||||
switch (type) {
|
||||
case FAST_PING_ICMP:
|
||||
@@ -592,6 +677,7 @@ static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&buffsize, optlen);
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&buffsize, optlen);
|
||||
setsockopt(fd, SOL_IP, IP_TTL, &val, sizeof(val));
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.events = EPOLLIN;
|
||||
@@ -655,6 +741,7 @@ static int _fast_ping_create_udp_sock(FAST_PING_TYPE type)
|
||||
struct epoll_event event;
|
||||
const int val = 255;
|
||||
const int on = 1;
|
||||
const int ip_tos = (IPTOS_LOWDELAY | IPTOS_RELIABILITY);
|
||||
|
||||
switch (type) {
|
||||
case FAST_PING_UDP:
|
||||
@@ -686,6 +773,7 @@ static int _fast_ping_create_udp_sock(FAST_PING_TYPE type)
|
||||
|
||||
setsockopt(fd, SOL_IP, IP_TTL, &val, sizeof(val));
|
||||
setsockopt(fd, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on));
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.events = EPOLLIN;
|
||||
@@ -741,8 +829,8 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _fast_ping_print_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno,
|
||||
int ttl, struct timeval *tv, void *userptr)
|
||||
static void _fast_ping_print_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len,
|
||||
int seqno, int ttl, struct timeval *tv, void *userptr)
|
||||
{
|
||||
if (result == PING_RESULT_RESPONSE) {
|
||||
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
||||
@@ -754,111 +842,184 @@ static void _fast_ping_print_result(struct ping_host_struct *ping_host, const ch
|
||||
}
|
||||
}
|
||||
|
||||
static int _fast_ping_get_addr_by_icmp(const char *ip_str, int port, struct addrinfo **out_gai, FAST_PING_TYPE *out_ping_type)
|
||||
{
|
||||
struct addrinfo *gai = NULL;
|
||||
int socktype = 0;
|
||||
int domain = -1;
|
||||
FAST_PING_TYPE ping_type;
|
||||
int sockproto = 0;
|
||||
char *service = NULL;
|
||||
|
||||
socktype = SOCK_RAW;
|
||||
domain = _fast_ping_getdomain(ip_str);
|
||||
if (domain < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
switch (domain) {
|
||||
case AF_INET:
|
||||
sockproto = IPPROTO_ICMP;
|
||||
ping_type = FAST_PING_ICMP;
|
||||
break;
|
||||
case AF_INET6:
|
||||
sockproto = IPPROTO_ICMPV6;
|
||||
ping_type = FAST_PING_ICMP6;
|
||||
break;
|
||||
default:
|
||||
goto errout;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_fast_ping_create_icmp(ping_type) < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
gai = _fast_ping_getaddr(ip_str, service, socktype, sockproto);
|
||||
if (gai == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
*out_gai = gai;
|
||||
*out_ping_type = ping_type;
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (gai) {
|
||||
freeaddrinfo(gai);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _fast_ping_get_addr_by_tcp(const char *ip_str, int port, struct addrinfo **out_gai, FAST_PING_TYPE *out_ping_type)
|
||||
{
|
||||
struct addrinfo *gai = NULL;
|
||||
int socktype = 0;
|
||||
FAST_PING_TYPE ping_type;
|
||||
int sockproto = 0;
|
||||
char *service = NULL;
|
||||
char port_str[MAX_IP_LEN];
|
||||
|
||||
if (port <= 0) {
|
||||
port = 80;
|
||||
}
|
||||
|
||||
sockproto = 0;
|
||||
socktype = SOCK_STREAM;
|
||||
snprintf(port_str, MAX_IP_LEN, "%d", port);
|
||||
service = port_str;
|
||||
ping_type = FAST_PING_TCP;
|
||||
|
||||
gai = _fast_ping_getaddr(ip_str, service, socktype, sockproto);
|
||||
if (gai == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
*out_gai = gai;
|
||||
*out_ping_type = ping_type;
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (gai) {
|
||||
freeaddrinfo(gai);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _fast_ping_get_addr_by_dns(const char *ip_str, int port, struct addrinfo **out_gai, FAST_PING_TYPE *out_ping_type)
|
||||
{
|
||||
struct addrinfo *gai = NULL;
|
||||
int socktype = 0;
|
||||
FAST_PING_TYPE ping_type;
|
||||
int sockproto = 0;
|
||||
char port_str[MAX_IP_LEN];
|
||||
int domain = -1;
|
||||
char *service = NULL;
|
||||
|
||||
if (port <= 0) {
|
||||
port = 53;
|
||||
}
|
||||
|
||||
domain = _fast_ping_getdomain(ip_str);
|
||||
if (domain < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
switch (domain) {
|
||||
case AF_INET:
|
||||
ping_type = FAST_PING_UDP;
|
||||
break;
|
||||
case AF_INET6:
|
||||
ping_type = FAST_PING_UDP6;
|
||||
break;
|
||||
default:
|
||||
goto errout;
|
||||
break;
|
||||
}
|
||||
|
||||
sockproto = 0;
|
||||
socktype = SOCK_DGRAM;
|
||||
snprintf(port_str, MAX_IP_LEN, "%d", port);
|
||||
service = port_str;
|
||||
|
||||
if (_fast_ping_create_udp(ping_type) < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
gai = _fast_ping_getaddr(ip_str, service, socktype, sockproto);
|
||||
if (gai == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
*out_gai = gai;
|
||||
*out_ping_type = ping_type;
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (gai) {
|
||||
freeaddrinfo(gai);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _fast_ping_get_addr_by_type(PING_TYPE type, const char *ip_str, int port, struct addrinfo **out_gai, FAST_PING_TYPE *out_ping_type)
|
||||
{
|
||||
switch (type) {
|
||||
case PING_TYPE_ICMP:
|
||||
return _fast_ping_get_addr_by_icmp(ip_str, port, out_gai, out_ping_type);
|
||||
break;
|
||||
case PING_TYPE_TCP:
|
||||
return _fast_ping_get_addr_by_tcp(ip_str, port, out_gai, out_ping_type);
|
||||
break;
|
||||
case PING_TYPE_DNS:
|
||||
return _fast_ping_get_addr_by_dns(ip_str, port, out_gai, out_ping_type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int count, int interval, int timeout, fast_ping_result ping_callback, void *userptr)
|
||||
{
|
||||
struct ping_host_struct *ping_host = NULL;
|
||||
struct addrinfo *gai = NULL;
|
||||
int domain = -1;
|
||||
int icmp_proto = 0;
|
||||
uint32_t addrkey;
|
||||
char ip_str[PING_MAX_HOSTLEN];
|
||||
char port_str[MAX_IP_LEN];
|
||||
char *service = NULL;
|
||||
int port = -1;
|
||||
FAST_PING_TYPE ping_type;
|
||||
int socktype = 0;
|
||||
unsigned int seed;
|
||||
int ret = 0;
|
||||
|
||||
if (parse_ip(host, ip_str, &port) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case PING_TYPE_ICMP: {
|
||||
socktype = SOCK_RAW;
|
||||
domain = _fast_ping_getdomain(ip_str);
|
||||
if (domain < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (domain) {
|
||||
case AF_INET:
|
||||
icmp_proto = IPPROTO_ICMP;
|
||||
ping_type = FAST_PING_ICMP;
|
||||
break;
|
||||
case AF_INET6:
|
||||
icmp_proto = IPPROTO_ICMPV6;
|
||||
ping_type = FAST_PING_ICMP6;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_fast_ping_create_icmp(ping_type) < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
gai = _fast_ping_getaddr(ip_str, service, socktype, icmp_proto);
|
||||
if (gai == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
} break;
|
||||
case PING_TYPE_TCP: {
|
||||
if (port <= 0) {
|
||||
port = 80;
|
||||
}
|
||||
|
||||
icmp_proto = 0;
|
||||
socktype = SOCK_STREAM;
|
||||
snprintf(port_str, MAX_IP_LEN, "%d", port);
|
||||
service = port_str;
|
||||
ping_type = FAST_PING_TCP;
|
||||
|
||||
gai = _fast_ping_getaddr(ip_str, service, socktype, icmp_proto);
|
||||
if (gai == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
} break;
|
||||
case PING_TYPE_DNS: {
|
||||
if (port <= 0) {
|
||||
port = 53;
|
||||
}
|
||||
|
||||
domain = _fast_ping_getdomain(ip_str);
|
||||
if (domain < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (domain) {
|
||||
case AF_INET:
|
||||
ping_type = FAST_PING_UDP;
|
||||
break;
|
||||
case AF_INET6:
|
||||
ping_type = FAST_PING_UDP6;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
icmp_proto = 0;
|
||||
socktype = SOCK_DGRAM;
|
||||
snprintf(port_str, MAX_IP_LEN, "%d", port);
|
||||
service = port_str;
|
||||
|
||||
if (_fast_ping_create_udp(ping_type) < 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
gai = _fast_ping_getaddr(ip_str, service, socktype, icmp_proto);
|
||||
if (gai == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
ret = _fast_ping_get_addr_by_type(type, ip_str, port, &gai, &ping_type);
|
||||
if (ret != 0) {
|
||||
tlog(TLOG_ERROR, "get addr by type failed, host: %s", host);
|
||||
goto errout;
|
||||
break;
|
||||
}
|
||||
|
||||
ping_host = malloc(sizeof(*ping_host));
|
||||
@@ -867,7 +1028,7 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
|
||||
}
|
||||
|
||||
memset(ping_host, 0, sizeof(*ping_host));
|
||||
strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
|
||||
safe_strncpy(ping_host->host, host, PING_MAX_HOSTLEN);
|
||||
ping_host->fd = -1;
|
||||
ping_host->timeout = timeout;
|
||||
ping_host->count = count;
|
||||
@@ -892,26 +1053,26 @@ struct ping_host_struct *fast_ping_start(PING_TYPE type, const char *host, int c
|
||||
goto errout;
|
||||
}
|
||||
memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen);
|
||||
freeaddrinfo(gai);
|
||||
|
||||
tlog(TLOG_DEBUG, "ping %s, id = %d", host, ping_host->sid);
|
||||
|
||||
addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0);
|
||||
addrkey = jhash(&ping_host->sid, sizeof(ping_host->sid), addrkey);
|
||||
addrkey = _fast_ping_hash_key(ping_host->sid, &ping_host->addr);
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
_fast_ping_host_get(ping_host);
|
||||
hash_add(ping.addrmap, &ping_host->addr_node, addrkey);
|
||||
pthread_mutex_unlock(&ping.map_lock);
|
||||
|
||||
_fast_ping_host_get(ping_host);
|
||||
_fast_ping_host_get(ping_host);
|
||||
if (_fast_ping_sendping(ping_host) != 0) {
|
||||
goto errout_remove;
|
||||
}
|
||||
|
||||
ping_host->run = 1;
|
||||
_fast_ping_host_put(ping_host);
|
||||
freeaddrinfo(gai);
|
||||
return ping_host;
|
||||
errout_remove:
|
||||
fast_ping_stop(ping_host);
|
||||
ping_host = NULL;
|
||||
errout:
|
||||
if (gai) {
|
||||
freeaddrinfo(gai);
|
||||
@@ -921,10 +1082,6 @@ errout:
|
||||
free(ping_host);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
errout_remove:
|
||||
fast_ping_stop(ping_host);
|
||||
_fast_ping_host_put(ping_host);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1028,7 +1185,8 @@ static struct fast_ping_packet *_fast_ping_icmp_packet(struct ping_host_struct *
|
||||
return packet;
|
||||
}
|
||||
|
||||
static struct fast_ping_packet *_fast_ping_recv_packet(struct ping_host_struct *ping_host, struct msghdr *msg, u_char *inpacket, int len, struct timeval *tvrecv)
|
||||
static struct fast_ping_packet *_fast_ping_recv_packet(struct ping_host_struct *ping_host, struct msghdr *msg, u_char *inpacket, int len,
|
||||
struct timeval *tvrecv)
|
||||
{
|
||||
struct fast_ping_packet *packet = NULL;
|
||||
|
||||
@@ -1094,17 +1252,16 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
goto errout;
|
||||
}
|
||||
|
||||
addrkey = jhash(&from, from_len, 0);
|
||||
tvsend = &packet->msg.tv;
|
||||
sid = packet->msg.sid;
|
||||
seq = packet->msg.seq;
|
||||
cookie = packet->msg.cookie;
|
||||
addrkey = jhash(&sid, sizeof(sid), addrkey);
|
||||
addrkey = _fast_ping_hash_key(sid, (struct sockaddr *)&from);
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
|
||||
{
|
||||
if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0 && recv_ping_host->sid == sid &&
|
||||
recv_ping_host->cookie == cookie) {
|
||||
if (_fast_ping_sockaddr_ip_cmp(&recv_ping_host->addr, recv_ping_host->addr_len, (struct sockaddr *)&from, from_len) == 0 &&
|
||||
recv_ping_host->sid == sid && recv_ping_host->cookie == cookie) {
|
||||
_fast_ping_host_get(recv_ping_host);
|
||||
break;
|
||||
}
|
||||
@@ -1117,8 +1274,8 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
}
|
||||
|
||||
if (recv_ping_host->seq != seq) {
|
||||
_fast_ping_host_put(recv_ping_host);
|
||||
tlog(TLOG_ERROR, "seq num mismatch, expect %u, real %u", recv_ping_host->seq, seq);
|
||||
_fast_ping_host_put(recv_ping_host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1230,13 +1387,14 @@ static int _fast_ping_process_udp(struct ping_host_struct *ping_host, struct tim
|
||||
if (len < sizeof(*dns_head)) {
|
||||
goto errout;
|
||||
}
|
||||
addrkey = jhash(&from, from_len, 0);
|
||||
|
||||
sid = ntohs(dns_head->id);
|
||||
addrkey = jhash(&sid, sizeof(sid), addrkey);
|
||||
addrkey = _fast_ping_hash_key(sid, (struct sockaddr *)&from);
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
|
||||
{
|
||||
if (recv_ping_host->addr_len == from_len && memcmp(&recv_ping_host->addr, &from, from_len) == 0 && recv_ping_host->sid == sid) {
|
||||
if (_fast_ping_sockaddr_ip_cmp(&recv_ping_host->addr, recv_ping_host->addr_len, (struct sockaddr *)&from, from_len) == 0 &&
|
||||
recv_ping_host->sid == sid) {
|
||||
_fast_ping_host_get(recv_ping_host);
|
||||
break;
|
||||
}
|
||||
@@ -1323,9 +1481,10 @@ static void _fast_ping_period_run(void)
|
||||
struct hlist_node *tmp = NULL;
|
||||
int i = 0;
|
||||
struct timeval now;
|
||||
struct timezone tz;
|
||||
struct timeval interval;
|
||||
int64_t millisecond;
|
||||
gettimeofday(&now, NULL);
|
||||
gettimeofday(&now, &tz);
|
||||
LIST_HEAD(action);
|
||||
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
@@ -1486,14 +1645,8 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void fast_ping_exit(void)
|
||||
static void _fast_ping_close_fds(void)
|
||||
{
|
||||
if (ping.tid > 0) {
|
||||
void *ret = NULL;
|
||||
ping.run = 0;
|
||||
pthread_join(ping.tid, &ret);
|
||||
}
|
||||
|
||||
if (ping.fd_icmp > 0) {
|
||||
close(ping.fd_icmp);
|
||||
ping.fd_icmp = -1;
|
||||
@@ -1504,6 +1657,26 @@ void fast_ping_exit(void)
|
||||
ping.fd_icmp6 = -1;
|
||||
}
|
||||
|
||||
if (ping.fd_udp > 0) {
|
||||
close(ping.fd_udp);
|
||||
ping.fd_udp = -1;
|
||||
}
|
||||
|
||||
if (ping.fd_udp6 > 0) {
|
||||
close(ping.fd_udp6);
|
||||
ping.fd_udp6 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void fast_ping_exit(void)
|
||||
{
|
||||
if (ping.tid > 0) {
|
||||
void *ret = NULL;
|
||||
ping.run = 0;
|
||||
pthread_join(ping.tid, &ret);
|
||||
}
|
||||
|
||||
_fast_ping_close_fds();
|
||||
_fast_ping_remove_all();
|
||||
|
||||
pthread_mutex_destroy(&ping.lock);
|
||||
|
||||
@@ -137,12 +137,12 @@ HTTP_METHOD http_head_get_method(struct http_head *http_head)
|
||||
return http_head->method;
|
||||
}
|
||||
|
||||
const char *http_head_get_url(struct http_head *http_head)
|
||||
const char *http_head_get_url(struct http_head *http_head)
|
||||
{
|
||||
return http_head->url;
|
||||
}
|
||||
|
||||
const char *http_head_get_httpversion(struct http_head *http_head)
|
||||
const char *http_head_get_httpversion(struct http_head *http_head)
|
||||
{
|
||||
return http_head->version;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ HTTP_HEAD_TYPE http_head_get_head_type(struct http_head *http_head)
|
||||
return http_head->head_type;
|
||||
}
|
||||
|
||||
char *http_head_get_data(struct http_head *http_head)
|
||||
char *http_head_get_data(struct http_head *http_head)
|
||||
{
|
||||
return http_head->data;
|
||||
}
|
||||
@@ -232,7 +232,7 @@ static int _http_head_parse_response(struct http_head *http_head, char *key, cha
|
||||
http_head->code = atol(ret_code);
|
||||
http_head->code_msg = result;
|
||||
http_head->version = key;
|
||||
http_head->head_type = HTTP_HEAD_RESPONSE;
|
||||
http_head->head_type = HTTP_HEAD_RESPONSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -195,6 +195,17 @@ void* art_search(const art_tree *t, const unsigned char *key, int key_len);
|
||||
*/
|
||||
void *art_substring(const art_tree *t, const unsigned char *str, int str_len, unsigned char *key, int *key_len);
|
||||
|
||||
/**
|
||||
* Wakk substring for a value in the ART tree
|
||||
* @arg t The tree
|
||||
* @arg str The key
|
||||
* @arg str_len The length of the key
|
||||
* @return NULL if the item was not found, otherwise
|
||||
* the value pointer is returned.
|
||||
*/
|
||||
typedef int (*walk_func)(unsigned char *key, uint32_t key_len, void *value, void *arg);
|
||||
void art_substring_walk(const art_tree *t, const unsigned char *str, int str_len, walk_func func, void *arg);
|
||||
|
||||
/**
|
||||
* Returns the minimum valued leaf
|
||||
* @return The minimum leaf or NULL
|
||||
|
||||
24
src/include/stringutil.h
Normal file
24
src/include/stringutil.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _GENERIC_STRING_UITL_H
|
||||
#define _GENERIC_STRING_UITL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
static inline char *safe_strncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
#if __GNUC__ > 7
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
||||
#endif
|
||||
char *ret = strncpy(dest, src, n - 1);
|
||||
if (n > 0) {
|
||||
dest[n - 1] = '\0';
|
||||
}
|
||||
#if __GNUC__ > 7
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -52,23 +52,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
static art_node* alloc_node(uint8_t type) {
|
||||
art_node* n;
|
||||
switch (type) {
|
||||
void *mem = NULL;
|
||||
switch (type) {
|
||||
case NODE4:
|
||||
n = (art_node*)calloc(1, sizeof(art_node4));
|
||||
mem = (art_node*)calloc(1, sizeof(art_node4));
|
||||
break;
|
||||
case NODE16:
|
||||
n = (art_node*)calloc(1, sizeof(art_node16));
|
||||
mem = (art_node*)calloc(1, sizeof(art_node16));
|
||||
break;
|
||||
case NODE48:
|
||||
n = (art_node*)calloc(1, sizeof(art_node48));
|
||||
mem = (art_node*)calloc(1, sizeof(art_node48));
|
||||
break;
|
||||
case NODE256:
|
||||
n = (art_node*)calloc(1, sizeof(art_node256));
|
||||
mem = (art_node*)calloc(1, sizeof(art_node256));
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
n->type = type;
|
||||
if (mem == NULL) {
|
||||
abort();
|
||||
}
|
||||
n = mem;
|
||||
n->type = type;
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -385,6 +390,10 @@ art_leaf* art_maximum(art_tree *t) {
|
||||
|
||||
static art_leaf* make_leaf(const unsigned char *key, int key_len, void *value) {
|
||||
art_leaf *l = (art_leaf*)calloc(1, sizeof(art_leaf)+key_len+1);
|
||||
if (l == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l->value = value;
|
||||
l->key_len = key_len;
|
||||
memcpy(l->key, key, key_len);
|
||||
@@ -1064,3 +1073,57 @@ void *art_substring(const art_tree *t, const unsigned char *str, int str_len, un
|
||||
|
||||
return found->value;
|
||||
}
|
||||
|
||||
void art_substring_walk(const art_tree *t, const unsigned char *str, int str_len, walk_func func, void *arg)
|
||||
{
|
||||
art_node **child;
|
||||
art_node *n = t->root;
|
||||
art_node *m;
|
||||
art_leaf *found = NULL;
|
||||
int prefix_len, depth = 0;
|
||||
int stop_search = 0;
|
||||
|
||||
while (n && stop_search == 0) {
|
||||
// Might be a leaf
|
||||
if (IS_LEAF(n)) {
|
||||
n = (art_node*)LEAF_RAW(n);
|
||||
// Check if the expanded path matches
|
||||
if (!str_prefix_matches((art_leaf*)n, str, str_len)) {
|
||||
found = (art_leaf*)n;
|
||||
stop_search = func(found->key, found->key_len, found->value, arg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if current is leaf
|
||||
child = find_child(n, 0);
|
||||
m = (child) ? *child : NULL;
|
||||
if (m && IS_LEAF(m)) {
|
||||
m = (art_node*)LEAF_RAW(m);
|
||||
// Check if the expanded path matches
|
||||
if (!str_prefix_matches((art_leaf*)m, str, str_len)) {
|
||||
found = (art_leaf*)m;
|
||||
stop_search = func(found->key, found->key_len, found->value, arg);
|
||||
}
|
||||
}
|
||||
|
||||
// Bail if the prefix does not match
|
||||
if (n->partial_len) {
|
||||
prefix_len = check_prefix(n, str, str_len, depth);
|
||||
if (prefix_len != min(MAX_PREFIX_LEN, n->partial_len))
|
||||
break;
|
||||
depth = depth + n->partial_len;
|
||||
}
|
||||
|
||||
// Recursively search
|
||||
child = find_child(n, str[depth]);
|
||||
n = (child) ? *child : NULL;
|
||||
depth++;
|
||||
}
|
||||
|
||||
if (found == NULL) {
|
||||
return ;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
@@ -117,11 +117,13 @@ void conf_getopt_reset(void)
|
||||
int argc = 2;
|
||||
char *argv[3] = {"reset", "", 0};
|
||||
|
||||
optind = 1;
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
optopt = 0;
|
||||
getopt_long(argc, argv, "", long_options, NULL);
|
||||
optind = 1;
|
||||
optind = 0;
|
||||
opterr = 0;
|
||||
optopt = 0;
|
||||
}
|
||||
|
||||
int conf_parse_args(char *key, char *value, int *argc, char **argv)
|
||||
@@ -165,7 +167,6 @@ int conf_parse_args(char *key, char *value, int *argc, char **argv)
|
||||
argv[count] = start;
|
||||
*ptr = '\0';
|
||||
ptr++;
|
||||
start = ptr;
|
||||
count++;
|
||||
sep_flag = ' ';
|
||||
start = NULL;
|
||||
@@ -181,7 +182,7 @@ int conf_parse_args(char *key, char *value, int *argc, char **argv)
|
||||
}
|
||||
|
||||
*argc = count;
|
||||
argv[count + 1] = 0;
|
||||
argv[count] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ static radix_node_t
|
||||
*radix_search_best2(radix_tree_t *radix, prefix_t *prefix, int inclusive)
|
||||
{
|
||||
radix_node_t *node;
|
||||
radix_node_t *stack[RADIX_MAXBITS + 1];
|
||||
radix_node_t *stack[RADIX_MAXBITS + 1] = {0};
|
||||
unsigned char *addr;
|
||||
unsigned int bitlen;
|
||||
int cnt = 0;
|
||||
|
||||
0
src/lib/stringutil.c
Normal file
0
src/lib/stringutil.c
Normal file
@@ -59,7 +59,8 @@ static void _help(void)
|
||||
" -c [conf] config file.\n"
|
||||
" -p [pid] pid file path\n"
|
||||
" -S ignore segment fault signal.\n"
|
||||
" -v verbose screent.\n"
|
||||
" -x verbose screen.\n"
|
||||
" -v dispaly version.\n"
|
||||
" -h show this help message.\n"
|
||||
|
||||
"Online help: http://pymumu.github.io/smartdns\n"
|
||||
@@ -69,6 +70,20 @@ static void _help(void)
|
||||
printf("%s", help);
|
||||
}
|
||||
|
||||
static void _show_version(void)
|
||||
{
|
||||
char str_ver[256] = {0};
|
||||
#ifdef SMARTDNS_VERION
|
||||
const char *ver = SMARTDNS_VERION;
|
||||
snprintf(str_ver, sizeof(str_ver), "%s", ver);
|
||||
#else
|
||||
struct tm tm;
|
||||
get_compiled_time(&tm);
|
||||
snprintf(str_ver, sizeof(str_ver), "1.%.4d%.2d%.2d-%.2d%.2d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
|
||||
#endif
|
||||
printf("smartdns %s\n", str_ver);
|
||||
}
|
||||
|
||||
static int _smartdns_load_from_resolv(void)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
@@ -108,7 +123,7 @@ static int _smartdns_load_from_resolv(void)
|
||||
port = DEFAULT_DNS_PORT;
|
||||
}
|
||||
|
||||
strncpy(dns_conf_servers[dns_conf_server_num].server, ns_ip, DNS_MAX_IPLEN);
|
||||
safe_strncpy(dns_conf_servers[dns_conf_server_num].server, ns_ip, DNS_MAX_IPLEN);
|
||||
dns_conf_servers[dns_conf_server_num].port = port;
|
||||
dns_conf_servers[dns_conf_server_num].type = DNS_SERVER_UDP;
|
||||
dns_conf_server_num++;
|
||||
@@ -139,16 +154,17 @@ static int _smartdns_add_servers(void)
|
||||
case DNS_SERVER_HTTPS: {
|
||||
struct client_dns_server_flag_https *flag_http = &flags.https;
|
||||
flag_http->spi_len = dns_client_spki_decode(dns_conf_servers[i].spki, (unsigned char *)flag_http->spki);
|
||||
strncpy(flag_http->hostname, dns_conf_servers[i].hostname, sizeof(flag_http->hostname));
|
||||
strncpy(flag_http->path, dns_conf_servers[i].path, sizeof(flag_http->path));
|
||||
strncpy(flag_http->httphost, dns_conf_servers[i].httphost, sizeof(flag_http->httphost));
|
||||
safe_strncpy(flag_http->hostname, dns_conf_servers[i].hostname, sizeof(flag_http->hostname));
|
||||
safe_strncpy(flag_http->path, dns_conf_servers[i].path, sizeof(flag_http->path));
|
||||
safe_strncpy(flag_http->httphost, dns_conf_servers[i].httphost, sizeof(flag_http->httphost));
|
||||
safe_strncpy(flag_http->tls_host_verify, dns_conf_servers[i].tls_host_verify, sizeof(flag_http->tls_host_verify));
|
||||
} break;
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &flags.tls;
|
||||
flag_tls->spi_len = dns_client_spki_decode(dns_conf_servers[i].spki, (unsigned char *)flag_tls->spki);
|
||||
strncpy(flag_tls->hostname, dns_conf_servers[i].hostname, sizeof(flag_tls->hostname));
|
||||
safe_strncpy(flag_tls->hostname, dns_conf_servers[i].hostname, sizeof(flag_tls->hostname));
|
||||
safe_strncpy(flag_tls->tls_host_verify, dns_conf_servers[i].tls_host_verify, sizeof(flag_tls->tls_host_verify));
|
||||
} break;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
break;
|
||||
default:
|
||||
@@ -232,7 +248,7 @@ static int _smartdns_init(void)
|
||||
logfile = dns_conf_log_file;
|
||||
}
|
||||
|
||||
ret = tlog_init(logfile, dns_conf_log_size, dns_conf_log_num, 1, 0, 0);
|
||||
ret = tlog_init(logfile, dns_conf_log_size, dns_conf_log_num, 0, 0);
|
||||
if (ret != 0) {
|
||||
tlog(TLOG_ERROR, "start tlog failed.\n");
|
||||
goto errout;
|
||||
@@ -359,10 +375,10 @@ int main(int argc, char *argv[])
|
||||
char pid_file[MAX_LINE_LEN];
|
||||
int signal_ignore = 0;
|
||||
|
||||
strncpy(config_file, SMARTDNS_CONF_FILE, MAX_LINE_LEN);
|
||||
strncpy(pid_file, SMARTDNS_PID_FILE, MAX_LINE_LEN);
|
||||
safe_strncpy(config_file, SMARTDNS_CONF_FILE, MAX_LINE_LEN);
|
||||
safe_strncpy(pid_file, SMARTDNS_PID_FILE, MAX_LINE_LEN);
|
||||
|
||||
while ((opt = getopt(argc, argv, "fhc:p:Sv")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "fhc:p:Svx")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
is_forground = 1;
|
||||
@@ -376,9 +392,13 @@ int main(int argc, char *argv[])
|
||||
case 'S':
|
||||
signal_ignore = 1;
|
||||
break;
|
||||
case 'v':
|
||||
case 'x':
|
||||
verbose_screen = 1;
|
||||
break;
|
||||
case 'v':
|
||||
_show_version();
|
||||
return 0;
|
||||
break;
|
||||
case 'h':
|
||||
_help();
|
||||
return 1;
|
||||
|
||||
677
src/tlog.c
677
src/tlog.c
File diff suppressed because it is too large
Load Diff
72
src/tlog.h
72
src/tlog.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* tinylog
|
||||
* Copyright (C) 2018 Ruilin Peng (Nick) <pymumu@gmail.com>
|
||||
* Copyright (C) 2018-2019 Ruilin Peng (Nick) <pymumu@gmail.com>
|
||||
* https://github.com/pymumu/tinylog
|
||||
*/
|
||||
|
||||
@@ -32,13 +32,36 @@ struct tlog_time {
|
||||
int usec;
|
||||
};
|
||||
|
||||
#ifndef TLOG_MAX_LINE_LEN
|
||||
#define TLOG_MAX_LINE_LEN (1024)
|
||||
#endif
|
||||
|
||||
/* TLOG FLAGS LIST */
|
||||
/* set tlog not compress file when archive */
|
||||
#define TLOG_NOCOMPRESS (1 << 0)
|
||||
|
||||
/* Set the segmentation mode to process the log, Used by the callback function to return a full log*/
|
||||
#define TLOG_SEGMENT (1 << 1)
|
||||
|
||||
/*
|
||||
multiwrite: enable multi process write mode.
|
||||
NOTICE: maxlogsize in all prcesses must be same when enable this mode.
|
||||
*/
|
||||
#define TLOG_MULTI_WRITE (1 << 2)
|
||||
|
||||
/* Not Block if buffer is insufficient. */
|
||||
#define TLOG_NONBLOCK (1 << 3)
|
||||
|
||||
/* enable log to screen */
|
||||
#define TLOG_SCREEN (1 << 4)
|
||||
|
||||
struct tlog_info {
|
||||
const char *level;
|
||||
tlog_level level;
|
||||
const char *file;
|
||||
const char *func;
|
||||
int line;
|
||||
struct tlog_time time;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
Function: Print log
|
||||
@@ -51,9 +74,12 @@ format: Log formats
|
||||
#define tlog(level, format, ...) tlog_ext(level, BASE_FILE_NAME, __LINE__, __func__, NULL, format, ##__VA_ARGS__)
|
||||
|
||||
extern int tlog_ext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, ...)
|
||||
__attribute__((format(printf, 6, 7)));
|
||||
__attribute__((format(printf, 6, 7))) __attribute__((nonnull (6)));
|
||||
extern int tlog_vext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, va_list ap);
|
||||
|
||||
/* write buff to log file */
|
||||
extern int tlog_write_log(char *buff, int bufflen);
|
||||
|
||||
/* set log level */
|
||||
extern int tlog_setlevel(tlog_level level);
|
||||
|
||||
@@ -63,17 +89,18 @@ extern void tlog_setlogscreen(int enable);
|
||||
/* enalbe early log to screen */
|
||||
extern void tlog_set_early_printf(int enable);
|
||||
|
||||
/* Get log level in string */
|
||||
extern const char *tlog_get_level_string(tlog_level level);
|
||||
|
||||
/*
|
||||
Function: Initialize log module
|
||||
logfile: log file.
|
||||
maxlogsize: The maximum size of a single log file.
|
||||
maxlogcount: Number of archived logs.
|
||||
block: Blocked if buffer is not sufficient.
|
||||
buffsize: Buffer size, zero for default (128K)
|
||||
multiwrite: enable multi process write mode.
|
||||
NOTICE: maxlogsize in all prcesses must be same when enable this mode.
|
||||
flag: read tlog flags
|
||||
*/
|
||||
extern int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int block, int buffsize, int multiwrite);
|
||||
extern int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag);
|
||||
|
||||
/* flush pending log message, and exit tlog */
|
||||
extern void tlog_exit(void);
|
||||
@@ -89,6 +116,12 @@ read _tlog_format for example.
|
||||
typedef int (*tlog_format_func)(char *buff, int maxlen, struct tlog_info *info, void *userptr, const char *format, va_list ap);
|
||||
extern int tlog_reg_format_func(tlog_format_func func);
|
||||
|
||||
/* register log output callback
|
||||
Note: info is invalid when flag TLOG_SEGMENT is not set.
|
||||
*/
|
||||
typedef int (*tlog_log_output_func)(struct tlog_info *info, char *buff, int bufflen, void *private_data);
|
||||
extern int tlog_reg_log_output_func(tlog_log_output_func output, void *private_data);
|
||||
|
||||
struct tlog_log;
|
||||
typedef struct tlog_log tlog_log;
|
||||
/*
|
||||
@@ -96,15 +129,16 @@ Function: open a new log stream, handler should close by tlog_close
|
||||
logfile: log file.
|
||||
maxlogsize: The maximum size of a single log file.
|
||||
maxlogcount: Number of archived logs.
|
||||
block: Blocked if buffer is not sufficient.
|
||||
buffsize: Buffer size, zero for default (128K)
|
||||
multiwrite: enable multi process write mode.
|
||||
NOTICE: maxlogsize in all prcesses must be same when enable this mode.
|
||||
|
||||
flag: read tlog flags
|
||||
return: log stream handler.
|
||||
*/
|
||||
extern tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int block, int buffsize, int multiwrite);
|
||||
extern tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag);
|
||||
|
||||
/* write buff to log file */
|
||||
extern int tlog_write(struct tlog_log *log, char *buff, int bufflen);
|
||||
|
||||
/* close log stream */
|
||||
extern void tlog_close(tlog_log *log);
|
||||
|
||||
/*
|
||||
@@ -112,7 +146,7 @@ Function: Print log to log stream
|
||||
log: log stream
|
||||
format: Log formats
|
||||
*/
|
||||
extern int tlog_printf(tlog_log *log, const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||
extern int tlog_printf(tlog_log *log, const char *format, ...) __attribute__((format(printf, 2, 3))) __attribute__((nonnull (1, 2)));
|
||||
|
||||
/*
|
||||
Function: Print log to log stream with ap
|
||||
@@ -125,6 +159,16 @@ extern int tlog_vprintf(tlog_log *log, const char *format, va_list ap);
|
||||
/* enalbe log to screen */
|
||||
extern void tlog_logscreen(tlog_log *log, int enable);
|
||||
|
||||
/* register output callback */
|
||||
typedef int (*tlog_output_func)(struct tlog_log *log, char *buff, int bufflen);
|
||||
extern int tlog_reg_output_func(tlog_log *log, tlog_output_func output);
|
||||
|
||||
/* set private data */
|
||||
extern void tlog_set_private(tlog_log *log, void *private_data);
|
||||
|
||||
/* get private data */
|
||||
extern void *tlog_get_private(tlog_log *log);
|
||||
|
||||
/* get local time */
|
||||
extern int tlog_localtime(struct tlog_time *tm);
|
||||
|
||||
|
||||
136
src/util.c
136
src/util.c
@@ -7,6 +7,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/capability.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <pthread.h>
|
||||
@@ -17,6 +18,7 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#define TMP_BUFF_LEN_32 32
|
||||
|
||||
@@ -65,6 +67,7 @@ struct ipset_netlink_msg {
|
||||
};
|
||||
|
||||
static int ipset_fd;
|
||||
static int pidfile_fd;
|
||||
|
||||
unsigned long get_tick_count(void)
|
||||
{
|
||||
@@ -125,6 +128,7 @@ int getaddr_by_host(char *host, struct sockaddr *addr, socklen_t *addr_len)
|
||||
result->ai_addrlen = *addr_len;
|
||||
}
|
||||
|
||||
addr->sa_family = result->ai_family;
|
||||
memcpy(addr, result->ai_addr, result->ai_addrlen);
|
||||
*addr_len = result->ai_addrlen;
|
||||
|
||||
@@ -138,6 +142,75 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int getsocknet_inet(int fd, struct sockaddr *addr, socklen_t *addr_len)
|
||||
{
|
||||
struct sockaddr_storage addr_store;
|
||||
socklen_t addr_store_len = sizeof(addr_store);
|
||||
if (getsockname(fd, (struct sockaddr *)&addr_store, &addr_store_len) != 0) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
switch (addr_store.ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr_in;
|
||||
addr_in = (struct sockaddr_in *)addr;
|
||||
addr_in->sin_family = AF_INET;
|
||||
*addr_len = sizeof(struct sockaddr_in);
|
||||
memcpy(addr, addr_in, sizeof(struct sockaddr_in));
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6;
|
||||
addr_in6 = (struct sockaddr_in6 *)addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||
struct sockaddr_in addr_in4;
|
||||
memset(&addr_in4, 0, sizeof(addr_in4));
|
||||
memcpy(&addr_in4.sin_addr.s_addr, addr_in6->sin6_addr.s6_addr + 12, sizeof(addr_in4.sin_addr.s_addr));
|
||||
addr_in4.sin_family = AF_INET;
|
||||
addr_in4.sin_port = 0;
|
||||
*addr_len = sizeof(struct sockaddr_in);
|
||||
memcpy(addr, &addr_in4, sizeof(struct sockaddr_in));
|
||||
} else {
|
||||
addr_in6->sin6_family = AF_INET6;
|
||||
*addr_len = sizeof(struct sockaddr_in6);
|
||||
memcpy(addr, addr_in6, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
goto errout;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fill_sockaddr_by_ip(unsigned char *ip, int ip_len, int port, struct sockaddr *addr, socklen_t *addr_len)
|
||||
{
|
||||
if (ip == NULL || addr == NULL || addr_len == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ip_len == IPV4_ADDR_LEN) {
|
||||
struct sockaddr_in *addr_in = NULL;
|
||||
addr->sa_family = AF_INET;
|
||||
addr_in = (struct sockaddr_in *)addr;
|
||||
addr_in->sin_port = htons(port);
|
||||
addr_in->sin_family = AF_INET;
|
||||
memcpy(&addr_in->sin_addr.s_addr, ip, ip_len);
|
||||
*addr_len = 16;
|
||||
} else if (ip_len == IPV6_ADDR_LEN) {
|
||||
struct sockaddr_in6 *addr_in6 = NULL;
|
||||
addr->sa_family = AF_INET6;
|
||||
addr_in6 = (struct sockaddr_in6 *)addr;
|
||||
addr_in6->sin6_port = htons(port);
|
||||
addr_in6->sin6_family = AF_INET6;
|
||||
memcpy(addr_in6->sin6_addr.s6_addr, ip, ip_len);
|
||||
*addr_len = 28;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int parse_ip(const char *value, char *ip, int *port)
|
||||
{
|
||||
int offset = 0;
|
||||
@@ -327,7 +400,7 @@ int parse_uri(char *value, char *scheme, char *host, int *port, char *path)
|
||||
process_ptr += field_len;
|
||||
|
||||
if (path) {
|
||||
strcpy(path, process_ptr);
|
||||
strncpy(path, process_ptr, PATH_MAX);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -350,7 +423,7 @@ int set_fd_nonblock(int fd, int nonblock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *reverse_string(char *output, char *input, int len)
|
||||
char *reverse_string(char *output, const char *input, int len, int to_lower_case)
|
||||
{
|
||||
char *begin = output;
|
||||
if (len <= 0) {
|
||||
@@ -361,6 +434,12 @@ char *reverse_string(char *output, char *input, int len)
|
||||
len--;
|
||||
while (len >= 0) {
|
||||
*output = *(input + len);
|
||||
if (to_lower_case) {
|
||||
if (*output >= 'A' && *output <= 'Z') {
|
||||
/* To lower case */
|
||||
*output = *output + 32;
|
||||
}
|
||||
}
|
||||
output++;
|
||||
len--;
|
||||
}
|
||||
@@ -473,7 +552,7 @@ static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int
|
||||
nested[0]->len = (void *)buffer + NETLINK_ALIGN(netlink_head->nlmsg_len) - (void *)nested[0];
|
||||
|
||||
for (;;) {
|
||||
rc = sendto(ipset_fd, buffer, netlink_head->nlmsg_len, 0, (struct sockaddr *)&snl, sizeof(snl));
|
||||
rc = sendto(ipset_fd, buffer, netlink_head->nlmsg_len, 0, (const struct sockaddr *)&snl, sizeof(snl));
|
||||
if (rc >= 0) {
|
||||
break;
|
||||
}
|
||||
@@ -575,6 +654,12 @@ int create_pid_file(const char *pid_file)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (pidfile_fd > 0) {
|
||||
close(pidfile_fd);
|
||||
}
|
||||
|
||||
pidfile_fd = fd;
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
if (fd > 0) {
|
||||
@@ -647,25 +732,10 @@ void SSL_CRYPTO_thread_cleanup(void)
|
||||
#ifndef MIN
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#endif
|
||||
typedef struct Protocol {
|
||||
const char *const name;
|
||||
const uint16_t default_port;
|
||||
int (*const parse_packet)(const char*, size_t, char *, const char **);
|
||||
const char *const abort_message;
|
||||
const size_t abort_message_len;
|
||||
} protocol_t;
|
||||
|
||||
static int parse_extensions(const char *, size_t, char *, const char **);
|
||||
static int parse_server_name_extension(const char *, size_t, char *, const char **);
|
||||
|
||||
const struct Protocol *const tls_protocol;
|
||||
|
||||
static const protocol_t tls_protocol_st = {
|
||||
.default_port = 443,
|
||||
.parse_packet = &parse_tls_header,
|
||||
};
|
||||
const protocol_t *const tls_protocol = &tls_protocol_st;
|
||||
|
||||
/* Parse a TLS packet for the Server Name Indication extension in the client
|
||||
* hello handshake, returning the first servername found (pointer to static
|
||||
* array)
|
||||
@@ -833,3 +903,33 @@ static int parse_server_name_extension(const char *data, size_t data_len, char *
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
void get_compiled_time(struct tm *tm)
|
||||
{
|
||||
char s_month[5];
|
||||
int month, day, year;
|
||||
int hour, min, sec;
|
||||
static const char *month_names = "JanFebMarAprMayJunJulAugSepOctNovDec";
|
||||
|
||||
sscanf(__DATE__, "%5s %d %d", s_month, &day, &year);
|
||||
month = (strstr(month_names, s_month) - month_names) / 3;
|
||||
sscanf(__TIME__, "%d:%d:%d", &hour, &min, &sec);
|
||||
tm->tm_year = year - 1900;
|
||||
tm->tm_mon = month;
|
||||
tm->tm_mday = day;
|
||||
tm->tm_isdst = -1;
|
||||
tm->tm_hour = hour;
|
||||
tm->tm_min = min;
|
||||
tm->tm_sec = sec;
|
||||
}
|
||||
|
||||
int has_network_raw_cap(void)
|
||||
{
|
||||
int fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (fd < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
19
src/util.h
19
src/util.h
@@ -4,6 +4,12 @@
|
||||
#define SMART_DNS_UTIL_H
|
||||
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
#include "stringutil.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus */
|
||||
|
||||
#define PORT_NOT_DEFINED -1
|
||||
#define MAX_IP_LEN 64
|
||||
@@ -14,6 +20,10 @@ char *gethost_by_addr(char *host, int maxsize, struct sockaddr *addr);
|
||||
|
||||
int getaddr_by_host(char *host, struct sockaddr *addr, socklen_t *addr_len);
|
||||
|
||||
int getsocknet_inet(int fd, struct sockaddr *addr, socklen_t *addr_len);
|
||||
|
||||
int fill_sockaddr_by_ip(unsigned char *ip, int ip_len, int port, struct sockaddr *addr, socklen_t *addr_len);
|
||||
|
||||
int parse_ip(const char *value, char *ip, int *port);
|
||||
|
||||
int check_is_ipaddr(const char *ip);
|
||||
@@ -22,7 +32,7 @@ int parse_uri(char *value, char *scheme, char *host, int *port, char *path);
|
||||
|
||||
int set_fd_nonblock(int fd, int nonblock);
|
||||
|
||||
char *reverse_string(char *output, char *input, int len);
|
||||
char *reverse_string(char *output, const char *input, int len, int to_lower_case);
|
||||
|
||||
void print_stack(void);
|
||||
|
||||
@@ -55,4 +65,11 @@ int create_pid_file(const char *pid_file);
|
||||
*/
|
||||
int parse_tls_header(const char *data, size_t data_len, char *hostname, const char **hostname_ptr);
|
||||
|
||||
void get_compiled_time(struct tm *tm);
|
||||
|
||||
int has_network_raw_cap(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus */
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user