⛄ Sync 2026-07-03 20:40:27

This commit is contained in:
github-actions[bot] committed 2026-07-03 20:40:27 +08:00
1 parent 2b1b1f1ad7
commit 40213156af
26 files changed
+2592 -5

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
include $(TOPDIR)/rules.mk
LUCI_TITLE:=MWAN3 Ledhelper simple webUI
LUCI_DEPENDS:=+luci-app-mwan3-nft +mwan3-ledhelper-nft
PKG_LICENSE:=GPLv3
PKG_VERSION:=0.0.1
PKG_RELEASE:=1
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
@@ -0,0 +1,110 @@
'use strict';
'require form';
'require fs';
'require view';
'require uci';
'require rpc';
'require ui';
'require network';
'require tools.widgets as widgets'
var callLEDs = rpc.declare({
object: 'luci',
method: 'getLEDs',
expect: { '': {} }
});
return view.extend({
load: function() {
return Promise.all([
callLEDs(),
L.resolveDefault(fs.list('/www' + L.resource('view/system/led-trigger')), []),
// load config mwan3
fs.read('/etc/config/mwan3').catch(function(err) { return ''; })
]).then(function(data) {
var plugins = data[1];
var mwan3Config = data[2];
var tasks = [];
// parce ifaces mwan3 config
var mwan3Interfaces = [];
if (mwan3Config) {
var lines = mwan3Config.split('\n');
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
var match = line.match(/^config interface '([^']+)'/);
if (match) {
mwan3Interfaces.push(match[1]);
}
}
}
for (var i = 0; i < plugins.length; i++) {
var m = plugins[i].name.match(/^(.+)\.js$/);
if (plugins[i].type != 'file' || m == null)
continue;
tasks.push(L.require('view.system.led-trigger.' + m[1]).then(L.bind(function(name){
return L.resolveDefault(L.require('view.system.led-trigger.' + name)).then(function(form) {
return {
name: name,
form: form,
};
});
}, this, m[1])));
}
return Promise.all(tasks).then(function(plugins) {
var value = {};
value[0] = data[0];
value[1] = plugins;
value[2] = mwan3Interfaces; // add mwan3 iface
return value;
});
});
},
render: function(data) {
var m, s, o, triggers = [];
var leds = data[0];
var mwan3Interfaces = data[2]; // get ifaces from mwan3 config
for (var k in leds)
for (var i = 0; i < leds[k].triggers.length; i++)
triggers[i] = leds[k].triggers[i];
m = new form.Map('mwan3_led', _('MWAN3 Ledhelper'), _('Flash led on link state.'));
s = m.section(form.GridSection, 'led', null);
s.anonymous = false;
s.addremove = true;
// filter NetworkSelect
o = s.option(widgets.NetworkSelect, 'iface', _('Set interface'));
o.exclude = s.section;
o.nocreate = true;
o.optional = true;
// filter interfaces
o.filter = function(section_id, value) {
return mwan3Interfaces.indexOf(value) !== -1;
};
o = s.option(form.ListValue, 'led_on', _('Select LED online'));
Object.keys(leds).sort().forEach(function(name) {
o.value(name);
});
o.value('', _('Exclude'));
o.default = '';
o.rmempty = true;
o = s.option(form.ListValue, 'led_off', _('Select LED offline'));
Object.keys(leds).sort().forEach(function(name) {
o.value(name);
});
o.value('', _('Exclude'));
o.default = '';
o.rmempty = true;
return m.render();
}
});
@@ -0,0 +1,22 @@
"Language: ru\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Last-Translator: Konstantine Shevlakov <shevlakov@132lan.ru>\n"
msgid "Flash led on link state."
msgstr "Индикация светодиодов"
msgid "Name"
msgstr "Имя"
msgid "Set interface"
msgstr "Интерфейс"
msgid "Exclude"
msgstr "Не использовать"
msgid "Select LED online"
msgstr "LED \"в сети\""
msgid "Select LED offline"
msgstr "LED \"вне сети\""
@@ -0,0 +1,10 @@
{
"admin/network/mwan3/led": {
"title": "LED",
"order": 55,
"action": {
"type": "view",
"path": "mwan3/network/led"
}
}
}
@@ -0,0 +1,25 @@
{
"luci-app-mwan3-ledhelper-nft": {
"description": "Grant access to MWAN3 LED configuration",
"read": {
"file": {
"/etc/init.d/mwan3": [ "exec" ],
"/etc/config/mwan3": [ "read" ]
},
"cgi-io": [ "exec" ],
"ubus": {
"file": [ "exec" ],
"uci": [ "changes", "get" ]
},
"uci": [ "mwan3_led" ]
},
"write": {
"cgi-io": [ "exec" ],
"ubus": {
"file": [ "exec" ],
"uci": [ "add", "apply", "confirm", "delete", "order", "rename", "set" ]
},
"uci": [ "mwan3_led" ]
}
}
}
+16
View File
@@ -0,0 +1,16 @@
#
# Copyright (C) 2017 Dan Luedtke <mail@danrl.com>
#
# This is free software, licensed under the GNU General Public License v2.
include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI support for the MWAN3 MultiWAN Manager
LUCI_DEPENDS:=+luci-base +mwan3-nft
PKG_LICENSE:=GPL-2.0
PKG_MAINTAINER:=Florian Eckert <fe@dev.tdt.de>
include $(TOPDIR)/feeds/luci/luci.mk
# call BuildPackage - OpenWrt buildroot signature
@@ -0,0 +1,8 @@
#mwan3-service-status > .alert-message {
display: inline-block;
margin: 1rem;
padding: 1rem;
width: 15rem;
height: 6rem;
vertical-align: middle;
}
@@ -0,0 +1,48 @@
'use strict';
'require form';
'require view';
return view.extend({
render: function () {
let m, s, o;
m = new form.Map('mwan3', _('MultiWAN Manager - Globals'));
s = m.section(form.NamedSection, 'globals', 'globals');
o = s.option(form.Value, 'mmx_mask', _('Firewall mask'),
_('Enter value in hex, starting with <code>0x</code>'));
o.datatype = 'hex(4)';
o.default = '0x3F00';
o = s.option(form.Flag, 'logging', _('Logging'),
_('Enables global firewall logging'));
o = s.option(form.ListValue, 'loglevel', _('Loglevel'),
_('Firewall loglevel'));
o.default = 'notice';
o.value('emerg', _('Emergency'));
o.value('alert', _('Alert'));
o.value('crit', _('Critical'));
o.value('error', _('Error'));
o.value('warning', _('Warning'));
o.value('notice', _('Notice'));
o.value('info', _('Info'));
o.value('debug', _('Debug'));
o.depends('logging', '1');
o = s.option(form.DynamicList, 'rt_table_lookup',
_('Routing table lookup'),
_('Also scan this Routing table for connected networks'));
o.datatype = 'uinteger';
o.value('220', _('Routing table %d').format('220'));
o = s.option(form.Flag, 'show_overview', _('Show on overview'),
_('Show MultiWAN status section on the overview page'));
o.default = o.enabled;
o.rmempty = false;
return m.render();
}
})
@@ -0,0 +1,324 @@
'use strict';
'require form';
'require fs';
'require view';
'require uci';
'require ui';
return view.extend({
load: function() {
return Promise.all([
L.resolveDefault(fs.stat('/usr/bin/httping'), {}),
L.resolveDefault(fs.stat('/usr/bin/nping'), {}),
L.resolveDefault(fs.stat('/usr/bin/arping'), {}),
uci.load('network')
]);
},
render: function (stats) {
let m, s, o;
m = new form.Map('mwan3', _('MultiWAN Manager - Interfaces'),
_('Mwan3 requires that all interfaces have a unique metric configured in /etc/config/network.') + '<br />' +
_('Names must match the interface name found in /etc/config/network.') + '<br />' +
_('Names may contain characters A-Z, a-z, 0-9, _ and no spaces-') + '<br />' +
_('Interfaces may not share the same name as configured members, policies or rules.'));
s = m.section(form.GridSection, 'interface');
s.addremove = true;
s.anonymous = false;
s.nodescriptions = true;
s.renderSectionAdd = function(extra_class) {
var usedNames = [
...uci.sections('mwan3', 'interface'),
...uci.sections('mwan3', 'member'),
...uci.sections('mwan3', 'policy'),
...uci.sections('mwan3', 'rule')
].map(function(sec) { return sec['.name']; });
var available = uci.sections('network', 'interface')
.map(function(sec) { return sec['.name']; })
.filter(function(name) {
return name !== 'loopback' &&
name.length <= 15 &&
usedNames.indexOf(name) === -1;
});
var el = E('div', { 'class': 'cbi-section-create' + (extra_class ? ' ' + extra_class : '') }, [
E('div', { 'class': 'cbi-section-create-name-container' }, [
E('select', {
'class': 'cbi-section-create-name',
'style': 'min-width: 12em'
}, available.length
? available.map(function(name) {
return E('option', { 'value': name }, name);
})
: [E('option', { 'value': '', 'disabled': true, 'selected': true },
_('No available interfaces'))]
),
E('button', {
'class': 'cbi-button cbi-button-add',
'title': _('Add'),
'disabled': available.length === 0 || null,
'click': ui.createHandlerFn(this, function(ev) {
var select = ev.target.closest('.cbi-section-create')
.querySelector('select.cbi-section-create-name');
var name = select ? select.value : '';
if (!name) return;
return this.handleAdd(ev, name);
})
}, _('Add'))
])
]);
return el;
};
o = s.option(form.Flag, 'enabled', _('Enabled'));
o.default = false;
o = s.option(form.ListValue, 'initial_state', _('Initial state'),
_('Expect interface state on up event'));
o.default = 'online';
o.value('online', _('Online'));
o.value('offline', _('Offline'));
o.modalonly = true;
o = s.option(form.ListValue, 'family', _('Internet Protocol'));
o.default = 'ipv4';
o.value('ipv4', _('IPv4'));
o.value('ipv6', _('IPv6'));
o.modalonly = true;
o = s.option(form.DynamicList, 'track_ip', _('Tracking hostname or IP address'),
_('This hostname or IP address will be pinged to determine if the link is up or down. Leave blank to assume interface is always online'));
o.datatype = 'host';
o.modalonly = true;
o = s.option(form.ListValue, 'track_method', _('Tracking method'));
o.default = 'ping';
o.value('ping');
if (stats[0].type === 'file') {
o.value('httping');
}
if (stats[1].type === 'file') {
o.value('nping-tcp');
o.value('nping-udp');
o.value('nping-icmp');
o.value('nping-arp');
}
if (stats[2].type === 'file') {
o.value('arping');
}
o = s.option(form.Flag, 'httping_ssl', _('Enable ssl tracking'),
_('Enables https tracking on ssl port 443'));
o.depends('track_method', 'httping');
o.rmempty = false;
o.modalonly = true;
o = s.option(form.Value, 'reliability', _('Tracking reliability'),
_('Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up'));
o.datatype = 'range(1, 100)';
o.default = '1';
o = s.option(form.ListValue, 'count', _('Ping count'));
o.default = '1';
o.value('1');
o.value('2');
o.value('3');
o.value('4');
o.value('5');
o.modalonly = true;
o = s.option(form.Value, 'size', _('Ping size'));
o.default = '56';
o.depends('track_method', 'ping');
o.value('8');
o.value('24');
o.value('56');
o.value('120');
o.value('248');
o.value('504');
o.value('1016');
o.value('1472');
o.value('2040');
o.datatype = 'range(1, 65507)';
o.modalonly = true;
o =s.option(form.Value, 'max_ttl', _('Max TTL'));
o.default = '60';
o.depends('track_method', 'ping');
o.value('10');
o.value('20');
o.value('30');
o.value('40');
o.value('50');
o.value('60');
o.value('70');
o.datatype = 'range(1, 255)';
o.modalonly = true;
o = s.option(form.Flag, 'check_quality', _('Check link quality'));
o.depends('track_method', 'ping');
o.default = false;
o.modalonly = true;
o = s.option(form.Value, 'failure_latency', _('Failure latency [ms]'));
o.depends('check_quality', '1');
o.default = '1000';
o.value('25');
o.value('50');
o.value('75');
o.value('100');
o.value('150');
o.value('200');
o.value('250');
o.value('300');
o.modalonly = true;
o = s.option(form.Value, 'failure_loss', _('Failure packet loss [%]'));
o.depends('check_quality', '1');
o.default = '40';
o.value('2');
o.value('5');
o.value('10');
o.value('20');
o.value('25');
o.modalonly = true;
o = s.option(form.Value, 'recovery_latency', _('Recovery latency [ms]'));
o.depends('check_quality', '1');
o.default = '500';
o.value('25');
o.value('50');
o.value('75');
o.value('100');
o.value('150');
o.value('200');
o.value('250');
o.value('300');
o.modalonly = true;
o = s.option(form.Value, 'recovery_loss', _('Recovery packet loss [%]'));
o.depends('check_quality', '1');
o.default = '10';
o.value('2');
o.value('5');
o.value('10');
o.value('20');
o.value('25');
o.modalonly = true;
o = s.option(form.ListValue, "timeout", _("Ping timeout"));
o.default = '4';
o.value('1', _('%d second').format('1'));
for (var i = 2; i <= 10; i++)
o.value(String(i), _('%d seconds').format(i));
o.modalonly = true;
o = s.option(form.ListValue, 'interval', _('Ping interval'));
o.default = '10';
o.value('1', _('%d second').format('1'));
o.value('3', _('%d seconds').format('3'));
o.value('5', _('%d seconds').format('5'));
o.value('10', _('%d seconds').format('10'));
o.value('20', _('%d seconds').format('20'));
o.value('30', _('%d seconds').format('30'));
o.value('60', _('%d minute').format('1'));
o.value('300', _('%d minutes').format('5'));
o.value('600', _('%d minutes').format('10'));
o.value('900', _('%d minutes').format('15'));
o.value('1800', _('%d minutes').format('30'));
o.value('3600', _('%d hour').format('1'));
o = s.option(form.Value, 'failure_interval', _('Failure interval'),
_('Ping interval during failure detection'));
o.default = '5';
o.value('1', _('%d second').format('1'));
o.value('3', _('%d seconds').format('3'));
o.value('5', _('%d seconds').format('5'));
o.value('10', _('%d seconds').format('10'));
o.value('20', _('%d seconds').format('20'));
o.value('30', _('%d seconds').format('30'));
o.value('60', _('%d minute').format('1'));
o.value('300', _('%d minutes').format('5'));
o.value('600', _('%d minutes').format('10'));
o.value('900', _('%d minutes').format('15'));
o.value('1800', _('%d minutes').format('30'));
o.value('3600', _('%d hour').format('1'));
o.modalonly = true;
o = s.option(form.Flag, 'keep_failure_interval', _('Keep failure interval'),
_('Keep ping failure interval during failure state'));
o.default = false;
o.modalonly = true;
o = s.option(form.Value, 'recovery_interval', _('Recovery interval'),
_('Ping interval during failure recovering'));
o.default = '5';
o.value('1', _('%d second').format('1'));
o.value('3', _('%d seconds').format('3'));
o.value('5', _('%d seconds').format('5'));
o.value('10', _('%d seconds').format('10'));
o.value('20', _('%d seconds').format('20'));
o.value('30', _('%d seconds').format('30'));
o.value('60', _('%d minute').format('1'));
o.value('300', _('%d minutes').format('5'));
o.value('600', _('%d minutes').format('10'));
o.value('900', _('%d minutes').format('15'));
o.value('1800', _('%d minutes').format('30'));
o.value('3600', _('%d hour').format('1'));
o.modalonly = true;
o = s.option(form.ListValue, 'down', _('Interface down'),
_('Interface will be deemed down after this many failed ping tests'));
o.default = '5';
o.value('1');
o.value('2');
o.value('3');
o.value('4');
o.value('5');
o.value('6');
o.value('7');
o.value('8');
o.value('9');
o.value('10');
o = s.option(form.ListValue, 'up', _('Interface up'),
_('Downed interface will be deemed up after this many successful ping tests'));
o.default = "5";
o.value('1');
o.value('2');
o.value('3');
o.value('4');
o.value('5');
o.value('6');
o.value('7');
o.value('8');
o.value('9');
o.value('10');
o = s.option(form.DynamicList, 'flush_conntrack', _('Flush conntrack table'),
_('Flush global firewall conntrack table on interface events'));
o.value('ifup', _('ifup (netifd)'));
o.value('ifdown', _('ifdown (netifd)'));
o.value('connected', _('connected (mwan3)'));
o.value('disconnected', _('disconnected (mwan3)'));
o.modalonly = true;
o = s.option(form.DummyValue, 'metric', _('Metric'),
_('This displays the metric assigned to this interface in /etc/config/network'));
o.rawhtml = true;
o.cfgvalue = function(s) {
var metric = uci.get('network', s, 'metric')
if (metric)
return metric;
else
return _('No interface metric set!');
}
return m.render();
}
})
@@ -0,0 +1,67 @@
'use strict';
'require form';
'require view';
'require uci';
'require ui';
return view.extend({
load: function() {
return Promise.all([
uci.load('mwan3')
]);
},
render: function () {
let m, s, o;
m = new form.Map('mwan3', _('MultiWAN Manager - Members'),
_('Members are profiles attaching a metric and weight to an MWAN interface.') + '<br />' +
_('Names may contain characters A-Z, a-z, 0-9, _ and no spaces.') + '<br />' +
_('Members may not share the same name as configured interfaces, policies or rules.'));
s = m.section(form.GridSection, 'member');
s.addremove = true;
s.anonymous = false;
s.nodescriptions = true;
/* This name length error check can likely be removed when mwan3 migrates to nftables */
s.renderSectionAdd = function(extra_class) {
var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, function(v) {
let sections = [
...uci.sections('mwan3', 'interface'),
...uci.sections('mwan3', 'member'),
...uci.sections('mwan3', 'policy'),
...uci.sections('mwan3', 'rule')
];
for (let j = 0; j < sections.length; j++) {
if (sections[j]['.name'] == v) {
return _('Members may not share the same name as configured interfaces, policies or rules.');
}
}
if (v.length > 15) return _('Name length shall not exceed 15 characters');
return true;
}, 'blur', 'keyup');
return el;
};
o = s.option(form.ListValue, 'interface', _('Interface'));
var options = uci.sections('mwan3', 'interface')
for (var i = 0; i < options.length; i++) {
var value = options[i]['.name'];
o.value(value);
}
o = s.option(form.Value, 'metric', _('Metric'),
_('Acceptable values: 1-256. Defaults to 1 if not set'));
o.datatype = 'range(1, 256)';
o = s.option(form.Value, 'weight', _('Weight'),
_('Acceptable values: 1-1000. Defaults to 1 if not set'));
o.datatype = 'range(1, 1000)';
return m.render();
}
})
@@ -0,0 +1,52 @@
'use strict';
'require view';
'require fs';
'require ui';
const isReadonlyView = !L.hasViewPermission() || null;
return view.extend({
load() {
return L.resolveDefault(fs.read('/etc/mwan3.user'), '');
},
handleSave(ev) {
const value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n';
return fs.write('/etc/mwan3.user', value).then(function(rc) {
document.querySelector('textarea').value = value;
ui.addNotification(null, E('p', _('Contents have been saved.')), 'info');
}).catch(function(e) {
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
});
},
render(mwan3user) {
return E([
E('h2', _('MultiWAN Manager - Notify')),
E('p', { 'class': 'cbi-section-descr' },
_('This section allows you to modify the content of "/etc/mwan3.user".') + '<br/>' +
_('The file is also preserved during sysupgrade.') + '<br/>' +
'<br />' +
_('Notes:') + '<br />' +
_('This file is interpreted as a shell script.') + '<br />' +
_('The first line of the script must be &#34;#!/bin/sh&#34; without quotes.') + '<br />' +
_('Lines beginning with # are comments and are not executed.') + '<br />' +
_('Put your custom mwan3 action here, they will be executed with each netifd hotplug interface event on interfaces for which mwan3 is enabled.') + '<br />' +
'<br />' +
_('There are three main environment variables that are passed to this script.') + '<br />' +
'<br />' +
_('%s: Name of the action that triggered this event').format('$ACTION') + '<br />' +
_('* %s: Is called by netifd and mwan3track').format('ifup') + '<br />' +
_('* %s: Is called by netifd and mwan3track').format('ifdown') + '<br />' +
_('* %s: Is only called by mwan3track if tracking was successful').format('connected') + '<br />' +
_('* %s: Is only called by mwan3track if tracking has failed').format('disonnected') + '<br />' +
_('%s: Name of the interface which went up or down (e.g. "wan" or "wwan")').format('$INTERFACE') + '<br />' +
_('%s: Name of Physical device which interface went up or down (e.g. "eth0" or "wwan0")').format('$DEVICE') + '<br />'),
E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 10, 'disabled': isReadonlyView }, [ mwan3user != null ? mwan3user : '' ]))
]);
},
handleSaveApply: null,
handleReset: null
});
@@ -0,0 +1,70 @@
'use strict';
'require form';
'require view';
'require uci';
'require ui';
return view.extend({
load: function() {
return Promise.all([
uci.load('mwan3')
]);
},
render: function () {
let m, s, o;
m = new form.Map('mwan3', _('MultiWAN Manager - Policies'),
_('Policies are profiles grouping one or more members controlling how Mwan3 distributes traffic.') + '<br />' +
_('Member interfaces with lower metrics are used first.') + '<br />' +
_('Member interfaces with the same metric will be load-balanced.') + '<br />' +
_('Load-balanced member interfaces distribute more traffic out those with higher weights.') + '<br />' +
_('Names may contain characters A-Z, a-z, 0-9, _ and no spaces.') + '<br />' +
_('Names must be 15 characters or less.') + '<br />' +
_('Policies may not share the same name as configured interfaces, members or rules'));
s = m.section(form.GridSection, 'policy');
s.addremove = true;
s.anonymous = false;
s.nodescriptions = true;
/* This name length error check can likely be removed when mwan3 migrates to nftables */
s.renderSectionAdd = function(extra_class) {
var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments),
nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, function(v) {
let sections = [
...uci.sections('mwan3', 'interface'),
...uci.sections('mwan3', 'member'),
...uci.sections('mwan3', 'policy'),
...uci.sections('mwan3', 'rule')
];
for (let j = 0; j < sections.length; j++) {
if (sections[j]['.name'] == v) {
return _('Policies may not share the same name as configured interfaces, members or rules');
}
}
if (v.length > 15) return _('Name length shall not exceed 15 characters');
return true;
}, 'blur', 'keyup');
return el;
};
o = s.option(form.DynamicList, 'use_member', _('Member used'));
var options = uci.sections('mwan3', 'member')
for (var i = 0; i < options.length; i++) {
var value = options[i]['.name'];
o.value(value);
}
o = s.option(form.ListValue, 'last_resort', _('Last resort'),
_('When all policy members are offline use this behavior for matched traffic'));
o.default = 'unreachable';
o.value('unreachable', _('unreachable (reject)'));
o.value('blackhole', _('blackhole (drop)'));
o.value('default', _('default (use main routing table)'));
return m.render();
}
})
@@ -0,0 +1,132 @@
'use strict';
'require form';
'require fs';
'require view';
'require uci';
'require ui';
return view.extend({
load: function() {
return Promise.all([
fs.exec_direct('/usr/libexec/luci-mwan3', ['ipset', 'dump']),
uci.load('mwan3')
]);
},
render: function (data) {
let m, s, o;
m = new form.Map('mwan3', _('MultiWAN Manager - Rules'),
_('Rules specify which traffic will use a particular MWAN policy.') + '<br />' +
_('Rules are based on IP address, port or protocol.') + '<br />' +
_('Rules are matched from top to bottom.') + '<br />' +
_('Rules below a matching rule are ignored.') + '<br />' +
_('Traffic not matching any rule is routed using the main routing table.') + '<br />' +
_('Traffic destined for known (other than default) networks is handled by the main routing table.') + '<br />' +
_('Traffic matching a rule, but all WAN interfaces for that policy are down will be blackholed.') + '<br />' +
_('Names may contain characters A-Z, a-z, 0-9, _ and no spaces.') + '<br />' +
_('Rules may not share the same name as configured interfaces, members or policies.'));
s = m.section(form.GridSection, 'rule');
s.addremove = true;
s.anonymous = false;
s.nodescriptions = true;
s.sortable = true;
/* This name length error check can likely be removed when mwan3 migrates to nftables */
s.renderSectionAdd = function(extra_class) {
const el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments);
const nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, function(v) {
let sections = [
...uci.sections('mwan3', 'interface'),
...uci.sections('mwan3', 'member'),
...uci.sections('mwan3', 'policy'),
...uci.sections('mwan3', 'rule')
];
for (let j = 0; j < sections.length; j++) {
if (sections[j]['.name'] == v) {
return _('Rules may not share the same name as configured interfaces, members or policies.');
}
}
if (v.length > 15) return _('Name length shall not exceed 15 characters');
return true;
}, 'blur', 'keyup');
return el;
};
o = s.option(form.ListValue, 'family', _('Internet Protocol'));
o.default = '';
o.value('', _('IPv4 and IPv6'));
o.value('ipv4', _('IPv4 only'));
o.value('ipv6', _('IPv6 only'));
o.modalonly = true;
o = s.option(form.Value, 'proto', _('Protocol'),
_('View the content of /etc/protocols for protocol description'));
o.default = 'all';
o.rmempty = false;
o.value('all');
o.value('tcp');
o.value('udp');
o.value('icmp');
o.value('esp');
o = s.option(form.Value, 'src_ip', _('Source address'),
_('Supports CIDR notation (eg "192.168.100.0/24") without quotes'));
o.datatype = 'ipaddr';
o = s.option(form.Value, 'src_port', _('Source port'),
_('May be entered as a single or multiple port(s) (eg "22" or "80,443") or as a portrange (eg "1024:2048") without quotes'));
o.depends('proto', 'tcp');
o.depends('proto', 'udp');
o = s.option(form.Value, 'dest_ip', _('Destination address'),
_('Supports CIDR notation (eg "192.168.100.0/24") without quotes'));
o.datatype = 'ipaddr';
o = s.option(form.Value, 'dest_port', _('Destination port'),
_('May be entered as a single or multiple port(s) (eg "22" or "80,443") or as a portrange (eg "1024:2048") without quotes'));
o.depends('proto', 'tcp');
o.depends('proto', 'udp');
o = s.option(form.ListValue, 'sticky', _('Sticky'),
_('Traffic from the same source IP address that previously matched this rule within the sticky timeout period will use the same WAN interface'));
o.default = '0';
o.value('1', _('Yes'));
o.value('0', _('No'));
o.modalonly = true;
o = s.option(form.Value, 'timeout', _('Sticky timeout'),
_('Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set'));
o.datatype = 'range(1, 1000000)';
o.modalonly = true;
o.depends('sticky', '1');
o = s.option(form.Value, 'ipset', _('IPset'),
_('Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg "ipset=/youtube.com/youtube")'));
o.value('', _('-- Please choose --'));
let ipsets = data[0].split(/\n/);
for (let ips of ipsets) {
if (ips.length > 0)
o.value(ips);
}
o.modalonly = true;
o = s.option(form.Flag, 'logging', _('Logging'),
_('Enables firewall rule logging (global mwan3 logging must also be enabled)'));
o.modalonly = true;
o = s.option(form.ListValue, 'use_policy', _('Policy assigned'));
let options = uci.sections('mwan3', 'policy')
for (let opt of options) {
o.value(opt['.name']);
}
o.value('unreachable', _('unreachable (reject)'));
o.value('blackhole', _('blackhole (drop)'));
o.value('default', _('default (use main routing table)'));
return m.render();
}
})
@@ -0,0 +1,22 @@
'use strict';
'require fs';
'require view';
return view.extend({
load: function() {
return L.resolveDefault(fs.exec_direct('/usr/sbin/mwan3', [ 'status' ]),'');
},
render: function (report) {
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
E('h2', _('MultiWAN Manager - Status')),
E('div', { 'class': 'cbi-section' }, [
E('pre', [ report ])
]),
])
},
handleSaveApply: null,
handleSave: null,
handleReset: null
})
@@ -0,0 +1,116 @@
'use strict';
'require fs';
'require uci';
'require dom';
'require ui';
'require view';
return view.extend({
handleCommand: function(exec, args) {
var buttons = document.querySelectorAll('.cbi-button');
for (var i = 0; i < buttons.length; i++)
buttons[i].setAttribute('disabled', 'true');
return fs.exec(exec, args).then(function(res) {
var out = document.querySelector('.command-output');
out.style.display = '';
dom.content(out, [ res.stdout || '', res.stderr || '' ]);
}).catch(function(err) {
ui.addNotification(null, E('p', [ err ]))
}).finally(function() {
for (var i = 0; i < buttons.length; i++)
buttons[i].removeAttribute('disabled');
});
},
handleAction: function(ev) {
var iface = document.getElementById('iface');
var task = document.getElementById('task');
switch (task.value) {
case 'gateway':
return this.handleCommand('/usr/libexec/luci-mwan3',
[ 'diag', 'gateway', iface.value ]);
case 'tracking':
return this.handleCommand('/usr/libexec/luci-mwan3',
[ 'diag', 'tracking', iface.value ]);
case 'rules':
return this.handleCommand('/usr/libexec/luci-mwan3',
[ 'diag', 'rules', iface.value ]);
case 'routes':
return this.handleCommand('/usr/libexec/luci-mwan3',
[ 'diag', 'routes', iface.value ]);
case 'ifup':
return this.handleCommand('/usr/sbin/mwan3',
[ 'ifup', iface.value]);
case 'ifdown':
return this.handleCommand('/usr/sbin/mwan3',
[ 'ifdown', iface.value]);
}
},
load: function() {
return Promise.all([
uci.load('mwan3')
]);
},
render: function () {
var taskSel = [
E('option', { 'value': 'gateway' }, [ _('Ping default gateway') ]),
E('option', { 'value': 'tracking' }, [ _('Ping tracking IP') ]),
E('option', { 'value': 'rules' }, [ _('Check IP rules') ]),
E('option', { 'value': 'routes' }, [ _('Check routing table') ]),
E('option', { 'value': 'ifup' }, [ _('Hotplug ifup') ]),
E('option', { 'value': 'ifdown' }, [ _('Hotplug ifdown') ])
];
var ifaceSel = [E('option', { value: '' }, [_('-- Interface Selection --')])];
var options = uci.sections('mwan3', 'interface')
for (var i = 0; i < options.length; i++) {
ifaceSel.push(E('option', { 'value': options[i]['.name'] }, options[i]['.name']));
}
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
E('h2', {}, [ _('MultiWAN Manager - Diagnostics') ]),
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-section-node' }, [
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, [ _('Interface') ]),
E('div', { 'class': 'cbi-value-field' }, [
E('select', {'class': 'cbi-input-select', 'id': 'iface'},
ifaceSel
)
])
]),
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, [ _('Task') ]),
E('div', { 'class': 'cbi-value-field' }, [
E('select', { 'class': 'cbi-input-select', 'id': 'task' },
taskSel
)
])
])
])
]),
'\xa0',
E('pre', { 'class': 'command-output', 'style': 'display:none' }),
'\xa0',
E('div', { 'class': 'right' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'id': 'execute',
'click': ui.createHandlerFn(this, 'handleAction')
}, [ _('Execute') ]),
]),
]);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
})
@@ -0,0 +1,109 @@
'use strict';
'require poll';
'require view';
'require rpc';
const callMwan3Status = rpc.declare({
object: 'mwan3',
method: 'status',
params: ['section'],
expect: { },
});
function getStatusBackgroundClass(status) {
switch (status) {
case 'online':
return 'label success';
case 'offline':
return 'label warning';
case 'disabled':
return 'label';
case 'notracking':
return 'label';
default:
return 'label';
}
}
function renderMwan3Status(status) {
if (!status.interfaces)
return '<strong>%h</strong>'.format(_('No MWAN interfaces found'));
var tableHtml = '<table class="table cbi-section-table" style="width: 100%;">';
tableHtml += '<thead><tr class="tr cbi-section-table-titles">';
tableHtml += '<th class="th left">' + _('Interface') + '</th>';
tableHtml += '<th class="th left">' + _('Status') + '</th>';
tableHtml += '<th class="th left">' + _('Uptime') + '</th>';
tableHtml += '</tr></thead><tbody>';
for (var iface in status.interfaces) {
var state = '';
var time = '';
var statusType = status.interfaces[iface].status;
switch (statusType) {
case 'online':
state = _('Online');
time = '%t'.format(status.interfaces[iface].online);
break;
case 'offline':
state = _('Offline');
time = '%t'.format(status.interfaces[iface].offline);
break;
case 'notracking':
state = _('No Tracking');
if ((status.interfaces[iface].uptime) > 0) {
time = '%t'.format(status.interfaces[iface].uptime);
} else {
time = '';
}
break;
default:
state = _('Disabled');
time = '';
break;
}
var statusClass = getStatusBackgroundClass(statusType);
tableHtml += '<tr class="tr cbi-section-table-row">';
tableHtml += '<td class="td left"><strong>' + iface + '</strong></td>';
tableHtml += '<td class="td left"><span class="' + statusClass + '">' + state + '</span></td>';
tableHtml += '<td class="td left">' + (time || '') + '</td>';
tableHtml += '</tr>';
}
tableHtml += '</tbody></table>';
return tableHtml;
}
return view.extend({
load: function() {
return Promise.all([
callMwan3Status("interfaces"),
]);
},
render: function (data) {
poll.add(function() {
return callMwan3Status("interfaces").then(function(result) {
var view = document.getElementById('mwan3-service-status');
view.innerHTML = renderMwan3Status(result);
});
});
return E('div', { class: 'cbi-map' }, [
E('h2', [ _('MultiWAN Manager - Overview') ]),
E('div', { class: 'cbi-section' }, [
E('div', { 'id': 'mwan3-service-status' }, [
E('em', { 'class': 'spinning' }, [ _('Collecting data ...') ])
])
])
]);
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});
@@ -0,0 +1,22 @@
'use strict';
'require fs';
'require view';
return view.extend({
load: function() {
return L.resolveDefault(fs.exec_direct('/usr/sbin/mwan3', [ 'internal', 'ipv4' ]),'');
},
render: function (report) {
return E('div', { 'class': 'cbi-map', 'id': 'map' }, [
E('h2', _('MultiWAN Manager - Troubleshooting')),
E('div', { 'class': 'cbi-section' }, [
E('pre', [ report ])
]),
])
},
handleSaveApply: null,
handleSave: null,
handleReset: null
})
@@ -0,0 +1,117 @@
'use strict';
'require baseclass';
'require rpc';
'require uci';
const callMwan3Status = rpc.declare({
object: 'mwan3',
method: 'status',
params: ['section'],
expect: { },
});
function getStatusBackgroundClass(status) {
switch (status) {
case 'online':
return 'label success';
case 'offline':
return 'label warning';
case 'disabled':
return 'label';
case 'notracking':
return 'label';
default:
return 'label';
}
}
return baseclass.extend({
title: _('MultiWAN Manager'),
load: function() {
return uci.load('mwan3').then(function() {
var globals = uci.sections('mwan3', 'globals');
if (!globals || !globals[0] || globals[0].show_overview !== '1')
return null;
return Promise.all([
callMwan3Status("interfaces"),
]);
});
},
render: function (result) {
if (!result)
return null;
if (!result[0]?.interfaces || Object.keys(result[0].interfaces).length === 0)
return null;
// Основной контейнер
var container = E('div', { 'class': 'cbi-section' });
// Таблица с системными классами LuCI
var table = E('table', { 'class': 'table cbi-section-table' });
// Заголовок
var thead = E('tr', { 'class': 'tr cbi-section-table-titles' });
thead.appendChild(E('th', { 'class': 'th left' }, [ _('Interface') ]));
thead.appendChild(E('th', { 'class': 'th left' }, [ _('Status') ]));
thead.appendChild(E('th', { 'class': 'th left' }, [ _('Uptime') ]));
table.appendChild(thead);
// Тело таблицы
var tbody = E('tbody');
for (var iface in result[0].interfaces) {
var state = '';
var time = '';
var statusType = result[0].interfaces[iface].status;
switch (statusType) {
case 'online':
state = _('Online');
time = '%t'.format(result[0].interfaces[iface].online);
break;
case 'offline':
state = _('Offline');
time = '%t'.format(result[0].interfaces[iface].offline);
break;
case 'notracking':
state = _('No Tracking');
if ((result[0].interfaces[iface].uptime) > 0) {
time = '%t'.format(result[0].interfaces[iface].uptime);
} else {
time = '';
}
break;
default:
state = _('Disabled');
time = '';
break;
}
var tr = E('tr', { 'class': 'tr cbi-section-table-row' });
// Ячейка интерфейса
tr.appendChild(E('td', { 'class': 'td left' }, [
E('strong', {}, [ iface ])
]));
// Ячейка статуса с цветным фоном через системные классы label
var statusClass = getStatusBackgroundClass(statusType);
tr.appendChild(E('td', { 'class': 'td left' }, [
E('span', { 'class': statusClass }, [ state ])
]));
// Ячейка времени
tr.appendChild(E('td', { 'class': 'td left' }, [ time || '' ]));
tbody.appendChild(tr);
}
table.appendChild(tbody);
container.appendChild(table);
return container;
}
});
+886
View File
@@ -0,0 +1,886 @@
msgid ""
msgstr ""
"Project-Id-Version: LuCI: mwan3\n"
"POT-Creation-Date: 2017-09-14 16:00+0300\n"
"PO-Revision-Date: 2026-05-02 12:03+0000\n"
"Last-Translator: SnIPeRSnIPeR "
"<snipersniper@users.noreply.hosted.weblate.org>\n"
"Language-Team: Russian <https://hosted.weblate.org/projects/openwrt/"
"luciapplicationsmwan3/ru/>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Weblate 5.17.1\n"
"Project-Info: Это технический перевод, не дословный. Главное-удобный русский "
"интерфейс, все проверялось в графическом режиме, совместим с другими apps\n"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:211
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:227
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:249
msgid "%d hour"
msgstr "%d час"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:206
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:222
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:244
msgid "%d minute"
msgstr "%d минута"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:207
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:208
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:209
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:210
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:223
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:224
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:225
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:226
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:245
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:246
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:247
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:248
msgid "%d minutes"
msgstr "%d минут"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:193
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:200
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:216
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:238
msgid "%d second"
msgstr "%d секунда"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:195
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:201
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:202
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:203
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:204
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:205
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:217
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:218
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:219
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:220
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:221
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:239
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:240
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:241
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:242
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:243
msgid "%d seconds"
msgstr "%d секунд"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:45
msgid ""
"%s: Name of Physical device which interface went up or down (e.g. \"eth0\" "
"or \"wwan0\")"
msgstr ""
"%s: Название физического устройства, интерфейс которого поднялся или упал "
"(прим. \"eth0\" или \"wwan0\")"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:39
msgid "%s: Name of the action that triggered this event"
msgstr "%s: Название действия вызвавшего это событие"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:44
msgid ""
"%s: Name of the interface which went up or down (e.g. \"wan\" or \"wwan\")"
msgstr ""
"%s: Название интерфейса который поднялся или упал (прим. \"wan\" или "
"\"wwan\")"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:40
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:41
msgid "* %s: Is called by netifd and mwan3track"
msgstr "* %s: Вызывается netifd и mwan3track"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:43
msgid "* %s: Is only called by mwan3track if tracking has failed"
msgstr ""
"* %s: Вызывается mwan3track только в том случае, если отслеживание не удалось"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:42
msgid "* %s: Is only called by mwan3track if tracking was successful"
msgstr "* %s: Вызывается mwan3track только в случае успешного отслеживания"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:71
msgid "-- Interface Selection --"
msgstr "-- Выбор интерфейса --"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:109
msgid "-- Please choose --"
msgstr "-- Выберите --"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:99
msgid ""
"Acceptable values: 1-100. This many Tracking IP addresses must respond for "
"the link to be deemed up"
msgstr ""
"Допустимые значения: 1–100. Количество IP-адресов, которое должно ответить "
"чтобы соединение было признано активным"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:62
msgid "Acceptable values: 1-1000. Defaults to 1 if not set"
msgstr "Допустимые значения: 1–1000. По умолчанию 1, если значение не задано"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:58
msgid "Acceptable values: 1-256. Defaults to 1 if not set"
msgstr "Допустимые значения: 1–256 По умолчанию 1, если значение не задано"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:26
msgid "Alert"
msgstr "Тревога"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:37
msgid "Also scan this Routing table for connected networks"
msgstr ""
"Также сканировать эту таблицу маршрутизации на предмет подключённых сетей"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:65
msgid "Check IP rules"
msgstr "Проверить правила IP"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:140
msgid "Check link quality"
msgstr "Проверка качества подключения"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:66
msgid "Check routing table"
msgstr "Проверить таблицу маршрутизации"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:96
msgid "Collecting data ..."
msgstr "Сбор данных ..."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:18
msgid "Contents have been saved."
msgstr "Содержимое сохранено."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:27
msgid "Critical"
msgstr "Критический"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:32
msgid "Debug"
msgstr "Отладка"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:85
msgid "Destination address"
msgstr "Адрес назначения"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:89
msgid "Destination port"
msgstr "Порт назначения"
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:31
msgid "Diagnostics"
msgstr "Диагностика"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:57
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:66
msgid "Disabled"
msgstr "Отключено"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:267
msgid ""
"Downed interface will be deemed up after this many successful ping tests"
msgstr ""
"Отключённый интерфейс будет считаться активным после указанного количество "
"успешных ping проверок"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:41
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:49
msgid "Downtime"
msgstr "Время простоя"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:25
msgid "Emergency"
msgstr "Аварийный"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:92
msgid "Enable ssl tracking"
msgstr "Включить отслеживание SSL"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:55
msgid "Enabled"
msgstr "Включено"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:118
msgid ""
"Enables firewall rule logging (global mwan3 logging must also be enabled)"
msgstr ""
"Включает журналирование правил брандмауэра (также должно быть включено "
"глобальное журналирование mwan3)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:20
msgid "Enables global firewall logging"
msgstr "Включает глобальное журналирование правил брандмауэера"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:93
msgid "Enables https tracking on ssl port 443"
msgstr "Включает отслеживание HTTPS на SSL порту 443"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:15
msgid "Enter value in hex, starting with <code>0x</code>"
msgstr "Введите значение в шестнадцатеричной форме, начиная с <code>0x</code>"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:28
msgid "Error"
msgstr "Ошибка"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:108
msgid "Execute"
msgstr "Выполнить"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:59
msgid "Expect interface state on up event"
msgstr "Ожидать состояние интерфейса при событии подключения интерейса"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:213
msgid "Failure interval"
msgstr "Интервал отказа"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:145
msgid "Failure latency [ms]"
msgstr "Задержка при отказе [мс]"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:158
msgid "Failure packet loss [%]"
msgstr "Потери пакетов при отказе [%]"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:23
msgid "Firewall loglevel"
msgstr "Уровень журналирования брандмауэра"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:14
msgid "Firewall mask"
msgstr "Маска межсетевого экрана"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:280
msgid "Flush conntrack table"
msgstr "Сбрасывать conntrack таблицу"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:281
msgid "Flush global firewall conntrack table on interface events"
msgstr ""
"Сбрасывать глобальную таблицу conntrack межсетевого экрана при событиях "
"интерфейса"
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:59
msgid "Globals"
msgstr "Глобальные"
#: applications/luci-app-mwan3/root/usr/share/rpcd/acl.d/luci-app-mwan3.json:51
msgid "Grant access for luci-app-mwan3 configuration"
msgstr "Предоставить доступ для настройки luci-app-mwan3"
#: applications/luci-app-mwan3/root/usr/share/rpcd/acl.d/luci-app-mwan3.json:3
msgid "Grant access for luci-app-mwan3 status information"
msgstr "Предоставить доступ к информации о состоянии luci-app-mwan3"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:68
msgid "Hotplug ifdown"
msgstr "Hotplug ifdown"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:67
msgid "Hotplug ifup"
msgstr "Hotplug ifup"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:107
msgid "IPset"
msgstr "IPset"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:67
msgid "IPv4"
msgstr "IPv4"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:61
msgid "IPv4 and IPv6"
msgstr "IPv4 и IPv6"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:62
msgid "IPv4 only"
msgstr "Только IPv4"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:68
msgid "IPv6"
msgstr "IPv6"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:63
msgid "IPv6 only"
msgstr "Только IPv6"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:31
msgid "Info"
msgstr "Информация"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:58
msgid "Initial state"
msgstr "Исходное состояние"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:50
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:83
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:65
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:77
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:101
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:67
msgid "Interface"
msgstr "Интерфейс"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:252
msgid "Interface down"
msgstr "Отключение интерфейса"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:266
msgid "Interface up"
msgstr "Включение интерфейса"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:253
msgid "Interface will be deemed down after this many failed ping tests"
msgstr ""
"Интерфейс будет считаться неработающим после заданного количество неудачных "
"пинг-запросов"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:25
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:46
msgid ""
"Interfaces may not share the same name as configured members, policies or "
"rules."
msgstr ""
"Интерфейсы не могут иметь то же имя, что и настроенные элементы, политики "
"или правила."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:65
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:59
msgid "Internet Protocol"
msgstr "Протокол Интернета (IP)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:230
msgid "Keep failure interval"
msgstr "Сохранять интервал отказа"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:231
msgid "Keep ping failure interval during failure state"
msgstr "Сохранять интервал отказа пинг-запроса во время состояния отказа"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:61
msgid "Last resort"
msgstr "Крайнее средство"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:34
msgid "Lines beginning with # are comments and are not executed."
msgstr "Строки, начинающиеся с #, являются комментариями и не выполняются."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:21
msgid ""
"Load-balanced member interfaces distribute more traffic out those with "
"higher weights."
msgstr ""
"Интерфейсы с балансировкой нагрузки распределяют больше трафика между "
"интерфейсами с большим весом."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:19
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:117
msgid "Logging"
msgstr "Журналирование"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:22
msgid "Loglevel"
msgstr "Уровень журналирования"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:127
msgid "Max TTL"
msgstr "Максимальное TTL"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:81
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:90
msgid ""
"May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or "
"as a portrange (eg \"1024:2048\") without quotes"
msgstr ""
"Может быть введено как один или несколько портов (например, «22» или "
"«80,443») или как диапазон портов (например, «1024:2048») без кавычек"
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:75
msgid "Member"
msgstr "Узел"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:19
msgid "Member interfaces with lower metrics are used first."
msgstr "Интерфейсы с более низкими метриками используются в первую очередь."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:20
msgid "Member interfaces with the same metric will be load-balanced."
msgstr "Интерфейсы с одинаковой метрикой будут сбалансированы по нагрузке."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:54
msgid "Member used"
msgstr "Используемый узел"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:18
msgid ""
"Members are profiles attaching a metric and weight to an MWAN interface."
msgstr "Элементы - это профили, прикрепляющие метрику и вес к интерфейсу MWAN."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:20
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:41
msgid ""
"Members may not share the same name as configured interfaces, policies or "
"rules."
msgstr ""
"Элементы не могут иметь одинаковые имена с настроенными интерфейсами, "
"политиками или правилами."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:288
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:57
msgid "Metric"
msgstr "Метрика"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:19
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:3
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:47
msgid "MultiWAN Manager"
msgstr "Менеджер MultiWAN"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:79
msgid "MultiWAN Manager - Diagnostics"
msgstr "Менеджер MultiWAN - Диагностика"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:10
msgid "MultiWAN Manager - Globals"
msgstr "Менеджер MultiWAN - Глобальные"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:21
msgid "MultiWAN Manager - Interfaces"
msgstr "Менеджер MultiWAN - Интерфейсы"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:17
msgid "MultiWAN Manager - Members"
msgstr "Менеджер MultiWAN - Элементы"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:26
msgid "MultiWAN Manager - Notify"
msgstr "Менеджер MultiWAN - Уведомления"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:93
msgid "MultiWAN Manager - Overview"
msgstr "Менеджер MultiWAN - Обзор"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:17
msgid "MultiWAN Manager - Policies"
msgstr "Менеджер MultiWAN - Политики"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:19
msgid "MultiWAN Manager - Rules"
msgstr "Менеджер MultiWAN - Правила"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/detail.js:12
msgid "MultiWAN Manager - Status"
msgstr "Менеджер MultiWAN - Статус"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/troubleshooting.js:12
msgid "MultiWAN Manager - Troubleshooting"
msgstr "Менеджер MultiWAN - Устранение неполадок"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:22
msgid ""
"Mwan3 requires that all interfaces have a unique metric configured in /etc/"
"config/network."
msgstr ""
"Mwan3 требует, чтобы все интерфейсы имели уникальную метрику, настроенную в /"
"etc/config/network."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:49
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:44
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:48
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:53
msgid "Name length shall not exceed 15 characters"
msgstr "Длина имени не должна превышать 15 символов"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:108
msgid ""
"Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg \"ipset=/"
"youtube.com/youtube\")"
msgstr ""
"Имя IPset правила. Требуется правило IPset в /etc/dnsmasq.conf (например "
"«ipset=/youtube.com/youtube»)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:24
msgid "Names may contain characters A-Z, a-z, 0-9, _ and no spaces-"
msgstr "Имена могут содержать символы A-Z, a-z, 0-9, _ и без пробелов и -"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:19
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:22
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:27
msgid "Names may contain characters A-Z, a-z, 0-9, _ and no spaces."
msgstr "Имена могут содержать символы A-Z, a-z, 0-9, _ и без пробелов."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:23
msgid "Names must be 15 characters or less."
msgstr "Имена должны состоять из 15 символов или менее."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:23
msgid "Names must match the interface name found in /etc/config/network."
msgstr "Имена должны совпадать с именем интерфейса из /etc/config/network."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:98
msgid "No"
msgstr "Нет"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:21
msgid "No MWAN interfaces found"
msgstr "Интерфейсы MWAN не найдены"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:44
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:52
msgid "No Tracking"
msgstr "Нет отслеживания"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:296
msgid "No interface metric set!"
msgstr "Не задана метрика интерфейса!"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:31
msgid "Notes:"
msgstr "Примечания:"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:30
msgid "Notice"
msgstr "Уведомление"
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:99
msgid "Notify"
msgstr "Уведомить"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:62
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:38
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:46
msgid "Offline"
msgstr "Отключён"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:61
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:31
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:40
msgid "Online"
msgstr "Онлайн"
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:15
msgid "Overview"
msgstr "Обзор"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:103
msgid "Ping count"
msgstr "Количество пинг-запросов"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:63
msgid "Ping default gateway"
msgstr "Пинг-запрос шлюза по умолчанию"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:198
msgid "Ping interval"
msgstr "Интервал пинг-запроса"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:214
msgid "Ping interval during failure detection"
msgstr "Интервал пинг-запросов во время обнаруженного отказа"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:236
msgid "Ping interval during failure recovering"
msgstr "Интервал пинг-запросов при восстановлении отказа"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:112
msgid "Ping size"
msgstr "Размер пакета пинг-запроса"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:191
msgid "Ping timeout"
msgstr "Время ожидания ответа пинг-запроса"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:64
msgid "Ping tracking IP"
msgstr "Пинг-запрос отслеживаемого IP"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:18
msgid ""
"Policies are profiles grouping one or more members controlling how Mwan3 "
"distributes traffic."
msgstr ""
"Политики - это профили, объединяющие один или несколько элементов, "
"управляющих распределением трафика в Mwan3."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:24
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:45
msgid ""
"Policies may not share the same name as configured interfaces, members or "
"rules"
msgstr ""
"Политики не могут иметь одинаковые имена с настроенными интерфейсами, "
"элементами или правилами"
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:83
msgid "Policy"
msgstr "Политика"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:121
msgid "Policy assigned"
msgstr "Назначенная политика"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:66
msgid "Protocol"
msgstr "Протокол"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:35
msgid ""
"Put your custom mwan3 action here, they will be executed with each netifd "
"hotplug interface event on interfaces for which mwan3 is enabled."
msgstr ""
"Поместите сюда ваши пользовательские действия mwan3, они будут выполняться "
"при каждом событии интерфейса netifd hotplug на интерфейсах, для которых "
"включён mwan3."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:235
msgid "Recovery interval"
msgstr "Интервал восстановления"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:168
msgid "Recovery latency [ms]"
msgstr "Задержка восстановления [мс]"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:181
msgid "Recovery packet loss [%]"
msgstr "Потери пакетов для восстановления [%]"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:39
msgid "Routing table %d"
msgstr "Таблица маршрутизации %d"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:36
msgid "Routing table lookup"
msgstr "Поиск таблицы маршрутизации"
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:91
msgid "Rule"
msgstr "Правило"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:21
msgid "Rules are based on IP address, port or protocol."
msgstr "Правила основаны на IP-адресе, порте или протоколе."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:22
msgid "Rules are matched from top to bottom."
msgstr "Правила сопоставляются сверху вниз."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:23
msgid "Rules below a matching rule are ignored."
msgstr "Правила, находящиеся ниже соответствующего правила, игнорируются."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:28
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:50
msgid ""
"Rules may not share the same name as configured interfaces, members or "
"policies."
msgstr ""
"Правила не могут иметь одинаковые имена с настроенными интерфейсами, "
"элементами или политиками."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:20
msgid "Rules specify which traffic will use a particular MWAN policy."
msgstr ""
"Правила определяют, какой трафик будет использовать определённую политику "
"MWAN."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:102
msgid "Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set"
msgstr ""
"Секунды. Допустимые значения: 1–1000000. По умолчанию 600, если значение не "
"установлено"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:76
msgid "Source address"
msgstr "Адрес источника"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:80
msgid "Source port"
msgstr "Порт источника"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:66
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:83
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:107
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:23
msgid "Status"
msgstr "Статус"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:94
msgid "Sticky"
msgstr "Режим Sticky"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:101
msgid "Sticky timeout"
msgstr "Время ожидания режима Sticky"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:77
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:86
msgid "Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"
msgstr "Поддерживает CIDR нотацию (например «192.168.100.0/24») без кавычек"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/diagnostics.js:91
msgid "Task"
msgstr "Задача"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:29
msgid "The file is also preserved during sysupgrade."
msgstr "Этот файл также сохраняется при обновлении системы."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:33
msgid ""
"The first line of the script must be &#34;#!/bin/sh&#34; without quotes."
msgstr "Первая строка скрипта должна быть &#34;#!/bin/sh&#34; без кавычек."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:37
msgid ""
"There are three main environment variables that are passed to this script."
msgstr "В этот сценарий передаются три основные переменные среды окружения."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:289
msgid ""
"This displays the metric assigned to this interface in /etc/config/network"
msgstr ""
"Здесь отображается метрика, назначенная этому интерфейсу в файле /etc/config/"
"network"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:32
msgid "This file is interpreted as a shell script."
msgstr "Этот файл интерпретируется как shell-скрипт."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:72
msgid ""
"This hostname or IP address will be pinged to determine if the link is up or "
"down. Leave blank to assume interface is always online"
msgstr ""
"Имя хоста или IP-адрес для пинг-запроса, чтобы определить активно соединение "
"или нет. Оставьте пустым, чтобы указать, что интерфейс всегда в сети"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:28
msgid "This section allows you to modify the content of \"/etc/mwan3.user\"."
msgstr "Этот раздел позволяет изменять содержимое файла \"/etc/mwan3.user\"."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:71
msgid "Tracking hostname or IP address"
msgstr "Отслеживамое имя хоста или IP-адрес"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:76
msgid "Tracking method"
msgstr "Метод отслеживания"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:98
msgid "Tracking reliability"
msgstr "Надёжность отслеживания"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:25
msgid ""
"Traffic destined for known (other than default) networks is handled by the "
"main routing table."
msgstr ""
"Трафик, предназначенный для известных (кроме стандартных) сетей, "
"обрабатывается основной таблицей маршрутизации."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:95
msgid ""
"Traffic from the same source IP address that previously matched this rule "
"within the sticky timeout period will use the same WAN interface"
msgstr ""
"Трафик с того же IP-адреса источника, который ранее соответствовал этому "
"правилу в период времени ожидания режима Sticky, будет использовать тот же "
"интерфейс WAN"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:26
msgid ""
"Traffic matching a rule, but all WAN interfaces for that policy are down "
"will be blackholed."
msgstr ""
"Трафик, соответствующий правилу, но все интерфейсы WAN для этой политики не "
"работают, будет заблокирован."
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:24
msgid "Traffic not matching any rule is routed using the main routing table."
msgstr ""
"Трафик, не соответствующий какому-либо правилу, направляется по основной "
"таблице маршрутизации."
#: applications/luci-app-mwan3/root/usr/share/luci/menu.d/luci-app-mwan3.json:39
msgid "Troubleshooting"
msgstr "Устранение неполадок"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/notify.js:20
msgid "Unable to save contents: %s"
msgstr "Не удалось сохранить содержимое: %s"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:34
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/status/overview.js:48
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:43
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/status/include/90_mwan3.js:56
msgid "Uptime"
msgstr "Время работы"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:67
msgid "View the content of /etc/protocols for protocol description"
msgstr "Просмотр содержимого файла /etc/protocols для описания протокола"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/globals.js:29
msgid "Warning"
msgstr "Предупреждение"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/member.js:61
msgid "Weight"
msgstr "Вес"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:62
msgid ""
"When all policy members are offline use this behavior for matched traffic"
msgstr ""
"Когда все члены политики находятся в автономном режиме, используйте это "
"поведение для сопоставляемого трафика"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:97
msgid "Yes"
msgstr "Да"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:65
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:127
msgid "blackhole (drop)"
msgstr "blackhole (отбросить)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:284
msgid "connected (mwan3)"
msgstr "подключено (connected, mwan3)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:66
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:128
msgid "default (use main routing table)"
msgstr "default (использовать основную таблицу маршрутизации)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:285
msgid "disconnected (mwan3)"
msgstr "отключено (disconnected, mwan3)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:283
msgid "ifdown (netifd)"
msgstr "отключено (ifdown, netifd)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/interface.js:282
msgid "ifup (netifd)"
msgstr "подключено (ifup, netifd)"
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/policy.js:64
#: applications/luci-app-mwan3/htdocs/luci-static/resources/view/mwan3/network/rule.js:126
msgid "unreachable (reject)"
msgstr "unreachable (отклонить)"
msgid "Show on overview"
msgstr "Показать на главной"
msgid "Show MultiWAN status section on the overview page"
msgstr "Показывать секцию состояния MultiWan на главной странице"
msgid "No available interfaces"
msgstr "Нет доступных интерфейсов"
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
uci -q get mwan3.globals >/dev/null || {
uci -q add mwan3 globals >/dev/null
uci -q rename mwan3.@globals[-1]="globals" >/dev/null
uci -q set mwan3.globals.local_source="none" >/dev/null
uci commit mwan3
}
exit 0
+199
View File
@@ -0,0 +1,199 @@
#!/bin/sh
#
# Copyright (C) 2021 TDT AG <development@tdt.de>
#
# This is free software, licensed under the GNU General Public License v2.
# See https://www.gnu.org/licenses/gpl-2.0.txt for more information.
#
. /lib/functions.sh
. /lib/functions/network.sh
. /usr/share/libubox/jshn.sh
IIF=1000
FWMARK=2000
ID=0
usage() {
local status="$1"
local msg="$2"
if [ -n "$msg" ]; then
echo "$msg"
echo ""
fi
echo "Usage: $(basename "$0") <command>"
echo "command:"
echo " diag: diagnostic commands"
echo " nftset: nft set commands"
echo ""
echo "diag <command> <iface>"
echo "command:"
echo " gateway <iface>: ping interface gateway"
echo " tracking <iface>: ping interface tracking targets"
echo " rules <iface>: check interface routing rules"
echo " routes <iface>: check interface routing tables"
echo ""
echo "nftset <command>"
echo "command:"
echo " dump: show all configured nft set names"
exit "$status"
}
diag_gateway() {
local iface="$1"
local gw
network_get_gateway gw "${iface}"
[ -z "$gw" ] && network_get_gateway gw "${iface}_4"
[ -z "$gw" ] && {
echo "No gateway for interface ${iface} found."
exit 2
}
mwan3 use "$iface" "ping" "-c" "5" "-W" "1" "$gw"
}
diag_tracking() {
local iface="$1"
checkips() {
local ip="$1"
local iface="$2"
mwan3 use "$iface" "ping" "-c" "5" "-W" "1" "$ip"
}
config_load mwan3
config_list_foreach "$iface" "track_ip" checkips "$iface"
}
iface_number() {
local cfg="$1"
local iface="$2"
let number++
[ "$cfg" = "$iface" ] && {
ID="$number"
}
}
diag_rules() {
local iface="$1"
local number=0
local iif=0
local fwmark=0
local iif_rule iif_result
local fwmark_rule fwmark_result
config_load mwan3
config_foreach iface_number 'interface' "$iface"
[ "$ID" = "0" ] && {
echo "Unable to get mwan3 interface number for \"$iface\"."
exit 2
}
let "iif=$IIF+$ID"
let "fwmark=$FWMARK+$ID"
iif_rule="$(ip rule | grep ${iif})"
iif_result="$?"
fwmark_rule="$(ip rule | grep ${fwmark})"
fwmark_result="$?"
if [ "$fwmark_result" = 0 ] && [ "$iif_result" = 0 ]; then
echo "All required IP rules for interface \"$iface\" found"
echo "$fwmark_rule"
echo "$iif_rule"
elif [ "$fwmark_result" = 1 ] && [ "$iif_result" = 0 ]; then
echo "Only iif IP rule for interface \"$iface\" found"
echo "$iif_rule"
elif [ "$fwmark_result" = 0 ] && [ "$iif_result" = 1 ]; then
echo "Only fwmark IP rule for interface \"$iface\" found"
echo "$fwmark_rule"
else
echo "Missing fwmark and iif IP rule for interface \"$iface\""
fi
}
diag_routes() {
local iface="$1"
local table table_result
config_load mwan3
config_foreach iface_number 'interface' "$iface"
[ "$ID" = "0" ] && {
echo "Unable to get mwan3 interface number for \"$iface\"."
exit 2
}
table="$(ip route list table $ID)"
table_result="$?"
if [ "$table_result" = 0 ]; then
echo "Routing table \"$ID\" for interface \"$iface\" found"
echo "$table"
else
echo "Routing table \"$ID\" for interface \"$iface\" not found"
fi
}
diag_cmd() {
case "$1" in
gateway)
diag_gateway "$2"
;;
tracking)
diag_tracking "$2"
;;
rules)
diag_rules "$2"
;;
routes)
diag_routes "$2"
;;
*)
usage "1" "Command not supported"
;;
esac
}
nftset_dump() {
nft -a list table inet mwan3 2>/dev/null | awk '/^\tset / && !/^\tset mwan3_/ {print $2}' | sort -u
}
nftset_cmd() {
case "$1" in
dump)
nftset_dump
;;
*)
usage "1" "Command not supported"
;;
esac
}
main () {
case "$1" in
diag)
diag_cmd "$2" "$3"
;;
nftset)
nftset_cmd "$2"
;;
*)
usage "1" "Command not supported"
;;
esac
}
main "$@"
@@ -0,0 +1,106 @@
{
"admin/status/mwan3": {
"title": "MultiWAN Manager",
"order": "600",
"action": {
"type": "firstchild"
},
"depends": {
"acl": [
"luci-app-mwan3-status"
]
}
},
"admin/status/mwan3/overview": {
"title": "Overview",
"order": 10,
"action": {
"type": "view",
"path": "mwan3/status/overview"
}
},
"admin/status/mwan3/detail": {
"title": "Status",
"order": 20,
"action": {
"type": "view",
"path": "mwan3/status/detail"
}
},
"admin/status/mwan3/diagnostics": {
"title": "Diagnostics",
"order": 30,
"action": {
"type": "view",
"path": "mwan3/status/diagnostics"
}
},
"admin/status/mwan3/troubleshooting": {
"title": "Troubleshooting",
"order": 40,
"action": {
"type": "view",
"path": "mwan3/status/troubleshooting"
}
},
"admin/network/mwan3": {
"title": "MultiWAN Manager",
"order": "600",
"action": {
"type": "firstchild"
},
"depends": {
"acl": [
"luci-app-mwan3"
]
}
},
"admin/network/mwan3/globals": {
"title": "Globals",
"order": 10,
"action": {
"type": "view",
"path": "mwan3/network/globals"
}
},
"admin/network/mwan3/interface": {
"title": "Interface",
"order": 20,
"action": {
"type": "view",
"path": "mwan3/network/interface"
}
},
"admin/network/mwan3/member": {
"title": "Member",
"order": 30,
"action": {
"type": "view",
"path": "mwan3/network/member"
}
},
"admin/network/mwan3/policy": {
"title": "Policy",
"order": 40,
"action": {
"type": "view",
"path": "mwan3/network/policy"
}
},
"admin/network/mwan3/rule": {
"title": "Rule",
"order": 50,
"action": {
"type": "view",
"path": "mwan3/network/rule"
}
},
"admin/network/mwan3/notify": {
"title": "Notify",
"order": 60,
"action": {
"type": "view",
"path": "mwan3/network/notify"
}
}
}
@@ -0,0 +1,94 @@
{
"luci-app-mwan3-status": {
"description": "Grant access for luci-app-mwan3 status information",
"read": {
"cgi-io": [
"exec"
],
"file": {
"/usr/sbin/mwan3 status": [
"exec"
]
},
"ubus": {
"mwan3": [
"status"
]
}
},
"write": {
"file": {
"/usr/libexec/luci-mwan3 diag gateway *": [
"exec"
],
"/usr/libexec/luci-mwan3 diag tracking *": [
"exec"
],
"/usr/libexec/luci-mwan3 diag rules *": [
"exec"
],
"/usr/libexec/luci-mwan3 diag routes *": [
"exec"
],
"/usr/sbin/mwan3 internal ipv4": [
"exec"
],
"/usr/sbin/mwan3 ifup *": [
"exec"
],
"/usr/sbin/mwan3 ifdown *": [
"exec"
]
},
"ubus": {
"file": [
"exec"
]
}
}
},
"luci-app-mwan3": {
"description": "Grant access for luci-app-mwan3 configuration",
"read": {
"cgi-io": [
"exec"
],
"file": {
"/etc/mwan3.user": [
"read"
],
"/usr/bin/httping": [
"list"
],
"/usr/bin/nping": [
"list"
],
"/usr/bin/arping": [
"list"
],
"/usr/libexec/luci-mwan3 ipset dump": [
"exec"
]
},
"ubus": {
"mwan3": [
"status"
]
},
"uci": [
"mwan3",
"network"
]
},
"write": {
"file": {
"/etc/mwan3.user": [
"write"
]
},
"uci": [
"mwan3"
]
}
}
}
+13 -2
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mwan3-ledhelper
PKG_VERSION:=0.0.1
PKG_RELEASE:=1
PKG_VERSION:=0.0.2
PKG_RELEASE:=2
PKG_MAINTAINER:=Konstantine Shevlakov <shevlakov@132lan.ru>
include $(INCLUDE_DIR)/package.mk
@@ -13,6 +13,12 @@ define Package/$(PKG_NAME)
DEPENDS:=+mwan3
endef
define Package/$(PKG_NAME)-nft
PKGARCH:=all
TITLE:=MWAN3 Led Helper (nft variant)
DEPENDS:=+mwan3-nft
endef
define Package/$(PKG_NAME)/description
Hotplug script to indicate led for mwan3 link states
endef
@@ -31,5 +37,10 @@ define Package/$(PKG_NAME)/install
$(CP) ./root/* $(1)/
endef
define Package/$(PKG_NAME)-nft/install
$(CP) ./root/* $(1)/
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
$(eval $(call BuildPackage,$(PKG_NAME)-nft))
+2 -2
View File
@@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=natflow
PKG_VERSION:=20260531
PKG_RELEASE:=30
PKG_RELEASE:=31
PKG_SOURCE:=$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/ptpt52/natflow.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=e75d2a375835d1d158604864199669343bdcdac6
PKG_SOURCE_VERSION:=834324456603e21efc73521fa6b87dc0cbac7e30
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_MAINTAINER:=Chen Minqiang <ptpt52@gmail.com>
PKG_LICENSE:=GPL-2.0
Executable → Regular
+1 -1
View File
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=pcie_mhi
PKG_VERSION:=1.3.8
PKG_RELEASE:=28
PKG_RELEASE:=29
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk