Compare commits

..

1 Commits

Author SHA1 Message Date
Nick Peng
27c1aedd3b http-svcb: add https svcb RR suppport 2023-10-23 02:43:28 +00:00
48 changed files with 1508 additions and 3635 deletions

View File

@@ -18,9 +18,7 @@ Checks: >
-bugprone-suspicious-memory-comparison,
-bugprone-not-null-terminated-result,
-bugprone-signal-handler,
-bugprone-assignment-in-if-condition,
-concurrency-mt-unsafe,
-modernize-macro-to-enum,
-misc-unused-parameters,
-misc-misplaced-widening-cast,
-misc-no-recursion,

View File

@@ -37,7 +37,7 @@ test -x $SMARTDNS || exit 5
case $1 in
start)
$SMARTDNS "$SMART_DNS_OPTS" -R
$SMARTDNS "$SMART_DNS_OPTS"
while true; do
if [ -e "$PIDFILE" ]; then
break;

View File

@@ -16,7 +16,6 @@
# Include another configuration options
# conf-file [file]
# conf-file blacklist-ip.conf
# conf-file *.conf
# dns server bind ip and port, default dns server port is 53, support binding multi ip and port
# bind udp server
@@ -31,8 +30,6 @@
# tls cert file
# bind-cert-key-pass [password]
# tls private key password
# bind-https server
# bind-https [IP]:[port][@device] [-group [group]] [-no-rule-addr] [-no-rule-nameserver] [-no-rule-ipset] [-no-speed-check] [-no-cache] [-no-rule-soa] [-no-dualstack-selection]
# option:
# -group: set domain request to use the appropriate server group.
# -no-rule-addr: skip address rule.
@@ -205,7 +202,6 @@ log-level info
# -host-ip [ip]: set dns server host ip.
# server 8.8.8.8 -blacklist-ip -check-edns -group g1 -group g2
# server tls://dns.google:853
# server quic://dns.gooel.com:443
# server https://dns.google/dns-query
# remote tcp dns server list
@@ -227,20 +223,6 @@ log-level info
# server-tls 8.8.8.8
# server-tls 1.0.0.1
# remote quic dns server list
# server-quic [IP]:[PORT] [-blacklist-ip] [-whitelist-ip] [-spki-pin [sha256-pin]] [-group [group] ...] [-exclude-default-group]
# -spki-pin: TLS spki pin to verify.
# -tls-host-verify: cert hostname to verify.
# -host-name: TLS sni hostname.
# k|-no-check-certificate: no check certificate.
# p|-proxy [proxy-name]: use proxy to connect to server.
# -bootstrap-dns: set as bootstrap dns server.
# Get SPKI with this command:
# echo | openssl s_client -connect '[ip]:443' | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
# default port is 443
# server-quic 8.8.8.8
# server-quic 1.0.0.1
# 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.
@@ -280,11 +262,6 @@ log-level info
# specific cname to domain
# cname /domain/target
# add srv record, support multiple srv record.
# srv-record /domain/[target][,port][,priority][,weight]
# srv-record /_ldap._tcp.example.com/ldapserver.example.com,389
# srv-record /_ldap._tcp.example.com/
# enalbe DNS64 feature
# dns64 [ip/subnet]
# dns64 64:ff9b::/96
@@ -371,4 +348,3 @@ log-level info
# ip-set -name ip-list -file /etc/smartdns/ip-list.conf
# bogus-nxdomain ip-set:ip-list
# ip-alias ip-set:ip-list 1.2.3.4
# ip-alias ip-set:ip-list ip-set:ip-map-list

View File

@@ -67,18 +67,6 @@ msgstr "配置分流域名列表"
msgid "Custom Settings"
msgstr "自定义设置"
msgid "DOH Server"
msgstr "DOH服务器"
msgid "DOH Server Port"
msgstr "DOH服务器端口"
msgid "DOT Server"
msgstr "DOT服务器"
msgid "DOT Server Port"
msgstr "DOT服务器端口"
msgid "DNS Block Setting"
msgstr "域名屏蔽设置"
@@ -196,44 +184,8 @@ msgstr "启用IPV6服务器。"
msgid "Enable TCP DNS Server"
msgstr "启用TCP服务器。"
msgid "Enable daily(week) auto update."
msgstr "启用每天(每周)自动更新"
msgid "Enable DOH DNS Server"
msgstr "启用DOH服务器。"
msgid "Enable DOT DNS Server"
msgstr "启用DOT服务器。"
msgid "Update Time (Every Week)"
msgstr "更新时间(每周)"
msgid "Every Day"
msgstr "每天"
msgid "Every Monday"
msgstr "每周一"
msgid "Every Tuesday"
msgstr "每周二"
msgid "Every Wednesday"
msgstr "每周三"
msgid "Every Thursday"
msgstr "每周四"
msgid "Every Friday"
msgstr "每周五"
msgid "Every Saturday"
msgstr "每周六"
msgid "Every Sunday"
msgstr "每周日"
msgid "Update Time (Every Day)"
msgstr "更新时间(每天)"
msgid "Enable daily auto update."
msgstr "启用每自动更新"
msgid "Enable domain prefetch, accelerate domain response speed."
msgstr "启用域名预加载,加速域名响应速度。"
@@ -446,15 +398,6 @@ msgstr "重启服务"
msgid "Second Server Settings"
msgstr "第二DNS服务器"
msgid "Server certificate file path."
msgstr "服务器证书文件路径。"
msgid "Server certificate key file path."
msgstr "服务器证书私钥文件路径。"
msgid "Server certificate key file password."
msgstr "服务器证书私钥文件密码。"
msgid "Serve expired"
msgstr "缓存过期服务"
@@ -467,15 +410,6 @@ msgstr "服务器组%s不存在"
msgid "Server Name"
msgstr "服务器名称"
msgid "Server Cert"
msgstr "服务器证书"
msgid "Server Cert Key"
msgstr "服务器证书私钥"
msgid "Server Cert Key Pass"
msgstr "服务器证书私钥密码"
msgid "Set Specific domain ip address."
msgstr "设置指定域名的IP地址。"
@@ -544,12 +478,6 @@ msgstr "跳过Nameserver规则。"
msgid "SmartDNS"
msgstr "SmartDNS"
msgid "Smartdns DOH server port."
msgstr "Smartdns DOH服务器端口号。
msgid "Smartdns DOT server port."
msgstr "Smartdns DOT服务器端口号。"
msgid "SmartDNS Server"
msgstr "SmartDNS 服务器"
@@ -720,4 +648,4 @@ msgid "type"
msgstr "类型"
msgid "udp"
msgstr "udp"
msgstr "udp"

View File

@@ -130,56 +130,6 @@ o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "1"
end
---- Enable DOT server;
o = s:taboption("advanced", Flag, "tls_server", translate("DOT Server"), translate("Enable DOT DNS Server"))
o.rmempty = false
o.default = o.disabled
o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "0"
end
o = s:taboption("advanced", Value, "tls_server_port", translate("DOT Server Port"), translate("Smartdns DOT server port."))
o.placeholder = 853
o.default = 853
o.datatype = "port"
o.rempty = false
o:depends('tls_server', '1')
---- Enable DOH server;
o = s:taboption("advanced", Flag, "doh_server", translate("DOH Server"), translate("Enable DOH DNS Server"))
o.rmempty = false
o.default = o.disabled
o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "0"
end
o = s:taboption("advanced", Value, "doh_server_port", translate("DOH Server Port"), translate("Smartdns DOH server port."))
o.placeholder = 843
o.default = 843
o.datatype = "port"
o.rempty = false
o:depends('doh_server', '1')
o = s:taboption("advanced", Value, "bind_cert", translate("Server Cert"), translate("Server certificate file path."))
o.datatype = "string"
o.placeholder = "/var/etc/smartdns/smartdns/smartdns-cert.pem"
o.rempty = true
o:depends('tls_server', '1')
o:depends('doh_server', '1')
o = s:taboption("advanced", Value, "bind_cert_key", translate("Server Cert Key"), translate("Server certificate key file path."))
o.datatype = "string"
o.placeholder = "/var/etc/smartdns/smartdns/smartdns-key.pem"
o.rempty = false
o:depends('tls_server', '1')
o:depends('doh_server', '1')
o = s:taboption("advanced", Value, "bind_cert_key_pass", translate("Server Cert Key Pass"), translate("Server certificate key file password."))
o.datatype = "string"
o.rempty = false
o:depends('tls_server', '1')
o:depends('doh_server', '1')
---- Support IPV6
o = s:taboption("advanced", Flag, "ipv6_server", translate("IPV6 Server"), translate("Enable IPV6 DNS Server"))
o.rmempty = false
@@ -721,26 +671,11 @@ s = m:section(TypedSection, "smartdns", translate("Download Files Setting"), tra
s.anonymous = true
---- download Files Settings
o = s:option(Flag, "enable_auto_update", translate("Enable Auto Update"), translate("Enable daily(week) auto update."))
o = s:option(Flag, "enable_auto_update", translate("Enable Auto Update"), translate("Enable daily auto update."))
o.rmempty = true
o.default = o.disabled
o.rempty = true
o = s:option(ListValue, "auto_update_week_time", translate("Update Time (Every Week)"))
o:value("*", translate("Every Day"))
o:value("1", translate("Every Monday"))
o:value("2", translate("Every Tuesday"))
o:value("3", translate("Every Wednesday"))
o:value("4", translate("Every Thursday"))
o:value("5", translate("Every Friday"))
o:value("6", translate("Every Saturday"))
o:value("0", translate("Every Sunday"))
o.default = "*"
o = s:option(ListValue, "auto_update_day_time", translate("Update Time (Every Day)"))
for i = 0, 23 do o:value(i, i .. ":00") end
o.default = 5
o = s:option(FileUpload, "upload_conf_file", translate("Upload Config File"),
translate("Upload smartdns config file to /etc/smartdns/conf.d"))
o.rmempty = true
@@ -845,3 +780,4 @@ o.write = function()
end
return m

View File

@@ -6,10 +6,6 @@ msgid ""
"Additional Flags for rules, read help on domain-rule for more information."
msgstr "额外的规则标识具体参考domain-rule的帮助说明。"
msgid ""
"Additional Flags for rules, read help on ip-rule for more information."
msgstr "额外的规则标识具体参考ip-rule的帮助说明。"
msgid "Additional Rule Flag"
msgstr "额外规则标识"
@@ -33,21 +29,12 @@ msgstr "自动设置Dnsmasq"
msgid "Automatically set as upstream of dnsmasq when port changes."
msgstr "端口更改时自动设为 dnsmasq 的上游。"
msgid "Blacklist IP"
msgstr "黑名单"
msgid "Blacklist IP Rule, Decline IP addresses within the range."
msgstr "黑名单规则拒绝指定范围的IP地址。"
msgid "Bind Device"
msgstr "绑定到设备"
msgid "Bind Device Name"
msgstr "绑定的设备名称"
msgid "Bogus nxdomain"
msgstr "假冒IP"
msgid "Block domain"
msgstr "屏蔽域名"
@@ -77,27 +64,9 @@ msgstr "配置域名规则列表"
msgid "Configure forwarding domain name list."
msgstr "配置分流域名列表"
msgid "Configure ip rule list."
msgstr "配置IP规则列表"
msgid "Custom Settings"
msgstr "自定义设置"
msgid "Do not use these IP addresses."
msgstr "忽略这些IP地址"
msgid "DOH Server"
msgstr "DOH服务器"
msgid "DOH Server Port"
msgstr "DOH服务器端口"
msgid "DOT Server"
msgstr "DOT服务器"
msgid "DOT Server Port"
msgstr "DOT服务器端口"
msgid "DNS Block Setting"
msgstr "域名屏蔽设置"
@@ -215,44 +184,8 @@ msgstr "启用IPV6服务器。"
msgid "Enable TCP DNS Server"
msgstr "启用TCP服务器。"
msgid "Enable daily (weekly) auto update."
msgstr "启用每日(每周)自动更新"
msgid "Enable DOH DNS Server"
msgstr "启用DOH服务器"
msgid "Enable DOT DNS Server"
msgstr "启用DOT服务器"
msgid "Update time (every day)"
msgstr "更新时间(每天)"
msgid "Update Time (Every Week)"
msgstr "更新时间(每周)"
msgid "Every Day"
msgstr "每天"
msgid "Every Monday"
msgstr "每周一"
msgid "Every Tuesday"
msgstr "每周二"
msgid "Every Wednesday"
msgstr "每周三"
msgid "Every Thursday"
msgstr "每周四"
msgid "Every Friday"
msgstr "每周五"
msgid "Every Saturday"
msgstr "每周六"
msgid "Every Sunday"
msgstr "每周日"
msgid "Enable daily auto update."
msgstr "启用每日自动更新"
msgid "Enable domain prefetch, accelerate domain response speed."
msgstr "启用域名预加载,加速域名响应速度。"
@@ -326,30 +259,6 @@ msgstr "IP黑名单过滤"
msgid "IPV6 Server"
msgstr "IPV6服务器"
msgid "IP alias"
msgstr "IP别名"
msgid "IP Addresses"
msgstr "IP地址"
msgid "IP Address Mapping, Can be used for CDN acceleration with Anycast IP, such as Cloudflare's CDN."
msgstr "IP地址映射可用于支持AnyCast IP的CDN加速比如Cloudflare的CDN。"
msgid "Ignore IP"
msgstr "忽略IP"
msgid "IP Rule List"
msgstr "IP规则列表"
msgid "IP Rule Name"
msgstr "IP规则名称"
msgid "IP Set File"
msgstr "IP集合列表文件"
msgid "IP addresses, CIDR format."
msgstr "IP地址CIDR格式。"
msgid "IPset Name"
msgstr "IPset名称"
@@ -440,9 +349,6 @@ msgstr "无"
msgid "Only socks5 proxy support udp server."
msgstr "仅SOCKS5代理支持UDP服务器。"
msgid "Please check the system logs and check if the configuration is valid."
msgstr "请检查系统日志,并检查配置是否合法。"
msgid "Please set proxy server first."
msgstr "请先设置代理服务器。"
@@ -474,9 +380,6 @@ msgstr "设置返回给客户端的域名TTL最大值。"
msgid "Report bugs"
msgstr "报告BUG"
msgid "Return SOA when the requested result contains a specified IP address."
msgstr "当结果包含对应范围的IP时返回SOA。"
msgid "Resolve Local Hostnames"
msgstr "解析本地主机名"
@@ -495,15 +398,6 @@ msgstr "重启服务"
msgid "Second Server Settings"
msgstr "第二DNS服务器"
msgid "Server certificate file path."
msgstr "服务器证书文件路径。"
msgid "Server certificate key file path."
msgstr "服务器证书私钥文件路径。"
msgid "Server certificate key file password."
msgstr "服务器证书私钥文件密码。"
msgid "Serve expired"
msgstr "缓存过期服务"
@@ -516,15 +410,6 @@ msgstr "服务器组%s不存在"
msgid "Server Name"
msgstr "服务器名称"
msgid "Server Cert"
msgstr "服务器证书"
msgid "Server Cert Key"
msgstr "服务器证书私钥"
msgid "Server Cert Key Pass"
msgstr "服务器证书私钥密码"
msgid "Set Specific domain ip address."
msgstr "设置指定域名的IP地址。"
@@ -534,9 +419,6 @@ msgstr "设置指定域名的规则列表。"
msgid "Set Specific ip blacklist."
msgstr "设置指定的 IP 黑名单列表。"
msgid "Set Specific ip rule list."
msgstr "设置对应IP的规则。"
msgid "Set TLS hostname to verify."
msgstr "设置校验TLS主机名。"
@@ -596,12 +478,6 @@ msgstr "跳过Nameserver规则。"
msgid "SmartDNS"
msgstr "SmartDNS"
msgid "Smartdns DOH server port."
msgstr "Smartdns DOH服务器端口号。
msgid "Smartdns DOT server port."
msgstr "Smartdns DOT服务器端口号。"
msgid "SmartDNS Server"
msgstr "SmartDNS 服务器"
@@ -699,9 +575,6 @@ msgstr "上传域名列表文件,或在下载文件设置页面设置自动下
msgid "Upload domain list file."
msgstr "上传域名列表文件"
msgid "Upload IP set file."
msgstr "上传IP集合列表文件。"
msgid "Upload smartdns config file to /etc/smartdns/conf.d"
msgstr "上传配置文件到/etc/smartdns/conf.d"
@@ -729,12 +602,6 @@ msgstr ""
"用于校验 TLS 服务器的有效性,数值为 Base64 编码的 SPKI 指纹,留空表示不验证 "
"TLS 的合法性。"
msgid "Whitelist IP"
msgstr "白名单"
msgid "Whitelist IP Rule, Accept IP addresses within the range."
msgstr "白名单规则接受指定范围的IP地址。"
msgid "Write cache to disk on exit and load on startup."
msgstr "退出时保存cache到磁盘启动时加载。"

View File

@@ -58,17 +58,12 @@ function smartdnsRenderStatus(res) {
var autoSetDnsmasq = uci.get_first('smartdns', 'smartdns', 'auto_set_dnsmasq');
var smartdnsPort = uci.get_first('smartdns', 'smartdns', 'port');
var smartdnsEnable = uci.get_first('smartdns', 'smartdns', 'enabled');
var dnsmasqServer = uci.get_first('dhcp', 'dnsmasq', 'server');
if (isRunning) {
renderHTML += "<span style=\"color:green;font-weight:bold\">SmartDNS - " + _("RUNNING") + "</span>";
} else {
renderHTML += "<span style=\"color:red;font-weight:bold\">SmartDNS - " + _("NOT RUNNING") + "</span>";
if (smartdnsEnable === '1') {
renderHTML += "<br /><span style=\"color:red;font-weight:bold\">" + _("Please check the system logs and check if the configuration is valid.");
renderHTML += "</span>";
}
return renderHTML;
}
@@ -84,6 +79,7 @@ function smartdnsRenderStatus(res) {
return renderHTML;
}
return view.extend({
load: function () {
return Promise.all([
@@ -160,7 +156,7 @@ return view.extend({
o.default = 53;
o.datatype = "port";
o.rempty = false;
// auto-conf-dnsmasq;
o = s.taboption("settings", form.Flag, "auto_set_dnsmasq", _("Automatically Set Dnsmasq"), _("Automatically set as upstream of dnsmasq when port changes."));
o.rmempty = false;
@@ -224,50 +220,6 @@ return view.extend({
o.rmempty = false;
o.default = o.enabled;
// Enable DOT server;
o = s.taboption("advanced", form.Flag, "tls_server", _("DOT Server"), _("Enable DOT DNS Server"));
o.rmempty = false;
o.default = o.disabled;
o = s.taboption("advanced", form.Value, "tls_server_port", _("DOT Server Port"), _("Smartdns DOT server port."));
o.placeholder = 853;
o.default = 853;
o.datatype = "port";
o.rempty = false;
o.depends('tls_server', '1');
// Enable DOH server;
o = s.taboption("advanced", form.Flag, "doh_server", _("DOH Server"), _("Enable DOH DNS Server"));
o.rmempty = false;
o.default = o.disabled;
o = s.taboption("advanced", form.Value, "doh_server_port", _("DOH Server Port"), _("Smartdns DOH server port."));
o.placeholder = 843;
o.default = 843;
o.datatype = "port";
o.rempty = false;
o.depends('doh_server', '1');
o = s.taboption("advanced", form.Value, "bind_cert", _("Server Cert"), _("Server certificate file path."));
o.datatype = "string";
o.placeholder = "/var/etc/smartdns/smartdns/smartdns-cert.pem"
o.rempty = true;
o.depends('tls_server', '1');
o.depends('doh_server', '1');
o = s.taboption("advanced", form.Value, "bind_cert_key", _("Server Cert Key"), _("Server certificate key file path."));
o.datatype = "string";
o.placeholder = "/var/etc/smartdns/smartdns/smartdns-key.pem"
o.rempty = false;
o.depends('tls_server', '1');
o.depends('doh_server', '1');
o = s.taboption("advanced", form.Value, "bind_cert_key_pass", _("Server Cert Key Pass"), _("Server certificate key file password."));
o.datatype = "string";
o.rempty = false;
o.depends('tls_server', '1');
o.depends('doh_server', '1');
// Support IPV6;
o = s.taboption("advanced", form.Flag, "ipv6_server", _("IPV6 Server"), _("Enable IPV6 DNS Server"));
o.rmempty = false;
@@ -327,7 +279,7 @@ return view.extend({
o.default = o.enabled;
// Ipset no speed.
o = s.taboption("advanced", form.Value, "ipset_no_speed", _("No Speed IPset Name"),
o = s.taboption("advanced", form.Value, "ipset_no_speed", _("No Speed IPset Name"),
_("Ipset name, Add domain result to ipset when speed check fails."));
o.rmempty = true;
o.datatype = "string";
@@ -348,7 +300,7 @@ return view.extend({
}
// NFTset no speed.
o = s.taboption("advanced", form.Value, "nftset_no_speed", _("No Speed NFTset Name"),
o = s.taboption("advanced", form.Value, "nftset_no_speed", _("No Speed NFTset Name"),
_("Nftset name, Add domain result to nftset when speed check fails, format: [#[4|6]:[family#table#set]]"));
o.rmempty = true;
o.datatype = "string";
@@ -391,7 +343,7 @@ return view.extend({
o.rempty = true;
// other args
o = s.taboption("advanced", form.Value, "server_flags", _("Additional Server Args"),
o = s.taboption("advanced", form.Value, "server_flags", _("Additional Server Args"),
_("Additional server args, refer to the help description of the bind option."))
o.default = ""
o.rempty = true
@@ -524,7 +476,7 @@ return view.extend({
}
// other args
o = s.taboption("seconddns", form.Value, "seconddns_server_flags", _("Additional Server Args"),
o = s.taboption("seconddns", form.Value, "seconddns_server_flags", _("Additional Server Args"),
_("Additional server args, refer to the help description of the bind option."))
o.default = ""
o.rempty = true
@@ -540,29 +492,11 @@ return view.extend({
///////////////////////////////////////
// download Files Settings
///////////////////////////////////////
o = s.taboption("files", form.Flag, "enable_auto_update", _("Enable Auto Update"), _("Enable daily (weekly) auto update."));
o = s.taboption("files", form.Flag, "enable_auto_update", _("Enable Auto Update"), _("Enable daily auto update."));
o.rmempty = true;
o.default = o.disabled;
o.rempty = true;
o = s.taboption("files", form.ListValue, "auto_update_week_time", _("Update Time (Every Week)"));
o.value('*', _('Every Day'));
o.value('1', _('Every Monday'));
o.value('2', _('Every Tuesday'));
o.value('3', _('Every Wednesday'));
o.value('4', _('Every Thursday'));
o.value('5', _('Every Friday'));
o.value('6', _('Every Saturday'));
o.value('0', _('Every Sunday'));
o.default = "*";
o.depends('enable_auto_update', '1');
o = s.taboption('files', form.ListValue, 'auto_update_day_time', _("Update time (every day)"));
for (var i = 0; i < 24; i++)
o.value(i, i + ':00');
o.default = '5';
o.depends('enable_auto_update', '1');
o = s.taboption("files", form.FileUpload, "upload_conf_file", _("Upload Config File"),
_("Upload smartdns config file to /etc/smartdns/conf.d"));
o.rmempty = true
@@ -870,7 +804,6 @@ return view.extend({
s.tab("forwarding", _('DNS Forwarding Setting'));
s.tab("block", _("DNS Block Setting"));
s.tab("domain-rule-list", _("Domain Rule List"), _("Set Specific domain rule list."));
s.tab("ip-rule-list", _("IP Rule List"), _("Set Specific ip rule list."));
s.tab("domain-address", _("Domain Address"), _("Set Specific domain ip address."));
s.tab("blackip-list", _("IP Blacklist"), _("Set Specific ip blacklist."));
@@ -1198,72 +1131,6 @@ return view.extend({
});
};
///////////////////////////////////////
// ip rule list;
///////////////////////////////////////
o = s.taboption('ip-rule-list', form.SectionValue, '__ip-rule-list__', form.GridSection, 'ip-rule-list', _('IP Rule List'),
_('Configure ip rule list.'));
ss = o.subsection;
ss.addremove = true;
ss.anonymous = true;
ss.sortable = true;
// enable flag;
so = ss.option(form.Flag, "enabled", _("Enable"), _("Enable"));
so.rmempty = false;
so.default = so.enabled;
so.editable = true;
// name;
so = ss.option(form.Value, "name", _("IP Rule Name"), _("IP Rule Name"));
so.rmempty = true;
so.datatype = "string";
so = ss.option(form.FileUpload, "ip_set_file", _("IP Set File"), _("Upload IP set file."));
so.rmempty = true
so.datatype = "file"
so.modalonly = true;
so.root_directory = "/etc/smartdns/ip-set"
so = ss.option(form.DynamicList, "ip_addr", _("IP Addresses"), _("IP addresses, CIDR format."));
so.rmempty = true;
so.datatype = "ipaddr"
so.modalonly = true;
so = ss.option(form.Flag, "whitelist_ip", _("Whitelist IP"), _("Whitelist IP Rule, Accept IP addresses within the range."));
so.rmempty = true;
so.default = so.disabled;
so.modalonly = true;
so = ss.option(form.Flag, "blacklist_ip", _("Blacklist IP"), _("Blacklist IP Rule, Decline IP addresses within the range."));
so.rmempty = true;
so.default = so.disabled;
so.modalonly = true;
so = ss.option(form.Flag, "ignore_ip", _("Ignore IP"), _("Do not use these IP addresses."));
so.rmempty = true;
so.default = so.disabled;
so.modalonly = true;
so = ss.option(form.Flag, "bogus_nxdomain", _("Bogus nxdomain"), _("Return SOA when the requested result contains a specified IP address."));
so.rmempty = true;
so.default = so.disabled;
so.modalonly = true;
so = ss.option(form.DynamicList, "ip_alias", _("IP alias"), _("IP Address Mapping, Can be used for CDN acceleration with Anycast IP, such as Cloudflare's CDN."));
so.rmempty = true;
so.datatype = 'ipaddr("nomask")';
so.modalonly = true;
// other args
so = ss.option(form.Value, "addition_flag", _("Additional Rule Flag"),
_("Additional Flags for rules, read help on ip-rule for more information."))
so.default = ""
so.rempty = true
so.modalonly = true;
////////////////
// Support
////////////////

View File

@@ -50,14 +50,12 @@ endef
define Package/smartdns/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d
$(INSTALL_DIR) $(1)/etc/smartdns $(1)/etc/smartdns/domain-set $(1)/etc/smartdns/conf.d/ $(1)/etc/smartdns/ip-set
$(INSTALL_DIR) $(1)/etc/smartdns $(1)/etc/smartdns/domain-set $(1)/etc/smartdns/conf.d/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/smartdns $(1)/usr/sbin/smartdns
$(INSTALL_BIN) $(PKG_BUILD_DIR)/package/openwrt/files/etc/init.d/smartdns $(1)/etc/init.d/smartdns
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/address.conf $(1)/etc/smartdns/address.conf
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/blacklist-ip.conf $(1)/etc/smartdns/blacklist-ip.conf
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/custom.conf $(1)/etc/smartdns/custom.conf
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/domain-block.list $(1)/etc/smartdns/domain-block.list
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/domain-forwarding.list $(1)/etc/smartdns/domain-forwarding.list
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/files/etc/config/smartdns $(1)/etc/config/smartdns
endef

View File

@@ -27,8 +27,6 @@ if [ ! -d "/run" ]; then
SERVICE_PID_FILE="/var/run/smartdns.pid"
fi
SMARTDNS_DEFAULT_FORWARDING_FILE="/etc/smartdns/domain-forwarding.list"
SMARTDNS_DEFAULT_DOMAIN_BLOCK_FILE="/etc/smartdns/domain-block.list"
SMARTDNS_CONF_DIR="/etc/smartdns"
SMARTDNS_CONF_DOWNLOAD_DIR="$SMARTDNS_CONF_DIR/conf.d"
SMARTDNS_DOMAIN_LIST_DOWNLOAD_DIR="$SMARTDNS_CONF_DIR/domain-set"
@@ -126,10 +124,6 @@ clear_iptable()
{
local OLD_PORT="$1"
local ipv6_server=$2
which iptables >/dev/null 2>&1
[ $? -ne 0 ] && return
IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F : '{print $2}')"
for IP in $IPS
do
@@ -266,13 +260,13 @@ disable_auto_update()
enable_auto_update()
{
grep "0 $auto_update_day_time * * $auto_update_week_time /etc/init.d/smartdns updatefiles" /etc/crontabs/root 2>/dev/null
grep "0 $auto_update_day_time * * * /etc/init.d/smartdns updatefiles" /etc/crontabs/root 2>/dev/null
if [ $? -eq 0 ]; then
return
fi
disable_auto_update 1
echo "0 $auto_update_day_time * * $auto_update_week_time /etc/init.d/smartdns updatefiles" >> /etc/crontabs/root
echo "0 $auto_update_day_time * * * /etc/init.d/smartdns updatefiles" >> /etc/crontabs/root
restart_crond
}
@@ -302,27 +296,23 @@ load_domain_rules()
config_get forwarding_domain_set_file "$section" "forwarding_domain_set_file" ""
[ ! -z "$forwarding_domain_set_file" ] && {
[ ! -e "$forwarding_domain_set_file" ] && touch $forwarding_domain_set_file
conf_append "domain-set" "-name ${domain_set_name}-forwarding-file -file '$forwarding_domain_set_file'"
conf_append "domain-rules" "/domain-set:${domain_set_name}-forwarding-file/ $domain_set_args"
}
[ ! -z "$domain_set_args" ] && {
[ ! -e "$SMARTDNS_DEFAULT_FORWARDING_FILE" ] && touch $SMARTDNS_DEFAULT_FORWARDING_FILE
conf_append "domain-set" "-name ${domain_set_name}-forwarding-list -file $SMARTDNS_DEFAULT_FORWARDING_FILE"
conf_append "domain-set" "-name ${domain_set_name}-forwarding-list -file /etc/smartdns/domain-forwarding.list"
conf_append "domain-rules" "/domain-set:${domain_set_name}-forwarding-list/ $domain_set_args"
}
config_get block_domain_set_file "$section" "block_domain_set_file"
[ ! -z "$block_domain_set_file" ] && {
[ ! -e "$block_domain_set_file" ] && touch $block_domain_set_file
conf_append "domain-set" "-name ${domain_set_name}-block-file -file '$block_domain_set_file'"
conf_append "domain-rules" "/domain-set:${domain_set_name}-block-file/ -address #"
conf_append "domain-rules" "/domain-set:${domain_set_name}-block-file/ --address #"
}
[ ! -e "$SMARTDNS_DEFAULT_DOMAIN_BLOCK_FILE" ] && touch $SMARTDNS_DEFAULT_DOMAIN_BLOCK_FILE
conf_append "domain-set" "-name ${domain_set_name}-block-list -file $SMARTDNS_DEFAULT_DOMAIN_BLOCK_FILE"
conf_append "domain-rules" "/domain-set:${domain_set_name}-block-list/ -address #"
conf_append "domain-set" "-name ${domain_set_name}-block-list -file /etc/smartdns/domain-block.list"
conf_append "domain-rules" "/domain-set:${domain_set_name}-block-list/ --address #"
}
load_domain_rule_list()
@@ -365,64 +355,16 @@ load_domain_rule_list()
[ ! -z "$addition_flag" ] && domain_set_args="$domain_set_args $addition_flag"
[ -z "$domain_set_args" ] && return
[ ! -e "$domain_list_file" ] && touch $domain_list_file
conf_append "domain-set" "-name domain-rule-list-${domain_set_name} -file '$domain_list_file'"
conf_append "domain-rules" "/domain-set:domain-rule-list-${domain_set_name}/ $domain_set_args"
}
ip_rule_addr_append()
{
conf_append "ip-rules" "$1 $IP_set_args"
}
load_IP_rule_list()
{
local section="$1"
local IP_set_args=""
local IP_set_name="$section"
config_get_bool enabled "$section" "enabled" "0"
[ "$enabled" != "1" ] && return
config_get ip_set_file "$section" "ip_set_file" ""
config_get_bool whitelist_ip "$section" "whitelist_ip" "0"
[ "$whitelist_ip" = "1" ] && IP_set_args="$IP_set_args -whitelist-ip"
config_get_bool blacklist_ip "$section" "blacklist_ip" "0"
[ "$blacklist_ip" = "1" ] && IP_set_args="$IP_set_args -blacklist-ip"
config_get_bool ignore_ip "$section" "ignore_ip" "0"
[ "$ignore_ip" = "1" ] && IP_set_args="$IP_set_args -ignore-ip"
config_get_bool bogus_nxdomain "$section" "bogus_nxdomain" "0"
[ "$bogus_nxdomain" = "1" ] && IP_set_args="$IP_set_args -bogus-nxdomain"
config_get ip_alias "$section" "ip_alias" ""
[ ! -z "$ip_alias" ] && {
ip_alias="$(echo "$ip_alias" | sed 's/ /,/g')"
IP_set_args="$IP_set_args -ip-alias $ip_alias"
}
config_get addition_flag "$section" "addition_flag" ""
[ ! -z "$addition_flag" ] && IP_set_args="$IP_set_args $addition_flag"
[ -z "$IP_set_args" ] && return
[ ! -z "$ip_set_file" ] && [ -e "$ip_set_file" ] && {
conf_append "ip-set" "-name ip-rule-list-file-${section} -file '$ip_set_file'"
conf_append "ip-rules" "ip-set:ip-rule-list-file-${section} $IP_set_args"
}
config_list_foreach "$section" "ip_addr" ip_rule_addr_append
}
conf_append_bind()
{
local ADDR=""
local bind_type="$1"
local port="$2"
local devices="$3"
local device=""
local port="$1"
local devices="$2"
local tcp_server="$3"
local ipv6_server="$4"
local ARGS="$5"
@@ -439,8 +381,16 @@ conf_append_bind()
for device in $devices; do
device="@$device"
[ "$device" = "@-" ] && device=""
conf_append "$bind_type" "$ADDR:$port$device $ARGS"
conf_append "bind" "$ADDR:$port$device $ARGS"
done
[ "$tcp_server" = "1" ] && {
for device in $devices; do
device="@$device"
[ "$device" = "@-" ] && device=""
conf_append "bind-tcp" "$ADDR:$port$device $ARGS"
done
}
}
load_second_server()
@@ -498,8 +448,7 @@ load_second_server()
config_get seconddns_server_flags "$section" "seconddns_server_flags" ""
[ -z "$seconddns_server_flags" ] || ARGS="$ARGS $seconddns_server_flags"
conf_append_bind "bind" "$seconddns_port" "$device" "$ipv6_server" "$ARGS"
[ "$seconddns_tcp_server" = "1" ] && conf_append_bind "bind-tcp" "$seconddns_port" "$device" "$ipv6_server" "$ARGS"
conf_append_bind "$seconddns_port" "$device" "$seconddns_tcp_server" "$ipv6_server" "$ARGS"
}
conf_append_conf_files()
@@ -547,16 +496,8 @@ load_service()
config_get port "$section" "port" "53"
config_get ipv6_server "$section" "ipv6_server" "1"
config_get tcp_server "$section" "tcp_server" "1"
config_get tls_server "$section" "tls_server" "0"
config_get tls_server_port "$section" "tls_server_port" "853"
config_get doh_server "$section" "doh_server" "0"
config_get doh_server_port "$section" "doh_server_port" "843"
config_get bind_cert "$section" "bind_cert" ""
config_get bind_cert_key "$section" "bind_cert_key" ""
config_get bind_cert_key_pass "$section" "bind_cert_key_pass" ""
config_get server_flags "$section" "server_flags" ""
config_get auto_update_week_time "$section" "auto_update_week_time" "*"
config_get auto_update_day_time "$section" "auto_update_day_time" "5"
config_get speed_check_mode "$section" "speed_check_mode" ""
@@ -710,14 +651,7 @@ load_service()
[ "$auto_set_dnsmasq" = "0" ] && [ "$old_auto_set_dnsmasq" = "1" ] && stop_forward_dnsmasq "$old_port" "0"
}
conf_append_bind "bind" "$port" "$device" "$ipv6_server" "$server_flags"
[ "$tcp_server" = "1" ] && conf_append_bind "bind-tcp" "$port" "$device" "$ipv6_server" "$server_flags"
[ "$tls_server" = "1" ] && conf_append_bind "bind-tls" "$tls_server_port" "$device" "$ipv6_server" "$server_flags"
[ "$doh_server" = "1" ] && conf_append_bind "bind-https" "$doh_server_port" "$device" "$ipv6_server" "$server_flags"
[ ! -z "$bind_cert" ] && conf_append "bind-cert-file" "$bind_cert"
[ ! -z "$bind_cert_key" ] && conf_append "bind-cert-key-file" "$bind_cert_key"
[ ! -z "$bind_cert_key_pass" ] && conf_append "bind-cert-key-pass" "$bind_cert_key_pass"
conf_append_bind "$port" "$device" "$tcp_server" "$ipv6_server" "$server_flags"
load_second_server "$section"
@@ -729,8 +663,6 @@ load_service()
config_foreach load_domain_rule_list "domain-rule-list"
config_foreach load_IP_rule_list "ip-rule-list"
{
echo "conf-file $ADDRESS_CONF"
echo "conf-file $BLACKLIST_IP_CONF"

View File

@@ -48,7 +48,6 @@ build()
mkdir $ROOT/root/etc/init.d -p
mkdir $ROOT/root/etc/smartdns/ -p
mkdir $ROOT/root/etc/smartdns/domain-set/ -p
mkdir $ROOT/root/etc/smartdns/ip-set/ -p
mkdir $ROOT/root/etc/smartdns/conf.d/ -p
cp $SMARTDNS_CONF $ROOT/root/etc/smartdns/

View File

@@ -340,12 +340,9 @@ case "$1" in
exit 1
fi
SMARTDNS_OPTION=""
[ "$SMARTDNS_CRASH_RESTART" = "1" ] && SMARTDNS_OPTION="$SMARTDNS_OPTION -R"
set_smartdns_port
get_tz
$SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID $SMARTDNS_OPTION
$SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID
if [ $? -ne 0 ]; then
clear_rule
exit 1

View File

@@ -5,7 +5,4 @@
SMARTDNS_WORKMODE="1"
# smartdns port
SMARTDNS_PORT="535"
# restart when crash
SMARTDNS_CRASH_RESTART="1"
SMARTDNS_PORT="535"

View File

@@ -15,8 +15,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
BIN=smartdns
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/timer_wheel.o lib/idna.o lib/conf.o lib/nftset.o
OBJS_MAIN=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o http_parse.o proxy.o timer.o
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/timer_wheel.o
OBJS_MAIN=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o http_parse.o proxy.o timer.o lib/conf.o lib/nftset.o
OBJS=$(OBJS_MAIN) $(OBJS_LIB)
# cflags
@@ -28,7 +28,7 @@ ifndef CFLAGS
endif
CFLAGS +=-Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing -funwind-tables -Wmissing-prototypes -Wshadow -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough
endif
override CFLAGS +=-Iinclude -I/home/rock/code/build/openssl/openssl-3.2.0/include
override CFLAGS +=-Iinclude
override CFLAGS += -DBASE_FILE_NAME='"$(notdir $<)"'
override CFLAGS += $(EXTRA_CFLAGS)
ifdef VER
@@ -40,7 +40,7 @@ override CXXFLAGS +=-Iinclude
# ldflags
ifeq ($(STATIC), yes)
override LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static -L/home/rock/code/build/openssl/openssl-3.2.0
override LDFLAGS += -lssl -lcrypto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -ldl -static
else
override LDFLAGS += -lssl -lcrypto -lpthread -ldl
endif

191
src/dns.c
View File

@@ -738,14 +738,14 @@ static int _dns_add_opt_RAW(struct dns_packet *packet, dns_opt_code_t opt_rrtype
struct dns_opt *opt = (struct dns_opt *)opt_data;
int len = 0;
opt->code = opt_rrtype;
opt->code = DNS_OPT_T_TCP_KEEPALIVE;
opt->length = sizeof(unsigned short);
memcpy(opt->data, raw, raw_len);
len += raw_len;
len += sizeof(*opt);
return _dns_add_RAW(packet, DNS_RRS_OPT, (dns_type_t)opt_rrtype, "", 0, opt_data, len);
return _dns_add_RAW(packet, DNS_RRS_OPT, (dns_type_t)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,
@@ -1030,7 +1030,7 @@ int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
return _dns_add_RAW(packet, DNS_RRS_OPT, (dns_type_t)DNS_OPT_T_ECS, "", 0, opt_data, len);
}
int dns_get_OPT_ECS(struct dns_rrs *rrs, 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)
{
unsigned char opt_data[DNS_MAX_OPT_LEN];
char domain[DNS_MAX_CNAME_LEN] = {0};
@@ -1067,16 +1067,16 @@ int dns_add_OPT_TCP_KEEPALIVE(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_KEEPALIVE(struct dns_rrs *rrs, unsigned short *timeout)
int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len,
unsigned short *timeout)
{
unsigned char opt_data[DNS_MAX_OPT_LEN];
char domain[DNS_MAX_CNAME_LEN] = {0};
struct dns_opt *opt = (struct dns_opt *)opt_data;
int len = DNS_MAX_OPT_LEN;
int ttl = 0;
unsigned char *data = NULL;
if (_dns_get_opt_RAW(rrs, domain, DNS_MAX_CNAME_LEN, &ttl, opt, &len) != 0) {
if (_dns_get_opt_RAW(rrs, NULL, 0, &ttl, opt, &len) != 0) {
return -1;
}
@@ -1104,60 +1104,6 @@ int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *timeout)
return 0;
}
int dns_add_SRV(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, int priority, int weight,
int port, const char *target)
{
unsigned char data[DNS_MAX_CNAME_LEN];
unsigned char *data_ptr = data;
int target_len = 0;
if (target == NULL) {
target = "";
}
target_len = strnlen(target, DNS_MAX_CNAME_LEN) + 1;
memcpy(data_ptr, &priority, sizeof(unsigned short));
data_ptr += sizeof(unsigned short);
memcpy(data_ptr, &weight, sizeof(unsigned short));
data_ptr += sizeof(unsigned short);
memcpy(data_ptr, &port, sizeof(unsigned short));
data_ptr += sizeof(unsigned short);
if (data_ptr - data + target_len >= DNS_MAX_CNAME_LEN) {
return -1;
}
safe_strncpy((char *)data_ptr, target, target_len);
data_ptr += target_len;
return _dns_add_RAW(packet, type, DNS_T_SRV, domain, ttl, data, data_ptr - data);
}
int dns_get_SRV(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned short *priority,
unsigned short *weight, unsigned short *port, char *target, int target_size)
{
unsigned char data[DNS_MAX_CNAME_LEN];
unsigned char *ptr = data;
int len = sizeof(data);
if (_dns_get_RAW(rrs, domain, maxsize, ttl, data, &len) != 0) {
return -1;
}
if (len < 6) {
return -1;
}
memcpy(priority, ptr, sizeof(unsigned short));
ptr += sizeof(unsigned short);
memcpy(weight, ptr, sizeof(unsigned short));
ptr += sizeof(unsigned short);
memcpy(port, ptr, sizeof(unsigned short));
ptr += sizeof(unsigned short);
safe_strncpy(target, (char *)ptr, target_size);
return 0;
}
int dns_add_HTTPS_start(struct dns_rr_nested *svcparam_buffer, struct dns_packet *packet, dns_rr_type type,
const char *domain, int ttl, int priority, const char *target)
{
@@ -1667,26 +1613,6 @@ static int _dns_encode_CNAME(struct dns_context *context, struct dns_rrs *rrs)
return 0;
}
static int _dns_decode_SRV(struct dns_context *context, unsigned short *priority, unsigned short *weight,
unsigned short *port, char *target, int target_size)
{
int ret = 0;
if (_dns_left_len(context) < 6) {
return -1;
}
*priority = _dns_read_short(&context->ptr);
*weight = _dns_read_short(&context->ptr);
*port = _dns_read_short(&context->ptr);
ret = _dns_decode_domain(context, target, target_size);
if (ret < 0) {
return -1;
}
return 0;
}
static int _dns_decode_SOA(struct dns_context *context, struct dns_soa *soa)
{
int ret = 0;
@@ -1776,54 +1702,6 @@ static int _dns_encode_SOA(struct dns_context *context, struct dns_rrs *rrs)
return 0;
}
static int _dns_encode_SRV(struct dns_context *context, struct dns_rrs *rrs)
{
int ret = 0;
int qtype = 0;
int qclass = 0;
int ttl = 0;
char domain[DNS_MAX_CNAME_LEN];
int rr_len = 0;
unsigned char *rr_len_ptr = NULL;
struct dns_context data_context;
_dns_init_context_by_rrs(rrs, &data_context);
ret = _dns_get_rr_head(&data_context, domain, DNS_MAX_CNAME_LEN, &qtype, &qclass, &ttl, &rr_len);
if (ret < 0) {
return -1;
}
ret = _dns_encode_rr_head(context, domain, qtype, qclass, ttl, rr_len, &rr_len_ptr);
if (ret < 0) {
return -1;
}
rr_len = 0;
if (_dns_left_len(context) < 6) {
return -1;
}
_dns_write_short(&context->ptr, *(unsigned short *)data_context.ptr);
data_context.ptr += 2;
_dns_write_short(&context->ptr, *(unsigned short *)data_context.ptr);
data_context.ptr += 2;
_dns_write_short(&context->ptr, *(unsigned short *)data_context.ptr);
data_context.ptr += 2;
rr_len += 6;
ret = _dns_encode_domain(context, (char *)data_context.ptr);
if (ret < 0) {
return -1;
}
rr_len += ret;
data_context.ptr += strnlen((char *)(data_context.ptr), DNS_MAX_CNAME_LEN) + 1;
_dns_write_short(&rr_len_ptr, rr_len);
return 0;
}
static int _dns_decode_opt_ecs(struct dns_context *context, struct dns_opt_ecs *ecs, int opt_len)
{
int len = 0;
@@ -1879,23 +1757,6 @@ static int _dns_decode_opt_cookie(struct dns_context *context, struct dns_opt_co
return 0;
}
static int _dns_decode_opt_tcp_keepalive(struct dns_context *context, unsigned short *timeout, int opt_len)
{
if (opt_len == 0) {
*timeout = 0;
return 0;
}
if (opt_len < (int)sizeof(unsigned short)) {
return -1;
}
*timeout = _dns_read_short(&context->ptr);
tlog(TLOG_DEBUG, "OPT TCP KEEPALIVE %u", *timeout);
return 0;
}
static int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs)
{
int ret = 0;
@@ -2014,7 +1875,7 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
unsigned short opt_code = 0;
unsigned short opt_len = 0;
unsigned short errcode = (ttl >> 16) & 0xFFFF;
unsigned short ever = (ttl) & 0xFFFF;
unsigned short ever = (ttl)&0xFFFF;
unsigned char *start = context->ptr;
struct dns_packet *packet = context->packet;
int ret = 0;
@@ -2099,20 +1960,6 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
return -1;
}
} break;
case DNS_OPT_T_TCP_KEEPALIVE: {
unsigned short timeout = 0;
ret = _dns_decode_opt_tcp_keepalive(context, &timeout, opt_len);
if (ret != 0) {
tlog(TLOG_ERROR, "decode tcp keepalive failed.");
return -1;
}
ret = dns_add_OPT_TCP_KEEPALIVE(packet, timeout);
if (ret != 0) {
tlog(TLOG_ERROR, "add tcp keepalive failed.");
return -1;
}
} break;
case DNS_OPT_T_PADDING:
context->ptr += opt_len;
break;
@@ -2399,24 +2246,6 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
return -1;
}
} break;
case DNS_T_SRV: {
unsigned short priority = 0;
unsigned short weight = 0;
unsigned short port = 0;
char target[DNS_MAX_CNAME_LEN];
ret = _dns_decode_SRV(context, &priority, &weight, &port, target, DNS_MAX_CNAME_LEN);
if (ret < 0) {
tlog(TLOG_DEBUG, "decode SRV failed, %s", domain);
return -1;
}
ret = dns_add_SRV(packet, type, domain, ttl, priority, weight, port, target);
if (ret < 0) {
tlog(TLOG_DEBUG, "add SRV failed, %s", domain);
return -1;
}
} break;
case DNS_T_OPT: {
unsigned char *opt_start = context->ptr;
ret = _dns_decode_opt(context, type, ttl, rr_len);
@@ -2533,12 +2362,6 @@ static int _dns_encode_an(struct dns_context *context, struct dns_rrs *rrs)
return -1;
}
break;
case DNS_T_SRV:
ret = _dns_encode_SRV(context, rrs);
if (ret < 0) {
return -1;
}
break;
case DNS_T_HTTPS:
ret = _dns_encode_HTTPS(context, rrs);
if (ret < 0) {

View File

@@ -280,15 +280,11 @@ int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size);
int dns_get_OPT_payload_size(struct dns_packet *packet);
int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs);
int dns_get_OPT_ECS(struct dns_rrs *rrs, 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_KEEPALIVE(struct dns_packet *packet, unsigned short timeout);
int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *timeout);
int dns_add_SRV(struct dns_packet *packet, dns_rr_type type, const char *domain, int ttl, int priority, int weight,
int port, const char *target);
int dns_get_SRV(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, unsigned short *priority,
unsigned short *weight, unsigned short *port, char *target, int target_size);
int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len,
unsigned short *timeout);
/* the key must be added in orders, or dig will report FORMERR */
int dns_add_HTTPS_start(struct dns_rr_nested *svcparam_buffer, struct dns_packet *packet, dns_rr_type type,

View File

@@ -32,8 +32,6 @@
#define DNS_CACHE_HITNUM_STEP 3
#define DNS_CACHE_HITNUM_STEP_MAX 6
#define DNS_CACHE_READ_TIMEOUT 60
#define DNS_CACHE_FAIL_TIMEOUT (60 * 5)
#define EXPIRED_DOMAIN_PREFETCH_TIME (3600 * 8)
struct dns_cache_head {
struct hash_table cache_hash;
@@ -46,16 +44,11 @@ struct dns_cache_head {
typedef int (*dns_cache_read_callback)(struct dns_cache_record *cache_record, struct dns_cache_data *cache_data);
static int is_cache_init;
static struct dns_cache_head dns_cache_head;
int dns_cache_init(int size, dns_cache_callback timeout_callback)
{
int bits = 0;
if (is_cache_init == 1) {
return -1;
}
INIT_LIST_HEAD(&dns_cache_head.cache_list);
bits = ilog2(size) - 1;
@@ -71,7 +64,6 @@ int dns_cache_init(int size, dns_cache_callback timeout_callback)
dns_cache_head.timeout_callback = timeout_callback;
pthread_mutex_init(&dns_cache_head.lock, NULL);
is_cache_init = 1;
return 0;
}
@@ -119,6 +111,11 @@ static void _dns_cache_remove(struct dns_cache *dns_cache)
dns_cache_release(dns_cache);
}
enum CACHE_TYPE dns_cache_data_type(struct dns_cache_data *cache_data)
{
return cache_data->head.cache_type;
}
uint32_t dns_cache_get_query_flag(struct dns_cache *dns_cache)
{
return dns_cache->info.query_flag;
@@ -129,6 +126,83 @@ const char *dns_cache_get_dns_group_name(struct dns_cache *dns_cache)
return dns_cache->info.dns_group_name;
}
struct dns_cache_data *dns_cache_new_data_addr(void)
{
struct dns_cache_addr *cache_addr = malloc(sizeof(struct dns_cache_addr));
memset(cache_addr, 0, sizeof(struct dns_cache_addr));
if (cache_addr == NULL) {
return NULL;
}
cache_addr->head.cache_type = CACHE_TYPE_NONE;
cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head);
cache_addr->head.magic = MAGIC_CACHE_DATA;
atomic_set(&cache_addr->head.ref, 1);
return (struct dns_cache_data *)cache_addr;
}
void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, char *cname, int cname_ttl)
{
if (dns_cache == NULL) {
goto errout;
}
dns_cache->head.is_soa = 1;
if (dns_cache->head.cache_type == CACHE_TYPE_PACKET) {
return;
}
struct dns_cache_addr *cache_addr = (struct dns_cache_addr *)dns_cache;
if (cache_addr == NULL) {
goto errout;
}
memset(cache_addr->addr_data.addr, 0, sizeof(cache_addr->addr_data.addr));
if (cname) {
safe_strncpy(cache_addr->addr_data.cname, cname, DNS_MAX_CNAME_LEN);
cache_addr->addr_data.cname_ttl = cname_ttl;
}
cache_addr->addr_data.soa = 1;
cache_addr->head.cache_type = CACHE_TYPE_ADDR;
cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head);
errout:
return;
}
void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, char *cname, int cname_ttl, unsigned char *addr,
int addr_len)
{
if (dns_cache == NULL) {
goto errout;
}
struct dns_cache_addr *cache_addr = (struct dns_cache_addr *)dns_cache;
if (cache_addr == NULL) {
goto errout;
}
if (addr_len == DNS_RR_A_LEN) {
memcpy(cache_addr->addr_data.addr, addr, DNS_RR_A_LEN);
} else if (addr_len != DNS_RR_AAAA_LEN) {
memcpy(cache_addr->addr_data.addr, addr, DNS_RR_AAAA_LEN);
} else {
goto errout;
}
if (cname) {
safe_strncpy(cache_addr->addr_data.cname, cname, DNS_MAX_CNAME_LEN);
cache_addr->addr_data.cname_ttl = cname_ttl;
}
cache_addr->head.cache_type = CACHE_TYPE_ADDR;
cache_addr->head.size = sizeof(struct dns_cache_addr) - sizeof(struct dns_cache_data_head);
errout:
return;
}
struct dns_cache_data *dns_cache_new_data_packet(void *packet, size_t packet_len)
{
struct dns_cache_packet *cache_packet = NULL;
@@ -146,6 +220,7 @@ struct dns_cache_data *dns_cache_new_data_packet(void *packet, size_t packet_len
memcpy(cache_packet->data, packet, packet_len);
memset(&cache_packet->head, 0, sizeof(cache_packet->head));
cache_packet->head.cache_type = CACHE_TYPE_PACKET;
cache_packet->head.size = packet_len;
cache_packet->head.magic = MAGIC_CACHE_DATA;
atomic_set(&cache_packet->head.ref, 1);
@@ -153,13 +228,13 @@ struct dns_cache_data *dns_cache_new_data_packet(void *packet, size_t packet_len
return (struct dns_cache_data *)cache_packet;
}
static void dns_cache_timer_release(struct tw_base *base, struct tw_timer_list *timer, void *data)
static void dns_cache_timer_relase(struct tw_timer_list *timer, void *data)
{
struct dns_cache *dns_cache = data;
dns_cache_release(dns_cache);
}
static void dns_cache_expired(struct tw_base *base, struct tw_timer_list *timer, void *data, unsigned long timestamp)
static void dns_cache_expired(struct tw_timer_list *timer, void *data, unsigned long timestamp)
{
struct dns_cache *dns_cache = data;
@@ -169,18 +244,9 @@ static void dns_cache_expired(struct tw_base *base, struct tw_timer_list *timer,
}
if (dns_cache_head.timeout_callback) {
dns_cache_tmout_action_t tmout_act = dns_cache_head.timeout_callback(dns_cache);
switch (tmout_act) {
case DNS_CACHE_TMOUT_ACTION_OK:
break;
case DNS_CACHE_TMOUT_ACTION_DEL:
if (dns_cache_head.timeout_callback(dns_cache) != 0) {
dns_cache_release(dns_cache);
return;
case DNS_CACHE_TMOUT_ACTION_RETRY:
dns_timer_mod(&dns_cache->timer, DNS_CACHE_FAIL_TIMEOUT);
return;
default:
break;
}
}
@@ -188,8 +254,8 @@ static void dns_cache_expired(struct tw_base *base, struct tw_timer_list *timer,
dns_timer_mod(&dns_cache->timer, 5);
}
static int _dns_cache_replace(struct dns_cache_key *cache_key, int rcode, int ttl, int speed, int timeout,
int update_time, struct dns_cache_data *cache_data)
static int _dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int speed, int timeout, int update_time,
struct dns_cache_data *cache_data)
{
struct dns_cache *dns_cache = NULL;
struct dns_cache_data *old_cache_data = NULL;
@@ -201,7 +267,7 @@ static int _dns_cache_replace(struct dns_cache_key *cache_key, int rcode, int tt
/* lookup existing cache */
dns_cache = dns_cache_lookup(cache_key);
if (dns_cache == NULL) {
return -1;
return dns_cache_insert(cache_key, ttl, speed, timeout, cache_data);
}
if (ttl < DNS_CACHE_TTL_MIN) {
@@ -211,7 +277,6 @@ static int _dns_cache_replace(struct dns_cache_key *cache_key, int rcode, int tt
/* update cache data */
pthread_mutex_lock(&dns_cache_head.lock);
dns_cache->del_pending = 0;
dns_cache->info.rcode = rcode;
dns_cache->info.qtype = cache_key->qtype;
dns_cache->info.query_flag = cache_key->query_flag;
dns_cache->info.ttl = ttl;
@@ -238,10 +303,10 @@ static int _dns_cache_replace(struct dns_cache_key *cache_key, int rcode, int tt
return 0;
}
int dns_cache_replace(struct dns_cache_key *cache_key, int rcode, int ttl, int speed, int timeout, int update_time,
int dns_cache_replace(struct dns_cache_key *cache_key, int ttl, int speed, int timeout, int update_time,
struct dns_cache_data *cache_data)
{
return _dns_cache_replace(cache_key, rcode, ttl, speed, timeout, update_time, cache_data);
return _dns_cache_replace(cache_key, ttl, speed, timeout, update_time, cache_data);
}
static void _dns_cache_remove_by_domain(struct dns_cache_key *cache_key)
@@ -280,8 +345,7 @@ static void _dns_cache_remove_by_domain(struct dns_cache_key *cache_key)
pthread_mutex_unlock(&dns_cache_head.lock);
}
static int _dns_cache_insert(struct dns_cache_info *info, struct dns_cache_data *cache_data, struct list_head *head,
int timeout)
static int _dns_cache_insert(struct dns_cache_info *info, struct dns_cache_data *cache_data, struct list_head *head)
{
uint32_t key = 0;
struct dns_cache *dns_cache = NULL;
@@ -309,8 +373,8 @@ static int _dns_cache_insert(struct dns_cache_info *info, struct dns_cache_data
dns_cache->del_pending = 0;
dns_cache->cache_data = cache_data;
dns_cache->timer.function = dns_cache_expired;
dns_cache->timer.del_function = dns_cache_timer_release;
dns_cache->timer.expires = timeout;
dns_cache->timer.del_function = dns_cache_timer_relase;
dns_cache->timer.expires = info->timeout;
dns_cache->timer.data = dns_cache;
pthread_mutex_lock(&dns_cache_head.lock);
hash_table_add(dns_cache_head.cache_hash, &dns_cache->node, key);
@@ -333,13 +397,13 @@ static int _dns_cache_insert(struct dns_cache_info *info, struct dns_cache_data
return 0;
errout:
if (dns_cache) {
dns_cache_release(dns_cache);
free(dns_cache);
}
return -1;
}
int dns_cache_insert(struct dns_cache_key *cache_key, int rcode, int ttl, int speed, int timeout,
int dns_cache_insert(struct dns_cache_key *cache_key, int ttl, int speed, int timeout,
struct dns_cache_data *cache_data)
{
struct dns_cache_info info;
@@ -368,28 +432,10 @@ int dns_cache_insert(struct dns_cache_key *cache_key, int rcode, int ttl, int sp
info.speed = speed;
info.timeout = timeout;
info.is_visited = 1;
info.rcode = rcode;
time(&info.insert_time);
time(&info.replace_time);
return _dns_cache_insert(&info, cache_data, &dns_cache_head.cache_list, timeout);
}
int dns_cache_update_timer(struct dns_cache_key *key, int timeout)
{
struct dns_cache *dns_cache = dns_cache_lookup(key);
if (dns_cache == NULL) {
return -1;
}
pthread_mutex_lock(&dns_cache_head.lock);
dns_timer_mod(&dns_cache->timer, timeout);
dns_cache->del_pending = 0;
pthread_mutex_unlock(&dns_cache_head.lock);
dns_cache_release(dns_cache);
return 0;
return _dns_cache_insert(&info, cache_data, &dns_cache_head.cache_list);
}
struct dns_cache *dns_cache_lookup(struct dns_cache_key *cache_key)
@@ -456,6 +502,60 @@ int dns_cache_get_ttl(struct dns_cache *dns_cache)
return ttl;
}
int dns_cache_get_cname_ttl(struct dns_cache *dns_cache)
{
time_t now = 0;
int ttl = 0;
time(&now);
struct dns_cache_addr *cache_addr = (struct dns_cache_addr *)dns_cache_get_data(dns_cache);
if (cache_addr == NULL) {
ttl = 0;
goto out;
}
if (cache_addr->head.cache_type != CACHE_TYPE_ADDR) {
ttl = 0;
goto out;
}
ttl = dns_cache->info.insert_time + cache_addr->addr_data.cname_ttl - now;
if (ttl < 0) {
ttl = 0;
goto out;
}
int addr_ttl = dns_cache_get_ttl(dns_cache);
if (ttl < addr_ttl && ttl < 0) {
return addr_ttl;
}
if (ttl < 0) {
ttl = 0;
goto out;
}
out:
if (cache_addr) {
dns_cache_data_put((struct dns_cache_data *)cache_addr);
}
return ttl;
}
int dns_cache_is_soa(struct dns_cache *dns_cache)
{
if (dns_cache == NULL) {
return 0;
}
if (dns_cache->cache_data->head.is_soa) {
return 1;
}
return 0;
}
struct dns_cache_data *dns_cache_get_data(struct dns_cache *dns_cache)
{
struct dns_cache_data *cache_data;
@@ -494,11 +594,6 @@ int dns_cache_is_visited(struct dns_cache *dns_cache)
return dns_cache->info.is_visited;
}
int dns_cache_total_num(void)
{
return atomic_read(&dns_cache_head.num);
}
void dns_cache_delete(struct dns_cache *dns_cache)
{
pthread_mutex_lock(&dns_cache_head.lock);
@@ -542,32 +637,21 @@ static int _dns_cache_read_to_cache(struct dns_cache_record *cache_record, struc
struct list_head *head = NULL;
head = &dns_cache_head.cache_list;
struct dns_cache_info *info = &cache_record->info;
int expired_time = 0;
time_t now = time(NULL);
if (now < info->replace_time) {
info->replace_time = now;
}
expired_time = dns_conf_serve_expired_prefetch_time;
if (expired_time == 0) {
expired_time = dns_conf_serve_expired_ttl / 2;
if (expired_time == 0 || expired_time > EXPIRED_DOMAIN_PREFETCH_TIME) {
expired_time = EXPIRED_DOMAIN_PREFETCH_TIME;
}
}
unsigned int seed_tmp = now;
int passed_time = now - info->replace_time;
int timeout = info->timeout - passed_time;
if ((timeout > expired_time + info->ttl) && expired_time >= 0) {
timeout = expired_time + info->ttl;
}
if (timeout < DNS_CACHE_READ_TIMEOUT * 2) {
timeout = DNS_CACHE_READ_TIMEOUT + (rand() % DNS_CACHE_READ_TIMEOUT);
timeout = DNS_CACHE_READ_TIMEOUT + (rand_r(&seed_tmp) % DNS_CACHE_READ_TIMEOUT);
}
if (_dns_cache_insert(&cache_record->info, cache_data, head, timeout) != 0) {
if (timeout > dns_conf_serve_expired_ttl && dns_conf_serve_expired_ttl >= 0) {
timeout = dns_conf_serve_expired_ttl;
}
info->timeout = timeout;
if (_dns_cache_insert(&cache_record->info, cache_data, head) != 0) {
tlog(TLOG_ERROR, "insert cache data failed.");
cache_data = NULL;
goto errout;
@@ -831,25 +915,19 @@ void dns_cache_destroy(void)
struct dns_cache *dns_cache = NULL;
struct dns_cache *tmp = NULL;
if (is_cache_init == 0) {
return;
}
pthread_mutex_lock(&dns_cache_head.lock);
list_for_each_entry_safe(dns_cache, tmp, &dns_cache_head.cache_list, list)
{
_dns_cache_remove(dns_cache);
_dns_cache_delete(dns_cache);
}
pthread_mutex_unlock(&dns_cache_head.lock);
pthread_mutex_destroy(&dns_cache_head.lock);
hash_table_free(dns_cache_head.cache_hash, free);
is_cache_init = 0;
}
const char *dns_cache_file_version(void)
{
const char *version = "cache ver 1.3";
const char *version = "cache ver 1.2";
return version;
}

View File

@@ -40,8 +40,16 @@ extern "C" {
#define MAGIC_CACHE_DATA 0x61546144
#define MAGIC_RECORD 0x64526352
enum CACHE_TYPE {
CACHE_TYPE_NONE,
CACHE_TYPE_ADDR,
CACHE_TYPE_PACKET,
};
struct dns_cache_data_head {
enum CACHE_TYPE cache_type;
atomic_t ref;
int is_soa;
ssize_t size;
uint32_t magic;
};
@@ -76,7 +84,6 @@ struct dns_cache_info {
char dns_group_name[DNS_GROUP_NAME_LEN];
uint32_t query_flag;
int ttl;
int rcode;
int hitnum;
int speed;
int timeout;
@@ -118,34 +125,25 @@ struct dns_cache_key {
uint32_t query_flag;
};
enum CACHE_TYPE dns_cache_data_type(struct dns_cache_data *cache_data);
uint32_t dns_cache_get_query_flag(struct dns_cache *dns_cache);
const char *dns_cache_get_dns_group_name(struct dns_cache *dns_cache);
struct dns_cache_data *dns_cache_new_data_packet(void *packet, size_t packet_len);
typedef enum DNS_CACHE_TMOUT_ACTION {
DNS_CACHE_TMOUT_ACTION_OK = 0,
DNS_CACHE_TMOUT_ACTION_DEL = 1,
DNS_CACHE_TMOUT_ACTION_RETRY = 2,
} dns_cache_tmout_action_t;
typedef dns_cache_tmout_action_t (*dns_cache_callback)(struct dns_cache *dns_cache);
typedef int (*dns_cache_callback)(struct dns_cache *dns_cache);
int dns_cache_init(int size, dns_cache_callback timeout_callback);
int dns_cache_replace(struct dns_cache_key *key, int rcode, int ttl, int speed, int timeout, int update_time,
int dns_cache_replace(struct dns_cache_key *key, int ttl, int speed, int tiemout, int update_time,
struct dns_cache_data *cache_data);
int dns_cache_insert(struct dns_cache_key *key, int rcode, int ttl, int speed, int timeout,
struct dns_cache_data *cache_data);
int dns_cache_insert(struct dns_cache_key *key, int ttl, int speed, int timeout, struct dns_cache_data *cache_data);
struct dns_cache *dns_cache_lookup(struct dns_cache_key *key);
int dns_cache_total_num(void);
int dns_cache_update_timer(struct dns_cache_key *key, int timeout);
void dns_cache_delete(struct dns_cache *dns_cache);
void dns_cache_get(struct dns_cache *dns_cache);
@@ -160,12 +158,23 @@ void dns_cache_update(struct dns_cache *dns_cache);
int dns_cache_get_ttl(struct dns_cache *dns_cache);
int dns_cache_get_cname_ttl(struct dns_cache *dns_cache);
int dns_cache_is_soa(struct dns_cache *dns_cache);
struct dns_cache_data *dns_cache_new_data_addr(void);
struct dns_cache_data *dns_cache_get_data(struct dns_cache *dns_cache);
void dns_cache_data_get(struct dns_cache_data *cache_data);
void dns_cache_data_put(struct dns_cache_data *cache_data);
void dns_cache_set_data_addr(struct dns_cache_data *dns_cache, char *cname, int cname_ttl, unsigned char *addr,
int addr_len);
void dns_cache_set_data_soa(struct dns_cache_data *dns_cache, char *cname, int cname_ttl);
void dns_cache_destroy(void);
int dns_cache_load(const char *file);

View File

@@ -61,7 +61,7 @@
#define DNS_TCP_BUFFER (32 * 1024)
#define DNS_TCP_IDLE_TIMEOUT (60 * 10)
#define DNS_TCP_CONNECT_TIMEOUT (5)
#define DNS_QUERY_TIMEOUT (3000)
#define DNS_QUERY_TIMEOUT (500)
#define DNS_QUERY_RETRY (4)
#define DNS_PENDING_SERVER_RETRY 60
#define SOCKET_PRIORITY (6)
@@ -93,7 +93,7 @@ struct dns_server_info {
/* server ping handle */
struct ping_host_struct *ping_host;
char ip[DNS_MAX_HOSTNAME];
char ip[DNS_HOSTNAME_LEN];
int port;
char proxy_name[DNS_HOSTNAME_LEN];
/* server type */
@@ -107,7 +107,6 @@ struct dns_server_info {
int ttl_range;
SSL *ssl;
int ssl_write_len;
int ssl_want_write;
SSL_CTX *ssl_ctx;
SSL_SESSION *ssl_session;
@@ -268,7 +267,7 @@ struct dns_query_struct {
/* replied hash table */
DECLARE_HASHTABLE(replied_map, 4);
};
static int is_client_init;
static struct dns_client client;
static LIST_HEAD(pending_servers);
static pthread_mutex_t pending_server_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -423,9 +422,6 @@ static const char *_dns_server_get_type_string(dns_server_type_t type)
case DNS_SERVER_HTTPS:
type_str = "https";
break;
case DNS_SERVER_QUIC:
type_str = "quic";
break;
default:
break;
}
@@ -866,7 +862,6 @@ static char *_dns_client_server_get_tls_host_verify(struct dns_server_info *serv
struct client_dns_server_flag_https *flag_https = &server_info->flags.https;
tls_host_verify = flag_https->tls_host_verify;
} break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
tls_host_verify = flag_tls->tls_host_verify;
@@ -899,7 +894,6 @@ static char *_dns_client_server_get_spki(struct dns_server_info *server_info, in
spki = flag_https->spki;
*spki_len = flag_https->spi_len;
} break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &server_info->flags.tls;
spki = flag_tls->spki;
@@ -960,7 +954,7 @@ static int _dns_client_set_trusted_cert(SSL_CTX *ssl_ctx)
return 0;
}
static SSL_CTX *_ssl_ctx_get(int is_quic)
static SSL_CTX *_ssl_ctx_get(void)
{
pthread_mutex_lock(&client.server_list_lock);
SSL_CTX *ssl_ctx = client.ssl_ctx;
@@ -970,18 +964,7 @@ static SSL_CTX *_ssl_ctx_get(int is_quic)
}
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
#if (OPENSSL_VERSION_NUMBER >= 0x30200000L)
if (is_quic) {
ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
} else {
ssl_ctx = SSL_CTX_new(TLS_client_method());
}
#else
if (is_quic) {
return NULL;
}
ssl_ctx = SSL_CTX_new(TLS_client_method());
#endif
#else
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
#endif
@@ -1068,12 +1051,6 @@ 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_QUIC: {
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
spki_data_len = flag_tls->spi_len;
sock_type = SOCK_DGRAM;
skip_check_cert = flag_tls->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;
@@ -1146,12 +1123,8 @@ static int _dns_client_server_add(char *server_ip, char *server_host, int port,
}
/* if server type is TLS, create ssl context */
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS || server_type == DNS_SERVER_QUIC) {
if (server_type == DNS_SERVER_QUIC) {
server_info->ssl_ctx = _ssl_ctx_get(1);
} else {
server_info->ssl_ctx = _ssl_ctx_get(0);
}
if (server_type == DNS_SERVER_TLS || server_type == DNS_SERVER_HTTPS) {
server_info->ssl_ctx = _ssl_ctx_get();
if (server_info->ssl_ctx == NULL) {
tlog(TLOG_ERROR, "init ssl failed.");
goto errout;
@@ -1263,7 +1236,6 @@ static void _dns_client_shutdown_socket(struct dns_server_info *server_info)
shutdown(server_info->fd, SHUT_RDWR);
}
break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS:
case DNS_SERVER_HTTPS:
if (server_info->ssl) {
@@ -1826,7 +1798,7 @@ static int _dns_client_create_socket_udp_proxy(struct dns_server_info *server_in
}
set_fd_nonblock(fd, 1);
set_sock_keepalive(fd, 30, 3, 5);
set_sock_keepalive(fd, 15, 3, 4);
ret = proxy_conn_connect(proxy);
if (ret != 0) {
@@ -1977,7 +1949,7 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
setsockopt(fd, IPPROTO_IP, IP_TOS, &ip_tos, sizeof(ip_tos));
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, 30, 3, 5);
set_sock_keepalive(fd, 15, 3, 4);
if (proxy) {
ret = proxy_conn_connect(proxy);
@@ -2025,138 +1997,6 @@ errout:
return -1;
}
static int _DNS_client_create_socket_quic(struct dns_server_info *server_info, char *hostname)
{
#ifdef OSSL_QUIC1_VERSION
int fd = 0;
struct epoll_event event;
SSL *ssl = NULL;
struct proxy_conn *proxy = NULL;
int ret = -1;
if (server_info->ssl_ctx == NULL) {
tlog(TLOG_ERROR, "create ssl ctx failed, %s", server_info->ip);
goto errout;
}
if (server_info->proxy_name[0] != '\0') {
proxy = proxy_conn_new(server_info->proxy_name, server_info->ip, server_info->port, 1);
if (proxy == NULL) {
tlog(TLOG_ERROR, "create proxy failed, %s, proxy: %s", server_info->ip, server_info->proxy_name);
goto errout;
}
fd = proxy_conn_get_fd(proxy);
} else {
fd = socket(server_info->ai_family, SOCK_DGRAM, IPPROTO_UDP);
}
ssl = SSL_new(server_info->ssl_ctx);
if (ssl == NULL) {
tlog(TLOG_ERROR, "new ssl failed, %s", server_info->ip);
goto errout;
}
if (fd < 0) {
tlog(TLOG_ERROR, "create socket failed, %s", strerror(errno));
goto errout;
}
if (set_fd_nonblock(fd, 1) != 0) {
tlog(TLOG_ERROR, "set socket non block failed, %s", strerror(errno));
goto errout;
}
if (server_info->so_mark >= 0) {
unsigned int so_mark = server_info->so_mark;
if (setsockopt(fd, SOL_SOCKET, SO_MARK, &so_mark, sizeof(so_mark)) != 0) {
tlog(TLOG_DEBUG, "set socket mark failed, %s", strerror(errno));
}
}
if (proxy) {
ret = proxy_conn_connect(proxy);
} else {
ret = connect(fd, &server_info->addr, server_info->ai_addrlen);
}
if (ret != 0) {
if (errno != EINPROGRESS) {
tlog(TLOG_DEBUG, "connect %s failed, %s", server_info->ip, strerror(errno));
goto errout;
}
}
SSL_set_connect_state(ssl);
SSL_set_blocking_mode(ssl, 0);
if (SSL_set_fd(ssl, fd) == 0) {
tlog(TLOG_ERROR, "ssl set fd failed.");
goto errout;
}
/* reuse ssl session */
if (server_info->ssl_session) {
SSL_set_session(ssl, server_info->ssl_session);
}
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);
}
SSL_set1_host(ssl, hostname);
static const unsigned char alpn[] = {3, 'd', 'o', 'q'};
if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {
tlog(TLOG_INFO, "SSL_set_alpn_protos failed.");
goto errout;
}
server_info->fd = fd;
server_info->ssl = ssl;
server_info->ssl_write_len = -1;
server_info->status = DNS_SERVER_STATUS_CONNECTING;
server_info->proxy = proxy;
memset(&event, 0, sizeof(event));
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.");
goto errout;
}
tlog(TLOG_DEBUG, "tls server %s connecting.\n", server_info->ip);
return 0;
errout:
if (server_info->fd > 0) {
server_info->fd = -1;
}
if (server_info->ssl) {
server_info->ssl = NULL;
}
server_info->status = DNS_SERVER_STATUS_INIT;
if (fd > 0 && proxy == NULL) {
close(fd);
}
if (ssl) {
SSL_free(ssl);
}
if (proxy) {
proxy_conn_free(proxy);
}
return -1;
#else
return -1;
#endif
}
static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, char *hostname)
{
int fd = 0;
@@ -2216,7 +2056,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info, ch
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, 30, 3, 5);
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));
@@ -2309,10 +2149,6 @@ static int _dns_client_create_socket(struct dns_server_info *server_info)
struct client_dns_server_flag_tls *flag_tls = NULL;
flag_tls = &server_info->flags.tls;
return _DNS_client_create_socket_tls(server_info, flag_tls->hostname);
} else if (server_info->type == DNS_SERVER_QUIC) {
struct client_dns_server_flag_tls *flag_tls = NULL;
flag_tls = &server_info->flags.tls;
return _DNS_client_create_socket_quic(server_info, flag_tls->hostname);
} else if (server_info->type == DNS_SERVER_HTTPS) {
struct client_dns_server_flag_https *flag_https = NULL;
flag_https = &server_info->flags.https;
@@ -2538,16 +2374,16 @@ static int _dns_client_socket_ssl_send(struct dns_server_info *server, const voi
ssl_ret = _ssl_get_error(server, ret);
switch (ssl_ret) {
case SSL_ERROR_NONE:
case SSL_ERROR_ZERO_RETURN:
return 0;
break;
case SSL_ERROR_ZERO_RETURN:
case SSL_ERROR_WANT_READ:
errno = EAGAIN;
ret = -SSL_ERROR_WANT_READ;
ret = -1;
break;
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
ret = -SSL_ERROR_WANT_WRITE;
ret = -1;
break;
case SSL_ERROR_SSL:
ssl_err = ERR_get_error();
@@ -2587,7 +2423,7 @@ static int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *buf
}
ret = _ssl_read(server, buf, num);
if (ret > 0) {
if (ret >= 0) {
return ret;
}
@@ -2599,11 +2435,11 @@ static int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *buf
break;
case SSL_ERROR_WANT_READ:
errno = EAGAIN;
ret = -SSL_ERROR_WANT_READ;
ret = -1;
break;
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
ret = -SSL_ERROR_WANT_WRITE;
ret = -1;
break;
case SSL_ERROR_SSL:
ssl_err = ERR_get_error();
@@ -2617,13 +2453,7 @@ static int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *buf
return 0;
}
#ifdef SSL_R_UNEXPECTED_EOF_WHILE_READING
if (ssl_reason == SSL_R_UNEXPECTED_EOF_WHILE_READING) {
return 0;
}
#endif
tlog(TLOG_WARN, "SSL read fail error no: %s(%lx), reason: %d\n", ERR_reason_error_string(ssl_err), ssl_err, ssl_reason);
tlog(TLOG_INFO, "SSL read fail error no: %s(%lx), len: %d\n", ERR_reason_error_string(ssl_err), ssl_err, num);
errno = EFAULT;
ret = -1;
break;
@@ -2632,6 +2462,9 @@ static int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *buf
return 0;
}
if (errno != ECONNRESET) {
tlog(TLOG_INFO, "SSL syscall failed, %s ", strerror(errno));
}
ret = -1;
return ret;
default:
@@ -2643,52 +2476,22 @@ static int _dns_client_socket_ssl_recv(struct dns_server_info *server, void *buf
return ret;
}
static int _dns_client_ssl_poll_event(struct dns_server_info *server_info, int ssl_ret)
{
struct epoll_event fd_event;
memset(&fd_event, 0, sizeof(fd_event));
if (ssl_ret == SSL_ERROR_WANT_READ) {
fd_event.events = EPOLLIN;
} else if (ssl_ret == SSL_ERROR_WANT_WRITE) {
fd_event.events = EPOLLOUT | EPOLLIN;
} else {
goto errout;
}
fd_event.data.ptr = server_info;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_MOD, server_info->fd, &fd_event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
goto errout;
}
return 0;
errout:
return -1;
}
static int _dns_client_socket_send(struct dns_server_info *server_info)
{
if (server_info->type == DNS_SERVER_UDP) {
return -1;
} 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 ||
server_info->type == DNS_SERVER_QUIC) {
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
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;
}
server_info->ssl_want_write = 0;
int ret = _dns_client_socket_ssl_send(server_info, server_info->send_buff.data, write_len);
if (ret < 0 && errno == EAGAIN) {
server_info->ssl_write_len = write_len;
if (_dns_client_ssl_poll_event(server_info, SSL_ERROR_WANT_WRITE) == 0) {
errno = EAGAIN;
if (ret != 0) {
if (errno == EAGAIN) {
server_info->ssl_write_len = write_len;
}
}
return ret;
@@ -2704,18 +2507,9 @@ static int _dns_client_socket_recv(struct dns_server_info *server_info)
} 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);
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
server_info->type == DNS_SERVER_QUIC) {
int ret = _dns_client_socket_ssl_recv(server_info, server_info->recv_buff.data + server_info->recv_buff.len,
DNS_TCP_BUFFER - server_info->recv_buff.len);
if (ret == -SSL_ERROR_WANT_WRITE && errno == EAGAIN) {
if (_dns_client_ssl_poll_event(server_info, SSL_ERROR_WANT_WRITE) == 0) {
errno = EAGAIN;
server_info->ssl_want_write = 1;
}
}
return ret;
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
return _dns_client_socket_ssl_recv(server_info, server_info->recv_buff.data + server_info->recv_buff.len,
DNS_TCP_BUFFER - server_info->recv_buff.len);
} else {
return -1;
}
@@ -2838,7 +2632,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
goto errout;
}
tlog(TLOG_WARN, "recv failed, server %s:%d, %s\n", server_info->ip, server_info->port, strerror(errno));
tlog(TLOG_ERROR, "recv failed, server %s:%d, %s\n", server_info->ip, server_info->port, strerror(errno));
goto errout;
}
@@ -2880,7 +2674,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e
server_info->status = DNS_SERVER_STATUS_DISCONNECTED;
}
if (server_info->send_buff.len > 0 || server_info->ssl_want_write == 1) {
if (server_info->send_buff.len > 0) {
/* send existing send_buffer data */
len = _dns_client_socket_send(server_info);
if (len < 0) {
@@ -3178,11 +2972,16 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
if (ret <= 0) {
memset(&fd_event, 0, sizeof(fd_event));
ssl_ret = _ssl_get_error(server_info, ret);
if (_dns_client_ssl_poll_event(server_info, ssl_ret) == 0) {
return 0;
}
if (ssl_ret != SSL_ERROR_SYSCALL) {
if (ssl_ret == SSL_ERROR_WANT_READ) {
fd_event.events = EPOLLIN;
} else if (ssl_ret == SSL_ERROR_WANT_WRITE) {
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,
@@ -3190,10 +2989,13 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e
goto errout;
}
if (errno != ENETUNREACH) {
tlog(TLOG_WARN, "Handshake with %s failed, %s", server_info->ip, strerror(errno));
fd_event.data.ptr = server_info;
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_MOD, server_info->fd, &fd_event) != 0) {
tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
goto errout;
}
goto errout;
return 0;
}
tlog(TLOG_DEBUG, "tls server %s connected.\n", server_info->ip);
@@ -3323,8 +3125,7 @@ static int _dns_client_process(struct dns_server_info *server_info, struct epoll
} else if (server_info->type == DNS_SERVER_TCP) {
/* receive from tcp */
return _dns_client_process_tcp(server_info, event, now);
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS ||
server_info->type == DNS_SERVER_QUIC) {
} else if (server_info->type == DNS_SERVER_TLS || server_info->type == DNS_SERVER_HTTPS) {
/* receive from tls */
return _dns_client_process_tls(server_info, event, now);
} else {
@@ -3526,8 +3327,7 @@ static int _dns_client_send_https(struct dns_server_info *server_info, void *pac
http_len = snprintf((char *)inpacket, DNS_IN_PACKSIZE,
"POST %s HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: smartdns\r\n"
"Content-Type: application/dns-message\r\n"
"content-type: application/dns-message\r\n"
"Content-Length: %d\r\n"
"\r\n",
https_flag->path, https_flag->httphost, len);
@@ -3560,11 +3360,6 @@ static int _dns_client_send_https(struct dns_server_info *server_info, void *pac
return 0;
}
static int _dns_client_send_quic(struct dns_server_info *server_info, void *packet, unsigned short len)
{
return _dns_client_send_tls(server_info, packet, len);
}
static int _dns_client_setup_server_packet(struct dns_server_info *server_info, struct dns_query_struct *query,
void *default_packet, int default_packet_len,
unsigned char *packet_data_buffer, void **packet_data, int *packet_data_len)
@@ -3620,11 +3415,7 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
}
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
if (server_info->type != DNS_SERVER_UDP) {
dns_add_OPT_TCP_KEEPALIVE(packet, 6000);
}
/* dns_add_OPT_TCP_KEEPALIVE(packet, 600); */
if ((query->qtype == DNS_T_A && server_info->ecs_ipv4.enable)) {
dns_add_OPT_ECS(packet, &server_info->ecs_ipv4.ecs);
} else if ((query->qtype == DNS_T_AAAA && server_info->ecs_ipv6.enable)) {
@@ -3698,7 +3489,7 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
}
}
total_server++;
tlog(TLOG_DEBUG, "send query to server %s:%d", server_info->ip, server_info->port);
tlog(TLOG_DEBUG, "send query to server %s", server_info->ip);
if (server_info->fd <= 0) {
ret = _dns_client_create_socket(server_info);
if (ret != 0) {
@@ -3738,11 +3529,6 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
ret = _dns_client_send_https(server_info, packet_data, packet_data_len);
send_err = errno;
break;
case DNS_SERVER_QUIC:
/* quic query */
ret = _dns_client_send_quic(server_info, packet_data, packet_data_len);
send_err = errno;
break;
default:
/* unsupported query type */
ret = -1;
@@ -3841,7 +3627,7 @@ static int _dns_client_send_query(struct dns_query_struct *query)
}
dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
/* dns_add_OPT_TCP_KEEPALIVE(packet, 1200); */
/* dns_add_OPT_TCP_KEEPALIVE(packet, 600); */
if (_dns_client_dns_add_ecs(query, packet) != 0) {
tlog(TLOG_ERROR, "add ecs failed.");
return -1;
@@ -4575,14 +4361,12 @@ int dns_client_init(void)
int fd_wakeup = -1;
int ret = 0;
if (is_client_init == 1) {
return -1;
}
if (client.epoll_fd > 0) {
return -1;
}
srandom(time(NULL));
memset(&client, 0, sizeof(client));
pthread_attr_init(&attr);
atomic_set(&client.dns_server_num, 0);
@@ -4626,7 +4410,6 @@ int dns_client_init(void)
}
client.fd_wakeup = fd_wakeup;
is_client_init = 1;
return 0;
errout:
@@ -4653,10 +4436,6 @@ errout:
void dns_client_exit(void)
{
if (is_client_init == 0) {
return;
}
if (client.tid) {
void *ret = NULL;
atomic_set(&client.run, 0);
@@ -4678,6 +4457,4 @@ void dns_client_exit(void)
SSL_CTX_free(client.ssl_ctx);
client.ssl_ctx = NULL;
}
is_client_init = 0;
}

View File

@@ -33,7 +33,6 @@ typedef enum {
DNS_SERVER_TCP,
DNS_SERVER_TLS,
DNS_SERVER_HTTPS,
DNS_SERVER_QUIC,
DNS_SERVER_TYPE_END,
} dns_server_type_t;

View File

@@ -17,16 +17,13 @@
*/
#include "dns_conf.h"
#include "idna.h"
#include "list.h"
#include "rbtree.h"
#include "tlog.h"
#include "util.h"
#include <errno.h>
#include <getopt.h>
#include <glob.h>
#include <libgen.h>
#include <openssl/ssl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -67,9 +64,6 @@ int dns_hosts_record_num;
/* DNS64 */
struct dns_dns64 dns_conf_dns_dns64;
/* SRV-HOST */
struct dns_srv_record_table dns_conf_srv_record_table;
/* server ip/port */
struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
int dns_conf_bind_ip_num = 0;
@@ -128,7 +122,7 @@ char dns_conf_ca_path[DNS_MAX_PATH];
char dns_conf_cache_file[DNS_MAX_PATH];
int dns_conf_cache_persist = 2;
int dns_conf_cache_checkpoint_time = DNS_DEFAULT_CHECKPOINT_TIME;
int dns_conf_cache_checkpoint_time;
/* auditing */
int dns_conf_audit_enable = 0;
@@ -172,12 +166,6 @@ char dns_resolv_file[DNS_MAX_PATH];
int dns_no_pidfile;
int dns_no_daemon;
struct hash_table conf_file_table;
struct conf_file_path {
struct hlist_node node;
char file[DNS_MAX_PATH];
};
/* ECS */
struct dns_edns_client_subnet dns_conf_ipv4_ecs;
struct dns_edns_client_subnet dns_conf_ipv6_ecs;
@@ -313,14 +301,8 @@ static int _get_domain(char *value, char *domain, int max_domain_size, char **pt
goto errout;
}
size_t domain_len = max_domain_size;
domain_len = utf8_to_punycode(begin, len, domain, domain_len);
if (domain_len <= 0) {
tlog(TLOG_ERROR, "domain name %s invalid", value);
goto errout;
}
domain[domain_len] = '\0';
memcpy(domain, begin, len);
domain[len] = '\0';
if (ptr_after_domain) {
*ptr_after_domain = end + 1;
@@ -509,26 +491,6 @@ static void _config_proxy_table_destroy(void)
}
}
static void _config_srv_record_table_destroy(void)
{
struct dns_srv_records *srv_records = NULL;
struct dns_srv_record *srv_record, *tmp1 = NULL;
struct hlist_node *tmp = NULL;
unsigned int i;
hash_for_each_safe(dns_conf_srv_record_table.srv, i, tmp, srv_records, node)
{
list_for_each_entry_safe(srv_record, tmp1, &srv_records->list, list)
{
list_del(&srv_record->list);
free(srv_record);
}
hlist_del_init(&srv_records->node);
free(srv_records);
}
}
static int _config_server(int argc, char *argv[], dns_server_type_t type, int default_port)
{
int index = dns_conf_server_num;
@@ -542,9 +504,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
unsigned char *spki = NULL;
int drop_packet_latency_ms = 0;
int is_bootstrap_dns = 0;
char host_ip[DNS_MAX_IPLEN] = {0};
int no_tls_host_name = 0;
int no_tls_host_verify = 0;
int is_hostip_set = 0;
int ttl = 0;
/* clang-format off */
@@ -601,9 +561,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
if (strcasecmp(scheme, "https") == 0) {
type = DNS_SERVER_HTTPS;
default_port = DEFAULT_DNS_HTTPS_PORT;
} else if (strcasecmp(scheme, "quic")) {
type = DNS_SERVER_QUIC;
default_port = DEFAULT_DNS_QUIC_PORT;
} else if (strcasecmp(scheme, "tls") == 0) {
type = DNS_SERVER_TLS;
default_port = DEFAULT_DNS_TLS_PORT;
@@ -619,12 +576,13 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
}
}
#ifndef OSSL_QUIC1_VERSION
if (type == DNS_SERVER_QUIC) {
tlog(TLOG_ERROR, "quic not support.");
return -1;
if (type == DNS_SERVER_HTTPS) {
safe_strncpy(server->hostname, server->server, sizeof(server->hostname));
safe_strncpy(server->httphost, server->server, sizeof(server->httphost));
if (server->path[0] == 0) {
safe_strncpy(server->path, "/", sizeof(server->path));
}
}
#endif
/* if port is not defined, set port to default 53 */
if (port == PORT_NOT_DEFINED) {
@@ -666,7 +624,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
case 'k': {
server->skip_check_cert = 1;
no_tls_host_verify = 1;
break;
}
case 'b': {
@@ -698,10 +655,10 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
break;
}
case 258: {
if (check_is_ipaddr(optarg) != 0) {
goto errout;
if (check_is_ipaddr(server->server) != 0) {
_conf_domain_rule_address(server->server, optarg);
is_hostip_set = 1;
}
safe_strncpy(host_ip, optarg, DNS_MAX_IPLEN);
break;
}
case 259: {
@@ -712,7 +669,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
safe_strncpy(server->hostname, optarg, DNS_MAX_CNAME_LEN);
if (strncmp(server->hostname, "-", 2) == 0) {
server->hostname[0] = '\0';
no_tls_host_name = 1;
}
break;
}
@@ -722,41 +678,28 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
}
case 262: {
safe_strncpy(server->tls_host_verify, optarg, DNS_MAX_CNAME_LEN);
if (strncmp(server->tls_host_verify, "-", 2) == 0) {
server->tls_host_verify[0] = '\0';
no_tls_host_verify = 1;
}
break;
}
default:
tlog(TLOG_WARN, "unknown server option: %s at '%s:%d'.", argv[optind - 1], conf_get_conf_file(),
conf_get_current_lineno());
break;
}
}
if (check_is_ipaddr(server->server) != 0) {
/* if server is domain name, then verify domain */
if (server->tls_host_verify[0] == '\0' && no_tls_host_verify == 0) {
safe_strncpy(server->tls_host_verify, server->server, DNS_MAX_CNAME_LEN);
}
if (server->hostname[0] == '\0' && no_tls_host_name == 0) {
safe_strncpy(server->hostname, server->server, DNS_MAX_CNAME_LEN);
}
if (server->httphost[0] == '\0') {
safe_strncpy(server->httphost, server->server, DNS_MAX_CNAME_LEN);
}
if (host_ip[0] != '\0') {
safe_strncpy(server->server, host_ip, DNS_MAX_IPLEN);
}
}
/* if server is domain name, then verify domain */
if (server->tls_host_verify[0] == '\0' && server->hostname[0] != '\0' && no_tls_host_verify == 0) {
safe_strncpy(server->tls_host_verify, server->hostname, DNS_MAX_CNAME_LEN);
if (server->tls_host_verify[0] == '\0' && check_is_ipaddr(server->server) != 0) {
safe_strncpy(server->tls_host_verify, server->server, DNS_MAX_CNAME_LEN);
}
/* update address rules for host-ip */
if (is_hostip_set == 1) {
struct dns_domain_rule *rule = _config_domain_rule_get(server->server);
if (rule) {
if (rule->rules[DOMAIN_RULE_ADDRESS_IPV4] != NULL && rule->rules[DOMAIN_RULE_ADDRESS_IPV6] == NULL) {
_conf_domain_rule_address(server->server, "#6");
} else if (rule->rules[DOMAIN_RULE_ADDRESS_IPV4] == NULL && rule->rules[DOMAIN_RULE_ADDRESS_IPV6] != NULL) {
_conf_domain_rule_address(server->server, "#4");
}
}
}
/* add new server */
@@ -766,17 +709,6 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
server->server_flag = server_flag;
server->ttl = ttl;
server->drop_packet_latency_ms = drop_packet_latency_ms;
if (server->type == DNS_SERVER_HTTPS) {
if (server->path[0] == 0) {
safe_strncpy(server->path, "/", sizeof(server->path));
}
if (server->httphost[0] == '\0') {
safe_strncpy(server->httphost, server->server, DNS_MAX_CNAME_LEN);
}
}
dns_conf_server_num++;
tlog(TLOG_DEBUG, "add server %s, flag: %X, ttl: %d", ip, result_flag, ttl);
@@ -861,8 +793,8 @@ static int _config_set_rule_each_from_list(const char *file, set_rule_add_func c
fp = fopen(file, "r");
if (fp == NULL) {
tlog(TLOG_ERROR, "open file %s error, %s", file, strerror(errno));
return -1;
tlog(TLOG_WARN, "open file %s error, %s", file, strerror(errno));
return 0;
}
line_no = 0;
@@ -912,9 +844,7 @@ static int _config_domain_rule_set_each(const char *domain_set, set_rule_add_fun
{
switch (set_name_item->type) {
case DNS_DOMAIN_SET_LIST:
if (_config_set_rule_each_from_list(set_name_item->file, callback, priv) != 0) {
return -1;
}
_config_set_rule_each_from_list(set_name_item->file, callback, priv);
break;
case DNS_DOMAIN_SET_GEOSITE:
break;
@@ -982,7 +912,7 @@ static int _config_setup_domain_key(const char *domain, char *domain_key, int do
return 0;
}
static __attribute__((unused)) struct dns_domain_rule *_config_domain_rule_get(const char *domain)
static struct dns_domain_rule *_config_domain_rule_get(const char *domain)
{
char domain_key[DNS_MAX_CONF_CNAME_LEN];
int len = 0;
@@ -1701,9 +1631,6 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
goto errout;
}
if (ptr) {
ptr++;
}
continue;
} else if (*(field) == '-') {
if (strncmp(field, "-4", sizeof("-4")) == 0) {
@@ -1721,9 +1648,6 @@ static int _conf_domain_rule_address(char *domain, const char *domain_address)
goto errout;
}
if (ptr) {
ptr++;
}
continue;
}
@@ -1894,122 +1818,6 @@ errout:
return 0;
}
struct dns_srv_records *dns_server_get_srv_record(const char *domain)
{
uint32_t key = 0;
key = hash_string(domain);
struct dns_srv_records *srv_records = NULL;
hash_for_each_possible(dns_conf_srv_record_table.srv, srv_records, node, key)
{
if (strncmp(srv_records->domain, domain, DNS_MAX_CONF_CNAME_LEN) == 0) {
return srv_records;
}
}
return NULL;
}
static int _confg_srv_record_add(const char *domain, const char *host, unsigned short priority, unsigned short weight,
unsigned short port)
{
struct dns_srv_records *srv_records = NULL;
struct dns_srv_record *srv_record = NULL;
uint32_t key = 0;
srv_records = dns_server_get_srv_record(domain);
if (srv_records == NULL) {
srv_records = malloc(sizeof(*srv_records));
if (srv_records == NULL) {
goto errout;
}
memset(srv_records, 0, sizeof(*srv_records));
safe_strncpy(srv_records->domain, domain, DNS_MAX_CONF_CNAME_LEN);
INIT_LIST_HEAD(&srv_records->list);
key = hash_string(domain);
hash_add(dns_conf_srv_record_table.srv, &srv_records->node, key);
}
srv_record = malloc(sizeof(*srv_record));
if (srv_record == NULL) {
goto errout;
}
memset(srv_record, 0, sizeof(*srv_record));
safe_strncpy(srv_record->host, host, DNS_MAX_CONF_CNAME_LEN);
srv_record->priority = priority;
srv_record->weight = weight;
srv_record->port = port;
list_add_tail(&srv_record->list, &srv_records->list);
return 0;
errout:
if (srv_record != NULL) {
free(srv_record);
}
return -1;
}
static int _config_srv_record(void *data, int argc, char *argv[])
{
char *value = NULL;
char domain[DNS_MAX_CONF_CNAME_LEN];
char buff[DNS_MAX_CONF_CNAME_LEN];
char *ptr = NULL;
int ret = -1;
char *host_s;
char *priority_s;
char *weight_s;
char *port_s;
unsigned short priority = 0;
unsigned short weight = 0;
unsigned short port = 1;
if (argc < 2) {
goto errout;
}
value = argv[1];
if (_get_domain(value, domain, DNS_MAX_CONF_CNAME_LEN, &value) != 0) {
goto errout;
}
safe_strncpy(buff, value, sizeof(buff));
host_s = strtok_r(buff, ",", &ptr);
if (host_s == NULL) {
host_s = "";
goto out;
}
port_s = strtok_r(NULL, ",", &ptr);
if (port_s != NULL) {
port = atoi(port_s);
}
priority_s = strtok_r(NULL, ",", &ptr);
if (priority_s != NULL) {
priority = atoi(priority_s);
}
weight_s = strtok_r(NULL, ",", &ptr);
if (weight_s != NULL) {
weight = atoi(weight_s);
}
out:
ret = _confg_srv_record_add(domain, host_s, priority, weight, port);
if (ret != 0) {
goto errout;
}
return 0;
errout:
tlog(TLOG_ERROR, "add srv-record %s:%s failed", domain, value);
return -1;
}
static void _config_speed_check_mode_clear(struct dns_domain_check_orders *check_orders)
{
memset(check_orders->orders, 0, sizeof(check_orders->orders));
@@ -2385,8 +2193,6 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
break;
}
default:
tlog(TLOG_WARN, "unknown bind option: %s at '%s:%d'.", argv[optind - 1], conf_get_conf_file(),
conf_get_current_lineno());
break;
}
}
@@ -2395,7 +2201,7 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type)
bind_ip->flags = server_flag;
bind_ip->group = group;
dns_conf_bind_ip_num++;
if (bind_ip->type == DNS_BIND_TYPE_TLS || bind_ip->type == DNS_BIND_TYPE_HTTPS) {
if (bind_ip->type == DNS_BIND_TYPE_TLS) {
if (bind_ip->ssl_cert_file == NULL || bind_ip->ssl_cert_key_file == NULL) {
bind_ip->ssl_cert_file = dns_conf_bind_ca_file;
bind_ip->ssl_cert_key_file = dns_conf_bind_ca_key_file;
@@ -2426,11 +2232,6 @@ static int _config_bind_ip_tls(void *data, int argc, char *argv[])
return _config_bind_ip(argc, argv, DNS_BIND_TYPE_TLS);
}
static int _config_bind_ip_https(void *data, int argc, char *argv[])
{
return _config_bind_ip(argc, argv, DNS_BIND_TYPE_HTTPS);
}
static int _config_option_parser_filepath(void *data, int argc, char *argv[])
{
if (argc <= 1) {
@@ -2466,14 +2267,6 @@ static int _config_server_https(void *data, int argc, char *argv[])
return ret;
}
static int _config_server_quic(void *data, int argc, char *argv[])
{
int ret = 0;
ret = _config_server(argc, argv, DNS_SERVER_QUIC, DEFAULT_DNS_QUIC_PORT);
return ret;
}
static int _conf_domain_rule_nameserver(char *domain, const char *group_name)
{
struct dns_nameserver_rule *nameserver_rule = NULL;
@@ -3009,11 +2802,6 @@ static int _conf_domain_set(void *data, int argc, char *argv[])
goto errout;
}
if (access(domain_set->file, F_OK) != 0) {
tlog(TLOG_ERROR, "domain set file %s not readable. %s", domain_set->file, strerror(errno));
goto errout;
}
key = hash_string(set_name);
hash_for_each_possible(dns_domain_set_name_table.names, domain_set_name_list, node, key)
{
@@ -3068,9 +2856,7 @@ static int _config_ip_rule_set_each(const char *ip_set, set_rule_add_func callba
{
switch (set_name_item->type) {
case DNS_IP_SET_LIST:
if (_config_set_rule_each_from_list(set_name_item->file, callback, priv) != 0) {
return -1;
}
_config_set_rule_each_from_list(set_name_item->file, callback, priv);
break;
default:
tlog(TLOG_WARN, "ip set %s type %d not support.", set_name_list->name, set_name_item->type);
@@ -3232,58 +3018,10 @@ errout:
return -1;
}
static int _config_ip_rule_alias_add_ip(const char *ip, struct ip_rule_alias *ip_alias)
{
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
unsigned char *paddr = NULL;
int ret = 0;
ret = getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len);
if (ret != 0) {
tlog(TLOG_ERROR, "ip is invalid: %s", ip);
goto errout;
}
switch (addr.ss_family) {
case AF_INET: {
struct sockaddr_in *addr_in = NULL;
addr_in = (struct sockaddr_in *)&addr;
paddr = (unsigned char *)&(addr_in->sin_addr.s_addr);
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = NULL;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
paddr = addr_in6->sin6_addr.s6_addr + 12;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} else {
paddr = addr_in6->sin6_addr.s6_addr;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_AAAA_LEN);
}
} break;
default:
goto errout;
break;
}
return 0;
errout:
return -1;
}
static int _config_ip_alias_add_ip_callback(const char *ip_cidr, void *priv)
{
return _config_ip_rule_alias_add_ip(ip_cidr, (struct ip_rule_alias *)priv);
}
static int _config_ip_alias(const char *ip_cidr, const char *ips)
{
struct ip_rule_alias *ip_alias = NULL;
char *target_ips = NULL;
int ret = 0;
if (ip_cidr == NULL || ips == NULL) {
goto errout;
@@ -3294,21 +3032,43 @@ static int _config_ip_alias(const char *ip_cidr, const char *ips)
goto errout;
}
if (strncmp(ips, "ip-set:", sizeof("ip-set:") - 1) == 0) {
if (_config_ip_rule_set_each(ips + sizeof("ip-set:") - 1, _config_ip_alias_add_ip_callback, ip_alias) != 0) {
goto errout;
}
} else {
target_ips = strdup(ips);
if (target_ips == NULL) {
target_ips = strdup(ips);
if (target_ips == NULL) {
goto errout;
}
for (char *tok = strtok(target_ips, ","); tok != NULL; tok = strtok(NULL, ",")) {
struct sockaddr_storage addr;
socklen_t addr_len = sizeof(addr);
unsigned char *paddr = NULL;
int ret = 0;
ret = getaddr_by_host(tok, (struct sockaddr *)&addr, &addr_len);
if (ret != 0) {
goto errout;
}
for (char *tok = strtok(target_ips, ","); tok != NULL; tok = strtok(NULL, ",")) {
ret = _config_ip_rule_alias_add_ip(tok, ip_alias);
if (ret != 0) {
goto errout;
switch (addr.ss_family) {
case AF_INET: {
struct sockaddr_in *addr_in = NULL;
addr_in = (struct sockaddr_in *)&addr;
paddr = (unsigned char *)&(addr_in->sin_addr.s_addr);
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} break;
case AF_INET6: {
struct sockaddr_in6 *addr_in6 = NULL;
addr_in6 = (struct sockaddr_in6 *)&addr;
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
paddr = addr_in6->sin6_addr.s6_addr + 12;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_A_LEN);
} else {
paddr = addr_in6->sin6_addr.s6_addr;
_dns_iplist_ip_address_add(&ip_alias->ip_alias, paddr, DNS_RR_AAAA_LEN);
}
} break;
default:
goto errout;
break;
}
}
@@ -3317,9 +3077,7 @@ static int _config_ip_alias(const char *ip_cidr, const char *ips)
}
_dns_ip_rule_put(&ip_alias->head);
if (target_ips) {
free(target_ips);
}
free(target_ips);
return 0;
errout:
@@ -3441,8 +3199,6 @@ static int _conf_ip_rules(void *data, int argc, char *argv[])
break;
}
default:
tlog(TLOG_WARN, "unknown ip-rules option: %s at '%s:%d'.", argv[optind - 1], conf_get_conf_file(),
conf_get_current_lineno());
break;
}
}
@@ -3511,11 +3267,6 @@ static int _conf_ip_set(void *data, int argc, char *argv[])
}
/* clang-format on */
if (access(ip_set->file, F_OK) != 0) {
tlog(TLOG_ERROR, "ip set file %s not readable. %s", ip_set->file, strerror(errno));
goto errout;
}
if (set_name[0] == 0 || ip_set->file[0] == 0) {
tlog(TLOG_ERROR, "invalid parameter.");
goto errout;
@@ -3548,10 +3299,6 @@ errout:
if (ip_set) {
free(ip_set);
}
if (ip_set_name_list != NULL) {
free(ip_set_name_list);
}
return -1;
}
@@ -3847,8 +3594,6 @@ static int _conf_domain_rules(void *data, int argc, char *argv[])
break;
}
default:
tlog(TLOG_WARN, "unknown domain-rules option: %s at '%s:%d'.", argv[optind - 1], conf_get_conf_file(),
conf_get_current_lineno());
break;
}
}
@@ -4300,7 +4045,6 @@ static struct config_item _config_item[] = {
CONF_CUSTOM("bind", _config_bind_ip_udp, NULL),
CONF_CUSTOM("bind-tcp", _config_bind_ip_tcp, NULL),
CONF_CUSTOM("bind-tls", _config_bind_ip_tls, NULL),
CONF_CUSTOM("bind-https", _config_bind_ip_https, NULL),
CONF_CUSTOM("bind-cert-file", _config_option_parser_filepath, &dns_conf_bind_ca_file),
CONF_CUSTOM("bind-cert-key-file", _config_option_parser_filepath, &dns_conf_bind_ca_key_file),
CONF_STRING("bind-cert-key-pass", dns_conf_bind_ca_key_pass, DNS_MAX_PATH),
@@ -4308,12 +4052,10 @@ static struct config_item _config_item[] = {
CONF_CUSTOM("server-tcp", _config_server_tcp, NULL),
CONF_CUSTOM("server-tls", _config_server_tls, NULL),
CONF_CUSTOM("server-https", _config_server_https, NULL),
CONF_CUSTOM("server-quic", _config_server_quic, NULL),
CONF_CUSTOM("nameserver", _config_nameserver, NULL),
CONF_YESNO("expand-ptr-from-address", &dns_conf_expand_ptr_from_address),
CONF_CUSTOM("address", _config_address, NULL),
CONF_CUSTOM("cname", _config_cname, NULL),
CONF_CUSTOM("srv-record", _config_srv_record, NULL),
CONF_CUSTOM("proxy-server", _config_proxy_server, NULL),
CONF_YESNO("ipset-timeout", &dns_conf_ipset_timeout_enable),
CONF_CUSTOM("ipset", _config_ipset, NULL),
@@ -4391,11 +4133,8 @@ static int _conf_printf(const char *file, int lineno, int ret)
case CONF_RET_ERR:
case CONF_RET_WARN:
case CONF_RET_BADCONF:
tlog(TLOG_WARN, "process config failed at '%s:%d'.", file, lineno);
return -1;
break;
case CONF_RET_NOENT:
tlog(TLOG_WARN, "unsupported config at '%s:%d'.", file, lineno);
tlog(TLOG_WARN, "process config file '%s' failed at line %d.", file, lineno);
syslog(LOG_NOTICE, "process config file '%s' failed at line %d.", file, lineno);
return -1;
break;
default:
@@ -4405,40 +4144,17 @@ static int _conf_printf(const char *file, int lineno, int ret)
return 0;
}
static int conf_file_check_duplicate(const char *conf_file)
{
struct conf_file_path *file = NULL;
uint32_t key = 0;
key = hash_string(conf_file);
hash_table_for_each_possible(conf_file_table, file, node, key)
{
if (strncmp(file->file, conf_file, DNS_MAX_PATH) != 0) {
continue;
}
return 0;
}
file = malloc(sizeof(*file));
if (file == NULL) {
return -1;
}
safe_strncpy(file->file, conf_file, DNS_MAX_PATH);
hash_table_add(conf_file_table, &file->node, key);
return -1;
}
static int conf_additional_file(const char *conf_file)
int config_additional_file(void *data, int argc, char *argv[])
{
char *conf_file = NULL;
char file_path[DNS_MAX_PATH];
char file_path_dir[DNS_MAX_PATH];
if (conf_file == NULL) {
if (argc < 1) {
return -1;
}
conf_file = argv[1];
if (conf_file[0] != '/') {
safe_strncpy(file_path_dir, conf_get_conf_file(), DNS_MAX_PATH);
dir_name(file_path_dir);
@@ -4456,83 +4172,14 @@ static int conf_additional_file(const char *conf_file)
}
if (access(file_path, R_OK) != 0) {
tlog(TLOG_ERROR, "config file '%s' is not readable, %s", conf_file, strerror(errno));
return -1;
}
if (conf_file_check_duplicate(file_path) == 0) {
tlog(TLOG_WARN, "conf file %s is not readable.", file_path);
syslog(LOG_NOTICE, "conf file %s is not readable.", file_path);
return 0;
}
return load_conf(file_path, _config_item, _conf_printf);
}
int config_additional_file(void *data, int argc, char *argv[])
{
const char *conf_pattern = NULL;
char file_path[DNS_MAX_PATH];
char file_path_dir[DNS_MAX_PATH];
glob_t globbuf = {0};
if (argc < 1) {
return -1;
}
conf_pattern = argv[1];
if (conf_pattern == NULL) {
return -1;
}
if (conf_pattern[0] != '/') {
safe_strncpy(file_path_dir, conf_get_conf_file(), DNS_MAX_PATH);
dir_name(file_path_dir);
if (strncmp(file_path_dir, conf_get_conf_file(), sizeof(file_path_dir)) == 0) {
if (snprintf(file_path, DNS_MAX_PATH, "%s", conf_pattern) < 0) {
return -1;
}
} else {
if (snprintf(file_path, DNS_MAX_PATH, "%s/%s", file_path_dir, conf_pattern) < 0) {
return -1;
}
}
} else {
safe_strncpy(file_path, conf_pattern, DNS_MAX_PATH);
}
errno = 0;
if (glob(file_path, 0, NULL, &globbuf) != 0) {
if (errno == 0) {
return 0;
}
tlog(TLOG_ERROR, "open config file '%s' failed, %s", file_path, strerror(errno));
return -1;
}
for (size_t i = 0; i != globbuf.gl_pathc; ++i) {
const char *file = globbuf.gl_pathv[i];
struct stat statbuf;
if (stat(file, &statbuf) != 0) {
continue;
}
if (!S_ISREG(statbuf.st_mode)) {
continue;
}
if (conf_additional_file(file) != 0) {
tlog(TLOG_ERROR, "load config file '%s' failed.", file);
globfree(&globbuf);
return -1;
}
}
globfree(&globbuf);
return 0;
}
const char *dns_conf_get_cache_dir(void)
{
if (dns_conf_cache_file[0] == '\0') {
@@ -4566,7 +4213,6 @@ static int _dns_server_load_conf_init(void)
hash_init(dns_ptr_table.ptr);
hash_init(dns_domain_set_name_table.names);
hash_init(dns_ip_set_name_table.names);
hash_init(dns_conf_srv_record_table.srv);
return 0;
}
@@ -4617,7 +4263,6 @@ void dns_server_load_exit(void)
_config_host_table_destroy(0);
_config_qtype_soa_table_destroy();
_config_proxy_table_destroy();
_config_srv_record_table_destroy();
dns_conf_server_num = 0;
dns_server_bind_destroy();
@@ -4684,21 +4329,6 @@ static int _dns_ping_cap_check(void)
return 0;
}
static void _config_file_hash_table_destroy(void)
{
struct conf_file_path *file = NULL;
struct hlist_node *tmp = NULL;
int i = 0;
hash_table_for_each_safe(conf_file_table, i, tmp, file, node)
{
hlist_del_init(&file->node);
free(file);
}
hash_table_free(conf_file_table, free);
}
static int _dns_conf_load_pre(void)
{
if (_dns_server_load_conf_init() != 0) {
@@ -4709,8 +4339,6 @@ static int _dns_conf_load_pre(void)
safe_strncpy(dns_save_fail_packet_dir, SMARTDNS_DEBUG_DIR, sizeof(dns_save_fail_packet_dir));
hash_table_init(conf_file_table, 8, malloc);
return 0;
errout:
@@ -4774,8 +4402,6 @@ static int _dns_conf_load_post(void)
_config_add_default_server_if_needed();
_config_file_hash_table_destroy();
return 0;
}

View File

@@ -56,11 +56,9 @@ extern "C" {
#define DEFAULT_DNS_PORT 53
#define DEFAULT_DNS_TLS_PORT 853
#define DEFAULT_DNS_HTTPS_PORT 443
#define DEFAULT_DNS_QUIC_PORT 853
#define DNS_MAX_CONF_CNAME_LEN 256
#define MAX_QTYPE_NUM 65535
#define DNS_MAX_REPLY_IP_NUM 8
#define DNS_DEFAULT_CHECKPOINT_TIME (3600 * 24)
#define SMARTDNS_CONF_FILE "/etc/smartdns/smartdns.conf"
#define SMARTDNS_LOG_FILE "/var/log/smartdns/smartdns.log"
@@ -325,7 +323,7 @@ struct dns_edns_client_subnet {
};
struct dns_servers {
char server[DNS_MAX_CNAME_LEN];
char server[DNS_MAX_IPLEN];
unsigned short port;
unsigned int result_flag;
unsigned int server_flag;
@@ -489,25 +487,6 @@ struct dns_dns64 {
uint32_t prefix_len;
};
struct dns_srv_record {
struct list_head list;
char host[DNS_MAX_CNAME_LEN];
unsigned short priority;
unsigned short weight;
unsigned short port;
};
struct dns_srv_records {
char domain[DNS_MAX_CNAME_LEN];
struct hlist_node node;
struct list_head list;
};
struct dns_srv_record_table {
DECLARE_HASHTABLE(srv, 4);
};
extern struct dns_srv_record_table dns_conf_srv_record_table;
extern struct dns_dns64 dns_conf_dns_dns64;
extern struct dns_bind_ip dns_conf_bind_ip[DNS_MAX_BIND_IP];
@@ -604,8 +583,6 @@ int dns_server_check_update_hosts(void);
struct dns_proxy_names *dns_server_get_proxy_nams(const char *proxyname);
struct dns_srv_records *dns_server_get_srv_record(const char *domain);
extern int config_additional_file(void *data, int argc, char *argv[]);
const char *dns_conf_get_cache_dir(void);

File diff suppressed because it is too large Load Diff

View File

@@ -183,7 +183,6 @@ struct fast_ping_struct {
int fake_ip_num;
};
static int is_fast_ping_init;
static struct fast_ping_struct ping;
static atomic_t ping_sid = ATOMIC_INIT(0);
static int bool_print_log = 1;
@@ -2188,10 +2187,6 @@ int fast_ping_init(void)
int ret = 0;
bool_print_log = 1;
if (is_fast_ping_init == 1) {
return -1;
}
if (ping.epoll_fd > 0) {
return -1;
}
@@ -2237,7 +2232,6 @@ int fast_ping_init(void)
goto errout;
}
is_fast_ping_init = 1;
return 0;
errout:
if (ping.notify_tid) {
@@ -2300,10 +2294,6 @@ static void _fast_ping_close_fds(void)
void fast_ping_exit(void)
{
if (is_fast_ping_init == 0) {
return;
}
if (ping.notify_tid) {
void *retval = NULL;
atomic_set(&ping.run, 0);
@@ -2334,6 +2324,4 @@ void fast_ping_exit(void)
pthread_mutex_destroy(&ping.notify_lock);
pthread_mutex_destroy(&ping.lock);
pthread_mutex_destroy(&ping.map_lock);
is_fast_ping_init = 0;
}

View File

@@ -111,10 +111,10 @@ const char *http_head_get_fields_value(struct http_head *http_head, const char *
uint32_t key;
struct http_head_fields *filed;
key = hash_string_case(name);
key = hash_string(name);
hash_for_each_possible(http_head->field_map, filed, node, key)
{
if (strncasecmp(filed->name, name, 128) == 0) {
if (strncmp(filed->name, name, 128) == 0) {
return filed->value;
}
}
@@ -205,7 +205,7 @@ static int _http_head_add_fields(struct http_head *http_head, char *name, char *
fields->value = value;
list_add_tail(&fields->list, &http_head->field_head.list);
key = hash_string_case(name);
key = hash_string(name);
hash_add(http_head->field_map, &fields->node, key);
return 0;
@@ -384,10 +384,6 @@ int http_head_parse(struct http_head *http_head, const char *data, int data_len)
if (http_head->head_ok == 0) {
for (i = 0; i < data_len; i++, data++) {
*(buff_end + i) = *data;
if (isprint(*data) == 0 && isspace(*data) == 0) {
return -2;
}
if (*data == '\n') {
if (http_head->buff_len + i < 2) {
continue;

View File

@@ -122,9 +122,9 @@ struct config_enum {
.data = value, .min = min_value, .max = max_value \
} \
}
#define CONF_SSIZE(key, value, min_value, max_value) \
#define CONF_SSIZE(key, value, min_value, max_value) \
{ \
key, conf_ssize, &(struct config_item_ssize) \
key, conf_ssize, &(struct config_item_ssize) \
{ \
.data = value, .min = min_value, .max = max_value \
} \

View File

@@ -21,7 +21,6 @@
#include "bitmap.h"
#include "jhash.h"
#include <ctype.h>
/* Fast hashing routine for ints, longs and pointers.
(C) 2002 Nadia Yvette Chambers, IBM */
@@ -224,28 +223,11 @@ static inline uint32_t hash_string_initval(const char *s, uint32_t initval)
return h;
}
static inline uint32_t hash_string_case_initval(const char *s, uint32_t initval)
{
uint32_t h = initval;
while (*s) {
h = h * 31 + tolower(*s);
s++;
}
return h;
}
static inline uint32_t hash_string(const char *s)
{
return hash_string_initval(s, 0);
}
static inline uint32_t hash_string_case(const char *s)
{
return hash_string_case_initval(s, 0);
}
static inline uint32_t hash_string_array(const char **a)
{
uint32_t h = 0;

View File

@@ -1,32 +0,0 @@
/*************************************************************************
*
* Copyright (C) 2018-2023 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/>.
*/
#ifndef _SMARTDNS_IDNA_H
#define _SMARTDNS_IDNA_H
#ifdef __cplusplus
extern "C" {
#endif
int utf8_to_punycode(const char *src, int src_len, char *dst, int dst_len);
#ifdef __cplusplus
}
#endif
#endif // !_SMARTDNS_IDNA_H

View File

@@ -21,15 +21,11 @@
#include "list.h"
#ifdef __cplusplus
extern "C" {
#endif
struct tw_base;
struct tw_timer_list;
typedef void (*tw_func)(struct tw_base *, struct tw_timer_list *, void *, unsigned long);
typedef void (*tw_del_func)(struct tw_base *, struct tw_timer_list *, void *);
typedef void (*tw_func)(struct tw_timer_list *, void *, unsigned long);
typedef void (*tw_del_func)(struct tw_timer_list *, void *);
struct tw_timer_list {
void *data;
@@ -51,7 +47,4 @@ int tw_mod_timer_pending(struct tw_base *, struct tw_timer_list *, unsigned long
int tw_mod_timer(struct tw_base *, struct tw_timer_list *, unsigned long);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -24,7 +24,6 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
static const char *current_conf_file = NULL;
static int current_conf_lineno = 0;
@@ -373,7 +372,6 @@ static int load_conf_file(const char *file, struct config_item *items, conf_erro
fp = fopen(file, "r");
if (fp == NULL) {
fprintf(stderr, "open config file '%s' failed, %s\n", file, strerror(errno));
return -1;
}
@@ -442,6 +440,7 @@ static int load_conf_file(const char *file, struct config_item *items, conf_erro
}
if (items[i].item == NULL) {
handler(file, line_no, CONF_RET_NOENT);
break;
}

View File

@@ -1,339 +0,0 @@
/*************************************************************************
*
* Copyright (C) 2018-2023 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/>.
*/
#define _GNU_SOURCE
#include "idna.h"
#include <limits.h>
static unsigned _utf8_decode_slow(const char **p, const char *pe, unsigned a)
{
unsigned b;
unsigned c;
unsigned d;
unsigned min;
if (a > 0xF7) {
return -1;
}
switch (pe - *p) {
default:
if (a > 0xEF) {
min = 0x10000;
a = a & 7;
b = (unsigned char)*(*p)++;
c = (unsigned char)*(*p)++;
d = (unsigned char)*(*p)++;
break;
}
case 2:
if (a > 0xDF) {
min = 0x800;
b = 0x80 | (a & 15);
c = (unsigned char)*(*p)++;
d = (unsigned char)*(*p)++;
a = 0;
break;
}
case 1:
if (a > 0xBF) {
min = 0x80;
b = 0x80;
c = 0x80 | (a & 31);
d = (unsigned char)*(*p)++;
a = 0;
break;
}
case 0:
return -1;
}
if (0x80 != (0xC0 & (b ^ c ^ d))) {
return -1;
}
b &= 63;
c &= 63;
d &= 63;
a = (a << 18) | (b << 12) | (c << 6) | d;
if (a < min) {
return -1;
}
if (a > 0x10FFFF) {
return -1;
}
if (a >= 0xD800 && a <= 0xDFFF) {
return -1;
}
return a;
}
static unsigned _utf8_decode(const char **p, const char *pe)
{
unsigned a;
a = (unsigned char)*(*p)++;
if (a < 128) {
return a;
}
return _utf8_decode_slow(p, pe, a);
}
static int _utf8_to_punycode_label(const char *s, const char *se, char **d, char *de)
{
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz0123456789";
const char *ss;
unsigned c;
unsigned h;
unsigned k;
unsigned n;
unsigned m;
unsigned q;
unsigned t;
unsigned x;
unsigned y;
unsigned bias;
unsigned delta;
unsigned todo;
int first;
h = 0;
ss = s;
todo = 0;
while (s < se) {
c = _utf8_decode(&s, se);
if (c == UINT_MAX) {
return -1;
}
if (c < 128) {
h++;
} else {
todo++;
}
}
if (todo > 0) {
if (*d < de) {
*(*d)++ = 'x';
}
if (*d < de) {
*(*d)++ = 'n';
}
if (*d < de) {
*(*d)++ = '-';
}
if (*d < de) {
*(*d)++ = '-';
}
}
x = 0;
s = ss;
while (s < se) {
c = _utf8_decode(&s, se);
if (c > 127) {
continue;
}
if (*d < de) {
*(*d)++ = c;
}
if (++x == h) {
break;
}
}
if (todo == 0) {
return h;
}
if (h > 0) {
if (*d < de) {
*(*d)++ = '-';
}
}
n = 128;
bias = 72;
delta = 0;
first = 1;
while (todo > 0) {
m = -1;
s = ss;
while (s < se) {
c = _utf8_decode(&s, se);
if (c >= n) {
if (c < m) {
m = c;
}
}
}
x = m - n;
y = h + 1;
if (x > ~delta / y) {
return -1;
}
delta += x * y;
n = m;
s = ss;
while (s < se) {
c = _utf8_decode(&s, se);
if (c < n) {
if (++delta == 0) {
return -1;
}
}
if (c != n) {
continue;
}
for (k = 36, q = delta;; k += 36) {
t = 1;
if (k > bias) {
t = k - bias;
}
if (t > 26) {
t = 26;
}
if (q < t) {
break;
}
x = q - t;
y = 36 - t;
q = x / y;
t = t + x % y;
if (*d < de) {
*(*d)++ = alphabet[t];
}
}
if (*d < de) {
*(*d)++ = alphabet[q];
}
delta /= 2;
if (first) {
delta /= 350;
first = 0;
}
h++;
delta += delta / h;
for (bias = 0; delta > 35 * 26 / 2; bias += 36) {
delta /= 35;
}
bias += 36 * delta / (delta + 38);
delta = 0;
todo--;
}
delta++;
n++;
}
return 0;
}
int utf8_to_punycode(const char *src, int src_len, char *dst, int dst_len)
{
const char *si;
const char *se;
const char *st;
unsigned c;
char *ds;
char *de;
int rc;
ds = dst;
si = src;
se = src + src_len;
de = dst + dst_len;
while (si < se) {
st = si;
c = _utf8_decode(&si, se);
if (c == UINT_MAX) {
return -1;
}
if (c != '.') {
if (c != 0x3002) {
if (c != 0xFF0E) {
if (c != 0xFF61) {
continue;
}
}
}
}
rc = _utf8_to_punycode_label(src, st, &dst, de);
if (rc < 0) {
return rc;
}
if (dst < de) {
*dst++ = '.';
}
src = si;
}
if (src < se) {
rc = _utf8_to_punycode_label(src, se, &dst, de);
if (rc < 0) {
return rc;
}
}
if (dst < de) {
*dst++ = '\0';
}
return dst - ds;
}

View File

@@ -34,7 +34,6 @@
#define TVR_MASK (TVR_SIZE - 1)
#define TVN_MASK (TVN_SIZE - 1)
#define INDEX(N) ((base->jiffies >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK)
#define MAX_TVAL ((unsigned long)((1ULL << (TVR_BITS + 4 * TVN_BITS)) - 1))
struct tvec {
struct list_head vec[TVN_SIZE];
@@ -66,6 +65,7 @@ static inline void _tw_add_timer(struct tw_base *base, struct tw_timer_list *tim
struct list_head *vec;
expires = timer->expires;
idx = expires - base->jiffies;
if (idx < TVR_SIZE) {
@@ -80,13 +80,9 @@ static inline void _tw_add_timer(struct tw_base *base, struct tw_timer_list *tim
} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
vec = base->tv4.vec + i;
} else if ((signed long)idx < 0) {
} else if ((long)idx < 0) {
vec = base->tv1.vec + (base->jiffies & TVR_MASK);
} else {
if (idx > MAX_TVAL) {
idx = MAX_TVAL;
expires = idx + base->jiffies;
}
i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
vec = base->tv5.vec + i;
}
@@ -94,6 +90,31 @@ static inline void _tw_add_timer(struct tw_base *base, struct tw_timer_list *tim
list_add_tail(&timer->entry, vec);
}
static inline unsigned long _apply_slack(struct tw_base *base, struct tw_timer_list *timer)
{
long delta;
unsigned long mask, expires, expires_limit;
expires = timer->expires;
delta = expires - base->jiffies;
if (delta < 256) {
return expires;
}
expires_limit = expires + delta / 256;
mask = expires ^ expires_limit;
if (mask == 0) {
return expires;
}
int bit = fls_long(mask);
mask = (1UL << bit) - 1;
expires_limit = expires_limit & ~(mask);
return expires_limit;
}
static inline void _tw_detach_timer(struct tw_timer_list *timer)
{
struct list_head *entry = &timer->entry;
@@ -158,7 +179,8 @@ void tw_add_timer(struct tw_base *base, struct tw_timer_list *timer)
pthread_spin_lock(&base->lock);
{
timer->expires += base->jiffies - 1;
timer->expires += base->jiffies;
timer->expires = _apply_slack(base, timer);
_tw_add_timer(base, timer);
}
pthread_spin_unlock(&base->lock);
@@ -178,7 +200,7 @@ int tw_del_timer(struct tw_base *base, struct tw_timer_list *timer)
pthread_spin_unlock(&base->lock);
if (ret == 1 && timer->del_function) {
timer->del_function(base, timer, timer->data);
timer->del_function(timer, timer->data);
}
return ret;
@@ -190,7 +212,9 @@ int tw_mod_timer_pending(struct tw_base *base, struct tw_timer_list *timer, unsi
pthread_spin_lock(&base->lock);
{
timer->expires = expires + base->jiffies - 1;
timer->expires = expires + base->jiffies;
timer->expires = _apply_slack(base, timer);
ret = __mod_timer(base, timer, 1);
}
pthread_spin_unlock(&base->lock);
@@ -208,7 +232,8 @@ int tw_mod_timer(struct tw_base *base, struct tw_timer_list *timer, unsigned lon
goto unblock;
}
timer->expires = expires + base->jiffies - 1;
timer->expires = expires + base->jiffies;
timer->expires = _apply_slack(base, timer);
ret = __mod_timer(base, timer, 0);
}
@@ -276,13 +301,13 @@ static inline void run_timers(struct tw_base *base)
_tw_detach_timer(timer);
pthread_spin_unlock(&base->lock);
{
fn(base, timer, data, call_time);
fn(timer, data, call_time);
}
pthread_spin_lock(&base->lock);
if ((timer_pending(timer) == 0 && timer->del_function)) {
if ( (timer_pending(timer) == 0 && timer->del_function) ) {
pthread_spin_unlock(&base->lock);
timer->del_function(base, timer, timer->data);
timer->del_function(timer, timer->data);
pthread_spin_lock(&base->lock);
}
}

View File

@@ -95,7 +95,6 @@ struct proxy_struct {
};
static struct proxy_struct proxy;
static int is_proxy_init;
static const char *proxy_socks5_status_code[] = {
"success",
@@ -1046,24 +1045,13 @@ int proxy_conn_is_udp(struct proxy_conn *proxy_conn)
int proxy_init(void)
{
if (is_proxy_init == 1) {
return -1;
}
memset(&proxy, 0, sizeof(proxy));
hash_init(proxy.proxy_server);
is_proxy_init = 1;
return 0;
}
void proxy_exit(void)
int proxy_exit(void)
{
if (is_proxy_init == 0) {
return;
}
_proxy_remove_all();
is_proxy_init = 0;
return ;
return 0;
}

View File

@@ -56,7 +56,7 @@ struct proxy_conn;
int proxy_init(void);
void proxy_exit(void);
int proxy_exit(void);
int proxy_add(const char *proxy_name, struct proxy_info *info);

View File

@@ -28,9 +28,9 @@
#include "hashtable.h"
#include "list.h"
#include "rbtree.h"
#include "timer.h"
#include "tlog.h"
#include "util.h"
#include "timer.h"
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -47,21 +47,12 @@
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <syslog.h>
#include <ucontext.h>
#define MAX_KEY_LEN 64
#define SMARTDNS_PID_FILE "/run/smartdns.pid"
#define SMARTDNS_LEGACY_PID_FILE "/var/run/smartdns.pid"
#define TMP_BUFF_LEN_32 32
#define SMARTDNS_CRASH_CODE 254
typedef enum {
SMARTDNS_RUN_MONITOR_OK = 0,
SMARTDNS_RUN_MONITOR_ERROR = 1,
SMARTDNS_RUN_MONITOR_EXIT = 2,
} smartdns_run_monitor_ret;
static int verbose_screen;
@@ -161,13 +152,12 @@ static void _help(void)
" -f run foreground.\n"
" -c [conf] config file.\n"
" -p [pid] pid file path, '-' means don't create pid file.\n"
" -R restart smartdns when crash.\n"
" -S ignore segment fault signal.\n"
" -x verbose screen.\n"
" -v display version.\n"
" -h show this help message.\n"
"Online help: https://pymumu.github.io/smartdns\n"
"Online help: http://pymumu.github.io/smartdns\n"
"Copyright (C) Nick Peng <pymumu@gmail.com>\n"
;
/* clang-format on */
@@ -268,7 +258,6 @@ static int _smartdns_prepare_server_flags(struct client_dns_server_flags *flags,
safe_strncpy(flag_http->tls_host_verify, server->tls_host_verify, sizeof(flag_http->tls_host_verify));
flag_http->skip_check_cert = server->skip_check_cert;
} break;
case DNS_SERVER_QUIC:
case DNS_SERVER_TLS: {
struct client_dns_server_flag_tls *flag_tls = &flags->tls;
flag_tls->spi_len = dns_client_spki_decode(server->spki, (unsigned char *)flag_tls->spki);
@@ -474,29 +463,19 @@ static int _smartdns_init(void)
int i = 0;
char logdir[PATH_MAX] = {0};
int logbuffersize = 0;
int enable_log_screen = 0;
if (get_system_mem_size() > 1024 * 1024 * 1024) {
logbuffersize = 1024 * 1024;
}
safe_strncpy(logdir, _smartdns_log_path(), PATH_MAX);
if (verbose_screen != 0 || dns_conf_log_console != 0 || access(dir_name(logdir), W_OK) != 0) {
enable_log_screen = 1;
}
unsigned int tlog_flag = TLOG_NONBLOCK;
if (isatty(1) && enable_log_screen == 1) {
tlog_flag |= TLOG_SCREEN_COLOR;
}
ret = tlog_init(logfile, dns_conf_log_size, dns_conf_log_num, logbuffersize, tlog_flag);
ret = tlog_init(logfile, dns_conf_log_size, dns_conf_log_num, logbuffersize, TLOG_NONBLOCK);
if (ret != 0) {
tlog(TLOG_ERROR, "start tlog failed.\n");
goto errout;
}
if (enable_log_screen) {
safe_strncpy(logdir, _smartdns_log_path(), PATH_MAX);
if (verbose_screen != 0 || dns_conf_log_console != 0 || access(dir_name(logdir), W_OK) != 0) {
tlog_setlogscreen(1);
}
@@ -594,6 +573,7 @@ static int _smartdns_run(void)
static void _smartdns_exit(void)
{
tlog(TLOG_INFO, "smartdns exit...");
dns_client_exit();
proxy_exit();
fast_ping_exit();
@@ -640,7 +620,7 @@ static void _sig_error_exit(int signo, siginfo_t *siginfo, void *ct)
__DATE__, __TIME__, arch);
print_stack();
sleep(1);
_exit(SMARTDNS_CRASH_CODE);
_exit(0);
}
static int sig_list[] = {SIGSEGV, SIGABRT, SIGBUS, SIGILL, SIGFPE};
@@ -746,169 +726,6 @@ static int _smartdns_init_pre(void)
return 0;
}
static void _smartdns_early_log(struct tlog_loginfo *loginfo, const char *format, va_list ap)
{
char log_buf[TLOG_MAX_LINE_LEN];
int sys_log_level = LOG_INFO;
int log_buf_maxlen = 0;
if (loginfo->level < TLOG_WARN) {
return;
}
log_buf_maxlen = sizeof(log_buf) - 2;
log_buf[log_buf_maxlen] = '\0';
int len = vsnprintf(log_buf, log_buf_maxlen, format, ap);
if (len <= 0) {
return;
} else if (len >= log_buf_maxlen) {
log_buf[log_buf_maxlen - 2] = '.';
log_buf[log_buf_maxlen - 3] = '.';
log_buf[log_buf_maxlen - 4] = '.';
len = log_buf_maxlen - 1;
}
if (log_buf[len - 1] != '\n') {
log_buf[len] = '\n';
len++;
}
log_buf[len] = '\0';
fprintf(stderr, "%s", log_buf);
switch (loginfo->level) {
case TLOG_ERROR:
sys_log_level = LOG_ERR;
break;
case TLOG_WARN:
sys_log_level = LOG_WARNING;
break;
case TLOG_NOTICE:
sys_log_level = LOG_NOTICE;
break;
case TLOG_INFO:
sys_log_level = LOG_INFO;
break;
case TLOG_DEBUG:
sys_log_level = LOG_DEBUG;
break;
default:
sys_log_level = LOG_INFO;
break;
}
syslog(sys_log_level, "%s", log_buf);
}
static int _smartdns_child_pid = 0;
static int _smartdns_child_restart = 0;
static void _smartdns_run_monitor_sig(int sig)
{
if (_smartdns_child_pid > 0) {
if (sig == SIGHUP) {
_smartdns_child_restart = 1;
kill(_smartdns_child_pid, SIGTERM);
return;
}
kill(_smartdns_child_pid, SIGTERM);
}
waitpid(_smartdns_child_pid, NULL, 0);
_exit(0);
}
static smartdns_run_monitor_ret _smartdns_run_monitor(int restart_when_crash, int is_run_as_daemon)
{
pid_t pid;
int status;
if (restart_when_crash == 0) {
return SMARTDNS_RUN_MONITOR_OK;
}
if (is_run_as_daemon) {
switch (daemon_run(NULL)) {
case DAEMON_RET_CHILD_OK:
break;
case DAEMON_RET_PARENT_OK:
return SMARTDNS_RUN_MONITOR_EXIT;
default:
return SMARTDNS_RUN_MONITOR_ERROR;
}
}
daemon_kickoff(0, 1);
restart:
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork failed, %s\n", strerror(errno));
return SMARTDNS_RUN_MONITOR_ERROR;
} else if (pid == 0) {
return SMARTDNS_RUN_MONITOR_OK;
}
_smartdns_child_pid = pid;
signal(SIGTERM, _smartdns_run_monitor_sig);
signal(SIGHUP, _smartdns_run_monitor_sig);
while (true) {
pid = waitpid(-1, &status, 0);
if (pid == _smartdns_child_pid) {
int need_restart = 0;
char signalmsg[64] = {0};
if (_smartdns_child_restart == 1) {
_smartdns_child_restart = 0;
goto restart;
}
if (WEXITSTATUS(status) == SMARTDNS_CRASH_CODE) {
need_restart = 1;
} else if (WEXITSTATUS(status) == 255) {
fprintf(stderr, "run daemon failed, please check log.\n");
} else if (WIFSIGNALED(status)) {
switch (WTERMSIG(status)) {
case SIGSEGV:
case SIGABRT:
case SIGBUS:
case SIGILL:
case SIGFPE:
snprintf(signalmsg, sizeof(signalmsg), " with signal %d", WTERMSIG(status));
need_restart = 1;
break;
default:
break;
}
}
if (need_restart == 1) {
printf("smartdns crashed%s, restart...\n", signalmsg);
goto restart;
}
break;
}
if (pid < 0) {
sleep(1);
}
}
return SMARTDNS_RUN_MONITOR_ERROR;
}
static void _smartdns_print_error_tip(void)
{
char buff[4096];
char *log_path = realpath(_smartdns_log_path(), buff);
if (log_path != NULL && access(log_path, F_OK) == 0) {
fprintf(stderr, "run daemon failed, please check log at %s\n", log_path);
}
}
#ifdef TEST
static smartdns_post_func _smartdns_post = NULL;
@@ -951,14 +768,12 @@ int main(int argc, char *argv[])
int opt = 0;
char config_file[MAX_LINE_LEN];
char pid_file[MAX_LINE_LEN];
int is_pid_file_set = 0;
int signal_ignore = 0;
int restart_when_crash = getpid() == 1 ? 1 : 0;
sigset_t empty_sigblock;
struct stat sb;
static struct option long_options[] = {
{"cache-print", required_argument, NULL, 256}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}};
{"cache-print", required_argument, 0, 256}, {"help", no_argument, 0, 'h'}, {NULL, 0, 0, 0}};
safe_strncpy(config_file, SMARTDNS_CONF_FILE, MAX_LINE_LEN);
@@ -973,7 +788,7 @@ int main(int argc, char *argv[])
sigprocmask(SIG_SETMASK, &empty_sigblock, NULL);
smartdns_close_allfds();
while ((opt = getopt_long(argc, argv, "fhc:p:SvxN:R", long_options, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "fhc:p:SvxN:", long_options, 0)) != -1) {
switch (opt) {
case 'f':
is_run_as_daemon = 0;
@@ -986,12 +801,8 @@ int main(int argc, char *argv[])
case 'p':
if (strncmp(optarg, "-", 2) == 0 || full_path(pid_file, sizeof(pid_file), optarg) != 0) {
snprintf(pid_file, sizeof(pid_file), "%s", optarg);
is_pid_file_set = 1;
}
break;
case 'R':
restart_when_crash = 1;
break;
case 'S':
signal_ignore = 1;
break;
@@ -1018,44 +829,27 @@ int main(int argc, char *argv[])
}
}
smartdns_run_monitor_ret init_ret = _smartdns_run_monitor(restart_when_crash, is_run_as_daemon);
if (init_ret != SMARTDNS_RUN_MONITOR_OK) {
if (init_ret == SMARTDNS_RUN_MONITOR_EXIT) {
return 0;
}
return 1;
}
srand(time(NULL));
tlog_reg_early_printf_callback(_smartdns_early_log);
ret = dns_server_load_conf(config_file);
if (ret != 0) {
fprintf(stderr, "load config failed.\n");
goto errout;
}
if (dns_no_daemon || restart_when_crash) {
if (dns_no_daemon) {
is_run_as_daemon = 0;
}
if (is_run_as_daemon) {
int child_status = -1;
switch (daemon_run(&child_status)) {
case DAEMON_RET_CHILD_OK:
break;
case DAEMON_RET_PARENT_OK: {
if (child_status != 0 && child_status != -3) {
_smartdns_print_error_tip();
int daemon_ret = daemon_run();
if (daemon_ret != -2) {
char buff[4096];
char *log_path = realpath(_smartdns_log_path(), buff);
if (log_path != NULL && access(log_path, F_OK) == 0 && daemon_ret != -3 && daemon_ret != 0) {
fprintf(stderr, "run daemon failed, please check log at %s\n", log_path);
}
return child_status;
} break;
case DAEMON_RET_ERR:
default:
fprintf(stderr, "run daemon failed.\n");
goto errout;
return daemon_ret;
}
}
@@ -1063,16 +857,6 @@ int main(int argc, char *argv[])
_reg_signal();
}
if (is_pid_file_set == 0) {
char pid_file_path[MAX_LINE_LEN];
safe_strncpy(pid_file_path, pid_file, MAX_LINE_LEN);
dir_name(pid_file_path);
if (access(pid_file_path, W_OK) != 0) {
dns_no_pidfile = 1;
}
}
if (strncmp(pid_file, "-", 2) != 0 && dns_no_pidfile == 0 && create_pid_file(pid_file) != 0) {
ret = -3;
goto errout;
@@ -1101,22 +885,16 @@ int main(int argc, char *argv[])
if (ret != 0) {
goto errout;
}
} else if (dns_conf_log_console == 0 && verbose_screen == 0) {
daemon_close_stdfds();
}
smartdns_test_notify(1);
ret = _smartdns_run();
tlog(TLOG_INFO, "smartdns exit...");
_smartdns_exit();
return ret;
errout:
if (is_run_as_daemon) {
daemon_kickoff(ret, dns_conf_log_console | verbose_screen);
} else if (dns_conf_log_console == 0 && verbose_screen == 0) {
_smartdns_print_error_tip();
}
smartdns_test_notify(2);
_smartdns_exit();
return ret;
return 1;
}

View File

@@ -79,7 +79,6 @@ struct tlog_log {
int zip_pid;
int multi_log;
int logscreen;
int logscreen_color;
int segment_log;
int max_line_size;
int print_errmsg;
@@ -149,7 +148,6 @@ static struct tlog tlog;
static int tlog_disable_early_print = 0;
static tlog_level tlog_set_level = TLOG_INFO;
static tlog_format_func tlog_format;
static tlog_early_print_func tlog_early_print;
static unsigned int tlog_localtime_lock = 0;
static const char *tlog_level_str[] = {
@@ -630,7 +628,7 @@ int tlog_printf(struct tlog_log *log, const char *format, ...)
return len;
}
static int _tlog_early_print(struct tlog_info_inter *info_inter, const char *format, va_list ap)
static int _tlog_early_print(tlog_level level, const char *file, int line, const char *func, const char *format, va_list ap)
{
char log_buf[TLOG_MAX_LINE_LEN];
size_t len = 0;
@@ -646,14 +644,9 @@ static int _tlog_early_print(struct tlog_info_inter *info_inter, const char *for
return -1;
}
if (tlog_early_print != NULL) {
tlog_early_print(&info_inter->info, format, ap);
return out_len;
}
len = snprintf(log_buf, sizeof(log_buf), "[%.4d-%.2d-%.2d %.2d:%.2d:%.2d,%.3d][%5s][%17s:%-4d] ",
cur_time.year, cur_time.mon, cur_time.mday, cur_time.hour, cur_time.min, cur_time.sec, cur_time.usec / 1000,
tlog_get_level_string(info_inter->info.level), info_inter->info.file, info_inter->info.line);
cur_time.year, cur_time.mon, cur_time.mday, cur_time.hour, cur_time.min, cur_time.sec, cur_time.usec / 1000,
tlog_get_level_string(level), file, line);
out_len = len;
len = vsnprintf(log_buf + out_len, sizeof(log_buf) - out_len - 1, format, ap);
out_len += len;
@@ -669,7 +662,7 @@ static int _tlog_early_print(struct tlog_info_inter *info_inter, const char *for
}
unused = write(STDOUT_FILENO, log_buf, out_len);
return out_len;
return len;
}
int tlog_vext(tlog_level level, const char *file, int line, const char *func, void *userptr, const char *format, va_list ap)
@@ -680,6 +673,14 @@ int tlog_vext(tlog_level level, const char *file, int line, const char *func, vo
return 0;
}
if (tlog.root == NULL) {
return _tlog_early_print(level, file, line, func, format, ap);
}
if (unlikely(tlog.root->logsize <= 0)) {
return 0;
}
if (level >= TLOG_END) {
return -1;
}
@@ -693,14 +694,6 @@ int tlog_vext(tlog_level level, const char *file, int line, const char *func, vo
return -1;
}
if (tlog.root == NULL) {
return _tlog_early_print(&info_inter, format, ap);
}
if (unlikely(tlog.root->logsize <= 0)) {
return 0;
}
return _tlog_vprintf(tlog.root, _tlog_root_log_buffer, &info_inter, format, ap);
}
@@ -1152,54 +1145,7 @@ static void _tlog_get_log_name_dir(struct tlog_log *log)
pthread_mutex_unlock(&tlog.lock);
}
static int _tlog_write_screen(struct tlog_log *log, struct tlog_loginfo *info, const char *buff, int bufflen)
{
int unused __attribute__((unused));
if (bufflen <= 0) {
return 0;
}
if (log->logscreen == 0) {
return 0;
}
if (log->logscreen_color && info != NULL) {
const char *color = NULL;
switch (info->level) {
case TLOG_DEBUG:
color = "\033[0;90m";
break;
case TLOG_NOTICE:
color = "\033[0;97m";
break;
case TLOG_WARN:
color = "\033[0;33m";
break;
case TLOG_ERROR:
color = "\033[0;31m";
break;
case TLOG_FATAL:
color = "\033[31;1m";
break;
default:
break;
}
if (color != NULL) {
fprintf(stdout, "%s%.*s\033[0m\n", color, bufflen - 2, buff);
} else {
fprintf(stdout, "%s", buff);
}
} else {
/* output log to screen */
unused = write(STDOUT_FILENO, buff, bufflen);
}
return bufflen;
}
static int _tlog_write_ext(struct tlog_log *log, struct tlog_loginfo *info, const char *buff, int bufflen)
static int _tlog_write(struct tlog_log *log, const char *buff, int bufflen)
{
int len;
int unused __attribute__((unused));
@@ -1215,7 +1161,7 @@ static int _tlog_write_ext(struct tlog_log *log, struct tlog_loginfo *info, cons
/* output log to screen */
if (log->logscreen) {
_tlog_write_screen(log, info, buff, bufflen);
unused = write(STDOUT_FILENO, buff, bufflen);
}
if (log->logcount <= 0) {
@@ -1299,11 +1245,6 @@ static int _tlog_write_ext(struct tlog_log *log, struct tlog_loginfo *info, cons
return len;
}
static inline int _tlog_write(struct tlog_log *log, const char *buff, int bufflen)
{
return _tlog_write_ext(log, NULL, buff, bufflen);
}
int tlog_write(struct tlog_log *log, const char *buff, int bufflen)
{
return _tlog_write(log, buff, bufflen);
@@ -1537,7 +1478,7 @@ static int _tlog_root_write_log(struct tlog_log *log, const char *buff, int buff
if (tlog.output_func == NULL) {
if (log->segment_log) {
head = (struct tlog_segment_log_head *)buff;
return _tlog_write_ext(log, &head->info, head->data, head->len);
return _tlog_write(log, head->data, head->len);
}
return _tlog_write(log, buff, bufflen);
}
@@ -1679,11 +1620,6 @@ void tlog_set_early_printf(int enable)
tlog_disable_early_print = (enable == 0) ? 1 : 0;
}
void tlog_reg_early_printf_callback(tlog_early_print_func callback)
{
tlog_early_print = callback;
}
const char *tlog_get_level_string(tlog_level level)
{
if (level >= TLOG_END) {
@@ -1809,7 +1745,7 @@ static void _tlog_get_gzip_cmd_path(void)
if (access(gzip_cmd_path, X_OK) != 0) {
continue;
}
snprintf(tlog.gzip_cmd, sizeof(tlog.gzip_cmd), "%s", gzip_cmd_path);
break;
}
@@ -1850,7 +1786,6 @@ tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int bu
log->block = ((flag & TLOG_NONBLOCK) == 0) ? 1 : 0;
log->nocompress = ((flag & TLOG_NOCOMPRESS) == 0) ? 0 : 1;
log->logscreen = ((flag & TLOG_SCREEN) == 0) ? 0 : 1;
log->logscreen_color = ((flag & TLOG_SCREEN_COLOR) == 0) ? 0 : 1;
log->multi_log = ((flag & TLOG_MULTI_WRITE) == 0) ? 0 : 1;
log->segment_log = ((flag & TLOG_SEGMENT) == 0) ? 0 : 1;
log->max_line_size = TLOG_MAX_LINE_LEN;
@@ -1862,11 +1797,6 @@ tlog_log *tlog_open(const char *logfile, int maxlogsize, int maxlogcount, int bu
log->nocompress = 1;
}
if (log->logscreen_color == 1) {
log->logscreen = 1;
log->segment_log = 1;
}
tlog_rename_logfile(log, logfile);
if (log->nocompress) {
strncpy(log->suffix, TLOG_SUFFIX_LOG, sizeof(log->suffix));
@@ -2040,7 +1970,6 @@ errout:
pthread_mutex_destroy(&tlog.lock);
tlog.run = 0;
tlog.root = NULL;
tlog_format = NULL;
_tlog_close(log, 1);
@@ -2049,10 +1978,6 @@ errout:
void tlog_exit(void)
{
if (tlog_format == NULL) {
return;
}
if (tlog.tid) {
void *ret = NULL;
tlog.run = 0;

View File

@@ -66,9 +66,6 @@ struct tlog_time {
/* enable support fork process */
#define TLOG_SUPPORT_FORK (1 << 5)
/* enable output to screen with color */
#define TLOG_SCREEN_COLOR (1 << 6)
struct tlog_loginfo {
tlog_level level;
const char *file;
@@ -114,10 +111,6 @@ extern void tlog_setlogscreen(int enable);
/* enable early log to screen */
extern void tlog_set_early_printf(int enable);
/* set early log callback */
typedef void (*tlog_early_print_func)(struct tlog_loginfo *loginfo, const char *format, va_list ap);
extern void tlog_reg_early_printf_callback(tlog_early_print_func callback);
/* Get log level in string */
extern const char *tlog_get_level_string(tlog_level level);
@@ -304,4 +297,4 @@ private:
#define tlog_error(...) tlog(TLOG_ERROR, ##__VA_ARGS__)
#define tlog_fatal(...) tlog(TLOG_FATAL, ##__VA_ARGS__)
#endif
#endif // !TLOG_H
#endif // !TLOG_H

View File

@@ -188,8 +188,7 @@ int generate_random_addr(unsigned char *addr, int addr_len, int mask)
return 0;
}
int generate_addr_map(const unsigned char *addr_from, const unsigned char *addr_to, unsigned char *addr_out,
int addr_len, int mask)
int generate_addr_map(const unsigned char *addr_from, const unsigned char *addr_to, unsigned char *addr_out, int addr_len, int mask)
{
if ((mask / 8) >= addr_len) {
if (mask % 8 != 0) {
@@ -1065,10 +1064,6 @@ void SSL_CRYPTO_thread_setup(void)
{
int i = 0;
if (lock_cs != NULL) {
return;
}
lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
if (!lock_cs || !lock_count) {
@@ -1098,18 +1093,12 @@ void SSL_CRYPTO_thread_cleanup(void)
{
int i = 0;
if (lock_cs == NULL) {
return;
}
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < CRYPTO_num_locks(); i++) {
pthread_mutex_destroy(&(lock_cs[i]));
}
OPENSSL_free(lock_cs);
OPENSSL_free(lock_count);
lock_cs = NULL;
lock_count = NULL;
}
#endif
@@ -1386,8 +1375,8 @@ int set_sock_keepalive(int fd, int keepidle, int keepinterval, int keepcnt)
}
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepinterval, sizeof(keepinterval));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepinterval, sizeof(keepinterval));
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepcnt, sizeof(keepcnt));
return 0;
}
@@ -1487,7 +1476,7 @@ void bug_ext(const char *file, int line, const char *func, const char *errfmt, .
int write_file(const char *filename, void *data, int data_len)
{
int fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644);
int fd = open(filename, O_WRONLY | O_CREAT, 0644);
if (fd < 0) {
return -1;
}
@@ -1535,9 +1524,9 @@ int dns_packet_save(const char *dir, const char *type, const char *from, const v
snprintf(time_s, sizeof(time_s) - 1, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.3d", ptm->tm_year + 1900, ptm->tm_mon + 1,
ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int)(tm_val.tv_usec / 1000));
snprintf(filename, sizeof(filename) - 1, "%s/%s-%.4d%.2d%.2d-%.2d%.2d%.2d%.3d.packet", dir, type,
snprintf(filename, sizeof(filename) - 1, "%s/%s-%.4d%.2d%.2d-%.2d%.2d%.2d%.1d.packet", dir, type,
ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
(int)(tm_val.tv_usec / 1000));
(int)(tm_val.tv_usec / 100000));
data = malloc(PACKET_BUF_SIZE);
if (data == NULL) {
@@ -1632,23 +1621,6 @@ errout:
return;
}
void daemon_close_stdfds(void)
{
int fd_null = open("/dev/null", O_RDWR);
if (fd_null < 0) {
fprintf(stderr, "open /dev/null failed, %s\n", strerror(errno));
return;
}
dup2(fd_null, STDIN_FILENO);
dup2(fd_null, STDOUT_FILENO);
dup2(fd_null, STDERR_FILENO);
if (fd_null > 2) {
close(fd_null);
}
}
int daemon_kickoff(int status, int no_close)
{
struct daemon_msg msg;
@@ -1667,7 +1639,19 @@ int daemon_kickoff(int status, int no_close)
}
if (no_close == 0) {
daemon_close_stdfds();
int fd_null = open("/dev/null", O_RDWR);
if (fd_null < 0) {
fprintf(stderr, "open /dev/null failed, %s\n", strerror(errno));
return -1;
}
dup2(fd_null, STDIN_FILENO);
dup2(fd_null, STDOUT_FILENO);
dup2(fd_null, STDERR_FILENO);
if (fd_null > 2) {
close(fd_null);
}
}
close(daemon_fd);
@@ -1703,7 +1687,7 @@ int daemon_keepalive(void)
return 0;
}
daemon_ret daemon_run(int *wstatus)
int daemon_run(void)
{
pid_t pid = 0;
int fds[2] = {0};
@@ -1753,16 +1737,11 @@ daemon_ret daemon_run(int *wstatus)
pid = msg.value;
continue;
} else if (msg.type == DAEMON_MSG_KICKOFF) {
if (wstatus != NULL) {
*wstatus = msg.value;
}
return DAEMON_RET_PARENT_OK;
return msg.value;
} else {
goto errout;
}
} while (true);
return DAEMON_RET_ERR;
}
setsid();
@@ -1787,13 +1766,10 @@ daemon_ret daemon_run(int *wstatus)
close(fds[0]);
daemon_fd = fds[1];
return DAEMON_RET_CHILD_OK;
return -2;
errout:
kill(pid, SIGKILL);
if (wstatus != NULL) {
*wstatus = -1;
}
return DAEMON_RET_ERR;
return -1;
}
#ifdef DEBUG
@@ -1913,24 +1889,6 @@ static int _dns_debug_display(struct dns_packet *packet)
inet_ntop(AF_INET6, addr, req_host, sizeof(req_host));
printf("domain: %s AAAA: %s TTL:%d\n", name, req_host, ttl);
} break;
case DNS_T_SRV: {
unsigned short priority = 0;
unsigned short weight = 0;
unsigned short port = 0;
int ret = 0;
char name[DNS_MAX_CNAME_LEN] = {0};
char target[DNS_MAX_CNAME_LEN];
ret = dns_get_SRV(rrs, name, DNS_MAX_CNAME_LEN, &ttl, &priority, &weight, &port, target, DNS_MAX_CNAME_LEN);
if (ret < 0) {
tlog(TLOG_DEBUG, "decode SRV failed, %s", name);
return -1;
}
printf("domain: %s SRV: %s TTL: %d priority: %d weight: %d port: %d\n", name, target, ttl, priority,
weight, port);
} break;
case DNS_T_HTTPS: {
char name[DNS_MAX_CNAME_LEN] = {0};
char target[DNS_MAX_CNAME_LEN] = {0};

View File

@@ -147,21 +147,12 @@ void print_stack(void);
void close_all_fd(int keepfd);
typedef enum daemon_ret {
DAEMON_RET_OK = 0,
DAEMON_RET_ERR = -1,
DAEMON_RET_CHILD_OK = -2,
DAEMON_RET_PARENT_OK = -3,
} daemon_ret;
daemon_ret daemon_run(int *wstatus);
int daemon_run(void);
int daemon_kickoff(int status, int no_close);
int daemon_keepalive(void);
void daemon_close_stdfds(void);
int write_file(const char *filename, void *data, int data_len);
int dns_packet_save(const char *dir, const char *type, const char *from, const void *packet, int packet_len);

View File

@@ -23,7 +23,7 @@ CXXFLAGS += -g
CXXFLAGS += -DTEST
CXXFLAGS += -I./ -I../src -I../src/include
SMARTDNS_OBJS = lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o lib/nftset.o lib/timer_wheel.o lib/idna.o
SMARTDNS_OBJS = lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o lib/nftset.o lib/timer_wheel.o
SMARTDNS_OBJS += smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o http_parse.o proxy.o timer.o
OBJS = $(addprefix ../src/, $(SMARTDNS_OBJS))

View File

@@ -56,36 +56,6 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST(Bind, https)
{
Defer
{
unlink("/tmp/smartdns-cert.pem");
unlink("/tmp/smartdns-key.pem");
};
smartdns::Server server_wrap;
smartdns::Server server;
server.Start(R"""(bind [::]:61053
server https://127.0.0.1:60053 -no-check-certificate
log-num 0
log-console yes
log-level debug
cache-persist no)""");
server_wrap.Start(R"""(bind-https [::]:60053
address /example.com/1.2.3.4
log-num 0
log-console yes
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("example.com", 61053));
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST(Bind, udp_tcp)
{
smartdns::MockServer server_upstream;
@@ -282,71 +252,3 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST(Bind, group)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream1;
smartdns::MockServer server_upstream2;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "9.10.11.12", 611);
return smartdns::SERVER_REQUEST_OK;
});
server_upstream1.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
return smartdns::SERVER_REQUEST_OK;
});
server_upstream2.Start("udp://0.0.0.0:63053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8", 611);
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
bind [::]:60153 -group g1
bind [::]:60253 -group g2
server 127.0.0.1:61053
server 127.0.0.1:62053 -group g1 -exclude-default-group
server 127.0.0.1:63053 -group g2 -exclude-default-group
log-num 0
log-console yes
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "9.10.11.12");
ASSERT_TRUE(client.Query("a.com", 60153));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
ASSERT_TRUE(client.Query("a.com", 60253));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "5.6.7.8");
}

View File

@@ -191,89 +191,6 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST_F(Cache, prefetch)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream1;
smartdns::MockServer server_upstream2;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "9.10.11.12", 611);
return smartdns::SERVER_REQUEST_OK;
});
server_upstream1.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
return smartdns::SERVER_REQUEST_OK;
});
server_upstream2.Start("udp://0.0.0.0:63053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "5.6.7.8", 611);
return smartdns::SERVER_REQUEST_OK;
});
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 100);
server.MockPing(PING_TYPE_ICMP, "5.6.7.8", 60, 110);
server.MockPing(PING_TYPE_ICMP, "9.10.11.12", 60, 110);
server.Start(R"""(bind [::]:60053
bind [::]:60153 -group g1
server 127.0.0.1:61053
server 127.0.0.1:62053 -group g1 -exclude-default-group
server 127.0.0.1:63053 -group g2
log-num 0
prefetch-domain yes
rr-ttl-max 2
serve-expired no
log-console yes
log-level debug
srv-record-selection no
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
ASSERT_TRUE(client.Query("a.com", 60153));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
sleep(1);
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 2);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
sleep(1);
ASSERT_TRUE(client.Query("a.com", 60153));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");
}
TEST_F(Cache, nocache)
{
smartdns::MockServer server_upstream;

266
test/cases/test-https.cc Normal file
View File

@@ -0,0 +1,266 @@
/*************************************************************************
*
* Copyright (C) 2018-2023 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/>.
*/
#include "client.h"
#include "dns.h"
#include "include/utils.h"
#include "server.h"
#include "util.h"
#include "gtest/gtest.h"
#include <fstream>
class HTTPS : public ::testing::Test
{
protected:
virtual void SetUp() {}
virtual void TearDown() {}
};
TEST_F(HTTPS, ipv4_speed_prefer)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_HTTPS) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_packet *packet = request->response_packet;
struct dns_rr_nested svcparam_buffer;
dns_add_HTTPS_start(&svcparam_buffer, packet, DNS_RRS_AN, request->domain.c_str(), 3, 1, "b.com");
const char alph[] = "\x02h2\x05h3-19";
int alph_len = sizeof(alph) - 1;
dns_HTTPS_add_alpn(&svcparam_buffer, alph, alph_len);
dns_HTTPS_add_port(&svcparam_buffer, 443);
unsigned char add_v4[] = {1, 2, 3, 4};
unsigned char *addr[1] = {add_v4};
dns_HTTPS_add_ipv4hint(&svcparam_buffer, addr, 1);
unsigned char ech[] = {0x00, 0x45, 0xfe, 0x0d, 0x00};
dns_HTTPS_add_ech(&svcparam_buffer, (void *)ech, sizeof(ech));
unsigned char add_v6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
addr[0] = add_v6;
dns_HTTPS_add_ipv6hint(&svcparam_buffer, addr, 1);
dns_add_HTTPS_end(&svcparam_buffer);
return smartdns::SERVER_REQUEST_OK;
});
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 10);
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com HTTPS", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "HTTPS");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1 b.com. alpn=\"h2,h3-19\" port=443 ipv4hint=1.2.3.4 ech=AEX+DQA=");
}
TEST_F(HTTPS, ipv6_speed_prefer)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_HTTPS) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_packet *packet = request->response_packet;
struct dns_rr_nested svcparam_buffer;
dns_add_HTTPS_start(&svcparam_buffer, packet, DNS_RRS_AN, request->domain.c_str(), 3, 1, "b.com");
const char alph[] = "\x02h2\x05h3-19";
int alph_len = sizeof(alph) - 1;
dns_HTTPS_add_alpn(&svcparam_buffer, alph, alph_len);
dns_HTTPS_add_port(&svcparam_buffer, 443);
unsigned char add_v4[] = {1, 2, 3, 4};
unsigned char *addr[1] = {add_v4};
dns_HTTPS_add_ipv4hint(&svcparam_buffer, addr, 1);
unsigned char ech[] = {0x00, 0x45, 0xfe, 0x0d, 0x00};
dns_HTTPS_add_ech(&svcparam_buffer, (void *)ech, sizeof(ech));
unsigned char add_v6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
addr[0] = add_v6;
dns_HTTPS_add_ipv6hint(&svcparam_buffer, addr, 1);
dns_add_HTTPS_end(&svcparam_buffer);
return smartdns::SERVER_REQUEST_OK;
});
server.MockPing(PING_TYPE_ICMP, "102:304:506:708:90a:b0c:d0e:f10", 60, 10);
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-console yes
dualstack-ip-selection no
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com HTTPS", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "HTTPS");
EXPECT_EQ(client.GetAnswer()[0].GetData(),
"1 b.com. alpn=\"h2,h3-19\" port=443 ech=AEX+DQA= ipv6hint=102:304:506:708:90a:b0c:d0e:f10");
}
TEST_F(HTTPS, ipv4_SOA)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_HTTPS) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_packet *packet = request->response_packet;
struct dns_rr_nested svcparam_buffer;
dns_add_HTTPS_start(&svcparam_buffer, packet, DNS_RRS_AN, request->domain.c_str(), 3, 1, "a.com");
const char alph[] = "\x02h2\x05h3-19";
int alph_len = sizeof(alph) - 1;
dns_HTTPS_add_alpn(&svcparam_buffer, alph, alph_len);
dns_HTTPS_add_port(&svcparam_buffer, 443);
unsigned char add_v4[] = {1, 2, 3, 4};
unsigned char *addr[1] = {add_v4};
dns_HTTPS_add_ipv4hint(&svcparam_buffer, addr, 1);
unsigned char ech[] = {0x00, 0x45, 0xfe, 0x0d, 0x00};
dns_HTTPS_add_ech(&svcparam_buffer, (void *)ech, sizeof(ech));
unsigned char add_v6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
addr[0] = add_v6;
dns_HTTPS_add_ipv6hint(&svcparam_buffer, addr, 1);
dns_add_HTTPS_end(&svcparam_buffer);
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-console yes
dualstack-ip-selection no
address /a.com/#4
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com HTTPS", 61053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
auto result_check = client.GetAnswer()[0].GetData();
ASSERT_TRUE(client.Query("a.com HTTPS", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "HTTPS");
EXPECT_EQ(client.GetAnswer()[0].GetData(),
"1 a.com. alpn=\"h2,h3-19\" port=443 ech=AEX+DQA= ipv6hint=102:304:506:708:90a:b0c:d0e:f10");
}
TEST_F(HTTPS, ipv6_SOA)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_HTTPS) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_packet *packet = request->response_packet;
struct dns_rr_nested svcparam_buffer;
dns_add_HTTPS_start(&svcparam_buffer, packet, DNS_RRS_AN, request->domain.c_str(), 3, 1, "a.com");
const char alph[] = "\x02h2\x05h3-19";
int alph_len = sizeof(alph) - 1;
dns_HTTPS_add_alpn(&svcparam_buffer, alph, alph_len);
dns_HTTPS_add_port(&svcparam_buffer, 443);
unsigned char add_v4[] = {1, 2, 3, 4};
unsigned char *addr[1] = {add_v4};
dns_HTTPS_add_ipv4hint(&svcparam_buffer, addr, 1);
unsigned char ech[] = {0x00, 0x45, 0xfe, 0x0d, 0x00};
dns_HTTPS_add_ech(&svcparam_buffer, (void *)ech, sizeof(ech));
unsigned char add_v6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
addr[0] = add_v6;
dns_HTTPS_add_ipv6hint(&svcparam_buffer, addr, 1);
dns_add_HTTPS_end(&svcparam_buffer);
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-console yes
dualstack-ip-selection no
address /a.com/#6
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com HTTPS", 61053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
auto result_check = client.GetAnswer()[0].GetData();
ASSERT_TRUE(client.Query("a.com HTTPS", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 3);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "HTTPS");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1 a.com. alpn=\"h2,h3-19\" port=443 ipv4hint=1.2.3.4 ech=AEX+DQA=");
}
TEST_F(HTTPS, SOA)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
return smartdns::SERVER_REQUEST_SOA;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-console yes
dualstack-ip-selection no
address /a.com/#6
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com HTTPS", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAuthorityNum(), 1);
EXPECT_EQ(client.GetStatus(), "NXDOMAIN");
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 60);
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
}

View File

@@ -1,77 +0,0 @@
/*************************************************************************
*
* Copyright (C) 2018-2023 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/>.
*/
#include "client.h"
#include "dns.h"
#include "include/utils.h"
#include "server.h"
#include "util.h"
#include "gtest/gtest.h"
#include <fstream>
class IDNA : public ::testing::Test
{
protected:
virtual void SetUp() {}
virtual void TearDown() {}
};
TEST_F(IDNA, match)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype == DNS_T_A) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 700);
return smartdns::SERVER_REQUEST_OK;
} else if (request->qtype == DNS_T_AAAA) {
smartdns::MockServer::AddIP(request, request->domain.c_str(), "64:ff9b::102:304", 700);
return smartdns::SERVER_REQUEST_OK;
}
return smartdns::SERVER_REQUEST_SOA;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
address /.com/10.10.10.10
address /.com/64:ff9b::1010:1010
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("xn--fiqs8s.com A", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "xn--fiqs8s.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "A");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "10.10.10.10");
ASSERT_TRUE(client.Query("xn--fiqs8s.com AAAA", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "xn--fiqs8s.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "AAAA");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "64:ff9b::1010:1010");
}

View File

@@ -73,48 +73,6 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "4.5.6.7");
}
TEST_F(IPRule, white_list_not_in)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream2;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
return smartdns::SERVER_REQUEST_OK;
});
server_upstream2.Start("udp://0.0.0.0:62053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "9.10.11.12", 611);
return smartdns::SERVER_REQUEST_OK;
});
/* this ip will be discard, but is reachable */
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 10);
server.Start(R"""(bind [::]:60053
server udp://127.0.0.1:61053 -whitelist-ip
server udp://127.0.0.1:62053 -whitelist-ip
whitelist-ip 4.5.6.7/24
log-num 0
log-console yes
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 0);
EXPECT_EQ(client.GetStatus(), "SERVFAIL");
}
TEST_F(IPRule, black_list)
{
smartdns::MockServer server_upstream;
@@ -252,72 +210,3 @@ cache-persist no)""");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "7.8.9.10");
}
TEST_F(IPRule, ip_alias_ip_set)
{
smartdns::MockServer server_upstream;
smartdns::MockServer server_upstream2;
smartdns::Server server;
std::string file = "/tmp/smartdns_test_ip_set.list" + smartdns::GenerateRandomString(5);
std::string file_ip = "/tmp/smartdns_test_ip_set_ip.list" + smartdns::GenerateRandomString(5);
std::ofstream ofs(file);
std::ofstream ofs_ip(file_ip);
ASSERT_TRUE(ofs.is_open());
ASSERT_TRUE(ofs_ip.is_open());
Defer
{
ofs.close();
unlink(file.c_str());
ofs_ip.close();
unlink(file_ip.c_str());
};
server_upstream.Start("udp://0.0.0.0:61053", [](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_A) {
return smartdns::SERVER_REQUEST_SOA;
}
smartdns::MockServer::AddIP(request, request->domain.c_str(), "1.2.3.4", 611);
smartdns::MockServer::AddIP(request, request->domain.c_str(), "4.5.6.7", 611);
smartdns::MockServer::AddIP(request, request->domain.c_str(), "7.8.9.10", 611);
return smartdns::SERVER_REQUEST_OK;
});
server.MockPing(PING_TYPE_ICMP, "1.2.3.4", 60, 10);
server.MockPing(PING_TYPE_ICMP, "4.5.6.7", 60, 90);
server.MockPing(PING_TYPE_ICMP, "7.8.9.10", 60, 40);
std::string ipset_list = R"""(
1.2.3.0/24
4.5.6.0/24
7.8.9.0/24
)""";
ofs.write(ipset_list.c_str(), ipset_list.length());
ofs.flush();
std::string ipset_list_ip = R"""(
1.1.1.1
)""";
ofs_ip.write(ipset_list_ip.c_str(), ipset_list_ip.length());
ofs_ip.flush();
server.Start(R"""(bind [::]:60053
server udp://127.0.0.1:61053 -blacklist-ip
ip-set -name ip-list -file )""" +
file + R"""(
ip-set -name ip-list-ip -file )""" +
file_ip + R"""(
ip-alias ip-set:ip-list ip-set:ip-list-ip
log-num 0
speed-check-mode none
log-console yes
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 1);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.1.1.1");
}

View File

@@ -255,3 +255,55 @@ cache-persist no)""");
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 30);
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
}
TEST_F(QtypeSOA, HTTPS_SOA)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
std::map<int, int> qid_map;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_HTTPS) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_packet *packet = request->response_packet;
struct dns_rr_nested svcparam_buffer;
dns_add_HTTPS_start(&svcparam_buffer, packet, DNS_RRS_AN, request->domain.c_str(), 3, 1, "a.com");
const char alph[] = "\x02h2\x05h3-19";
int alph_len = sizeof(alph) - 1;
dns_HTTPS_add_alpn(&svcparam_buffer, alph, alph_len);
dns_HTTPS_add_port(&svcparam_buffer, 443);
unsigned char add_v4[] = {1, 2, 3, 4};
unsigned char *addr[1] = {add_v4};
dns_HTTPS_add_ipv4hint(&svcparam_buffer, addr, 1);
unsigned char ech[] = {0x00, 0x45, 0xfe, 0x0d, 0x00};
dns_HTTPS_add_ech(&svcparam_buffer, (void *)ech, sizeof(ech));
unsigned char add_v6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
addr[0] = add_v6;
dns_HTTPS_add_ipv6hint(&svcparam_buffer, addr, 1);
dns_add_HTTPS_end(&svcparam_buffer);
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-console yes
dualstack-ip-selection no
speed-check-mode none
address /a.com/#
log-level debug
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("a.com HTTPS", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAuthorityNum(), 1);
EXPECT_EQ(client.GetStatus(), "NXDOMAIN");
EXPECT_EQ(client.GetAuthority()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAuthority()[0].GetTTL(), 30);
EXPECT_EQ(client.GetAuthority()[0].GetType(), "SOA");
}

View File

@@ -99,7 +99,7 @@ cache-persist no)""");
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 2);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_LT(client.GetQueryTime(), 40);
EXPECT_LT(client.GetQueryTime(), 20);
EXPECT_EQ(client.GetAnswer()[0].GetName(), "b.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
@@ -107,7 +107,7 @@ cache-persist no)""");
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 2);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_LT(client.GetQueryTime(), 40);
EXPECT_LT(client.GetQueryTime(), 20);
EXPECT_EQ(client.GetAnswer()[0].GetName(), "a.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1.2.3.4");

View File

@@ -1,105 +0,0 @@
/*************************************************************************
*
* Copyright (C) 2018-2023 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/>.
*/
#include "client.h"
#include "dns.h"
#include "include/utils.h"
#include "server.h"
#include "util.h"
#include "gtest/gtest.h"
#include <fstream>
class SRV : public ::testing::Test
{
protected:
virtual void SetUp() {}
virtual void TearDown() {}
};
TEST_F(SRV, query)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_SRV) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_packet *packet = request->response_packet;
dns_add_SRV(packet, DNS_RRS_AN, request->domain.c_str(), 603, 1, 1, 443, "www.example.com");
dns_add_SRV(packet, DNS_RRS_AN, request->domain.c_str(), 603, 1, 1, 443, "www1.example.com");
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
speed-check-mode none
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("_ldap._tcp.local.com SRV", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 2);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "_ldap._tcp.local.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 603);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "SRV");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1 1 443 www.example.com.");
}
TEST_F(SRV, match)
{
smartdns::MockServer server_upstream;
smartdns::Server server;
server_upstream.Start("udp://0.0.0.0:61053", [&](struct smartdns::ServerRequestContext *request) {
if (request->qtype != DNS_T_SRV) {
return smartdns::SERVER_REQUEST_SOA;
}
struct dns_packet *packet = request->response_packet;
dns_add_SRV(packet, DNS_RRS_AN, request->domain.c_str(), 603, 1, 1, 443, "www.example.com");
dns_add_SRV(packet, DNS_RRS_AN, request->domain.c_str(), 603, 1, 1, 443, "www1.example.com");
return smartdns::SERVER_REQUEST_OK;
});
server.Start(R"""(bind [::]:60053
server 127.0.0.1:61053
log-num 0
log-console yes
log-level debug
srv-record /_ldap._tcp.local.com/www.a.com,443,1,1
srv-record /_ldap._tcp.local.com/www1.a.com,443,1,1
srv-record /_ldap._tcp.local.com/www2.a.com,443,1,1
speed-check-mode none
cache-persist no)""");
smartdns::Client client;
ASSERT_TRUE(client.Query("_ldap._tcp.local.com SRV", 60053));
std::cout << client.GetResult() << std::endl;
ASSERT_EQ(client.GetAnswerNum(), 3);
EXPECT_EQ(client.GetStatus(), "NOERROR");
EXPECT_EQ(client.GetAnswer()[0].GetName(), "_ldap._tcp.local.com");
EXPECT_EQ(client.GetAnswer()[0].GetTTL(), 600);
EXPECT_EQ(client.GetAnswer()[0].GetType(), "SRV");
EXPECT_EQ(client.GetAnswer()[0].GetData(), "1 1 443 www.a.com.");
}

View File

@@ -55,7 +55,7 @@ TEST_F(SubNet, pass_subnet)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -125,7 +125,7 @@ TEST_F(SubNet, conf)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -196,7 +196,7 @@ TEST_F(SubNet, conf_v6)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -269,7 +269,7 @@ TEST_F(SubNet, v4_server_subnet_txt)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -340,7 +340,7 @@ TEST_F(SubNet, v6_default_subnet_txt)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -410,7 +410,7 @@ TEST_F(SubNet, per_server)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -442,7 +442,7 @@ TEST_F(SubNet, per_server)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -479,7 +479,7 @@ TEST_F(SubNet, per_server)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}
@@ -524,7 +524,7 @@ TEST_F(SubNet, per_server)
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
memset(&ecs, 0, sizeof(ecs));
ret = dns_get_OPT_ECS(rrs, &ecs);
ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
if (ret != 0) {
continue;
}