summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-openvpn/luasrc
diff options
context:
space:
mode:
Diffstat (limited to 'applications/luci-app-openvpn/luasrc')
-rw-r--r--applications/luci-app-openvpn/luasrc/controller/openvpn.lua43
-rw-r--r--applications/luci-app-openvpn/luasrc/model/cbi/openvpn-advanced.lua129
-rw-r--r--applications/luci-app-openvpn/luasrc/model/cbi/openvpn-basic.lua156
-rw-r--r--applications/luci-app-openvpn/luasrc/model/cbi/openvpn-file.lua82
-rw-r--r--applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua74
-rw-r--r--applications/luci-app-openvpn/luasrc/view/openvpn/cbi-select-input-add.htm120
-rw-r--r--applications/luci-app-openvpn/luasrc/view/openvpn/ovpn_css.htm38
-rw-r--r--applications/luci-app-openvpn/luasrc/view/openvpn/pageswitch.htm18
8 files changed, 582 insertions, 78 deletions
diff --git a/applications/luci-app-openvpn/luasrc/controller/openvpn.lua b/applications/luci-app-openvpn/luasrc/controller/openvpn.lua
index 2e48a469a1..c9a932d870 100644
--- a/applications/luci-app-openvpn/luasrc/controller/openvpn.lua
+++ b/applications/luci-app-openvpn/luasrc/controller/openvpn.lua
@@ -8,4 +8,47 @@ function index()
entry( {"admin", "services", "openvpn"}, cbi("openvpn"), _("OpenVPN") )
entry( {"admin", "services", "openvpn", "basic"}, cbi("openvpn-basic"), nil ).leaf = true
entry( {"admin", "services", "openvpn", "advanced"}, cbi("openvpn-advanced"), nil ).leaf = true
+ entry( {"admin", "services", "openvpn", "file"}, form("openvpn-file"), nil ).leaf = true
+ entry( {"admin", "services", "openvpn", "upload"}, call("ovpn_upload"))
+end
+
+function ovpn_upload()
+ local fs = require("nixio.fs")
+ local http = require("luci.http")
+ local util = require("luci.util")
+ local uci = require("luci.model.uci").cursor()
+ local upload = http.formvalue("ovpn_file")
+ local name = http.formvalue("instance_name2")
+ local file = "/etc/openvpn/" ..name.. ".ovpn"
+
+ if name and upload then
+ local fp
+
+ http.setfilehandler(
+ function(meta, chunk, eof)
+ local data = util.trim(chunk:gsub("\r\n", "\n")) .. "\n"
+ data = util.trim(data:gsub("[\128-\255]", ""))
+
+ if not fp and meta and meta.name == "ovpn_file" then
+ fp = io.open(file, "w")
+ end
+ if fp and data then
+ fp:write(data)
+ end
+ if fp and eof then
+ fp:close()
+ end
+ end
+ )
+
+ if fs.access(file) then
+ if not uci:get_first("openvpn", name) then
+ uci:set("openvpn", name, "openvpn")
+ uci:set("openvpn", name, "config", file)
+ uci:save("openvpn")
+ uci:commit("openvpn")
+ end
+ end
+ end
+ http.redirect(luci.dispatcher.build_url('admin/services/openvpn'))
end
diff --git a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-advanced.lua b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-advanced.lua
index 6dc43bec24..40201baceb 100644
--- a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-advanced.lua
+++ b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-advanced.lua
@@ -1,9 +1,7 @@
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Licensed to the public under the Apache License 2.0.
-require("luci.ip")
-require("luci.model.uci")
-
+local fs = require("nixio.fs")
local knownParams = {
--
@@ -160,6 +158,10 @@ local knownParams = {
"script_security",
{ 0, 1, 2, 3 },
translate("Policy level over usage of external programs and scripts") },
+ { ListValue,
+ "compress",
+ { "lzo", "lz4" },
+ translate("Enable a compression algorithm") },
} },
{ "Networking", {
@@ -236,6 +238,10 @@ local knownParams = {
"route_nopull",
0,
translate("Don't pull routes automatically") },
+ { Flag,
+ "allow_recursive_routing",
+ 0,
+ translate("Don't drop incoming tun packets with same destination as host") },
{ ListValue,
"mtu_disc",
{ "yes", "maybe", "no" },
@@ -244,6 +250,15 @@ local knownParams = {
"mtu_test",
0,
translate("Empirically measure MTU") },
+ { ListValue,
+ "comp_lzo",
+ { "yes", "no", "adaptive" },
+ translate("Use fast LZO compression") },
+ { Flag,
+ "comp_noadapt",
+ 0,
+ translate("Don't use adaptive lzo compression"),
+ { comp_lzo=1 } },
{ Value,
"link_mtu",
1500,
@@ -362,7 +377,7 @@ local knownParams = {
{ client="0" }, { client="" } },
{ DynamicList,
"push",
- { "redirect-gateway" },
+ { "redirect-gateway", "comp-lzo" },
translate("Push options to peer"),
{ client="0" }, { client="" } },
{ Flag,
@@ -464,7 +479,7 @@ local knownParams = {
0,
translate("Accept options pushed from server"),
{ client="1" } },
- { Value,
+ { FileUpload,
"auth_user_pass",
"/etc/openvpn/userpass.txt",
translate("Authenticate using username/password"),
@@ -540,6 +555,10 @@ local knownParams = {
{ "", "local", "def1", "local def1" },
translate("Automatically redirect default route"),
{ client="1" } },
+ { Value,
+ "verify_client_cert",
+ { "none", "optional", "require" },
+ translate("Specify whether the client is required to supply a valid certificate") },
} },
{ "Cryptography", {
@@ -555,7 +574,51 @@ local knownParams = {
-- parse
{ Value,
"cipher",
- "BF-CBC",
+ {
+ "AES-128-CBC",
+ "AES-128-CFB",
+ "AES-128-CFB1",
+ "AES-128-CFB8",
+ "AES-128-GCM",
+ "AES-128-OFB",
+ "AES-192-CBC",
+ "AES-192-CFB",
+ "AES-192-CFB1",
+ "AES-192-CFB8",
+ "AES-192-GCM",
+ "AES-192-OFB",
+ "AES-256-CBC",
+ "AES-256-CFB",
+ "AES-256-CFB1",
+ "AES-256-CFB8",
+ "AES-256-GCM",
+ "AES-256-OFB",
+ "BF-CBC",
+ "BF-CFB",
+ "BF-OFB",
+ "CAST5-CBC",
+ "CAST5-CFB",
+ "CAST5-OFB",
+ "DES-CBC",
+ "DES-CFB",
+ "DES-CFB1",
+ "DES-CFB8",
+ "DES-EDE-CBC",
+ "DES-EDE-CFB",
+ "DES-EDE-OFB",
+ "DES-EDE3-CBC",
+ "DES-EDE3-CFB",
+ "DES-EDE3-CFB1",
+ "DES-EDE3-CFB8",
+ "DES-EDE3-OFB",
+ "DES-OFB",
+ "DESX-CBC",
+ "RC2-40-CBC",
+ "RC2-64-CBC",
+ "RC2-CBC",
+ "RC2-CFB",
+ "RC2-OFB"
+ },
translate("Encryption cipher for packets") },
-- parse
{ Value,
@@ -689,10 +752,18 @@ local knownParams = {
"tls_version_max",
"1.2",
translate("The highest supported TLS version") },
- { Value,
+ { ListValue,
"key_direction",
- "1",
+ { 0, 1 },
translate("The key direction for 'tls-auth' and 'secret' options") },
+ { Flag,
+ "ncp_disable",
+ 0,
+ translate("This completely disables cipher negotiation") },
+ { Value,
+ "ncp_ciphers",
+ "AES-256-GCM:AES-128-GCM",
+ translate("Restrict the allowed ciphers to be negotiated") },
} }
}
@@ -701,8 +772,10 @@ local cts = { }
local params = { }
local m = Map("openvpn")
-local p = m:section( SimpleSection )
+m.redirect = luci.dispatcher.build_url("admin", "services", "openvpn")
+m.apply_on_parse = true
+local p = m:section( SimpleSection )
p.template = "openvpn/pageswitch"
p.mode = "advanced"
p.instance = arg[1]
@@ -732,8 +805,44 @@ for _, option in ipairs(params) do
option[2], option[4]
)
+ o.optional = true
+
if option[1] == DummyValue then
o.value = option[3]
+ elseif option[1] == FileUpload then
+
+ function o.cfgvalue(self, section)
+ local cfg_val = AbstractValue.cfgvalue(self, section)
+
+ if cfg_val then
+ return cfg_val
+ end
+ end
+
+ function o.formvalue(self, section)
+ local sel_val = AbstractValue.formvalue(self, section)
+ local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
+
+ if sel_val and sel_val ~= "" then
+ return sel_val
+ end
+
+ if txt_val and txt_val ~= "" then
+ return txt_val
+ end
+ end
+
+ function o.remove(self, section)
+ local cfg_val = AbstractValue.cfgvalue(self, section)
+ local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
+
+ if cfg_val and fs.access(cfg_val) and txt_val == "" then
+ fs.unlink(cfg_val)
+ end
+ return AbstractValue.remove(self, section)
+ end
+ elseif option[1] == Flag then
+ o.default = nil
else
if option[1] == DynamicList then
function o.cfgvalue(...)
@@ -742,8 +851,6 @@ for _, option in ipairs(params) do
end
end
- o.optional = true
-
if type(option[3]) == "table" then
if o.optional then o:value("", "-- remove --") end
for _, v in ipairs(option[3]) do
diff --git a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-basic.lua b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-basic.lua
index 483860c8e9..132c4d8f99 100644
--- a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-basic.lua
+++ b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-basic.lua
@@ -1,45 +1,104 @@
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Licensed to the public under the Apache License 2.0.
-require("luci.ip")
-require("luci.model.uci")
+local fs = require("nixio.fs")
local basicParams = {
- --
+ --
-- Widget, Name, Default(s), Description
--
-
- { ListValue, "verb", { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, translate("Set output verbosity") },
- { Value, "nice",0, translate("Change process priority") },
- { Value,"port",1194, translate("TCP/UDP port # for both local and remote") },
- { ListValue,"dev_type",{ "tun", "tap" }, translate("Type of used device") },
-
- { Value,"ifconfig","10.200.200.3 10.200.200.1", translate("Set tun/tap adapter parameters") },
- { Value,"server","10.200.200.0 255.255.255.0", translate("Configure server mode") },
- { Value,"server_bridge","192.168.1.1 255.255.255.0 192.168.1.128 192.168.1.254", translate("Configure server bridge") },
- { Flag,"nobind",0, translate("Do not bind to local address and port") },
-
- { Value,"keepalive","10 60", translate("Helper directive to simplify the expression of --ping and --ping-restart in server mode configurations") },
-
- { ListValue,"proto",{ "udp", "tcp-client", "tcp-server" }, translate("Use protocol") },
-
- { Flag,"client",0, translate("Configure client mode") },
- { Flag,"client_to_client",0, translate("Allow client-to-client traffic") },
- { DynamicList,"remote","vpnserver.example.org", translate("Remote host name or ip address") },
-
- { FileUpload,"secret","/etc/openvpn/secret.key", translate("Enable Static Key encryption mode (non-TLS)") },
- { Value,"key_direction","1", translate("The key direction for 'tls-auth' and 'secret' options") },
- { FileUpload,"pkcs12","/etc/easy-rsa/keys/some-client.pk12", translate("PKCS#12 file containing keys") },
- { FileUpload,"ca","/etc/easy-rsa/keys/ca.crt", translate("Certificate authority") },
- { FileUpload,"dh","/etc/easy-rsa/keys/dh1024.pem", translate("Diffie Hellman parameters") },
- { FileUpload,"cert","/etc/easy-rsa/keys/some-client.crt", translate("Local certificate") },
- { FileUpload,"key","/etc/easy-rsa/keys/some-client.key", translate("Local private key") },
+ { ListValue,
+ "verb",
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 },
+ translate("Set output verbosity") },
+ { Value,
+ "nice",
+ 0,
+ translate("Change process priority") },
+ { Value,
+ "port",
+ 1194,
+ translate("TCP/UDP port # for both local and remote") },
+ { ListValue,
+ "dev_type",
+ { "tun", "tap" },
+ translate("Type of used device") },
+ { Value,
+ "ifconfig",
+ "10.200.200.3 10.200.200.1",
+ translate("Set tun/tap adapter parameters") },
+ { Value,
+ "server",
+ "10.200.200.0 255.255.255.0",
+ translate("Configure server mode") },
+ { Value,
+ "server_bridge",
+ "192.168.1.1 255.255.255.0 192.168.1.128 192.168.1.254",
+ translate("Configure server bridge") },
+ { Flag,
+ "nobind",
+ 0,
+ translate("Do not bind to local address and port") },
+ { ListValue,
+ "comp_lzo",
+ {"yes","no","adaptive"},
+ translate("Use fast LZO compression") },
+ { Value,
+ "keepalive",
+ "10 60",
+ translate("Helper directive to simplify the expression of --ping and --ping-restart in server mode configurations") },
+ { ListValue,
+ "proto",
+ { "udp", "tcp-client", "tcp-server" },
+ translate("Use protocol") },
+ { Flag,
+ "client",
+ 0,
+ translate("Configure client mode") },
+ { Flag,
+ "client_to_client",
+ 0,
+ translate("Allow client-to-client traffic") },
+ { DynamicList,
+ "remote",
+ "vpnserver.example.org",
+ translate("Remote host name or ip address") },
+ { FileUpload,
+ "secret",
+ "/etc/openvpn/secret.key",
+ translate("Enable Static Key encryption mode (non-TLS)") },
+ { ListValue,
+ "key_direction",
+ { 0, 1 },
+ translate("The key direction for 'tls-auth' and 'secret' options") },
+ { FileUpload,
+ "pkcs12",
+ "/etc/easy-rsa/keys/some-client.pk12",
+ translate("PKCS#12 file containing keys") },
+ { FileUpload,
+ "ca",
+ "/etc/easy-rsa/keys/ca.crt",
+ translate("Certificate authority") },
+ { FileUpload,
+ "dh",
+ "/etc/easy-rsa/keys/dh1024.pem",
+ translate("Diffie Hellman parameters") },
+ { FileUpload,
+ "cert",
+ "/etc/easy-rsa/keys/some-client.crt",
+ translate("Local certificate") },
+ { FileUpload,
+ "key",
+ "/etc/easy-rsa/keys/some-client.key",
+ translate("Local private key") },
}
local m = Map("openvpn")
-local p = m:section( SimpleSection )
+m.redirect = luci.dispatcher.build_url("admin", "services", "openvpn")
+m.apply_on_parse = true
+local p = m:section( SimpleSection )
p.template = "openvpn/pageswitch"
p.mode = "basic"
p.instance = arg[1]
@@ -52,11 +111,45 @@ for _, option in ipairs(basicParams) do
option[1], option[2],
option[2], option[4]
)
-
+
o.optional = true
if option[1] == DummyValue then
o.value = option[3]
+ elseif option[1] == FileUpload then
+
+ function o.cfgvalue(self, section)
+ local cfg_val = AbstractValue.cfgvalue(self, section)
+
+ if cfg_val then
+ return cfg_val
+ end
+ end
+
+ function o.formvalue(self, section)
+ local sel_val = AbstractValue.formvalue(self, section)
+ local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
+
+ if sel_val and sel_val ~= "" then
+ return sel_val
+ end
+
+ if txt_val and txt_val ~= "" then
+ return txt_val
+ end
+ end
+
+ function o.remove(self, section)
+ local cfg_val = AbstractValue.cfgvalue(self, section)
+ local txt_val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
+
+ if cfg_val and fs.access(cfg_val) and txt_val == "" then
+ fs.unlink(cfg_val)
+ end
+ return AbstractValue.remove(self, section)
+ end
+ elseif option[1] == Flag then
+ o.default = nil
else
if option[1] == DynamicList then
function o.cfgvalue(...)
@@ -85,4 +178,3 @@ for _, option in ipairs(basicParams) do
end
return m
-
diff --git a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-file.lua b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-file.lua
new file mode 100644
index 0000000000..9d50601b1f
--- /dev/null
+++ b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn-file.lua
@@ -0,0 +1,82 @@
+-- Licensed to the public under the Apache License 2.0.
+
+local ip = require("luci.ip")
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local uci = require("luci.model.uci").cursor()
+local cfg_file = uci:get("openvpn", arg[1], "config")
+local auth_file = cfg_file:match("(.+)%..+").. ".auth"
+
+local m = Map("openvpn")
+
+local p = m:section( SimpleSection )
+p.template = "openvpn/pageswitch"
+p.mode = "file"
+p.instance = arg[1]
+
+if not cfg_file or not fs.access(cfg_file) then
+ local f = SimpleForm("error", nil, translatef("The OVPN config file (%s) could not be found, please check your configuration.", cfg_file or "n/a"))
+ f:append(Template("openvpn/ovpn_css"))
+ f.reset = false
+ f.submit = false
+ return m, f
+end
+
+if fs.stat(cfg_file).size >= 102400 then
+ f = SimpleForm("error", nil,
+ translatef("The size of the OVPN config file (%s) is too large for online editing in LuCI (&ge; 100 KB). ", cfg_file)
+ .. translate("Please edit this file directly in a terminal session."))
+ f:append(Template("openvpn/ovpn_css"))
+ f.reset = false
+ f.submit = false
+ return m, f
+end
+
+f = SimpleForm("cfg", nil)
+f:append(Template("openvpn/ovpn_css"))
+f.submit = translate("Save")
+f.reset = false
+
+s = f:section(SimpleSection, nil, translatef("Section to modify the OVPN config file (%s)", cfg_file))
+file = s:option(TextValue, "data1")
+file.datatype = "string"
+file.rows = 20
+
+function file.cfgvalue()
+ return fs.readfile(cfg_file) or ""
+end
+
+function file.write(self, section, data1)
+ return fs.writefile(cfg_file, "\n" .. util.trim(data1:gsub("\r\n", "\n")) .. "\n")
+end
+
+function file.remove(self, section, value)
+ return fs.writefile(cfg_file, "")
+end
+
+function s.handle(self, state, data1)
+ return true
+end
+
+s = f:section(SimpleSection, nil, translatef("Section to add an optional 'auth-user-pass' file with your credentials (%s)", auth_file))
+file = s:option(TextValue, "data2")
+file.datatype = "string"
+file.rows = 5
+
+function file.cfgvalue()
+ return fs.readfile(auth_file) or ""
+end
+
+function file.write(self, section, data2)
+ return fs.writefile(auth_file, util.trim(data2:gsub("\r\n", "\n")) .. "\n")
+end
+
+function file.remove(self, section, value)
+ return fs.writefile(auth_file, "")
+end
+
+function s.handle(self, state, data2)
+ return true
+end
+
+return m, f
diff --git a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua
index e17aa4085b..41266d860e 100644
--- a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua
+++ b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua
@@ -4,7 +4,7 @@
local fs = require "nixio.fs"
local sys = require "luci.sys"
local uci = require "luci.model.uci".cursor()
-local testfullps = luci.sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have
+local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have
local psstring = (string.len(testfullps)>0) and "ps w" or "ps axfw" --set command we use to get pid
local m = Map("openvpn", translate("OpenVPN"))
@@ -13,9 +13,16 @@ s.template = "cbi/tblsection"
s.template_addremove = "openvpn/cbi-select-input-add"
s.addremove = true
s.add_select_options = { }
-s.extedit = luci.dispatcher.build_url(
- "admin", "services", "openvpn", "basic", "%s"
-)
+
+local cfg = s:option(DummyValue, "config")
+function cfg.cfgvalue(self, section)
+ local file_cfg = self.map:get(section, "config")
+ if file_cfg then
+ s.extedit = luci.dispatcher.build_url("admin", "services", "openvpn", "file", "%s")
+ else
+ s.extedit = luci.dispatcher.build_url("admin", "services", "openvpn", "basic", "%s")
+ end
+end
uci:load("openvpn_recipes")
uci:foreach( "openvpn_recipes", "openvpn_recipe",
@@ -61,20 +68,38 @@ function s.create(self, name)
if s then
local options = uci:get_all("openvpn_recipes", recipe)
for k, v in pairs(options) do
- uci:set("openvpn", name, k, v)
+ if k ~= "_role" and k ~= "_description" then
+ if type(v) == "boolean" then
+ v = v and "1" or "0"
+ end
+ uci:set("openvpn", name, k, v)
+ end
end
- uci:delete("openvpn", name, "_role")
- uci:delete("openvpn", name, "_description")
uci:save("openvpn")
- luci.http.redirect( self.extedit:format(name) )
+ uci:commit("openvpn")
+ if extedit then
+ luci.http.redirect( self.extedit:format(name) )
+ end
end
elseif #name > 0 then
self.invalid_cts = true
end
-
return 0
end
+function s.remove(self, name)
+ local cfg_file = "/etc/openvpn/" ..name.. ".ovpn"
+ local auth_file = "/etc/openvpn/" ..name.. ".auth"
+ if fs.access(cfg_file) then
+ fs.unlink(cfg_file)
+ end
+ if fs.access(auth_file) then
+ fs.unlink(auth_file)
+ end
+ uci:delete("openvpn", name)
+ uci:save("openvpn")
+ uci:commit("openvpn")
+end
s:option( Flag, "enabled", translate("Enabled") )
@@ -106,28 +131,45 @@ function updown.cfgvalue(self, section)
end
function updown.write(self, section, value)
if self.option == "stop" then
- luci.sys.call("/etc/init.d/openvpn stop %s" % section)
+ sys.call("/etc/init.d/openvpn stop %s" % section)
else
- luci.sys.call("/etc/init.d/openvpn start %s" % section)
+ sys.call("/etc/init.d/openvpn start %s" % section)
end
luci.http.redirect( self.redirect )
end
-
local port = s:option( DummyValue, "port", translate("Port") )
function port.cfgvalue(self, section)
local val = AbstractValue.cfgvalue(self, section)
- return val or "1194"
+ if not val then
+ local file_cfg = self.map:get(section, "config")
+ if file_cfg and fs.access(file_cfg) then
+ val = sys.exec("awk '{if(match(tolower($1),/^port$/)&&match($2,/[0-9]+/)){cnt++;printf $2;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
+ if val == "-" then
+ val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match($3,/[0-9]+/)){cnt++;printf $3;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
+ end
+ end
+ end
+ return val or "-"
end
local proto = s:option( DummyValue, "proto", translate("Protocol") )
function proto.cfgvalue(self, section)
local val = AbstractValue.cfgvalue(self, section)
- return val or "udp"
+ if not val then
+ local file_cfg = self.map:get(section, "config")
+ if file_cfg and fs.access(file_cfg) then
+ val = sys.exec("awk '{if(match(tolower($1),/^proto$/)&&match(tolower($2),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf tolower($2);exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
+ if val == "-" then
+ val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match(tolower($4),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf $4;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
+ end
+ end
+ end
+ return val or "-"
end
-function m.on_after_commit(self,map)
- require("luci.sys").call('/etc/init.d/openvpn reload')
+function m.on_after_apply(self,map)
+ sys.call('/etc/init.d/openvpn reload')
end
return m
diff --git a/applications/luci-app-openvpn/luasrc/view/openvpn/cbi-select-input-add.htm b/applications/luci-app-openvpn/luasrc/view/openvpn/cbi-select-input-add.htm
index 0166de778e..e75bfda900 100644
--- a/applications/luci-app-openvpn/luasrc/view/openvpn/cbi-select-input-add.htm
+++ b/applications/luci-app-openvpn/luasrc/view/openvpn/cbi-select-input-add.htm
@@ -1,11 +1,111 @@
-<div class="cbi-section-create">
- <% if self.invalid_cts then -%><div class="cbi-section-error"><% end %>
- <input type="text" class="cbi-section-create-name" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.text" />
- <select class="cbi-section-create-name" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.select">
- <%- for k, v in luci.util.kspairs(self.add_select_options) do %>
- <option value="<%=k%>"><%=luci.util.pcdata(v)%></option>
- <% end -%>
- </select>
- <input class="cbi-button cbi-button-add" type="submit" value="<%:Add%>" title="<%:Add%>" />
- <% if self.invalid_cts then %><br /><%:Invalid%></div><% end %>
+
+<script type="text/javascript">
+//<![CDATA[
+ function vpn_add()
+ {
+ var vpn_name = div_add.querySelector("#instance_name1").value.replace(/[^\x00-\x7F]|[\s!@#$%^&*()\-+=\[\]{};':"\\|,<>\/?]/g,'');
+ var vpn_template = div_add.querySelector("#instance_template").value;
+ var form = document.getElementsByName('cbi')[0];
+
+ if (!vpn_name || !vpn_name.length)
+ {
+ return info_message(vpn_output, "<%=pcdata(translate("The 'Name' field must not be empty!"))%>", 2000);
+ }
+
+ document.getElementById("instance_name1").value = vpn_name;
+ if (document.getElementById("cbi-openvpn-" + vpn_name) != null)
+ {
+ return info_message(vpn_output, "<%=pcdata(translate("Instance with that name already exists!"))%>", 2000);
+ }
+
+ if (!vpn_template || !vpn_template.length)
+ {
+ return info_message(vpn_output, "<%=pcdata(translate("Please select a valid VPN template!"))%>", 2000);
+ }
+
+ if (form)
+ {
+ form.submit();
+ }
+ }
+
+ function vpn_upload()
+ {
+ var vpn_name = div_upload.querySelector("#instance_name2").value.replace(/[^\x00-\x7F]|[\s!@#$%^&*()\-+=\[\]{};':"\\|,<>\/?]/g,'');
+ var vpn_file = document.getElementById("ovpn_file").value;
+ var form = document.getElementsByName('cbi')[0];
+
+ if (!vpn_name || !vpn_name.length)
+ {
+ return info_message(vpn_output, "<%=pcdata(translate("The 'Name' field must not be empty!"))%>", 2000);
+ }
+
+ document.getElementById("instance_name2").value = vpn_name;
+ if (document.getElementById("cbi-openvpn-" + vpn_name) != null)
+ {
+ return info_message(vpn_output, "<%=pcdata(translate("Instance with that name already exists!"))%>", 2000);
+ }
+
+ if (!vpn_file || !vpn_file.length)
+ {
+ return info_message(vpn_output, "<%=pcdata(translate("Please select a valid OVPN config file to upload!"))%>", 2000);
+ }
+
+ if (form)
+ {
+ form.enctype = 'multipart/form-data';
+ form.action = '<%=url('admin/services/openvpn/upload')%>';
+ form.submit();
+ }
+ }
+
+ function info_message(output, msg, timeout)
+ {
+ timeout = timeout || 0;
+ output.innerHTML = '<em>' + msg + '</em>';
+ if (timeout > 0)
+ {
+ setTimeout(function(){ output.innerHTML=""}, timeout);
+ }
+ }
+//]]>
+</script>
+
+<%+openvpn/ovpn_css%>
+
+<div class="cbi-section-node">
+ <div class="table cbi-section-table">
+ <h4><%:Template based configuration%></h4>
+ <div class="tr cbi-section-table-row" id="div_add">
+ <div class="td left">
+ <input type="text" maxlength="20" placeholder="Instance name" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.text" id="instance_name1" />
+ </div>
+ <div class="td left">
+ <select id="instance_template" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.select">
+ <option value="" selected="selected" disabled="disabled"><%:Select template ...%></option>
+ <%- for k, v in luci.util.kspairs(self.add_select_options) do %>
+ <option value="<%=k%>"><%=luci.util.pcdata(v)%></option>
+ <% end -%>
+ </select>
+ </div>
+ <div class="td left">
+ <input class="cbi-button cbi-button-add" type="submit" onclick="vpn_add(); return false;" value="<%:Add%>" title="<%:Add template based configuration%>" /><br />
+ </div>
+ </div>
+ <h4><%:OVPN configuration file upload%></h4>
+ <div class="tr cbi-section-table-row" id="div_upload">
+ <div class="td left">
+ <input type="text" maxlength="20" placeholder="Instance name" name="instance_name2" id="instance_name2" />
+ </div>
+ <div class="td left">
+ <input type="file" name="ovpn_file" id="ovpn_file" accept="application/x-openvpn-profile,.ovpn" />
+ </div>
+ <div class="td left">
+ <input class="cbi-button cbi-button-add" type="submit" onclick="vpn_upload(); return false;" value="<%:Upload%>" title="<%:Upload ovpn file%>" />
+ </div>
+ </div>
+ </div>
+ <div class="vpn-output">
+ <span id="vpn_output"></span>
+ </div>
</div>
diff --git a/applications/luci-app-openvpn/luasrc/view/openvpn/ovpn_css.htm b/applications/luci-app-openvpn/luasrc/view/openvpn/ovpn_css.htm
new file mode 100644
index 0000000000..55c0a543fc
--- /dev/null
+++ b/applications/luci-app-openvpn/luasrc/view/openvpn/ovpn_css.htm
@@ -0,0 +1,38 @@
+<style type="text/css">
+ h4
+ {
+ white-space: nowrap;
+ border-bottom: 0px;
+ margin: 10px 5px 5px 5px;
+ }
+ .tr
+ {
+ border: 0px;
+ text-align: left;
+ }
+ .vpn-output
+ {
+ box-shadow: none;
+ margin: 10px 5px 5px 5px;
+ color: #a22;
+ }
+ textarea
+ {
+ border: 1px solid #cccccc;
+ padding: 5px;
+ font-size: 12px;
+ font-family: monospace;
+ resize: none;
+ white-space: pre;
+ overflow-wrap: normal;
+ overflow-x: scroll;
+ }
+ a
+ {
+ line-height: 1.5;
+ }
+ hr
+ {
+ margin: 0.5em 0;
+ }
+</style>
diff --git a/applications/luci-app-openvpn/luasrc/view/openvpn/pageswitch.htm b/applications/luci-app-openvpn/luasrc/view/openvpn/pageswitch.htm
index 8cb019b461..c1fe05215a 100644
--- a/applications/luci-app-openvpn/luasrc/view/openvpn/pageswitch.htm
+++ b/applications/luci-app-openvpn/luasrc/view/openvpn/pageswitch.htm
@@ -4,25 +4,25 @@
Licensed to the public under the Apache License 2.0.
-%>
+<%+openvpn/ovpn_css%>
+
<div class="cbi-section">
<h3>
- <a href="<%=url('admin/services/openvpn')%>"><%:Overview%></a> &raquo;
+ <a href="<%=url('admin/services/openvpn')%>"><%:Overview%></a> &#187;
<%=luci.i18n.translatef("Instance \"%s\"", self.instance)%>
</h3>
-
<% if self.mode == "basic" then %>
- <a href="<%=url('admin/services/openvpn/advanced', self.instance, "Service")%>"><%:Switch to advanced configuration »%></a>
- <% else %>
- <a href="<%=url('admin/services/openvpn/basic', self.instance)%>"><%:« Switch to basic configuration%></a>
- <hr style="margin:0.5em 0" />
+ <a href="<%=url('admin/services/openvpn/advanced', self.instance, "Service")%>"><%:Switch to advanced configuration%> &#187;</a><p/>
+ <hr />
+ <% elseif self.mode == "advanced" then %>
+ <a href="<%=url('admin/services/openvpn/basic', self.instance)%>"><%:Switch to basic configuration%> &#187;</a><p/>
+ <hr />
<%:Configuration category%>:
<% for i, c in ipairs(self.categories) do %>
<% if c == self.category then %>
<strong><%=translate(c)%></strong>
<% else %>
- <a href="<%=luci.dispatcher.build_url(
- "admin", "services", "openvpn", "advanced", self.instance, c
- )%>"><%=translate(c)%></a>
+ <a href="<%=luci.dispatcher.build_url("admin", "services", "openvpn", "advanced", self.instance, c)%>"><%=translate(c)%></a>
<% end %>
<% if next(self.categories, i) then %>|<% end %>
<% end %>