From 01a44515bcbb05ef1bd70fde62fb2d17081b0c24 Mon Sep 17 00:00:00 2001 From: Arayuki Mago Date: Thu, 3 Oct 2024 14:31:13 +0900 Subject: [PATCH 1/2] luci-proto-ipv6: map: Add SNAT fix option for specific ISP Ensure that the multiple port ranges used with specific ISP MAP-E implementation are actually SNAT-ed correctly. Signed-off-by: Arayuki Mago --- modules/luci-base/po/ja/base.po | 21 +++++++++++++++ modules/luci-base/po/zh_Hans/base.po | 21 +++++++++++++++ .../luci-static/resources/protocol/map.js | 26 +++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/modules/luci-base/po/ja/base.po b/modules/luci-base/po/ja/base.po index 20b256e53e8b..3176378ab9e9 100644 --- a/modules/luci-base/po/ja/base.po +++ b/modules/luci-base/po/ja/base.po @@ -11011,6 +11011,26 @@ msgstr "" "RFC7597の代わりに従来のMAPインターフェース識別子フォーマット(draft-ietf-" "softwire-map-00)を使用" +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:90 +msgid "Enable SNAT fix" +msgstr "SNAT修正を有効化" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:90 +msgid "Apply SNAT fixes with certain ISPs" +msgstr "特定ISPに対してSNAT修正を適用" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:92 +msgid "Exclude SNAT ports" +msgstr "SNATポートを除外" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:92 +msgid "List of ports to exclude from SNAT. Separate ports with spaces" +msgstr "SNATから除外するポートのリスト。スペースで区切る" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:109 +msgid "Duplicate port found: " +msgstr "重複ポート番号検出:" + #: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 msgid "Use routing table" msgstr "ルーティングテーブルを使用" @@ -12194,6 +12214,7 @@ msgstr "有効なポートまたはポート範囲(port1-port2)" #: modules/luci-base/htdocs/luci-static/resources/validation.js:368 #: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:207 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:106 msgid "valid port value" msgstr "有効なポート番号" diff --git a/modules/luci-base/po/zh_Hans/base.po b/modules/luci-base/po/zh_Hans/base.po index 300d876419ee..1010af0e5098 100644 --- a/modules/luci-base/po/zh_Hans/base.po +++ b/modules/luci-base/po/zh_Hans/base.po @@ -10954,6 +10954,26 @@ msgid "" msgstr "" "使用旧式 MAP 接口标识符格式(draft-ietf-softwire-map-00),而非 RFC7597" +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:90 +msgid "Enable SNAT fix" +msgstr "启用 SNAT 修复" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:90 +msgid "Apply SNAT fixes with certain ISPs" +msgstr "对某些 ISP 应用 SNAT 修复" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:92 +msgid "Exclude SNAT ports" +msgstr "排除 SNAT 端口" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:92 +msgid "List of ports to exclude from SNAT. Separate ports with spaces" +msgstr "要从 SNAT 中排除的端口列表。用空格分隔" + +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:109 +msgid "Duplicate port found: " +msgstr "重复的端口号:" + #: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 msgid "Use routing table" msgstr "使用路由表" @@ -12135,6 +12155,7 @@ msgstr "有效端口或端口范围(port1-port2)" #: modules/luci-base/htdocs/luci-static/resources/validation.js:368 #: modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js:207 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:106 msgid "valid port value" msgstr "有效端口值" 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 index 82e016921030..be0b4893ba16 100644 --- a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js +++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js @@ -86,5 +86,31 @@ return network.registerProtocol('map', { o.datatype = 'max(9200)'; o = s.taboption('advanced', form.Flag, 'legacymap', _('Use legacy MAP'), _('Use legacy MAP interface identifier format (draft-ietf-softwire-map-00) instead of RFC7597')); + + o = s.taboption('advanced', form.Flag, 'snat_fix', _('Enable SNAT fix'), _('Apply SNAT fixes with certain ISPs')); + + o = s.taboption('advanced', form.Value, 'dont_snat_to', _('Exclude SNAT ports'), _('List of ports to exclude from SNAT. Separate ports with spaces')); + o.depends('snat_fix', '1'); + o.datatype = 'string'; + o.placeholder = '80 443 8080'; + o.validate = function (section_id, value) { + value = value.trim().replace(/\s+/g, ' '); + if (!value) return true; + let seen = new Set(); + for (let port of value.split(' ')) { + let portNum = parseInt(port, 10); + if (!/^\d+$/.test(port) || portNum < 1 || portNum > 65535) { + return _('Expecting: %s').format(_('valid port value')); + } + if (seen.has(port)) { + return _('Duplicate port found: ') + port; + } + seen.add(port); + } + return true; + }; + o.write = function (section_id, form_value) { + return this.super('write', [section_id, form_value.trim().replace(/\s+/g, ' ')]); + }; } }); From 4167e04e861c6f826e1154e157d8be96633ae106 Mon Sep 17 00:00:00 2001 From: Arayuki Mago Date: Sat, 5 Oct 2024 05:44:31 +0900 Subject: [PATCH 2/2] luci-proto-ipv6: add support for 4in6 tunnel displaying status in luci Add support for showing 4in6 tunnel status in luci. Signed-off-by: Arayuki Mago --- modules/luci-base/po/ja/base.po | 11 ++++- modules/luci-base/po/zh_Hans/base.po | 11 ++++- .../view/status/include/30_network.js | 18 +++++-- .../luci-static/resources/protocol/dslite.js | 4 ++ .../luci-static/resources/protocol/ipip6.js | 4 ++ .../luci-static/resources/protocol/map.js | 48 ++++++++++++++++++- 6 files changed, 90 insertions(+), 6 deletions(-) diff --git a/modules/luci-base/po/ja/base.po b/modules/luci-base/po/ja/base.po index 3176378ab9e9..ad1ab8fa97ea 100644 --- a/modules/luci-base/po/ja/base.po +++ b/modules/luci-base/po/ja/base.po @@ -11028,9 +11028,18 @@ msgid "List of ports to exclude from SNAT. Separate ports with spaces" msgstr "SNATから除外するポートのリスト。スペースで区切る" #: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:109 -msgid "Duplicate port found: " +msgid "Duplicate port found:" msgstr "重複ポート番号検出:" +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:60 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:71 +msgid "Available portsets" +msgstr "利用可能ポート" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:61 +msgid "Show" +msgstr "表示" + #: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 msgid "Use routing table" msgstr "ルーティングテーブルを使用" diff --git a/modules/luci-base/po/zh_Hans/base.po b/modules/luci-base/po/zh_Hans/base.po index 1010af0e5098..2469241d9f94 100644 --- a/modules/luci-base/po/zh_Hans/base.po +++ b/modules/luci-base/po/zh_Hans/base.po @@ -10971,9 +10971,18 @@ msgid "List of ports to exclude from SNAT. Separate ports with spaces" msgstr "要从 SNAT 中排除的端口列表。用空格分隔" #: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:109 -msgid "Duplicate port found: " +msgid "Duplicate port found:" msgstr "重复的端口号:" +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:60 +#: protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js:71 +msgid "Available portsets" +msgstr "可用的端口组" + +#: modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js:61 +msgid "Show" +msgstr "显示" + #: protocols/luci-proto-relay/htdocs/luci-static/resources/protocol/relay.js:179 msgid "Use routing table" msgstr "使用路由表" diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js index 0d051bdeaf9f..4e49391b31ae 100644 --- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js @@ -22,7 +22,17 @@ function renderbox(ifc, ipv6) { addrs = (ipv6 ? ifc.getIP6Addrs() : ifc.getIPAddrs()) || [], dnssrv = (ipv6 ? ifc.getDNS6Addrs() : ifc.getDNSAddrs()) || [], expires = ifc.getExpiry(), - uptime = ifc.getUptime(); + uptime = ifc.getUptime(), + type = ifc.getOpkgPackage(); + + if (type === 'map-t' && typeof ifc.callShowPortsets === 'function') { + addrs = ifc.getIPAddrs().concat(ifc.getIPv6Addrs()); + var showPortsets = ifc.callShowPortsets(); + } + + if (type === 'ds-lite') { + addrs = ifc.getIPAddrs().concat(ifc.getIP6Addrs()); + } return E('div', { class: 'ifacebox' }, [ E('div', { class: 'ifacebox-head center ' + (active ? 'active' : '') }, @@ -31,8 +41,8 @@ function renderbox(ifc, ipv6) { L.itemlist(E('span'), [ _('Protocol'), ifc.getI18n() || E('em', _('Not connected')), _('Prefix Delegated'), ipv6 ? ifc.getIP6Prefix() : null, - _('Address'), addrs[0], - _('Address'), addrs[1], + (type === 'map-t' || type === 'ds-lite' ? _('IPv4 address') : _('Address')), addrs[0], + (type === 'map-t' || type === 'ds-lite' ? _('IPv6 address') : _('Address')), addrs[1], _('Address'), addrs[2], _('Address'), addrs[3], _('Address'), addrs[4], @@ -47,6 +57,8 @@ function renderbox(ifc, ipv6) { _('DNS') + ' 3', dnssrv[2], _('DNS') + ' 4', dnssrv[3], _('DNS') + ' 5', dnssrv[4], + showPortsets ? _('Available portsets') : null, + showPortsets ? E('button', { class: 'cbi-button cbi-button-apply', click: showPortsets }, _('Show')) : null, _('Expires'), (expires != null && expires > -1) ? '%t'.format(expires) : null, _('Connected'), (uptime > 0) ? '%t'.format(uptime) : null ]), 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 index 5981973e311f..a58374697e59 100644 --- a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js +++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/dslite.js @@ -31,6 +31,10 @@ return network.registerProtocol('dslite', { return null; }, + getGatewayAddr: function () { + return this.get('peeraddr'); + }, + containsDevice: function(ifname) { return (network.getIfnameOf(ifname) == this.getIfname()); }, diff --git a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/ipip6.js b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/ipip6.js index 6f38317f49e2..d7614df55d12 100644 --- a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/ipip6.js +++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/ipip6.js @@ -30,6 +30,10 @@ return network.registerProtocol('ipip6', { return null; }, + getGatewayAddr: function () { + return this.get('peeraddr'); + }, + containsDevice: function (ifname) { return (network.getIfnameOf(ifname) == this.getIfname()); }, 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 index be0b4893ba16..f6e2c5bbbd13 100644 --- a/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js +++ b/protocols/luci-proto-ipv6/htdocs/luci-static/resources/protocol/map.js @@ -37,6 +37,52 @@ return network.registerProtocol('map', { return (network.getIfnameOf(ifname) == this.getIfname()); }, + getGatewayAddr: function () { + return this.get('peeraddr'); + }, + + getIPv6Addrs: function () { + var d = this._ubus('data'); + if (L.isObject(d) && typeof (d.ipv6addr) == 'string') + return d.ipv6addr; + return null; + }, + + callShowPortsets: function () { + var d = this._ubus('data'); + if (L.isObject(d) && typeof (d.portsets) == 'string') { + var portSets = d.portsets; + if (portSets) { + var portArray = portSets.split(' '); + var groupedPorts = []; + for (var i = 0; i < portArray.length; i += 2) { + groupedPorts.push(portArray.slice(i, i + 2)); + } + portSets = E('table', { style: 'width: 100%; border-collapse: collapse;' }, + groupedPorts.map(function (portGroup) { + return E('tr', {}, [ + E('td', { style: 'padding: 10px; border: 1px solid #ddd; text-align: center; font-size: 16px;' }, portGroup[0]), + portGroup[1] ? E('td', { style: 'padding: 10px; border: 1px solid #ddd; text-align: center; font-size: 16px;' }, portGroup[1]) : E('td', {}) + ]); + }) + ); + } + function showPortsets() { + L.ui.showModal(_('Available portsets'), [ + E('div', { style: 'max-height: 400px; overflow-y: auto; padding: 10px; border: 1px solid #ddd;' }, portSets || _('No Data')), + E('div', { class: 'right' }, [ + E('button', { + class: 'btn', + click: L.ui.hideModal + }, _('Close')) + ]) + ]); + } + return showPortsets; + } + return null; + }, + renderFormOptions: function(s) { var o; @@ -103,7 +149,7 @@ return network.registerProtocol('map', { return _('Expecting: %s').format(_('valid port value')); } if (seen.has(port)) { - return _('Duplicate port found: ') + port; + return _('Duplicate port found:') + port; } seen.add(port); }