mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-26 17:32:51 +08:00
🌴 Sync 2026-09-19 18:46:44
This commit is contained in:
1 parent
375023b135
commit
9e354d0c3e
30 files changed
+322
-1252
No files matched your search
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.9.16
|
||||
PKG_RELEASE:=281
|
||||
PKG_RELEASE:=282
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -564,9 +564,12 @@ o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ tls_certificate = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "tls_certificate_pem") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(Value, "cipherSuites", translate("Cipher Suites"), '<a href="https://go.dev/src/crypto/tls/cipher_suites.go#L44" target="_blank">***</a>' .. " " .. translate("Configures the list of supported cipher suites, separated by :"))
|
||||
@@ -585,9 +588,12 @@ o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ ech = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "ech_config") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(Value, "ech_query_server_name", translate("ECH Query Domain"), translate("Overrides the domain name used for ECH HTTPS record queries."))
|
||||
|
||||
@@ -453,9 +453,12 @@ o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ tls_certificate = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "tls_certificate_pem") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(Flag, "ech", translate("ECH"))
|
||||
|
||||
@@ -253,12 +253,19 @@ o.default = 0
|
||||
o.validate = function(self, value, t)
|
||||
if value then
|
||||
local reality = s.fields["reality"] and s.fields["reality"]:formvalue(t) or nil
|
||||
local use_pem = s.fields["tls_use_pem"] and s.fields["tls_use_pem"]:formvalue(t) or nil
|
||||
if reality and reality == "1" then return value end
|
||||
if value == "1" then
|
||||
if value == "1" and use_pem ~= "1" then
|
||||
local ca = s.fields["tls_certificateFile"] and s.fields["tls_certificateFile"]:formvalue(t) or ""
|
||||
local key = s.fields["tls_keyFile"] and s.fields["tls_keyFile"]:formvalue(t) or ""
|
||||
if ca == "" or key == "" then
|
||||
return nil, translate("Certificate or Private key path can not be empty!")
|
||||
return nil, translate("Certificate and Private key path can not be empty!")
|
||||
end
|
||||
elseif value == "1" and use_pem == "1" then
|
||||
local ca = s.fields["tls_certificate"] and s.fields["tls_certificate"]:formvalue(t) or ""
|
||||
local key = s.fields["tls_key"] and s.fields["tls_key"]:formvalue(t) or ""
|
||||
if ca == "" or key == "" then
|
||||
return nil, translate("Certificate and Private key PEM can not be empty!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
@@ -311,14 +318,21 @@ o:depends({ protocol = "hysteria" })
|
||||
|
||||
-- [[ TLS部分 ]] --
|
||||
|
||||
o = s:option(FileUpload, "tls_certificateFile", translate("Path to the certificate file"), translate("as:") .. "/etc/ssl/fullchain.crt")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".crt"
|
||||
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
|
||||
o = s:option(Flag, "tls_use_pem", translate("Use PEM"), translate("Use certificate and private key PEM content."))
|
||||
o:depends({ tls = true, reality = false })
|
||||
o:depends({ protocol = "naive" })
|
||||
o:depends({ protocol = "hysteria" })
|
||||
o:depends({ protocol = "tuic" })
|
||||
o:depends({ protocol = "hysteria2" })
|
||||
|
||||
o = s:option(FileUpload, "tls_certificateFile", translate("Path to the certificate file"), translate("as:") .. "/etc/ssl/fullchain.crt")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".crt"
|
||||
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
|
||||
o:depends({ tls = true, reality = false, tls_use_pem = false })
|
||||
o:depends({ protocol = "naive", tls_use_pem = false })
|
||||
o:depends({ protocol = "hysteria", tls_use_pem = false })
|
||||
o:depends({ protocol = "tuic", tls_use_pem = false })
|
||||
o:depends({ protocol = "hysteria2", tls_use_pem = false })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not api.fs.access(value) then
|
||||
@@ -333,11 +347,11 @@ end
|
||||
o = s:option(FileUpload, "tls_keyFile", translate("Path to the private key file"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
|
||||
if o and o:formvalue(arg[1]) then o.default = o:formvalue(arg[1]) end
|
||||
o:depends({ tls = true, reality = false })
|
||||
o:depends({ protocol = "naive" })
|
||||
o:depends({ protocol = "hysteria" })
|
||||
o:depends({ protocol = "tuic" })
|
||||
o:depends({ protocol = "hysteria2" })
|
||||
o:depends({ tls = true, reality = false, tls_use_pem = false })
|
||||
o:depends({ protocol = "naive", tls_use_pem = false })
|
||||
o:depends({ protocol = "hysteria", tls_use_pem = false })
|
||||
o:depends({ protocol = "tuic", tls_use_pem = false })
|
||||
o:depends({ protocol = "hysteria2", tls_use_pem = false })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not api.fs.access(value) then
|
||||
@@ -349,6 +363,32 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(TextValue, "tls_certificate", "TLS Certificate (PEM)", translate("Full certificate (chain), PEM format."))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ tls_use_pem = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "tls_certificate") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(TextValue, "tls_key", "TLS Private Key (PEM)", translate("Private key in PEM format."))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ tls_use_pem = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "tls_key") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(Flag, "ech", translate("ECH"))
|
||||
o.default = "0"
|
||||
o:depends({ tls = true, flow = "", reality = false })
|
||||
@@ -362,13 +402,12 @@ o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ ech = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "ech_key") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n")
|
||||
value = value:gsub("^%s*\n", "")
|
||||
if value:sub(-1) == "\n" then
|
||||
value = value:sub(1, -2)
|
||||
end
|
||||
return value
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(ListValue, "transport", translate("Transport"))
|
||||
|
||||
@@ -193,12 +193,19 @@ o.default = 0
|
||||
o.validate = function(self, value, t)
|
||||
if value then
|
||||
local reality = s.fields["reality"] and s.fields["reality"]:formvalue(t) or nil
|
||||
local use_pem = s.fields["tls_use_pem"] and s.fields["tls_use_pem"]:formvalue(t) or nil
|
||||
if reality and reality == "1" then return value end
|
||||
if value == "1" then
|
||||
if value == "1" and use_pem ~= "1" then
|
||||
local ca = s.fields["tls_certificateFile"] and s.fields["tls_certificateFile"]:formvalue(t) or ""
|
||||
local key = s.fields["tls_keyFile"] and s.fields["tls_keyFile"]:formvalue(t) or ""
|
||||
if ca == "" or key == "" then
|
||||
return nil, translate("Certificate or Private key path can not be empty!")
|
||||
return nil, translate("Certificate and Private key path can not be empty!")
|
||||
end
|
||||
elseif value == "1" and use_pem == "1" then
|
||||
local ca = s.fields["tls_certificate"] and s.fields["tls_certificate"]:formvalue(t) or ""
|
||||
local key = s.fields["tls_key"] and s.fields["tls_key"]:formvalue(t) or ""
|
||||
if ca == "" or key == "" then
|
||||
return nil, translate("Certificate and Private key PEM can not be empty!")
|
||||
end
|
||||
end
|
||||
return value
|
||||
@@ -263,11 +270,15 @@ end
|
||||
|
||||
-- [[ TLS部分 ]] --
|
||||
|
||||
o = s:option(Flag, "tls_use_pem", translate("Use PEM"), translate("Use certificate and private key PEM content."))
|
||||
o:depends({ tls = true, reality = false })
|
||||
o:depends({ protocol = "hysteria2" })
|
||||
|
||||
o = s:option(FileUpload, "tls_certificateFile", translate("Path to the certificate file"), translate("as:") .. "/etc/ssl/fullchain.crt")
|
||||
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. s.section .. ".crt"
|
||||
if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end
|
||||
o:depends({ tls = true, reality = false })
|
||||
o:depends({ protocol = "hysteria2"})
|
||||
o:depends({ tls = true, reality = false, tls_use_pem = false })
|
||||
o:depends({ protocol = "hysteria2", tls_use_pem = false })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not api.fs.access(value) then
|
||||
@@ -282,8 +293,8 @@ end
|
||||
o = s:option(FileUpload, "tls_keyFile", translate("Path to the private key file"), translate("as:") .. "/etc/ssl/private.key")
|
||||
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. s.section .. ".key"
|
||||
if o and o:formvalue(s.section) then o.default = o:formvalue(s.section) end
|
||||
o:depends({ tls = true, reality = false })
|
||||
o:depends({ protocol = "hysteria2"})
|
||||
o:depends({ tls = true, reality = false, tls_use_pem = false })
|
||||
o:depends({ protocol = "hysteria2", tls_use_pem = false })
|
||||
o.validate = function(self, value, t)
|
||||
if value and value ~= "" then
|
||||
if not api.fs.access(value) then
|
||||
@@ -295,6 +306,32 @@ o.validate = function(self, value, t)
|
||||
return nil
|
||||
end
|
||||
|
||||
o = s:option(TextValue, "tls_certificate", "TLS Certificate (PEM)", translate("Full certificate (chain), PEM format."))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ tls_use_pem = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "tls_certificate") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(TextValue, "tls_key", "TLS Private Key (PEM)", translate("Private key in PEM format."))
|
||||
o.default = ""
|
||||
o.rows = 5
|
||||
o.wrap = "off"
|
||||
o:depends({ tls_use_pem = true })
|
||||
o.cfgvalue = function(self, section)
|
||||
return (m:get(section, "tls_key") or ""):gsub("\\n", "\n")
|
||||
end
|
||||
o.validate = function(self, value)
|
||||
value = api.trim(value):gsub("\r\n", "\n"):gsub("\r", "\n"):gsub("[ \t]*\n[ \t]*", "\n"):gsub("\n+", "\n")
|
||||
return value:gsub("\n", "\\n")
|
||||
end
|
||||
|
||||
o = s:option(Flag, "ech", translate("ECH"))
|
||||
o.default = "0"
|
||||
o:depends({ tls = true, reality = false })
|
||||
|
||||
@@ -248,7 +248,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
--max_version = "1.3",
|
||||
fragment = fragment,
|
||||
record_fragment = record_fragment,
|
||||
certificate = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and api.split(node.tls_certificate_pem, "\n") or nil,
|
||||
certificate = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and api.split(node.tls_certificate_pem:gsub("\\n", "\n"), "\n") or nil,
|
||||
cipher_suites = (node.cipherSuites and node.cipherSuites ~= "") and api.split(node.cipherSuites, ":") or nil,
|
||||
ech = (node.ech == "1") and (function()
|
||||
local function get_ech_domain(s) --兼容xray "域名+DNS" 格式ech
|
||||
@@ -273,7 +273,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
ech.query_server_name = qname
|
||||
ech_domain[qname] = true
|
||||
elseif config then
|
||||
ech.config = { config }
|
||||
ech.config = api.split(config:gsub("\\n", "\n"), "\n")
|
||||
elseif node.tls_serverName and node.tls_serverName ~= "" then
|
||||
ech_domain[node.tls_serverName] = true
|
||||
end
|
||||
@@ -709,8 +709,10 @@ function gen_config_server(node)
|
||||
|
||||
local tls = {
|
||||
enabled = true,
|
||||
certificate_path = node.tls_certificateFile,
|
||||
key_path = node.tls_keyFile,
|
||||
certificate_path = (node.tls_use_pem ~= "1") and node.tls_certificateFile or nil,
|
||||
key_path = (node.tls_use_pem ~= "1") and node.tls_keyFile or nil,
|
||||
certificate = (node.tls_use_pem == "1" and node.tls_certificate) and api.split(node.tls_certificate:gsub("\\n", "\n"), "\n") or nil,
|
||||
key = (node.tls_use_pem == "1" and node.tls_key) and api.split(node.tls_key:gsub("\\n", "\n"), "\n") or nil,
|
||||
alpn = (node.alpn and node.alpn ~= "default") and (function()
|
||||
local alpn = {}
|
||||
string.gsub(node.alpn, '[^,]+', function(w)
|
||||
@@ -724,6 +726,8 @@ function gen_config_server(node)
|
||||
if node.tls == "1" and node.reality == "1" then
|
||||
tls.certificate_path = nil
|
||||
tls.key_path = nil
|
||||
tls.certificate = nil
|
||||
tls.key = nil
|
||||
tls.server_name = node.reality_handshake_server
|
||||
tls.reality = {
|
||||
enabled = true,
|
||||
|
||||
@@ -181,7 +181,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
verifyPeerCertByName = node.tls_CertByName or "",
|
||||
echConfigList = (node.ech == "1") and node.ech_config or nil,
|
||||
certificates = (node.tls_certificate == "1" and node.tls_certificate_pem ~= "") and {
|
||||
certificate = api.split(node.tls_certificate_pem, "\n"),
|
||||
certificate = api.split(node.tls_certificate_pem:gsub("\\n", "\n"), "\n"),
|
||||
usage = "verify"
|
||||
} or nil,
|
||||
cipherSuites = node.cipherSuites or nil
|
||||
@@ -697,8 +697,10 @@ function gen_config_server(node)
|
||||
disableSystemRoot = false,
|
||||
certificates = {
|
||||
{
|
||||
certificateFile = node.tls_certificateFile,
|
||||
keyFile = node.tls_keyFile
|
||||
certificateFile = (node.tls_use_pem ~= "1") and node.tls_certificateFile or nil,
|
||||
keyFile = (node.tls_use_pem ~= "1") and node.tls_keyFile or nil,
|
||||
certificate = (node.tls_use_pem == "1" and node.tls_certificate) and api.split(node.tls_certificate:gsub("\\n", "\n"), "\n") or nil,
|
||||
key = (node.tls_use_pem == "1" and node.tls_key) and api.split(node.tls_key:gsub("\\n", "\n"), "\n") or nil
|
||||
}
|
||||
},
|
||||
echServerKeys = (node.ech == "1") and node.ech_key or nil
|
||||
|
||||
@@ -1655,8 +1655,17 @@ msgstr "ECH 密钥路径"
|
||||
msgid "Can't find this file!"
|
||||
msgstr "找不到这个文件!"
|
||||
|
||||
msgid "Certificate or Private key path can not be empty!"
|
||||
msgstr "证书或私钥文件路径不能为空!"
|
||||
msgid "Certificate and Private key path can not be empty!"
|
||||
msgstr "证书和私钥文件路径不能为空!"
|
||||
|
||||
msgid "Certificate and Private key PEM can not be empty!"
|
||||
msgstr "证书和私钥 PEM 不能为空!"
|
||||
|
||||
msgid "Use PEM"
|
||||
msgstr "使用 PEM"
|
||||
|
||||
msgid "Use certificate and private key PEM content."
|
||||
msgstr "使用证书和私钥的 PEM 内容。"
|
||||
|
||||
msgid "Server-Side"
|
||||
msgstr "服务器端"
|
||||
@@ -1850,6 +1859,12 @@ msgstr "TLS 证书(PEM)"
|
||||
msgid "Full certificate (chain), PEM format."
|
||||
msgstr "完整证书(链),PEM 格式。"
|
||||
|
||||
msgid "TLS Private Key (PEM)"
|
||||
msgstr "TLS 私钥(PEM)"
|
||||
|
||||
msgid "Private key in PEM format."
|
||||
msgstr "PEM 格式的私钥。"
|
||||
|
||||
msgid "ECH Config"
|
||||
msgstr "ECH 配置"
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=netifd
|
||||
PKG_RELEASE:=5
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
|
||||
PKG_SOURCE_DATE:=2026-02-26
|
||||
PKG_SOURCE_VERSION:=cbb83a1857407a28a63dc09412a1f209195914ef
|
||||
PKG_MIRROR_HASH:=skip
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
PKG_LICENSE_FILES:=
|
||||
|
||||
PKG_BUILD_FLAGS:=lto
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/netifd
|
||||
SECTION:=base
|
||||
CATEGORY:=Base system
|
||||
DEPENDS:=+libuci +libnl-tiny +libubus +ubus +ubusd +jshn +libubox +libudebug \
|
||||
+ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-uloop +ucode-mod-uci
|
||||
TITLE:=OpenWrt Network Interface Configuration Daemon
|
||||
endef
|
||||
|
||||
define Package/netifd/conffiles
|
||||
/etc/udhcpc.user
|
||||
/etc/udhcpc.user.d/
|
||||
endef
|
||||
|
||||
TARGET_CFLAGS += \
|
||||
-I$(STAGING_DIR)/usr/include/libnl-tiny \
|
||||
-I$(STAGING_DIR)/usr/include
|
||||
|
||||
CMAKE_OPTIONS += \
|
||||
-DLIBNL_LIBS=-lnl-tiny \
|
||||
-DDEBUG=1
|
||||
|
||||
define Package/netifd/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/
|
||||
$(CP) ./files/* $(1)/
|
||||
$(INSTALL_DIR) $(1)/etc/udhcpc.user.d/
|
||||
$(CP) \
|
||||
$(PKG_BUILD_DIR)/scripts/utils.sh \
|
||||
$(PKG_BUILD_DIR)/scripts/netifd-proto.sh \
|
||||
$(1)/lib/netifd/
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,netifd))
|
||||
@@ -1,6 +0,0 @@
|
||||
[ ifup = "$ACTION" ] && {
|
||||
uci_toggle_state network "$INTERFACE" up 1
|
||||
[ -n "$DEVICE" ] && {
|
||||
uci_toggle_state network "$INTERFACE" ifname "$DEVICE"
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=20
|
||||
STOP=90
|
||||
|
||||
USE_PROCD=1
|
||||
|
||||
init_switch() {
|
||||
setup_switch() { return 0; }
|
||||
|
||||
include /lib/network
|
||||
setup_switch
|
||||
}
|
||||
|
||||
start_service() {
|
||||
init_switch
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command /sbin/netifd
|
||||
procd_set_param respawn
|
||||
procd_set_param watch network.interface
|
||||
[ -e /proc/sys/kernel/core_pattern ] && {
|
||||
procd_set_param limits core="unlimited"
|
||||
}
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
local rv=0
|
||||
|
||||
init_switch
|
||||
ubus call network reload || rv=1
|
||||
return $rv
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
[ -x /sbin/wifi ] && /sbin/wifi down
|
||||
ifdown -a
|
||||
sleep 1
|
||||
}
|
||||
|
||||
validate_atm_bridge_section()
|
||||
{
|
||||
uci_validate_section network "atm-bridge" "${1}" \
|
||||
'unit:uinteger:0' \
|
||||
'vci:range(32, 65535):35' \
|
||||
'vpi:range(0, 255):8' \
|
||||
'atmdev:uinteger:0' \
|
||||
'encaps:or("llc", "vc"):llc' \
|
||||
'payload:or("bridged", "routed"):bridged'
|
||||
}
|
||||
|
||||
validate_route_section()
|
||||
{
|
||||
uci_validate_section network route "${1}" \
|
||||
'interface:string' \
|
||||
'target:cidr4' \
|
||||
'netmask:netmask4' \
|
||||
'gateway:ip4addr' \
|
||||
'metric:uinteger' \
|
||||
'mtu:uinteger' \
|
||||
'table:or(range(0,65535),string)'
|
||||
}
|
||||
|
||||
validate_route6_section()
|
||||
{
|
||||
uci_validate_section network route6 "${1}" \
|
||||
'interface:string' \
|
||||
'target:cidr6' \
|
||||
'gateway:ip6addr' \
|
||||
'metric:uinteger' \
|
||||
'mtu:uinteger' \
|
||||
'table:or(range(0,65535),string)'
|
||||
}
|
||||
|
||||
validate_rule_section()
|
||||
{
|
||||
uci_validate_section network rule "${1}" \
|
||||
'in:string' \
|
||||
'out:string' \
|
||||
'src:cidr4' \
|
||||
'dest:cidr4' \
|
||||
'tos:range(0,31)' \
|
||||
'mark:string' \
|
||||
'invert:bool' \
|
||||
'lookup:or(range(0,65535),string)' \
|
||||
'goto:range(0,65535)' \
|
||||
'action:or("prohibit", "unreachable", "blackhole", "throw")'
|
||||
}
|
||||
|
||||
validate_rule6_section()
|
||||
{
|
||||
uci_validate_section network rule6 "${1}" \
|
||||
'in:string' \
|
||||
'out:string' \
|
||||
'src:cidr6' \
|
||||
'dest:cidr6' \
|
||||
'tos:range(0,31)' \
|
||||
'mark:string' \
|
||||
'invert:bool' \
|
||||
'lookup:or(range(0,65535),string)' \
|
||||
'goto:range(0,65535)' \
|
||||
'action:or("prohibit", "unreachable", "blackhole", "throw")'
|
||||
}
|
||||
|
||||
validate_switch_section()
|
||||
{
|
||||
uci_validate_section network switch "${1}" \
|
||||
'name:string' \
|
||||
'enable:bool' \
|
||||
'enable_vlan:bool' \
|
||||
'reset:bool' \
|
||||
'ar8xxx_mib_poll_interval:uinteger' \
|
||||
'ar8xxx_mib_type:range(0,1)'
|
||||
}
|
||||
|
||||
validate_switch_vlan()
|
||||
{
|
||||
uci_validate_section network switch_vlan "${1}" \
|
||||
'device:string' \
|
||||
'vlan:uinteger' \
|
||||
'ports:list(ports)'
|
||||
}
|
||||
|
||||
service_triggers()
|
||||
{
|
||||
procd_add_reload_trigger network wireless
|
||||
|
||||
procd_open_validate
|
||||
validate_atm_bridge_section
|
||||
validate_route_section
|
||||
[ -e /proc/sys/net/ipv6 ] && validate_route6_section
|
||||
validate_rule_section
|
||||
[ -e /proc/sys/net/ipv6 ] && validate_rule6_section
|
||||
validate_switch_section
|
||||
validate_switch_vlan
|
||||
procd_close_validate
|
||||
}
|
||||
|
||||
shutdown() {
|
||||
ifdown -a
|
||||
sleep 1
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=25
|
||||
USE_PROCD=1
|
||||
|
||||
start_service() {
|
||||
reload_service
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "network"
|
||||
procd_add_reload_trigger "firewall"
|
||||
procd_add_raw_trigger "interface.*" 1000 /etc/init.d/packet_steering reload
|
||||
}
|
||||
|
||||
reload_service() {
|
||||
packet_steering="$(uci -q get "network.@globals[0].packet_steering")"
|
||||
steering_flows="$(uci -q get "network.@globals[0].steering_flows")"
|
||||
[ "${steering_flows:-0}" -gt 0 ] && opts="-l $steering_flows"
|
||||
if [ -e "/usr/libexec/platform/packet-steering.sh" ]; then
|
||||
/usr/libexec/platform/packet-steering.sh "$packet_steering"
|
||||
else
|
||||
/usr/libexec/network/packet-steering.uc $opts "$packet_steering"
|
||||
fi
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
. /lib/functions.sh
|
||||
|
||||
migrate_release() {
|
||||
local config="$1"
|
||||
local proto
|
||||
local release
|
||||
|
||||
config_get proto "$config" proto
|
||||
config_get release "$config" release
|
||||
|
||||
[ "$proto" = "dhcp" ] && [ -n "$release" ] && {
|
||||
norelease="$((!$release))"
|
||||
uci_set network "$config" norelease "$norelease"
|
||||
uci_remove network "$config" release
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
config_load network
|
||||
config_foreach migrate_release interface
|
||||
uci commit network
|
||||
|
||||
exit 0
|
||||
@@ -1 +0,0 @@
|
||||
# This script is sourced by udhcpc's dhcp.script at every DHCP event.
|
||||
@@ -1,120 +0,0 @@
|
||||
#!/bin/sh
|
||||
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/netifd/netifd-proto.sh
|
||||
|
||||
set_classless_routes() {
|
||||
local max=128
|
||||
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
|
||||
proto_add_ipv4_route "${1%%/*}" "${1##*/}" "$2" "$ip"
|
||||
max=$(($max-1))
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
setup_interface () {
|
||||
proto_init_update "*" 1
|
||||
proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}"
|
||||
# TODO: apply $broadcast
|
||||
|
||||
local ip_net IP PREFIX NETWORK NETMASK BROADCAST
|
||||
ipcalc "$ip/$mask" && ip_net="$NETWORK"
|
||||
|
||||
local i
|
||||
for i in $router; do
|
||||
local gw_net
|
||||
ipcalc "$i/$mask" && gw_net="$NETWORK"
|
||||
|
||||
[ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip"
|
||||
proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip"
|
||||
|
||||
local r
|
||||
for r in $CUSTOMROUTES; do
|
||||
proto_add_ipv4_route "${r%%/*}" "${r##*/}" "$i" "$ip"
|
||||
done
|
||||
done
|
||||
|
||||
# CIDR STATIC ROUTES (rfc3442)
|
||||
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
|
||||
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
|
||||
|
||||
for i in $dns; do
|
||||
proto_add_dns_server "$i"
|
||||
done
|
||||
for i in $domain; do
|
||||
proto_add_dns_search "$i"
|
||||
done
|
||||
|
||||
# TODO: Deprecate timesvr in favor of timesrv
|
||||
if [ -n "$timesvr" -a -z "$timesrv" ]; then
|
||||
timesrv="$timesvr"
|
||||
echo "Environment variable 'timesvr' will be deprecated; use 'timesrv' instead."
|
||||
fi
|
||||
|
||||
proto_add_data
|
||||
[ -n "$ZONE" ] && json_add_string zone "$ZONE"
|
||||
[ -n "$ntpsrv" ] && json_add_string ntpserver "$ntpsrv"
|
||||
[ -n "$timesrv" ] && json_add_string timeserver "$timesrv"
|
||||
[ -n "$hostname" ] && json_add_string hostname "$hostname"
|
||||
[ -n "$message" ] && json_add_string message "$message"
|
||||
[ -n "$timezone" ] && json_add_int timezone "$timezone"
|
||||
[ -n "$lease" ] && json_add_int leasetime "$lease"
|
||||
[ -n "$serverid" ] && json_add_string dhcpserver "$serverid"
|
||||
proto_close_data
|
||||
|
||||
proto_send_update "$INTERFACE"
|
||||
|
||||
|
||||
if [ "$IFACE6RD" != 0 -a -n "$ip6rd" ]; then
|
||||
local v4mask="${ip6rd%% *}"
|
||||
ip6rd="${ip6rd#* }"
|
||||
local ip6rdprefixlen="${ip6rd%% *}"
|
||||
ip6rd="${ip6rd#* }"
|
||||
local ip6rdprefix="${ip6rd%% *}"
|
||||
ip6rd="${ip6rd#* }"
|
||||
local ip6rdbr="${ip6rd%% *}"
|
||||
|
||||
[ -n "$ZONE" ] || ZONE=$(fw3 -q network $INTERFACE 2>/dev/null)
|
||||
[ -z "$IFACE6RD" -o "$IFACE6RD" = 1 ] && IFACE6RD=${INTERFACE}_6
|
||||
|
||||
json_init
|
||||
json_add_string name "$IFACE6RD"
|
||||
json_add_string ifname "@$INTERFACE"
|
||||
json_add_string proto "6rd"
|
||||
json_add_string peeraddr "$ip6rdbr"
|
||||
json_add_int ip4prefixlen "$v4mask"
|
||||
json_add_string ip6prefix "$ip6rdprefix"
|
||||
json_add_int ip6prefixlen "$ip6rdprefixlen"
|
||||
json_add_string tunlink "$INTERFACE"
|
||||
[ -n "$IFACE6RD_DELEGATE" ] && json_add_boolean delegate "$IFACE6RD_DELEGATE"
|
||||
[ -n "$ZONE6RD" ] || ZONE6RD=$ZONE
|
||||
[ -n "$ZONE6RD" ] && json_add_string zone "$ZONE6RD"
|
||||
[ -n "$MTU6RD" ] && json_add_string mtu "$MTU6RD"
|
||||
json_close_object
|
||||
|
||||
ubus call network add_dynamic "$(json_dump)"
|
||||
fi
|
||||
}
|
||||
|
||||
deconfig_interface() {
|
||||
proto_init_update "*" 0
|
||||
proto_send_update "$INTERFACE"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
deconfig)
|
||||
deconfig_interface
|
||||
;;
|
||||
renew|bound)
|
||||
setup_interface
|
||||
;;
|
||||
esac
|
||||
|
||||
# user rules
|
||||
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user "$@"
|
||||
for f in /etc/udhcpc.user.d/*; do
|
||||
[ -f "$f" ] && (. "$f" "$@")
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -1,79 +0,0 @@
|
||||
import * as uci from "uci";
|
||||
import * as uloop from "uloop";
|
||||
import * as ubus from "ubus";
|
||||
import { access, dirname } from "fs";
|
||||
|
||||
function ex_handler(e)
|
||||
{
|
||||
netifd.log(netifd.L_WARNING, `Exception: ${e}\n${e.stacktrace[0].context}\n`);
|
||||
}
|
||||
|
||||
uloop.guard(ex_handler);
|
||||
ubus.guard(ex_handler);
|
||||
|
||||
let wireless;
|
||||
|
||||
function uci_ctx()
|
||||
{
|
||||
let savedir = netifd.dummy_mode ? "./tmp" : null;
|
||||
let ctx = uci.cursor(netifd.config_path, savedir, null, {
|
||||
strict: false
|
||||
});
|
||||
return ctx;
|
||||
}
|
||||
|
||||
function config_init()
|
||||
{
|
||||
let ctx = uci_ctx();
|
||||
|
||||
if (wireless)
|
||||
wireless.config_init(ctx);
|
||||
}
|
||||
|
||||
function config_start()
|
||||
{
|
||||
if (wireless)
|
||||
wireless.config_start();
|
||||
}
|
||||
|
||||
function check_interfaces()
|
||||
{
|
||||
if (wireless)
|
||||
wireless.check_interfaces();
|
||||
}
|
||||
|
||||
function hotplug(name, add)
|
||||
{
|
||||
if (wireless)
|
||||
wireless.hotplug(name, add);
|
||||
}
|
||||
|
||||
function ex_wrap(cb)
|
||||
{
|
||||
let fn = cb;
|
||||
return (...args) => {
|
||||
try {
|
||||
return fn(...args);
|
||||
} catch (e) {
|
||||
netifd.log(netifd.L_WARNING, `${e}\n${e.stacktrace[0].context}`);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
netifd.cb = {
|
||||
hotplug: ex_wrap(hotplug),
|
||||
config_init: ex_wrap(config_init),
|
||||
config_start: ex_wrap(config_start),
|
||||
check_interfaces: ex_wrap(check_interfaces),
|
||||
};
|
||||
|
||||
const wireless_module = dirname(sourcepath()) + "/wireless.uc";
|
||||
if (access(wireless_module, "r")) {
|
||||
try {
|
||||
wireless = loadfile(wireless_module)();
|
||||
} catch (e) {
|
||||
netifd.log(netifd.L_WARNING, `Error loading wireless module: ${e}\n${e.stacktrace[0].context}\n`);
|
||||
}
|
||||
} else {
|
||||
netifd.log(netifd.L_WARNING, `Wireless module not found\n`);
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ -x /sbin/udhcpc ] || exit 0
|
||||
|
||||
. /lib/functions.sh
|
||||
. /lib/functions/network.sh
|
||||
. ../netifd-proto.sh
|
||||
. /lib/config/uci.sh
|
||||
init_proto "$@"
|
||||
|
||||
proto_dhcp_init_config() {
|
||||
renew_handler=1
|
||||
|
||||
proto_config_add_string 'ipaddr:ipaddr'
|
||||
proto_config_add_string 'hostname:hostname'
|
||||
proto_config_add_string clientid
|
||||
proto_config_add_string sendclientid
|
||||
proto_config_add_string vendorid
|
||||
proto_config_add_boolean 'broadcast:bool'
|
||||
proto_config_add_boolean 'norelease:bool'
|
||||
proto_config_add_string 'reqopts:list(string)'
|
||||
proto_config_add_boolean 'defaultreqopts:bool'
|
||||
proto_config_add_string iface6rd
|
||||
proto_config_add_array 'sendopts:list(string)'
|
||||
proto_config_add_boolean delegate
|
||||
proto_config_add_string zone6rd
|
||||
proto_config_add_string zone
|
||||
proto_config_add_string mtu6rd
|
||||
proto_config_add_string customroutes
|
||||
proto_config_add_boolean classlessroute
|
||||
}
|
||||
|
||||
proto_dhcp_add_sendopts() {
|
||||
[ -n "$1" ] && append "$3" "-x $1"
|
||||
}
|
||||
|
||||
proto_dhcp_get_default_clientid() {
|
||||
[ -z "$1" ] && return
|
||||
|
||||
local iface="$1"
|
||||
local duid
|
||||
local iaid
|
||||
|
||||
duid="$(uci_get network @globals[0] dhcp_default_duid)"
|
||||
[ -n "$duid" ] && {
|
||||
duid="$(hexdump_2hex "$duid")"
|
||||
[ -z "$duid" ] && logger -p warn -t dhcp "$iface: ignoring invalid dhcp_default_duid value"
|
||||
}
|
||||
[ -z "$duid" ] && return
|
||||
network_generate_iface_iaid iaid "$iface"
|
||||
printf "ff%s%s" "$iaid" "$duid"
|
||||
}
|
||||
|
||||
proto_dhcp_setup() {
|
||||
local config="$1"
|
||||
local iface="$2"
|
||||
|
||||
local ipaddr hostname clientid sendclientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute
|
||||
json_get_vars ipaddr hostname clientid sendclientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute
|
||||
|
||||
local opt dhcpopts
|
||||
for opt in $reqopts; do
|
||||
append dhcpopts "-O $opt"
|
||||
done
|
||||
|
||||
json_for_each_item proto_dhcp_add_sendopts sendopts dhcpopts
|
||||
|
||||
[ -z "$hostname" ] && hostname="$(cat /proc/sys/kernel/hostname)"
|
||||
[ "$hostname" = "*" ] && hostname=
|
||||
|
||||
[ "$defaultreqopts" = 0 ] && defaultreqopts="-o" || defaultreqopts=
|
||||
[ "$broadcast" = 1 ] && broadcast="-B" || broadcast=
|
||||
[ "$norelease" = 1 ] && norelease="" || norelease="-R"
|
||||
case "$sendclientid" in
|
||||
global)
|
||||
clientid="$(proto_dhcp_get_default_clientid "$iface")"
|
||||
;;
|
||||
hardware)
|
||||
clientid=''
|
||||
;;
|
||||
none)
|
||||
clientid='-C'
|
||||
;;
|
||||
auto|\
|
||||
*)
|
||||
[ -n "$clientid" ] && {
|
||||
clientid="$(hexdump_2hex "$clientid")"
|
||||
[ -z "$clientid" ] && {
|
||||
logger -p warn -t dhcp "$iface: ignoring invalid clientid value"
|
||||
}
|
||||
}
|
||||
[ -z "$clientid" ] && clientid="$(proto_dhcp_get_default_clientid "$iface")"
|
||||
;;
|
||||
esac
|
||||
[ -n "${clientid##-C}" ] && clientid="-x 0x3d:$clientid"
|
||||
[ -n "$vendorid" ] && append dhcpopts "-x 0x3c:$(echo -n "$vendorid" | hexdump -ve '1/1 "%02x"')"
|
||||
[ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd"
|
||||
[ "$iface6rd" != 0 -a -f /lib/netifd/proto/6rd.sh ] && append dhcpopts "-O 212"
|
||||
[ -n "$zone6rd" ] && proto_export "ZONE6RD=$zone6rd"
|
||||
[ -n "$zone" ] && proto_export "ZONE=$zone"
|
||||
[ -n "$mtu6rd" ] && proto_export "MTU6RD=$mtu6rd"
|
||||
[ -n "$customroutes" ] && proto_export "CUSTOMROUTES=$customroutes"
|
||||
[ "$delegate" = "0" ] && proto_export "IFACE6RD_DELEGATE=0"
|
||||
# Request classless route option (see RFC 3442) by default
|
||||
[ "$classlessroute" = "0" ] || append dhcpopts "-O 121"
|
||||
|
||||
# Avoid sending duplicate Option 60 values
|
||||
local emptyvendorid
|
||||
case "$dhcpopts" in
|
||||
*"-x 0"[xX]*"3"[cC]":"* |\
|
||||
*"-x 60:"* |\
|
||||
*"-x vendor:"*)
|
||||
emptyvendorid=1
|
||||
;;
|
||||
esac
|
||||
|
||||
proto_export "INTERFACE=$config"
|
||||
proto_run_command "$config" udhcpc \
|
||||
-p /var/run/udhcpc-$iface.pid \
|
||||
-s /lib/netifd/dhcp.script \
|
||||
-f -t 0 -i "$iface" \
|
||||
${ipaddr:+-r ${ipaddr/\/*/}} \
|
||||
${hostname:+-x "hostname:$hostname"} \
|
||||
${emptyvendorid:+-V ""} \
|
||||
$clientid $defaultreqopts $broadcast $norelease $dhcpopts
|
||||
}
|
||||
|
||||
proto_dhcp_renew() {
|
||||
local interface="$1"
|
||||
# SIGUSR1 forces udhcpc to renew its lease
|
||||
local sigusr1="$(kill -l SIGUSR1)"
|
||||
[ -n "$sigusr1" ] && proto_kill_command "$interface" $sigusr1
|
||||
}
|
||||
|
||||
proto_dhcp_teardown() {
|
||||
local interface="$1"
|
||||
proto_kill_command "$interface"
|
||||
}
|
||||
|
||||
add_protocol dhcp
|
||||
@@ -1,131 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
import { glob, basename, realpath, chdir, mkstemp } from "fs";
|
||||
|
||||
export const TYPE_ARRAY = 1;
|
||||
export const TYPE_STRING = 3;
|
||||
export const TYPE_INT = 5;
|
||||
export const TYPE_BOOL = 7;
|
||||
|
||||
export function parse_bool(val)
|
||||
{
|
||||
switch (val) {
|
||||
case "1":
|
||||
case "true":
|
||||
return true;
|
||||
case "0":
|
||||
case "false":
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export function parse_array(val)
|
||||
{
|
||||
if (type(val) != "array")
|
||||
val = split(val, /\s+/);
|
||||
return val;
|
||||
};
|
||||
|
||||
function __type_parsers()
|
||||
{
|
||||
let ret = [];
|
||||
|
||||
ret[TYPE_ARRAY] = parse_array;
|
||||
ret[TYPE_STRING] = function(val) {
|
||||
return val;
|
||||
};
|
||||
ret[TYPE_INT] = function(val) {
|
||||
return +val;
|
||||
};
|
||||
ret[TYPE_BOOL] = parse_bool;
|
||||
|
||||
return ret;
|
||||
}
|
||||
export const type_parser = __type_parsers();
|
||||
|
||||
export function handler_load(path, cb)
|
||||
{
|
||||
for (let script in glob(path + "/*.sh")) {
|
||||
script = basename(script);
|
||||
|
||||
let f = mkstemp();
|
||||
let prev_dir = realpath(".");
|
||||
chdir(path);
|
||||
system(`./${script} "" "dump" >&${f.fileno()}`);
|
||||
chdir(prev_dir);
|
||||
f.seek();
|
||||
while (!f.error()) {
|
||||
let data = trim(f.read("line"));
|
||||
try {
|
||||
data = json(data);
|
||||
} catch (e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type(data) != "object")
|
||||
continue;
|
||||
|
||||
cb(script, data);
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
};
|
||||
|
||||
export function handler_attributes(data, extra, validate)
|
||||
{
|
||||
let ret = { ...extra };
|
||||
for (let cur in data) {
|
||||
let name_data = split(cur[0], ":", 2);
|
||||
let name = name_data[0];
|
||||
ret[name] = cur[1];
|
||||
if (validate && name_data[1])
|
||||
validate[name] = name_data[1];
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
export function parse_attribute_list(data, spec)
|
||||
{
|
||||
let ret = {};
|
||||
|
||||
for (let name, type_id in spec) {
|
||||
if (!(name in data))
|
||||
continue;
|
||||
|
||||
let val = data[name];
|
||||
let parser = type_parser[type_id];
|
||||
if (parser)
|
||||
val = parser(val);
|
||||
ret[name] = val;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
export function is_equal(val1, val2) {
|
||||
let t1 = type(val1);
|
||||
|
||||
if (t1 != type(val2))
|
||||
return false;
|
||||
|
||||
if (t1 == "array") {
|
||||
if (length(val1) != length(val2))
|
||||
return false;
|
||||
|
||||
for (let i = 0; i < length(val1); i++)
|
||||
if (!is_equal(val1[i], val2[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} else if (t1 == "object") {
|
||||
for (let key in val1)
|
||||
if (!is_equal(val1[key], val2[key]))
|
||||
return false;
|
||||
for (let key in val2)
|
||||
if (val1[key] == null)
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
return val1 == val2;
|
||||
}
|
||||
};
|
||||
@@ -1,76 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Copyright (C) 2011 OpenWrt.org
|
||||
|
||||
. /usr/share/libubox/jshn.sh
|
||||
|
||||
find_config() {
|
||||
local device="$1"
|
||||
local ifdev ifl3dev ifobj
|
||||
for ifobj in $(ubus list network.interface.\*); do
|
||||
interface="${ifobj##network.interface.}"
|
||||
(
|
||||
json_load "$(ifstatus $interface)"
|
||||
json_get_var ifdev device
|
||||
json_get_var ifl3dev l3_device
|
||||
if [ "$device" = "$ifdev" ] || [ "$device" = "$ifl3dev" ]; then
|
||||
echo "$interface"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
) && return
|
||||
done
|
||||
}
|
||||
|
||||
unbridge() {
|
||||
return
|
||||
}
|
||||
|
||||
ubus_call() {
|
||||
json_init
|
||||
local _data="$(ubus -S call "$1" "$2")"
|
||||
[ -z "$_data" ] && return 1
|
||||
json_load "$_data"
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
fixup_interface() {
|
||||
local config="$1"
|
||||
local ifname type device l3dev
|
||||
|
||||
config_get type "$config" type
|
||||
config_get ifname "$config" ifname
|
||||
[ "bridge" = "$type" ] && ifname="br-$config"
|
||||
ubus_call "network.interface.$config" status || return 0
|
||||
json_get_var l3dev l3_device
|
||||
[ -n "$l3dev" ] && ifname="$l3dev"
|
||||
json_init
|
||||
config_set "$config" ifname "$ifname"
|
||||
}
|
||||
|
||||
scan_interfaces() {
|
||||
config_load network
|
||||
config_foreach fixup_interface interface
|
||||
}
|
||||
|
||||
prepare_interface_bridge() {
|
||||
local config="$1"
|
||||
|
||||
[ -n "$config" ] || return 0
|
||||
ubus call network.interface."$config" prepare
|
||||
}
|
||||
|
||||
setup_interface() {
|
||||
local iface="$1"
|
||||
local config="$2"
|
||||
|
||||
[ -n "$config" ] || return 0
|
||||
ubus call network.interface."$config" add_device "{ \"name\": \"$iface\" }"
|
||||
}
|
||||
|
||||
do_sysctl() {
|
||||
[ -n "$2" ] && \
|
||||
sysctl -n -e -w "$1=$2" >/dev/null || \
|
||||
sysctl -n -e "$1"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
. /usr/share/libubox/jshn.sh
|
||||
DEVICE="$1"
|
||||
|
||||
[ -n "$DEVICE" ] || {
|
||||
echo "Usage: $0 <device>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
json_init
|
||||
json_add_string name "$DEVICE"
|
||||
ubus call network.device status "$(json_dump)"
|
||||
@@ -1 +0,0 @@
|
||||
ifup
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
INTERFACE="$1"
|
||||
|
||||
[ -n "$INTERFACE" ] || {
|
||||
echo "Usage: $0 <interface>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
ubus -S list "network.interface.$INTERFACE" >/dev/null || {
|
||||
echo "Interface $INTERFACE not found"
|
||||
exit 1
|
||||
}
|
||||
ubus call network.interface status "{ \"interface\" : \"$INTERFACE\" }"
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
ifup_all=
|
||||
|
||||
if_call() {
|
||||
local interface="$1"
|
||||
for mode in $modes; do
|
||||
ubus call network.interface $mode "{ \"interface\" : \"$interface\" }"
|
||||
done
|
||||
}
|
||||
|
||||
case "$0" in
|
||||
*ifdown) modes=down;;
|
||||
*ifup)
|
||||
modes="down up"
|
||||
;;
|
||||
*) echo "Invalid command: $0";;
|
||||
esac
|
||||
|
||||
while :; do
|
||||
case "$1" in
|
||||
-a)
|
||||
ifup_all=1
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ "$modes" = "down up" ] && ubus call network reload
|
||||
if [ -n "$ifup_all" ]; then
|
||||
for interface in $(ubus -S list 'network.interface.*'); do
|
||||
if_call "${interface##network.interface.}"
|
||||
done
|
||||
exit
|
||||
else
|
||||
ubus -S list "network.interface.$1" > /dev/null || {
|
||||
echo "Interface $1 not found"
|
||||
exit
|
||||
}
|
||||
if_call "$1"
|
||||
fi
|
||||
@@ -1,279 +0,0 @@
|
||||
#!/usr/bin/env ucode
|
||||
'use strict';
|
||||
import { glob, basename, dirname, readlink, readfile, realpath, writefile, error, open } from "fs";
|
||||
|
||||
let napi_weight = 1.0;
|
||||
let cpu_thread_weight = 0.75;
|
||||
let rx_weight = 0.75;
|
||||
let eth_bias = 2.0;
|
||||
let debug = 0, do_nothing = 0;
|
||||
let disable;
|
||||
let cpus;
|
||||
let all_cpus;
|
||||
let local_flows = 0;
|
||||
|
||||
while (length(ARGV) > 0) {
|
||||
let arg = shift(ARGV);
|
||||
switch (arg) {
|
||||
case "-d":
|
||||
debug++;
|
||||
break;
|
||||
case "-n":
|
||||
do_nothing++;
|
||||
break;
|
||||
case '0':
|
||||
disable = true;
|
||||
break;
|
||||
case '2':
|
||||
all_cpus = true;
|
||||
break;
|
||||
case '-l':
|
||||
local_flows = +shift(ARGV);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function task_name(pid)
|
||||
{
|
||||
let stat = open(`/proc/${pid}/status`, "r");
|
||||
if (!stat)
|
||||
return;
|
||||
let line = stat.read("line");
|
||||
stat.close();
|
||||
return trim(split(line, "\t", 2)[1]);
|
||||
}
|
||||
|
||||
function set_task_cpu(pid, cpu) {
|
||||
if (disable)
|
||||
cpu = join(",", map(cpus, (cpu) => cpu.id));
|
||||
let name = task_name(pid);
|
||||
if (!name)
|
||||
return;
|
||||
if (debug || do_nothing)
|
||||
warn(`taskset -p -c ${cpu} ${name}\n`);
|
||||
if (!do_nothing)
|
||||
system(`taskset -p -c ${cpu} ${pid}`);
|
||||
}
|
||||
|
||||
function cpu_mask(cpu)
|
||||
{
|
||||
let mask;
|
||||
if (cpu < 0)
|
||||
mask = (1 << length(cpus)) - 1;
|
||||
else
|
||||
mask = (1 << int(cpu));
|
||||
return sprintf("%x", mask);
|
||||
}
|
||||
|
||||
function set_netdev_cpu(dev, cpu, rx_queue) {
|
||||
rx_queue ??= "rx-*";
|
||||
let queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_cpus`);
|
||||
let val = cpu_mask(cpu);
|
||||
if (disable)
|
||||
val = 0;
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${val} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${val}`);
|
||||
}
|
||||
queues = glob(`/sys/class/net/${dev}/queues/${rx_queue}/rps_flow_cnt`);
|
||||
for (let queue in queues) {
|
||||
if (debug || do_nothing)
|
||||
warn(`echo ${local_flows} > ${queue}\n`);
|
||||
if (!do_nothing)
|
||||
writefile(queue, `${local_flows}`);
|
||||
}
|
||||
}
|
||||
|
||||
function task_device_match(name, device)
|
||||
{
|
||||
let napi_match = match(name, /napi\/([^-]*)-\d+/);
|
||||
if (!napi_match)
|
||||
napi_match = match(name, /mt76-tx (phy\d+)/);
|
||||
if (napi_match &&
|
||||
(index(device.phy, napi_match[1]) >= 0 ||
|
||||
index(device.netdev, napi_match[1]) >= 0))
|
||||
return true;
|
||||
|
||||
if (device.driver == "mtk_soc_eth" && match(name, /napi\/mtk_eth-/))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
cpus = map(glob("/sys/bus/cpu/devices/*"), (path) => {
|
||||
return {
|
||||
id: int(match(path, /.*cpu(\d+)/)[1]),
|
||||
core: int(trim(readfile(`${path}/topology/core_id`))),
|
||||
load: 0.0,
|
||||
};
|
||||
});
|
||||
|
||||
cpus = slice(cpus, 0, 64);
|
||||
if (length(cpus) < 2)
|
||||
exit(0);
|
||||
|
||||
function cpu_add_weight(cpu_id, weight)
|
||||
{
|
||||
let cpu = cpus[cpu_id];
|
||||
cpu.load += weight;
|
||||
for (let sibling in cpus) {
|
||||
if (sibling == cpu || sibling.core != cpu.core)
|
||||
continue;
|
||||
sibling.load += weight * cpu_thread_weight;
|
||||
}
|
||||
}
|
||||
|
||||
function get_next_cpu(weight, prev_cpu)
|
||||
{
|
||||
if (disable)
|
||||
return 0;
|
||||
|
||||
let sort_cpus = sort(slice(cpus), (a, b) => a.load - b.load);
|
||||
let idx = 0;
|
||||
|
||||
if (prev_cpu != null && sort_cpus[idx].id == prev_cpu)
|
||||
idx++;
|
||||
|
||||
let cpu = sort_cpus[idx].id;
|
||||
cpu_add_weight(cpu, weight);
|
||||
return cpu;
|
||||
}
|
||||
|
||||
let phys_devs = {};
|
||||
let netdev_phys = {};
|
||||
let netdevs = map(glob("/sys/class/net/*"), (dev) => basename(dev));
|
||||
|
||||
for (let dev in netdevs) {
|
||||
let pdev_path = realpath(`/sys/class/net/${dev}/device`);
|
||||
if (!pdev_path)
|
||||
continue;
|
||||
|
||||
if (length(glob(`/sys/class/net/${dev}/lower_*`)) > 0)
|
||||
continue;
|
||||
|
||||
let pdev = phys_devs[pdev_path];
|
||||
if (!pdev) {
|
||||
pdev = phys_devs[pdev_path] = {
|
||||
path: pdev_path,
|
||||
driver: basename(readlink(`${pdev_path}/driver`)),
|
||||
netdev: [],
|
||||
phy: [],
|
||||
tasks: [],
|
||||
rx_tasks: [],
|
||||
rx_queues: map(glob(`/sys/class/net/${dev}/queues/rx-*/rps_cpus`),
|
||||
(v) => basename(dirname(v))),
|
||||
};
|
||||
}
|
||||
|
||||
let phyidx = trim(readfile(`/sys/class/net/${dev}/phy80211/index`));
|
||||
if (phyidx != null) {
|
||||
let phy = `phy${phyidx}`;
|
||||
if (index(pdev.phy, phy) < 0)
|
||||
push(pdev.phy, phy);
|
||||
}
|
||||
|
||||
push(pdev.netdev, dev);
|
||||
netdev_phys[dev] = pdev;
|
||||
}
|
||||
|
||||
for (let path in glob("/proc/*/exe")) {
|
||||
readlink(path);
|
||||
if (error() != "No such file or directory")
|
||||
continue;
|
||||
|
||||
let pid = basename(dirname(path));
|
||||
let name = task_name(pid);
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!task_device_match(name, dev))
|
||||
continue;
|
||||
|
||||
push(dev.tasks, pid);
|
||||
|
||||
let napi_match = match(name, /napi\/([^-]*)-(\d+)/);
|
||||
if (napi_match && napi_match[2] > 0)
|
||||
push(dev.rx_tasks, pid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function assign_dev_queues_cpu(dev) {
|
||||
let num = length(dev.rx_queues);
|
||||
if (num < length(dev.rx_tasks))
|
||||
num = length(dev.rx_tasks);
|
||||
|
||||
for (let i = 0; i < num; i++) {
|
||||
let cpu;
|
||||
|
||||
let task = dev.rx_tasks[i];
|
||||
if (num >= length(cpus))
|
||||
cpu = i % length(cpus);
|
||||
else if (task)
|
||||
cpu = get_next_cpu(napi_weight);
|
||||
else
|
||||
cpu = -1;
|
||||
set_task_cpu(task, cpu);
|
||||
|
||||
let rxq = dev.rx_queues[i];
|
||||
if (!rxq)
|
||||
continue;
|
||||
|
||||
if (num >= length(cpus))
|
||||
cpu = (i + 1) % length(cpus);
|
||||
else if (all_cpus)
|
||||
cpu = -1;
|
||||
else
|
||||
cpu = get_next_cpu(napi_weight, cpu);
|
||||
for (let netdev in dev.netdev)
|
||||
set_netdev_cpu(netdev, cpu, rxq);
|
||||
}
|
||||
}
|
||||
|
||||
function assign_dev_cpu(dev) {
|
||||
if (length(dev.rx_queues) > 1 &&
|
||||
length(dev.rx_tasks) > 1)
|
||||
return assign_dev_queues_cpu(dev);
|
||||
|
||||
if (length(dev.tasks) > 0) {
|
||||
let cpu = dev.napi_cpu = get_next_cpu(napi_weight);
|
||||
for (let task in dev.tasks)
|
||||
set_task_cpu(task, cpu);
|
||||
}
|
||||
|
||||
if (length(dev.netdev) > 0) {
|
||||
let cpu;
|
||||
if (all_cpus)
|
||||
cpu = -1;
|
||||
else
|
||||
cpu = get_next_cpu(rx_weight, dev.napi_cpu);
|
||||
for (let netdev in dev.netdev)
|
||||
set_netdev_cpu(netdev, cpu);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign ethernet devices first
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.phy))
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
// Add bias to avoid assigning other tasks to CPUs with ethernet NAPI
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (!length(dev.tasks) || dev.napi_cpu == null)
|
||||
continue;
|
||||
cpu_add_weight(dev.napi_cpu, eth_bias);
|
||||
}
|
||||
|
||||
// Assign WLAN devices
|
||||
for (let devname in phys_devs) {
|
||||
let dev = phys_devs[devname];
|
||||
if (length(dev.phy) > 0)
|
||||
assign_dev_cpu(dev);
|
||||
}
|
||||
|
||||
if (debug > 1)
|
||||
warn(sprintf("devices: %.J\ncpus: %.J\n", phys_devs, cpus));
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/bin/sh
|
||||
[ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1
|
||||
|
||||
set_classless_routes() {
|
||||
local max=128
|
||||
local type
|
||||
while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do
|
||||
[ ${1##*/} -eq 32 ] && type=host || type=net
|
||||
echo "udhcpc: adding route for $type $1 via $2"
|
||||
route add -$type "$1" gw "$2" dev "$interface"
|
||||
max=$(($max-1))
|
||||
shift 2
|
||||
done
|
||||
}
|
||||
|
||||
setup_interface() {
|
||||
echo "udhcpc: ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface"
|
||||
ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface
|
||||
|
||||
[ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && {
|
||||
echo "udhcpc: setting default routers: $router"
|
||||
|
||||
local valid_gw=""
|
||||
for i in $router ; do
|
||||
route add default gw $i dev $interface
|
||||
valid_gw="${valid_gw:+$valid_gw|}$i"
|
||||
done
|
||||
|
||||
eval $(route -n | awk '
|
||||
/^0.0.0.0\W{9}('$valid_gw')\W/ {next}
|
||||
/^0.0.0.0/ {print "route del -net "$1" gw "$2";"}
|
||||
')
|
||||
}
|
||||
|
||||
# CIDR STATIC ROUTES (rfc3442)
|
||||
[ -n "$staticroutes" ] && set_classless_routes $staticroutes
|
||||
[ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes
|
||||
}
|
||||
|
||||
|
||||
applied=
|
||||
case "$1" in
|
||||
deconfig)
|
||||
ip -4 addr flush dev "$interface"
|
||||
;;
|
||||
renew)
|
||||
setup_interface update
|
||||
;;
|
||||
bound)
|
||||
setup_interface ifup
|
||||
;;
|
||||
esac
|
||||
|
||||
# user rules
|
||||
[ -f /etc/udhcpc.user ] && . /etc/udhcpc.user
|
||||
|
||||
exit 0
|
||||
@@ -1,11 +0,0 @@
|
||||
--- a/proto.c
|
||||
+++ b/proto.c
|
||||
@@ -426,6 +426,8 @@ proto_apply_static_ip_settings(struct interface *iface, struct blob_attr *attr)
|
||||
error = "INVALID_NETMASK";
|
||||
goto error;
|
||||
}
|
||||
+ } else if (iface && !strncmp(iface->name, "lan", 3)) {
|
||||
+ netmask = 24;
|
||||
}
|
||||
|
||||
if ((cur = tb[OPT_BROADCAST])) {
|
||||
@@ -0,0 +1,52 @@
|
||||
#
|
||||
# Copyright (C) 2016 Shuanglei Tao <tsl0922@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ttyd
|
||||
PKG_VERSION:=1.7.7
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/tsl0922/ttyd/tar.gz/$(PKG_VERSION)?
|
||||
PKG_HASH:=skip
|
||||
|
||||
PKG_MAINTAINER:=Shuanglei Tao <tsl0922@gmail.com>
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
PKG_CPE_ID:=cpe:/a:ttyd_project:ttyd
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
define Package/ttyd
|
||||
SECTION:=utils
|
||||
CATEGORY:=Utilities
|
||||
TITLE:=Command-line tool for sharing terminal over the web
|
||||
DEPENDS:=+libcap +libopenssl +libjson-c +libuv +zlib +libwebsockets-full
|
||||
URL:=https://github.com/tsl0922/ttyd
|
||||
SUBMENU:=Terminal
|
||||
endef
|
||||
|
||||
define Package/ttyd/description
|
||||
ttyd is a command-line tool for sharing terminal over the web.
|
||||
endef
|
||||
|
||||
define Package/ttyd/conffiles
|
||||
/etc/config/ttyd
|
||||
endef
|
||||
|
||||
define Package/ttyd/install
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/ttyd $(1)/usr/bin/
|
||||
$(INSTALL_DIR) $(1)/etc/config/
|
||||
$(INSTALL_CONF) ./files/ttyd.config $(1)/etc/config/ttyd
|
||||
$(INSTALL_DIR) $(1)/etc/init.d/
|
||||
$(INSTALL_BIN) ./files/ttyd.init $(1)/etc/init.d/ttyd
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ttyd))
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
config ttyd
|
||||
option command '/bin/login'
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=99
|
||||
STOP=50
|
||||
USE_PROCD=1
|
||||
|
||||
NAME=ttyd
|
||||
PROG=/usr/bin/$NAME
|
||||
|
||||
validate_section_ttyd()
|
||||
{
|
||||
uci_load_validate ttyd ttyd "$1" "$2" \
|
||||
'enable:bool:1' \
|
||||
'port:port' \
|
||||
'interface:string' \
|
||||
'credential:string' \
|
||||
'uid:uinteger' \
|
||||
'gid:uinteger' \
|
||||
'signal:uinteger' \
|
||||
'url_arg:bool' \
|
||||
'readonly:bool:0' \
|
||||
'client_option:list(string)' \
|
||||
'terminal_type:string' \
|
||||
'check_origin:bool' \
|
||||
'max_clients:uinteger' \
|
||||
'once:bool' \
|
||||
'index:string' \
|
||||
'ipv6:bool' \
|
||||
'ssl:bool' \
|
||||
'ssl_cert:file' \
|
||||
'ssl_key:file' \
|
||||
'ssl_ca:file' \
|
||||
'debug:uinteger' \
|
||||
'command:string'
|
||||
}
|
||||
|
||||
ttyd_instance()
|
||||
{
|
||||
[ "$2" = 0 ] || {
|
||||
echo "validation failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
[ "$enable" = 0 ] && return 1
|
||||
[ -z "$command" ] && return 1
|
||||
|
||||
[ "${interface::1}" = @ ] && {
|
||||
interface=$(
|
||||
. /lib/functions/network.sh
|
||||
network_get_device device "${interface:1}"
|
||||
echo -n "$device"
|
||||
)
|
||||
}
|
||||
|
||||
[ "$url_arg" = 0 ] && url_arg=""
|
||||
[ "$readonly" = 0 ] && readonly="-W"
|
||||
[ "$check_origin" = 0 ] && check_origin=""
|
||||
[ "$once" = 0 ] && once=""
|
||||
[ "$ipv6" = 0 ] && ipv6=""
|
||||
[ "$ssl" = 0 ] && ssl=""
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$PROG" \
|
||||
${port:+-p $port} \
|
||||
${interface:+-i $interface} \
|
||||
${credential:+-c $credential} \
|
||||
${uid:+-u $uid} \
|
||||
${gid:+-g $gid} \
|
||||
${signal:+-s $signal} \
|
||||
${url_arg:+-a} \
|
||||
${readonly:-} \
|
||||
${terminal_type:+-T $terminal_type} \
|
||||
${check_origin:+-O} \
|
||||
${max_clients:+-m $max_clients} \
|
||||
${once:+-o} \
|
||||
${index:+-I $index} \
|
||||
${ipv6:+-6} \
|
||||
${ssl:+-S} \
|
||||
${ssl_cert:+-C $ssl_cert} \
|
||||
${ssl_key:+-K $ssl_key} \
|
||||
${ssl_ca:+-A $ssl_ca} \
|
||||
${debug:+-d $debug}
|
||||
config_list_foreach "$1" client_option "procd_append_param command -t"
|
||||
procd_append_param command $command
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
start_service() {
|
||||
config_load "$NAME"
|
||||
config_foreach validate_section_ttyd ttyd ttyd_instance
|
||||
}
|
||||
|
||||
shutdown() {
|
||||
# close all open connections
|
||||
killall "$NAME"
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "$NAME"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
--- a/src/server.c
|
||||
+++ b/src/server.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
+#include <syslog.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
@@ -520,7 +521,8 @@ int main(int argc, char **argv) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
- lws_set_log_level(debug_level, NULL);
|
||||
+ openlog("ttyd", LOG_NDELAY | LOG_PID, LOG_DAEMON);
|
||||
+ lws_set_log_level(debug_level, lwsl_emit_syslog);
|
||||
|
||||
char server_hdr[128] = "";
|
||||
sprintf(server_hdr, "ttyd/%s (libwebsockets/%s)", TTYD_VERSION, LWS_LIBRARY_VERSION);
|
||||
Reference in new issue
Block a user