summaryrefslogtreecommitdiffhomepage
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js161
-rw-r--r--protocols/luci-proto-3g/luasrc/model/cbi/admin_network/proto_3g.lua149
-rw-r--r--protocols/luci-proto-3g/luasrc/model/network/proto_3g.lua2
-rw-r--r--protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js48
-rw-r--r--protocols/luci-proto-hnet/luasrc/model/cbi/admin_network/proto_hnet.lua37
-rw-r--r--protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js69
-rw-r--r--protocols/luci-proto-ipip/luasrc/model/cbi/admin_network/proto_ipip.lua34
-rw-r--r--protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js60
-rw-r--r--protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js101
-rw-r--r--protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js81
-rw-r--r--protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js65
-rw-r--r--protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js58
-rw-r--r--protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js79
-rw-r--r--protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js96
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_464xlat.lua33
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua102
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6rd.lua72
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6to4.lua37
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dhcpv6.lua58
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dslite.lua53
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_map.lua88
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/network/proto_4x6.lua2
-rw-r--r--protocols/luci-proto-ipv6/luasrc/model/network/proto_6x4.lua2
-rw-r--r--protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js123
-rw-r--r--protocols/luci-proto-ncm/luasrc/model/cbi/admin_network/proto_ncm.lua110
-rw-r--r--protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js159
-rw-r--r--protocols/luci-proto-openconnect/luasrc/model/cbi/admin_network/proto_openconnect.lua90
-rwxr-xr-xprotocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect78
-rw-r--r--protocols/luci-proto-openconnect/root/usr/share/rpcd/acl.d/luci-openconnect.json17
-rw-r--r--protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js75
-rw-r--r--protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js149
-rw-r--r--protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js136
-rw-r--r--protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js114
-rw-r--r--protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js123
-rw-r--r--protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_l2tp.lua61
-rw-r--r--protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_ppp.lua127
-rw-r--r--protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoa.lua133
-rw-r--r--protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoe.lua135
-rw-r--r--protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pptp.lua106
-rw-r--r--protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js142
-rw-r--r--protocols/luci-proto-pppossh/luasrc/model/cbi/admin_network/proto_pppossh.lua122
-rw-r--r--protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js101
-rw-r--r--protocols/luci-proto-qmi/luasrc/model/cbi/admin_network/proto_qmi.lua63
-rw-r--r--protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js183
-rw-r--r--protocols/luci-proto-relay/luasrc/model/cbi/admin_network/proto_relay.lua68
-rw-r--r--protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js111
-rw-r--r--protocols/luci-proto-vpnc/luasrc/model/cbi/admin_network/proto_vpnc.lua85
-rw-r--r--protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js140
-rw-r--r--protocols/luci-proto-wireguard/luasrc/model/cbi/admin_network/proto_wireguard.lua179
49 files changed, 2472 insertions, 1945 deletions
diff --git a/protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js b/protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js
new file mode 100644
index 0000000000..07bed36c23
--- /dev/null
+++ b/protocols/luci-proto-3g/htdocs/luci-static/resources/protocol/3g.js
@@ -0,0 +1,161 @@
+'use strict';
+'require rpc';
+'require uci';
+'require form';
+'require network';
+
+var callFileList = rpc.declare({
+ object: 'file',
+ method: 'list',
+ params: [ 'path' ],
+ expect: { entries: [] },
+ filter: function(list, params) {
+ var rv = [];
+ for (var i = 0; i < list.length; i++)
+ if (list[i].name.match(/^tty[A-Z]/) || list[i].name.match(/^cdc-wdm/) || list[i].name.match(/^[0-9]+$/))
+ rv.push(params.path + list[i].name);
+ return rv.sort();
+ }
+});
+
+network.registerPatternVirtual(/^3g-.+$/);
+
+function write_keepalive(section_id, value) {
+ var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
+ i_opt = this.map.lookupOption('_keepalive_interval', section_id),
+ f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
+ i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
+
+ if (f == null || f == '' || isNaN(f))
+ f = 0;
+
+ if (i == null || i == '' || isNaN(i) || i < 1)
+ i = 1;
+
+ if (f > 0)
+ uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
+ else
+ uci.unset('network', section_id, 'keepalive');
+}
+
+return network.registerProtocol('3g', {
+ getI18n: function() {
+ return _('UMTS/GPRS/EV-DO');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || '3g-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'comgt';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'device', _('Modem device'));
+ o.rmempty = false;
+ o.load = function(section_id) {
+ return callFileList('/dev/').then(L.bind(function(devices) {
+ for (var i = 0; i < devices.length; i++)
+ this.value(devices[i]);
+ return callFileList('/dev/tts/');
+ }, this)).then(L.bind(function(devices) {
+ for (var i = 0; i < devices.length; i++)
+ this.value(devices[i]);
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ o = s.taboption('general', form.Value, 'service', _('Service Type'));
+ o.value('', _('-- Please choose --'));
+ o.value('umts', 'UMTS/GPRS');
+ o.value('umts_only', _('UMTS only'));
+ o.value('gprs_only', _('GPRS only'));
+ o.value('evdo', 'CDMA/EV-DO');
+
+ s.taboption('general', form.Value, 'apn', _('APN'));
+ s.taboption('general', form.Value, 'pincode', _('PIN'));
+ s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.password = true;
+
+ o = s.taboption('general', form.Value, 'dialnumber', _('Dial number'));
+ o.placeholder = '*99***1#';
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'));
+ o.value('auto', _('Automatic'));
+ o.value('0', _('Disabled'));
+ o.value('1', _('Manual'));
+ o.default = 'auto';
+ }
+
+ o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready'));
+ o.placeholder = '10';
+ o.datatype = 'min(1)';
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+
+ o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^(\d+)[ ,]\d+$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
+ o.placeholder = '5';
+ o.datatype = 'min(1)';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^\d+[ ,](\d+)$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ }
+});
diff --git a/protocols/luci-proto-3g/luasrc/model/cbi/admin_network/proto_3g.lua b/protocols/luci-proto-3g/luasrc/model/cbi/admin_network/proto_3g.lua
deleted file mode 100644
index 85c5cd6042..0000000000
--- a/protocols/luci-proto-3g/luasrc/model/cbi/admin_network/proto_3g.lua
+++ /dev/null
@@ -1,149 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local device, apn, service, pincode, username, password, dialnumber
-local ipv6, delay, defaultroute, metric, peerdns, dns,
- keepalive_failure, keepalive_interval, demand
-
-
-device = section:taboption("general", Value, "device", translate("Modem device"))
-device.rmempty = false
-
-local device_suggestions = nixio.fs.glob("/dev/tty[A-Z]*")
- or nixio.fs.glob("/dev/tts/*")
-
-if device_suggestions then
- local node
- for node in device_suggestions do
- device:value(node)
- end
-end
-
-
-service = section:taboption("general", Value, "service", translate("Service Type"))
-service:value("", translate("-- Please choose --"))
-service:value("umts", "UMTS/GPRS")
-service:value("umts_only", translate("UMTS only"))
-service:value("gprs_only", translate("GPRS only"))
-service:value("evdo", "CDMA/EV-DO")
-
-
-apn = section:taboption("general", Value, "apn", translate("APN"))
-
-
-pincode = section:taboption("general", Value, "pincode", translate("PIN"))
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password.password = true
-
-dialnumber = section:taboption("general", Value, "dialnumber", translate("Dial number"))
-dialnumber.placeholder = "*99***1#"
-
-if luci.model.network:has_ipv6() then
-
- ipv6 = section:taboption("advanced", ListValue, "ipv6",
- translate("Obtain IPv6-Address"))
-
- ipv6:value("auto", translate("Automatic"))
- ipv6:value("0", translate("Disabled"))
- ipv6:value("1", translate("Manual"))
- ipv6.default = "auto"
-
-end
-
-
-delay = section:taboption("advanced", Value, "delay",
- translate("Modem init timeout"),
- translate("Maximum amount of seconds to wait for the modem to become ready"))
-
-delay.placeholder = "10"
-delay.datatype = "min(1)"
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
-
-keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure",
- translate("LCP echo failure threshold"),
- translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures"))
-
-function keepalive_failure.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^(%d+)[ ,]+%d+") or v)
- end
-end
-
-function keepalive_failure.write() end
-function keepalive_failure.remove() end
-
-keepalive_failure.placeholder = "0"
-keepalive_failure.datatype = "uinteger"
-
-
-keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval",
- translate("LCP echo interval"),
- translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold"))
-
-function keepalive_interval.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^%d+[ ,]+(%d+)"))
- end
-end
-
-function keepalive_interval.write(self, section, value)
- local f = tonumber(keepalive_failure:formvalue(section)) or 0
- local i = tonumber(value) or 5
- if i < 1 then i = 1 end
- if f > 0 then
- m:set(section, "keepalive", "%d %d" %{ f, i })
- else
- m:del(section, "keepalive")
- end
-end
-
-keepalive_interval.remove = keepalive_interval.write
-keepalive_interval.placeholder = "5"
-keepalive_interval.datatype = "min(1)"
-
-
-demand = section:taboption("advanced", Value, "demand",
- translate("Inactivity timeout"),
- translate("Close inactive connection after the given amount of seconds, use 0 to persist connection"))
-
-demand.placeholder = "0"
-demand.datatype = "uinteger"
diff --git a/protocols/luci-proto-3g/luasrc/model/network/proto_3g.lua b/protocols/luci-proto-3g/luasrc/model/network/proto_3g.lua
index b2454838f9..60d8e2ebae 100644
--- a/protocols/luci-proto-3g/luasrc/model/network/proto_3g.lua
+++ b/protocols/luci-proto-3g/luasrc/model/network/proto_3g.lua
@@ -38,7 +38,7 @@ function proto.get_interfaces(self)
return nil
end
-function proto.contains_interface(self, ifname)
+function proto.contains_interface(self, ifc)
if self:is_floating() then
return (netmod:ifnameof(ifc) == self:ifname())
else
diff --git a/protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js b/protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js
new file mode 100644
index 0000000000..84396ede08
--- /dev/null
+++ b/protocols/luci-proto-hnet/htdocs/luci-static/resources/protocol/hnet.js
@@ -0,0 +1,48 @@
+'use strict';
+'require form';
+'require network';
+
+return network.registerProtocol('hnet', {
+ getI18n: function() {
+ return _('Automatic Homenet (HNCP)');
+ },
+
+ getOpkgPackage: function() {
+ return 'hnet-full';
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL2Device() || this.getDevice(), o;
+
+ o = s.taboption('general', form.ListValue, 'mode', _('Category'));
+ o.value('auto', _('Automatic'));
+ o.value('external', _('External'));
+ o.value('internal', _('Internal'));
+ o.value('leaf', _('Leaf'));
+ o.value('guest', _('Guest'));
+ o.value('adhoc', _('Ad-Hoc'));
+ o.value('hybrid', _('Hybrid'));
+ o.default = 'auto';
+
+ o = s.taboption('advanced', form.Value, 'ip6assign', _('IPv6 assignment length'), _('Assign a part of given length of every public IPv6-prefix to this interface'));
+ o.datatype = 'max(128)';
+ o.default = '64';
+
+ s.taboption('advanced', form.Value, 'link_id', _('IPv6 assignment hint'), _('Assign prefix parts using this hexadecimal subprefix ID for this interface.'));
+
+ o = s.taboption('advanced', form.Value, 'ip4assign', _('IPv4 assignment length'));
+ o.datatype = 'max(32)';
+ o.default = '24';
+
+ o = s.taboption('advanced', form.Value, 'dnsname', _('DNS-Label / FQDN'));
+ o.default = s.section;
+
+ o = s.taboption('advanced', form.Value, 'macaddr', _('Override MAC address'));
+ o.datatype = 'macaddr';
+ o.placeholder = dev ? (dev.getMAC() || '') : '';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.datatype = 'max(9200)';
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ }
+});
diff --git a/protocols/luci-proto-hnet/luasrc/model/cbi/admin_network/proto_hnet.lua b/protocols/luci-proto-hnet/luasrc/model/cbi/admin_network/proto_hnet.lua
deleted file mode 100644
index 2ed34faf71..0000000000
--- a/protocols/luci-proto-hnet/luasrc/model/cbi/admin_network/proto_hnet.lua
+++ /dev/null
@@ -1,37 +0,0 @@
--- Copyright 2013 Steven Barth <steven@midlink.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local mode = section:taboption("general", ListValue, "mode", translate("Category"))
-mode:value("auto", translate("Automatic"))
-mode:value("external", translate("External"))
-mode:value("internal", translate("Internal"))
-mode:value("leaf", translate("Leaf"))
-mode:value("guest", translate("Guest"))
-mode:value("adhoc", translate("Ad-Hoc"))
-mode:value("hybrid", translate("Hybrid"))
-mode.default = "auto"
-
-
-
-local plen = section:taboption("advanced", Value, "ip6assign", translate("IPv6 assignment length"),
- translate("Assign a part of given length of every public IPv6-prefix to this interface"))
-plen.datatype = "max(128)"
-plen.default = "64"
-
-section:taboption("advanced", Value, "link_id", translate("IPv6 assignment hint"),
- translate("Assign prefix parts using this hexadecimal subprefix ID for this interface."))
-
-plen = section:taboption("advanced", Value, "ip4assign", translate("IPv4 assignment length"))
-plen.datatype = "max(32)"
-plen.default = "24"
-
-local o = section:taboption("advanced", Value, "dnsname", translate("DNS-Label / FQDN"))
-o.default = map.name
-
-luci.tools.proto.opt_macaddr(section, ifc, translate("Override MAC address"))
-
-o = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-o.placeholder = "1500"
-o.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js b/protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js
new file mode 100644
index 0000000000..7423a08585
--- /dev/null
+++ b/protocols/luci-proto-ipip/htdocs/luci-static/resources/protocol/ipip.js
@@ -0,0 +1,69 @@
+'use strict';
+'require form';
+'require network';
+'require tools.widgets as widgets';
+
+network.registerPatternVirtual(/^ipip-.+$/);
+
+return network.registerProtocol('ipip', {
+ getI18n: function() {
+ return _('IPv4-in-IPv4 (RFC2003)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'ipip-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'ipip';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'peeraddr', _('Remote IPv4 address or FQDN'), _('The IPv4 address or the fully-qualified domain name of the remote tunnel end.'));
+ o.optional = false;
+ o.datatype = 'or(hostname,ip4addr("nomask"))';
+
+ o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('The local IPv4 address over which the tunnel is created (optional).'));
+ o.optional = true;
+ o.datatype = 'ip4addr("nomask")';
+
+ o = s.taboption('general', widgets.NetworkSelect, 'tunlink', _('Bind interface'), _('Bind the tunnel to this interface (optional).'));
+ o.exclude = s.section;
+ o.nocreate = true;
+ o.optional = true;
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'), _('Specify an MTU (Maximum Transmission Unit) other than the default (1280 bytes).'));
+ o.optional = true;
+ o.placeholder = 1280;
+ o.datatype = 'range(68, 9200)';
+
+ o = s.taboption('advanced', form.Value, 'ttl', _('Override TTL'), _('Specify a TTL (Time to Live) for the encapsulating packet other than the default (64).'));
+ o.optional = true;
+ o.placeholder = 64;
+ o.datatype = 'min(1)';
+
+ o = s.taboption('advanced', form.Value, 'tos', _('Override TOS'), _('Specify a TOS (Type of Service).'));
+ o.optional = true;
+ o.datatype = 'range(0, 255)';
+
+ s.taboption('advanced', form.Flag, 'df', _("Don't Fragment"), _("Enable the DF (Don't Fragment) flag of the encapsulating packets."));
+ }
+});
diff --git a/protocols/luci-proto-ipip/luasrc/model/cbi/admin_network/proto_ipip.lua b/protocols/luci-proto-ipip/luasrc/model/cbi/admin_network/proto_ipip.lua
deleted file mode 100644
index 8817f18d6d..0000000000
--- a/protocols/luci-proto-ipip/luasrc/model/cbi/admin_network/proto_ipip.lua
+++ /dev/null
@@ -1,34 +0,0 @@
--- Copyright 2016 Roger Pueyo Centelles <roger.pueyo@guifi.net>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local peeraddr, ipaddr, ttl, tos, df, mtu, tunlink
-
-peeraddr = section:taboption("general", Value, "peeraddr", translate("Remote IPv4 address or FQDN"), translate("The IPv4 address or the fully-qualified domain name of the remote tunnel end."))
-peeraddr.optional = false
-peeraddr.datatype = "or(hostname,ip4addr)"
-
-ipaddr = section:taboption("general", Value, "ipaddr", translate("Local IPv4 address"), translate("The local IPv4 address over which the tunnel is created (optional)."))
-ipaddr.optional = true
-ipaddr.datatype = "ip4addr"
-
-tunlink = section:taboption("general", Value, "tunlink", translate("Bind interface"), translate("Bind the tunnel to this interface (optional)."))
-ipaddr.optional = true
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"), translate("Specify an MTU (Maximum Transmission Unit) other than the default (1280 bytes)."))
-mtu.optional = true
-mtu.placeholder = 1280
-mtu.datatype = "range(68, 9200)"
-
-ttl = section:taboption("advanced", Value, "ttl", translate("Override TTL"), translate("Specify a TTL (Time to Live) for the encapsulating packet other than the default (64)."))
-ttl.optional = true
-ttl.placeholder = 64
-ttl.datatype = "min(1)"
-
-tos = section:taboption("advanced", Value, "tos", translate("Override TOS"), translate("Specify a TOS (Type of Service)."))
-tos.optional = true
-tos.datatype = "range(0, 255)"
-
-df = section:taboption("advanced", Flag, "df", translate("Don't Fragment"), translate("Enable the DF (Don't Fragment) flag of the encapsulating packets."))
diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js
new file mode 100644
index 0000000000..a74708fd01
--- /dev/null
+++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/464xlat.js
@@ -0,0 +1,60 @@
+'use strict';
+'require form';
+'require network';
+'require tools.widgets as widgets';
+
+network.registerPatternVirtual(/^464-.+$/);
+network.registerErrorCode('CLAT_CONFIG_FAILED', _('CLAT configuration failed'));
+
+return network.registerProtocol('464xlat', {
+ getI18n: function() {
+ return _('464XLAT (CLAT)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || '464-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return '464xlat';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'ip6prefix', _('NAT64 Prefix'), _('Leave empty to autodetect'));
+ o.datatype = 'cidr6';
+
+ o = s.taboption('advanced', widgets.NetworkSelect, 'tunlink', _('Tunnel Link'));
+ o.nocreate = true;
+ o.exclude = s.section;
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
+ o.placeholder = '1280';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js
new file mode 100644
index 0000000000..f26ced7b40
--- /dev/null
+++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6in4.js
@@ -0,0 +1,101 @@
+'use strict';
+'require uci';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^6in4-.+$/);
+
+return network.registerProtocol('6in4', {
+ getI18n: function() {
+ return _('IPv6-in-IPv4 (RFC4213)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || '6in4-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return '6in4';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Leave empty to use the current WAN address'));
+ o.datatype = 'ip4addr("nomask")';
+ o.load = function(section_id) {
+ return network.getWANNetworks().then(L.bind(function(nets) {
+ if (nets.length)
+ this.placeholder = nets[0].getIPAddr();
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ o = s.taboption('general', form.Value, 'peeraddr', _('Remote IPv4 address'), _('This is usually the address of the nearest PoP operated by the tunnel broker'));
+ o.rmempty = false;
+ o.datatype = 'ip4addr("nomask")';
+
+ o = s.taboption('general', form.Value, 'ip6addr', _('Local IPv6 address'), _('This is the local endpoint address assigned by the tunnel broker, it usually ends with <code>...:2/64</code>'));
+ o.datatype = 'cidr6';
+
+ o = s.taboption('general', form.DynamicList, 'ip6prefix', _('IPv6 routed prefix'), _('This is the prefix routed to you by the tunnel broker for use by clients'));
+ o.datatype = 'cidr6';
+
+ o = s.taboption('general', form.Flag, '_update', _('Dynamic tunnel'), _('Enable HE.net dynamic endpoint update'));
+ o.enabled = '1';
+ o.disabled = '0';
+ o.write = function() {};
+ o.remove = function() {};
+ o.cfgvalue = function(section_id) {
+ return !isNaN(+uci.get('network', section_id, 'tunnelid')) ? this.enabled : this.disabled;
+ };
+
+ o = s.taboption('general', form.Value, 'tunnelid', _('Tunnel ID'));
+ o.datatype = 'uinteger';
+ o.depends('_update', '1');
+
+ o = s.taboption('general', form.Value, 'username', _('HE.net username'), _('This is the plain username for logging into the account'));
+ o.depends('_update', '1');
+ o.validate = function(section_id, value) {
+ if (/^[a-fA-F0-9]{32}$/.test(value))
+ return _('The HE.net endpoint update configuration changed, you must now use the plain username instead of the user ID!');
+ return true;
+ };
+
+ o = s.taboption('general', form.Value, 'password', _('HE.net password'), _('This is either the "Update Key" configured for the tunnel or the account password if no update key has been configured'));
+ o.password = true;
+ o.depends('_update', '1');
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
+ o.placeholder = '64';
+ o.datatype = 'range(1,255)';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
+ o.placeholder = '1280';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js
new file mode 100644
index 0000000000..6a8f506bc9
--- /dev/null
+++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6rd.js
@@ -0,0 +1,81 @@
+'use strict';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^6rd-.+$/);
+
+return network.registerProtocol('6rd', {
+ getI18n: function() {
+ return _('IPv6-over-IPv4 (6rd)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || '6rd-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return '6rd';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Leave empty to use the current WAN address'));
+ o.datatype = 'ip4addr("nomask")';
+ o.load = function(section_id) {
+ return network.getWANNetworks().then(L.bind(function(nets) {
+ if (nets.length)
+ this.placeholder = nets[0].getIPAddr();
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ o = s.taboption('general', form.Value, 'peeraddr', _('Remote IPv4 address'), _('This IPv4 address of the relay'));
+ o.rmempty = false;
+ o.datatype = 'ip4addr("nomask")';
+
+ o = s.taboption('general', form.Value, 'ip6prefix', _('IPv6 prefix'), _('The IPv6 prefix assigned to the provider, usually ends with <code>::</code>'));
+ o.rmempty = false;
+ o.datatype = 'ip6addr';
+
+ o = s.taboption('general', form.Value, 'ip6prefixlen', _('IPv6 prefix length'), _('The length of the IPv6 prefix in bits'));
+ o.placeholder = '16';
+ o.datatype = 'range(0,128)';
+
+ o = s.taboption('general', form.Value, 'ip4prefixlen', _('IPv4 prefix length'), _('The length of the IPv4 prefix in bits, the remainder is used in the IPv6 addresses.'));
+ o.placeholder = '0';
+ o.datatype = 'range(0,32)';
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
+ o.placeholder = '64';
+ o.datatype = 'range(1,255)';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
+ o.placeholder = '1280';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js
new file mode 100644
index 0000000000..abfe1c8fc4
--- /dev/null
+++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/6to4.js
@@ -0,0 +1,65 @@
+'use strict';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^6to4-.+$/);
+
+return network.registerProtocol('6to4', {
+ getI18n: function() {
+ return _('IPv6-over-IPv4 (6to4)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || '6to4-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return '6rd';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Leave empty to use the current WAN address'));
+ o.datatype = 'ip4addr("nomask")';
+ o.load = function(section_id) {
+ return network.getWANNetworks().then(L.bind(function(nets) {
+ if (nets.length)
+ this.placeholder = nets[0].getIPAddr();
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
+ o.placeholder = '64';
+ o.datatype = 'range(1,255)';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
+ o.placeholder = '1280';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js
new file mode 100644
index 0000000000..eba58f4248
--- /dev/null
+++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dhcpv6.js
@@ -0,0 +1,58 @@
+'use strict';
+'require form';
+'require network';
+
+return network.registerProtocol('dhcpv6', {
+ getI18n: function() {
+ return _('DHCPv6 client');
+ },
+
+ getOpkgPackage: function() {
+ return 'odhcp6c';
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL2Device() || this.getDevice(), o;
+
+ o = s.taboption('general', form.ListValue, 'reqaddress', _('Request IPv6-address'));
+ o.value('try');
+ o.value('force');
+ o.value('none', 'disabled');
+ o.default = 'try';
+
+ o = s.taboption('general', form.Value, 'reqprefix', _('Request IPv6-prefix of length'));
+ o.value('auto', _('Automatic'));
+ o.value('no', _('disabled'));
+ o.value('48');
+ o.value('52');
+ o.value('56');
+ o.value('60');
+ o.value('64');
+ o.default = 'auto';
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'ip6prefix', _('Custom delegated IPv6-prefix'));
+ o.datatype = 'cidr6';
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ o.cast = 'string';
+
+ o = s.taboption('advanced', form.Value, 'clientid', _('Client ID to send when requesting DHCP'));
+ o.datatype = 'hexstring';
+
+ o = s.taboption('advanced', form.Value, 'macaddr', _('Override MAC address'));
+ o.datatype = 'macaddr';
+ o.placeholder = dev ? (dev.getMAC() || '') : '';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js
new file mode 100644
index 0000000000..fa0e68ddc3
--- /dev/null
+++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js
@@ -0,0 +1,79 @@
+'use strict';
+'require form';
+'require network';
+'require tools.widgets as widgets';
+
+network.registerPatternVirtual(/^ds-.+$/);
+network.registerErrorCode('AFTR_DNS_FAIL', _('Unable to resolve AFTR host name'));
+
+return network.registerProtocol('dslite', {
+ getI18n: function() {
+ return _('Dual-Stack Lite (RFC6333)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'ds-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'ds-lite';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'peeraddr', _('DS-Lite AFTR address'));
+ o.rmempty = false;
+ o.datatype = 'or(hostname,ip6addr("nomask"))';
+
+ o = s.taboption('general', form.Value, 'ip6addr', _('Local IPv6 address'), _('Leave empty to use the current WAN address'));
+ o.datatype = 'ip6addr("nomask")';
+ o.load = function(section_id) {
+ return network.getWAN6Networks().then(L.bind(function(nets) {
+ if (Array.isArray(nets) && nets.length)
+ this.placeholder = nets[0].getIP6Addr();
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ o = s.taboption('advanced', widgets.NetworkSelect, 'tunlink', _('Tunnel Link'));
+ o.nocreate = true;
+ o.exclude = s.section;
+
+ o = s.taboption('advanced', form.ListValue, 'encaplimit', _('Encapsulation limit'));
+ o.rmempty = false;
+ o.default = 'ignore';
+ o.datatype = 'or("ignore",range(0,255))';
+ o.value('ignore', _('ignore'));
+ for (var i = 0; i < 256; i++)
+ o.value(i);
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
+ o.placeholder = '1280';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js
new file mode 100644
index 0000000000..006ebfbf08
--- /dev/null
+++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js
@@ -0,0 +1,96 @@
+'use strict';
+'require form';
+'require network';
+'require tools.widgets as widgets';
+
+network.registerPatternVirtual(/^map-.+$/);
+network.registerErrorCode('INVALID_MAP_RULE', _('MAP rule is invalid'));
+network.registerErrorCode('NO_MATCHING_PD', _('No matching prefix delegation'));
+network.registerErrorCode('UNSUPPORTED_TYPE', _('Unsupported MAP type'));
+
+return network.registerProtocol('map', {
+ getI18n: function() {
+ return _('MAP / LW4over6');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'map-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'map-t';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.ListValue, 'type', _('Type'));
+ o.value('map-e', 'MAP-E');
+ o.value('map-t', 'MAP-T');
+ o.value('lw4o6', 'LW4over6');
+
+ o = s.taboption('general', form.Value, 'peeraddr', _('BR / DMR / AFTR'));
+ o.rmempty = false;
+ o.datatype = 'ip6addr';
+
+ o = s.taboption('general', form.Value, 'ipaddr', _('IPv4 prefix'));
+ o.datatype = 'ip4addr';
+
+ o = s.taboption('general', form.Value, 'ip4prefixlen', _('IPv4 prefix length'), _('The length of the IPv4 prefix in bits, the remainder is used in the IPv6 addresses.'));
+ o.placeholder = '32';
+ o.datatype = 'range(0,32)';
+
+ o = s.taboption('general', form.Value, 'ip6prefix', _('IPv6 prefix'), _('The IPv6 prefix assigned to the provider, usually ends with <code>::</code>'));
+ o.rmempty = false;
+ o.datatype = 'ip6addr';
+
+ o = s.taboption('general', form.Value, 'ip6prefixlen', _('IPv6 prefix length'), _('The length of the IPv6 prefix in bits'));
+ o.placeholder = '16';
+ o.datatype = 'range(0,64)';
+
+ o = s.taboption('general', form.Value, 'ealen', _('EA-bits length'));
+ o.datatype = 'range(0,48)';
+
+ o = s.taboption('general', form.Value, 'psidlen', _('PSID-bits length'));
+ o.datatype = 'range(0,16)';
+
+ o = s.taboption('general', form.Value, 'offset', _('PSID offset'));
+ o.datatype = 'range(0,16)';
+
+ o = s.taboption('advanced', widgets.NetworkSelect, 'tunlink', _('Tunnel Link'));
+ o.nocreate = true;
+ o.exclude = s.section;
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
+ o.placeholder = '64';
+ o.datatype = 'range(1,255)';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
+ o.placeholder = '1280';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_464xlat.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_464xlat.lua
deleted file mode 100644
index 5a37582faf..0000000000
--- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_464xlat.lua
+++ /dev/null
@@ -1,33 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Copyright 2013 Steven Barth <steven@midlink.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-local tunlink, defaultroute, metric, mtu
-
-section:taboption("general", Value, "ip6prefix",
- translate("NAT64 Prefix"), translate("Leave empty to autodetect"))
-
-tunlink = section:taboption("advanced", DynamicList, "tunlink", translate("Tunnel Link"))
-tunlink.template = "cbi/network_netlist"
-tunlink.nocreate = true
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Use MTU on tunnel interface"))
-mtu.placeholder = "1280"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua
deleted file mode 100644
index 3c9f41f6b5..0000000000
--- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua
+++ /dev/null
@@ -1,102 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local ipaddr, peeraddr, ip6addr, tunnelid, username, password
-local defaultroute, metric, ttl, mtu
-
-
-ipaddr = s:taboption("general", Value, "ipaddr",
- translate("Local IPv4 address"),
- translate("Leave empty to use the current WAN address"))
-
-ipaddr.datatype = "ip4addr"
-
-
-peeraddr = s:taboption("general", Value, "peeraddr",
- translate("Remote IPv4 address"),
- translate("This is usually the address of the nearest PoP operated by the tunnel broker"))
-
-peeraddr.rmempty = false
-peeraddr.datatype = "ip4addr"
-
-
-ip6addr = s:taboption("general", Value, "ip6addr",
- translate("Local IPv6 address"),
- translate("This is the local endpoint address assigned by the tunnel broker, it usually ends with <code>...:2/64</code>"))
-
-ip6addr.datatype = "ip6addr"
-
-
-local ip6prefix = s:taboption("general", Value, "ip6prefix",
- translate("IPv6 routed prefix"),
- translate("This is the prefix routed to you by the tunnel broker for use by clients"))
-
-ip6prefix.datatype = "list(ip6addr)"
-
-
-local update = section:taboption("general", Flag, "_update",
- translate("Dynamic tunnel"),
- translate("Enable HE.net dynamic endpoint update"))
-
-update.enabled = "1"
-update.disabled = "0"
-
-function update.write() end
-function update.remove() end
-function update.cfgvalue(self, section)
- return (tonumber(m:get(section, "tunnelid")) ~= nil)
- and self.enabled or self.disabled
-end
-
-
-tunnelid = section:taboption("general", Value, "tunnelid", translate("Tunnel ID"))
-tunnelid.datatype = "uinteger"
-tunnelid:depends("_update", update.enabled)
-
-
-username = section:taboption("general", Value, "username",
- translate("HE.net username"),
- translate("This is the plain username for logging into the account"))
-
-username:depends("_update", update.enabled)
-username.validate = function(self, val, sid)
- if type(val) == "string" and #val == 32 and val:match("^[a-fA-F0-9]+$") then
- return nil, translate("The HE.net endpoint update configuration changed, you must now use the plain username instead of the user ID!")
- end
- return val
-end
-
-
-password = section:taboption("general", Value, "password",
- translate("HE.net password"),
- translate("This is either the \"Update Key\" configured for the tunnel or the account password if no update key has been configured"))
-
-password.password = true
-password:depends("_update", update.enabled)
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-ttl = section:taboption("advanced", Value, "ttl", translate("Use TTL on tunnel interface"))
-ttl.placeholder = "64"
-ttl.datatype = "range(1,255)"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Use MTU on tunnel interface"))
-mtu.placeholder = "1280"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6rd.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6rd.lua
deleted file mode 100644
index 708a9c5add..0000000000
--- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6rd.lua
+++ /dev/null
@@ -1,72 +0,0 @@
--- Copyright 2011-2012 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local ipaddr, peeraddr, ip6addr, tunnelid, username, password
-local defaultroute, metric, ttl, mtu
-
-
-ipaddr = s:taboption("general", Value, "ipaddr",
- translate("Local IPv4 address"),
- translate("Leave empty to use the current WAN address"))
-
-ipaddr.datatype = "ip4addr"
-
-
-peeraddr = s:taboption("general", Value, "peeraddr",
- translate("Remote IPv4 address"),
- translate("This IPv4 address of the relay"))
-
-peeraddr.rmempty = false
-peeraddr.datatype = "ip4addr"
-
-
-ip6addr = s:taboption("general", Value, "ip6prefix",
- translate("IPv6 prefix"),
- translate("The IPv6 prefix assigned to the provider, usually ends with <code>::</code>"))
-
-ip6addr.rmempty = false
-ip6addr.datatype = "ip6addr"
-
-
-ip6prefixlen = s:taboption("general", Value, "ip6prefixlen",
- translate("IPv6 prefix length"),
- translate("The length of the IPv6 prefix in bits"))
-
-ip6prefixlen.placeholder = "16"
-ip6prefixlen.datatype = "range(0,128)"
-
-
-ip6prefixlen = s:taboption("general", Value, "ip4prefixlen",
- translate("IPv4 prefix length"),
- translate("The length of the IPv4 prefix in bits, the remainder is used in the IPv6 addresses."))
-
-ip6prefixlen.placeholder = "0"
-ip6prefixlen.datatype = "range(0,32)"
-
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-ttl = section:taboption("advanced", Value, "ttl", translate("Use TTL on tunnel interface"))
-ttl.placeholder = "64"
-ttl.datatype = "range(1,255)"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Use MTU on tunnel interface"))
-mtu.placeholder = "1280"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6to4.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6to4.lua
deleted file mode 100644
index 50a706974d..0000000000
--- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6to4.lua
+++ /dev/null
@@ -1,37 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local ipaddr, defaultroute, metric, ttl, mtu
-
-
-ipaddr = section:taboption("general", Value, "ipaddr",
- translate("Local IPv4 address"),
- translate("Leave empty to use the current WAN address"))
-
-ipaddr.datatype = "ip4addr"
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-ttl = section:taboption("advanced", Value, "ttl", translate("Use TTL on tunnel interface"))
-ttl.placeholder = "64"
-ttl.datatype = "range(1,255)"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Use MTU on tunnel interface"))
-mtu.placeholder = "1280"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dhcpv6.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dhcpv6.lua
deleted file mode 100644
index 49281ee41d..0000000000
--- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dhcpv6.lua
+++ /dev/null
@@ -1,58 +0,0 @@
--- Copyright 2013 Steven Barth <steven@midlink.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-
-local o = section:taboption("general", ListValue, "reqaddress",
- translate("Request IPv6-address"))
-o:value("try")
-o:value("force")
-o:value("none", "disabled")
-o.default = "try"
-
-
-o = section:taboption("general", Value, "reqprefix",
- translate("Request IPv6-prefix of length"))
-o:value("auto", translate("Automatic"))
-o:value("no", translate("disabled"))
-o:value("48")
-o:value("52")
-o:value("56")
-o:value("60")
-o:value("64")
-o.default = "auto"
-
-
-o = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-o.default = o.enabled
-
-
-o = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-o.default = o.enabled
-
-
-o = section:taboption("advanced", Value, "ip6prefix",
- translate("Custom delegated IPv6-prefix"))
-o.dataype = "list(ip6addr)"
-
-
-o = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-o:depends("peerdns", "")
-o.datatype = "list(ip6addr)"
-o.cast = "string"
-
-
-o = section:taboption("advanced", Value, "clientid",
- translate("Client ID to send when requesting DHCP"))
-
-luci.tools.proto.opt_macaddr(section, ifc, translate("Override MAC address"))
-
-o = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-o.placeholder = "1500"
-o.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dslite.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dslite.lua
deleted file mode 100644
index eca9750adb..0000000000
--- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_dslite.lua
+++ /dev/null
@@ -1,53 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Copyright 2013 Steven Barth <steven@midlink.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local peeraddr, ip6addr
-local tunlink, defaultroute, metric, ttl, mtu
-
-
-
-
-peeraddr = section:taboption("general", Value, "peeraddr",
- translate("DS-Lite AFTR address"))
-
-peeraddr.rmempty = false
-peeraddr.datatype = "or(hostname,ip6addr)"
-
-ip6addr = section:taboption("general", Value, "ip6addr",
- translate("Local IPv6 address"),
- translate("Leave empty to use the current WAN address"))
-
-ip6addr.datatype = "ip6addr"
-
-
-tunlink = section:taboption("advanced", DynamicList, "tunlink", translate("Tunnel Link"))
-tunlink.template = "cbi/network_netlist"
-tunlink.nocreate = true
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-ttl = section:taboption("advanced", Value, "ttl", translate("Use TTL on tunnel interface"))
-ttl.placeholder = "64"
-ttl.datatype = "range(1,255)"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Use MTU on tunnel interface"))
-mtu.placeholder = "1280"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_map.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_map.lua
deleted file mode 100644
index 37d4ec901a..0000000000
--- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_map.lua
+++ /dev/null
@@ -1,88 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Copyright 2013 Steven Barth <steven@midlink.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local peeraddr, ip6addr
-local tunlink, defaultroute, metric, ttl, mtu
-
-
-maptype = section:taboption("general", ListValue, "type", translate("Type"))
-maptype:value("map-e", "MAP-E")
-maptype:value("map-t", "MAP-T")
-maptype:value("lw4o6", "LW4over6")
-
-
-peeraddr = section:taboption("general", Value, "peeraddr",
- translate("BR / DMR / AFTR"))
-
-peeraddr.rmempty = false
-peeraddr.datatype = "ip6addr"
-
-
-ipaddr = section:taboption("general", Value, "ipaddr",
- translate("IPv4 prefix"))
-ipaddr.datatype = "ip4addr"
-
-
-ip4prefixlen = s:taboption("general", Value, "ip4prefixlen",
- translate("IPv4 prefix length"),
- translate("The length of the IPv4 prefix in bits, the remainder is used in the IPv6 addresses."))
-
-ip4prefixlen.placeholder = "32"
-ip4prefixlen.datatype = "range(0,32)"
-
-ip6addr = s:taboption("general", Value, "ip6prefix",
- translate("IPv6 prefix"),
- translate("The IPv6 prefix assigned to the provider, usually ends with <code>::</code>"))
-
-ip6addr.rmempty = false
-ip6addr.datatype = "ip6addr"
-
-
-ip6prefixlen = s:taboption("general", Value, "ip6prefixlen",
- translate("IPv6 prefix length"),
- translate("The length of the IPv6 prefix in bits"))
-
-ip6prefixlen.placeholder = "16"
-ip6prefixlen.datatype = "range(0,64)"
-
-
-s:taboption("general", Value, "ealen",
- translate("EA-bits length")).datatype = "range(0,48)"
-
-s:taboption("general", Value, "psidlen",
- translate("PSID-bits length")).datatype = "range(0,16)"
-
-s:taboption("general", Value, "offset",
- translate("PSID offset")).datatype = "range(0,16)"
-
-tunlink = section:taboption("advanced", DynamicList, "tunlink", translate("Tunnel Link"))
-tunlink.template = "cbi/network_netlist"
-tunlink.nocreate = true
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-ttl = section:taboption("advanced", Value, "ttl", translate("Use TTL on tunnel interface"))
-ttl.placeholder = "64"
-ttl.datatype = "range(1,255)"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Use MTU on tunnel interface"))
-mtu.placeholder = "1280"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ipv6/luasrc/model/network/proto_4x6.lua b/protocols/luci-proto-ipv6/luasrc/model/network/proto_4x6.lua
index 7508e0d4b0..0b329d8a92 100644
--- a/protocols/luci-proto-ipv6/luasrc/model/network/proto_4x6.lua
+++ b/protocols/luci-proto-ipv6/luasrc/model/network/proto_4x6.lua
@@ -49,7 +49,7 @@ for _, p in ipairs({"dslite", "map", "464xlat"}) do
return nil
end
- function proto.contains_interface(self, ifname)
+ function proto.contains_interface(self, ifc)
return (netmod:ifnameof(ifc) == self:ifname())
end
end
diff --git a/protocols/luci-proto-ipv6/luasrc/model/network/proto_6x4.lua b/protocols/luci-proto-ipv6/luasrc/model/network/proto_6x4.lua
index 9a4396c5be..2fd0b11957 100644
--- a/protocols/luci-proto-ipv6/luasrc/model/network/proto_6x4.lua
+++ b/protocols/luci-proto-ipv6/luasrc/model/network/proto_6x4.lua
@@ -42,7 +42,7 @@ for _, p in ipairs({"6in4", "6to4", "6rd"}) do
return nil
end
- function proto.contains_interface(self, ifname)
+ function proto.contains_interface(self, ifc)
return (netmod:ifnameof(ifc) == self:ifname())
end
diff --git a/protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js b/protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js
new file mode 100644
index 0000000000..3ab6c01d61
--- /dev/null
+++ b/protocols/luci-proto-ncm/htdocs/luci-static/resources/protocol/ncm.js
@@ -0,0 +1,123 @@
+'use strict';
+'require rpc';
+'require form';
+'require network';
+
+var callFileList = rpc.declare({
+ object: 'file',
+ method: 'list',
+ params: [ 'path' ],
+ expect: { entries: [] },
+ filter: function(list, params) {
+ var rv = [];
+ for (var i = 0; i < list.length; i++)
+ if (list[i].name.match(/^ttyUSB/) || list[i].name.match(/^cdc-wdm/))
+ rv.push(params.path + list[i].name);
+ return rv.sort();
+ }
+});
+
+network.registerPatternVirtual(/^ncm-.+$/);
+network.registerErrorCode('CONFIGURE_FAILED', _('Configuration failed'));
+network.registerErrorCode('DISCONNECT_FAILED', _('Disconnection attempt failed'));
+network.registerErrorCode('FINALIZE_FAILED', _('Finalizing failed'));
+network.registerErrorCode('GETINFO_FAILED', _('Modem information query failed'));
+network.registerErrorCode('INITIALIZE_FAILED', _('Initialization failure'));
+network.registerErrorCode('SETMODE_FAILED', _('Setting operation mode failed'));
+network.registerErrorCode('UNSUPPORTED_MODEM', _('Unsupported modem'));
+
+return network.registerProtocol('ncm', {
+ getI18n: function() {
+ return _('NCM');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'wan';
+ },
+
+ getOpkgPackage: function() {
+ return 'comgt-ncm';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'device', _('Modem device'));
+ o.rmempty = false;
+ o.load = function(section_id) {
+ return callFileList('/dev/').then(L.bind(function(devices) {
+ for (var i = 0; i < devices.length; i++)
+ this.value(devices[i]);
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ o = s.taboption('general', form.Value, 'service', _('Service Type'));
+ o.value('', _('Modem default'));
+ o.value('preferlte', _('Prefer LTE'));
+ o.value('preferumts', _('Prefer UMTS'));
+ o.value('lte', 'LTE');
+ o.value('umts', 'UMTS/GPRS');
+ o.value('gsm', _('GPRS only'));
+ o.value('auto', _('auto'));
+
+ o = s.taboption('general', form.ListValue, 'pdptype', _('IP Protocol'));
+ o.default = 'IP';
+ o.value('IP', _('IPv4'));
+ o.value('IPV4V6', _('IPv4+IPv6'));
+ o.value('IPV6', _('IPv6'));
+
+ s.taboption('general', form.Value, 'apn', _('APN'));
+ s.taboption('general', form.Value, 'pincode', _('PIN'));
+ s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.password = true;
+
+ o = s.taboption('general', form.Value, 'dialnumber', _('Dial number'));
+ o.placeholder = '*99***1#';
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'));
+ o.value('auto', _('Automatic'));
+ o.value('0', _('Disabled'));
+ o.value('1', _('Manual'));
+ o.default = 'auto';
+ }
+
+ o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready'));
+ o.placeholder = '10';
+ o.datatype = 'min(1)';
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ }
+});
diff --git a/protocols/luci-proto-ncm/luasrc/model/cbi/admin_network/proto_ncm.lua b/protocols/luci-proto-ncm/luasrc/model/cbi/admin_network/proto_ncm.lua
deleted file mode 100644
index 3fe4ef33aa..0000000000
--- a/protocols/luci-proto-ncm/luasrc/model/cbi/admin_network/proto_ncm.lua
+++ /dev/null
@@ -1,110 +0,0 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2015 Cezary Jackiewicz <cezary.jackiewicz@gmail.com>
-
-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
-]]--
-
-local map, section, net = ...
-
-local device, apn, service, pincode, username, password, dialnum
-local ipv6, delay, defaultroute, metric, peerdns, dns
-
-
-device = section:taboption("general", Value, "device", translate("Modem device"))
-device.rmempty = false
-
-local dev
-for dev in nixio.fs.glob("/dev/ttyUSB*") do
- device:value(dev)
-end
-for dev in nixio.fs.glob("/dev/cdc-wdm*") do
- device:value(dev)
-end
-
-mode = section:taboption("general", Value, "mode", translate("Service Type"))
-mode:value("", translate("Modem default"))
-mode:value("preferlte", translate("Prefer LTE"))
-mode:value("preferumts", translate("Prefer UMTS"))
-mode:value("lte", "LTE")
-mode:value("umts", "UMTS/GPRS")
-mode:value("gsm", translate("GPRS only"))
-mode:value("auto", translate("auto"))
-
-
-mode = section:taboption("general", Value, "pdptype", translate("IP Protocol"))
-mode.default = "IP"
-mode:value("IP", translate("IPv4"))
-mode:value("IPV4V6", translate("IPv4+IPv6"))
-mode:value("IPV6", translate("IPv6"))
-
-
-apn = section:taboption("general", Value, "apn", translate("APN"))
-
-
-pincode = section:taboption("general", Value, "pincode", translate("PIN"))
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password.password = true
-
-
-dialnum = section:taboption("general", Value, "dialnum", translate("Dial number"))
-dialnum.placeholder = "*99#"
-
-
-if luci.model.network:has_ipv6() then
-
- ipv6 = section:taboption("advanced", ListValue, "ipv6")
- ipv6:value("auto", translate("Automatic"))
- ipv6:value("0", translate("Disabled"))
- ipv6:value("1", translate("Manual"))
- ipv6.default = "auto"
-
-end
-
-
-delay = section:taboption("advanced", Value, "delay",
- translate("Modem init timeout"),
- translate("Maximum amount of seconds to wait for the modem to become ready"))
-
-delay.placeholder = "10"
-delay.datatype = "min(1)"
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
diff --git a/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js b/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js
new file mode 100644
index 0000000000..14fc8f6d35
--- /dev/null
+++ b/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js
@@ -0,0 +1,159 @@
+'use strict';
+'require rpc';
+'require form';
+'require network';
+
+var callGetCertificateFiles = rpc.declare({
+ object: 'luci.openconnect',
+ method: 'getCertificates',
+ params: [ 'interface' ],
+ expect: { '': {} }
+});
+
+var callSetCertificateFiles = rpc.declare({
+ object: 'luci.openconnect',
+ method: 'setCertificates',
+ params: [ 'interface', 'user_certificate', 'user_privatekey', 'ca_certificate' ],
+ expect: { '': {} }
+});
+
+network.registerPatternVirtual(/^vpn-.+$/);
+
+function sanitizeCert(s) {
+ if (typeof(s) != 'string')
+ return null;
+
+ s = s.trim();
+
+ if (s == '')
+ return null;
+
+ s = s.replace(/\r\n?/g, '\n');
+
+ if (!s.match(/\n$/))
+ s += '\n';
+
+ return s;
+}
+
+function validateCert(priv, section_id, value) {
+ var beg = priv ? /^-----BEGIN RSA PRIVATE KEY-----$/ : /^-----BEGIN CERTIFICATE-----$/,
+ end = priv ? /^-----END RSA PRIVATE KEY-----$/ : /^-----END CERTIFICATE-----$/,
+ lines = value.trim().split(/[\r\n]/),
+ start = false,
+ i;
+
+ for (i = 0; i < lines.length; i++) {
+ if (lines[i].match(beg))
+ start = true;
+ else if (start && !lines[i].match(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/))
+ break;
+ }
+
+ if (!start || i < lines.length - 1 || !lines[i].match(end))
+ return _('This does not look like a valid PEM file');
+
+ return true;
+}
+
+return network.registerProtocol('openconnect', {
+ getI18n: function() {
+ return _('OpenConnect (CISCO AnyConnect)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'vpn-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'openconnect';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getDevice().getName(),
+ certLoadPromise = null,
+ o;
+
+ o = s.taboption('general', form.Value, 'server', _('VPN Server'));
+ o.datatype = 'host(0)';
+
+ o = s.taboption('general', form.Value, 'port', _('VPN Server port'));
+ o.placeholder = '443';
+ o.datatype = 'port';
+
+ s.taboption('general', form.Value, 'serverhash', _("VPN Server's certificate SHA1 hash"));
+ s.taboption('general', form.Value, 'authgroup', _('Auth Group'));
+ s.taboption("general", form.Value, "username", _("Username"));
+
+ o = s.taboption('general', form.Value, 'password', _('Password'));
+ o.password = true;
+
+ o = s.taboption('general', form.Value, 'password2', _('Password2'));
+ o.password = true;
+
+ o = s.taboption('general', form.TextValue, 'usercert', _('User certificate (PEM encoded)'));
+ o.rows = 10;
+ o.monospace = true;
+ o.validate = L.bind(validateCert, o, false);
+ o.load = function(section_id) {
+ certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
+ return certLoadPromise.then(function(certs) { return certs.user_certificate });
+ };
+ o.write = function(section_id, value) {
+ return callSetCertificateFiles(section_id, sanitizeCert(value), null, null);
+ };
+
+ o = s.taboption('general', form.TextValue, 'userkey', _('User key (PEM encoded)'));
+ o.rows = 10;
+ o.monospace = true;
+ o.validate = L.bind(validateCert, o, true);
+ o.load = function(section_id) {
+ certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
+ return certLoadPromise.then(function(certs) { return certs.user_privatekey });
+ };
+ o.write = function(section_id, value) {
+ return callSetCertificateFiles(section_id, null, sanitizeCert(value), null);
+ };
+
+ o = s.taboption('general', form.TextValue, 'ca', _('CA certificate; if empty it will be saved after the first connection.'));
+ o.rows = 10;
+ o.monospace = true;
+ o.validate = L.bind(validateCert, o, false);
+ o.load = function(section_id) {
+ certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
+ return certLoadPromise.then(function(certs) { return certs.ca_certificate });
+ };
+ o.write = function(section_id, value) {
+ return callSetCertificateFiles(section_id, null, null, sanitizeCert(value));
+ };
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.depends('defaultroute', '1');
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.optional = true;
+ o.placeholder = 1406;
+ o.datatype = 'range(68, 9200)';
+ }
+});
diff --git a/protocols/luci-proto-openconnect/luasrc/model/cbi/admin_network/proto_openconnect.lua b/protocols/luci-proto-openconnect/luasrc/model/cbi/admin_network/proto_openconnect.lua
deleted file mode 100644
index 5adfccae48..0000000000
--- a/protocols/luci-proto-openconnect/luasrc/model/cbi/admin_network/proto_openconnect.lua
+++ /dev/null
@@ -1,90 +0,0 @@
--- Copyright 2014 Nikos Mavrogiannopoulos <nmav@gnutls.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local server, username, password, cert, ca
-local oc_cert_file, oc_key_file, oc_ca_file
-
-local ifc = net:get_interface():name()
-
-oc_cert_file = "/etc/openconnect/user-cert-" .. ifc .. ".pem"
-oc_key_file = "/etc/openconnect/user-key-" .. ifc .. ".pem"
-oc_ca_file = "/etc/openconnect/ca-" .. ifc .. ".pem"
-
-server = section:taboption("general", Value, "server", translate("VPN Server"))
-server.datatype = "host(0)"
-
-port = section:taboption("general", Value, "port", translate("VPN Server port"))
-port.placeholder = "443"
-port.datatype = "port"
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-section:taboption("general", Value, "serverhash", translate("VPN Server's certificate SHA1 hash"))
-
-section:taboption("general", Value, "authgroup", translate("Auth Group"))
-
-username = section:taboption("general", Value, "username", translate("Username"))
-password = section:taboption("general", Value, "password", translate("Password"))
-password.password = true
-password2 = section:taboption("general", Value, "password2", translate("Password2"))
-password2.password = true
-
-
-cert = section:taboption("advanced", Value, "usercert", translate("User certificate (PEM encoded)"))
-cert.template = "cbi/tvalue"
-cert.rows = 10
-
-function cert.cfgvalue(self, section)
- return nixio.fs.readfile(oc_cert_file)
-end
-
-function cert.write(self, section, value)
- value = value:gsub("\r\n?", "\n")
- nixio.fs.writefile(oc_cert_file, value)
-end
-
-cert = section:taboption("advanced", Value, "userkey", translate("User key (PEM encoded)"))
-cert.template = "cbi/tvalue"
-cert.rows = 10
-
-function cert.cfgvalue(self, section)
- return nixio.fs.readfile(oc_key_file)
-end
-
-function cert.write(self, section, value)
- value = value:gsub("\r\n?", "\n")
- nixio.fs.writefile(oc_key_file, value)
-end
-
-
-ca = section:taboption("advanced", Value, "ca", translate("CA certificate; if empty it will be saved after the first connection."))
-ca.template = "cbi/tvalue"
-ca.rows = 10
-
-function ca.cfgvalue(self, section)
- return nixio.fs.readfile(oc_ca_file)
-end
-
-function ca.write(self, section, value)
- value = value:gsub("\r\n?", "\n")
- nixio.fs.writefile(oc_ca_file, value)
-end
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-mtu.placeholder = "1406"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect b/protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect
new file mode 100755
index 0000000000..9378cc518b
--- /dev/null
+++ b/protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect
@@ -0,0 +1,78 @@
+#!/usr/bin/env lua
+
+local json = require "luci.jsonc"
+local fs = require "nixio.fs"
+
+local function readfile(path)
+ local s = fs.readfile(path)
+ return s and (s:gsub("^%s+", ""):gsub("%s+$", ""))
+end
+
+local function writefile(path, data)
+ local n = fs.writefile(path, data)
+ return (n == #data)
+end
+
+local function parseInput()
+ local parse = json.new()
+ local done, err
+
+ while true do
+ local chunk = io.read(4096)
+ if not chunk then
+ break
+ elseif not done and not err then
+ done, err = parse:parse(chunk)
+ end
+ end
+
+ if not done then
+ print(json.stringify({ error = err or "Incomplete input" }))
+ os.exit(1)
+ end
+
+ return parse:get()
+end
+
+if arg[1] == "list" then
+ print(json.stringify({
+ getCertificates = {
+ interface = "interface"
+ },
+ setCertificates = {
+ interface = "interface",
+ user_certificate = "PEM file data",
+ user_privatekey = "PEM file data",
+ ca_certificate = "PEM file data"
+ }
+ }))
+elseif arg[1] == "call" then
+ local args = parseInput()
+
+ if not args.interface or
+ type(args.interface) ~= "string" or
+ not args.interface:match("^[a-zA-Z0-9_]+$")
+ then
+ print(json.stringify({ error = "Invalid interface name" }))
+ os.exit(1)
+ end
+
+ if arg[2] == "getCertificates" then
+ print(json.stringify({
+ user_certificate = readfile(string.format("/etc/openconnect/user-cert-%s.pem", args.interface)),
+ user_privatekey = readfile(string.format("/etc/openconnect/user-key-%s.pem", args.interface)),
+ ca_certificate = readfile(string.format("/etc/openconnect/ca-%s.pem", args.interface))
+ }))
+ elseif arg[2] == "setCertificates" then
+ if args.user_certificate then
+ writefile(string.format("/etc/openconnect/user-cert-%s.pem", args.interface), args.user_certificate)
+ end
+ if args.user_privatekey then
+ writefile(string.format("/etc/openconnect/user-key-%s.pem", args.interface), args.user_privatekey)
+ end
+ if args.ca_certificate then
+ writefile(string.format("/etc/openconnect/ca-%s.pem", args.interface), args.ca_certificate)
+ end
+ print(json.stringify({ result = true }))
+ end
+end
diff --git a/protocols/luci-proto-openconnect/root/usr/share/rpcd/acl.d/luci-openconnect.json b/protocols/luci-proto-openconnect/root/usr/share/rpcd/acl.d/luci-openconnect.json
new file mode 100644
index 0000000000..66bc5ac24f
--- /dev/null
+++ b/protocols/luci-proto-openconnect/root/usr/share/rpcd/acl.d/luci-openconnect.json
@@ -0,0 +1,17 @@
+{
+ "luci-proto-openconnect": {
+ "description": "Grant access to LuCI OpenConnect procedures",
+ "read": {
+ "ubus": {
+ "luci.openconnect": [ "getCertificates" ]
+ },
+ "uci": [ "network" ]
+ },
+ "write": {
+ "ubus": {
+ "luci.openconnect": [ "setCertificates" ]
+ },
+ "uci": [ "network" ]
+ }
+ }
+}
diff --git a/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js
new file mode 100644
index 0000000000..13bb3548a7
--- /dev/null
+++ b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/l2tp.js
@@ -0,0 +1,75 @@
+'use strict';
+'require uci';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^l2tp-.+$/);
+
+return network.registerProtocol('l2tp', {
+ getI18n: function() {
+ return _('L2TP');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'l2tp-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'xl2tpd';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL3Device() || this.getDevice(), o;
+
+ o = s.taboption('general', form.Value, 'server', _('L2TP Server'));
+ o.datatype = 'or(host(1), hostport(1))';
+
+ s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.password = true;
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
+ o.value('auto', _('Automatic'));
+ o.value('0', _('Disabled'));
+ o.value('1', _('Manual'));
+ o.default = 'auto';
+ }
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ o.cast = 'string';
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js
new file mode 100644
index 0000000000..57a7b6a0e1
--- /dev/null
+++ b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/ppp.js
@@ -0,0 +1,149 @@
+'use strict';
+'require rpc';
+'require uci';
+'require form';
+'require network';
+
+var callFileList = rpc.declare({
+ object: 'file',
+ method: 'list',
+ params: [ 'path' ],
+ expect: { entries: [] },
+ filter: function(list, params) {
+ var rv = [];
+ for (var i = 0; i < list.length; i++)
+ if (list[i].name.match(/^tty[A-Z]/) || list[i].name.match(/^cdc-wdm/) || list[i].name.match(/^[0-9]+$/))
+ rv.push(params.path + list[i].name);
+ return rv.sort();
+ }
+});
+
+network.registerPatternVirtual(/^ppp-.+$/);
+
+function write_keepalive(section_id, value) {
+ var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
+ i_opt = this.map.lookupOption('_keepalive_interval', section_id),
+ f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
+ i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
+
+ if (f == null || f == '' || isNaN(f))
+ f = 0;
+
+ if (i == null || i == '' || isNaN(i) || i < 1)
+ i = 1;
+
+ if (f > 0)
+ uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
+ else
+ uci.unset('network', section_id, 'keepalive');
+}
+
+return network.registerProtocol('ppp', {
+ getI18n: function() {
+ return _('PPP');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'ppp-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'ppp';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL3Device() || this.getDevice(), o;
+
+ o = s.taboption('general', form.Value, 'device', _('Modem device'));
+ o.rmempty = false;
+ o.load = function(section_id) {
+ return callFileList('/dev/').then(L.bind(function(devices) {
+ for (var i = 0; i < devices.length; i++)
+ this.value(devices[i]);
+ return callFileList('/dev/tts/');
+ }, this)).then(L.bind(function(devices) {
+ for (var i = 0; i < devices.length; i++)
+ this.value(devices[i]);
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.password = true;
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
+ o.value('auto', _('Automatic'));
+ o.value('0', _('Disabled'));
+ o.value('1', _('Manual'));
+ o.default = 'auto';
+ }
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ o.cast = 'string';
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^(\d+)[ ,]\d+$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
+ o.placeholder = '5';
+ o.datatype = 'min(1)';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^\d+[ ,](\d+)$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js
new file mode 100644
index 0000000000..483ac9e555
--- /dev/null
+++ b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoa.js
@@ -0,0 +1,136 @@
+'use strict';
+'require uci';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^pppoa-.+$/);
+
+function write_keepalive(section_id, value) {
+ var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
+ i_opt = this.map.lookupOption('_keepalive_interval', section_id),
+ f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
+ i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
+
+ if (f == null || f == '' || isNaN(f))
+ f = 0;
+
+ if (i == null || i == '' || isNaN(i) || i < 1)
+ i = 1;
+
+ if (f > 0)
+ uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
+ else
+ uci.unset('network', section_id, 'keepalive');
+}
+
+return network.registerProtocol('pppoa', {
+ getI18n: function() {
+ return _('PPPoATM');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'pppoa-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'ppp-mod-pppoa';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL3Device() || this.getDevice(), o;
+
+ o = s.taboption('general', form.ListValue, 'encaps', _('PPPoA Encapsulation'));
+ o.value('vc', 'VC-Mux');
+ o.value('llc', 'LLC');
+
+ o = s.taboption('general', form.Value, 'atmdev', _('ATM device number'));
+ o.default = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('general', form.Value, 'vci', _('ATM Virtual Channel Identifier (VCI)'));
+ o.default = '35';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('general', form.Value, 'vpi', _('ATM Virtual Path Identifier (VPI)'));
+ o.default = '8';
+ o.datatype = 'uinteger';
+
+ s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.password = true;
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
+ o.value('auto', _('Automatic'));
+ o.value('0', _('Disabled'));
+ o.value('1', _('Manual'));
+ o.default = 'auto';
+ }
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ o.cast = 'string';
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^(\d+)[ ,]\d+$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
+ o.placeholder = '5';
+ o.datatype = 'min(1)';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^\d+[ ,](\d+)$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js
new file mode 100644
index 0000000000..5d71c43376
--- /dev/null
+++ b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pppoe.js
@@ -0,0 +1,114 @@
+'use strict';
+'require uci';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^pppoe-.+$/);
+
+function write_keepalive(section_id, value) {
+ var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
+ i_opt = this.map.lookupOption('_keepalive_interval', section_id),
+ f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
+ i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
+
+ if (f == null || f == '' || isNaN(f))
+ f = 0;
+
+ if (i == null || i == '' || isNaN(i) || i < 1)
+ i = 1;
+
+ if (f > 0)
+ uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
+ else
+ uci.unset('network', section_id, 'keepalive');
+}
+
+return network.registerProtocol('pppoe', {
+ getI18n: function() {
+ return _('PPPoE');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'pppoe-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'ppp-mod-pppoe';
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL3Device() || this.getDevice(), o;
+
+ s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.password = true;
+
+ o = s.taboption('general', form.Value, 'ac', _('Access Concentrator'), _('Leave empty to autodetect'));
+ o.placeholder = _('auto');
+
+ o = s.taboption('general', form.Value, 'service', _('Service Name'), _('Leave empty to autodetect'));
+ o.placeholder = _('auto');
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
+ o.value('auto', _('Automatic'));
+ o.value('0', _('Disabled'));
+ o.value('1', _('Manual'));
+ o.default = 'auto';
+ }
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ o.cast = 'string';
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^(\d+)[ ,]\d+$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
+ o.placeholder = '5';
+ o.datatype = 'min(1)';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^\d+[ ,](\d+)$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, 'host_uniq', _('Host-Uniq tag content'), _('Raw hex-encoded bytes. Leave empty unless your ISP require this'));
+ o.placeholder = _('auto');
+ o.datatype = 'hexstring';
+
+ o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js
new file mode 100644
index 0000000000..006adc1a1e
--- /dev/null
+++ b/protocols/luci-proto-ppp/htdocs/luci-static/resources/protocol/pptp.js
@@ -0,0 +1,123 @@
+'use strict';
+'require uci';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^pptp-.+$/);
+
+function write_keepalive(section_id, value) {
+ var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
+ i_opt = this.map.lookupOption('_keepalive_interval', section_id),
+ f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
+ i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
+
+ if (f == null || f == '' || isNaN(f))
+ f = 0;
+
+ if (i == null || i == '' || isNaN(i) || i < 1)
+ i = 1;
+
+ if (f > 0)
+ uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
+ else
+ uci.unset('network', section_id, 'keepalive');
+}
+
+return network.registerProtocol('pptp', {
+ getI18n: function() {
+ return _('PPtP');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'pptp-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'ppp-mod-pptp';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL3Device() || this.getDevice(), o;
+
+ o = s.taboption('general', form.Value, 'server', _('VPN Server'));
+ o.datatype = 'host(0)';
+
+ s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.password = true;
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
+ o.value('auto', _('Automatic'));
+ o.value('0', _('Disabled'));
+ o.value('1', _('Manual'));
+ o.default = 'auto';
+ }
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ o.cast = 'string';
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^(\d+)[ ,]\d+$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
+ o.placeholder = '5';
+ o.datatype = 'min(1)';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^\d+[ ,](\d+)$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_l2tp.lua b/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_l2tp.lua
deleted file mode 100644
index 604f019ee6..0000000000
--- a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_l2tp.lua
+++ /dev/null
@@ -1,61 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local server, username, password
-local ipv6, defaultroute, metric, peerdns, dns, mtu
-
-
-server = section:taboption("general", Value, "server", translate("L2TP Server"))
-server.datatype = "or(host(1), hostport(1))"
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password.password = true
-
-if luci.model.network:has_ipv6() then
- ipv6 = section:taboption("advanced", ListValue, "ipv6",
- translate("Obtain IPv6-Address"),
- translate("Enable IPv6 negotiation on the PPP link"))
- ipv6:value("auto", translate("Automatic"))
- ipv6:value("0", translate("Disabled"))
- ipv6:value("1", translate("Manual"))
- ipv6.default = "auto"
-end
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-mtu.placeholder = "1500"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_ppp.lua b/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_ppp.lua
deleted file mode 100644
index 5f468bc14c..0000000000
--- a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_ppp.lua
+++ /dev/null
@@ -1,127 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local device, username, password
-local ipv6, defaultroute, metric, peerdns, dns,
- keepalive_failure, keepalive_interval, demand, mtu
-
-
-device = section:taboption("general", Value, "device", translate("Modem device"))
-device.rmempty = false
-
-local device_suggestions = nixio.fs.glob("/dev/tty*S*")
- or nixio.fs.glob("/dev/tts/*")
-
-if device_suggestions then
- local node
- for node in device_suggestions do
- device:value(node)
- end
-end
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password.password = true
-
-
-if luci.model.network:has_ipv6() then
- ipv6 = section:taboption("advanced", ListValue, "ipv6",
- translate("Obtain IPv6-Address"),
- translate("Enable IPv6 negotiation on the PPP link"))
- ipv6:value("auto", translate("Automatic"))
- ipv6:value("0", translate("Disabled"))
- ipv6:value("1", translate("Manual"))
- ipv6.default = "auto"
-end
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
-
-keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure",
- translate("LCP echo failure threshold"),
- translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures"))
-
-function keepalive_failure.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^(%d+)[ ,]+%d+") or v)
- end
-end
-
-keepalive_failure.placeholder = "0"
-keepalive_failure.datatype = "uinteger"
-
-
-keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval",
- translate("LCP echo interval"),
- translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold"))
-
-function keepalive_interval.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^%d+[ ,]+(%d+)"))
- end
-end
-
-function keepalive_interval.write(self, section, value)
- local f = tonumber(keepalive_failure:formvalue(section)) or 0
- local i = tonumber(value) or 5
- if i < 1 then i = 1 end
- if f > 0 then
- m:set(section, "keepalive", "%d %d" %{ f, i })
- else
- m:set(section, "keepalive", "0")
- end
-end
-
-keepalive_interval.remove = keepalive_interval.write
-keepalive_failure.write = keepalive_interval.write
-keepalive_failure.remove = keepalive_interval.write
-keepalive_interval.placeholder = "5"
-keepalive_interval.datatype = "min(1)"
-
-
-demand = section:taboption("advanced", Value, "demand",
- translate("Inactivity timeout"),
- translate("Close inactive connection after the given amount of seconds, use 0 to persist connection"))
-
-demand.placeholder = "0"
-demand.datatype = "uinteger"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-mtu.placeholder = "1500"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoa.lua b/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoa.lua
deleted file mode 100644
index 004fd7ef67..0000000000
--- a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoa.lua
+++ /dev/null
@@ -1,133 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local encaps, atmdev, vci, vpi, username, password
-local ipv6, defaultroute, metric, peerdns, dns,
- keepalive_failure, keepalive_interval, demand, mtu
-
-
-encaps = section:taboption("general", ListValue, "encaps", translate("PPPoA Encapsulation"))
-encaps:value("vc", "VC-Mux")
-encaps:value("llc", "LLC")
-
-
-atmdev = section:taboption("general", Value, "atmdev", translate("ATM device number"))
-atmdev.default = "0"
-atmdev.datatype = "uinteger"
-
-
-vci = section:taboption("general", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
-vci.default = "35"
-vci.datatype = "uinteger"
-
-
-vpi = section:taboption("general", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
-vpi.default = "8"
-vpi.datatype = "uinteger"
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password.password = true
-
-
-if luci.model.network:has_ipv6() then
- ipv6 = section:taboption("advanced", ListValue, "ipv6",
- translate("Obtain IPv6-Address"),
- translate("Enable IPv6 negotiation on the PPP link"))
- ipv6:value("auto", translate("Automatic"))
- ipv6:value("0", translate("Disabled"))
- ipv6:value("1", translate("Manual"))
- ipv6.default = "auto"
-end
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
-
-keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure",
- translate("LCP echo failure threshold"),
- translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures"))
-
-function keepalive_failure.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^(%d+)[ ,]+%d+") or v)
- end
-end
-
-keepalive_failure.placeholder = "0"
-keepalive_failure.datatype = "uinteger"
-
-
-keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval",
- translate("LCP echo interval"),
- translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold"))
-
-function keepalive_interval.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^%d+[ ,]+(%d+)"))
- end
-end
-
-function keepalive_interval.write(self, section, value)
- local f = tonumber(keepalive_failure:formvalue(section)) or 0
- local i = tonumber(value) or 5
- if i < 1 then i = 1 end
- if f > 0 then
- m:set(section, "keepalive", "%d %d" %{ f, i })
- else
- m:set(section, "keepalive", "0")
- end
-end
-
-keepalive_interval.remove = keepalive_interval.write
-keepalive_failure.write = keepalive_interval.write
-keepalive_failure.remove = keepalive_interval.write
-keepalive_interval.placeholder = "5"
-keepalive_interval.datatype = "min(1)"
-
-
-demand = section:taboption("advanced", Value, "demand",
- translate("Inactivity timeout"),
- translate("Close inactive connection after the given amount of seconds, use 0 to persist connection"))
-
-demand.placeholder = "0"
-demand.datatype = "uinteger"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-mtu.placeholder = "1500"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoe.lua b/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoe.lua
deleted file mode 100644
index 063d8c07eb..0000000000
--- a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pppoe.lua
+++ /dev/null
@@ -1,135 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local username, password, ac, service
-local ipv6, defaultroute, metric, peerdns, dns,
- keepalive_failure, keepalive_interval, demand, mtu
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password.password = true
-
-
-ac = section:taboption("general", Value, "ac",
- translate("Access Concentrator"),
- translate("Leave empty to autodetect"))
-
-ac.placeholder = translate("auto")
-
-
-service = section:taboption("general", Value, "service",
- translate("Service Name"),
- translate("Leave empty to autodetect"))
-
-service.placeholder = translate("auto")
-
-
-if luci.model.network:has_ipv6() then
- ipv6 = section:taboption("advanced", ListValue, "ipv6",
- translate("Obtain IPv6-Address"),
- translate("Enable IPv6 negotiation on the PPP link"))
- ipv6:value("auto", translate("Automatic"))
- ipv6:value("0", translate("Disabled"))
- ipv6:value("1", translate("Manual"))
- ipv6.default = "auto"
-end
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
-
-keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure",
- translate("LCP echo failure threshold"),
- translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures"))
-
-function keepalive_failure.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^(%d+)[ ,]+%d+") or v)
- end
-end
-
-keepalive_failure.placeholder = "0"
-keepalive_failure.datatype = "uinteger"
-
-
-keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval",
- translate("LCP echo interval"),
- translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold"))
-
-function keepalive_interval.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^%d+[ ,]+(%d+)"))
- end
-end
-
-function keepalive_interval.write(self, section, value)
- local f = tonumber(keepalive_failure:formvalue(section)) or 0
- local i = tonumber(value) or 5
- if i < 1 then i = 1 end
- if f > 0 then
- m:set(section, "keepalive", "%d %d" %{ f, i })
- else
- m:set(section, "keepalive", "0")
- end
-end
-
-keepalive_interval.remove = keepalive_interval.write
-keepalive_failure.write = keepalive_interval.write
-keepalive_failure.remove = keepalive_interval.write
-keepalive_interval.placeholder = "5"
-keepalive_interval.datatype = "min(1)"
-
-
-host_uniq = section:taboption("advanced", Value, "host_uniq",
- translate("Host-Uniq tag content"),
- translate("Raw hex-encoded bytes. Leave empty unless your ISP require this"))
-
-host_uniq.placeholder = translate("auto")
-host_uniq.datatype = "hexstring"
-
-
-demand = section:taboption("advanced", Value, "demand",
- translate("Inactivity timeout"),
- translate("Close inactive connection after the given amount of seconds, use 0 to persist connection"))
-
-demand.placeholder = "0"
-demand.datatype = "uinteger"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-mtu.placeholder = "1500"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pptp.lua b/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pptp.lua
deleted file mode 100644
index 6a828efe96..0000000000
--- a/protocols/luci-proto-ppp/luasrc/model/cbi/admin_network/proto_pptp.lua
+++ /dev/null
@@ -1,106 +0,0 @@
--- Copyright 2011-2012 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local server, username, password
-local defaultroute, metric, peerdns, dns,
- keepalive_failure, keepalive_interval, demand, mtu
-
-
-server = section:taboption("general", Value, "server", translate("VPN Server"))
-server.datatype = "host(0)"
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password.password = true
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
-
-keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure",
- translate("LCP echo failure threshold"),
- translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures"))
-
-function keepalive_failure.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^(%d+)[ ,]+%d+") or v)
- end
-end
-
-keepalive_failure.placeholder = "0"
-keepalive_failure.datatype = "uinteger"
-
-
-keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval",
- translate("LCP echo interval"),
- translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold"))
-
-function keepalive_interval.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^%d+[ ,]+(%d+)"))
- end
-end
-
-function keepalive_interval.write(self, section, value)
- local f = tonumber(keepalive_failure:formvalue(section)) or 0
- local i = tonumber(value) or 5
- if i < 1 then i = 1 end
- if f > 0 then
- m:set(section, "keepalive", "%d %d" %{ f, i })
- else
- m:set(section, "keepalive", "0")
- end
-end
-
-keepalive_interval.remove = keepalive_interval.write
-keepalive_failure.write = keepalive_interval.write
-keepalive_failure.remove = keepalive_interval.write
-keepalive_interval.placeholder = "5"
-keepalive_interval.datatype = "min(1)"
-
-
-demand = section:taboption("advanced", Value, "demand",
- translate("Inactivity timeout"),
- translate("Close inactive connection after the given amount of seconds, use 0 to persist connection"))
-
-demand.placeholder = "0"
-demand.datatype = "uinteger"
-
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-mtu.placeholder = "1500"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js b/protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js
new file mode 100644
index 0000000000..ec8e8a152e
--- /dev/null
+++ b/protocols/luci-proto-pppossh/htdocs/luci-static/resources/protocol/pppossh.js
@@ -0,0 +1,142 @@
+'use strict';
+'require uci';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^pppossh-.+$/);
+
+function write_keepalive(section_id, value) {
+ var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
+ i_opt = this.map.lookupOption('_keepalive_interval', section_id),
+ f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
+ i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
+
+ if (f == null || f == '' || isNaN(f))
+ f = 0;
+
+ if (i == null || i == '' || isNaN(i) || i < 1)
+ i = 1;
+
+ if (f > 0)
+ uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
+ else
+ uci.unset('network', section_id, 'keepalive');
+}
+
+return network.registerProtocol('pppossh', {
+ getI18n: function() {
+ return _('PPPoSSH');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'pppossh-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'pppossh';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'sshuser', _('SSH username'));
+ o.rmempty = false;
+ o.validate = function(section_id, value) {
+ var id_opt = this.section.children.filter(function(o) { return o.option == 'identity' })[0];
+ if (id_opt && value.length) {
+ var input = this.map.findElement('id', id_opt.cbid(section_id)).querySelector('input[type="text"]');
+ if (input)
+ input.placeholder = (value == 'root' ? '/root' : '/home/' + value) + '/.ssh/id_rsa';
+ }
+ return true;
+ };
+
+ o = s.taboption('general', form.Value, 'server', _('SSH server address'));
+ o.datatype = 'host(0)';
+ o.rmempty = false;
+
+ o = s.taboption('general', form.Value, 'port', _('SSH server port'));
+ o.datatype = 'port';
+ o.optional = true;
+ o.placeholder = 22;
+
+ o = s.taboption('general', form.Value, 'ssh_options', _('Extra SSH command options'));
+ o.optional = true;
+
+ o = s.taboption('general', form.DynamicList, 'identity', _('List of SSH key files for auth'));
+ o.optional = true;
+ o.datatype = 'file';
+
+ o = s.taboption('general', form.Value, 'ipaddr', _('Local IP address to assign'));
+ o.datatype = 'ipaddr("nomask")';
+
+ o = s.taboption('general', form.Value, 'peeraddr', _('Peer IP address to assign'));
+ o.datatype = 'ipaddr("nomask")';
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.Flag, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
+ o.default = o.disabled;
+ }
+
+ o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
+ o.depends('peerdns', '0');
+ o.datatype = 'ipaddr';
+ o.cast = 'string';
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+
+ o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^(\d+)[ ,]\d+$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
+ o.placeholder = '5';
+ o.datatype = 'min(1)';
+ o.write = write_keepalive;
+ o.remove = write_keepalive;
+ o.cfgvalue = function(section_id) {
+ var v = uci.get('network', section_id, 'keepalive');
+ if (typeof(v) == 'string' && v != '') {
+ var m = v.match(/^\d+[ ,](\d+)$/);
+ return m ? m[1] : v;
+ }
+ };
+
+ o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
+ o.placeholder = '0';
+ o.datatype = 'uinteger';
+ }
+});
diff --git a/protocols/luci-proto-pppossh/luasrc/model/cbi/admin_network/proto_pppossh.lua b/protocols/luci-proto-pppossh/luasrc/model/cbi/admin_network/proto_pppossh.lua
deleted file mode 100644
index e53262b5dc..0000000000
--- a/protocols/luci-proto-pppossh/luasrc/model/cbi/admin_network/proto_pppossh.lua
+++ /dev/null
@@ -1,122 +0,0 @@
--- Copyright (C) 2015 Yousong Zhou <yszhou4tech@gmail.com>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local sshuser, server, port, ssh_options, identity, ipaddr, peeraddr
-
-sshuser = section:taboption("general", Value, "sshuser", translate("SSH username"))
-
-server = section:taboption("general", Value, "server", translate("SSH server address"))
-server.datatype = "host(0)"
-
-port = section:taboption("general", Value, "port", translate("SSH server port"))
-port.datatype = "port"
-port.optional = true
-port.default = 22
-
-ssh_options = section:taboption("general", Value, "ssh_options", translate("Extra SSH command options"))
-ssh_options.optional = true
-
-identity = section:taboption("general", DynamicList, "identity", translate("List of SSH key files for auth"))
-identity.optional = true
-identity.datatype = "file"
-
-ipaddr = section:taboption("general", Value, "ipaddr", translate("Local IP address to assign"))
-ipaddr.datatype = "ipaddr"
-
-peeraddr = section:taboption("general", Value, "peeraddr", translate("Peer IP address to assign"))
-peeraddr.datatype = "ipaddr"
-
-
-local ipv6, defaultroute, metric, peerdns, dns,
- keepalive_failure, keepalive_interval, demand
-
-if luci.model.network:has_ipv6() then
- ipv6 = section:taboption("advanced", Flag, "ipv6",
- translate("Enable IPv6 negotiation on the PPP link"))
- ipv6.default = ipv6.disabled
-end
-
-
-defaultroute = section:taboption("advanced", Flag, "defaultroute",
- translate("Use default gateway"),
- translate("If unchecked, no default route is configured"))
-
-defaultroute.default = defaultroute.enabled
-
-
-metric = section:taboption("advanced", Value, "metric",
- translate("Use gateway metric"))
-
-metric.placeholder = "0"
-metric.datatype = "uinteger"
-metric:depends("defaultroute", defaultroute.enabled)
-
-
-peerdns = section:taboption("advanced", Flag, "peerdns",
- translate("Use DNS servers advertised by peer"),
- translate("If unchecked, the advertised DNS server addresses are ignored"))
-
-peerdns.default = peerdns.enabled
-
-
-dns = section:taboption("advanced", DynamicList, "dns",
- translate("Use custom DNS servers"))
-
-dns:depends("peerdns", "")
-dns.datatype = "ipaddr"
-dns.cast = "string"
-
-
-keepalive_failure = section:taboption("advanced", Value, "_keepalive_failure",
- translate("LCP echo failure threshold"),
- translate("Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures"))
-
-function keepalive_failure.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^(%d+)[ ,]+%d+") or v)
- end
-end
-
-function keepalive_failure.write() end
-function keepalive_failure.remove() end
-
-keepalive_failure.placeholder = "0"
-keepalive_failure.datatype = "uinteger"
-
-
-keepalive_interval = section:taboption("advanced", Value, "_keepalive_interval",
- translate("LCP echo interval"),
- translate("Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold"))
-
-function keepalive_interval.cfgvalue(self, section)
- local v = m:get(section, "keepalive")
- if v and #v > 0 then
- return tonumber(v:match("^%d+[ ,]+(%d+)"))
- end
-end
-
-function keepalive_interval.write(self, section, value)
- local f = tonumber(keepalive_failure:formvalue(section)) or 0
- local i = tonumber(value) or 5
- if i < 1 then i = 1 end
- if f > 0 then
- m:set(section, "keepalive", "%d %d" %{ f, i })
- else
- m:set(section, "keepalive", "0")
- end
-end
-
-keepalive_interval.remove = keepalive_interval.write
-keepalive_interval.placeholder = "5"
-keepalive_interval.datatype = "min(1)"
-
-
-demand = section:taboption("advanced", Value, "demand",
- translate("Inactivity timeout"),
- translate("Close inactive connection after the given amount of seconds, use 0 to persist connection"))
-
-demand.placeholder = "0"
-demand.datatype = "uinteger"
diff --git a/protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js b/protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js
new file mode 100644
index 0000000000..eeda91f6e6
--- /dev/null
+++ b/protocols/luci-proto-qmi/htdocs/luci-static/resources/protocol/qmi.js
@@ -0,0 +1,101 @@
+'use strict';
+'require rpc';
+'require form';
+'require network';
+
+var callFileList = rpc.declare({
+ object: 'file',
+ method: 'list',
+ params: [ 'path' ],
+ expect: { entries: [] },
+ filter: function(list, params) {
+ var rv = [];
+ for (var i = 0; i < list.length; i++)
+ if (list[i].name.match(/^cdc-wdm/))
+ rv.push(params.path + list[i].name);
+ return rv.sort();
+ }
+});
+
+network.registerPatternVirtual(/^qmi-.+$/);
+network.registerErrorCode('CALL_FAILED', _('Call failed'));
+network.registerErrorCode('NO_CID', _('Unable to obtain client ID'));
+network.registerErrorCode('PLMN_FAILED', _('Setting PLMN failed'));
+
+return network.registerProtocol('qmi', {
+ getI18n: function() {
+ return _('QMI Cellular');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'qmi-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'uqmi';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var dev = this.getL3Device() || this.getDevice(), o;
+
+ o = s.taboption('general', form.Value, 'device', _('Modem device'));
+ o.rmempty = false;
+ o.load = function(section_id) {
+ return callFileList('/dev/').then(L.bind(function(devices) {
+ for (var i = 0; i < devices.length; i++)
+ this.value(devices[i]);
+ return form.Value.prototype.load.apply(this, [section_id]);
+ }, this));
+ };
+
+ s.taboption('general', form.Value, 'apn', _('APN'));
+ s.taboption('general', form.Value, 'pincode', _('PIN'));
+
+ o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type'));
+ o.value('both', 'PAP/CHAP (both)');
+ o.value('pap', 'PAP');
+ o.value('chap', 'CHAP');
+ o.value('none', 'NONE');
+ o.default = 'none';
+
+ o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
+ o.depends('auth', 'pap');
+ o.depends('auth', 'chap');
+ o.depends('auth', 'both');
+
+ o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
+ o.depends('auth', 'pap');
+ o.depends('auth', 'chap');
+ o.depends('auth', 'both');
+ o.password = true;
+
+ if (L.hasSystemFeature('ipv6')) {
+ o = s.taboption('advanced', form.Flag, 'ipv6', _('Enable IPv6 negotiation'));
+ o.default = o.disabled;
+ }
+
+ o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready'));
+ o.placeholder = '10';
+ o.datatype = 'min(1)';
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
+ o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
+ o.datatype = 'max(9200)';
+ }
+});
diff --git a/protocols/luci-proto-qmi/luasrc/model/cbi/admin_network/proto_qmi.lua b/protocols/luci-proto-qmi/luasrc/model/cbi/admin_network/proto_qmi.lua
deleted file mode 100644
index 383bc4662f..0000000000
--- a/protocols/luci-proto-qmi/luasrc/model/cbi/admin_network/proto_qmi.lua
+++ /dev/null
@@ -1,63 +0,0 @@
--- Copyright 2016 David Thornley <david.thornley@touchstargroup.com>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local device, apn, pincode, username, password
-local auth, ipv6, delay, mtu
-
-
-device = section:taboption("general", Value, "device", translate("Modem device"))
-device.rmempty = false
-
-local device_suggestions = nixio.fs.glob("/dev/cdc-wdm*")
-
-if device_suggestions then
- local node
- for node in device_suggestions do
- device:value(node)
- end
-end
-
-
-apn = section:taboption("general", Value, "apn", translate("APN"))
-
-
-pincode = section:taboption("general", Value, "pincode", translate("PIN"))
-
-
-auth = section:taboption("general", Value, "auth", translate("Authentication Type"))
-auth:value("both", "PAP/CHAP (both)")
-auth:value("pap", "PAP")
-auth:value("chap", "CHAP")
-auth:value("none", "NONE")
-auth.default = "none"
-
-
-username = section:taboption("general", Value, "username", translate("PAP/CHAP username"))
-username:depends("auth", "pap")
-username:depends("auth", "chap")
-username:depends("auth", "both")
-
-
-password = section:taboption("general", Value, "password", translate("PAP/CHAP password"))
-password:depends("auth", "pap")
-password:depends("auth", "chap")
-password:depends("auth", "both")
-password.password = true
-
-
-if luci.model.network:has_ipv6() then
- ipv6 = section:taboption("advanced", Flag, "ipv6", translate("Enable IPv6 negotiation"))
- ipv6.default = ipv6.disabled
-end
-
-delay = section:taboption("advanced", Value, "delay",
- translate("Modem init timeout"),
- translate("Maximum amount of seconds to wait for the modem to become ready"))
-delay.placeholder = "10"
-delay.datatype = "min(1)"
-
-mtu = section:taboption("advanced", Value, "mtu", translate("Override MTU"))
-mtu.placeholder = "1500"
-mtu.datatype = "max(9200)"
diff --git a/protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js b/protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js
new file mode 100644
index 0000000000..b3082276b1
--- /dev/null
+++ b/protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js
@@ -0,0 +1,183 @@
+'use strict';
+'require uci';
+'require form';
+'require network';
+'require tools.widgets as widgets';
+
+network.registerPatternVirtual(/^relay-.+$/);
+
+var RelayDevicePrototype = {
+ __init__: function(ifname, network) {
+ this.ifname = ifname;
+ this.network = network;
+ },
+
+ _aggregateDevices: function(fn, first) {
+ var devices = this.network ? this.network.getDevices() : [],
+ rv = 0;
+
+ for (var i = 0; i < devices.length; i++) {
+ var v = devices[i][fn].apply(devices[i]);
+
+ if (v != null) {
+ if (first)
+ return v;
+
+ rv += v;
+ }
+ }
+
+ return first ? null : [ rv, devices.length ];
+ },
+
+ getPorts: function() { return this.network ? this.network.getDevices() : [] },
+
+ getType: function() { return 'tunnel' },
+ getTypeI18n: function() { return _('Relay Bridge') },
+
+ getShortName: function() {
+ return '%s "%h"'.format(_('Relay'), this.ifname);
+ },
+
+ isUp: function() {
+ var res = this._aggregateDevices('isUp');
+ return (res[1] > 0 && res[0] == res[1]);
+ },
+
+ getTXBytes: function() { return this._aggregateDevices('getTXBytes')[0] },
+ getRXBytes: function() { return this._aggregateDevices('getRXBytes')[0] },
+ getTXPackets: function() { return this._aggregateDevices('getTXPackets')[0] },
+ getRXPackets: function() { return this._aggregateDevices('getRXPackets')[0] },
+
+ getMAC: function() { return this._aggregateDevices('getMAC', true) },
+
+ getIPAddrs: function() {
+ var ipaddr = this.network ? L.toArray(uci.get('network', this.network.getName(), 'ipaddr'))[0] : null;
+ return (ipaddr != null ? [ ipaddr ] : []);
+ },
+
+ getIP6Addrs: function() { return [] }
+};
+
+return network.registerProtocol('relay', {
+ getI18n: function() {
+ return _('Relay bridge');
+ },
+
+ getIfname: function() {
+ return 'relay-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'relayd';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ isUp: function() {
+ var dev = this.getDevice();
+ return (dev ? dev.isUp() : false);
+ },
+
+ getDevice: function() {
+ return network.instantiateDevice(this.sid, this, RelayDevicePrototype);
+ },
+
+ getDevices: function() {
+ if (this.devices)
+ return this.devices;
+
+ var networkNames = L.toArray(uci.get('network', this.sid, 'network')),
+ deviceNames = L.toArray(uci.get('network', this.sid, 'ifname')),
+ devices = {},
+ rv = [];
+
+ for (var i = 0; i < networkNames.length; i++) {
+ var net = network.instantiateNetwork(networkNames[i]),
+ dev = net ? net.getDevice() : null;
+
+ if (dev)
+ devices[dev.getName()] = dev;
+ }
+
+ for (var i = 0; i < deviceNames.length; i++) {
+ var dev = network.getDevice(deviceNames[i]);
+
+ if (dev)
+ devices[dev.getName()] = dev;
+ }
+
+ deviceNames = Object.keys(devices);
+ deviceNames.sort();
+
+ for (var i = 0; i < deviceNames.length; i++)
+ rv.push(devices[deviceNames[i]]);
+
+ this.devices = rv;
+
+ return rv;
+ },
+
+ getUptime: function() {
+ var networkNames = L.toArray(uci.get('network', this.sid, 'network')),
+ uptime = 0;
+
+ for (var i = 0; i < networkNames.length; i++) {
+ var net = network.instantiateNetwork(networkNames[i]);
+ if (net)
+ uptime = Math.max(uptime, net.getUptime());
+ }
+
+ return uptime;
+ },
+
+ getErrors: function() {
+ return null;
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Address to access local relay bridge'));
+ o.datatype = 'ip4addr("nomask")';
+
+ o = s.taboption('general', widgets.NetworkSelect, 'network', _('Relay between networks'));
+ o.exclude = s.section;
+ o.multiple = true;
+ o.nocreate = true;
+ o.nobridges = true;
+ o.novirtual = true;
+
+ o = s.taboption('advanced', form.Flag, 'forward_bcast', _('Forward broadcast traffic'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Flag, 'forward_dhcp', _('Forward DHCP traffic'));
+ o.default = o.enabled;
+
+ o = s.taboption('advanced', form.Value, 'gateway', _('Use DHCP gateway'), _('Override the gateway in DHCP responses'));
+ o.datatype = 'ip4addr("nomask")';
+ o.depends('forward_dhcp', '1');
+
+ o = s.taboption('advanced', form.Value, 'expiry', _('Host expiry timeout'), _('Specifies the maximum amount of seconds after which hosts are presumed to be dead'));
+ o.placeholder = '30';
+ o.datatype = 'min(1)';
+
+ o = s.taboption('advanced', form.Value, 'retry', _('ARP retry threshold'), _('Specifies the maximum amount of failed ARP requests until hosts are presumed to be dead'));
+ o.placeholder = '5';
+ o.datatype = 'min(1)';
+
+ o = s.taboption('advanced', form.Value, 'table', _('Use routing table'), _('Override the table used for internal routes'));
+ o.placeholder = '16800';
+ o.datatype = 'range(0,65535)';
+ }
+});
diff --git a/protocols/luci-proto-relay/luasrc/model/cbi/admin_network/proto_relay.lua b/protocols/luci-proto-relay/luasrc/model/cbi/admin_network/proto_relay.lua
deleted file mode 100644
index 3381d85e47..0000000000
--- a/protocols/luci-proto-relay/luasrc/model/cbi/admin_network/proto_relay.lua
+++ /dev/null
@@ -1,68 +0,0 @@
--- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local ipaddr, network
-local forward_bcast, forward_dhcp, gateway, expiry, retry, table
-
-
-ipaddr = section:taboption("general", Value, "ipaddr",
- translate("Local IPv4 address"),
- translate("Address to access local relay bridge"))
-
-ipaddr.datatype = "ip4addr"
-
-
-network = s:taboption("general", DynamicList, "network", translate("Relay between networks"))
-network.widget = "checkbox"
-network.exclude = arg[1]
-network.template = "cbi/network_netlist"
-network.nocreate = true
-network.nobridges = true
-network.novirtual = true
-network:depends("proto", "relay")
-
-
-forward_bcast = section:taboption("advanced", Flag, "forward_bcast",
- translate("Forward broadcast traffic"))
-
-forward_bcast.default = forward_bcast.enabled
-
-
-forward_dhcp = section:taboption("advanced", Flag, "forward_dhcp",
- translate("Forward DHCP traffic"))
-
-forward_dhcp.default = forward_dhcp.enabled
-
-
-gateway = section:taboption("advanced", Value, "gateway",
- translate("Use DHCP gateway"),
- translate("Override the gateway in DHCP responses"))
-
-gateway.datatype = "ip4addr"
-gateway:depends("forward_dhcp", forward_dhcp.enabled)
-
-
-expiry = section:taboption("advanced", Value, "expiry",
- translate("Host expiry timeout"),
- translate("Specifies the maximum amount of seconds after which hosts are presumed to be dead"))
-
-expiry.placeholder = "30"
-expiry.datatype = "min(1)"
-
-
-retry = section:taboption("advanced", Value, "retry",
- translate("ARP retry threshold"),
- translate("Specifies the maximum amount of failed ARP requests until hosts are presumed to be dead"))
-
-retry.placeholder = "5"
-retry.datatype = "min(1)"
-
-
-table = section:taboption("advanced", Value, "table",
- translate("Use routing table"),
- translate("Override the table used for internal routes"))
-
-table.placeholder = "16800"
-table.datatype = "range(0,65535)"
diff --git a/protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js b/protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js
new file mode 100644
index 0000000000..87ccc9df1c
--- /dev/null
+++ b/protocols/luci-proto-vpnc/htdocs/luci-static/resources/protocol/vpnc.js
@@ -0,0 +1,111 @@
+'use strict';
+'require form';
+'require network';
+
+network.registerPatternVirtual(/^vpn-.+$/);
+
+return network.registerProtocol('vpnc', {
+ getI18n: function() {
+ return _('VPNC (CISCO 3000 (and others) VPN)');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || 'vpn-%s'.format(this.sid);
+ },
+
+ getOpkgPackage: function() {
+ return 'vpnc';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o;
+
+ o = s.taboption('general', form.Value, 'server', _('VPN Server'));
+ o.datatype = 'host(0)';
+
+ o = s.taboption('general', form.Value, 'local_addr', _('VPN Local address'));
+ o.placeholder = '0.0.0.0';
+ o.datatype = 'ipaddr';
+
+ o = s.taboption('general', form.Value, 'local_port', _('VPN Local port'));
+ o.placeholder = '500';
+ o.datatype = 'port';
+
+ o = s.taboption('general', form.Value, 'interface', _('Output Interface'));
+ o.template = 'cbi/network_netlist';
+
+ o = s.taboption('general', form.Value, 'mtu', _('MTU'));
+ o.datatype = 'uinteger';
+
+ s.taboption('general', form.Value, 'username', _('Username'));
+
+ o = s.taboption('general', form.Value, 'password', _('Password'));
+ o.password = true;
+
+ o = s.taboption('general', form.Value, 'hexpassword', _('Obfuscated Password'));
+ o.password = true;
+
+ s.taboption('general', form.Value, 'authgroup', _('Auth Group'));
+
+ o = s.taboption('general', form.Value, 'passgroup', _('Group Password'));
+ o.password = true;
+
+ o = s.taboption('general', form.Value, 'hexpassgroup', _('Obfuscated Group Password'));
+ o.password= true;
+
+ s.taboption('general', form.Value, 'domain', _('NT Domain'));
+ s.taboption('general', form.Value, 'vendor', _('Vendor'));
+
+ o = s.taboption('general', form.ListValue, 'dh_group', _('IKE DH Group'));
+ o.value('dh2');
+ o.value('dh1');
+ o.value('dh5');
+
+ o = s.taboption('general', form.ListValue, 'pfs', _('Perfect Forward Secrecy'));
+ o.value('server');
+ o.value('nopfs');
+ o.value('dh1');
+ o.value('dh2');
+ o.value('dh5');
+
+ o = s.taboption('general', form.ListValue, 'natt_mode', _('NAT-T Mode'));
+ o.value('natt', _('RFC3947 NAT-T mode'));
+ o.value('none', _('No NAT-T'));
+ o.value('force-natt', _('Force use of NAT-T'));
+ o.value('cisco-udp', _('Cisco UDP encapsulation'));
+
+ o = s.taboption('general', form.Flag, 'enable_no_enc', _('Disable Encryption'), _('If checked, encryption is disabled'));
+ o.default = o.disabled;
+
+ o = s.taboption('general', form.Flag, 'enable_single_des', _('Enable Single DES'), _('If checked, 1DES is enabled'));
+ o.default = o.disabled;
+
+ o = s.taboption('general', form.Value, 'dpd_idle', _('DPD Idle Timeout'));
+ o.datatype = 'uinteger';
+ o.placeholder = '600';
+
+ o = s.taboption('general', form.Value, 'target_network', _('Target network'));
+ o.placeholder = '0.0.0.0/0';
+ o.datatype = 'network';
+
+ o = s.taboption('general', form.ListValue, 'defaultroute', _('Default Route'), _('Set VPN as Default Route'));
+ o.value('0', _('No'));
+ o.value('1', _('Yes'));
+ }
+});
diff --git a/protocols/luci-proto-vpnc/luasrc/model/cbi/admin_network/proto_vpnc.lua b/protocols/luci-proto-vpnc/luasrc/model/cbi/admin_network/proto_vpnc.lua
deleted file mode 100644
index 3d85d02f40..0000000000
--- a/protocols/luci-proto-vpnc/luasrc/model/cbi/admin_network/proto_vpnc.lua
+++ /dev/null
@@ -1,85 +0,0 @@
--- Copyright 2015 Daniel Dickinson <openwrt@daniel.thecshore.com>
--- Licensed to the public under the Apache License 2.0.
-
-local map, section, net = ...
-
-local server, username, password, hexpassword
-local authgroup, interface, passgroup, hexpassgroup
-local domain, vendor, natt_mode, dh_group
-local pfs, enable_single_des, enable_no_enc
-local mtu, local_addr, local_port, dpd_idle
-local auth_mode, target_network, defaultroute
-
-local ifc = net:get_interface():name()
-
-server = section:taboption("general", Value, "server", translate("VPN Server"))
-server.datatype = "host(0)"
-
-port = section:taboption("general", Value, "local_addr", translate("VPN Local address"))
-port.placeholder = "0.0.0.0"
-port.datatype = "ipaddr"
-
-port = section:taboption("general", Value, "local_port", translate("VPN Local port"))
-port.placeholder = "500"
-port.datatype = "port"
-
-ifname = section:taboption("general", Value, "interface", translate("Output Interface"))
-ifname.template = "cbi/network_netlist"
-
-mtu = section:taboption("general", Value, "mtu", translate("MTU"))
-mtu.datatype = "uinteger"
-
-username = section:taboption("general", Value, "username", translate("Username"))
-password = section:taboption("general", Value, "password", translate("Password"))
-password.password = true
-hexpassword = section:taboption("general", Value, "hexpassword", translate("Obfuscated Password"))
-hexpassword.password = true
-authroup = section:taboption("general", Value, "authgroup", translate("Auth Group"))
-passgroup = section:taboption("general", Value, "passgroup", translate("Group Password"))
-passgroup.password = true
-hexpassgroup = section:taboption("general", Value, "hexpassgroup", translate("Obfuscated Group Password"))
-hexpassword.password= true
-
-domain = section:taboption("general", Value, "domain", translate("NT Domain"))
-vendor = section:taboption("general", Value, "vendor", translate("Vendor"))
-dh_group = section:taboption("general", ListValue, "dh_group", translate("IKE DH Group"))
-dh_group:value("dh2")
-dh_group:value("dh1")
-dh_group:value("dh5")
-
-pfs = section:taboption("general", ListValue, "pfs", translate("Perfect Forward Secrecy"))
-pfs:value("server")
-pfs:value("nopfs")
-pfs:value("dh1")
-pfs:value("dh2")
-pfs:value("dh5")
-
-natt_mode = section:taboption("general", ListValue, "natt_mode", translate("NAT-T Mode"))
-natt_mode:value("natt", translate("RFC3947 NAT-T mode"))
-natt_mode:value("none", translate("No NAT-T"))
-natt_mode:value("force-natt", translate("Force use of NAT-T"))
-natt_mode:value("cisco-udp", translate("Cisco UDP encapsulation"))
-
-enable_no_enc = section:taboption("general", Flag, "enable_no_enc",
- translate("Disable Encryption"),
- translate("If checked, encryption is disabled"))
-enable_no_enc.default = enable_no_enc.disabled
-
-enable_single_des = section:taboption("general", Flag, "enable_single_des",
- translate("Enable Single DES"),
- translate("If checked, 1DES is enabled"))
-enable_no_enc.default = enable_single_des.disabled
-
-dpd_idle = section:taboption("general", Value, "dpd_idle", translate("DPD Idle Timeout"))
-dpd_idle.datatype = "uinteger"
-dpd_idle.placeholder = "600"
-
-ifname = section:taboption("general", Value, "target_network", translate("Target network"))
-port.placeholder = "0.0.0.0/0"
-port.datatype = "network"
-
-defaultroute = section:taboption("general", ListValue, "defaultroute",
- translate("Default Route"),
- translate("Set VPN as Default Route"))
-defaultroute:value("0", translate("No"))
-defaultroute:value("1", translate("Yes"))
diff --git a/protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js b/protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js
new file mode 100644
index 0000000000..ab76326eee
--- /dev/null
+++ b/protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js
@@ -0,0 +1,140 @@
+'use strict';
+'require form';
+'require network';
+
+function validateBase64(section_id, value) {
+ if (value.length == 0)
+ return true;
+
+ if (value.length != 44 || !value.match(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/))
+ return _('Invalid Base64 key string');
+
+ return true;
+}
+
+return network.registerProtocol('wireguard', {
+ getI18n: function() {
+ return _('WireGuard VPN');
+ },
+
+ getIfname: function() {
+ return this._ubus('l3_device') || this.sid;
+ },
+
+ getOpkgPackage: function() {
+ return 'wireguard-tools';
+ },
+
+ isFloating: function() {
+ return true;
+ },
+
+ isVirtual: function() {
+ return true;
+ },
+
+ getDevices: function() {
+ return null;
+ },
+
+ containsDevice: function(ifname) {
+ return (network.getIfnameOf(ifname) == this.getIfname());
+ },
+
+ renderFormOptions: function(s) {
+ var o, ss;
+
+ // -- general ---------------------------------------------------------------------
+
+ o = s.taboption('general', form.Value, 'private_key', _('Private Key'), _('Required. Base64-encoded private key for this interface.'));
+ o.password = true;
+ o.validate = validateBase64;
+ o.rmempty = false;
+
+ o = s.taboption('general', form.Value, 'listen_port', _('Listen Port'), _('Optional. UDP port used for outgoing and incoming packets.'));
+ o.datatype = 'port';
+ o.placeholder = _('random');
+ o.optional = true;
+
+ o = s.taboption('general', form.DynamicList, 'addresses', _('IP Addresses'), _('Recommended. IP addresses of the WireGuard interface.'));
+ o.datatype = 'ipaddr';
+ o.optional = true;
+
+
+ // -- advanced --------------------------------------------------------------------
+
+ o = s.taboption('advanced', form.Value, 'metric', _('Metric'), _('Optional'));
+ o.datatype = 'uinteger';
+ o.placeholder = '0';
+ o.optional = true;
+
+ o = s.taboption('advanced', form.Value, 'mtu', _('MTU'), _('Optional. Maximum Transmission Unit of tunnel interface.'));
+ o.datatype = 'range(1280,1420)';
+ o.placeholder = '1420';
+ o.optional = true;
+
+ o = s.taboption('advanced', form.Value, 'fwmark', _('Firewall Mark'), _('Optional. 32-bit mark for outgoing encrypted packets. Enter value in hex, starting with <code>0x</code>.'));
+ o.optional = true;
+ o.validate = function(section_id, value) {
+ if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,4}$/))
+ return _('Invalid hexadecimal value');
+
+ return true;
+ };
+
+
+ // -- peers -----------------------------------------------------------------------
+
+ try {
+ s.tab('peers', _('Peers'), _('Further information about WireGuard interfaces and peers at <a href=\'http://wireguard.com\'>wireguard.com</a>.'));
+ }
+ catch(e) {}
+
+ o = s.taboption('peers', form.SectionValue, '_peers', form.TypedSection, 'wireguard_%s'.format(s.section));
+ o.depends('proto', 'wireguard');
+
+ ss = o.subsection;
+ ss.anonymous = true;
+ ss.addremove = true;
+ ss.addbtntitle = _('Add peer');
+
+ ss.renderSectionPlaceholder = function() {
+ return E([], [
+ E('br'),
+ E('em', _('No peers defined yet'))
+ ]);
+ };
+
+ o = ss.option(form.Value, 'description', _('Description'), _('Optional. Description of peer.'));
+ o.placeholder = 'My Peer';
+ o.datatype = 'string';
+ o.optional = true;
+
+ o = ss.option(form.Value, 'public_key', _('Public Key'), _('Required. Base64-encoded public key of peer.'));
+ o.validate = validateBase64;
+ o.rmempty = false;
+
+ o = ss.option(form.Value, 'preshared_key', _('Preshared Key'), _('Optional. Base64-encoded preshared key. Adds in an additional layer of symmetric-key cryptography for post-quantum resistance.'));
+ o.password = true;
+ o.validate = validateBase64;
+ o.optional = true;
+
+ o = ss.option(form.DynamicList, 'allowed_ips', _('Allowed IPs'), _("Required. IP addresses and prefixes that this peer is allowed to use inside the tunnel. Usually the peer's tunnel IP addresses and the networks the peer routes through the tunnel."));
+ o.datatype = 'ipaddr';
+ o.rmempty = false;
+
+ o = ss.option(form.Flag, 'route_allowed_ips', _('Route Allowed IPs'), _('Optional. Create routes for Allowed IPs for this peer.'));
+
+ o = ss.option(form.Value, 'endpoint_host', _('Endpoint Host'), _('Optional. Host of peer. Names are resolved prior to bringing up the interface.'));
+ o.placeholder = 'vpn.example.com';
+ o.datatype = 'host';
+
+ o = ss.option(form.Value, 'endpoint_port', _('Endpoint Port'), _('Optional. Port of peer.'));
+ o.placeholder = '51820';
+ o.datatype = 'port';
+
+ o = ss.option(form.Value, 'persistent_keepalive', _('Persistent Keep Alive'), _('Optional. Seconds between keep alive messages. Default is 0 (disabled). Recommended value if this device is behind a NAT is 25.'));
+ o.datatype = 'range(0,65535)';
+ o.placeholder = '0';
+ }
+});
diff --git a/protocols/luci-proto-wireguard/luasrc/model/cbi/admin_network/proto_wireguard.lua b/protocols/luci-proto-wireguard/luasrc/model/cbi/admin_network/proto_wireguard.lua
deleted file mode 100644
index 64e256a517..0000000000
--- a/protocols/luci-proto-wireguard/luasrc/model/cbi/admin_network/proto_wireguard.lua
+++ /dev/null
@@ -1,179 +0,0 @@
--- Copyright 2016-2017 Dan Luedtke <mail@danrl.com>
--- Licensed to the public under the Apache License 2.0.
-
-
-local map, section, net = ...
-local ifname = net:get_interface():name()
-local private_key, listen_port
-local metric, mtu, preshared_key, description
-local peers, public_key, allowed_ips, endpoint, persistent_keepalive
-
-
--- general ---------------------------------------------------------------------
-
-private_key = section:taboption(
- "general",
- Value,
- "private_key",
- translate("Private Key"),
- translate("Required. Base64-encoded private key for this interface.")
-)
-private_key.password = true
-private_key.datatype = "and(base64,rangelength(44,44))"
-private_key.optional = false
-
-
-listen_port = section:taboption(
- "general",
- Value,
- "listen_port",
- translate("Listen Port"),
- translate("Optional. UDP port used for outgoing and incoming packets.")
-)
-listen_port.datatype = "port"
-listen_port.placeholder = translate("random")
-listen_port.optional = true
-
-addresses = section:taboption(
- "general",
- DynamicList,
- "addresses",
- translate("IP Addresses"),
- translate("Recommended. IP addresses of the WireGuard interface.")
-)
-addresses.datatype = "ipaddr"
-addresses.optional = true
-
-
--- advanced --------------------------------------------------------------------
-
-metric = section:taboption(
- "advanced",
- Value,
- "metric",
- translate("Metric"),
- translate("Optional")
-)
-metric.datatype = "uinteger"
-metric.placeholder = "0"
-metric.optional = true
-
-
-mtu = section:taboption(
- "advanced",
- Value,
- "mtu",
- translate("MTU"),
- translate("Optional. Maximum Transmission Unit of tunnel interface.")
-)
-mtu.datatype = "range(1280,1420)"
-mtu.placeholder = "1420"
-mtu.optional = true
-
-fwmark = section:taboption(
- "advanced",
- Value,
- "fwmark",
- translate("Firewall Mark"),
- translate("Optional. 32-bit mark for outgoing encrypted packets. " ..
- "Enter value in hex, starting with <code>0x</code>.")
-)
-fwmark.datatype = "hex(4)"
-fwmark.optional = true
-
-
--- peers -----------------------------------------------------------------------
-
-peers = map:section(
- TypedSection,
- "wireguard_" .. ifname,
- translate("Peers"),
- translate("Further information about WireGuard interfaces and peers " ..
- "at <a href=\"http://wireguard.com\">wireguard.com</a>.")
-)
-peers.template = "cbi/tsection"
-peers.anonymous = true
-peers.addremove = true
-
-
-description = peers:option(
- Value,
- "description",
- translate("Description"),
- translate("Optional. Description of peer."))
-description.placeholder = "My Peer"
-description.datatype = "string"
-description.optional = true
-
-
-public_key = peers:option(
- Value,
- "public_key",
- translate("Public Key"),
- translate("Required. Base64-encoded public key of peer.")
-)
-public_key.datatype = "and(base64,rangelength(44,44))"
-public_key.optional = false
-
-
-preshared_key = peers:option(
- Value,
- "preshared_key",
- translate("Preshared Key"),
- translate("Optional. Base64-encoded preshared key. " ..
- "Adds in an additional layer of symmetric-key " ..
- "cryptography for post-quantum resistance.")
-)
-preshared_key.password = true
-preshared_key.datatype = "and(base64,rangelength(44,44))"
-preshared_key.optional = true
-
-
-allowed_ips = peers:option(
- DynamicList,
- "allowed_ips",
- translate("Allowed IPs"),
- translate("Required. IP addresses and prefixes that this peer is allowed " ..
- "to use inside the tunnel. Usually the peer's tunnel IP " ..
- "addresses and the networks the peer routes through the tunnel.")
-)
-allowed_ips.datatype = "ipaddr"
-allowed_ips.optional = false
-
-
-route_allowed_ips = peers:option(
- Flag,
- "route_allowed_ips",
- translate("Route Allowed IPs"),
- translate("Optional. Create routes for Allowed IPs for this peer.")
-)
-
-
-endpoint_host = peers:option(
- Value,
- "endpoint_host",
- translate("Endpoint Host"),
- translate("Optional. Host of peer. Names are resolved " ..
- "prior to bringing up the interface."))
-endpoint_host.placeholder = "vpn.example.com"
-endpoint_host.datatype = "host"
-
-
-endpoint_port = peers:option(
- Value,
- "endpoint_port",
- translate("Endpoint Port"),
- translate("Optional. Port of peer."))
-endpoint_port.placeholder = "51820"
-endpoint_port.datatype = "port"
-
-
-persistent_keepalive = peers:option(
- Value,
- "persistent_keepalive",
- translate("Persistent Keep Alive"),
- translate("Optional. Seconds between keep alive messages. " ..
- "Default is 0 (disabled). Recommended value if " ..
- "this device is behind a NAT is 25."))
-persistent_keepalive.datatype = "range(0,65535)"
-persistent_keepalive.placeholder = "0"