Compare commits
30 Commits
Release30
...
Release32-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80cb27c795 | ||
|
|
cb73eadf01 | ||
|
|
69ba3f8789 | ||
|
|
c380bbe0e3 | ||
|
|
da74e877c5 | ||
|
|
a300873b3f | ||
|
|
a9829f6155 | ||
|
|
1923271630 | ||
|
|
c23ec7ea8f | ||
|
|
aad751c1f5 | ||
|
|
138df2fd5d | ||
|
|
297ea29639 | ||
|
|
bc0d6b89ca | ||
|
|
2148efd262 | ||
|
|
ce46ac58a7 | ||
|
|
c1f9941427 | ||
|
|
770ce9e8bc | ||
|
|
60d0fc856e | ||
|
|
95472129ee | ||
|
|
f79ceeac43 | ||
|
|
54801e1ed6 | ||
|
|
304e94bc6f | ||
|
|
3985ea8269 | ||
|
|
c2c418ed89 | ||
|
|
b78c9eb6fe | ||
|
|
0aec326d55 | ||
|
|
29e4d4b48b | ||
|
|
a6fe329105 | ||
|
|
c824c0abc5 | ||
|
|
3ad7cd7f45 |
@@ -7,3 +7,4 @@ UseTab: ForContinuationAndIndentation
|
||||
MaxEmptyLinesToKeep: 1
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
BreakBeforeBraces: Linux
|
||||
ColumnLimit: 120
|
||||
|
||||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM debian:buster-slim
|
||||
|
||||
RUN apt update && \
|
||||
apt install -y git make gcc libssl-dev && \
|
||||
git clone https://github.com/pymumu/smartdns.git --depth 1 && \
|
||||
cd smartdns && \
|
||||
sh ./package/build-pkg.sh --platform debian --arch `dpkg --print-architecture` && \
|
||||
dpkg -i package/*.deb && \
|
||||
cd / && \
|
||||
rm -rf smartdns/ && \
|
||||
apt autoremove -y git make gcc libssl-dev && \
|
||||
apt clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
EXPOSE 53/udp
|
||||
VOLUME "/etc/smartdns/"
|
||||
|
||||
CMD ["/usr/sbin/smartdns", "-f"]
|
||||
47
Makefile
Normal file
47
Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
# Copyright (C) 2018-2020 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
||||
#
|
||||
# smartdns is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# smartdns is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
PKG_CONFIG := pkg-config
|
||||
DESTDIR :=
|
||||
PREFIX := /usr
|
||||
SBINDIR := $(PREFIX)/sbin
|
||||
SYSCONFDIR := /etc
|
||||
RUNSTATEDIR := /var/run
|
||||
SYSTEMDSYSTEMUNITDIR := $(shell ${PKG_CONFIG} --variable=systemdsystemunitdir systemd)
|
||||
SMARTDNS_SYSTEMD = systemd/smartdns.service
|
||||
|
||||
.PHONY: all clean install SMARTDNS_BIN
|
||||
all: SMARTDNS_BIN
|
||||
|
||||
SMARTDNS_BIN: $(SMARTDNS_SYSTEMD)
|
||||
$(MAKE) $(MFLAGS) -C src all
|
||||
|
||||
$(SMARTDNS_SYSTEMD): systemd/smartdns.service.in
|
||||
cp $< $@
|
||||
sed -i 's|@SBINDIR@|$(SBINDIR)|' $@
|
||||
sed -i 's|@SYSCONFDIR@|$(SYSCONFDIR)|' $@
|
||||
sed -i 's|@RUNSTATEDIR@|$(RUNSTATEDIR)|' $@
|
||||
|
||||
clean:
|
||||
$(MAKE) $(MFLAGS) -C src clean
|
||||
$(RM) $(SMARTDNS_SYSTEMD)
|
||||
|
||||
install: SMARTDNS_BIN
|
||||
install -v -m 0640 -D -t $(DESTDIR)$(SYSCONFDIR)/default etc/default/smartdns
|
||||
install -v -m 0755 -D -t $(DESTDIR)$(SYSCONFDIR)/init.d etc/init.d/smartdns
|
||||
install -v -m 0640 -D -t $(DESTDIR)$(SYSCONFDIR)/smartdns etc/smartdns/smartdns.conf
|
||||
install -v -m 0755 -D -t $(DESTDIR)$(SBINDIR) src/smartdns
|
||||
install -v -m 0644 -D -t $(DESTDIR)$(SYSTEMDSYSTEMUNITDIR) systemd/smartdns.service
|
||||
|
||||
@@ -519,8 +519,8 @@ https://github.com/pymumu/smartdns/releases
|
||||
|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>`[-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
|
||||
|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> `-no-check-certificate:`:跳过证书校验。<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> `-no-check-certificate:`:跳过证书校验。<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
|
||||
@@ -537,6 +537,8 @@ https://github.com/pymumu/smartdns/releases
|
||||
|serve-expired-ttl|过期缓存服务最长超时时间|0|秒,0:表示停用超时,> 0表示指定的超时的秒数|serve-expired-ttl 0
|
||||
|dualstack-ip-selection|双栈IP优选|no|[yes\|no]|dualstack-ip-selection yes
|
||||
|dualstack-ip-selection-threshold|双栈IP优选阈值|30ms|毫秒|dualstack-ip-selection-threshold [0-1000]
|
||||
|ca-file|证书文件|/etc/ssl/certs/ca-certificates.crt|路径|ca-file /etc/ssl/certs/ca-certificates.crt
|
||||
|ca-path|证书文件路径|/etc/ssl/certs|路径|ca-path /etc/ssl/certs
|
||||
|
||||
## FAQ
|
||||
|
||||
|
||||
@@ -513,8 +513,8 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
||||
|conf-file|additional conf file|None|File path|conf-file /etc/smartdns/smartdns.more.conf
|
||||
|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
|
||||
|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>`-no-check-certificate:`: No check certificate. <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>`-no-check-certificate:`: No check certificate. <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
|
||||
@@ -531,6 +531,8 @@ Note: Merlin firmware is derived from ASUS firmware and can theoretically be use
|
||||
|serve-expired-ttl|Cache serve expired limite TTL|0|second,0:disable,> 0 seconds after expiration|serve-expired-ttl 0
|
||||
|dualstack-ip-selection|Dualstack ip selection|no|[yes\|no]|dualstack-ip-selection yes
|
||||
|dualstack-ip-selection-threshold|Dualstack ip select threadhold|30ms|millisecond|dualstack-ip-selection-threshold [0-1000]
|
||||
|ca-file|certificate file|/etc/ssl/certs/ca-certificates.crt|path|ca-file /etc/ssl/certs/ca-certificates.crt
|
||||
|ca-path|certificates path|/etc/ssl/certs|path|ca-path /etc/ssl/certs
|
||||
|
||||
## FAQ
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 52 KiB |
@@ -112,6 +112,14 @@ log-level info
|
||||
# audit-size 128k
|
||||
# audit-num 2
|
||||
|
||||
# certificate file
|
||||
# ca-file [file]
|
||||
# ca-file /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
# certificate path
|
||||
# ca-path [path]
|
||||
# ca-path /etc/ss/certs
|
||||
|
||||
# remote udp dns server list
|
||||
# server [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-check-edns] [-group [group] ...] [-exclude-default-group]
|
||||
# default port is 53
|
||||
@@ -130,8 +138,9 @@ log-level info
|
||||
# remote tls dns server list
|
||||
# server-tls [IP]:[PORT] [-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.
|
||||
# -tls-host-verify: cert hostname to verify.
|
||||
# -host-name: TLS sni hostname.
|
||||
# -no-check-certificate: no check certificate.
|
||||
# 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
|
||||
@@ -141,9 +150,10 @@ log-level info
|
||||
# remote https dns server list
|
||||
# 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.
|
||||
# -tls-host-verify: cert hostname to verify.
|
||||
# -host-name: TLS sni hostname.
|
||||
# -http-host: http host.
|
||||
# -no-check-certificate: no check certificate.
|
||||
# default port is 443
|
||||
# server-https https://cloudflare-dns.com/dns-query
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ showhelp()
|
||||
build_smartdns()
|
||||
{
|
||||
if [ "$PLATFORM" != "luci" ]; then
|
||||
make -C $CODE_DIR/src clean
|
||||
make -C $CODE_DIR/src all -j8 VER=$VER $MAKE_ARGS
|
||||
make -C $CODE_DIR clean $MAKE_ARGS
|
||||
make -C $CODE_DIR all -j8 VER=$VER $MAKE_ARGS
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "make smartdns failed"
|
||||
exit 1
|
||||
|
||||
@@ -77,14 +77,18 @@ install_files()
|
||||
return 1
|
||||
fi
|
||||
|
||||
install -v -m 0755 -t $PREFIX/usr/sbin src/smartdns
|
||||
install -v -m 0755 -t $PREFIX/usr/sbin usr/sbin/smartdns
|
||||
if [ $? -ne 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
install -v -m 0640 -t $PREFIX$SMARTDNS_CONF_DIR etc/smartdns/smartdns.conf
|
||||
if [ $? -ne 0 ]; then
|
||||
return 1
|
||||
if [ -e "$PREFIX$SMARTDNS_CONF_DIR/smartdns.conf" ]; then
|
||||
cp etc/smartdns/smartdns.conf $PREFIX$SMARTDNS_CONF_DIR/smartdns.conf.pkg
|
||||
else
|
||||
install -v -m 0640 -t $PREFIX$SMARTDNS_CONF_DIR etc/smartdns/smartdns.conf
|
||||
if [ $? -ne 0 ]; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
install -v -m 0640 -t $PREFIX/etc/default etc/default/smartdns
|
||||
@@ -118,7 +122,6 @@ uninstall_smartdns()
|
||||
if [ -z "$PREFIX" ]; then
|
||||
stop_service 2>/dev/null
|
||||
fi
|
||||
rm -f $PREFIX$SMARTDNS_CONF_DIR/smartdns.conf
|
||||
rmdir $PREFIX$SMARTDNS_CONF_DIR 2>/dev/null
|
||||
rm -f $PREFIX/usr/sbin/smartdns
|
||||
rm -f $PREFIX/etc/default/smartdns
|
||||
@@ -23,12 +23,17 @@ build()
|
||||
cd $PKG_ROOT/
|
||||
|
||||
# Generic x86_64
|
||||
mkdir $PKG_ROOT/smartdns/src -p
|
||||
mkdir $PKG_ROOT/smartdns/usr/sbin -p
|
||||
mkdir $PKG_ROOT/smartdns/package -p
|
||||
mkdir $PKG_ROOT/smartdns/systemd -p
|
||||
|
||||
cd $SMARTDNS_DIR
|
||||
cp package/windows $PKG_ROOT/smartdns/package/ -a
|
||||
cp etc systemd *.md LICENSE install $PKG_ROOT/smartdns/ -a
|
||||
cp src/smartdns $PKG_ROOT/smartdns/src -a
|
||||
cp etc *.md LICENSE package/linux/install $PKG_ROOT/smartdns/ -a
|
||||
cp systemd/smartdns.service $PKG_ROOT/smartdns/systemd
|
||||
cp src/smartdns $PKG_ROOT/smartdns/usr/sbin -a
|
||||
chmod +x $PKG_ROOT/smartdns/install
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "copy smartdns file failed"
|
||||
rm -fr $PKG_ROOT
|
||||
|
||||
@@ -214,6 +214,12 @@ msgstr "校验TLS主机名"
|
||||
msgid "Set TLS hostname to verify."
|
||||
msgstr "设置校验TLS主机名。"
|
||||
|
||||
msgid "No check certificate"
|
||||
msgstr "停用证书校验"
|
||||
|
||||
msgid "Do not check certificate."
|
||||
msgstr "不校验证书的合法性。"
|
||||
|
||||
msgid "TLS SNI name"
|
||||
msgstr "TLS SNI名称"
|
||||
|
||||
|
||||
@@ -78,6 +78,16 @@ o.rempty = true
|
||||
o:depends("type", "tls")
|
||||
o:depends("type", "https")
|
||||
|
||||
---- certificate verify
|
||||
o = s:option(Flag, "no_check_certificate", translate("No check certificate"), translate("Do not check certificate."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
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 for query."))
|
||||
o.default = ""
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
--
|
||||
-- Copyright (C) 2018-2020 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
||||
--
|
||||
-- smartdns is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- smartdns is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
module("luci.controller.smartdns", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/smartdns") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
page = entry({"admin", "services", "smartdns"}, view("smartdns/smartdns"), _("SmartDNS"), 60)
|
||||
page.dependent = true
|
||||
end
|
||||
@@ -226,6 +226,12 @@ msgstr "校验TLS主机名"
|
||||
msgid "Set TLS hostname to verify."
|
||||
msgstr "设置校验TLS主机名。"
|
||||
|
||||
msgid "No check certificate"
|
||||
msgstr "停用证书校验"
|
||||
|
||||
msgid "Do not check certificate."
|
||||
msgstr "不校验证书的合法性。"
|
||||
|
||||
msgid "TLS SNI name"
|
||||
msgstr "TLS SNI名称"
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"admin/services/smartdns": {
|
||||
"title": "SmartDNS",
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "smartdns/smartdns"
|
||||
},
|
||||
"depends": {
|
||||
"uci": { "smartdns": true }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,20 @@
|
||||
"read": {
|
||||
"file": {
|
||||
"/etc/smartdns/*": [ "read" ],
|
||||
"/usr/sbin/iptables": [ "exec" ],
|
||||
"/usr/sbin/ip6tables": [ "exec" ],
|
||||
"/usr/sbin/iptables -t nat -nL PREROUTING": [ "exec" ],
|
||||
"/usr/sbin/ip6tables -t nat -nL PREROUTING": [ "exec" ],
|
||||
"/usr/sbin/smartdns": [ "exec" ]
|
||||
},
|
||||
"ubus": {
|
||||
"service": [ "list" ]
|
||||
}
|
||||
},
|
||||
"uci": [ "smartdns" ]
|
||||
},
|
||||
"write": {
|
||||
"file": {
|
||||
"/etc/smartdns/*": [ "write" ]
|
||||
}
|
||||
},
|
||||
"uci": [ "smartdns" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -201,7 +201,7 @@ return L.view.extend({
|
||||
_("Attempts to serve old responses from cache with a TTL of 0 in the response without waiting for the actual resolution to finish."));
|
||||
o.rmempty = false;
|
||||
o.default = o.disabled;
|
||||
|
||||
|
||||
// Redirect;
|
||||
o = s.taboption("settings", form.ListValue, "redirect", _("Redirect"), _("SmartDNS redirect mode"));
|
||||
o.placeholder = "none";
|
||||
@@ -253,7 +253,7 @@ return L.view.extend({
|
||||
|
||||
// dns server group;
|
||||
o = s.taboption("seconddns", form.Value, "seconddns_server_group", _("Server Group"),
|
||||
_("Query DNS through specific dns server group, such as office, home."));
|
||||
_("Query DNS through specific dns server group, such as office, home."));
|
||||
o.rmempty = true;
|
||||
o.placeholder = "default";
|
||||
o.datatype = "hostname";
|
||||
@@ -305,8 +305,7 @@ return L.view.extend({
|
||||
|
||||
// custom settings;
|
||||
o = s.taboption("custom", form.TextValue, "custom_conf",
|
||||
_(""),
|
||||
_("smartdns custom settings"));
|
||||
"", _("smartdns custom settings"));
|
||||
|
||||
o.rows = 20;
|
||||
o.cfgvalue = function (section_id) {
|
||||
@@ -390,6 +389,15 @@ return L.view.extend({
|
||||
o.depends("type", "tls")
|
||||
o.depends("type", "https")
|
||||
|
||||
// certificate verify
|
||||
o = s.taboption("advanced", form.Flag, "no_check_certificate", _("No check certificate"),
|
||||
_("Do not check certificate."))
|
||||
o.rmempty = false
|
||||
o.default = o.disabled
|
||||
o.modalonly = true;
|
||||
o.depends("type", "tls")
|
||||
o.depends("type", "https")
|
||||
|
||||
// SNI host name
|
||||
o = s.taboption("advanced", form.Value, "host_name", _("TLS SNI name"),
|
||||
_("Sets the server name indication for query."))
|
||||
@@ -482,4 +490,3 @@ return L.view.extend({
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -53,21 +53,15 @@ build()
|
||||
cd $ROOT/
|
||||
build_tool
|
||||
|
||||
mkdir $ROOT/root/usr/lib/lua/ -p
|
||||
mkdir $ROOT/root/usr/lib/lua/luci/controller/ -p
|
||||
mkdir $ROOT/root/usr/lib/lua/luci -p
|
||||
mkdir $ROOT/root/usr/share/rpcd/acl.d/ -p
|
||||
cp $ROOT/files/luci/controller/* $ROOT/root/usr/lib/lua/luci/controller/ -avf
|
||||
cp $ROOT/files/luci/i18n $ROOT/root/usr/lib/lua/luci/ -avf
|
||||
cp $ROOT/files/luci/view $ROOT/root/usr/lib/lua/luci/ -avf
|
||||
|
||||
mkdir $ROOT/root/www/luci-static/resources/view -p
|
||||
cp $ROOT/files/luci/htdocs/luci-static/resources/view/* $ROOT/root/www/luci-static/resources/view/ -avf
|
||||
|
||||
#Generate Language
|
||||
$PO2LMO $ROOT/files/luci/i18n/smartdns.zh-cn.po $ROOT/root/usr/lib/lua/luci/i18n/smartdns.zh-cn.lmo
|
||||
rm $ROOT/root/usr/lib/lua/luci/i18n/smartdns.zh-cn.po
|
||||
|
||||
cp $ROOT/files/usr $ROOT/root/ -avf
|
||||
cp $ROOT/files/root/* $ROOT/root/ -avf
|
||||
INST_SIZE="`du -sb $ROOT/root/ | awk '{print $1}'`"
|
||||
|
||||
sed -i "s/^Architecture.*/Architecture: all/g" $ROOT/control/control
|
||||
|
||||
@@ -9,6 +9,9 @@ PKG_NAME:=smartdns
|
||||
PKG_VERSION:=1.2019.28
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://www.github.com/pymumu/smartdns.git
|
||||
PKG_SOURCE_VERSION:=982002e836e486fb4e360bc10e84e7e7197caf46
|
||||
|
||||
@@ -46,7 +46,6 @@ set_forward_dnsmasq()
|
||||
[ "$server" = "$addr" ] && continue
|
||||
uci add_list dhcp.@dnsmasq[0].server="$server"
|
||||
done
|
||||
uci delete dhcp.@dnsmasq[0].resolvfile 2>/dev/null
|
||||
uci set dhcp.@dnsmasq[0].noresolv=1
|
||||
uci commit dhcp
|
||||
/etc/init.d/dnsmasq restart
|
||||
@@ -57,14 +56,13 @@ stop_forward_dnsmasq()
|
||||
local OLD_PORT="$1"
|
||||
addr="127.0.0.1#$OLD_PORT"
|
||||
OLD_SERVER="$(uci get dhcp.@dnsmasq[0].server 2>/dev/null)"
|
||||
if echo "$OLD_SERVER" | grep "^$addr" >/dev/null 2>&1; then
|
||||
if ! echo "$OLD_SERVER" | grep "^$addr" >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
|
||||
uci del_list dhcp.@dnsmasq[0].server="$addr" 2>/dev/null
|
||||
addrlist="$(uci get dhcp.@dnsmasq[0].server 2>/dev/null)"
|
||||
[ -z "$addrlist" ] && {
|
||||
uci set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.auto 2>/dev/null
|
||||
uci delete dhcp.@dnsmasq[0].noresolv 2>/dev/null
|
||||
}
|
||||
uci commit dhcp
|
||||
@@ -125,7 +123,6 @@ service_triggers() {
|
||||
procd_add_reload_trigger smartdns
|
||||
}
|
||||
|
||||
|
||||
conf_append()
|
||||
{
|
||||
echo "$1 $2" >> $SMARTDNS_CONF_TMP
|
||||
@@ -159,6 +156,7 @@ load_server()
|
||||
config_get type "$section" "type" "udp"
|
||||
config_get ip "$section" "ip" ""
|
||||
config_get tls_host_verify "$section" "tls_host_verify" ""
|
||||
config_get no_check_certificate "$section" "no_check_certificate" "0"
|
||||
config_get host_name "$section" "host_name" ""
|
||||
config_get http_host "$section" "http_host" ""
|
||||
config_get server_group "$section" "server_group" ""
|
||||
@@ -189,6 +187,7 @@ load_server()
|
||||
fi
|
||||
|
||||
[ -z "$tls_host_verify" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -tls-host-verify $tls_host_verify"
|
||||
[ "$no_check_certificate" = "0" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -no-check-certificate"
|
||||
[ -z "$host_name" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -host-name $host_name"
|
||||
[ -z "$http_host" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -http-host $http_host"
|
||||
[ -z "$server_group" ] || ADDITIONAL_ARGS="$ADDITIONAL_ARGS -group $server_group"
|
||||
|
||||
@@ -38,7 +38,7 @@ else
|
||||
override LDFLAGS += -lssl -lcrypto -lpthread
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
|
||||
49
src/dns.c
49
src/dns.c
@@ -18,15 +18,15 @@
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "dns.h"
|
||||
#include "tlog.h"
|
||||
#include "stringutil.h"
|
||||
#include "tlog.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define QR_MASK 0x8000
|
||||
#define OPCODE_MASK 0x7800
|
||||
@@ -37,9 +37,9 @@
|
||||
#define RCODE_MASK 0x000F
|
||||
#define DNS_RR_END (0XFFFF)
|
||||
|
||||
#define UNUSED(expr) \
|
||||
do { \
|
||||
(void)(expr); \
|
||||
#define UNUSED(expr) \
|
||||
do { \
|
||||
(void)(expr); \
|
||||
} while (0)
|
||||
|
||||
/* read short and move pointer */
|
||||
@@ -305,7 +305,8 @@ static int _dns_get_qr_head(struct dns_data_context *data_context, char *domain,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_add_rr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass, int ttl, int rr_len)
|
||||
static int _dns_add_rr_head(struct dns_data_context *data_context, char *domain, int qtype, int qclass, int ttl,
|
||||
int rr_len)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
@@ -333,7 +334,8 @@ static int _dns_add_rr_head(struct dns_data_context *data_context, char *domain,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_get_rr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass, int *ttl, int *rr_len)
|
||||
static int _dns_get_rr_head(struct dns_data_context *data_context, char *domain, int maxsize, int *qtype, int *qclass,
|
||||
int *ttl, int *rr_len)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
@@ -358,7 +360,8 @@ static int _dns_get_rr_head(struct dns_data_context *data_context, char *domain,
|
||||
return len;
|
||||
}
|
||||
|
||||
static int _dns_add_RAW(struct dns_packet *packet, dns_rr_type rrtype, dns_type_t rtype, char *domain, int ttl, void *raw, int raw_len)
|
||||
static int _dns_add_RAW(struct dns_packet *packet, dns_rr_type rrtype, dns_type_t rtype, char *domain, int ttl,
|
||||
void *raw, int raw_len)
|
||||
{
|
||||
int maxlen = 0;
|
||||
int len = 0;
|
||||
@@ -451,14 +454,16 @@ static int _dns_add_opt_RAW(struct dns_packet *packet, dns_opt_code_t opt_rrtype
|
||||
return _dns_add_RAW(packet, DNS_RRS_OPT, DNS_OPT_T_TCP_KEEPALIVE, "", 0, opt_data, len);
|
||||
}
|
||||
|
||||
static int _dns_get_opt_RAW(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct dns_opt *dns_opt, int *dns_optlen)
|
||||
static int _dns_get_opt_RAW(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct dns_opt *dns_opt,
|
||||
int *dns_optlen)
|
||||
{
|
||||
*dns_optlen = DNS_MAX_OPT_LEN;
|
||||
|
||||
return _dns_get_RAW(rrs, domain, maxsize, ttl, dns_opt, dns_optlen);
|
||||
}
|
||||
|
||||
static int __attribute__((unused)) _dns_add_OPT(struct dns_packet *packet, dns_rr_type type, unsigned short opt_code, unsigned short opt_len, struct dns_opt *opt)
|
||||
static int __attribute__((unused)) _dns_add_OPT(struct dns_packet *packet, dns_rr_type type, unsigned short opt_code,
|
||||
unsigned short opt_len, struct dns_opt *opt)
|
||||
{
|
||||
// TODO
|
||||
|
||||
@@ -508,7 +513,8 @@ static int __attribute__((unused)) _dns_add_OPT(struct dns_packet *packet, dns_
|
||||
return _dns_rr_add_end(packet, type, DNS_T_OPT, len);
|
||||
}
|
||||
|
||||
static int __attribute__((unused)) _dns_get_OPT(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt *opt, int *opt_maxlen)
|
||||
static int __attribute__((unused)) _dns_get_OPT(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len,
|
||||
struct dns_opt *opt, int *opt_maxlen)
|
||||
{
|
||||
// TODO
|
||||
|
||||
@@ -593,7 +599,8 @@ int dns_get_NS(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *c
|
||||
return _dns_get_RAW(rrs, domain, maxsize, ttl, cname, &len);
|
||||
}
|
||||
|
||||
int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, unsigned char addr[DNS_RR_AAAA_LEN])
|
||||
int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl,
|
||||
unsigned char addr[DNS_RR_AAAA_LEN])
|
||||
{
|
||||
return _dns_add_RAW(packet, type, DNS_T_AAAA, domain, ttl, addr, DNS_RR_AAAA_LEN);
|
||||
}
|
||||
@@ -749,7 +756,8 @@ int dns_add_OPT_TCP_KEEYALIVE(struct dns_packet *packet, unsigned short timeout)
|
||||
return _dns_add_opt_RAW(packet, DNS_OPT_T_TCP_KEEPALIVE, &timeout_net, data_len);
|
||||
}
|
||||
|
||||
int dns_get_OPT_TCP_KEEYALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, unsigned short *timeout)
|
||||
int dns_get_OPT_TCP_KEEYALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len,
|
||||
unsigned short *timeout)
|
||||
{
|
||||
unsigned char opt_data[DNS_MAX_OPT_LEN];
|
||||
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
||||
@@ -961,7 +969,8 @@ 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 enough %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;
|
||||
@@ -979,7 +988,8 @@ 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 enough %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;
|
||||
}
|
||||
|
||||
@@ -988,7 +998,8 @@ 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 enough %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);
|
||||
@@ -1089,7 +1100,8 @@ static int _dns_encode_qr_head(struct dns_context *context, char *domain, int qt
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_decode_rr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass, int *ttl, int *rr_len)
|
||||
static int _dns_decode_rr_head(struct dns_context *context, char *domain, int domain_size, int *qtype, int *qclass,
|
||||
int *ttl, int *rr_len)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
@@ -1358,7 +1370,8 @@ static int _dns_decode_opt_ecs(struct dns_context *context, struct dns_opt_ecs *
|
||||
memcpy(ecs->addr, context->ptr, len);
|
||||
context->ptr += len;
|
||||
|
||||
tlog(TLOG_DEBUG, "ECS: family:%d, source_prefix:%d, scope_prefix:%d, len:%d", ecs->family, ecs->source_prefix, ecs->scope_prefix, len);
|
||||
tlog(TLOG_DEBUG, "ECS: family:%d, source_prefix:%d, scope_prefix:%d, len:%d", ecs->family, ecs->source_prefix,
|
||||
ecs->scope_prefix, len);
|
||||
tlog(TLOG_DEBUG, "%d.%d.%d.%d", ecs->addr[0], ecs->addr[1], ecs->addr[2], ecs->addr[3]);
|
||||
|
||||
return 0;
|
||||
|
||||
19
src/dns.h
19
src/dns.h
@@ -44,7 +44,10 @@ typedef enum dns_rr_type {
|
||||
DNS_RRS_END,
|
||||
} dns_rr_type;
|
||||
|
||||
typedef enum dns_class { DNS_C_IN = 1, DNS_C_ANY = 255 } dns_class_t;
|
||||
typedef enum dns_class {
|
||||
DNS_C_IN = 1, // DNS C IN
|
||||
DNS_C_ANY = 255
|
||||
} dns_class_t;
|
||||
|
||||
typedef enum dns_type {
|
||||
DNS_T_A = 1,
|
||||
@@ -63,10 +66,10 @@ typedef enum dns_type {
|
||||
DNS_T_ALL = 255
|
||||
} dns_type_t;
|
||||
|
||||
typedef enum dns_opt_code {
|
||||
DNS_OPT_T_ECS = 8,
|
||||
typedef enum dns_opt_code {
|
||||
DNS_OPT_T_ECS = 8, // OPT ECS
|
||||
DNS_OPT_T_TCP_KEEPALIVE = 11,
|
||||
DNS_OPT_T_ALL = 255
|
||||
DNS_OPT_T_ALL = 255
|
||||
} dns_opt_code_t;
|
||||
|
||||
typedef enum dns_opcode {
|
||||
@@ -107,7 +110,7 @@ struct dns_head {
|
||||
unsigned short ancount; /* number of answer entries */
|
||||
unsigned short nscount; /* number of authority entries */
|
||||
unsigned short nrcount; /* number of addititional resource entries */
|
||||
} __attribute__((packed));
|
||||
} __attribute__((packed, aligned(2)));
|
||||
|
||||
struct dns_rrs {
|
||||
unsigned short next;
|
||||
@@ -196,7 +199,8 @@ int dns_get_A(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned
|
||||
int dns_add_PTR(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, char *cname);
|
||||
int dns_get_PTR(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, char *cname, int cname_size);
|
||||
|
||||
int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, unsigned char addr[DNS_RR_AAAA_LEN]);
|
||||
int dns_add_AAAA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl,
|
||||
unsigned char addr[DNS_RR_AAAA_LEN]);
|
||||
int dns_get_AAAA(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned char addr[DNS_RR_AAAA_LEN]);
|
||||
|
||||
int dns_add_SOA(struct dns_packet *packet, dns_rr_type type, char *domain, int ttl, struct dns_soa *soa);
|
||||
@@ -212,7 +216,8 @@ int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs);
|
||||
int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs);
|
||||
|
||||
int dns_add_OPT_TCP_KEEYALIVE(struct dns_packet *packet, unsigned short timeout);
|
||||
int dns_get_OPT_TCP_KEEYALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, unsigned short *timeout);
|
||||
int dns_get_OPT_TCP_KEEYALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len,
|
||||
unsigned short *timeout);
|
||||
/*
|
||||
* Packet operation
|
||||
*/
|
||||
|
||||
@@ -118,7 +118,8 @@ static void _dns_cache_move_inactive(struct dns_cache *dns_cache)
|
||||
list_add_tail(&dns_cache->list, &dns_cache_head.inactive_list);
|
||||
}
|
||||
|
||||
int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, int speed)
|
||||
int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr,
|
||||
int addr_len, int speed)
|
||||
{
|
||||
struct dns_cache *dns_cache = NULL;
|
||||
|
||||
@@ -129,7 +130,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
|
||||
/* lookup existing cache */
|
||||
dns_cache = dns_cache_lookup(domain, qtype);
|
||||
if (dns_cache == NULL) {
|
||||
return 0;
|
||||
return dns_cache_insert(domain, cname, cname_ttl, ttl, qtype, addr, addr_len, speed);
|
||||
}
|
||||
|
||||
if (ttl < DNS_CACHE_TTL_MIN) {
|
||||
@@ -178,7 +179,8 @@ errout_unlock:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, int speed)
|
||||
int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr,
|
||||
int addr_len, int speed)
|
||||
{
|
||||
uint32_t key = 0;
|
||||
struct dns_cache *dns_cache = NULL;
|
||||
|
||||
@@ -57,9 +57,11 @@ struct dns_cache {
|
||||
|
||||
int dns_cache_init(int size, int enable_inactive, int inactive_list_expired);
|
||||
|
||||
int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, int speed);
|
||||
int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr,
|
||||
int addr_len, int speed);
|
||||
|
||||
int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, int speed);
|
||||
int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr,
|
||||
int addr_len, int speed);
|
||||
|
||||
struct dns_cache *dns_cache_lookup(char *domain, dns_type_t qtype);
|
||||
|
||||
|
||||
496
src/dns_client.c
496
src/dns_client.c
@@ -29,8 +29,8 @@
|
||||
#include "tlog.h"
|
||||
#include "util.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/filter.h>
|
||||
#include <netdb.h>
|
||||
@@ -46,7 +46,6 @@
|
||||
#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>
|
||||
@@ -59,11 +58,11 @@
|
||||
#define DNS_TCP_IDLE_TIMEOUT (60 * 10)
|
||||
#define DNS_TCP_CONNECT_TIMEOUT (5)
|
||||
#define DNS_QUERY_TIMEOUT (500)
|
||||
#define DNS_QUERY_RETRY (3)
|
||||
#define DNS_QUERY_RETRY (6)
|
||||
#define DNS_PENDING_SERVER_RETRY 40
|
||||
#define SOCKET_PRIORITY (6)
|
||||
#define SOCKET_IP_TOS (IPTOS_LOWDELAY | IPTOS_RELIABILITY)
|
||||
|
||||
|
||||
/* ECS info */
|
||||
struct dns_client_ecs {
|
||||
int enable;
|
||||
@@ -106,8 +105,10 @@ struct dns_server_info {
|
||||
int ttl;
|
||||
int ttl_range;
|
||||
SSL *ssl;
|
||||
int ssl_write_len;
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL_SESSION *ssl_session;
|
||||
char skip_check_cert;
|
||||
dns_server_status status;
|
||||
|
||||
struct dns_server_buff send_buff;
|
||||
@@ -149,6 +150,7 @@ struct dns_server_pending {
|
||||
unsigned int query_v6;
|
||||
/* server type */
|
||||
dns_server_type_t type;
|
||||
int retry_cnt;
|
||||
|
||||
int port;
|
||||
|
||||
@@ -247,12 +249,11 @@ static LIST_HEAD(pending_servers);
|
||||
static pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int dns_client_has_bootstrap_dns = 0;
|
||||
|
||||
const char *_dns_server_get_type_string(dns_server_type_t type)
|
||||
const char *_dns_server_get_type_string(dns_server_type_t type)
|
||||
{
|
||||
const char *type_str = "";
|
||||
|
||||
switch (type)
|
||||
{
|
||||
switch (type) {
|
||||
case DNS_SERVER_UDP:
|
||||
type_str = "udp";
|
||||
break;
|
||||
@@ -322,8 +323,9 @@ static int _dns_client_server_exist(const char *server_ip, int port, dns_server_
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _dns_client_server_update_ttl(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 _dns_client_server_update_ttl(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)
|
||||
{
|
||||
struct dns_server_info *server_info = userptr;
|
||||
if (result != PING_RESULT_RESPONSE || server_info == NULL) {
|
||||
@@ -479,7 +481,8 @@ errout:
|
||||
}
|
||||
|
||||
/* add server to group */
|
||||
static 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;
|
||||
|
||||
@@ -713,8 +716,42 @@ static char *_dns_client_server_get_spki(struct dns_server_info *server_info, in
|
||||
return spki;
|
||||
}
|
||||
|
||||
static int _dns_client_set_trusted_cert(SSL_CTX *ssl_ctx)
|
||||
{
|
||||
char *cafile = NULL;
|
||||
char *capath = NULL;
|
||||
int cert_path_set = 0;
|
||||
|
||||
if (dns_conf_ca_file[0]) {
|
||||
cafile = dns_conf_ca_file;
|
||||
}
|
||||
|
||||
if (dns_conf_ca_path[0]) {
|
||||
capath = dns_conf_ca_path;
|
||||
}
|
||||
|
||||
if (cafile == NULL && capath == NULL) {
|
||||
if (SSL_CTX_set_default_verify_paths(ssl_ctx)) {
|
||||
cafile = "/etc/ssl/certs/ca-certificates.crt";
|
||||
capath = "/etc/ssl/certs";
|
||||
} else {
|
||||
cert_path_set = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cert_path_set == 0) {
|
||||
if (!SSL_CTX_load_verify_locations(ssl_ctx, cafile, capath)) {
|
||||
tlog(TLOG_WARN, "load certificate from %s:%s failed.", cafile, capath);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* add dns server information */
|
||||
static int _dns_client_server_add(char *server_ip, char *server_host, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags)
|
||||
static int _dns_client_server_add(char *server_ip, char *server_host, int port, dns_server_type_t server_type,
|
||||
struct client_dns_server_flags *flags)
|
||||
{
|
||||
struct dns_server_info *server_info = NULL;
|
||||
struct addrinfo *gai = NULL;
|
||||
@@ -722,6 +759,7 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
int ttl = 0;
|
||||
char port_s[8];
|
||||
int sock_type;
|
||||
char skip_check_cert = 0;
|
||||
|
||||
switch (server_type) {
|
||||
case DNS_SERVER_UDP: {
|
||||
@@ -746,11 +784,13 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
}
|
||||
}
|
||||
sock_type = SOCK_STREAM;
|
||||
skip_check_cert = flag_https->skip_check_cert;
|
||||
} break;
|
||||
case DNS_SERVER_TLS: {
|
||||
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
|
||||
spki_data_len = flag_tls->spi_len;
|
||||
sock_type = SOCK_STREAM;
|
||||
skip_check_cert = flag_tls->skip_check_cert;
|
||||
} break;
|
||||
case DNS_SERVER_TCP:
|
||||
sock_type = SOCK_STREAM;
|
||||
@@ -796,6 +836,7 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
server_info->status = DNS_SERVER_STATUS_INIT;
|
||||
server_info->ttl = ttl;
|
||||
server_info->ttl_range = 0;
|
||||
server_info->skip_check_cert = skip_check_cert;
|
||||
memcpy(&server_info->flags, flags, sizeof(server_info->flags));
|
||||
|
||||
/* exclude this server from default group */
|
||||
@@ -813,15 +854,26 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
#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;
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(server_info->ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
SSL_CTX_set_session_cache_mode(server_info->ssl_ctx, SSL_SESS_CACHE_CLIENT);
|
||||
SSL_CTX_sess_set_cache_size(server_info->ssl_ctx, 64);
|
||||
if (_dns_client_set_trusted_cert(server_info->ssl_ctx) != 0) {
|
||||
tlog(TLOG_WARN, "disable check certificate for %s.", server_info->ip);
|
||||
server_info->skip_check_cert = 1;
|
||||
SSL_CTX_set_verify(server_info->ssl_ctx, SSL_VERIFY_NONE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* safe address info */
|
||||
if (gai->ai_addrlen > sizeof(server_info->in6)) {
|
||||
tlog(TLOG_ERROR, "addr len invalid, %d, %zd, %d", gai->ai_addrlen, sizeof(server_info->addr), server_info->ai_family);
|
||||
tlog(TLOG_ERROR, "addr len invalid, %d, %zd, %d", gai->ai_addrlen, sizeof(server_info->addr),
|
||||
server_info->ai_family);
|
||||
goto errout;
|
||||
}
|
||||
memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen);
|
||||
@@ -829,7 +881,8 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
/* start ping task */
|
||||
if (server_type == DNS_SERVER_UDP) {
|
||||
if (ttl <= 0 && (server_info->flags.result_flag & DNSSERVER_FLAG_CHECK_TTL)) {
|
||||
server_info->ping_host = fast_ping_start(PING_TYPE_DNS, server_ip, 0, 60000, 1000, _dns_client_server_update_ttl, server_info);
|
||||
server_info->ping_host =
|
||||
fast_ping_start(PING_TYPE_DNS, server_ip, 0, 60000, 1000, _dns_client_server_update_ttl, server_info);
|
||||
if (server_info->ping_host == NULL) {
|
||||
tlog(TLOG_ERROR, "start ping failed.");
|
||||
goto errout;
|
||||
@@ -854,13 +907,14 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
|
||||
return 0;
|
||||
errout:
|
||||
if (server_info) {
|
||||
if (server_info->ping_host) {
|
||||
fast_ping_stop(server_info->ping_host);
|
||||
}
|
||||
|
||||
if (server_info->ssl_ctx) {
|
||||
SSL_CTX_free(server_info->ssl_ctx);
|
||||
server_info->ssl_ctx = NULL;
|
||||
}
|
||||
if (server_info->ping_host) {
|
||||
fast_ping_stop(server_info->ping_host);
|
||||
}
|
||||
|
||||
free(server_info);
|
||||
}
|
||||
@@ -880,8 +934,12 @@ static void _dns_client_close_socket(struct dns_server_info *server_info)
|
||||
|
||||
if (server_info->ssl) {
|
||||
/* Shutdown ssl */
|
||||
if (server_info->status == DNS_SERVER_STATUS_CONNECTED) {
|
||||
SSL_shutdown(server_info->ssl);
|
||||
}
|
||||
SSL_free(server_info->ssl);
|
||||
server_info->ssl = NULL;
|
||||
server_info->ssl_write_len = -1;
|
||||
}
|
||||
|
||||
/* remove fd from epoll */
|
||||
@@ -896,6 +954,36 @@ static void _dns_client_close_socket(struct dns_server_info *server_info)
|
||||
tlog(TLOG_DEBUG, "server %s closed.", server_info->ip);
|
||||
}
|
||||
|
||||
static void _dns_client_shutdown_socket(struct dns_server_info *server_info)
|
||||
{
|
||||
if (server_info->fd <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (server_info->type) {
|
||||
case DNS_SERVER_UDP:
|
||||
return;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
if (server_info->fd > 0) {
|
||||
shutdown(server_info->fd, SHUT_RDWR);
|
||||
}
|
||||
break;
|
||||
case DNS_SERVER_TLS:
|
||||
case DNS_SERVER_HTTPS:
|
||||
if (server_info->ssl) {
|
||||
/* Shutdown ssl */
|
||||
if (server_info->status == DNS_SERVER_STATUS_CONNECTED) {
|
||||
SSL_shutdown(server_info->ssl);
|
||||
}
|
||||
shutdown(server_info->fd, SHUT_RDWR);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _dns_client_server_close(struct dns_server_info *server_info)
|
||||
{
|
||||
/* stop ping task */
|
||||
@@ -1004,7 +1092,8 @@ void _dns_client_server_pending_release(struct dns_server_pending *pending)
|
||||
free(pending);
|
||||
}
|
||||
|
||||
static int _dns_client_server_pending(char *server_ip, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags)
|
||||
static int _dns_client_server_pending(char *server_ip, int port, dns_server_type_t server_type,
|
||||
struct client_dns_server_flags *flags)
|
||||
{
|
||||
struct dns_server_pending *pending = NULL;
|
||||
|
||||
@@ -1040,8 +1129,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;
|
||||
|
||||
@@ -1071,7 +1160,8 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dns_client_add_server(char *server_ip, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags)
|
||||
int dns_client_add_server(char *server_ip, int port, dns_server_type_t server_type,
|
||||
struct client_dns_server_flags *flags)
|
||||
{
|
||||
return _dns_client_add_server_pending(server_ip, NULL, port, server_type, flags, 1);
|
||||
}
|
||||
@@ -1287,7 +1377,8 @@ static int _dns_replied_check_add(struct dns_query_struct *dns_query, struct soc
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *inpacket, int inpacket_len, struct sockaddr *from, socklen_t from_len)
|
||||
static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *inpacket, int inpacket_len,
|
||||
struct sockaddr *from, socklen_t from_len)
|
||||
{
|
||||
int len;
|
||||
int i;
|
||||
@@ -1309,8 +1400,8 @@ static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *
|
||||
len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
|
||||
if (len != 0) {
|
||||
char host_name[DNS_MAX_CNAME_LEN];
|
||||
tlog(TLOG_WARN, "decode failed, packet len = %d, tc = %d, id = %d, from = %s\n", inpacket_len, packet->head.tc, packet->head.id,
|
||||
gethost_by_addr(host_name, sizeof(host_name), from));
|
||||
tlog(TLOG_WARN, "decode failed, packet len = %d, tc = %d, id = %d, from = %s\n", inpacket_len, packet->head.tc,
|
||||
packet->head.id, gethost_by_addr(host_name, sizeof(host_name), from));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1320,9 +1411,12 @@ static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *
|
||||
return -1;
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, tc = %d, rd = %d, ra = %d, rcode = %d, payloadsize = %d\n",
|
||||
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len, packet->head.id, packet->head.tc,
|
||||
packet->head.rd, packet->head.ra, packet->head.rcode, dns_get_OPT_payload_size(packet));
|
||||
tlog(TLOG_DEBUG,
|
||||
"qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, tc = %d, rd = %d, ra = %d, rcode "
|
||||
"= %d, payloadsize = %d\n",
|
||||
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len,
|
||||
packet->head.id, packet->head.tc, packet->head.rd, packet->head.ra, packet->head.rcode,
|
||||
dns_get_OPT_payload_size(packet));
|
||||
|
||||
/* get question */
|
||||
rrs = dns_get_rrs_start(packet, DNS_RRS_QD, &rr_count);
|
||||
@@ -1361,7 +1455,8 @@ static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *
|
||||
|
||||
/* notify caller dns query result */
|
||||
if (query->callback) {
|
||||
ret = query->callback(query->domain, DNS_QUERY_RESULT, server_info->flags.result_flag, packet, inpacket, inpacket_len, query->user_ptr);
|
||||
ret = query->callback(query->domain, DNS_QUERY_RESULT, server_info->flags.result_flag, packet, inpacket,
|
||||
inpacket_len, query->user_ptr);
|
||||
if (request_num == 0 || ret) {
|
||||
/* if all server replied, or done, stop query, release resource */
|
||||
_dns_client_query_remove(query);
|
||||
@@ -1453,8 +1548,13 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
|
||||
set_sock_keepalive(fd, 15, 3, 4);
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen) != 0) {
|
||||
if (errno == ENETUNREACH) {
|
||||
tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (errno != EINPROGRESS) {
|
||||
tlog(TLOG_ERROR, "connect failed.");
|
||||
tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
@@ -1463,7 +1563,7 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
|
||||
event.events = EPOLLIN | EPOLLOUT;
|
||||
event.data.ptr = server_info;
|
||||
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
|
||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||
tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1517,20 +1617,26 @@ 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, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof(yes));
|
||||
// setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof(yes));
|
||||
// set_sock_keepalive(fd, 15, 3, 4);
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof(yes));
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_THIN_LINEAR_TIMEOUTS, &yes, sizeof(yes));
|
||||
set_sock_keepalive(fd, 15, 3, 4);
|
||||
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 == ENETUNREACH) {
|
||||
tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (errno != EINPROGRESS) {
|
||||
tlog(TLOG_ERROR, "connect %s failed, %s", server_info->ip, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
SSL_set_connect_state(ssl);
|
||||
if (SSL_set_fd(ssl, fd) == 0) {
|
||||
tlog(TLOG_ERROR, "ssl set fd failed.");
|
||||
goto errout;
|
||||
@@ -1541,7 +1647,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
|
||||
SSL_set_session(ssl, server_info->ssl_session);
|
||||
}
|
||||
|
||||
SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
SSL_set_mode(ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
if (hostname[0] != 0) {
|
||||
SSL_set_tlsext_host_name(ssl, hostname);
|
||||
}
|
||||
@@ -1556,6 +1662,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
|
||||
|
||||
server_info->fd = fd;
|
||||
server_info->ssl = ssl;
|
||||
server_info->ssl_write_len = -1;
|
||||
server_info->status = DNS_SERVER_STATUS_CONNECTING;
|
||||
|
||||
tlog(TLOG_DEBUG, "tls server %s connecting.\n", server_info->ip);
|
||||
@@ -1646,7 +1753,8 @@ static int _dns_client_process_udp(struct dns_server_info *server_info, struct e
|
||||
}
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "recv udp packet from %s, len: %d, ttl: %d", gethost_by_addr(from_host, sizeof(from_host), (struct sockaddr *)&from), len, ttl);
|
||||
tlog(TLOG_DEBUG, "recv udp packet from %s, len: %d, ttl: %d",
|
||||
gethost_by_addr(from_host, sizeof(from_host), (struct sockaddr *)&from), len, ttl);
|
||||
|
||||
/* update recv time */
|
||||
time(&server_info->last_recv);
|
||||
@@ -1666,23 +1774,21 @@ static int _dns_client_socket_ssl_send(SSL *ssl, const void *buf, int num)
|
||||
unsigned long ssl_err = 0;
|
||||
|
||||
if (ssl == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = SSL_write(ssl, buf, num);
|
||||
if (ret >= 0) {
|
||||
if (ret > 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssl_ret = SSL_get_error(ssl, ret);
|
||||
switch (ssl_ret) {
|
||||
case SSL_ERROR_NONE:
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
return 0;
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
case SSL_ERROR_WANT_READ:
|
||||
errno = EAGAIN;
|
||||
ret = -1;
|
||||
@@ -1693,12 +1799,15 @@ 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 || ERR_GET_REASON(ssl_err) == SSL_R_PROTOCOL_IS_SHUTDOWN) {
|
||||
int ssl_reason = ERR_GET_REASON(ssl_err);
|
||||
if (ssl_reason == SSL_R_UNINITIALIZED || ssl_reason == SSL_R_PROTOCOL_IS_SHUTDOWN ||
|
||||
ssl_reason == SSL_R_BAD_LENGTH || ssl_reason == SSL_R_SHUTDOWN_WHILE_IN_INIT ||
|
||||
ssl_reason == SSL_R_BAD_WRITE_RETRY) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "SSL write fail error no: %s(%ld)\n", ERR_reason_error_string(ssl_err), ssl_err);
|
||||
tlog(TLOG_ERROR, "SSL write fail error no: %s(%d)\n", ERR_reason_error_string(ssl_err), ssl_reason);
|
||||
errno = EFAULT;
|
||||
ret = -1;
|
||||
break;
|
||||
@@ -1733,9 +1842,6 @@ static int _dns_client_socket_ssl_recv(SSL *ssl, void *buf, int num)
|
||||
ssl_ret = SSL_get_error(ssl, ret);
|
||||
switch (ssl_ret) {
|
||||
case SSL_ERROR_NONE:
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
return 0;
|
||||
break;
|
||||
@@ -1749,16 +1855,25 @@ static int _dns_client_socket_ssl_recv(SSL *ssl, void *buf, int num)
|
||||
break;
|
||||
case SSL_ERROR_SSL:
|
||||
ssl_err = ERR_get_error();
|
||||
if (ERR_GET_REASON(ssl_err) == SSL_R_UNINITIALIZED) {
|
||||
int ssl_reason = ERR_GET_REASON(ssl_err);
|
||||
if (ssl_reason == SSL_R_UNINITIALIZED) {
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tlog(TLOG_ERROR, "SSL read fail error no: %s(%ld)\n", ERR_reason_error_string(ssl_err), ssl_err);
|
||||
if (ssl_reason == SSL_R_SHUTDOWN_WHILE_IN_INIT || ssl_reason == SSL_R_PROTOCOL_IS_SHUTDOWN) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlog(TLOG_ERROR, "SSL read fail error no: %s(%lx)\n", ERR_reason_error_string(ssl_err), ssl_err);
|
||||
errno = EFAULT;
|
||||
ret = -1;
|
||||
break;
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if (errno == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno != ECONNRESET) {
|
||||
tlog(TLOG_INFO, "SSL syscall failed, %s ", strerror(errno));
|
||||
}
|
||||
@@ -1780,7 +1895,18 @@ static int _dns_client_socket_send(struct dns_server_info *server_info)
|
||||
} else if (server_info->type == DNS_SERVER_TCP) {
|
||||
return send(server_info->fd, server_info->send_buff.data, server_info->send_buff.len, MSG_NOSIGNAL);
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
|
||||
return _dns_client_socket_ssl_send(server_info->ssl, server_info->send_buff.data, server_info->send_buff.len);
|
||||
int write_len = server_info->send_buff.len;
|
||||
if (server_info->ssl_write_len > 0) {
|
||||
write_len = server_info->ssl_write_len;
|
||||
server_info->ssl_write_len = -1;
|
||||
}
|
||||
int ret = _dns_client_socket_ssl_send(server_info->ssl, server_info->send_buff.data, write_len);
|
||||
if (ret != 0) {
|
||||
if (errno == EAGAIN) {
|
||||
server_info->ssl_write_len = write_len;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -1791,7 +1917,8 @@ static int _dns_client_socket_recv(struct dns_server_info *server_info)
|
||||
if (server_info->type == DNS_SERVER_UDP) {
|
||||
return -1;
|
||||
} else if (server_info->type == DNS_SERVER_TCP) {
|
||||
return recv(server_info->fd, server_info->recv_buff.data + server_info->recv_buff.len, DNS_TCP_BUFFER - server_info->recv_buff.len, 0);
|
||||
return recv(server_info->fd, server_info->recv_buff.data + server_info->recv_buff.len,
|
||||
DNS_TCP_BUFFER - server_info->recv_buff.len, 0);
|
||||
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
|
||||
return _dns_client_socket_ssl_recv(server_info->ssl, server_info->recv_buff.data + server_info->recv_buff.len,
|
||||
DNS_TCP_BUFFER - server_info->recv_buff.len);
|
||||
@@ -1806,29 +1933,31 @@ static int _dns_client_process_tcp_buff(struct dns_server_info *server_info)
|
||||
int dns_packet_len = 0;
|
||||
struct http_head *http_head = NULL;
|
||||
unsigned char *inpacket_data = NULL;
|
||||
int ret = -1;
|
||||
|
||||
while (1) {
|
||||
if (server_info->type == DNS_SERVER_HTTPS) {
|
||||
http_head = http_head_init(4096);
|
||||
if (http_head == NULL) {
|
||||
goto errout;
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
goto errout;
|
||||
|
||||
tlog(TLOG_DEBUG, "remote server not supported.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (http_head_get_httpcode(http_head) != 200) {
|
||||
tlog(TLOG_WARN, "http server query from %s:%d failed, server return http code : %d, %s",
|
||||
server_info->ip, server_info->port,
|
||||
http_head_get_httpcode(http_head),
|
||||
http_head_get_httpcode_msg(http_head));
|
||||
goto errout;
|
||||
tlog(TLOG_WARN, "http server query from %s:%d failed, server return http code : %d, %s",
|
||||
server_info->ip, server_info->port, http_head_get_httpcode(http_head),
|
||||
http_head_get_httpcode_msg(http_head));
|
||||
goto out;
|
||||
}
|
||||
|
||||
dns_packet_len = http_head_get_data_len(http_head);
|
||||
@@ -1841,12 +1970,13 @@ static int _dns_client_process_tcp_buff(struct dns_server_info *server_info)
|
||||
len = ntohs(*((unsigned short *)(inpacket_data)));
|
||||
if (len <= 0 || len >= DNS_IN_PACKSIZE) {
|
||||
/* data len is invalid */
|
||||
goto errout;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (len > server_info->recv_buff.len - 2) {
|
||||
/* len is not expceded, wait and recv */
|
||||
break;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
inpacket_data = server_info->recv_buff.data + 2;
|
||||
@@ -1856,8 +1986,9 @@ static int _dns_client_process_tcp_buff(struct dns_server_info *server_info)
|
||||
|
||||
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 (_dns_client_recv(server_info, inpacket_data, dns_packet_len, &server_info->addr, server_info->ai_addrlen) !=
|
||||
0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (http_head) {
|
||||
@@ -1875,16 +2006,17 @@ static int _dns_client_process_tcp_buff(struct dns_server_info *server_info)
|
||||
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;
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
ret = 0;
|
||||
out:
|
||||
if (http_head) {
|
||||
http_head_destroy(http_head);
|
||||
}
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _dns_client_process_tcp(struct dns_server_info *server_info, struct epoll_event *event, unsigned long now)
|
||||
@@ -2031,15 +2163,35 @@ static int _dns_client_tls_matchName(const char *host, const char *pattern, int
|
||||
if (i == size && host[j] == '\0') {
|
||||
match = 0;
|
||||
}
|
||||
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
static int _dns_client_tls_get_cert_CN(X509 *cert, char *cn, int max_cn_len)
|
||||
{
|
||||
X509_NAME *cert_name = NULL;
|
||||
|
||||
cert_name = X509_get_subject_name(cert);
|
||||
if (cert_name == NULL) {
|
||||
tlog(TLOG_ERROR, "get subject name failed.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (X509_NAME_get_text_by_NID(cert_name, NID_commonName, cn, max_cn_len) == -1) {
|
||||
tlog(TLOG_ERROR, "cannot found x509 name");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
{
|
||||
X509 *cert = NULL;
|
||||
X509_PUBKEY *pubkey = NULL;
|
||||
X509_NAME *cert_name = NULL;
|
||||
char peer_CN[256];
|
||||
char cert_fingerprint[256];
|
||||
int i = 0;
|
||||
@@ -2060,24 +2212,29 @@ static int _dns_client_tls_verify(struct dns_server_info *server_info)
|
||||
return -1;
|
||||
}
|
||||
|
||||
cert_name = X509_get_subject_name(cert);
|
||||
if (cert_name == NULL) {
|
||||
tlog(TLOG_ERROR, "get subject name failed.");
|
||||
if (server_info->skip_check_cert == 0) {
|
||||
long res = SSL_get_verify_result(server_info->ssl);
|
||||
if (res != X509_V_OK) {
|
||||
peer_CN[0] = '\0';
|
||||
_dns_client_tls_get_cert_CN(cert, peer_CN, sizeof(peer_CN));
|
||||
tlog(TLOG_WARN, "peer server %s certificate verify failed", server_info->ip);
|
||||
tlog(TLOG_WARN, "peer CN: %s", peer_CN);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
if (_dns_client_tls_get_cert_CN(cert, peer_CN, sizeof(peer_CN)) != 0) {
|
||||
tlog(TLOG_ERROR, "get cert CN failed.");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (X509_NAME_get_text_by_NID(cert_name, NID_commonName, peer_CN, 256) == -1) {
|
||||
tlog(TLOG_ERROR, "cannot found x509 name");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
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);
|
||||
if (_dns_client_tls_matchName(tls_host_verify, peer_CN, strnlen(peer_CN, 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;
|
||||
}
|
||||
}
|
||||
@@ -2164,7 +2321,7 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
|
||||
|
||||
if (server_info->status == DNS_SERVER_STATUS_CONNECTING) {
|
||||
/* do SSL hand shake */
|
||||
ret = SSL_connect(server_info->ssl);
|
||||
ret = SSL_do_handshake(server_info->ssl);
|
||||
if (ret == 0) {
|
||||
goto errout;
|
||||
} else if (ret < 0) {
|
||||
@@ -2173,8 +2330,17 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
|
||||
if (ssl_ret == SSL_ERROR_WANT_READ) {
|
||||
fd_event.events = EPOLLIN;
|
||||
} else if (ssl_ret == SSL_ERROR_WANT_WRITE) {
|
||||
fd_event.events = EPOLLOUT;
|
||||
fd_event.events = EPOLLOUT | EPOLLIN;
|
||||
} else if (ssl_ret == SSL_ERROR_SYSCALL) {
|
||||
if (errno != ENETUNREACH) {
|
||||
tlog(TLOG_WARN, "Handshake with %s failed, %s", server_info->ip, strerror(errno));
|
||||
}
|
||||
goto errout;
|
||||
} else {
|
||||
unsigned long ssl_err = ERR_get_error();
|
||||
int ssl_reason = ERR_GET_REASON(ssl_err);
|
||||
tlog(TLOG_WARN, "Handshake with %s failed, error no: %s(%d, %d, %d)\n", server_info->ip,
|
||||
ERR_reason_error_string(ssl_err), ret, ssl_ret, ssl_reason);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -2281,7 +2447,7 @@ static int _dns_client_send_data_to_buffer(struct dns_server_info *server_info,
|
||||
event.events = EPOLLIN | EPOLLOUT;
|
||||
event.data.ptr = server_info;
|
||||
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_MOD, server_info->fd, &event) != 0) {
|
||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||
tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2354,16 +2520,17 @@ static int _dns_client_send_tls(struct dns_server_info *server_info, void *packe
|
||||
}
|
||||
|
||||
if (server_info->ssl == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
send_len = _dns_client_socket_ssl_send(server_info->ssl, inpacket, len);
|
||||
if (send_len < 0) {
|
||||
if (errno == EAGAIN || errno == EPIPE || server_info->ssl == NULL ) {
|
||||
if (send_len <= 0) {
|
||||
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) {
|
||||
SSL_set_shutdown(server_info->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
|
||||
SSL_shutdown(server_info->ssl);
|
||||
}
|
||||
return -1;
|
||||
} else if (send_len < len) {
|
||||
@@ -2404,12 +2571,13 @@ static int _dns_client_send_https(struct dns_server_info *server_info, void *pac
|
||||
}
|
||||
|
||||
if (server_info->ssl == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
send_len = _dns_client_socket_ssl_send(server_info->ssl, inpacket, http_len);
|
||||
if (send_len < 0) {
|
||||
if (errno == EAGAIN || errno == EPIPE || server_info->ssl == NULL ) {
|
||||
if (send_len <= 0) {
|
||||
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) {
|
||||
@@ -2431,61 +2599,85 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
||||
struct dns_server_group_member *tmp = NULL;
|
||||
int ret = 0;
|
||||
int send_err = 0;
|
||||
int i = 0;
|
||||
|
||||
query->send_tick = get_tick_count();
|
||||
|
||||
/* send query to all dns servers */
|
||||
pthread_mutex_lock(&client.server_list_lock);
|
||||
list_for_each_entry_safe(group_member, tmp, &query->server_group->head, list)
|
||||
{
|
||||
server_info = group_member->server;
|
||||
if (server_info->fd <= 0) {
|
||||
ret = _dns_client_create_socket(server_info);
|
||||
for (i = 0; i < 2; i++) {
|
||||
pthread_mutex_lock(&client.server_list_lock);
|
||||
list_for_each_entry_safe(group_member, tmp, &query->server_group->head, list)
|
||||
{
|
||||
server_info = group_member->server;
|
||||
if (server_info->fd <= 0) {
|
||||
ret = _dns_client_create_socket(server_info);
|
||||
if (ret != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
atomic_inc(&query->dns_request_sent);
|
||||
switch (server_info->type) {
|
||||
case DNS_SERVER_UDP:
|
||||
/* udp query */
|
||||
ret = _dns_client_send_udp(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
/* tcp query */
|
||||
ret = _dns_client_send_tcp(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
case DNS_SERVER_TLS:
|
||||
/* tls query */
|
||||
ret = _dns_client_send_tls(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
case DNS_SERVER_HTTPS:
|
||||
/* https query */
|
||||
ret = _dns_client_send_https(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
default:
|
||||
/* unsupport query type */
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
if (send_err == ENETUNREACH) {
|
||||
tlog(TLOG_DEBUG, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
|
||||
server_info->type);
|
||||
_dns_client_close_socket(server_info);
|
||||
atomic_dec(&query->dns_request_sent);
|
||||
continue;
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err),
|
||||
server_info->type);
|
||||
time_t now;
|
||||
time(&now);
|
||||
if (now - 5 > server_info->last_recv || send_err != ENOMEM) {
|
||||
_dns_client_shutdown_socket(server_info);
|
||||
}
|
||||
|
||||
atomic_dec(&query->dns_request_sent);
|
||||
continue;
|
||||
}
|
||||
time(&server_info->last_send);
|
||||
}
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
|
||||
atomic_inc(&query->dns_request_sent);
|
||||
switch (server_info->type) {
|
||||
case DNS_SERVER_UDP:
|
||||
/* udp query */
|
||||
ret = _dns_client_send_udp(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
case DNS_SERVER_TCP:
|
||||
/* tcp query */
|
||||
ret = _dns_client_send_tcp(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
case DNS_SERVER_TLS:
|
||||
/* tls query */
|
||||
ret = _dns_client_send_tls(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
case DNS_SERVER_HTTPS:
|
||||
/* https query */
|
||||
ret = _dns_client_send_https(server_info, packet, len);
|
||||
send_err = errno;
|
||||
break;
|
||||
default:
|
||||
/* unsupport query type */
|
||||
ret = -1;
|
||||
if (atomic_read(&query->dns_request_sent) > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
if (send_err != ENOMEM) {
|
||||
tlog(TLOG_ERROR, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err), server_info->type);
|
||||
} else {
|
||||
tlog(TLOG_DEBUG, "send query to %s failed, %s, type: %d", server_info->ip, strerror(send_err), server_info->type);
|
||||
}
|
||||
atomic_dec(&query->dns_request_sent);
|
||||
continue;
|
||||
}
|
||||
time(&server_info->last_send);
|
||||
}
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
|
||||
if (atomic_read(&query->dns_request_sent) <= 0) {
|
||||
tlog(TLOG_ERROR, "Send query to upstream server failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2655,22 +2847,23 @@ static void _dns_client_check_servers(void)
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
}
|
||||
|
||||
static int _dns_client_pending_server_resolve(char *domain, dns_rtcode_t rtcode, dns_type_t addr_type, char *ip, unsigned int ping_time, void *user_ptr)
|
||||
static int _dns_client_pending_server_resolve(char *domain, dns_rtcode_t rtcode, dns_type_t addr_type, char *ip,
|
||||
unsigned int ping_time, void *user_ptr)
|
||||
{
|
||||
struct dns_server_pending *pending = user_ptr;
|
||||
int ret = 0;
|
||||
|
||||
if (addr_type == DNS_T_A) {
|
||||
pending->has_v4 = 1;
|
||||
pending->ping_time_v4 = -1;
|
||||
if (rtcode == DNS_RC_NOERROR) {
|
||||
pending->has_v4 = 1;
|
||||
pending->ping_time_v4 = ping_time;
|
||||
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->has_v6 = 1;
|
||||
pending->ping_time_v6 = ping_time;
|
||||
safe_strncpy(pending->ipv6, ip, DNS_HOSTNAME_LEN);
|
||||
}
|
||||
@@ -2712,11 +2905,15 @@ static void _dns_client_add_pending_servers(void)
|
||||
if (++dely < 3) {
|
||||
return;
|
||||
}
|
||||
dely = 0;
|
||||
|
||||
pthread_mutex_lock(&pending_server_mutex);
|
||||
list_for_each_entry_safe(pending, tmp, &pending_servers, list)
|
||||
{
|
||||
/* send dns type A, AAAA query to bootstrap DNS server */
|
||||
int add_success = 0;
|
||||
char *dnsserver_ip = NULL;
|
||||
|
||||
if (pending->query_v4 == 0) {
|
||||
pending->query_v4 = 1;
|
||||
_dns_client_server_pending_get(pending);
|
||||
@@ -2728,25 +2925,40 @@ static void _dns_client_add_pending_servers(void)
|
||||
if (pending->query_v6 == 0) {
|
||||
pending->query_v6 = 1;
|
||||
_dns_client_server_pending_get(pending);
|
||||
dns_server_query(pending->host, DNS_T_AAAA, _dns_client_pending_server_resolve, pending);
|
||||
if (dns_server_query(pending->host, DNS_T_AAAA, _dns_client_pending_server_resolve, pending) != 0) {
|
||||
_dns_client_server_pending_release_lck(pending);
|
||||
}
|
||||
}
|
||||
|
||||
/* if both A, AAAA has query result, select fastest IP address */
|
||||
if (pending->has_v4 && pending->has_v6) {
|
||||
char *ip = NULL;
|
||||
if (pending->ping_time_v4 <= pending->ping_time_v6 && pending->ipv4[0]) {
|
||||
ip = pending->ipv4;
|
||||
dnsserver_ip = pending->ipv4;
|
||||
} else {
|
||||
ip = pending->ipv6;
|
||||
dnsserver_ip = pending->ipv6;
|
||||
}
|
||||
} else if (pending->has_v4) {
|
||||
dnsserver_ip = pending->ipv4;
|
||||
} else if (pending->has_v6) {
|
||||
dnsserver_ip = pending->ipv6;
|
||||
}
|
||||
|
||||
if (ip[0]) {
|
||||
if (_dns_client_add_pendings(pending, ip) != 0) {
|
||||
tlog(TLOG_WARN, "add pending DNS server %s failed.", pending->host);
|
||||
}
|
||||
if (dnsserver_ip && dnsserver_ip[0]) {
|
||||
if (_dns_client_add_pendings(pending, dnsserver_ip) == 0) {
|
||||
add_success = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pending->retry_cnt++;
|
||||
if (pending->retry_cnt >= DNS_PENDING_SERVER_RETRY || add_success) {
|
||||
if (add_success == 0) {
|
||||
tlog(TLOG_WARN, "add pending DNS server %s failed.", pending->host);
|
||||
}
|
||||
_dns_client_server_pending_release_lck(pending);
|
||||
} else {
|
||||
tlog(TLOG_DEBUG, "add pending DNS server %s failed, retry %d...", pending->host, pending->retry_cnt);
|
||||
pending->query_v4 = 0;
|
||||
pending->query_v6 = 0;
|
||||
}
|
||||
|
||||
/* if has no bootstrap DNS, just call getaddrinfo to get address */
|
||||
@@ -2757,7 +2969,7 @@ static void _dns_client_add_pending_servers(void)
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_dns_client_server_pending_release_lck(pending);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +52,9 @@ int dns_client_init(void);
|
||||
int dns_client_set_ecs(char *ip, int subnet);
|
||||
|
||||
/* query result notify function */
|
||||
typedef int (*dns_client_callback)(char *domain, dns_result_type rtype, unsigned int result_flag, struct dns_packet *packet, unsigned char *inpacket,
|
||||
int inpacket_len, void *user_ptr);
|
||||
typedef int (*dns_client_callback)(char *domain, dns_result_type rtype, unsigned int result_flag,
|
||||
struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
|
||||
void *user_ptr);
|
||||
|
||||
/* query domain */
|
||||
int dns_client_query(char *domain, int qtype, dns_client_callback callback, void *user_ptr, const char *group_name);
|
||||
@@ -69,6 +70,7 @@ struct client_dns_server_flag_tls {
|
||||
int spi_len;
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_verify[DNS_MAX_CNAME_LEN];
|
||||
char skip_check_cert;
|
||||
};
|
||||
|
||||
struct client_dns_server_flag_https {
|
||||
@@ -78,6 +80,7 @@ struct client_dns_server_flag_https {
|
||||
char httphost[DNS_MAX_CNAME_LEN];
|
||||
char path[DNS_MAX_CNAME_LEN];
|
||||
char tls_host_verify[DNS_MAX_CNAME_LEN];
|
||||
char skip_check_cert;
|
||||
};
|
||||
|
||||
struct client_dns_server_flags {
|
||||
@@ -95,7 +98,8 @@ struct client_dns_server_flags {
|
||||
int dns_client_spki_decode(const char *spki, unsigned char *spki_data_out);
|
||||
|
||||
/* add remote dns server */
|
||||
int dns_client_add_server(char *server_ip, int port, dns_server_type_t server_type, struct client_dns_server_flags *flags);
|
||||
int dns_client_add_server(char *server_ip, int port, dns_server_type_t server_type,
|
||||
struct client_dns_server_flags *flags);
|
||||
|
||||
/* remove remote dns server */
|
||||
int dns_client_remove_server(char *server_ip, int port, dns_server_type_t server_type);
|
||||
|
||||
@@ -68,6 +68,10 @@ char dns_conf_log_file[DNS_MAX_PATH];
|
||||
size_t dns_conf_log_size = 1024 * 1024;
|
||||
int dns_conf_log_num = 8;
|
||||
|
||||
/* CA file */
|
||||
char dns_conf_ca_file[DNS_MAX_PATH];
|
||||
char dns_conf_ca_path[DNS_MAX_PATH];
|
||||
|
||||
/* auditing */
|
||||
int dns_conf_audit_enable = 0;
|
||||
int dns_conf_audit_log_SOA;
|
||||
@@ -246,6 +250,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
{"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 */
|
||||
{"no-check-certificate", no_argument, NULL, 'N'}, /* do not check certificate */
|
||||
{"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 */
|
||||
@@ -257,6 +262,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip = argv[1];
|
||||
if (index >= DNS_MAX_SERVERS) {
|
||||
tlog(TLOG_WARN, "exceeds max server number, %s", ip);
|
||||
return 0;
|
||||
@@ -269,8 +275,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
server->httphost[0] = '\0';
|
||||
server->tls_host_verify[0] = '\0';
|
||||
|
||||
ip = argv[1];
|
||||
|
||||
if (type == DNS_SERVER_HTTPS) {
|
||||
if (parse_uri(ip, NULL, server->server, &port, server->path) != 0) {
|
||||
return -1;
|
||||
@@ -340,6 +344,10 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
safe_strncpy(server->tls_host_verify, optarg, DNS_MAX_CNAME_LEN);
|
||||
break;
|
||||
}
|
||||
case 'N': {
|
||||
server->skip_check_cert = 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -862,6 +870,7 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ip = argv[1];
|
||||
if (index >= DNS_MAX_SERVERS) {
|
||||
tlog(TLOG_WARN, "exceeds max server number, %s", ip);
|
||||
return 0;
|
||||
@@ -870,7 +879,6 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
|
||||
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 */
|
||||
@@ -1370,6 +1378,8 @@ static struct config_item _config_item[] = {
|
||||
CONF_CUSTOM("ignore-ip", _conf_ip_ignore, NULL),
|
||||
CONF_CUSTOM("edns-client-subnet", _conf_edns_client_subnet, NULL),
|
||||
CONF_CUSTOM("domain-rules", _conf_domain_rules, NULL),
|
||||
CONF_STRING("ca-file", (char *)&dns_conf_ca_file, DNS_MAX_PATH),
|
||||
CONF_STRING("ca-path", (char *)&dns_conf_ca_path, DNS_MAX_PATH),
|
||||
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
|
||||
CONF_END(),
|
||||
};
|
||||
|
||||
@@ -145,6 +145,7 @@ struct dns_servers {
|
||||
unsigned int server_flag;
|
||||
int ttl;
|
||||
dns_server_type_t type;
|
||||
char skip_check_cert;
|
||||
char spki[DNS_MAX_SPKI_LEN];
|
||||
char hostname[DNS_MAX_CNAME_LEN];
|
||||
char httphost[DNS_MAX_CNAME_LEN];
|
||||
@@ -211,6 +212,9 @@ extern char dns_conf_log_file[DNS_MAX_PATH];
|
||||
extern size_t dns_conf_log_size;
|
||||
extern int dns_conf_log_num;
|
||||
|
||||
extern char dns_conf_ca_file[DNS_MAX_PATH];
|
||||
extern char dns_conf_ca_path[DNS_MAX_PATH];
|
||||
|
||||
extern struct dns_domain_check_order dns_conf_check_order;
|
||||
|
||||
extern struct dns_server_groups dns_conf_server_groups[DNS_NAX_GROUP_NUMBER];
|
||||
|
||||
447
src/dns_server.c
447
src/dns_server.c
@@ -299,12 +299,15 @@ static void _dns_server_audit_log(struct dns_request *request)
|
||||
}
|
||||
|
||||
if (request->qtype == DNS_T_AAAA && request->has_ipv6) {
|
||||
snprintf(req_result, sizeof(req_result), "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->ipv6_addr[0],
|
||||
request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6],
|
||||
request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12],
|
||||
snprintf(req_result, sizeof(req_result),
|
||||
"%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->ipv6_addr[0],
|
||||
request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4],
|
||||
request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8],
|
||||
request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12],
|
||||
request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||
} else if (request->qtype == DNS_T_A && request->has_ipv4) {
|
||||
snprintf(req_result, sizeof(req_result), "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
snprintf(req_result, sizeof(req_result), "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1],
|
||||
request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
} else if (request->has_soa) {
|
||||
if (!dns_conf_audit_log_SOA) {
|
||||
return;
|
||||
@@ -317,9 +320,11 @@ static void _dns_server_audit_log(struct dns_request *request)
|
||||
gethost_by_addr(req_host, sizeof(req_host), &request->addr);
|
||||
tlog_localtime(&tm);
|
||||
|
||||
snprintf(req_time, sizeof(req_time), "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d,%.3d]", tm.year, tm.mon, tm.mday, tm.hour, tm.min, tm.sec, tm.usec / 1000);
|
||||
snprintf(req_time, sizeof(req_time), "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d,%.3d]", tm.year, tm.mon, tm.mday, tm.hour,
|
||||
tm.min, tm.sec, tm.usec / 1000);
|
||||
|
||||
tlog_printf(dns_audit, "%s %s query %s, type %d, result %s\n", req_time, req_host, request->domain, request->qtype, req_result);
|
||||
tlog_printf(dns_audit, "%s %s query %s, type %d, result %s\n", req_time, req_host, request->domain, request->qtype,
|
||||
req_result);
|
||||
}
|
||||
|
||||
static int _dns_add_rrs(struct dns_packet *packet, struct dns_request *request)
|
||||
@@ -437,7 +442,8 @@ static int _dns_server_reply_tcp_to_buffer(struct dns_server_conn_tcp_client *tc
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_reply_tcp(struct dns_request *request, struct dns_server_conn_tcp_client *tcpclient, void *packet, unsigned short len)
|
||||
static int _dns_server_reply_tcp(struct dns_request *request, struct dns_server_conn_tcp_client *tcpclient,
|
||||
void *packet, unsigned short len)
|
||||
{
|
||||
int send_len = 0;
|
||||
unsigned char inpacket_data[DNS_IN_PACKSIZE];
|
||||
@@ -465,10 +471,12 @@ static int _dns_server_reply_tcp(struct dns_request *request, struct dns_server_
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_reply_udp(struct dns_request *request, struct dns_server_conn_udp *udpserver, unsigned char *inpacket, int inpacket_len)
|
||||
static int _dns_server_reply_udp(struct dns_request *request, struct dns_server_conn_udp *udpserver,
|
||||
unsigned char *inpacket, int inpacket_len)
|
||||
{
|
||||
int send_len = 0;
|
||||
send_len = sendto(udpserver->head.fd, inpacket, inpacket_len, 0, (struct sockaddr *)&request->addr, request->addr_len);
|
||||
send_len =
|
||||
sendto(udpserver->head.fd, inpacket, inpacket_len, 0, (struct sockaddr *)&request->addr, request->addr_len);
|
||||
if (send_len != inpacket_len) {
|
||||
tlog(TLOG_ERROR, "send failed.");
|
||||
return -1;
|
||||
@@ -558,7 +566,6 @@ static int _dns_result_callback_nxdomain(struct dns_request *request)
|
||||
char ip[DNS_MAX_CNAME_LEN];
|
||||
unsigned int ping_time = -1;
|
||||
|
||||
|
||||
ip[0] = 0;
|
||||
if (request->result_callback == NULL) {
|
||||
return 0;
|
||||
@@ -586,20 +593,24 @@ static int _dns_result_callback(struct dns_request *request)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sprintf(ip, "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
sprintf(ip, "%d.%d.%d.%d", request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2],
|
||||
request->ipv4_addr[3]);
|
||||
ping_time = request->ping_ttl_v4;
|
||||
return request->result_callback(request->domain, request->rcode, request->qtype, ip, ping_time, request->user_ptr);
|
||||
return request->result_callback(request->domain, request->rcode, request->qtype, ip, ping_time,
|
||||
request->user_ptr);
|
||||
} else if (request->qtype == DNS_T_AAAA) {
|
||||
if (request->has_ipv6 == 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
sprintf(ip, "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->ipv6_addr[0], request->ipv6_addr[1],
|
||||
request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7],
|
||||
request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13],
|
||||
request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||
sprintf(ip, "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->ipv6_addr[0],
|
||||
request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4],
|
||||
request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8],
|
||||
request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11], request->ipv6_addr[12],
|
||||
request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||
ping_time = request->ping_ttl_v6;
|
||||
return request->result_callback(request->domain, request->rcode, request->qtype, ip, ping_time, request->user_ptr);
|
||||
return request->result_callback(request->domain, request->rcode, request->qtype, ip, ping_time,
|
||||
request->user_ptr);
|
||||
}
|
||||
|
||||
_dns_result_callback_nxdomain(request);
|
||||
@@ -695,8 +706,8 @@ static int _dns_server_request_complete_A(struct dns_request *request)
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
|
||||
request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0],
|
||||
request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
|
||||
request->has_soa = 0;
|
||||
if (request->has_ping_result == 0 && request->ttl_v4 > DNS_SERVER_TMOUT_TTL) {
|
||||
@@ -709,10 +720,12 @@ static int _dns_server_request_complete_A(struct dns_request *request)
|
||||
|
||||
/* if doing prefetch, update cache only */
|
||||
if (request->prefetch) {
|
||||
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
|
||||
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN,
|
||||
request->ping_ttl_v4);
|
||||
} else {
|
||||
/* insert result to cache */
|
||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
|
||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN,
|
||||
request->ping_ttl_v4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -729,10 +742,13 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
|
||||
}
|
||||
|
||||
if (request->has_ipv6) {
|
||||
tlog(TLOG_INFO, "result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode,
|
||||
request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
|
||||
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
|
||||
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||
tlog(TLOG_INFO,
|
||||
"result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
request->domain, request->rcode, request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2],
|
||||
request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6],
|
||||
request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10],
|
||||
request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14],
|
||||
request->ipv6_addr[15]);
|
||||
|
||||
if (request->has_ping_result == 0 && request->ttl_v6 > DNS_SERVER_TMOUT_TTL) {
|
||||
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
|
||||
@@ -741,10 +757,12 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
|
||||
/* if doing prefetch, update cache only */
|
||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) != 0) {
|
||||
if (request->prefetch) {
|
||||
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN, request->ping_ttl_v6);
|
||||
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr,
|
||||
DNS_RR_AAAA_LEN, request->ping_ttl_v6);
|
||||
} else {
|
||||
/* insert result to cache */
|
||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN, request->ping_ttl_v6);
|
||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr,
|
||||
DNS_RR_AAAA_LEN, request->ping_ttl_v6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -752,17 +770,20 @@ static int _dns_server_request_complete_AAAA(struct dns_request *request)
|
||||
}
|
||||
|
||||
if (request->has_ipv4 && (request->ping_ttl_v4 > 0)) {
|
||||
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
|
||||
request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0],
|
||||
request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
|
||||
/* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */
|
||||
if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) {
|
||||
if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 ||
|
||||
request->ping_ttl_v6 < 0) {
|
||||
tlog(TLOG_DEBUG, "Force IPV4 perfered.");
|
||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) != 0) {
|
||||
if (request->prefetch) {
|
||||
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
|
||||
dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr,
|
||||
DNS_RR_A_LEN, request->ping_ttl_v4);
|
||||
} else {
|
||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
|
||||
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr,
|
||||
DNS_RR_A_LEN, request->ping_ttl_v4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,6 +880,7 @@ static void _dns_server_select_possible_ipaddress(struct dns_request *request)
|
||||
|
||||
/* Return the most likely correct IP address */
|
||||
/* Returns the IP with the most hits, or the last returned record is considered to be the most likely correct. */
|
||||
pthread_mutex_lock(&request->ip_map_lock);
|
||||
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
|
||||
{
|
||||
if (addr_map->addr_type != request->qtype) {
|
||||
@@ -875,6 +897,7 @@ static void _dns_server_select_possible_ipaddress(struct dns_request *request)
|
||||
maxhit_addr_map = addr_map;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&request->ip_map_lock);
|
||||
|
||||
if (maxhit_addr_map && maxhit > 1) {
|
||||
selected_addr_map = maxhit_addr_map;
|
||||
@@ -891,16 +914,19 @@ static void _dns_server_select_possible_ipaddress(struct dns_request *request)
|
||||
case DNS_T_A: {
|
||||
memcpy(request->ipv4_addr, selected_addr_map->ipv4_addr, DNS_RR_A_LEN);
|
||||
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
|
||||
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
|
||||
request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode,
|
||||
request->ipv4_addr[0], request->ipv4_addr[1], request->ipv4_addr[2], request->ipv4_addr[3]);
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
memcpy(request->ipv6_addr, selected_addr_map->ipv6_addr, DNS_RR_AAAA_LEN);
|
||||
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
|
||||
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain,
|
||||
request->rcode, request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4],
|
||||
request->ipv6_addr[5], request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10],
|
||||
request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
|
||||
tlog(TLOG_DEBUG,
|
||||
"possible result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
request->domain, request->rcode, request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2],
|
||||
request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5], request->ipv6_addr[6],
|
||||
request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10],
|
||||
request->ipv6_addr[11], request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14],
|
||||
request->ipv6_addr[15]);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
@@ -942,11 +968,13 @@ static void _dns_server_request_release_complete(struct dns_request *request, in
|
||||
_dns_server_request_complete(request);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&request->ip_map_lock);
|
||||
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
|
||||
{
|
||||
hash_del(&addr_map->node);
|
||||
free(addr_map);
|
||||
}
|
||||
pthread_mutex_unlock(&request->ip_map_lock);
|
||||
|
||||
_dns_server_delete_request(request);
|
||||
}
|
||||
@@ -998,8 +1026,9 @@ errout:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _dns_server_ping_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 _dns_server_ping_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)
|
||||
{
|
||||
struct dns_request *request = userptr;
|
||||
int may_complete = 0;
|
||||
@@ -1181,7 +1210,8 @@ static int _dns_server_get_conf_ttl(int ttl)
|
||||
return ttl;
|
||||
}
|
||||
|
||||
static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char *addr, int addr_len, dns_type_t addr_type, int result_flag)
|
||||
static int _dns_server_ip_rule_check(struct dns_request *request, unsigned char *addr, int addr_len,
|
||||
dns_type_t addr_type, int result_flag)
|
||||
{
|
||||
prefix_t prefix;
|
||||
radix_node_t *node = NULL;
|
||||
@@ -1266,7 +1296,8 @@ static int _dns_server_is_adblock_ipv6(unsigned char addr[16])
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request *request, char *domain, unsigned int result_flag, int ping_timeout)
|
||||
static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request *request, char *domain,
|
||||
unsigned int result_flag, int ping_timeout)
|
||||
{
|
||||
int ttl;
|
||||
int ip_check_result = 0;
|
||||
@@ -1339,7 +1370,8 @@ static int _dns_server_process_answer_A(struct dns_rrs *rrs, struct dns_request
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_request *request, char *domain, unsigned int result_flag, int ping_timeout)
|
||||
static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_request *request, char *domain,
|
||||
unsigned int result_flag, int ping_timeout)
|
||||
{
|
||||
unsigned char addr[16];
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
@@ -1354,8 +1386,9 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
|
||||
_dns_server_request_get(request);
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
|
||||
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", name, ttl, addr[0], addr[1], addr[2],
|
||||
addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
name, ttl, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
|
||||
addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
|
||||
ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
|
||||
if (ip_check_result == 0) {
|
||||
@@ -1399,8 +1432,9 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6],
|
||||
addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]", addr[0], addr[1], addr[2],
|
||||
addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13],
|
||||
addr[14], addr[15]);
|
||||
|
||||
/* start ping */
|
||||
if (_dns_server_check_speed(request, ip, 0, ping_timeout) != 0) {
|
||||
@@ -1410,7 +1444,8 @@ static int _dns_server_process_answer_AAAA(struct dns_rrs *rrs, struct dns_reque
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet, unsigned int result_flag)
|
||||
static int _dns_server_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet,
|
||||
unsigned int result_flag)
|
||||
{
|
||||
int ttl;
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
@@ -1477,9 +1512,11 @@ static int _dns_server_process_answer(struct dns_request *request, char *domain,
|
||||
request->has_soa = 1;
|
||||
request->rcode = packet->head.rcode;
|
||||
dns_get_SOA(rrs, name, 128, &ttl, &request->soa);
|
||||
tlog(TLOG_DEBUG, "domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: %d, minimum: %d", domain,
|
||||
request->qtype, request->soa.mname, request->soa.rname, request->soa.serial, request->soa.refresh, request->soa.retry, request->soa.expire,
|
||||
request->soa.minimum);
|
||||
tlog(TLOG_DEBUG,
|
||||
"domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: "
|
||||
"%d, minimum: %d",
|
||||
domain, request->qtype, request->soa.mname, request->soa.rname, request->soa.serial,
|
||||
request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
|
||||
if (atomic_inc_return(&request->soa_num) >= (dns_server_num() / 2)) {
|
||||
_dns_server_request_complete(request);
|
||||
}
|
||||
@@ -1508,7 +1545,8 @@ static int dns_server_update_reply_packet_id(struct dns_request *request, unsign
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_passthrough_rule_check(struct dns_request *request, char *domain, struct dns_packet *packet, unsigned int result_flag)
|
||||
static int _dns_server_passthrough_rule_check(struct dns_request *request, char *domain, struct dns_packet *packet,
|
||||
unsigned int result_flag)
|
||||
{
|
||||
int ttl;
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
@@ -1567,8 +1605,10 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, char
|
||||
_dns_server_request_get(request);
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
|
||||
tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", name, ttl, addr[0], addr[1],
|
||||
addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
tlog(TLOG_DEBUG,
|
||||
"domain: %s TTL: %d IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
name, ttl, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8],
|
||||
addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
|
||||
ip_check_result = _dns_server_ip_rule_check(request, addr, 16, DNS_T_AAAA, result_flag);
|
||||
if (ip_check_result == 0) {
|
||||
@@ -1591,23 +1631,188 @@ static int _dns_server_passthrough_rule_check(struct dns_request *request, char
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns_packet *packet, unsigned char *inpacket, int inpacket_len)
|
||||
static int _dns_server_get_answer(struct dns_request *request, struct dns_packet *packet)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int ttl = 0;
|
||||
struct dns_rrs *rrs = NULL;
|
||||
int rr_count = 0;
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
|
||||
for (j = 1; j < DNS_RRS_END; j++) {
|
||||
rrs = dns_get_rrs_start(packet, j, &rr_count);
|
||||
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||
switch (rrs->type) {
|
||||
case DNS_T_A: {
|
||||
unsigned char addr[4];
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
|
||||
if (request->qtype != DNS_T_A) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get A result */
|
||||
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
memcpy(request->ipv4_addr, addr, DNS_RR_A_LEN);
|
||||
request->ttl_v4 = _dns_server_get_conf_ttl(ttl);
|
||||
request->has_ipv4 = 1;
|
||||
request->rcode = packet->head.rcode;
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
unsigned char addr[16];
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
|
||||
if (request->qtype != DNS_T_AAAA) {
|
||||
/* ignore non-matched query type */
|
||||
continue;
|
||||
}
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
memcpy(request->ipv6_addr, addr, DNS_RR_AAAA_LEN);
|
||||
request->ttl_v6 = _dns_server_get_conf_ttl(ttl);
|
||||
request->has_ipv6 = 1;
|
||||
request->rcode = packet->head.rcode;
|
||||
} break;
|
||||
case DNS_T_NS: {
|
||||
char cname[DNS_MAX_CNAME_LEN];
|
||||
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
|
||||
tlog(TLOG_DEBUG, "NS: %s ttl:%d cname: %s\n", name, ttl, cname);
|
||||
} break;
|
||||
case DNS_T_CNAME: {
|
||||
char cname[DNS_MAX_CNAME_LEN];
|
||||
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
|
||||
tlog(TLOG_DEBUG, "name:%s ttl: %d cname: %s\n", name, ttl, cname);
|
||||
safe_strncpy(request->cname, cname, DNS_MAX_CNAME_LEN);
|
||||
request->ttl_cname = ttl;
|
||||
request->has_cname = 1;
|
||||
} break;
|
||||
case DNS_T_SOA: {
|
||||
request->has_soa = 1;
|
||||
request->rcode = packet->head.rcode;
|
||||
dns_get_SOA(rrs, name, 128, &ttl, &request->soa);
|
||||
tlog(TLOG_DEBUG,
|
||||
"domain: %s, qtype: %d, SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: "
|
||||
"%d, minimum: %d",
|
||||
request->domain, request->qtype, request->soa.mname, request->soa.rname, request->soa.serial,
|
||||
request->soa.refresh, request->soa.retry, request->soa.expire, request->soa.minimum);
|
||||
if (atomic_inc_return(&request->soa_num) >= (dns_server_num() / 2)) {
|
||||
_dns_server_request_complete(request);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
tlog(TLOG_DEBUG, "%s, qtype: %d", name, rrs->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns_packet *packet,
|
||||
unsigned char *inpacket, int inpacket_len)
|
||||
{
|
||||
int ttl;
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
int rr_count;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
struct dns_rrs *rrs = NULL;
|
||||
struct dns_ipset_rule *ipset_rule = NULL;
|
||||
struct dns_rule_flags *rule_flags = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (atomic_inc_return(&request->notified) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (request->result_callback) {
|
||||
_dns_server_get_answer(request, packet);
|
||||
_dns_result_callback(request);
|
||||
}
|
||||
|
||||
if (request->conn == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* When passthrough, modify the id to be the id of the client request. */
|
||||
dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
|
||||
ret = _dns_reply_inpacket(request, inpacket, inpacket_len);
|
||||
|
||||
if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_IPSET) == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* check ipset rule */
|
||||
rule_flags = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
|
||||
if (rule_flags) {
|
||||
if (rule_flags->flags & DOMAIN_FLAG_IPSET_IGNORE) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ipset_rule = request->domain_rule.rules[DOMAIN_RULE_IPSET];
|
||||
if (ipset_rule == NULL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (j = 1; j < DNS_RRS_END; j++) {
|
||||
rrs = dns_get_rrs_start(packet, j, &rr_count);
|
||||
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
|
||||
switch (rrs->type) {
|
||||
case DNS_T_A: {
|
||||
unsigned char addr[4];
|
||||
if (request->qtype != DNS_T_A) {
|
||||
/* ignore non-matched query type */
|
||||
if (request->dualstack_selection == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* get A result */
|
||||
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
|
||||
/* add IPV4 to ipset */
|
||||
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
|
||||
|
||||
tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %d.%d.%d.%d",
|
||||
request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3]);
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
unsigned char addr[16];
|
||||
if (request->qtype != DNS_T_AAAA) {
|
||||
/* ignore non-matched query type */
|
||||
break;
|
||||
}
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
|
||||
/* add IPV6 to ipset */
|
||||
if (request->has_ipv6) {
|
||||
if (request->has_ipv4) {
|
||||
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
|
||||
}
|
||||
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_AAAA_LEN, request->ttl_v6 * 2);
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
|
||||
request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8],
|
||||
addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsigned int result_flag, struct dns_packet *packet, unsigned char *inpacket,
|
||||
int inpacket_len, void *user_ptr)
|
||||
static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsigned int result_flag,
|
||||
struct dns_packet *packet, unsigned char *inpacket, int inpacket_len,
|
||||
void *user_ptr)
|
||||
{
|
||||
struct dns_request *request = user_ptr;
|
||||
int ip_num = 0;
|
||||
@@ -1627,7 +1832,6 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, unsi
|
||||
|
||||
return _dns_server_reply_passthrouth(request, packet, inpacket, inpacket_len);
|
||||
}
|
||||
|
||||
_dns_server_process_answer(request, domain, packet, result_flag);
|
||||
return 0;
|
||||
} else if (rtype == DNS_QUERY_ERR) {
|
||||
@@ -1679,23 +1883,28 @@ static int _dns_server_process_ptr(struct dns_request *request)
|
||||
struct sockaddr_in *addr_in;
|
||||
addr_in = (struct sockaddr_in *)ifa->ifa_addr;
|
||||
addr = (unsigned char *)&(addr_in->sin_addr.s_addr);
|
||||
snprintf(reverse_addr, sizeof(reverse_addr), "%d.%d.%d.%d.in-addr.arpa", addr[3], addr[2], addr[1], addr[0]);
|
||||
snprintf(reverse_addr, sizeof(reverse_addr), "%d.%d.%d.%d.in-addr.arpa", addr[3], addr[2], addr[1],
|
||||
addr[0]);
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6;
|
||||
addr_in6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||
addr = addr_in6->sin6_addr.s6_addr + 12;
|
||||
snprintf(reverse_addr, sizeof(reverse_addr), "%d.%d.%d.%d.in-addr.arpa", addr[3], addr[2], addr[1], addr[0]);
|
||||
snprintf(reverse_addr, sizeof(reverse_addr), "%d.%d.%d.%d.in-addr.arpa", addr[3], addr[2], addr[1],
|
||||
addr[0]);
|
||||
} else {
|
||||
addr = addr_in6->sin6_addr.s6_addr;
|
||||
snprintf(reverse_addr, sizeof(reverse_addr),
|
||||
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", addr[15] & 0xF,
|
||||
(addr[15] >> 4) & 0xF, addr[14] & 0xF, (addr[14] >> 4) & 0xF, addr[13] & 0xF, (addr[13] >> 4) & 0xF, addr[12] & 0xF,
|
||||
(addr[12] >> 4) & 0xF, addr[11] & 0xF, (addr[11] >> 4) & 0xF, addr[10] & 0xF, (addr[10] >> 4) & 0xF, addr[9] & 0xF,
|
||||
(addr[9] >> 4) & 0xF, addr[8] & 0xF, (addr[8] >> 4) & 0xF, addr[7] & 0xF, (addr[7] >> 4) & 0xF, addr[6] & 0xF, (addr[6] >> 4) & 0xF,
|
||||
addr[5] & 0xF, (addr[5] >> 4) & 0xF, addr[4] & 0xF, (addr[4] >> 4) & 0xF, addr[3] & 0xF, (addr[3] >> 4) & 0xF, addr[2] & 0xF,
|
||||
(addr[2] >> 4) & 0xF, addr[1] & 0xF, (addr[1] >> 4) & 0xF, addr[0] & 0xF, (addr[0] >> 4) & 0xF);
|
||||
"%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
|
||||
"%x.ip6.arpa",
|
||||
addr[15] & 0xF, (addr[15] >> 4) & 0xF, addr[14] & 0xF, (addr[14] >> 4) & 0xF, addr[13] & 0xF,
|
||||
(addr[13] >> 4) & 0xF, addr[12] & 0xF, (addr[12] >> 4) & 0xF, addr[11] & 0xF,
|
||||
(addr[11] >> 4) & 0xF, addr[10] & 0xF, (addr[10] >> 4) & 0xF, addr[9] & 0xF,
|
||||
(addr[9] >> 4) & 0xF, addr[8] & 0xF, (addr[8] >> 4) & 0xF, addr[7] & 0xF, (addr[7] >> 4) & 0xF,
|
||||
addr[6] & 0xF, (addr[6] >> 4) & 0xF, addr[5] & 0xF, (addr[5] >> 4) & 0xF, addr[4] & 0xF,
|
||||
(addr[4] >> 4) & 0xF, addr[3] & 0xF, (addr[3] >> 4) & 0xF, addr[2] & 0xF, (addr[2] >> 4) & 0xF,
|
||||
addr[1] & 0xF, (addr[1] >> 4) & 0xF, addr[0] & 0xF, (addr[0] >> 4) & 0xF);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
@@ -1736,7 +1945,8 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _dns_server_log_rule(const char *domain, enum domain_rule rule_type, unsigned char *rule_key, int rule_key_len)
|
||||
static void _dns_server_log_rule(const char *domain, enum domain_rule rule_type, unsigned char *rule_key,
|
||||
int rule_key_len)
|
||||
{
|
||||
char rule_name[DNS_MAX_CNAME_LEN];
|
||||
|
||||
@@ -1751,8 +1961,7 @@ static void _dns_server_log_rule(const char *domain, enum domain_rule rule_type,
|
||||
|
||||
static void _dns_server_update_rule_by_flags(struct dns_request *request)
|
||||
{
|
||||
struct dns_rule_flags *rule_flag =
|
||||
(struct dns_rule_flags *)request->domain_rule.rules[0];
|
||||
struct dns_rule_flags *rule_flag = (struct dns_rule_flags *)request->domain_rule.rules[0];
|
||||
unsigned int flags = 0;
|
||||
|
||||
if (rule_flag == NULL) {
|
||||
@@ -1828,7 +2037,8 @@ void _dns_server_get_domain_rule(struct dns_request *request)
|
||||
domain_key[domain_len] = 0;
|
||||
|
||||
/* find domain rule */
|
||||
art_substring_walk(&dns_conf_domain_rule, (unsigned char *)domain_key, domain_len, _dns_server_get_rules, &walk_args);
|
||||
art_substring_walk(&dns_conf_domain_rule, (unsigned char *)domain_key, domain_len, _dns_server_get_rules,
|
||||
&walk_args);
|
||||
if (likely(dns_conf_log_level > TLOG_DEBUG)) {
|
||||
return;
|
||||
}
|
||||
@@ -1961,7 +2171,7 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _dns_server_prolcess_speed_check_rule(struct dns_request *request)
|
||||
static void _dns_server_process_speed_check_rule(struct dns_request *request)
|
||||
{
|
||||
struct dns_domain_check_order *check_order = NULL;
|
||||
|
||||
@@ -1978,9 +2188,10 @@ static int _dns_server_process_cache(struct dns_request *request)
|
||||
{
|
||||
struct dns_cache *dns_cache = NULL;
|
||||
struct dns_cache *dns_cache_A = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_CACHE) == 0) {
|
||||
goto errout;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dns_cache = dns_cache_lookup(request->domain, request->qtype);
|
||||
@@ -1989,26 +2200,28 @@ static int _dns_server_process_cache(struct dns_request *request)
|
||||
dns_cache_A = dns_cache_lookup(request->domain, DNS_T_A);
|
||||
if (dns_cache_A) {
|
||||
tlog(TLOG_DEBUG, "No IPV6 Found, Force IPV4 perfered.");
|
||||
dns_cache_release(dns_cache_A);
|
||||
dns_cache_release(dns_cache);
|
||||
return _dns_server_reply_SOA(DNS_RC_NOERROR, request);
|
||||
if (dns_cache_get_ttl(dns_cache_A) == 0) {
|
||||
_dns_server_prefetch_request(request->domain, request->qtype);
|
||||
}
|
||||
ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
goto errout;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (request->qtype != dns_cache->qtype) {
|
||||
goto errout;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (request->dualstack_selection && request->qtype == DNS_T_AAAA) {
|
||||
dns_cache_A = dns_cache_lookup(request->domain, DNS_T_A);
|
||||
if (dns_cache_A && (dns_cache_A->speed > 0)) {
|
||||
if ((dns_cache_A->speed + (dns_conf_dualstack_ip_selection_threshold * 10)) < dns_cache->speed || dns_cache->speed < 0) {
|
||||
if ((dns_cache_A->speed + (dns_conf_dualstack_ip_selection_threshold * 10)) < dns_cache->speed ||
|
||||
dns_cache->speed < 0) {
|
||||
tlog(TLOG_DEBUG, "Force IPV4 perfered.");
|
||||
dns_cache_release(dns_cache_A);
|
||||
dns_cache_release(dns_cache);
|
||||
return _dns_server_reply_SOA(DNS_RC_NOERROR, request);
|
||||
ret = _dns_server_reply_SOA(DNS_RC_NOERROR, request);
|
||||
goto out_update_cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2026,7 +2239,7 @@ static int _dns_server_process_cache(struct dns_request *request)
|
||||
request->has_ipv6 = 1;
|
||||
break;
|
||||
default:
|
||||
goto errout;
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2044,28 +2257,26 @@ static int _dns_server_process_cache(struct dns_request *request)
|
||||
_dns_reply(request);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out_update_cache:
|
||||
if (dns_cache_get_ttl(dns_cache) == 0) {
|
||||
_dns_server_prefetch_request(request->domain, request->qtype);
|
||||
} else {
|
||||
dns_cache_update(dns_cache);
|
||||
}
|
||||
dns_cache_release(dns_cache);
|
||||
|
||||
if (dns_cache_A) {
|
||||
dns_cache_release(dns_cache_A);
|
||||
dns_cache_A = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
out:
|
||||
if (dns_cache) {
|
||||
dns_cache_release(dns_cache);
|
||||
}
|
||||
|
||||
if (dns_cache_A) {
|
||||
dns_cache_release(dns_cache_A);
|
||||
dns_cache_A = NULL;
|
||||
}
|
||||
return -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _dns_server_request_set_client(struct dns_request *request, struct dns_server_conn_head *conn)
|
||||
@@ -2084,7 +2295,8 @@ static void _dns_server_request_set_enable_prefetch(struct dns_request *request)
|
||||
request->prefetch = 1;
|
||||
}
|
||||
|
||||
static int _dns_server_request_set_client_addr(struct dns_request *request, struct sockaddr_storage *from, socklen_t from_len)
|
||||
static int _dns_server_request_set_client_addr(struct dns_request *request, struct sockaddr_storage *from,
|
||||
socklen_t from_len)
|
||||
{
|
||||
switch (from->ss_family) {
|
||||
case AF_INET:
|
||||
@@ -2207,7 +2419,7 @@ static int _dns_server_do_query(struct dns_request *request, const char *domain,
|
||||
}
|
||||
|
||||
/* process speed check rule */
|
||||
_dns_server_prolcess_speed_check_rule(request);
|
||||
_dns_server_process_speed_check_rule(request);
|
||||
|
||||
/* check and set passthrough */
|
||||
_dns_server_check_set_passthrough(request);
|
||||
@@ -2255,8 +2467,9 @@ errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *local, socklen_t local_len,
|
||||
struct sockaddr_storage *from, socklen_t from_len)
|
||||
static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *inpacket, int inpacket_len,
|
||||
struct sockaddr_storage *local, socklen_t local_len, struct sockaddr_storage *from,
|
||||
socklen_t from_len)
|
||||
{
|
||||
int decode_len;
|
||||
int ret = -1;
|
||||
@@ -2272,16 +2485,19 @@ static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *in
|
||||
int qtype = DNS_T_ALL;
|
||||
|
||||
/* decode packet */
|
||||
tlog(TLOG_DEBUG, "recv query packet from %s, len = %d", gethost_by_addr(name, sizeof(name), (struct sockaddr *)from), inpacket_len);
|
||||
tlog(TLOG_DEBUG, "recv query packet from %s, len = %d",
|
||||
gethost_by_addr(name, sizeof(name), (struct sockaddr *)from), inpacket_len);
|
||||
decode_len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
|
||||
if (decode_len < 0) {
|
||||
tlog(TLOG_DEBUG, "decode failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "request qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, tc = %d, rd = %d, ra = %d, rcode = %d\n",
|
||||
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len, packet->head.id, packet->head.tc,
|
||||
packet->head.rd, packet->head.ra, packet->head.rcode);
|
||||
tlog(TLOG_DEBUG,
|
||||
"request qdcount = %d, ancount = %d, nscount = %d, nrcount = %d, len = %d, id = %d, tc = %d, rd = %d, ra = "
|
||||
"%d, rcode = %d\n",
|
||||
packet->head.qdcount, packet->head.ancount, packet->head.nscount, packet->head.nrcount, inpacket_len,
|
||||
packet->head.id, packet->head.tc, packet->head.rd, packet->head.ra, packet->head.rcode);
|
||||
|
||||
if (packet->head.qr != DNS_QR_QUERY) {
|
||||
goto errout;
|
||||
@@ -2381,6 +2597,7 @@ int dns_server_query(char *domain, int qtype, dns_result_callback callback, void
|
||||
return ret;
|
||||
errout:
|
||||
if (request) {
|
||||
_dns_server_request_set_callback(request, NULL, NULL);
|
||||
_dns_server_request_release(request);
|
||||
}
|
||||
|
||||
@@ -2452,7 +2669,8 @@ static int _dns_server_client_close(struct dns_server_conn_head *conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_tcp_accept(struct dns_server_conn_tcp_server *tcpserver, struct epoll_event *event, unsigned long now)
|
||||
static int _dns_server_tcp_accept(struct dns_server_conn_tcp_server *tcpserver, struct epoll_event *event,
|
||||
unsigned long now)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
struct dns_server_conn_tcp_client *tcpclient = NULL;
|
||||
@@ -2516,7 +2734,8 @@ static int _dns_server_tcp_recv(struct dns_server_conn_tcp_client *tcpclient)
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = recv(tcpclient->head.fd, tcpclient->recvbuff.buf + tcpclient->recvbuff.size, sizeof(tcpclient->recvbuff.buf) - tcpclient->recvbuff.size, 0);
|
||||
len = recv(tcpclient->head.fd, tcpclient->recvbuff.buf + tcpclient->recvbuff.size,
|
||||
sizeof(tcpclient->recvbuff.buf) - tcpclient->recvbuff.size, 0);
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
return RECV_ERROR_AGAIN;
|
||||
@@ -2566,8 +2785,8 @@ static int _dns_server_tcp_process_one_request(struct dns_server_conn_tcp_client
|
||||
request_data = (unsigned char *)(tcpclient->recvbuff.buf + proceed_len + sizeof(unsigned short));
|
||||
|
||||
/* process one record */
|
||||
if (_dns_server_recv(&tcpclient->head, request_data, request_len, &tcpclient->localaddr, tcpclient->localaddr_len, &tcpclient->addr,
|
||||
tcpclient->addr_len) != 0) {
|
||||
if (_dns_server_recv(&tcpclient->head, request_data, request_len, &tcpclient->localaddr,
|
||||
tcpclient->localaddr_len, &tcpclient->addr, tcpclient->addr_len) != 0) {
|
||||
tlog(TLOG_ERROR, "process tcp request failed.");
|
||||
return RECV_ERROR_FAIL;
|
||||
}
|
||||
@@ -2650,7 +2869,8 @@ static int _dns_server_tcp_send(struct dns_server_conn_tcp_client *tcpclient)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_server_process_tcp(struct dns_server_conn_tcp_client *dnsserver, struct epoll_event *event, unsigned long now)
|
||||
static int _dns_server_process_tcp(struct dns_server_conn_tcp_client *dnsserver, struct epoll_event *event,
|
||||
unsigned long now)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -2724,16 +2944,18 @@ static void _dns_server_second_ping_check(struct dns_request *request)
|
||||
switch (addr_map->addr_type) {
|
||||
case DNS_T_A: {
|
||||
_dns_server_request_get(request);
|
||||
sprintf(ip, "%d.%d.%d.%d", addr_map->ipv4_addr[0], addr_map->ipv4_addr[1], addr_map->ipv4_addr[2], addr_map->ipv4_addr[3]);
|
||||
sprintf(ip, "%d.%d.%d.%d", addr_map->ipv4_addr[0], addr_map->ipv4_addr[1], addr_map->ipv4_addr[2],
|
||||
addr_map->ipv4_addr[3]);
|
||||
if (_dns_server_check_speed(request, ip, 1, DNS_PING_SECOND_TIMEOUT) != 0) {
|
||||
_dns_server_request_release(request);
|
||||
}
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
_dns_server_request_get(request);
|
||||
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]", addr_map->ipv6_addr[0], addr_map->ipv6_addr[1],
|
||||
addr_map->ipv6_addr[2], addr_map->ipv6_addr[3], addr_map->ipv6_addr[4], addr_map->ipv6_addr[5], addr_map->ipv6_addr[6],
|
||||
addr_map->ipv6_addr[7], addr_map->ipv6_addr[8], addr_map->ipv6_addr[9], addr_map->ipv6_addr[10], addr_map->ipv6_addr[11],
|
||||
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]",
|
||||
addr_map->ipv6_addr[0], addr_map->ipv6_addr[1], addr_map->ipv6_addr[2], addr_map->ipv6_addr[3],
|
||||
addr_map->ipv6_addr[4], addr_map->ipv6_addr[5], addr_map->ipv6_addr[6], addr_map->ipv6_addr[7],
|
||||
addr_map->ipv6_addr[8], addr_map->ipv6_addr[9], addr_map->ipv6_addr[10], addr_map->ipv6_addr[11],
|
||||
addr_map->ipv6_addr[12], addr_map->ipv6_addr[13], addr_map->ipv6_addr[14], addr_map->ipv6_addr[15]);
|
||||
|
||||
if (_dns_server_check_speed(request, ip, 1, DNS_PING_SECOND_TIMEOUT) != 0) {
|
||||
@@ -2758,7 +2980,8 @@ static void _dns_server_prefetch_domain(struct dns_cache *dns_cache)
|
||||
}
|
||||
|
||||
/* start prefetch domain */
|
||||
tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->domain, dns_cache->qtype, dns_cache->ttl, hitnum);
|
||||
tlog(TLOG_DEBUG, "prefetch by cache %s, qtype %d, ttl %d, hitnum %d", dns_cache->domain, dns_cache->qtype,
|
||||
dns_cache->ttl, hitnum);
|
||||
if (_dns_server_prefetch_request(dns_cache->domain, dns_cache->qtype) != 0) {
|
||||
tlog(TLOG_ERROR, "prefetch domain %s, qtype %d, failed.", dns_cache->domain, dns_cache->qtype);
|
||||
}
|
||||
@@ -2990,7 +3213,8 @@ static int _dns_create_socket(const char *host_ip, int type)
|
||||
|
||||
fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol);
|
||||
if (fd < 0) {
|
||||
tlog(TLOG_ERROR, "create socket failed, family = %d, type = %d, proto = %d, %s\n", gai->ai_family, gai->ai_socktype, gai->ai_protocol, strerror(errno));
|
||||
tlog(TLOG_ERROR, "create socket failed, family = %d, type = %d, proto = %d, %s\n", gai->ai_family,
|
||||
gai->ai_socktype, gai->ai_protocol, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -3008,7 +3232,7 @@ static int _dns_create_socket(const char *host_ip, int type)
|
||||
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
|
||||
|
||||
if (bind(fd, gai->ai_addr, gai->ai_addrlen) != 0) {
|
||||
tlog(TLOG_ERROR, "bind service failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "bind service %s failed, %s\n", host_ip, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -3255,4 +3479,3 @@ void dns_server_exit(void)
|
||||
|
||||
dns_cache_destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ void dns_server_stop(void);
|
||||
void dns_server_exit(void);
|
||||
|
||||
/* query result notify function */
|
||||
typedef int (*dns_result_callback)(char *domain, dns_rtcode_t rtcode, dns_type_t addr_type, char *ip, unsigned int ping_time, void *user_ptr);
|
||||
typedef int (*dns_result_callback)(char *domain, dns_rtcode_t rtcode, dns_type_t addr_type, char *ip,
|
||||
unsigned int ping_time, void *user_ptr);
|
||||
|
||||
/* query domain */
|
||||
int dns_server_query(char *domain, int qtype, dns_result_callback callback, void *user_ptr);
|
||||
|
||||
104
src/fast_ping.c
104
src/fast_ping.c
@@ -219,7 +219,8 @@ 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)
|
||||
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;
|
||||
@@ -379,8 +380,8 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host)
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len, ping_host->seq, ping_host->ttl, &tv,
|
||||
ping_host->userptr);
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len,
|
||||
ping_host->seq, ping_host->ttl, &tv, ping_host->userptr);
|
||||
}
|
||||
|
||||
tlog(TLOG_DEBUG, "ping end, id %d", ping_host->sid);
|
||||
@@ -407,8 +408,8 @@ static void _fast_ping_host_remove(struct ping_host_struct *ping_host)
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len, ping_host->seq, ping_host->ttl, &tv,
|
||||
ping_host->userptr);
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len,
|
||||
ping_host->seq, ping_host->ttl, &tv, ping_host->userptr);
|
||||
}
|
||||
|
||||
_fast_ping_host_put(ping_host);
|
||||
@@ -435,7 +436,8 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
|
||||
packet->msg.seq = ping_host->seq;
|
||||
icmp6->icmp6_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
|
||||
|
||||
len = sendto(ping.fd_icmp6, &ping_host->packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
||||
len = sendto(ping.fd_icmp6, &ping_host->packet, sizeof(struct fast_ping_packet), 0,
|
||||
(struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
||||
if (len < 0 || len != sizeof(struct fast_ping_packet)) {
|
||||
int err = errno;
|
||||
if (errno == ENETUNREACH || errno == EINVAL) {
|
||||
@@ -450,8 +452,9 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
|
||||
}
|
||||
|
||||
char ping_host_name[PING_MAX_HOSTLEN];
|
||||
tlog(TLOG_ERROR, "sendto %s, id %d, %s", gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr), ping_host->sid,
|
||||
strerror(err));
|
||||
tlog(TLOG_ERROR, "sendto %s, id %d, %s",
|
||||
gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr),
|
||||
ping_host->sid, strerror(err));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -482,15 +485,17 @@ static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host)
|
||||
packet->msg.cookie = ping_host->cookie;
|
||||
icmp->icmp_cksum = _fast_ping_checksum((void *)packet, sizeof(struct fast_ping_packet));
|
||||
|
||||
len = sendto(ping.fd_icmp, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
||||
len = sendto(ping.fd_icmp, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr,
|
||||
ping_host->addr_len);
|
||||
if (len < 0 || len != sizeof(struct fast_ping_packet)) {
|
||||
int err = errno;
|
||||
if (errno == ENETUNREACH || errno == EINVAL) {
|
||||
goto errout;
|
||||
}
|
||||
char ping_host_name[PING_MAX_HOSTLEN];
|
||||
tlog(TLOG_ERROR, "sendto %s, id %d, %s", gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr), ping_host->sid,
|
||||
strerror(err));
|
||||
tlog(TLOG_ERROR, "sendto %s, id %d, %s",
|
||||
gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr),
|
||||
ping_host->sid, strerror(err));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -535,8 +540,9 @@ static int _fast_ping_sendping_udp(struct ping_host_struct *ping_host)
|
||||
goto errout;
|
||||
}
|
||||
char ping_host_name[PING_MAX_HOSTLEN];
|
||||
tlog(TLOG_ERROR, "sendto %s, id %d, %s", gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr), ping_host->sid,
|
||||
strerror(err));
|
||||
tlog(TLOG_ERROR, "sendto %s, id %d, %s",
|
||||
gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr),
|
||||
ping_host->sid, strerror(err));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -567,6 +573,11 @@ static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
|
||||
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));
|
||||
set_sock_keepalive(fd, 0, 0, 0);
|
||||
/* Set the socket lingering so we will RST connections instead of wasting
|
||||
* bandwidth with the four-step close
|
||||
*/
|
||||
set_sock_lingertime(fd, 0);
|
||||
|
||||
ping_host->seq++;
|
||||
if (connect(fd, (struct sockaddr *)&ping_host->addr, ping_host->addr_len) != 0) {
|
||||
@@ -583,7 +594,8 @@ static int _fast_ping_sendping_tcp(struct ping_host_struct *ping_host)
|
||||
bool_print_log = 0;
|
||||
}
|
||||
|
||||
tlog(TLOG_ERROR, "connect %s, id %d, %s", gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr),
|
||||
tlog(TLOG_ERROR, "connect %s, id %d, %s",
|
||||
gethost_by_addr(ping_host_name, sizeof(ping_host_name), (struct sockaddr *)&ping_host->addr),
|
||||
ping_host->sid, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
@@ -671,8 +683,8 @@ static int _fast_ping_create_icmp_sock(FAST_PING_TYPE type)
|
||||
}
|
||||
|
||||
struct icmp_filter filt;
|
||||
filt.data = ~((1 << ICMP_SOURCE_QUENCH) | (1 << ICMP_DEST_UNREACH) | (1 << ICMP_TIME_EXCEEDED) | (1 << ICMP_PARAMETERPROB) | (1 << ICMP_REDIRECT) |
|
||||
(1 << ICMP_ECHOREPLY));
|
||||
filt.data = ~((1 << ICMP_SOURCE_QUENCH) | (1 << ICMP_DEST_UNREACH) | (1 << ICMP_TIME_EXCEEDED) |
|
||||
(1 << ICMP_PARAMETERPROB) | (1 << ICMP_REDIRECT) | (1 << ICMP_ECHOREPLY));
|
||||
setsockopt(fd, SOL_RAW, ICMP_FILTER, &filt, sizeof filt);
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&buffsize, optlen);
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&buffsize, optlen);
|
||||
@@ -829,8 +841,9 @@ 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;
|
||||
@@ -842,7 +855,8 @@ 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)
|
||||
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;
|
||||
@@ -891,7 +905,8 @@ errout:
|
||||
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)
|
||||
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;
|
||||
@@ -926,7 +941,8 @@ errout:
|
||||
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)
|
||||
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;
|
||||
@@ -982,7 +998,8 @@ errout:
|
||||
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)
|
||||
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:
|
||||
@@ -1001,14 +1018,15 @@ static int _fast_ping_get_addr_by_type(PING_TYPE type, const char *ip_str, int p
|
||||
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 *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;
|
||||
uint32_t addrkey;
|
||||
char ip_str[PING_MAX_HOSTLEN];
|
||||
int port = -1;
|
||||
FAST_PING_TYPE ping_type;
|
||||
FAST_PING_TYPE ping_type = FAST_PING_END;
|
||||
unsigned int seed;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1106,7 +1124,8 @@ static void tv_sub(struct timeval *out, struct timeval *in)
|
||||
out->tv_sec -= in->tv_sec;
|
||||
}
|
||||
|
||||
static struct fast_ping_packet *_fast_ping_icmp6_packet(struct ping_host_struct *ping_host, struct msghdr *msg, u_char *packet_data, int data_len)
|
||||
static struct fast_ping_packet *_fast_ping_icmp6_packet(struct ping_host_struct *ping_host, struct msghdr *msg,
|
||||
u_char *packet_data, int data_len)
|
||||
{
|
||||
int icmp_len;
|
||||
struct fast_ping_packet *packet = (struct fast_ping_packet *)packet_data;
|
||||
@@ -1148,7 +1167,8 @@ static struct fast_ping_packet *_fast_ping_icmp6_packet(struct ping_host_struct
|
||||
return packet;
|
||||
}
|
||||
|
||||
static struct fast_ping_packet *_fast_ping_icmp_packet(struct ping_host_struct *ping_host, struct msghdr *msg, u_char *packet_data, int data_len)
|
||||
static struct fast_ping_packet *_fast_ping_icmp_packet(struct ping_host_struct *ping_host, struct msghdr *msg,
|
||||
u_char *packet_data, int data_len)
|
||||
{
|
||||
struct ip *ip = (struct ip *)packet_data;
|
||||
struct fast_ping_packet *packet;
|
||||
@@ -1185,8 +1205,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;
|
||||
|
||||
@@ -1248,7 +1268,8 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
packet = _fast_ping_recv_packet(ping_host, &msg, inpacket, len, now);
|
||||
if (packet == NULL) {
|
||||
char name[PING_MAX_HOSTLEN];
|
||||
tlog(TLOG_DEBUG, "recv ping packet from %s failed.", gethost_by_addr(name, sizeof(name), (struct sockaddr *)&from));
|
||||
tlog(TLOG_DEBUG, "recv ping packet from %s failed.",
|
||||
gethost_by_addr(name, sizeof(name), (struct sockaddr *)&from));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -1260,7 +1281,8 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
|
||||
{
|
||||
if (_fast_ping_sockaddr_ip_cmp(&recv_ping_host->addr, recv_ping_host->addr_len, (struct sockaddr *)&from, from_len) == 0 &&
|
||||
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;
|
||||
@@ -1282,8 +1304,9 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
recv_ping_host->ttl = packet->ttl;
|
||||
tv_sub(&tvresult, tvsend);
|
||||
if (recv_ping_host->ping_callback) {
|
||||
recv_ping_host->ping_callback(recv_ping_host, recv_ping_host->host, PING_RESULT_RESPONSE, &recv_ping_host->addr, recv_ping_host->addr_len,
|
||||
recv_ping_host->seq, recv_ping_host->ttl, &tvresult, recv_ping_host->userptr);
|
||||
recv_ping_host->ping_callback(recv_ping_host, recv_ping_host->host, PING_RESULT_RESPONSE, &recv_ping_host->addr,
|
||||
recv_ping_host->addr_len, recv_ping_host->seq, recv_ping_host->ttl, &tvresult,
|
||||
recv_ping_host->userptr);
|
||||
}
|
||||
|
||||
recv_ping_host->send = 0;
|
||||
@@ -1316,8 +1339,8 @@ static int _fast_ping_process_tcp(struct ping_host_struct *ping_host, struct epo
|
||||
}
|
||||
tv_sub(&tvresult, tvsend);
|
||||
if (ping_host->ping_callback) {
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr, ping_host->addr_len, ping_host->seq, ping_host->ttl,
|
||||
&tvresult, ping_host->userptr);
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_RESPONSE, &ping_host->addr,
|
||||
ping_host->addr_len, ping_host->seq, ping_host->ttl, &tvresult, ping_host->userptr);
|
||||
}
|
||||
|
||||
ping_host->send = 0;
|
||||
@@ -1393,7 +1416,8 @@ static int _fast_ping_process_udp(struct ping_host_struct *ping_host, struct tim
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
hash_for_each_possible(ping.addrmap, recv_ping_host, addr_node, addrkey)
|
||||
{
|
||||
if (_fast_ping_sockaddr_ip_cmp(&recv_ping_host->addr, recv_ping_host->addr_len, (struct sockaddr *)&from, from_len) == 0 &&
|
||||
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;
|
||||
@@ -1410,8 +1434,9 @@ static int _fast_ping_process_udp(struct ping_host_struct *ping_host, struct tim
|
||||
tvsend = &recv_ping_host->last;
|
||||
tv_sub(&tvresult, tvsend);
|
||||
if (recv_ping_host->ping_callback) {
|
||||
recv_ping_host->ping_callback(recv_ping_host, recv_ping_host->host, PING_RESULT_RESPONSE, &recv_ping_host->addr, recv_ping_host->addr_len,
|
||||
recv_ping_host->seq, recv_ping_host->ttl, &tvresult, recv_ping_host->userptr);
|
||||
recv_ping_host->ping_callback(recv_ping_host, recv_ping_host->host, PING_RESULT_RESPONSE, &recv_ping_host->addr,
|
||||
recv_ping_host->addr_len, recv_ping_host->seq, recv_ping_host->ttl, &tvresult,
|
||||
recv_ping_host->userptr);
|
||||
}
|
||||
|
||||
recv_ping_host->send = 0;
|
||||
@@ -1518,8 +1543,9 @@ static void _fast_ping_period_run(void)
|
||||
tv_sub(&interval, &ping_host->last);
|
||||
millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000;
|
||||
if (millisecond >= ping_host->timeout && ping_host->send == 1) {
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_TIMEOUT, &ping_host->addr, ping_host->addr_len, ping_host->seq, ping_host->ttl,
|
||||
&interval, ping_host->userptr);
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_TIMEOUT, &ping_host->addr,
|
||||
ping_host->addr_len, ping_host->seq, ping_host->ttl, &interval,
|
||||
ping_host->userptr);
|
||||
ping_host->send = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,13 @@ typedef enum {
|
||||
} FAST_PING_RESULT;
|
||||
|
||||
struct ping_host_struct;
|
||||
typedef void (*fast_ping_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);
|
||||
typedef void (*fast_ping_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);
|
||||
|
||||
/* start ping */
|
||||
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 *fast_ping_start(PING_TYPE type, const char *host, int count, int interval, int timeout,
|
||||
fast_ping_result ping_callback, void *userptr);
|
||||
|
||||
/* stop ping */
|
||||
int fast_ping_stop(struct ping_host_struct *ping_host);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "http_parse.h"
|
||||
#include "hash.h"
|
||||
#include "hashtable.h"
|
||||
#include "util.h"
|
||||
#include "jhash.h"
|
||||
#include "list.h"
|
||||
#include <stdlib.h>
|
||||
@@ -214,7 +215,7 @@ static int _http_head_parse_response(struct http_head *http_head, char *key, cha
|
||||
{
|
||||
char *field_start = NULL;
|
||||
char *tmp_ptr = NULL;
|
||||
char *result = NULL;
|
||||
char *ret_msg = NULL;
|
||||
char *ret_code = NULL;
|
||||
|
||||
if (strstr(key, "HTTP/") == NULL) {
|
||||
@@ -226,29 +227,27 @@ static int _http_head_parse_response(struct http_head *http_head, char *key, cha
|
||||
field_start = tmp_ptr;
|
||||
}
|
||||
|
||||
if (*tmp_ptr == ' ') {
|
||||
*tmp_ptr = '\0';
|
||||
if (ret_code == NULL) {
|
||||
ret_code = field_start;
|
||||
} else if (result == NULL) {
|
||||
result = field_start;
|
||||
break;
|
||||
}
|
||||
|
||||
field_start = NULL;
|
||||
if (*tmp_ptr != ' ') {
|
||||
continue;
|
||||
}
|
||||
|
||||
*tmp_ptr = '\0';
|
||||
ret_code = field_start;
|
||||
ret_msg = tmp_ptr + 1;
|
||||
field_start = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (field_start && result == NULL) {
|
||||
result = field_start;
|
||||
if (ret_code == NULL || ret_msg == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret_code == NULL || result == NULL) {
|
||||
if (is_numeric(ret_code) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
http_head->code = atol(ret_code);
|
||||
http_head->code_msg = result;
|
||||
http_head->code_msg = ret_msg;
|
||||
http_head->version = key;
|
||||
http_head->head_type = HTTP_HEAD_RESPONSE;
|
||||
|
||||
|
||||
@@ -20,12 +20,6 @@
|
||||
#ifndef _GENERIC_ATOMIC_H
|
||||
#define _GENERIC_ATOMIC_H
|
||||
|
||||
|
||||
/* Check GCC version, just to be safe */
|
||||
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
|
||||
# error atomic.h works only with GCC newer than version 4.1
|
||||
#endif /* GNUC >= 4.1 */
|
||||
|
||||
/**
|
||||
* Atomic type.
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GENERIC_CONF_H
|
||||
#define _GENERIC_CONF_H
|
||||
|
||||
@@ -27,9 +26,9 @@
|
||||
#define CONF_INT_MAX (~(1 << 31))
|
||||
#define CONF_INT_MIN (1 << 31)
|
||||
|
||||
#define CONF_RET_OK 0
|
||||
#define CONF_RET_ERR -1
|
||||
#define CONF_RET_WARN -2
|
||||
#define CONF_RET_OK 0
|
||||
#define CONF_RET_ERR -1
|
||||
#define CONF_RET_WARN -2
|
||||
#define CONF_RET_NOENT -3
|
||||
|
||||
struct config_item {
|
||||
@@ -64,48 +63,48 @@ struct config_item_size {
|
||||
size_t max;
|
||||
};
|
||||
|
||||
#define CONF_INT(key, value, min_value, max_value) \
|
||||
{ \
|
||||
key, conf_int, &(struct config_item_int) \
|
||||
{ \
|
||||
.data = value, .min = min_value, .max = max_value \
|
||||
} \
|
||||
#define CONF_INT(key, value, min_value, max_value) \
|
||||
{ \
|
||||
key, conf_int, &(struct config_item_int) \
|
||||
{ \
|
||||
.data = value, .min = min_value, .max = max_value \
|
||||
} \
|
||||
}
|
||||
#define CONF_STRING(key, value, len_value) \
|
||||
{ \
|
||||
key, conf_string, &(struct config_item_string) \
|
||||
{ \
|
||||
.data = value, .size = len_value \
|
||||
} \
|
||||
#define CONF_STRING(key, value, len_value) \
|
||||
{ \
|
||||
key, conf_string, &(struct config_item_string) \
|
||||
{ \
|
||||
.data = value, .size = len_value \
|
||||
} \
|
||||
}
|
||||
#define CONF_YESNO(key, value) \
|
||||
{ \
|
||||
key, conf_yesno, &(struct config_item_yesno) \
|
||||
{ \
|
||||
.data = value \
|
||||
} \
|
||||
#define CONF_YESNO(key, value) \
|
||||
{ \
|
||||
key, conf_yesno, &(struct config_item_yesno) \
|
||||
{ \
|
||||
.data = value \
|
||||
} \
|
||||
}
|
||||
#define CONF_SIZE(key, value, min_value, max_value) \
|
||||
{ \
|
||||
key, conf_size, &(struct config_item_size) \
|
||||
{ \
|
||||
.data = value, .min = min_value, .max = max_value \
|
||||
} \
|
||||
#define CONF_SIZE(key, value, min_value, max_value) \
|
||||
{ \
|
||||
key, conf_size, &(struct config_item_size) \
|
||||
{ \
|
||||
.data = value, .min = min_value, .max = max_value \
|
||||
} \
|
||||
}
|
||||
/*
|
||||
* func: int (*func)(void *data, int argc, char *argv[]);
|
||||
*/
|
||||
#define CONF_CUSTOM(key, func, data) \
|
||||
{ \
|
||||
key, conf_custom, &(struct config_item_custom) \
|
||||
{ \
|
||||
.custom_data = data, .custom_func = func \
|
||||
} \
|
||||
#define CONF_CUSTOM(key, func, data) \
|
||||
{ \
|
||||
key, conf_custom, &(struct config_item_custom) \
|
||||
{ \
|
||||
.custom_data = data, .custom_func = func \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CONF_END() \
|
||||
{ \
|
||||
NULL, NULL, NULL \
|
||||
#define CONF_END() \
|
||||
{ \
|
||||
NULL, NULL, NULL \
|
||||
}
|
||||
|
||||
extern int conf_custom(const char *item, void *data, int argc, char *argv[]);
|
||||
|
||||
@@ -79,7 +79,8 @@ static void _show_version(void)
|
||||
#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);
|
||||
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);
|
||||
}
|
||||
@@ -157,13 +158,18 @@ static int _smartdns_add_servers(void)
|
||||
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));
|
||||
safe_strncpy(flag_http->tls_host_verify, dns_conf_servers[i].tls_host_verify,
|
||||
sizeof(flag_http->tls_host_verify));
|
||||
flag_http->skip_check_cert = dns_conf_servers[i].skip_check_cert;
|
||||
} 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);
|
||||
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));
|
||||
safe_strncpy(flag_tls->tls_host_verify, dns_conf_servers[i].tls_host_verify,
|
||||
sizeof(flag_tls->tls_host_verify));
|
||||
flag_tls->skip_check_cert = dns_conf_servers[i].skip_check_cert;
|
||||
|
||||
} break;
|
||||
case DNS_SERVER_TCP:
|
||||
break;
|
||||
@@ -175,7 +181,8 @@ static int _smartdns_add_servers(void)
|
||||
flags.type = dns_conf_servers[i].type;
|
||||
flags.server_flag = dns_conf_servers[i].server_flag;
|
||||
flags.result_flag = dns_conf_servers[i].result_flag;
|
||||
ret = dns_client_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type, &flags);
|
||||
ret = dns_client_add_server(dns_conf_servers[i].server, dns_conf_servers[i].port, dns_conf_servers[i].type,
|
||||
&flags);
|
||||
if (ret != 0) {
|
||||
tlog(TLOG_ERROR, "add server failed, %s:%d", dns_conf_servers[i].server, dns_conf_servers[i].port);
|
||||
return -1;
|
||||
@@ -259,7 +266,8 @@ static int _smartdns_init(void)
|
||||
tlog_setlogscreen(verbose_screen);
|
||||
tlog_setlevel(dns_conf_log_level);
|
||||
|
||||
tlog(TLOG_NOTICE, "smartdns starting...(Copyright (C) Nick Peng <pymumu@gmail.com>, build:%s %s)", __DATE__, __TIME__);
|
||||
tlog(TLOG_NOTICE, "smartdns starting...(Copyright (C) Nick Peng <pymumu@gmail.com>, build:%s %s)", __DATE__,
|
||||
__TIME__);
|
||||
|
||||
if (_smartdns_init_ssl() != 0) {
|
||||
tlog(TLOG_ERROR, "init ssl failed.");
|
||||
@@ -331,21 +339,30 @@ static void _sig_error_exit(int signo, siginfo_t *siginfo, void *ct)
|
||||
{
|
||||
unsigned long PC = 0;
|
||||
ucontext_t *context = ct;
|
||||
const char *arch = NULL;
|
||||
#if defined(__i386__)
|
||||
int *pgregs = (int *)(&(context->uc_mcontext.gregs));
|
||||
PC = pgregs[REG_EIP];
|
||||
arch = "i386";
|
||||
#elif defined(__x86_64__)
|
||||
int *pgregs = (int *)(&(context->uc_mcontext.gregs));
|
||||
PC = pgregs[REG_RIP];
|
||||
arch = "x86_64";
|
||||
#elif defined(__arm__)
|
||||
PC = context->uc_mcontext.arm_pc;
|
||||
arch = "arm";
|
||||
#elif defined(__aarch64__)
|
||||
PC = context->uc_mcontext.pc;
|
||||
arch = "arm64";
|
||||
#elif defined(__mips__)
|
||||
PC = context->uc_mcontext.pc;
|
||||
arch = "mips";
|
||||
#endif
|
||||
tlog(TLOG_FATAL, "process exit with signal %d, code = %d, errno = %d, pid = %d, self = %d, pc = %#lx, addr = %#lx, build(%s %s)\n", signo, siginfo->si_code,
|
||||
siginfo->si_errno, siginfo->si_pid, getpid(), PC, (unsigned long)siginfo->si_addr, __DATE__, __TIME__);
|
||||
tlog(TLOG_FATAL,
|
||||
"process exit with signal %d, code = %d, errno = %d, pid = %d, self = %d, pc = %#lx, addr = %#lx, build(%s "
|
||||
"%s %s)\n",
|
||||
signo, siginfo->si_code, siginfo->si_errno, siginfo->si_pid, getpid(), PC, (unsigned long)siginfo->si_addr,
|
||||
__DATE__, __TIME__, arch);
|
||||
|
||||
sleep(1);
|
||||
_exit(0);
|
||||
@@ -422,6 +439,7 @@ int main(int argc, char *argv[])
|
||||
goto errout;
|
||||
}
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
if (dns_server_load_conf(config_file) != 0) {
|
||||
fprintf(stderr, "load config failed.\n");
|
||||
goto errout;
|
||||
@@ -434,7 +452,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
signal(SIGINT, _sig_exit);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
atexit(_smartdns_exit);
|
||||
|
||||
return _smartdns_run();
|
||||
|
||||
57
src/tlog.c
57
src/tlog.c
@@ -94,7 +94,7 @@ struct tlog {
|
||||
};
|
||||
|
||||
struct tlog_segment_log_head {
|
||||
struct tlog_info info;
|
||||
struct tlog_loginfo info;
|
||||
unsigned short len;
|
||||
char data[0];
|
||||
} __attribute__((packed));
|
||||
@@ -117,7 +117,7 @@ struct count_log {
|
||||
};
|
||||
|
||||
struct tlog_info_inter {
|
||||
struct tlog_info info;
|
||||
struct tlog_loginfo info;
|
||||
void *userptr;
|
||||
};
|
||||
|
||||
@@ -166,6 +166,10 @@ static int _tlog_mkdir(const char *path)
|
||||
if (access(path, F_OK) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(*path == ' ' && *path != '\0') {
|
||||
path++;
|
||||
}
|
||||
|
||||
strncpy(path_c, path, sizeof(path_c) - 1);
|
||||
path_c[sizeof(path_c) - 1] = '\0';
|
||||
@@ -181,6 +185,11 @@ static int _tlog_mkdir(const char *path)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (path_end == path_c) {
|
||||
path_end++;
|
||||
continue;
|
||||
}
|
||||
|
||||
str = *path_end;
|
||||
*path_end = '\0';
|
||||
if (access(path_c, F_OK) == 0) {
|
||||
@@ -203,8 +212,8 @@ static int _tlog_mkdir(const char *path)
|
||||
|
||||
static struct tm *_tlog_localtime(time_t *timep, struct tm *tm)
|
||||
{
|
||||
static time_t last_time = {0};
|
||||
static struct tm last_tm = {0};
|
||||
static time_t last_time;
|
||||
static struct tm last_tm;
|
||||
|
||||
/* localtime_r has a global timezone lock, it's about 8 times slower than gmtime
|
||||
* this code is used to speed up localtime_r call.
|
||||
@@ -297,11 +306,14 @@ void *tlog_get_private(tlog_log *log)
|
||||
return log->private_data;
|
||||
}
|
||||
|
||||
static int _tlog_format(char *buff, int maxlen, struct tlog_info *info, void *userptr, const char *format, va_list ap)
|
||||
static int _tlog_format(char *buff, int maxlen, struct tlog_loginfo *info, void *userptr, const char *format, va_list ap)
|
||||
{
|
||||
int len = 0;
|
||||
int total_len = 0;
|
||||
struct tlog_time *tm = &info->time;
|
||||
void* unused __attribute__ ((unused));
|
||||
|
||||
unused = userptr;
|
||||
|
||||
if (tlog.root->multi_log) {
|
||||
/* format prefix */
|
||||
@@ -388,6 +400,9 @@ static int _tlog_print_buffer(char *buff, int maxlen, void *userptr, const char
|
||||
{
|
||||
int len;
|
||||
int total_len = 0;
|
||||
void* unused __attribute__ ((unused));
|
||||
|
||||
unused = userptr;
|
||||
|
||||
/* format log message */
|
||||
len = vsnprintf(buff, maxlen, format, ap);
|
||||
@@ -550,8 +565,9 @@ int tlog_printf(struct tlog_log *log, const char *format, ...)
|
||||
static int _tlog_early_print(const char *format, va_list ap)
|
||||
{
|
||||
char log_buf[TLOG_MAX_LINE_LEN];
|
||||
int len = 0;
|
||||
int out_len = 0;
|
||||
size_t len = 0;
|
||||
size_t out_len = 0;
|
||||
int unused __attribute__ ((unused));
|
||||
|
||||
if (tlog_disable_early_print) {
|
||||
return 0;
|
||||
@@ -565,9 +581,9 @@ static int _tlog_early_print(const char *format, va_list ap)
|
||||
out_len = sizeof(log_buf);
|
||||
}
|
||||
|
||||
write(STDOUT_FILENO, log_buf, out_len);
|
||||
unused = write(STDOUT_FILENO, log_buf, out_len);
|
||||
if (log_buf[out_len - 1] != '\n') {
|
||||
write(STDOUT_FILENO, "\n", 1);
|
||||
unused = write(STDOUT_FILENO, "\n", 1);
|
||||
}
|
||||
|
||||
return len;
|
||||
@@ -650,6 +666,7 @@ static int _tlog_list_dir(const char *path, list_callback callback, void *userpt
|
||||
DIR *dir = NULL;
|
||||
struct dirent *ent;
|
||||
int ret = 0;
|
||||
const char* unused __attribute__ ((unused)) = path;
|
||||
|
||||
dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
@@ -682,6 +699,7 @@ static int _tlog_count_log_callback(const char *path, struct dirent *entry, void
|
||||
struct count_log *count_log = (struct count_log *)userptr;
|
||||
struct tlog_log *log = count_log->log;
|
||||
char logname[TLOG_LOG_NAME_LEN * 2];
|
||||
const char* unused __attribute__ ((unused)) = path;
|
||||
|
||||
if (strstr(entry->d_name, log->suffix) == NULL) {
|
||||
return 0;
|
||||
@@ -1005,9 +1023,10 @@ static int _tlog_archive_log(struct tlog_log *log)
|
||||
}
|
||||
}
|
||||
|
||||
static int _tlog_write(struct tlog_log *log, char *buff, int bufflen)
|
||||
static int _tlog_write(struct tlog_log *log, const char *buff, int bufflen)
|
||||
{
|
||||
int len;
|
||||
int unused __attribute__ ((unused));
|
||||
|
||||
if (bufflen <= 0) {
|
||||
return 0;
|
||||
@@ -1015,7 +1034,7 @@ static int _tlog_write(struct tlog_log *log, char *buff, int bufflen)
|
||||
|
||||
/* output log to screen */
|
||||
if (log->logscreen) {
|
||||
write(STDOUT_FILENO, buff, bufflen);
|
||||
unused = write(STDOUT_FILENO, buff, bufflen);
|
||||
}
|
||||
|
||||
/* if log file size exceeds threshold, start to compress */
|
||||
@@ -1027,7 +1046,7 @@ static int _tlog_write(struct tlog_log *log, char *buff, int bufflen)
|
||||
if (log->filesize < lseek(log->fd, 0, SEEK_END) && log->multi_log == 0) {
|
||||
const char *msg = "[Auto enable multi-process write mode, log may be lost, please enable multi-process write mode manually]\n";
|
||||
log->multi_log = 1;
|
||||
write(log->fd, msg, strlen(msg));
|
||||
unused = write(log->fd, msg, strlen(msg));
|
||||
}
|
||||
close(log->fd);
|
||||
log->fd = -1;
|
||||
@@ -1083,7 +1102,7 @@ static int _tlog_write(struct tlog_log *log, char *buff, int bufflen)
|
||||
return len;
|
||||
}
|
||||
|
||||
int tlog_write(struct tlog_log *log, char *buff, int bufflen)
|
||||
int tlog_write(struct tlog_log *log, const char *buff, int bufflen)
|
||||
{
|
||||
return _tlog_write(log, buff, bufflen);
|
||||
}
|
||||
@@ -1297,7 +1316,7 @@ static void _tlog_work_write(struct tlog_log *log, int log_len, int log_extlen,
|
||||
}
|
||||
}
|
||||
|
||||
static int _tlog_root_write_log(struct tlog_log *log, char *buff, int bufflen)
|
||||
static int _tlog_root_write_log(struct tlog_log *log, const char *buff, int bufflen)
|
||||
{
|
||||
struct tlog_segment_log_head *head = NULL;
|
||||
static struct tlog_segment_log_head empty_info;
|
||||
@@ -1326,7 +1345,10 @@ static void *_tlog_work(void *arg)
|
||||
int log_dropped = 0;
|
||||
struct tlog_log *log = NULL;
|
||||
struct tlog_log *loop_log = NULL;
|
||||
void* unused __attribute__ ((unused));
|
||||
|
||||
unused = arg;
|
||||
|
||||
while (1) {
|
||||
log_len = 0;
|
||||
log_extlen = 0;
|
||||
@@ -1355,7 +1377,7 @@ static void *_tlog_work(void *arg)
|
||||
log = _tlog_wait_log_locked(log);
|
||||
if (log == NULL) {
|
||||
pthread_mutex_unlock(&tlog.lock);
|
||||
if (errno != ETIMEDOUT) {
|
||||
if (errno != ETIMEDOUT && tlog.run) {
|
||||
sleep(1);
|
||||
}
|
||||
continue;
|
||||
@@ -1491,6 +1513,11 @@ int tlog_setlevel(tlog_level level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlog_level tlog_getlevel(void)
|
||||
{
|
||||
return tlog_set_level;
|
||||
}
|
||||
|
||||
tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int buffsize, unsigned int flag)
|
||||
{
|
||||
struct tlog_log *log = NULL;
|
||||
|
||||
83
src/tlog.h
83
src/tlog.h
@@ -9,6 +9,11 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
extern "C" {
|
||||
#endif /*__cplusplus */
|
||||
|
||||
@@ -55,7 +60,7 @@ struct tlog_time {
|
||||
/* enable log to screen */
|
||||
#define TLOG_SCREEN (1 << 4)
|
||||
|
||||
struct tlog_info {
|
||||
struct tlog_loginfo {
|
||||
tlog_level level;
|
||||
const char *file;
|
||||
const char *func;
|
||||
@@ -83,6 +88,9 @@ extern int tlog_write_log(char *buff, int bufflen);
|
||||
/* set log level */
|
||||
extern int tlog_setlevel(tlog_level level);
|
||||
|
||||
/* get log level */
|
||||
extern tlog_level tlog_getlevel(void);
|
||||
|
||||
/* enalbe log to screen */
|
||||
extern void tlog_setlogscreen(int enable);
|
||||
|
||||
@@ -113,13 +121,13 @@ steps:
|
||||
|
||||
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);
|
||||
typedef int (*tlog_format_func)(char *buff, int maxlen, struct tlog_loginfo *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);
|
||||
typedef int (*tlog_log_output_func)(struct tlog_loginfo *info, const 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;
|
||||
@@ -132,11 +140,11 @@ maxlogcount: Number of archived logs.
|
||||
buffsize: Buffer size, zero for default (128K)
|
||||
flag: read tlog flags
|
||||
return: log stream handler.
|
||||
*/
|
||||
*/
|
||||
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);
|
||||
extern int tlog_write(struct tlog_log *log, const char *buff, int bufflen);
|
||||
|
||||
/* close log stream */
|
||||
extern void tlog_close(tlog_log *log);
|
||||
@@ -160,7 +168,7 @@ extern int tlog_vprintf(tlog_log *log, const char *format, va_list ap);
|
||||
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);
|
||||
typedef int (*tlog_output_func)(struct tlog_log *log, const char *buff, int bufflen);
|
||||
extern int tlog_reg_output_func(tlog_log *log, tlog_output_func output);
|
||||
|
||||
/* set private data */
|
||||
@@ -173,6 +181,65 @@ extern void *tlog_get_private(tlog_log *log);
|
||||
extern int tlog_localtime(struct tlog_time *tm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus */
|
||||
class Tlog {
|
||||
using Stream = std::ostringstream;
|
||||
using Buffer = std::unique_ptr<Stream, std::function<void(Stream*)>>;
|
||||
public:
|
||||
Tlog(){}
|
||||
~Tlog(){}
|
||||
|
||||
static Tlog &Instance() {
|
||||
static Tlog logger;
|
||||
return logger;
|
||||
}
|
||||
|
||||
Buffer LogStream(tlog_level level, const char *file, int line, const char *func, void *userptr) {
|
||||
return Buffer(new Stream, [=](Stream *st) {
|
||||
tlog_ext(level, file, line, func, userptr, "%s", st->str().c_str());
|
||||
delete st;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class TlogOut {
|
||||
using Stream = std::ostringstream;
|
||||
using Buffer = std::unique_ptr<Stream, std::function<void(Stream*)>>;
|
||||
public:
|
||||
TlogOut(){}
|
||||
~TlogOut(){}
|
||||
|
||||
static TlogOut &Instance() {
|
||||
static TlogOut logger;
|
||||
return logger;
|
||||
}
|
||||
|
||||
Buffer Out(tlog_log *log) {
|
||||
return Buffer(new Stream, [=](Stream *st) {
|
||||
tlog_printf(log, "%s", st->str().c_str());
|
||||
delete st;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
#define Tlog_logger (Tlog::Instance())
|
||||
#define Tlog_stream(level) if (tlog_getlevel() <= level) *Tlog_logger.LogStream(level, BASE_FILE_NAME, __LINE__, __func__, NULL)
|
||||
#define tlog_debug Tlog_stream(TLOG_DEBUG)
|
||||
#define tlog_info Tlog_stream(TLOG_INFO)
|
||||
#define tlog_notice Tlog_stream(TLOG_NOTICE)
|
||||
#define tlog_warn Tlog_stream(TLOG_WARN)
|
||||
#define tlog_error Tlog_stream(TLOG_ERROR)
|
||||
#define tlog_fatal Tlog_stream(TLOG_FATAL)
|
||||
|
||||
#define Tlog_out_logger (TlogOut::Instance())
|
||||
#define tlog_out(stream) (*Tlog_out_logger.Out(stream))
|
||||
|
||||
} /*__cplusplus */
|
||||
#else
|
||||
#define tlog_debug(...) tlog(TLOG_DEBUG, ##__VA_ARGS__)
|
||||
#define tlog_info(...) tlog(TLOG_INFO, ##__VA_ARGS__)
|
||||
#define tlog_notice(...) tlog(TLOG_NOTICE, ##__VA_ARGS__)
|
||||
#define tlog_warn(...) tlog(TLOG_WARN, ##__VA_ARGS__)
|
||||
#define tlog_error(...) tlog(TLOG_ERROR, ##__VA_ARGS__)
|
||||
#define tlog_fatal(...) tlog(TLOG_FATAL, ##__VA_ARGS__)
|
||||
#endif
|
||||
#endif // !TLOG_H
|
||||
|
||||
75
src/util.c
75
src/util.c
@@ -24,20 +24,20 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <inttypes.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <pthread.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#define TMP_BUFF_LEN_32 32
|
||||
|
||||
@@ -285,14 +285,14 @@ int parse_ip(const char *value, char *ip, int *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _check_is_ipv4(const char *ip)
|
||||
static int _check_is_ipv4(const char *ip)
|
||||
{
|
||||
const char *ptr = ip;
|
||||
char c = 0;
|
||||
int dot_num = 0;
|
||||
int dig_num = 0;
|
||||
|
||||
while ( (c = *ptr++) != '\0') {
|
||||
while ((c = *ptr++) != '\0') {
|
||||
if (c == '.') {
|
||||
dot_num++;
|
||||
dig_num = 0;
|
||||
@@ -326,7 +326,7 @@ static int _check_is_ipv6(const char *ip)
|
||||
int colon_num = 0;
|
||||
int dig_num = 0;
|
||||
|
||||
while ( (c = *ptr++) != '\0') {
|
||||
while ((c = *ptr++) != '\0') {
|
||||
if (c == '[' || c == ']') {
|
||||
continue;
|
||||
}
|
||||
@@ -420,7 +420,7 @@ int parse_uri(char *value, char *scheme, char *host, int *port, char *path)
|
||||
|
||||
if (path) {
|
||||
strncpy(path, process_ptr, PATH_MAX);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -456,8 +456,8 @@ char *reverse_string(char *output, const char *input, int len, int to_lower_case
|
||||
if (to_lower_case) {
|
||||
if (*output >= 'A' && *output <= 'Z') {
|
||||
/* To lower case */
|
||||
*output = *output + 32;
|
||||
}
|
||||
*output = *output + 32;
|
||||
}
|
||||
}
|
||||
output++;
|
||||
len--;
|
||||
@@ -502,7 +502,8 @@ static int _ipset_support_timeout(const char *ipsetname)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int addr_len, unsigned long timeout, int operate)
|
||||
static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int addr_len, unsigned long timeout,
|
||||
int operate)
|
||||
{
|
||||
struct nlmsghdr *netlink_head;
|
||||
struct ipset_netlink_msg *netlink_msg;
|
||||
@@ -560,7 +561,9 @@ static int _ipset_operate(const char *ipsetname, const unsigned char addr[], int
|
||||
netlink_head->nlmsg_len += NETLINK_ALIGN(sizeof(struct ipset_netlink_attr));
|
||||
nested[1]->type = NLA_F_NESTED | IPSET_ATTR_IP;
|
||||
|
||||
_ipset_add_attr(netlink_head, (af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER, addr_len, addr);
|
||||
_ipset_add_attr(netlink_head,
|
||||
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER, addr_len,
|
||||
addr);
|
||||
nested[1]->len = (void *)buffer + NETLINK_ALIGN(netlink_head->nlmsg_len) - (void *)nested[1];
|
||||
|
||||
if (timeout > 0 && _ipset_support_timeout(ipsetname) == 0) {
|
||||
@@ -925,25 +928,35 @@ 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;
|
||||
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";
|
||||
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(__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_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 is_numeric(const char *str)
|
||||
{
|
||||
while (*str != '\0') {
|
||||
if (*str < '0' || *str > '9')
|
||||
return -1;
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int has_network_raw_cap(void)
|
||||
{
|
||||
int fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
@@ -958,7 +971,7 @@ int has_network_raw_cap(void)
|
||||
int set_sock_keepalive(int fd, int keepidle, int keepinterval, int keepcnt)
|
||||
{
|
||||
const int yes = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes))!= 0) {
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -966,5 +979,19 @@ int set_sock_keepalive(int fd, int keepidle, int keepinterval, int keepcnt)
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepinterval, sizeof(keepinterval));
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepcnt, sizeof(keepcnt));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_sock_lingertime(int fd, int time)
|
||||
{
|
||||
struct linger l;
|
||||
|
||||
l.l_onoff = 1;
|
||||
l.l_linger = 0;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (const char *)&l, sizeof(l)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
12
src/util.h
12
src/util.h
@@ -19,27 +19,27 @@
|
||||
#ifndef SMART_DNS_UTIL_H
|
||||
#define SMART_DNS_UTIL_H
|
||||
|
||||
#include "stringutil.h"
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
#include "stringutil.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /*__cplusplus */
|
||||
|
||||
#ifndef TCP_FASTOPEN
|
||||
#define TCP_FASTOPEN 23
|
||||
#define TCP_FASTOPEN 23
|
||||
#endif
|
||||
|
||||
#ifndef TCP_FASTOPEN_CONNECT
|
||||
#define TCP_FASTOPEN_CONNECT 30
|
||||
#endif
|
||||
#ifndef TCP_THIN_LINEAR_TIMEOUTS
|
||||
#define TCP_THIN_LINEAR_TIMEOUTS 16
|
||||
#define TCP_THIN_LINEAR_TIMEOUTS 16
|
||||
#endif
|
||||
|
||||
#ifndef TCP_THIN_DUPACK
|
||||
#define TCP_THIN_DUPACK 17
|
||||
#define TCP_THIN_DUPACK 17
|
||||
#endif
|
||||
|
||||
#define PORT_NOT_DEFINED -1
|
||||
@@ -98,10 +98,14 @@ int parse_tls_header(const char *data, size_t data_len, char *hostname, const ch
|
||||
|
||||
void get_compiled_time(struct tm *tm);
|
||||
|
||||
int is_numeric(const char *str);
|
||||
|
||||
int has_network_raw_cap(void);
|
||||
|
||||
int set_sock_keepalive(int fd, int keepidle, int keepinterval, int keepcnt);
|
||||
|
||||
int set_sock_lingertime(int fd, int time);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus */
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
[Unit]
|
||||
Description=smart dns server
|
||||
After=network.target
|
||||
StartLimitBurst=0
|
||||
StartLimitIntervalSec=60
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/smartdns.pid
|
||||
EnvironmentFile=/etc/default/smartdns
|
||||
ExecStart=/usr/sbin/smartdns $SMART_DNS_OPTS
|
||||
PIDFile=@RUNSTATEDIR@/smartdns.pid
|
||||
EnvironmentFile=@SYSCONFDIR@/default/smartdns
|
||||
ExecStart=@SBINDIR@/smartdns -p @RUNSTATEDIR@/smartdns.pid $SMART_DNS_OPTS
|
||||
KillMode=process
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
StartLimitBurst=0
|
||||
StartLimitIntervalSec=60
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user