feat: add new smartdns
This commit is contained in:
38
luci-app-smartdns/Makefile
Normal file
38
luci-app-smartdns/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (C) 2018-2024 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 $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
PKG_MAINTAINER:=Nick Peng <pymumu@gmail.com>
|
||||
PKG_VERSION:=1.2024.45
|
||||
PKG_RELEASE:=1
|
||||
|
||||
LUCI_TITLE:=LuCI for smartdns
|
||||
LUCI_DESCRIPTION:=Provides Luci for smartdns
|
||||
LUCI_DEPENDS:=+smartdns +luci-compat
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
define Package/$(PKG_NAME)/config
|
||||
# shown in make menuconfig <Help>
|
||||
help
|
||||
$(LUCI_TITLE)
|
||||
Version: $(PKG_VERSION)-$(PKG_RELEASE)
|
||||
endef
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
57
luci-app-smartdns/luasrc/controller/smartdns.lua
Normal file
57
luci-app-smartdns/luasrc/controller/smartdns.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
--
|
||||
-- Copyright (C) 2018-2024 Ruilin Peng (Nick) <pymumu@gmail.com>.
|
||||
--
|
||||
-- smartdns is free software: you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation, either version 3 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- smartdns is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
module("luci.controller.smartdns", package.seeall)
|
||||
local smartdns = require "luci.model.smartdns"
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/smartdns") then
|
||||
return
|
||||
end
|
||||
|
||||
local page
|
||||
page = entry({"admin", "services", "smartdns"}, cbi("smartdns/smartdns"), _("SmartDNS"), 60)
|
||||
page.dependent = true
|
||||
page = entry({"admin", "services", "smartdns", "status"}, call("act_status"))
|
||||
page.leaf = true
|
||||
page = entry({"admin", "services", "smartdns", "upstream"}, cbi("smartdns/upstream"), nil)
|
||||
page.leaf = true
|
||||
end
|
||||
|
||||
local function is_running()
|
||||
return luci.sys.call("pidof smartdns >/dev/null") == 0
|
||||
end
|
||||
|
||||
function act_status()
|
||||
local e={}
|
||||
local ipv6_server;
|
||||
local dnsmasq_server = smartdns.get_config_option("dhcp", "dnsmasq", "server", {nil})[1]
|
||||
local auto_set_dnsmasq = smartdns.get_config_option("smartdns", "smartdns", "auto_set_dnsmasq", nil);
|
||||
|
||||
e.auto_set_dnsmasq = auto_set_dnsmasq
|
||||
e.dnsmasq_server = dnsmasq_server
|
||||
e.local_port = smartdns.get_config_option("smartdns", "smartdns", "port", nil);
|
||||
if e.local_port ~= nil and e.local_port ~= "53" and auto_set_dnsmasq ~= nil and auto_set_dnsmasq == "1" then
|
||||
local str;
|
||||
str = "127.0.0.1#" .. e.local_port
|
||||
if dnsmasq_server ~= str then
|
||||
e.dnsmasq_redirect_failure = 1
|
||||
end
|
||||
end
|
||||
e.running = is_running()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(e)
|
||||
end
|
||||
1221
luci-app-smartdns/luasrc/model/cbi/smartdns/smartdns.lua
Normal file
1221
luci-app-smartdns/luasrc/model/cbi/smartdns/smartdns.lua
Normal file
File diff suppressed because it is too large
Load Diff
158
luci-app-smartdns/luasrc/model/cbi/smartdns/upstream.lua
Normal file
158
luci-app-smartdns/luasrc/model/cbi/smartdns/upstream.lua
Normal file
@@ -0,0 +1,158 @@
|
||||
--
|
||||
-- Copyright (C) 2018-2024 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/>.
|
||||
|
||||
local sid = arg[1]
|
||||
|
||||
m = Map("smartdns", "%s - %s" %{translate("SmartDNS Server"), translate("Upstream DNS Server Configuration")})
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/smartdns")
|
||||
|
||||
if m.uci:get("smartdns", sid) ~= "server" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Edit Server ]]--
|
||||
s = m:section(NamedSection, sid, "server")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
---- name
|
||||
s:option(Value, "name", translate("DNS Server Name"), translate("DNS Server Name"))
|
||||
|
||||
---- IP address
|
||||
o = s:option(Value, "ip", translate("ip"), translate("DNS Server ip"))
|
||||
o.datatype = "or(host, string)"
|
||||
o.rmempty = false
|
||||
---- port
|
||||
o = s:option(Value, "port", translate("port"), translate("DNS Server port"))
|
||||
o.placeholder = "default"
|
||||
o.datatype = "port"
|
||||
o.rempty = true
|
||||
o:depends("type", "udp")
|
||||
o:depends("type", "tcp")
|
||||
o:depends("type", "tls")
|
||||
|
||||
---- type
|
||||
o = s:option(ListValue, "type", translate("type"), translate("DNS Server type"))
|
||||
o.placeholder = "udp"
|
||||
o:value("udp", translate("udp"))
|
||||
o:value("tcp", translate("tcp"))
|
||||
o:value("tls", translate("tls"))
|
||||
o:value("https", translate("https"))
|
||||
o.default = "udp"
|
||||
o.rempty = false
|
||||
|
||||
---- server group
|
||||
o = s:option(Value, "server_group", translate("Server Group"), translate("DNS Server group belongs to, such as office, home."))
|
||||
o.rmempty = true
|
||||
o.placeholder = "default"
|
||||
o.datatype = "hostname"
|
||||
o.rempty = true
|
||||
|
||||
---- exclude default group
|
||||
o = s:option(Flag, "exclude_default_group", translate("Exclude Default Group"), translate("Exclude DNS Server from default group."))
|
||||
o.rmempty = true
|
||||
o.default = o.disabled
|
||||
o.editable = true
|
||||
o.modalonly = true
|
||||
|
||||
---- blacklist_ip
|
||||
o = s:option(Flag, "blacklist_ip", translate("IP Blacklist Filtering"), translate("Filtering IP with blacklist"))
|
||||
o.rmempty = true
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
|
||||
---- TLS host verify
|
||||
o = s:option(Value, "tls_host_verify", translate("TLS Hostname Verify"), translate("Set TLS hostname to verify."))
|
||||
o.default = ""
|
||||
o.datatype = "string"
|
||||
o.rempty = true
|
||||
o:depends("type", "tls")
|
||||
o:depends("type", "https")
|
||||
|
||||
---- certificate verify
|
||||
o = s:option(Flag, "no_check_certificate", translate("No check certificate"), translate("Do not check certificate."))
|
||||
o.rmempty = true
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
o:depends("type", "tls")
|
||||
o:depends("type", "https")
|
||||
|
||||
---- SNI host name
|
||||
o = s:option(Value, "host_name", translate("TLS SNI name"), translate("Sets the server name indication for query."))
|
||||
o.default = ""
|
||||
o.datatype = "hostname"
|
||||
o.rempty = true
|
||||
o:depends("type", "tls")
|
||||
o:depends("type", "https")
|
||||
|
||||
---- http host
|
||||
o = s:option(Value, "http_host", translate("HTTP Host"), translate("Set the HTTP host used for the query. Use this parameter when the host of the URL address is an IP address."))
|
||||
o.default = ""
|
||||
o.datatype = "hostname"
|
||||
o.rempty = true
|
||||
o:depends("type", "https")
|
||||
|
||||
---- anti-Answer-Forgery
|
||||
-- o = s:option(Flag, "check_edns", translate("Anti Answer Forgery"), translate("Anti answer forgery, if DNS does not work properly after enabling, please turn off this feature"))
|
||||
-- o.rmempty = false
|
||||
-- o.default = o.disabled
|
||||
-- o:depends("type", "udp")
|
||||
-- o.cfgvalue = function(...)
|
||||
-- return Flag.cfgvalue(...) or "0"
|
||||
-- end
|
||||
|
||||
---- SPKI pin
|
||||
o = s:option(Value, "spki_pin", translate("TLS SPKI Pinning"), translate("Used to verify the validity of the TLS server, The value is Base64 encoded SPKI fingerprint, leaving blank to indicate that the validity of TLS is not verified."))
|
||||
o.default = ""
|
||||
o.datatype = "string"
|
||||
o.rempty = true
|
||||
o:depends("type", "tls")
|
||||
o:depends("type", "https")
|
||||
|
||||
---- mark
|
||||
o = s:option(Value, "set_mark", translate("Marking Packets"), translate("Set mark on packets."))
|
||||
o.default = ""
|
||||
o.rempty = true
|
||||
o.datatype = "uinteger"
|
||||
|
||||
---- use proxy
|
||||
o = s:option(Flag, "use_proxy", translate("Use Proxy"), translate("Use proxy to connect to upstream DNS server."))
|
||||
o.rmempty = true
|
||||
o.default = o.disabled
|
||||
o.cfgvalue = function(...)
|
||||
return Flag.cfgvalue(...) or "0"
|
||||
end
|
||||
function o.validate(self, value, section)
|
||||
if value == "1" then
|
||||
local proxy = m.uci:get_first("smartdns", "smartdns", "proxy_server")
|
||||
if proxy == nil or proxy == "" then
|
||||
return nil, translate("Please set proxy server first.")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
---- other args
|
||||
o = s:option(Value, "addition_arg", translate("Additional Server Args"), translate("Additional Args for upstream dns servers"))
|
||||
o.default = ""
|
||||
o.rempty = true
|
||||
|
||||
return m
|
||||
31
luci-app-smartdns/luasrc/model/smartdns.lua
Normal file
31
luci-app-smartdns/luasrc/model/smartdns.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
--
|
||||
-- Copyright (C) 2018-2024 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/>.
|
||||
|
||||
require ("nixio.fs")
|
||||
require ("luci.http")
|
||||
require ("luci.dispatcher")
|
||||
require ("nixio.fs")
|
||||
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
|
||||
module("luci.model.smartdns", package.seeall)
|
||||
|
||||
function get_config_option(module, section, option, default)
|
||||
return uci:get_first(module, section, option) or default
|
||||
end
|
||||
|
||||
return m
|
||||
|
||||
28
luci-app-smartdns/luasrc/view/smartdns/smartdns_status.htm
Normal file
28
luci-app-smartdns/luasrc/view/smartdns/smartdns_status.htm
Normal file
@@ -0,0 +1,28 @@
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(3, '<%=luci.dispatcher.build_url("admin", "services", "smartdns", "status")%>', null,
|
||||
function(x, data) {
|
||||
var tb = document.getElementById('smartdns_status');
|
||||
if (data && tb) {
|
||||
var links = "";
|
||||
if (data.running) {
|
||||
links = '<b><font color=green>SmartDNS - <%:RUNNING%></font></b></em>';
|
||||
if (data.dnsmasq_redirect_failure == 1) {
|
||||
links += "<br></br><b><font color=red><%:Dnsmasq Forwarded To Smartdns Failure%></font></b>"
|
||||
}
|
||||
} else {
|
||||
links = '<b><font color=red>SmartDNS - <%:NOT RUNNING%></font></b>';
|
||||
}
|
||||
|
||||
tb.innerHTML = links;
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]>
|
||||
</script>
|
||||
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
|
||||
<fieldset class="cbi-section">
|
||||
<p id="smartdns_status">
|
||||
<em><%:Collecting data...%></em>
|
||||
</p>
|
||||
</fieldset>
|
||||
|
||||
854
luci-app-smartdns/po/zh-cn/smartdns.po
Normal file
854
luci-app-smartdns/po/zh-cn/smartdns.po
Normal file
@@ -0,0 +1,854 @@
|
||||
|
||||
msgid "Additional Args for upstream dns servers"
|
||||
msgstr "额外的上游 DNS 服务器参数"
|
||||
|
||||
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 "额外规则标识"
|
||||
|
||||
msgid "Additional Server Args"
|
||||
msgstr "额外的服务器参数"
|
||||
|
||||
msgid "Additional server args, refer to the help description of the bind option."
|
||||
msgstr "额外的服务器参数,参考bind选项的帮助说明。"
|
||||
|
||||
msgid "Advanced Settings"
|
||||
msgstr "高级设置"
|
||||
|
||||
msgid "Audit Log Output Mode"
|
||||
msgstr "审计日志输出模式"
|
||||
|
||||
msgid "Audit Log Size"
|
||||
msgstr "审计日志大小"
|
||||
|
||||
msgid "Audit Log Number"
|
||||
msgstr "审计日志数量"
|
||||
|
||||
msgid "Audit Log File"
|
||||
msgstr "审计日志文件路径"
|
||||
|
||||
msgid ""
|
||||
"Attempts to serve old responses from cache with a TTL of 0 in the response "
|
||||
"without waiting for the actual resolution to finish."
|
||||
msgstr "查询性能优化,有请求时尝试回应TTL为0的过期记录,以避免查询等待。"
|
||||
|
||||
msgid "Automatically Set Dnsmasq"
|
||||
msgstr "自动设置Dnsmasq"
|
||||
|
||||
msgid "Automatically set as upstream of dnsmasq when port changes."
|
||||
msgstr "端口更改时自动设为 dnsmasq 的上游。"
|
||||
|
||||
msgid "Basic Settings"
|
||||
msgstr "基本设置"
|
||||
|
||||
msgid "Bind Device"
|
||||
msgstr "绑定到设备"
|
||||
|
||||
msgid "Bind Device Name"
|
||||
msgstr "绑定的设备名称"
|
||||
|
||||
msgid "Bogus nxdomain"
|
||||
msgstr "假冒IP"
|
||||
|
||||
msgid "Blacklist IP"
|
||||
msgstr "黑名单"
|
||||
|
||||
msgid "Blacklist IP Rule, Decline IP addresses within the range."
|
||||
msgstr "黑名单规则,拒绝指定范围的IP地址。"
|
||||
|
||||
msgid "Block domain"
|
||||
msgstr "屏蔽域名"
|
||||
|
||||
msgid "Block domain."
|
||||
msgstr "屏蔽域名。"
|
||||
|
||||
msgid "Cache Persist"
|
||||
msgstr "持久化缓存"
|
||||
|
||||
msgid "Cache Size"
|
||||
msgstr "缓存大小"
|
||||
|
||||
msgid "Client Rules"
|
||||
msgstr "客户端规则"
|
||||
|
||||
msgid "Client Address"
|
||||
msgstr "客户端地址"
|
||||
|
||||
msgid "Client Address File"
|
||||
msgstr "客户端地址文件"
|
||||
|
||||
msgid "Client Rules Settings, can achieve parental control functionality."
|
||||
msgstr "客户端规则设置,可以实现家长控制功能。"
|
||||
|
||||
msgid "Collecting data ..."
|
||||
msgstr "正在收集数据..."
|
||||
|
||||
msgid ""
|
||||
"Configure IP blacklists that will be filtered from the results of specific "
|
||||
"DNS server."
|
||||
msgstr "配置需要从指定域名服务器结果过滤的IP黑名单。"
|
||||
|
||||
msgid "Configure block domain list."
|
||||
msgstr "配置屏蔽域名列表"
|
||||
|
||||
msgid "Configure domain rule list."
|
||||
msgstr "配置域名规则列表"
|
||||
|
||||
msgid "Configure forwarding domain name list."
|
||||
msgstr "配置分流域名列表"
|
||||
|
||||
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 "域名屏蔽设置"
|
||||
|
||||
msgid "DNS Forwarding Setting"
|
||||
msgstr "域名分流设置"
|
||||
|
||||
msgid "DNS Server Name"
|
||||
msgstr "DNS服务器名称"
|
||||
|
||||
msgid "DNS Server group"
|
||||
msgstr "服务器组"
|
||||
|
||||
msgid "DNS Server group belongs to, such as office, home."
|
||||
msgstr "设置服务器组,例如office,home"
|
||||
|
||||
msgid "DNS Server ip"
|
||||
msgstr "DNS服务器IP"
|
||||
|
||||
msgid "DNS Server port"
|
||||
msgstr "DNS服务器端口"
|
||||
|
||||
msgid "DNS Server type"
|
||||
msgstr "协议类型"
|
||||
|
||||
msgid "DNS domain result cache size"
|
||||
msgstr "缓存DNS的结果,缓存大小,配置零则不缓存。"
|
||||
|
||||
msgid "DNS64"
|
||||
msgstr "DNS64"
|
||||
|
||||
msgid "DNS64 Server Settings"
|
||||
msgstr "DNS64服务器配置"
|
||||
|
||||
msgid "default"
|
||||
msgstr "默认"
|
||||
|
||||
msgid "Description"
|
||||
msgstr "描述"
|
||||
|
||||
msgid "Dnsmasq Forwarded To Smartdns Failure"
|
||||
msgstr "重定向dnsmasq到smartdns失败"
|
||||
|
||||
msgid "Do not check certificate."
|
||||
msgstr "不校验证书的合法性。"
|
||||
|
||||
msgid "Do not check speed."
|
||||
msgstr "禁用测速。"
|
||||
|
||||
msgid "Domain Address"
|
||||
msgstr "域名地址"
|
||||
|
||||
msgid "Domain List"
|
||||
msgstr "域名列表"
|
||||
|
||||
msgid "Domain List File"
|
||||
msgstr "域名列表文件"
|
||||
|
||||
msgid "Domain Rule List"
|
||||
msgstr "域名规则列表"
|
||||
|
||||
msgid "Domain Rule Name"
|
||||
msgstr "域名规则名称"
|
||||
|
||||
msgid "Domain Rules"
|
||||
msgstr "域名规则"
|
||||
|
||||
msgid "Domain Rules Settings"
|
||||
msgstr "域名规则设置"
|
||||
|
||||
msgid "Domain TTL"
|
||||
msgstr "域名TTL"
|
||||
|
||||
msgid "Domain TTL Max"
|
||||
msgstr "域名TTL最大值"
|
||||
|
||||
msgid "Domain TTL Min"
|
||||
msgstr "域名TTL最小值"
|
||||
|
||||
msgid "Domain prefetch"
|
||||
msgstr "域名预加载"
|
||||
|
||||
msgid "Donate"
|
||||
msgstr "捐助"
|
||||
|
||||
msgid "Donate to smartdns"
|
||||
msgstr "捐助smartdns项目"
|
||||
|
||||
msgid "Download Files"
|
||||
msgstr "下载文件"
|
||||
|
||||
msgid "Download Files Setting"
|
||||
msgstr "下载文件设置"
|
||||
|
||||
msgid ""
|
||||
"Download domain list files for domain-rule and include config files, please "
|
||||
"refresh the page after download to take effect."
|
||||
msgstr ""
|
||||
"下载域名规则所需要的域名列表文件和smartdns配置文件,下载完成后刷新页面。"
|
||||
|
||||
msgid "Dual-stack IP Selection"
|
||||
msgstr "双栈IP优选"
|
||||
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Enable Auto Update"
|
||||
msgstr "启用自动更新"
|
||||
|
||||
msgid "Enable IP selection between IPV4 and IPV6"
|
||||
msgstr "启用 IPV4 和 IPV6 间的 IP 优选策略。"
|
||||
|
||||
msgid "Enable IPV6 DNS Server"
|
||||
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 Audit Log"
|
||||
msgstr "启用审计日志"
|
||||
|
||||
msgid "Enable domain prefetch, accelerate domain response speed."
|
||||
msgstr "启用域名预加载,加速域名响应速度。"
|
||||
|
||||
msgid "Enable or disable second DNS server."
|
||||
msgstr "是否启用第二DNS服务器。"
|
||||
|
||||
msgid "Enable or disable smartdns server"
|
||||
msgstr "启用或禁用SmartDNS服务"
|
||||
|
||||
msgid "Exclude DNS Server from default group."
|
||||
msgstr "从default默认服务器组中排除。"
|
||||
|
||||
msgid "Exclude Default Group"
|
||||
msgstr "从默认组中排除"
|
||||
|
||||
msgid "file"
|
||||
msgstr "文件"
|
||||
|
||||
msgid "Fastest IP"
|
||||
msgstr "最快IP"
|
||||
|
||||
msgid "Fastest Response"
|
||||
msgstr "最快响应"
|
||||
|
||||
msgid "File Name"
|
||||
msgstr "文件名"
|
||||
|
||||
msgid "File Type"
|
||||
msgstr "文件类型"
|
||||
|
||||
msgid "Filtering IP with blacklist"
|
||||
msgstr "使用IP黑名单过滤"
|
||||
|
||||
msgid "First Ping"
|
||||
msgstr "最快PING"
|
||||
|
||||
msgid "Force AAAA SOA"
|
||||
msgstr "停用IPV6地址解析"
|
||||
|
||||
msgid "Force AAAA SOA."
|
||||
msgstr "停用IPV6地址解析。"
|
||||
|
||||
msgid "Force HTTPS SOA"
|
||||
msgstr "停用HTTPS记录解析"
|
||||
|
||||
msgid "Force HTTPS SOA."
|
||||
msgstr "停用HTTPS记录解析。"
|
||||
|
||||
msgid "General Settings"
|
||||
msgstr "常规设置"
|
||||
|
||||
msgid "Generate Coredump"
|
||||
msgstr "生成coredump"
|
||||
|
||||
msgid ""
|
||||
"Generate Coredump file when smartdns crash, coredump file is located at /tmp/"
|
||||
"smartdns.xxx.core."
|
||||
msgstr ""
|
||||
"当smartdns异常时生成coredump文件,coredump文件在/tmp/smartdns.xxx.core."
|
||||
|
||||
msgid "Grant access to LuCI app smartdns"
|
||||
msgstr "授予访问 LuCI 应用 smartdns 的权限"
|
||||
|
||||
msgid "Hosts File"
|
||||
msgstr "Hosts文件"
|
||||
|
||||
msgid "HTTP Host"
|
||||
msgstr "HTTP主机"
|
||||
|
||||
msgid "IP alias"
|
||||
msgstr "IP别名"
|
||||
|
||||
msgid "IP Alias Setting"
|
||||
msgstr "IP别名设置"
|
||||
|
||||
msgid "IP Blacklist"
|
||||
msgstr "IP黑名单"
|
||||
|
||||
msgid "IP Blacklist Filtering"
|
||||
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 Rules"
|
||||
msgstr "IP规则"
|
||||
|
||||
msgid "IP Rules Settings"
|
||||
msgstr "IP规则设置"
|
||||
|
||||
msgid "IP Rule Name"
|
||||
msgstr "IP规则名称"
|
||||
|
||||
msgid "IP Set File"
|
||||
msgstr "IP集合列表文件"
|
||||
|
||||
msgid "IP addresses, CIDR format."
|
||||
msgstr "IP地址,CIDR格式。"
|
||||
|
||||
msgid "IPV6 Server"
|
||||
msgstr "IPV6服务器"
|
||||
|
||||
msgid "IPset Name"
|
||||
msgstr "IPset名称"
|
||||
|
||||
msgid "IPset name."
|
||||
msgstr "IPset名称。"
|
||||
|
||||
msgid ""
|
||||
"If a client address is specified, only that client will apply this "
|
||||
"rule. You can enter an IP address, such as 1.2.3.4, or a MAC address, "
|
||||
"such as aa:bb:cc:dd:ee:ff."
|
||||
msgstr ""
|
||||
"如果指定了客户端,那么对应的客户端会应用相应的规则,可以输入IP地址,如:1.2.3.4,或MAC地址,如:aa:bb:cc:dd:ee:ff。"
|
||||
|
||||
msgid "If you like this software, please buy me a cup of coffee."
|
||||
msgstr "如果本软件对你有帮助,请给作者加个蛋。"
|
||||
|
||||
msgid "Include Config Files<br>/etc/smartdns/conf.d"
|
||||
msgstr "包含配置文件<br>/etc/smartdns/conf.d"
|
||||
|
||||
msgid "Include hosts file."
|
||||
msgstr "包含hosts文件。"
|
||||
|
||||
msgid ""
|
||||
"Include other config files from /etc/smartdns/conf.d or custom path, can be "
|
||||
"downloaded from the download page."
|
||||
msgstr ""
|
||||
"包含配置文件,路径为/etc/smartdns/conf.d,或自定义配置文件路径,可以从下载页"
|
||||
"配置自动下载。面配置自动下载。"
|
||||
|
||||
msgid "Ipset name, Add domain result to ipset when speed check fails."
|
||||
msgstr "IPset名称,当测速失败时,将查询到的结果添加到对应的IPSet集合中。"
|
||||
|
||||
msgid "List of files to download."
|
||||
msgstr "下载文件列表。"
|
||||
|
||||
msgid "Listen only on the specified interfaces."
|
||||
msgstr "监听在指定的设备上,避免非本地网络的DNS查询请求。"
|
||||
|
||||
msgid "Local Port"
|
||||
msgstr "本地端口"
|
||||
|
||||
msgid "Log Output Mode"
|
||||
msgstr "日志输出模式"
|
||||
|
||||
msgid "Log Size"
|
||||
msgstr "日志大小"
|
||||
|
||||
msgid "Log Level"
|
||||
msgstr "日志级别"
|
||||
|
||||
msgid "Log Number"
|
||||
msgstr "日志数量"
|
||||
|
||||
msgid "Log File"
|
||||
msgstr "日志文件路径"
|
||||
|
||||
msgid "mDNS Lookup"
|
||||
msgstr "mDNS查询"
|
||||
|
||||
msgid "Marking Packets"
|
||||
msgstr "数据包标记"
|
||||
|
||||
msgid "Maximum TTL for all domain result."
|
||||
msgstr "所有域名的最大 TTL 值。"
|
||||
|
||||
msgid "Minimum TTL for all domain result."
|
||||
msgstr "所有域名的最小 TTL 值。"
|
||||
|
||||
msgid "NFTset Name"
|
||||
msgstr "NFTSet名称"
|
||||
|
||||
msgid "NFTset name format error, format: [#[4|6]:[family#table#set]]"
|
||||
msgstr "NFTSet名称格式错误,格式:[#[4|6]:[family#table#set]]"
|
||||
|
||||
msgid "NFTset name, format: [#[4|6]:[family#table#set]]"
|
||||
msgstr "NFTSet名称,格式:[#[4|6]:[family#table#set]]"
|
||||
|
||||
msgid "NOT RUNNING"
|
||||
msgstr "未运行"
|
||||
|
||||
msgid "Name of device name listen on."
|
||||
msgstr "绑定的设备名称。"
|
||||
|
||||
msgid ""
|
||||
"Nftset name, Add domain result to nftset when speed check fails, format: "
|
||||
"[#[4|6]:[family#table#set]]"
|
||||
msgstr "NFTset名称,当测速失败时,将查询到的结果添加到对应的NFTSet集合中。"
|
||||
|
||||
msgid "No"
|
||||
msgstr "否"
|
||||
|
||||
msgid "No Speed IPset Name"
|
||||
msgstr "无速度时IPSet名称"
|
||||
|
||||
msgid "No Speed NFTset Name"
|
||||
msgstr "无速度时NFTSet名称"
|
||||
|
||||
msgid "No check certificate"
|
||||
msgstr "停用证书校验"
|
||||
|
||||
msgid "None"
|
||||
msgstr "无"
|
||||
|
||||
msgid "Only socks5 proxy support udp server."
|
||||
msgstr "仅SOCKS5代理支持UDP服务器。"
|
||||
|
||||
msgid "Please set proxy server first."
|
||||
msgstr "请先设置代理服务器。"
|
||||
|
||||
msgid "Proxy Server"
|
||||
msgstr "代理服务器"
|
||||
|
||||
msgid "Proxy Server Settings"
|
||||
msgstr "代理服务器设置"
|
||||
|
||||
msgid "Proxy Server URL, format: [socks5|http]://user:pass@ip:port."
|
||||
msgstr "代理服务器地址,格式:[socks5|http]://user:pass@ip:port。"
|
||||
|
||||
msgid ""
|
||||
"Proxy server URL format error, format: [socks5|http]://user:pass@ip:port."
|
||||
msgstr "代理服务器地址格式错误,格式:[socks5|http]://user:pass@ip:port。"
|
||||
|
||||
msgid "Query DNS through specific dns server group, such as office, home."
|
||||
msgstr "使用指定服务器组查询,比如office, home。"
|
||||
|
||||
msgid "RUNNING"
|
||||
msgstr "运行中"
|
||||
|
||||
msgid "Reply Domain TTL Max"
|
||||
msgstr "回应的域名TTL最大值"
|
||||
|
||||
msgid "Reply maximum TTL for all domain result."
|
||||
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 "解析本地主机名"
|
||||
|
||||
msgid "Resolve local hostnames by reading Dnsmasq lease file."
|
||||
msgstr "读取Dnsmasq的租约文件解析本地主机名。"
|
||||
|
||||
msgid "Resolve local network hostname via mDNS protocol."
|
||||
msgstr "使用mDNS协议解析本地网络主机名。"
|
||||
|
||||
msgid "Response Mode"
|
||||
msgstr "响应模式"
|
||||
|
||||
msgid "Restart"
|
||||
msgstr "重启"
|
||||
|
||||
msgid "Restart Service"
|
||||
msgstr "重启服务"
|
||||
|
||||
msgid "syslog"
|
||||
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 "缓存过期服务"
|
||||
|
||||
msgid "Server Group"
|
||||
msgstr "服务器组"
|
||||
|
||||
msgid "Server Group %s not exists"
|
||||
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地址。"
|
||||
|
||||
msgid "Set Specific domain rule list."
|
||||
msgstr "设置指定域名的规则列表。"
|
||||
|
||||
msgid "Set Specific ip blacklist."
|
||||
msgstr "设置指定的 IP 黑名单列表。"
|
||||
|
||||
msgid "Set TLS hostname to verify."
|
||||
msgstr "设置校验TLS主机名。"
|
||||
|
||||
msgid "Set mark on packets."
|
||||
msgstr "设置数据包标记。"
|
||||
|
||||
msgid ""
|
||||
"Set the HTTP host used for the query. Use this parameter when the host of "
|
||||
"the URL address is an IP address."
|
||||
msgstr "设置查询时使用的HTTP主机,当URL地址的host是IP地址时,使用此参数。"
|
||||
|
||||
msgid "Sets the server name indication for query. '-' for disable SNI name."
|
||||
msgstr "设置服务器SNI名称,‘-’表示禁用SNI名称。"
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "设置"
|
||||
|
||||
msgid "Skip Address Rules"
|
||||
msgstr "跳过address规则"
|
||||
|
||||
msgid "Skip Cache"
|
||||
msgstr "跳过cache"
|
||||
|
||||
msgid "Skip Cache."
|
||||
msgstr "跳过cache。"
|
||||
|
||||
msgid "Skip Dualstack Selection"
|
||||
msgstr "跳过双栈优选"
|
||||
|
||||
msgid "Skip Dualstack Selection."
|
||||
msgstr "跳过双栈优选。"
|
||||
|
||||
msgid "Skip IP Alias"
|
||||
msgstr "跳过IP别名"
|
||||
|
||||
msgid "Skip Ipset Rule"
|
||||
msgstr "跳过ipset规则"
|
||||
|
||||
msgid "Skip Nameserver Rule"
|
||||
msgstr "跳过Nameserver规则"
|
||||
|
||||
msgid "Skip SOA Address Rule"
|
||||
msgstr "跳过address SOA(#)规则"
|
||||
|
||||
msgid "Skip SOA address rules."
|
||||
msgstr "跳过address SOA(#)规则。"
|
||||
|
||||
msgid "Skip Speed Check"
|
||||
msgstr "跳过测速"
|
||||
|
||||
msgid "Skip address rules."
|
||||
msgstr "跳过address规则。"
|
||||
|
||||
msgid "Skip ipset rules."
|
||||
msgstr "跳过ipset规则。"
|
||||
|
||||
msgid "Skip nameserver rules."
|
||||
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 服务器"
|
||||
|
||||
msgid ""
|
||||
"SmartDNS is a local high-performance DNS server, supports finding fastest "
|
||||
"IP, supports ad filtering, and supports avoiding DNS poisoning."
|
||||
msgstr "SmartDNS是一个本地高性能DNS服务器,支持返回最快IP,支持广告过滤。"
|
||||
|
||||
msgid "SmartDNS official website"
|
||||
msgstr "SmartDNS官方网站"
|
||||
|
||||
msgid "Smartdns local server port"
|
||||
msgstr "SmartDNS本地服务端口"
|
||||
|
||||
msgid ""
|
||||
"Smartdns local server port, smartdns will be automatically set as main dns "
|
||||
"when the port is 53."
|
||||
msgstr ""
|
||||
"SmartDNS本地服务端口,当端口号设置为53时,smartdns将会自动配置为主dns。"
|
||||
|
||||
msgid ""
|
||||
"Smartdns response mode, First Ping: return the first ping IP, Fastest IP: "
|
||||
"return the fastest IP, Fastest Response: return the fastest DNS response."
|
||||
msgstr ""
|
||||
"SmartDNS响应模式,最快PING: 返回最早有ping结果的IP,速度适中;最快IP: 返回"
|
||||
"最快IP,查询请求可能延长; 最快响应:返回最快响应的结果,查询请求时间短。"
|
||||
|
||||
msgid "Smartdns server name"
|
||||
msgstr "SmartDNS的服务器名称,默认为smartdns,留空为主机名"
|
||||
|
||||
msgid "Smartdns speed check mode."
|
||||
msgstr "SmartDNS测速模式。"
|
||||
|
||||
msgid ""
|
||||
"Specify an IP address to return for any host in the given domains, Queries "
|
||||
"in the domains are never forwarded and always replied to with the specified "
|
||||
"IP address which may be IPv4 or IPv6."
|
||||
msgstr ""
|
||||
"配置特定域名返回特定的IP地址,域名查询将不到上游服务器请求,直接返回配置的IP"
|
||||
"地址,可用于广告屏蔽。"
|
||||
|
||||
msgid "Speed Check Mode"
|
||||
msgstr "测速模式"
|
||||
|
||||
msgid "Speed check mode is invalid."
|
||||
msgstr "测速模式无效。"
|
||||
|
||||
msgid "TCP Server"
|
||||
msgstr "TCP服务器"
|
||||
|
||||
msgid "TCP port is empty"
|
||||
msgstr "TCP端口号为空"
|
||||
|
||||
msgid "TLS Hostname Verify"
|
||||
msgstr "校验TLS主机名"
|
||||
|
||||
msgid "TLS SNI name"
|
||||
msgstr "TLS SNI名称"
|
||||
|
||||
msgid "TLS SPKI Pinning"
|
||||
msgstr "TLS SPKI 指纹"
|
||||
|
||||
msgid "TTL for all domain result."
|
||||
msgstr "设置所有域名的 TTL 值。"
|
||||
|
||||
msgid "Technical Support"
|
||||
msgstr "技术支持"
|
||||
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
msgid "URL format error, format: http:// or https://"
|
||||
msgstr "URL格式错误,格式:http://或https://"
|
||||
|
||||
msgid "Update"
|
||||
msgstr "更新"
|
||||
|
||||
msgid "Update Files"
|
||||
msgstr "更新文件"
|
||||
|
||||
msgid "Upload client address file, same as Client Address function."
|
||||
msgstr "上传客户端地址文件,与客户端地址功能相同。"
|
||||
|
||||
msgid "Upload Config File"
|
||||
msgstr "上传配置文件"
|
||||
|
||||
msgid "Upload Domain List File"
|
||||
msgstr "上传域名列表文件"
|
||||
|
||||
msgid "Upload domain list file to /etc/smartdns/domain-set"
|
||||
msgstr "上传域名列表文件到/etc/smartdns/domain-set"
|
||||
|
||||
msgid ""
|
||||
"Upload domain list file, or configure auto download from Download File "
|
||||
"Setting page."
|
||||
msgstr "上传域名列表文件,或在下载文件设置页面设置自动下载。"
|
||||
|
||||
msgid "Upload domain list file."
|
||||
msgstr "上传域名列表文件"
|
||||
|
||||
msgid "Upload File"
|
||||
msgstr "上传文件"
|
||||
|
||||
msgid "Upload IP set file."
|
||||
msgstr "上传IP集合列表文件。"
|
||||
|
||||
msgid "Upload smartdns config file to /etc/smartdns/conf.d"
|
||||
msgstr "上传配置文件到/etc/smartdns/conf.d"
|
||||
|
||||
msgid "Upstream DNS Server Configuration"
|
||||
msgstr "上游DNS服务器配置"
|
||||
|
||||
msgid "Upstream Servers"
|
||||
msgstr "上游服务器"
|
||||
|
||||
msgid ""
|
||||
"Upstream Servers, support UDP, TCP protocol. Please configure multiple DNS "
|
||||
"servers, including multiple foreign DNS servers."
|
||||
msgstr ""
|
||||
"上游 DNS 服务器,支持 UDP,TCP 协议。请配置多个上游 DNS 服务器,包括多个国内"
|
||||
"外服务器。"
|
||||
|
||||
msgid "Use Proxy"
|
||||
msgstr "使用代理"
|
||||
|
||||
msgid "Use proxy to connect to upstream DNS server."
|
||||
msgstr "使用代理连接上游DNS服务器。"
|
||||
|
||||
msgid ""
|
||||
"Used to verify the validity of the TLS server, The value is Base64 encoded "
|
||||
"SPKI fingerprint, leaving blank to indicate that the validity of TLS is not "
|
||||
"verified."
|
||||
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到磁盘,启动时加载。"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr "是"
|
||||
|
||||
msgid "default"
|
||||
msgstr "默认"
|
||||
|
||||
msgid "domain list (/etc/smartdns/domain-set)"
|
||||
msgstr "域名列表(/etc/smartdns/domain-set)"
|
||||
|
||||
msgid "other file (/etc/smartdns/download)"
|
||||
msgstr "其它文件(/etc/smartdns/download)"
|
||||
|
||||
msgid "https"
|
||||
msgstr "https"
|
||||
|
||||
msgid "ip"
|
||||
msgstr "ip"
|
||||
|
||||
msgid "ip-set file (/etc/smartdns/ip-set)"
|
||||
msgstr "IP集合列表文件(/etc/smartdns/ip-set)"
|
||||
|
||||
msgid "ipset name format error, format: [#[4|6]:]ipsetname"
|
||||
msgstr "IPset名称格式错误,格式:[#[4|6]:]ipsetname"
|
||||
|
||||
msgid "open website"
|
||||
msgstr "打开网站"
|
||||
|
||||
msgid "port"
|
||||
msgstr "端口"
|
||||
|
||||
msgid "smartdns config (/etc/smartdns/conf.d)"
|
||||
msgstr "smartdns 配置文件(/etc/smartdns/conf.d)"
|
||||
|
||||
msgid "smartdns custom settings"
|
||||
msgstr "smartdns 自定义设置,具体配置参数参考指导"
|
||||
|
||||
msgid "tcp"
|
||||
msgstr "tcp"
|
||||
|
||||
msgid "tls"
|
||||
msgstr "tls"
|
||||
|
||||
msgid "type"
|
||||
msgstr "类型"
|
||||
|
||||
msgid "udp"
|
||||
msgstr "udp"
|
||||
1
luci-app-smartdns/po/zh_Hans
Symbolic link
1
luci-app-smartdns/po/zh_Hans
Symbolic link
@@ -0,0 +1 @@
|
||||
zh-cn
|
||||
26
luci-app-smartdns/root/etc/uci-defaults/50_luci-smartdns
Normal file
26
luci-app-smartdns/root/etc/uci-defaults/50_luci-smartdns
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2018-2024 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/>.
|
||||
|
||||
uci -q batch <<-EOF >/dev/null
|
||||
delete ucitrack.@smartdns[-1]
|
||||
add ucitrack smartdns
|
||||
set ucitrack.@smartdns[-1].init=smartdns
|
||||
commit ucitrack
|
||||
EOF
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
||||
202
luci-app-tcpdump/LICENSE
Normal file
202
luci-app-tcpdump/LICENSE
Normal file
@@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
20
luci-app-tcpdump/Makefile
Normal file
20
luci-app-tcpdump/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2016 Openwrt.org
|
||||
#
|
||||
# This is free software, licensed under the Apache License, Version 2.0 .
|
||||
#
|
||||
# Copyright (C) 2019, KFERMercer <iMercer@yeah.net>
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for tcpdump
|
||||
LUCI_DEPENDS:=+tcpdump
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-tcpdump
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=2
|
||||
PKG_MAINTAINER:=<https://github.com/KFERMercer/luci-app-tcpdump>
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
# call BuildPackage - OpenWrt buildroot signature
|
||||
13
luci-app-tcpdump/README.md
Normal file
13
luci-app-tcpdump/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# luci-app-tcpdump
|
||||
|
||||
LuCI interface for tcpdump.\
|
||||
It can be used to capture live TCP traffic for analysis.
|
||||
|
||||
## How to build into firmware:
|
||||
|
||||
`git clone https://github.com/KFERMercer/luci-app-tcpdump.git ./package/luci-app-tcpdump`
|
||||
|
||||
`make menuconfig`
|
||||
|
||||
|
||||
### Original codes built by [MacManas](https://github.com/MacManas/luci-app-tcpdump).
|
||||
356
luci-app-tcpdump/luasrc/controller/tcpdump.lua
Normal file
356
luci-app-tcpdump/luasrc/controller/tcpdump.lua
Normal file
@@ -0,0 +1,356 @@
|
||||
--[[
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
|
||||
Copyright 2013-2014 Diego Manas <diegomanas.dev@gmail.com>
|
||||
|
||||
Copyright (C) 2019, KFERMercer <iMercer@yeah.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
2019-07-12 modified by KFERMercer <iMercer@yeah.com>:
|
||||
format code
|
||||
|
||||
]] --
|
||||
module("luci.controller.tcpdump", package.seeall)
|
||||
|
||||
tcpdump_root_folder = "/tmp/tcpdump/"
|
||||
tcpdump_cap_folder = tcpdump_root_folder .. "cap/"
|
||||
tcpdump_filter_folder = tcpdump_root_folder .. "filter/"
|
||||
pid_file = tcpdump_root_folder .. "tcpdump.pid"
|
||||
log_file = tcpdump_root_folder .. "tcpdump.log"
|
||||
out_file = tcpdump_root_folder .. "tcpdump.out"
|
||||
sleep_file = tcpdump_root_folder .. "tcpdump.sleep"
|
||||
|
||||
function index()
|
||||
template("myapp-mymodule/helloworld")
|
||||
entry({"admin", "network", "tcpdump"}, template("tcpdump"), _ "Tcpdump", 70).dependent =
|
||||
false
|
||||
|
||||
page = entry({"admin", "network", "tcpdump", "capture_start"},
|
||||
call("capture_start"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "tcpdump", "capture_stop"},
|
||||
call("capture_stop"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "tcpdump", "update"}, call("update"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "tcpdump", "capture_get"},
|
||||
call("capture_get"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "tcpdump", "capture_remove"},
|
||||
call("capture_remove"), nil)
|
||||
page.leaf = true
|
||||
|
||||
end
|
||||
|
||||
function param_check(ifname, stop_value, stop_unit, filter)
|
||||
local check = false
|
||||
local message = {}
|
||||
-- Check interface
|
||||
-- Check for empty interface
|
||||
if ifname == nil or ifname == '' then
|
||||
table.insert(message, "Interface name is null or blank.")
|
||||
end
|
||||
-- Check for existing interface
|
||||
local nixio = require "nixio"
|
||||
for k, v in ipairs(nixio.getifaddrs()) do
|
||||
if v.family == "packet" then
|
||||
if ifname == v.name then
|
||||
check = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Check special interface name "any"
|
||||
if iface == 'any' then check = true end
|
||||
-- ERROR interface name not found
|
||||
if not check then
|
||||
table.insert(message, "Interface does not exist or is not valid.")
|
||||
end
|
||||
-- Check stop condition value
|
||||
if tonumber(stop_value) == nil then
|
||||
check = false
|
||||
table.insert(message, "Capture length parameter must be a number.")
|
||||
end
|
||||
-- Check stop condition flag
|
||||
if stop_unit == nil then
|
||||
check = false
|
||||
table.insert(message, "Capture unit is null or blank.")
|
||||
else
|
||||
stop_unit = string.upper(stop_unit)
|
||||
if stop_unit ~= "T" and stop_unit ~= "P" then
|
||||
check = false
|
||||
table.insert(message, "Capture unit must be Time(T) or packet(P).")
|
||||
end
|
||||
end
|
||||
return check, message
|
||||
end
|
||||
|
||||
function capture_start(ifname, stop_value, stop_unit, filter)
|
||||
local active, pid = capture_active()
|
||||
local res = {}
|
||||
local cmd = {}
|
||||
if active then
|
||||
cmd["ok"] = false
|
||||
cmd["msg"] = {"Previous capture is still ongoing!"}
|
||||
else
|
||||
local check, msg = param_check(ifname, stop_value, stop_unit, filter)
|
||||
if not check then
|
||||
cmd["ok"] = false
|
||||
cmd["msg"] = msg
|
||||
else
|
||||
-- Create temporal folders
|
||||
os.execute("mkdir -p " .. tcpdump_cap_folder)
|
||||
os.execute("mkdir -p " .. tcpdump_filter_folder)
|
||||
local prefix = "capture_" .. os.date("%Y-%m-%d_%H.%M.%S")
|
||||
local pcap_file = tcpdump_cap_folder .. prefix .. ".pcap"
|
||||
local filter_file = tcpdump_filter_folder .. prefix .. ".filter"
|
||||
string_to_file(filter_file, filter)
|
||||
string_to_file(out_file, prefix)
|
||||
tcpdump_start(ifname, stop_value, stop_unit, filter_file, pcap_file)
|
||||
res["filter"] = filter
|
||||
cmd["ok"] = true
|
||||
cmd["msg"] = {"Capture in progress.."}
|
||||
end
|
||||
end
|
||||
res["cmd"] = cmd
|
||||
res["capture"] = capture()
|
||||
res["list"] = list()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(res)
|
||||
end
|
||||
|
||||
function string_to_file(file, data)
|
||||
if data == nil then data = "" end
|
||||
local f = io.open(file, "w")
|
||||
f:write(data)
|
||||
f:close()
|
||||
end
|
||||
|
||||
function tcpdump_start(ifname, stop_value, stop_unit, filter_file, pcap_file)
|
||||
local cmd = "tcpdump -i %s -F %s -w %s"
|
||||
cmd = string.format(cmd, ifname, filter_file, pcap_file)
|
||||
-- Packet limit if required
|
||||
if tonumber(stop_value) ~= 0 and stop_unit == "P" then
|
||||
cmd = cmd .. " -c " .. stop_value
|
||||
end
|
||||
-- Mute output and record PID on pid_file
|
||||
cmd = string.format("%s &> %s & echo $! > %s", cmd, log_file, pid_file)
|
||||
os.execute(cmd)
|
||||
-- Time limit if required
|
||||
if tonumber(stop_value) ~= 0 and stop_unit == "T" then
|
||||
local f = io.open(pid_file, "r")
|
||||
if f ~= nil then
|
||||
local pid = f:read()
|
||||
f:close()
|
||||
local t_out =
|
||||
string.format("sleep %s && kill %s &", stop_value, pid)
|
||||
os.execute(t_out)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function capture_stop()
|
||||
local res = {}
|
||||
local cmd = {}
|
||||
local _, active, pid = capture()
|
||||
if active then
|
||||
luci.sys.process.signal(pid, 9)
|
||||
cmd["ok"] = true
|
||||
cmd["msg"] = {"Capture has been terminated"}
|
||||
else
|
||||
cmd["ok"] = false
|
||||
cmd["msg"] = {"There was not active capture!"}
|
||||
end
|
||||
capture_cleanup()
|
||||
res["cmd"] = cmd
|
||||
res["capture"] = capture()
|
||||
res["list"] = list()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(res)
|
||||
end
|
||||
|
||||
function capture_active()
|
||||
local f = io.open(pid_file, "r")
|
||||
if f ~= nil then
|
||||
pid = f:read()
|
||||
f:close()
|
||||
-- Check it is a legal PID and still alive
|
||||
if tonumber(pid) ~= nil and luci.sys.process.signal(pid, 0) then
|
||||
return true, pid
|
||||
end
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
|
||||
function capture_log()
|
||||
local log
|
||||
local f = io.open(log_file, "r")
|
||||
if f ~= nil then
|
||||
log = f:read("*all")
|
||||
f:close()
|
||||
else
|
||||
log = ""
|
||||
end
|
||||
return log
|
||||
end
|
||||
|
||||
function capture_name()
|
||||
local cap_name = nil
|
||||
local f = io.open(out_file, "r")
|
||||
if f ~= nil then
|
||||
cap_name = f:read()
|
||||
f:close()
|
||||
end
|
||||
return cap_name
|
||||
end
|
||||
|
||||
function capture()
|
||||
local fs = require "nixio.fs"
|
||||
local res = {}
|
||||
local active, pid = capture_active()
|
||||
local msg
|
||||
res["active"] = active
|
||||
res["log"] = capture_log()
|
||||
if active then
|
||||
res["msg"] = "Capture in progress.."
|
||||
res["cap_name"] = capture_name()
|
||||
elseif fs.access(pid_file) then
|
||||
capture_cleanup()
|
||||
res["msg"] = "Process seems to be dead, removing pid file!"
|
||||
else
|
||||
res["msg"] = "No capture in progress"
|
||||
end
|
||||
return res, active, pid
|
||||
end
|
||||
|
||||
function capture_cleanup()
|
||||
-- Careless file removal
|
||||
os.remove(pid_file)
|
||||
os.remove(log_file)
|
||||
os.remove(out_file)
|
||||
local f = io.open(sleep_file, "r")
|
||||
if f ~= nil then
|
||||
pid = f:read()
|
||||
f:close()
|
||||
-- Kill sleep process if still alive
|
||||
if tonumber(pid) ~= nil or not luci.sys.process.signal(pid, 0) then
|
||||
luci.sys.process.signal(pid, 9)
|
||||
end
|
||||
end
|
||||
-- Careless file removal
|
||||
os.remove(sleep_file)
|
||||
end
|
||||
|
||||
function list_entries(cap_name)
|
||||
local fs = require "nixio.fs"
|
||||
local entries = {}
|
||||
local name
|
||||
local size
|
||||
local mtime
|
||||
local filter
|
||||
local glob_str
|
||||
if cap_name == nil then
|
||||
glob_str = tcpdump_cap_folder .. "*.pcap"
|
||||
else
|
||||
glob_str = tcpdump_cap_folder .. cap_name .. ".pcap"
|
||||
end
|
||||
for file in fs.glob(glob_str) do
|
||||
name = string.sub(fs.basename(file), 1, -6)
|
||||
size = fs.stat(file, "size")
|
||||
mtime = fs.stat(file, "ctime")
|
||||
-- Figure out if there's an associated filter
|
||||
if fs.access(tcpdump_filter_folder .. name .. ".filter") then
|
||||
filter = true
|
||||
else
|
||||
filter = false
|
||||
end
|
||||
table.insert(entries,
|
||||
{name = name, size = size, mtime = mtime, filter = filter})
|
||||
end
|
||||
return entries
|
||||
end
|
||||
|
||||
function list(cap_name)
|
||||
res = {}
|
||||
res["entries"] = list_entries(cap_name)
|
||||
res["update"] = (cap_name ~= nil)
|
||||
return res
|
||||
end
|
||||
|
||||
function update(cap_name)
|
||||
local res = {}
|
||||
local cmd = {}
|
||||
cmd["ok"] = true
|
||||
res["cmd"] = cmd
|
||||
res["capture"] = capture()
|
||||
res["list"] = list(cap_name)
|
||||
-- Build response
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(res)
|
||||
end
|
||||
|
||||
function pump_file(file, mime_str)
|
||||
local fh = io.open(file)
|
||||
local reader = luci.ltn12.source.file(fh)
|
||||
luci.http.header("Content-Disposition", "attachment; filename=\"" ..
|
||||
nixio.fs.basename(file) .. "\"")
|
||||
if mime_str ~= nil then
|
||||
luci.http.prepare_content(mime_str)
|
||||
else
|
||||
luci.http.prepare_content("application/octet-stream")
|
||||
end
|
||||
luci.ltn12.pump.all(reader, luci.http.write)
|
||||
fh:close()
|
||||
end
|
||||
|
||||
function capture_get(file_type, cap_name)
|
||||
if file_type == "all" then
|
||||
local system = require "luci.controller.admin.system"
|
||||
local tar_captures_cmd = "tar -c " .. tcpdump_cap_folder ..
|
||||
"*.pcap 2>/dev/null"
|
||||
local reader = system.ltn12_popen(tar_captures_cmd)
|
||||
luci.http.header('Content-Disposition',
|
||||
'attachment; filename="captures-%s.tar"' %
|
||||
{os.date("%Y-%m-%d_%H.%M.%S")})
|
||||
luci.http.prepare_content("application/x-tar")
|
||||
luci.ltn12.pump.all(reader, luci.http.write)
|
||||
elseif file_type == "pcap" then
|
||||
local file = tcpdump_cap_folder .. cap_name .. '.pcap'
|
||||
pump_file(file)
|
||||
elseif file_type == "filter" then
|
||||
local file = tcpdump_filter_folder .. cap_name .. '.filter'
|
||||
pump_file(file, "text/plain")
|
||||
else
|
||||
-- TODO
|
||||
end
|
||||
end
|
||||
|
||||
function capture_remove(cap_name)
|
||||
if cap_name == 'all' then
|
||||
local fs = require "nixio.fs"
|
||||
for file in fs.glob(tcpdump_cap_folder .. "*.pcap") do
|
||||
os.remove(file)
|
||||
end
|
||||
for file in fs.glob(tcpdump_filter_folder .. "*.filter") do
|
||||
os.remove(file)
|
||||
end
|
||||
else
|
||||
-- Remove both, capture and filter file
|
||||
os.remove(tcpdump_cap_folder .. cap_name .. ".pcap")
|
||||
os.remove(tcpdump_filter_folder .. cap_name .. ".filter")
|
||||
end
|
||||
-- Return current status and list
|
||||
update()
|
||||
end
|
||||
246
luci-app-tcpdump/luasrc/view/tcpdump.htm
Normal file
246
luci-app-tcpdump/luasrc/view/tcpdump.htm
Normal file
@@ -0,0 +1,246 @@
|
||||
<%#
|
||||
LuCI - Lua Configuration Interface
|
||||
|
||||
Copyright (C) 2013-2014, Diego Manas <diegomanas.dev@gmail.com>
|
||||
|
||||
Initial layout based on cshark project: https://github.com/cloudshark/cshark
|
||||
Copyright (C) 2014, QA Cafe, Inc.
|
||||
|
||||
Copyright (C) 2019, KFERMercer <iMercer@yeah.net>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
$Id$
|
||||
|
||||
2019-07-12 modified by KFERMercer <iMercer@yeah.com>:
|
||||
format code & change tag name
|
||||
|
||||
-%>
|
||||
<%+header%>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Start network capture%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr>
|
||||
<th><%:Interface%></th>
|
||||
<th colspan='2'><%:seconds, packets%></th>
|
||||
<th><%:Filter%></th>
|
||||
<th><%:Actions%></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<select title="<%:Interface%>" style="width:auto" id="cap_ifname">
|
||||
<%
|
||||
local nixio = require "nixio"
|
||||
for k, v in ipairs(nixio.getifaddrs()) do
|
||||
if v.family == "packet" then
|
||||
%>
|
||||
<option value="<%=v.name%>"><%=v.name%> </option>
|
||||
<%
|
||||
end
|
||||
end
|
||||
%>
|
||||
<option value="any"><%:any%></option>
|
||||
</select>
|
||||
</td>
|
||||
<td colspan='2'>
|
||||
<input id="cap_stop_value" type="text" value="0" />
|
||||
<select title="<%:timeout, bytes, seconds%>" id="cap_stop_unit" style="width:auto">
|
||||
<option value="T"><%:seconds%></option>
|
||||
<option value="P"><%:packets%></option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<input style="margin: 5px 0" type="text" title="<%:Filter%>" placeholder="filter" id="cap_filter" />
|
||||
</td>
|
||||
<td>
|
||||
<input type="button" id="bt_capture" value="<%:Disabled%>" class="cbi-button" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Output%></legend>
|
||||
<span id="tcpdump-message"></span>
|
||||
<span id="tcpdump-log"></span>
|
||||
</fieldset>
|
||||
|
||||
<hr />
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Capture links%></legend>
|
||||
<div class="cbi-section-node">
|
||||
<table id="t_list" class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Capture file%></th>
|
||||
<th class="cbi-section-table-cell"><%:Modification date%></th>
|
||||
<th class="cbi-section-table-cell"><%:Capture size%></th>
|
||||
<th class="cbi-section-table-cell"><%:Actions%></th>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<hr />
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
|
||||
var capture_active = false;
|
||||
var capture_name;
|
||||
|
||||
function update_button() {
|
||||
var bt_capture = document.getElementById('bt_capture');
|
||||
if (!capture_active) {
|
||||
bt_capture.value = '<%:Start capture%>';
|
||||
bt_capture.onclick = capture_start;
|
||||
} else {
|
||||
bt_capture.value = '<%:Stop capture%>';
|
||||
bt_capture.onclick = capture_stop;
|
||||
}
|
||||
bt_capture.disabled = false;
|
||||
}
|
||||
|
||||
function capture_start() {
|
||||
var elem_ifname = document.getElementById('cap_ifname');
|
||||
var elem_stop_value = document.getElementById('cap_stop_value');
|
||||
var elem_stop_unit = document.getElementById('cap_stop_unit');
|
||||
var elem_filter = document.getElementById('cap_filter');
|
||||
|
||||
var ifname = elem_ifname.options[elem_ifname.selectedIndex].value;
|
||||
var stop_value = elem_stop_value.value;
|
||||
var stop_unit = elem_stop_unit.options[elem_stop_unit.selectedIndex].value;
|
||||
var filter = elem_filter.value;
|
||||
// TODO Implement checks?
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "tcpdump")%>/capture_start/' +
|
||||
ifname + '/' + stop_value + '/' + stop_unit + '/' + filter,
|
||||
null, update_callback)
|
||||
}
|
||||
|
||||
function capture_stop() {
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "tcpdump")%>/capture_stop',
|
||||
null, update_callback)
|
||||
}
|
||||
|
||||
function update_poll() {
|
||||
XHR.poll(10, '<%=luci.dispatcher.build_url("admin", "network", "tcpdump")%>/update',
|
||||
null, update_callback)
|
||||
}
|
||||
|
||||
function update_callback(xhr, json) {
|
||||
console.log(xhr)
|
||||
console.log(json)
|
||||
update_table(xhr, json)
|
||||
update_status(xhr, json)
|
||||
}
|
||||
|
||||
function update_table(xhr, json) {
|
||||
var table = document.getElementById("t_list");
|
||||
if (!table) return;
|
||||
// Remove all rows except headers
|
||||
while (table.rows.length > 1) {
|
||||
table.deleteRow(-1);
|
||||
}
|
||||
|
||||
if (!xhr) {
|
||||
var cell = table.insertRow(-1).insertCell(0);
|
||||
cell.colSpan = table.rows[0].cells.length;
|
||||
cell.innerHTML = '<em><br />Could not retrieve captures.</em>';
|
||||
return;
|
||||
}
|
||||
var entries = json.list.entries;
|
||||
if (!entries || !entries.length) {
|
||||
var cell = table.insertRow(-1).insertCell(0);
|
||||
cell.colSpan = table.rows[0].cells.length;
|
||||
cell.innerHTML = '<em><br />There are no captures available yet.</em>';
|
||||
return;
|
||||
}
|
||||
// Add rows
|
||||
var total_size = 0
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
var row = table.insertRow(-1);
|
||||
total_size += entries[i].size;
|
||||
var url = '<%=luci.dispatcher.build_url("admin", "network", "tcpdump")%>'
|
||||
row.insertCell().innerHTML = '<a href="#" onclick="capture_get(\'pcap\', \'' + entries[i].name + '\')">' + entries[i].name + '</a>';
|
||||
row.insertCell().innerHTML = human_date(entries[i].mtime);
|
||||
row.insertCell().innerHTML = human_size(entries[i].size);
|
||||
var cell = row.insertCell();
|
||||
cell.innerHTML += '<input type="button" onclick="capture_get(\'pcap\', \'' + entries[i].name + '\')" class="cbi-button cbi-button-download" value ="<%:pcap file%>" />';
|
||||
cell.innerHTML += '<input type="button" onclick="capture_get(\'filter\', \'' + entries[i].name + '\')" class="cbi-button cbi-button-download" value ="<%:filter file%>" />';
|
||||
cell.lastChild.disabled = !entries[i].filter;
|
||||
cell.innerHTML += '<input type="button" onclick="capture_remove(\'' + entries[i].name + '\')" class="cbi-button cbi-button-reset" value ="<%:Remove%>" />';
|
||||
}
|
||||
// Add summary row at the end
|
||||
var row = table.insertRow(-1);
|
||||
row.insertCell().innerHTML = '<b><%:All files%></b>';
|
||||
row.insertCell();
|
||||
row.insertCell().innerHTML = human_size(total_size);
|
||||
row.insertCell().innerHTML = '<input type="button" onclick="capture_get(\'all\')" class="cbi-button cbi-button-download" value ="<%:Download%>" />';
|
||||
row.cells[row.cells.length - 1].innerHTML += '<input type="button" onclick="capture_remove(\'all\')" class="cbi-button cbi-button-reset" value ="<%:Remove%>" />';
|
||||
}
|
||||
|
||||
function update_status(xhr, json) {
|
||||
capture_active = json.capture.active;
|
||||
capture_name = json.capture.cap_name;
|
||||
var in_use;
|
||||
in_use = document.getElementById("tcpdump-message");
|
||||
var msg = ""
|
||||
if (json.cmd.hasOwnProperty("msg")) {
|
||||
for (var i = 0; i < json.cmd.msg.length; i++) {
|
||||
msg += json.cmd.msg[i] + "\n";
|
||||
}
|
||||
} else {
|
||||
msg = json.capture.msg;
|
||||
}
|
||||
in_use.innerHTML = "<pre>" + msg + "</pre>";
|
||||
in_use = document.getElementById("tcpdump-log");
|
||||
if (capture_active) {
|
||||
in_use.innerHTML = "<pre>" + json.capture.log + "</pre>";
|
||||
} else {
|
||||
in_use.innerHTML = ""
|
||||
}
|
||||
update_button()
|
||||
}
|
||||
|
||||
function human_size(size) {
|
||||
var units = ["B", "KiB", "MiB", "GiB"]
|
||||
var unit_index = 0
|
||||
while (size > 1024 && unit_index < 3) {
|
||||
unit_index += 1
|
||||
size /= 1024
|
||||
}
|
||||
return Math.round(size * 100) / 100 + " " + units[unit_index]
|
||||
}
|
||||
|
||||
function human_date(date_seconds) {
|
||||
var date = new Date(date_seconds * 1000)
|
||||
return date.getDate() + "/" + (date.getMonth() + 1) + "/" + date.getFullYear() + " " +
|
||||
date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds()
|
||||
}
|
||||
|
||||
function capture_get(type, cap_name) {
|
||||
var iframe;
|
||||
iframe = document.getElementById("hiddenDownloader");
|
||||
if (iframe == null) {
|
||||
iframe = document.createElement('iframe');
|
||||
iframe.id = "hiddenDownloader";
|
||||
iframe.style.visibility = 'hidden';
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
iframe.src = '<%=luci.dispatcher.build_url("admin", "network", "tcpdump")%>/capture_get/' + type + '/' + cap_name;
|
||||
}
|
||||
|
||||
function capture_remove(cap_name) {
|
||||
XHR.get('<%=luci.dispatcher.build_url("admin", "network", "tcpdump")%>/capture_remove/' + cap_name, null, update_callback)
|
||||
}
|
||||
|
||||
document.onload = update_poll();
|
||||
//]]></script>
|
||||
<%+footer%>
|
||||
107
luci-app-tcpdump/po/zh-cn/tcpdump.po
Normal file
107
luci-app-tcpdump/po/zh-cn/tcpdump.po
Normal file
@@ -0,0 +1,107 @@
|
||||
msgid "Tcpdump"
|
||||
msgstr "Tcpdump 流量监控"
|
||||
|
||||
msgid "Start network capture"
|
||||
msgstr "Tcpdump 流量监控"
|
||||
|
||||
msgid "Interface"
|
||||
msgstr "捕获指定的接口"
|
||||
|
||||
msgid "seconds, packets"
|
||||
msgstr "捕获限制"
|
||||
|
||||
msgid "Filter"
|
||||
msgstr "过滤"
|
||||
|
||||
msgid "Actions"
|
||||
msgstr "操作"
|
||||
|
||||
msgid "any"
|
||||
msgstr "所有"
|
||||
|
||||
msgid "timeout, bytes, seconds"
|
||||
msgstr "超时, 字节, 秒"
|
||||
|
||||
msgid "seconds"
|
||||
msgstr "秒"
|
||||
|
||||
msgid "packets"
|
||||
msgstr "数据包"
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr "已禁用"
|
||||
|
||||
msgid "Output"
|
||||
msgstr "输出"
|
||||
|
||||
msgid "Capture links"
|
||||
msgstr "捕获结果"
|
||||
|
||||
msgid "Capture file"
|
||||
msgstr "文件名"
|
||||
|
||||
msgid "Modification date"
|
||||
msgstr "停止时间"
|
||||
|
||||
msgid "Capture size"
|
||||
msgstr "文件大小"
|
||||
|
||||
msgid "Start capture"
|
||||
msgstr "开始捕获"
|
||||
|
||||
msgid "Stop capture"
|
||||
msgstr "停止捕获"
|
||||
|
||||
msgid "pcap file"
|
||||
msgstr ".pcap文件"
|
||||
|
||||
msgid "filter file"
|
||||
msgstr ".filter文件"
|
||||
|
||||
msgid "Remove"
|
||||
msgstr "删除"
|
||||
|
||||
msgid "All files"
|
||||
msgstr "所有文件"
|
||||
|
||||
msgid "Download"
|
||||
msgstr "下载"
|
||||
|
||||
msgid "Interface name is null or blank."
|
||||
msgstr "请指定要捕获的接口."
|
||||
|
||||
msgid "Interface does not exist or is not valid."
|
||||
msgstr "接口不存在或无效."
|
||||
|
||||
msgid "Capture length parameter must be a number."
|
||||
msgstr "捕获长度参数必须是数字."
|
||||
|
||||
msgid "Capture unit is null or blank."
|
||||
msgstr "捕获单位为空或空白."
|
||||
|
||||
msgid "Capture unit must be Time(T) or packet(P)."
|
||||
msgstr "捕获单位必须是时间(T)或包(P)."
|
||||
|
||||
msgid "Previous capture is still ongoing!"
|
||||
msgstr "先前的捕获未停止!"
|
||||
|
||||
msgid "Capture in progress.."
|
||||
msgstr "正在捕获..."
|
||||
|
||||
msgid "Capture has been terminated"
|
||||
msgstr "捕获已被终止"
|
||||
|
||||
msgid "There was not active capture!"
|
||||
msgstr "捕获活动未运行!"
|
||||
|
||||
msgid "Process seems to be dead, removing pid file!"
|
||||
msgstr "进程失去响应, 正在删除pid文件!"
|
||||
|
||||
msgid "No capture in progress"
|
||||
msgstr "没有正在进行的捕获"
|
||||
|
||||
msgid "Could not retrieve captures."
|
||||
msgstr "无法检索捕获."
|
||||
|
||||
msgid "There are no captures available yet."
|
||||
msgstr "目前没有可用的捕获."
|
||||
1
luci-app-tcpdump/po/zh_Hans
Symbolic link
1
luci-app-tcpdump/po/zh_Hans
Symbolic link
@@ -0,0 +1 @@
|
||||
zh-cn
|
||||
140
smartdns/Makefile
Normal file
140
smartdns/Makefile
Normal file
@@ -0,0 +1,140 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
# Copyright (c) 2018-2023 Nick Peng (pymumu@gmail.com)
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=smartdns
|
||||
PKG_VERSION:=47.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/pymumu/smartdns/tar.gz/Release$(PKG_VERSION)?
|
||||
PKG_HASH:=0a143ee81ccb7a31b7b7b0c29d6a6ee41a54331da75477719925592af124ec97
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-Release$(PKG_VERSION)
|
||||
|
||||
PKG_MAINTAINER:=Nick Peng <pymumu@gmail.com>
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_smartdns-ui
|
||||
PKG_BUILD_DEPENDS:=PACKAGE_smartdns-ui:node/host PACKAGE_smartdns-ui:rust-bindgen/host
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
|
||||
RUST_PKG_FEATURES:=build-release
|
||||
RUST_PKG_LOCKED:=0
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk
|
||||
|
||||
MAKE_PATH:=src
|
||||
MAKE_VARS+= VER=$(PKG_VERSION)
|
||||
|
||||
define Package/smartdns/Default
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=IP Addresses and Names
|
||||
TITLE:=smartdns
|
||||
URL:=https://www.github.com/pymumu/smartdns/
|
||||
endef
|
||||
|
||||
define Package/smartdns
|
||||
$(call Package/smartdns/Default)
|
||||
TITLE+= server
|
||||
DEPENDS:=+i386:libatomic +libopenssl
|
||||
endef
|
||||
|
||||
define Package/smartdns/description
|
||||
SmartDNS is a local DNS server which accepts DNS query requests from local network clients,
|
||||
gets DNS query results from multiple upstream DNS servers concurrently, and returns the fastest IP to clients.
|
||||
Unlike dnsmasq's all-servers, smartdns returns the fastest IP, and encrypt DNS queries with DoT or DoH.
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui
|
||||
$(call Package/smartdns/Default)
|
||||
TITLE+= dashboard
|
||||
DEPENDS:=+smartdns $(RUST_ARCH_DEPENDS) @!(TARGET_x86_geode||TARGET_x86_legacy)
|
||||
endef
|
||||
|
||||
define Package/smartdns-ui/description
|
||||
A dashboard ui for smartdns server.
|
||||
endef
|
||||
|
||||
define Package/smartdns/conffiles
|
||||
/etc/config/smartdns
|
||||
/etc/smartdns/address.conf
|
||||
/etc/smartdns/blacklist-ip.conf
|
||||
/etc/smartdns/custom.conf
|
||||
/etc/smartdns/domain-block.list
|
||||
/etc/smartdns/domain-forwarding.list
|
||||
endef
|
||||
|
||||
define Download/smartdns-webui
|
||||
PROTO:=git
|
||||
URL:=https://github.com/pymumu/smartdns-webui.git
|
||||
SOURCE_DATE:=2025-09-18
|
||||
SOURCE_VERSION:=c322303eac2ebee389f4a72a002163552e552f74
|
||||
MIRROR_HASH:=b239f3d994e05ad08356bf1be629cd84c2bfc6706997aafea881284cacc29545
|
||||
SUBDIR:=smartdns-webui-$$$$(subst -,.,$$$$(SOURCE_DATE))~$$$$(call version_abbrev,$$$$(SOURCE_VERSION))
|
||||
FILE:=$$(SUBDIR).tar.zst
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
|
||||
ifneq ($(CONFIG_PACKAGE_smartdns-ui),)
|
||||
$(eval $(call Download,smartdns-webui))
|
||||
$(eval $(Download/smartdns-webui))
|
||||
mkdir -p $(PKG_BUILD_DIR)/smartdns-webui
|
||||
zstdcat $(DL_DIR)/$(FILE) | tar -C $(PKG_BUILD_DIR)/smartdns-webui $(TAR_OPTIONS) --strip-components=1
|
||||
endif
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(call Build/Compile/Default)
|
||||
|
||||
ifneq ($(CONFIG_PACKAGE_smartdns-ui),)
|
||||
( \
|
||||
pushd $(PKG_BUILD_DIR) ; \
|
||||
pushd smartdns-webui ; \
|
||||
npm install ; \
|
||||
npm run build ; \
|
||||
popd ; \
|
||||
pushd plugin/smartdns-ui ; \
|
||||
$(CARGO_PKG_CONFIG_VARS) \
|
||||
MAKEFLAGS="$(PKG_JOBS)" \
|
||||
TARGET_CFLAGS="$(filter-out -O%,$(TARGET_CFLAGS)) $(RUSTC_CFLAGS)" \
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=$(TOOLCHAIN_ROOT_DIR)" \
|
||||
cargo build -v --profile $(CARGO_PKG_PROFILE) \
|
||||
$(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \
|
||||
$(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \
|
||||
$(CARGO_PKG_ARGS) ; \
|
||||
popd ; \
|
||||
popd ; \
|
||||
)
|
||||
endif
|
||||
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/
|
||||
$(INSTALL_DIR) $(1)/etc/smartdns/ip-set $(1)/etc/smartdns/download
|
||||
$(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
|
||||
|
||||
define Package/smartdns-ui/install
|
||||
$(INSTALL_DIR) $(1)/usr/lib
|
||||
$(INSTALL_DIR) $(1)/usr/share/smartdns
|
||||
$(CP) $(PKG_BUILD_DIR)/plugin/smartdns-ui/target/$(RUSTC_TARGET_ARCH)/$(CARGO_PKG_PROFILE)/libsmartdns_ui.so $(1)/usr/lib/smartdns_ui.so
|
||||
$(CP) $(PKG_BUILD_DIR)/smartdns-webui/out $(1)/usr/share/smartdns/wwwroot
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,smartdns))
|
||||
$(eval $(call BuildPackage,smartdns-ui))
|
||||
Reference in New Issue
Block a user