You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
849 lines
21 KiB
849 lines
21 KiB
|
|
/*
|
|
* All required uci packages are stored variable uci.
|
|
* The GUI code displayes and manipulated this variable.
|
|
*/
|
|
var uci = {};
|
|
var wifi_status = {};
|
|
|
|
var gid = 0;
|
|
var net_options = [['LAN', 'lan'], ['Freifunk', 'freifunk'], ['Mesh', 'mesh'], ['WAN', 'wan'], ['None', 'none']];
|
|
var txpower_choices = [
|
|
['20 dBm (100 mW)', '20'],
|
|
['19 dBm (79 mW)', '19'],
|
|
['18 dBm (63 mW)', '18'],
|
|
['17 dBm (50 mW)', '17'],
|
|
['16 dBm (39 mW)', '16'],
|
|
['15 dBm (31 mW)', '15'],
|
|
['14 dBm (25 mW)', '14'],
|
|
['13 dBm (19 mW)', '13'],
|
|
['12 dBm (15 mW)', '12'],
|
|
['11 dBm (12 mW)', '11'],
|
|
['10 dBm (10 mW)', '10'],
|
|
['9 dBm (7 mW)', '9'],
|
|
['8 dBm (6 mW)', '8'],
|
|
['6 dBm (5 mW)', '6'],
|
|
['5 dBm (3 mW)', '5'],
|
|
['4 dBm (2 mW)', '4'],
|
|
['0 dBm (1 mW)', '0'],
|
|
['auto', 'auto']
|
|
];
|
|
|
|
function init()
|
|
{
|
|
send('/cgi-bin/misc', { func : 'wifi_status' }, function(data) {
|
|
wifi_status = JSON.parse(data);
|
|
send('/cgi-bin/network', { func : 'get_settings' }, function(data) {
|
|
uci = fromUCI(data);
|
|
rebuild_other();
|
|
rebuild_assignment();
|
|
rebuild_wifi();
|
|
rebuild_switches();
|
|
adv_apply();
|
|
tr();
|
|
});
|
|
});
|
|
}
|
|
|
|
function updateFrom(src)
|
|
{
|
|
var obj = {};
|
|
collect_inputs(src, obj);
|
|
for (var name in obj) {
|
|
var value = obj[name];
|
|
var path = name.split('#');
|
|
|
|
var pkg = path[0];
|
|
var sec = path[1];
|
|
var opt = path[2];
|
|
|
|
uci[pkg].pchanged = true;
|
|
uci[pkg][sec][opt] = value
|
|
}
|
|
}
|
|
|
|
function getChangeModeAction(ifname)
|
|
{
|
|
return function(e) {
|
|
var src = (e.target || e.srcElement);
|
|
var mode = (src.data || src.value);
|
|
delNetSection(ifname);
|
|
addNetSection(ifname, mode);
|
|
};
|
|
}
|
|
|
|
function appendSetting(p, path, value, mode)
|
|
{
|
|
var id = path.join('#');
|
|
var b;
|
|
var cfg = path[0]
|
|
var name = path[path.length-1];
|
|
switch (name)
|
|
{
|
|
case 'country':
|
|
b = append_input(p, 'tr_country', id, value);
|
|
b.lastChild.classList.add('adv_disable');
|
|
break;
|
|
case 'channel':
|
|
var channels = [1,2,3,4,5,6,7,8,9,10,11,12];
|
|
if (value > 35) channels = [36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140];
|
|
b = append_selection(p, 'tr_channel', id, value, channels);
|
|
b.lastChild.classList.add('adv_disable');
|
|
addHelp(b, 'tr_channel_help' );
|
|
break;
|
|
case 'txpower':
|
|
value = value ? value : 'undefined';
|
|
b = append_selection(p, 'tr_transmission_power', id, value, txpower_choices);
|
|
addHelp(b, 'tr_transmission_power_help');
|
|
b.classList.add('adv_hide');
|
|
break;
|
|
case 'mode':
|
|
if (!inArray(mode, ['wan', 'none']))
|
|
return;
|
|
b = append_selection(p, 'tr_mode', id, value, [['Client', 'sta'],['AccessPoint', 'ap']]);
|
|
addHelp(b, 'tr_mode_help');
|
|
break;
|
|
case 'encryption':
|
|
if (!inArray(mode, ['wan', 'lan', 'none']))
|
|
return;
|
|
b = append_selection(p, 'tr_encryption', id, value, [['None', 'none'],['WPA', 'psk'], ['WPA2', 'psk2']]);
|
|
break;
|
|
case 'key':
|
|
if (!inArray(mode, ['wan', 'lan', 'none']))
|
|
return;
|
|
b = append_input(p, 'tr_password', id, value);
|
|
addInputCheck(b.lastChild, /^[\S]{8,32}$/, 'tr_password_format');
|
|
break;
|
|
case 'hwmode':
|
|
if (value == '11g') {
|
|
value = '802.11g (2.4 GHz)';
|
|
} else if (value == '11a') {
|
|
value = '802.11a (5 GHz)';
|
|
} else {
|
|
value = '802.' + value;
|
|
}
|
|
b = append_label(p, 'tr_mode', value);
|
|
break;
|
|
case 'mesh_id':
|
|
b = append_input(p, 'tr_mesh_id', id, value);
|
|
if (!inArray(mode, ['wan', 'lan', 'none']))
|
|
b.lastChild.classList.add('adv_disable');
|
|
addInputCheck(b.lastChild, /^[^\x00-\x1F\x80-\x9F]{3,30}$/, 'tr_invalid_input');
|
|
break;
|
|
case 'ssid':
|
|
b = append_input(p, 'tr_ssid', id, value);
|
|
if (!inArray(mode, ['wan', 'lan', 'none']))
|
|
b.lastChild.classList.add('adv_disable');
|
|
addInputCheck(b.lastChild, /^[^\x00-\x1F\x80-\x9F]{3,30}$/, 'tr_invalid_input');
|
|
break;
|
|
/*
|
|
case 'macaddr':
|
|
if (path[1] != 'freifunk') return;
|
|
b = append_input(p, 'tr_mac_address', id, value);
|
|
addInputCheck(b.lastChild,/^((([0-9a-f]{2}:){5}([0-9a-f]{2}))|)$/, 'tr_invalid_mac');
|
|
addHelp(b, 'tr_mac_address_help');
|
|
break;
|
|
*/
|
|
case 'mesh_on_wan':
|
|
b = append_radio(p, 'tr_mesh_on_wan', id, value, [['tr_yes', '1'], ['tr_no', '0']]);
|
|
onDesc(b, 'INPUT', function(e) {
|
|
e.onclick = function(e) {
|
|
var src = (e.target || e.srcElement);
|
|
var val = (src.data || src.value);
|
|
if (val != value) {
|
|
if (val == '1') {
|
|
uci.network['wan_mesh'] = {stype:'interface', ifname : '@wan', proto : 'batadv_hardif', master : 'bat0'};
|
|
} else {
|
|
delete uci.network['wan_mesh'];
|
|
}
|
|
uci.network.pchanged = true;
|
|
}
|
|
}
|
|
});
|
|
addHelp(b, 'tr_mesh_on_lan_help');
|
|
break;
|
|
case 'disabled':
|
|
b = append_radio(p, 'tr_disabled', id, value, [['tr_yes', '1'], ['tr_no', '0']]);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
b.id = id; // Needed for updateFrom.
|
|
b.onchange = function() {
|
|
updateFrom(b);
|
|
};
|
|
|
|
return b;
|
|
}
|
|
|
|
function getInterfaceMode(ifname)
|
|
{
|
|
var n = uci.network;
|
|
|
|
if (inArray(ifname, split(n.freifunk.ifname)))
|
|
return 'freifunk';
|
|
|
|
if (inArray(ifname, split(n.lan.ifname)))
|
|
return 'lan';
|
|
|
|
if (inArray(ifname, split(n.wan.ifname)))
|
|
return 'wan';
|
|
|
|
if (config_find(n, {'ifname' : ifname, 'proto' : 'batadv_hardif'}))
|
|
return 'mesh';
|
|
|
|
return 'none';
|
|
}
|
|
|
|
function getWifiMode(id)
|
|
{
|
|
var obj = uci.wireless[id];
|
|
|
|
if (obj.network == 'freifunk') return 'freifunk';
|
|
if (obj.network == 'lan') return 'lan';
|
|
if (obj.network == 'wan') return 'wan';
|
|
if (obj.mode == 'mesh') return 'mesh';
|
|
|
|
return 'none';
|
|
}
|
|
|
|
function rebuild_other()
|
|
{
|
|
var root = $('other');
|
|
removeChilds(root);
|
|
hide(root);
|
|
|
|
var fs = append_section(root, 'tr_other');
|
|
|
|
if ('network' in uci) {
|
|
var n = uci['network'];
|
|
appendSetting(fs, ['network', 'freifunk', 'macaddr'], n['freifunk']['macaddr']);
|
|
}
|
|
|
|
if ('freifunk' in uci) {
|
|
var f = uci.freifunk;
|
|
var i = firstSectionID(f, 'settings');
|
|
appendSetting(fs, ['freifunk', i, 'mesh_on_wan'], f[i]['mesh_on_wan']);
|
|
}
|
|
|
|
root.classList.add('adv_hide');
|
|
}
|
|
|
|
function rebuild_assignment()
|
|
{
|
|
var root = $('assignment');
|
|
removeChilds(root);
|
|
hide(root);
|
|
|
|
var fs = append_section(root, 'tr_ports');
|
|
addHelp(fs, 'tr_individual_ports');
|
|
|
|
var ignore = ['local-node', 'fastd_mesh', 'bat0', 'lo'];
|
|
var ifnames = [];
|
|
|
|
// remove dummy-interface
|
|
switch (uci.misc.data.model) {
|
|
case 'tp-link-tl-wr941n-nd-v1':
|
|
case 'tp-link-tl-wr941n-nd-v2':
|
|
case 'tp-link-tl-wr941n-nd-v3':
|
|
ignore.push('eth0');
|
|
}
|
|
|
|
// Collect all interfaces.
|
|
config_foreach(uci.network, 'interface', function(sid, sobj) {
|
|
if (sobj.ifname) ifnames = ifnames.concat(split(sobj.ifname));
|
|
});
|
|
|
|
// Ignore switch interfaces.
|
|
config_foreach(uci.network, 'switch', function(sid, sobj) {
|
|
var swinfo = collect_switch_info(sobj.name);
|
|
config_foreach(uci.network, 'switch_vlan', function(vid, vobj) {
|
|
ignore.push(getInterfaceName(vid, swinfo));
|
|
});
|
|
});
|
|
|
|
// Ignore wlan interfaces.
|
|
config_foreach(uci.wireless, 'wifi-iface', function(sid, sobj) {
|
|
if (sobj.ifname) ignore.push(sobj.ifname);
|
|
});
|
|
|
|
ifnames = uniq(ifnames);
|
|
ifnames.sort();
|
|
for (var i in ifnames)
|
|
{
|
|
var ifname = ifnames[i];
|
|
if ((ifname.length == 0) || inArray(ifname, ignore) || ifname[0] == '@' ) {
|
|
continue;
|
|
}
|
|
var mode = getInterfaceMode(ifname);
|
|
var entry = append_selection(fs, ifname, 'set_mode_'+ifname, mode, net_options);
|
|
entry.onchange = getChangeModeAction(ifname);
|
|
show(root);
|
|
}
|
|
}
|
|
|
|
function collect_wifi_info(device)
|
|
{
|
|
var modes = [];
|
|
config_foreach(uci.wireless, 'wifi-iface', function(id, obj) {
|
|
if (device == obj.device)
|
|
modes.push(getWifiMode(id));
|
|
});
|
|
return {'modes' : modes};
|
|
}
|
|
|
|
function modeName(mode) {
|
|
for (var i in net_options) {
|
|
if (net_options[i][1] == mode) {
|
|
return net_options[i][0];
|
|
}
|
|
}
|
|
return mode;
|
|
}
|
|
|
|
function addNetSection(ifname, mode)
|
|
{
|
|
var n = uci.network;
|
|
|
|
switch (mode) {
|
|
case 'wan':
|
|
n.wan.ifname = addItem(n.wan.ifname, ifname);
|
|
break;
|
|
case 'lan':
|
|
n.lan.ifname = addItem(n.lan.ifname, ifname);
|
|
break;
|
|
case 'freifunk':
|
|
n.freifunk.ifname = addItem(n.freifunk.ifname, ifname);
|
|
break;
|
|
case 'mesh':
|
|
var net = ifname.replace('.', '_');
|
|
n[net] = {stype: 'interface',ifname: ifname,mtu: '1406',proto: 'batadv_hardif',master: 'bat0'};
|
|
break;
|
|
case 'none':
|
|
var net = ifname.replace('.', '_');
|
|
n[net] = {stype: 'interface',ifname: ifname,proto: 'none'};
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
n.pchanged = true;
|
|
}
|
|
|
|
function delNetSection(ifname)
|
|
{
|
|
var n = uci.network;
|
|
|
|
config_foreach(n, 'interface', function(id, obj) {
|
|
if (obj.ifname == ifname && !inArray(id, ['wan', 'lan', 'freifunk']))
|
|
delete n[id];
|
|
});
|
|
|
|
n.wan.ifname = removeItem(n.wan.ifname, ifname);
|
|
n.lan.ifname = removeItem(n.lan.ifname, ifname);
|
|
n.freifunk.ifname = removeItem(n.freifunk.ifname, ifname);
|
|
|
|
n.pchanged = true;
|
|
}
|
|
|
|
function randomString(length) {
|
|
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
|
|
var str = '';
|
|
for (var i = 0; i < length; i++) {
|
|
var rnum = Math.floor(Math.random() * chars.length);
|
|
str += chars.substring(rnum,rnum+1);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
function addWifiSection(device, mode)
|
|
{
|
|
var w = uci.wireless;
|
|
var n = uci.network;
|
|
var s = config_find(uci.freifunk, {'stype' : 'settings'});
|
|
var ifname = device+'_'+mode;
|
|
|
|
// Add section to /etc/config/wireless
|
|
switch (mode)
|
|
{
|
|
case 'wan':
|
|
// Only works if interface is not in a bridge!
|
|
w[ifname] = {device: device,stype: 'wifi-iface',mode: 'sta',ssid: 'OtherNetwork',key: 'password_for_OtherNetwork',encryption: 'psk2', network: 'wan'};
|
|
break;
|
|
case 'mesh':
|
|
var net = ifname.replace('.', '_');
|
|
// 802.11s
|
|
w[ifname] = {device: device, stype: 'wifi-iface',mode: 'mesh',mesh_id: s.default_mesh_id,mesh_fwding: 0,network: net};
|
|
// Connected via option network
|
|
n[net] = {stype: 'interface',mtu: '1532',proto: 'batadv_hardif',master: 'bat0'};
|
|
n.pchanged = true;
|
|
break;
|
|
case 'freifunk':
|
|
w[ifname] = {device: device,stype: 'wifi-iface',mode:'ap',ssid: (s.community+'.freifunk.net'),network: 'freifunk'};
|
|
break;
|
|
case 'lan':
|
|
w[ifname] = {device: device,stype: 'wifi-iface',mode:'ap',ssid: 'MyNetwork',key: randomString(10),encryption: 'psk2',network: 'lan'};
|
|
break;
|
|
default:
|
|
return alert('mode error \''+mode+'\' '+device);
|
|
}
|
|
|
|
w.pchanged = true;
|
|
}
|
|
|
|
function delWifiSection(dev, mode)
|
|
{
|
|
var w = uci.wireless;
|
|
var n = uci.network;
|
|
|
|
config_foreach(w, 'wifi-iface', function(id, obj) {
|
|
if (obj.device == dev && getWifiMode(id) == mode) {
|
|
if (mode == 'mesh') {
|
|
delete n[obj.network];
|
|
n.pchanged = true;
|
|
}
|
|
delete w[id];
|
|
w.pchanged = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
function getWifiInterfaceState(dev, wid) {
|
|
var obj = wifi_status[dev];
|
|
|
|
if (!obj.up) {
|
|
return 'tr_inactive';
|
|
}
|
|
|
|
var interfaces = obj['interfaces'];
|
|
for (var i = 0; interfaces && i < interfaces.length; i++) {
|
|
var e = interfaces[i];
|
|
if (e.section == wid) {
|
|
return ('ifname' in e) ? 'tr_active' : 'tr_error';
|
|
}
|
|
}
|
|
return 'tr_unknown';
|
|
}
|
|
|
|
function countWifi(mode, wmode) {
|
|
var n = 0;
|
|
config_foreach(uci.wireless, 'wifi-iface', function(wid, wobj) {
|
|
if (wmode && wobj['mode'] != wmode) {
|
|
return;
|
|
}
|
|
if (getWifiMode(wid) == mode) n++;
|
|
});
|
|
return n;
|
|
}
|
|
|
|
function countOther(mode) {
|
|
return split(uci['network'][mode]['ifname']).length;
|
|
}
|
|
|
|
// Make sure we use only one interface for WAN
|
|
// when using WAN of Wifi. Otherwise it won't work.
|
|
function setWanMode(mode) {
|
|
var changed = (uci['network']['wan']['mode'] == mode);
|
|
if (mode == 'static' || mode == 'bridge') {
|
|
uci['network']['wan']['mode'] = mode;
|
|
uci['network'].pchanged = changed;
|
|
}
|
|
}
|
|
|
|
function rebuild_wifi()
|
|
{
|
|
var root = $('wireless');
|
|
removeChilds(root);
|
|
|
|
// Print wireless sections.
|
|
config_foreach(uci.wireless, 'wifi-device', function(dev, obj) {
|
|
var fs = append_section(root, 'Wireless \''+dev+'\'', dev);
|
|
var info = collect_wifi_info(dev);
|
|
|
|
for (var sid in obj)
|
|
appendSetting(fs, ['wireless', dev, sid], obj[sid]);
|
|
|
|
var mode_checks = append_check(fs, 'Mode', dev+'_mode', info.modes, [['LAN','lan', 'tr_lan_help'], ['Freifunk','freifunk', 'tr_freifunk_help'], ['Mesh', 'mesh', 'tr_mesh_help'], ['WAN', 'wan', 'tr_wan_help']]);
|
|
var parent = append(fs, 'div');
|
|
|
|
// Print wireless interfaces.
|
|
config_foreach(uci.wireless, 'wifi-iface', function(wid, wobj) {
|
|
if (wobj.device != dev) return;
|
|
|
|
var mode = getWifiMode(wid);
|
|
var title = (mode == 'none') ? '\''+wobj.network+'\'' : modeName(mode);
|
|
var entry = append_section(parent, title, 'wireless_'+dev+'_'+mode);
|
|
|
|
for (var opt in wobj)
|
|
appendSetting(entry, ['wireless', wid, opt], wobj[opt], mode);
|
|
|
|
var state = getWifiInterfaceState(dev, wid);
|
|
var b = append_label(entry, 'tr_state', state);
|
|
addHelp(b, 'tr_wifi_help');
|
|
|
|
if (mode == 'none') {
|
|
append_button(entry, 'tr_delete', function() {
|
|
delWifiSection(dev, mode);
|
|
rebuild_wifi();
|
|
adv_apply();
|
|
tr();
|
|
});
|
|
}
|
|
});
|
|
|
|
// Add or remove a wifi interface.
|
|
onDesc(mode_checks, 'INPUT', function(e) {
|
|
e.onclick = function(e) {
|
|
var src = (e.target || e.srcElement);
|
|
var mode = (src.data || src.value);
|
|
|
|
if (src.checked) {
|
|
if (obj.type != 'mac80211')
|
|
alert('tr_not_supported');
|
|
addWifiSection(dev, mode);
|
|
} else {
|
|
delWifiSection(dev, mode);
|
|
}
|
|
rebuild_wifi();
|
|
adv_apply();
|
|
tr();
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
function collect_switch_info(device)
|
|
{
|
|
var obj = {
|
|
device : device
|
|
};
|
|
|
|
// Portmap is a mapping of label to internal port number.
|
|
// Label starting with eth are not displayed and treated as physical interfaces.
|
|
switch (uci.misc.data.model)
|
|
{
|
|
case 'tp-link-tl-wdr3600-v1':
|
|
case 'tp-link-tl-wdr4300-v1':
|
|
case 'tp-link-archer-c7-v4':
|
|
case 'tp-link-archer-c7-v5':
|
|
obj.map = [['eth0',0],['WAN',1],['LAN1',2],['LAN2',3],['LAN3',4],['LAN4',5]];
|
|
break;
|
|
case 'tp-link-tl-wr1043n-nd-v1':
|
|
obj.map = [['eth0',5],['WAN',0],['LAN1',1],['LAN2',2],['LAN3',3],['LAN4',4]];
|
|
break;
|
|
case 'tp-link-tl-wr1043n-nd-v2':
|
|
case 'tp-link-tl-wr1043n-nd-v3':
|
|
case 'tp-link-tl-wr1043n-nd-v4':
|
|
case 'tp-link-tl-wr1043n-v5':
|
|
obj.map = [['eth1',0],['WAN',5],['LAN1',4],['LAN2',3],['LAN3',2],['LAN4',1]];
|
|
break;
|
|
case 'tp-link-tl-wdr3500-v1':
|
|
case 'tp-link-tl-wr741n-nd-v4':
|
|
case 'tp-link-tl-wr841n-nd-v3':
|
|
case 'tp-link-tl-wr841n-nd-v5':
|
|
obj.map = [['eth0',0],['LAN1',2],['LAN2',3],['LAN3',4],['LAN4',1]];
|
|
break;
|
|
case 'tp-link-tl-wr841n-nd-v8':
|
|
case 'tp-link-tl-mr3420-v2':
|
|
obj.map = [['eth1',0],['LAN1',2],['LAN2',3],['LAN3',4],['LAN4',1]];
|
|
break;
|
|
case 'tp-link-tl-wr941n-nd-v5':
|
|
case 'tp-link-tl-wr941n-nd-v6':
|
|
obj.map = [['eth1',0],['LAN1',4],['LAN2',3],['LAN3',2],['LAN4',1]];
|
|
break;
|
|
case 'tp-link-tl-wr841n-nd-v9':
|
|
case 'tp-link-tl-wr841n-nd-v10':
|
|
case 'tp-link-tl-wr841n-nd-v11':
|
|
obj.map = [['eth0',0],['LAN1',4],['LAN2',3],['LAN3',2],['LAN4',1]];
|
|
break;
|
|
case 'tp-link-tl-wr842n-nd-v1':
|
|
case 'tp-link-tl-wr842n-nd-v2':
|
|
obj.map = [['eth1',0],['LAN1',2],['LAN2',3],['LAN3',4],['LAN4',1]];
|
|
break;
|
|
case 'tp-link-tl-wr842n-nd-v3':
|
|
obj.map = [['eth0',0],['LAN1',4],['LAN2',3],['LAN3',2],['LAN4',1]];
|
|
break;
|
|
case 'tp-link-tl-wr841n-nd-v7':
|
|
case 'tp-link-tl-mr3420-v1':
|
|
obj.map = [['eth0',0],['LAN1',1],['LAN2',2],['LAN3',3],['LAN4',4]];
|
|
break;
|
|
case 'tp-link-cpe210-v1-0':
|
|
case 'tp-link-cpe210-v1-1':
|
|
case 'tp-link-cpe220-v1-0':
|
|
case 'tp-link-cpe510-v1-0':
|
|
case 'tp-link-cpe510-v1-1':
|
|
case 'tp-link-cpe520-v1-0':
|
|
obj.map = [['eth0',0],['LAN0',5],['LAN1',4]];
|
|
break;
|
|
case 'tp-link-archer-c5-v1':
|
|
case 'tp-link-archer-c7-v2':
|
|
obj.map = [['eth1',0],['LAN1',2],['LAN2',3],['LAN3',4],['LAN4',5],['eth0',6],['WAN',1]];
|
|
break;
|
|
case 'd-link-dir-615-d':
|
|
case 'd-link-dir-615-h1':
|
|
case 'd-link-dir-615-h2':
|
|
obj.map = [['eth0',6],['LAN1',3],['LAN2',2],['LAN3',1],['LAN4',0],['Internet',4]];
|
|
break;
|
|
case 'd-link-dir-860l-b1':
|
|
obj.map = [['eth0',6],['LAN1',1],['LAN2',2],['LAN3',3],['LAN4',4],['WAN',0]] ;
|
|
break;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function getSwitchVid(port, swinfo)
|
|
{
|
|
var found_vid;
|
|
config_foreach(uci.network, 'switch_vlan', function(vid, vobj) {
|
|
if (vobj.device == swinfo.device && vobj.ports.indexOf(port) != -1) {
|
|
found_vid = vid;
|
|
return false;
|
|
}
|
|
});
|
|
return found_vid;
|
|
}
|
|
|
|
function countPortUse(port, swinfo)
|
|
{
|
|
var count = 0;
|
|
config_foreach(uci.network, 'switch_vlan', function(vid, vobj) {
|
|
if (vobj.device == swinfo.device) {
|
|
count += (vobj.ports.indexOf(port) != -1);
|
|
}
|
|
});
|
|
return count;
|
|
}
|
|
|
|
function renameInterface(old_ifname, new_ifname)
|
|
{
|
|
for (var i in uci.network) {
|
|
var ifname = split(uci.network[i].ifname);
|
|
var index = ifname.indexOf(old_ifname);
|
|
if (index !== -1) {
|
|
ifname[index] = new_ifname;
|
|
uci.network[i].ifname = ifname.join(' ');
|
|
}
|
|
}
|
|
}
|
|
|
|
function replaceSwitchPort(fromPort, toPort, swinfo)
|
|
{
|
|
var vid = getSwitchVid(fromPort, swinfo);
|
|
if (vid) {
|
|
var vobj = uci.network[vid];
|
|
var fromIfname = getInterfaceName(vid, swinfo);
|
|
vobj.ports = replaceItem(vobj.ports, fromPort, toPort);
|
|
var toIfname = getInterfaceName(vid, swinfo);
|
|
renameInterface(fromIfname, toIfname);
|
|
}
|
|
}
|
|
|
|
function fixPortTag(swinfo)
|
|
{
|
|
for (var i in swinfo.map) {
|
|
var v = swinfo.map[i];
|
|
if (v[0].startsWith('eth'))
|
|
{
|
|
var bport = v[1];
|
|
if (countPortUse(bport, swinfo) > 1) {
|
|
replacePort(bport, bport + 't', swinfo);
|
|
} else {
|
|
replacePort(bport+'t', bport, swinfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function getInterfaceName(vid, swinfo)
|
|
{
|
|
var vobj = uci.network[vid];
|
|
for (var i in swinfo.map) {
|
|
var v = swinfo.map[i];
|
|
if (v[0].startsWith('eth')) {
|
|
if (vobj.ports.indexOf(''+v[1]+'t') != -1) {
|
|
return v[0] + '.' + vobj.vlan;
|
|
}
|
|
else if (vobj.ports.indexOf(v[1]) != -1) {
|
|
return v[0];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get base port.
|
|
function getBasePort(port, swinfo)
|
|
{
|
|
var bport;
|
|
var found = false;
|
|
var map = swinfo.map;
|
|
for (var i in map) {
|
|
var v = map[i];
|
|
if (v[0].startsWith('eth')) {
|
|
bport = v[1];
|
|
}
|
|
if (v[1] == port) {
|
|
return bport;
|
|
}
|
|
}
|
|
// A default port must exist.
|
|
}
|
|
|
|
function removePort(port, mode, swinfo)
|
|
{
|
|
var vid = getSwitchVid(port, swinfo);
|
|
var bport = getBasePort(port, swinfo);
|
|
var ifname = getInterfaceName(vid, swinfo);
|
|
var vobj = uci.network[vid];
|
|
|
|
vobj.ports = removeItem(vobj.ports, port.toString());
|
|
// Only the base port or no port at all is left => remove section.
|
|
if (split(vobj.ports).length < 2) {
|
|
delNetSection(ifname);
|
|
delete uci.network[vid];
|
|
}
|
|
|
|
if (countPortUse(bport, swinfo) < 2) {
|
|
// Untag base port.
|
|
replaceSwitchPort(bport+'t', bport, swinfo);
|
|
}
|
|
|
|
uci.network.pchanged = true;
|
|
}
|
|
|
|
function addPort(port, mode, swinfo)
|
|
{
|
|
var bport = getBasePort(port, swinfo);
|
|
|
|
var vlans = [];
|
|
var added = config_foreach(uci.network, 'switch_vlan', function(vid, vobj) {
|
|
vlans.push(parseInt(vobj.vlan));
|
|
if (vobj.device == swinfo.device && vobj.ports.indexOf(bport) != -1) {
|
|
var ifname = getInterfaceName(vid, swinfo);
|
|
if (getInterfaceMode(ifname) == mode) {
|
|
vobj.ports = addItem(vobj.ports, port.toString());
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
});
|
|
|
|
if (!added) {
|
|
// Get smallest unused vlan number > 0.
|
|
var vlan = vlans.sort(function(a, b){return a-b}).reduce(function(r, v, i) { return (r < vlans.length) ? r : ((i+1 != v) ? i+1 : r); }, vlans.length + 1);
|
|
|
|
var ports = '' + bport;
|
|
if (countPortUse(bport, swinfo) > 0) {
|
|
// Tag base port.
|
|
replaceSwitchPort(bport, bport + 't', swinfo);
|
|
ports += 't ' + port;
|
|
} else {
|
|
ports += ' ' + port;
|
|
}
|
|
|
|
var vid = 'cfg'+(++gid);
|
|
uci.network[vid] = { 'stype' : 'switch_vlan', 'device' : swinfo.device, 'vlan' : ''+vlan, 'ports' : ports };
|
|
|
|
var ifname = getInterfaceName(vid, swinfo);
|
|
addNetSection(ifname, mode);
|
|
}
|
|
|
|
uci.network.pchanged = true;
|
|
}
|
|
|
|
function getChangeHandler(port, mode, swinfo)
|
|
{
|
|
return function(e) {
|
|
var src = (e.target || e.srcElement);
|
|
var mode = (src.data || src.value);
|
|
|
|
removePort(port, mode, swinfo);
|
|
addPort(port, mode, swinfo);
|
|
|
|
rebuild_switches();
|
|
};
|
|
}
|
|
|
|
function rebuild_switches()
|
|
{
|
|
var root = $('switches');
|
|
removeChilds(root);
|
|
addHelp(root, 'tr_switches_help');
|
|
|
|
config_foreach(uci.network, 'switch', function(sid, sobj) {
|
|
var swinfo = collect_switch_info(sobj.name);
|
|
var sfs = append_section(root, 'Switch \''+swinfo.device+'\'');
|
|
|
|
if (!swinfo.map) {
|
|
var p = append(sfs, 'div');
|
|
var label = append(p, 'label');
|
|
label.classList.add('tr_no_port_config');
|
|
} else for (var i in swinfo.map) {
|
|
var name = swinfo.map[i][0];
|
|
var port = swinfo.map[i][1];
|
|
if (name.startsWith('eth')) {
|
|
continue;
|
|
}
|
|
var vid = getSwitchVid(port, swinfo);
|
|
var ifname = getInterfaceName(vid, swinfo);
|
|
var mode = getInterfaceMode(ifname);
|
|
var bport = getBasePort(port, swinfo);
|
|
|
|
var p = append(sfs, 'div');
|
|
var label = append(p, 'label');
|
|
label.textContent = name + ':';
|
|
|
|
var select = append_options(p, 'port_'+port, mode, net_options);
|
|
select.onchange = getChangeHandler(port, mode, swinfo);
|
|
}
|
|
});
|
|
}
|
|
|
|
/*
|
|
* WAN over wifi works only if the wifi interface
|
|
* is not in a bridge. Switch to static in this case.
|
|
* Also check if there are other WAN interfaces
|
|
*since only a bridge would support that.
|
|
*/
|
|
function checkWifiWan() {
|
|
var pre_mode = uci.network.wan.type;
|
|
var new_mode = 'bridge';
|
|
|
|
if (countWifi('wan', 'sta')) {
|
|
if ((countWifi('wan') + countOther('wan')) > 1) {
|
|
return false;
|
|
}
|
|
new_mode = 'static';
|
|
}
|
|
|
|
if (pre_mode != new_mode) {
|
|
uci.network.wan.type = new_mode;
|
|
uci.network.pchanged = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function save_data()
|
|
{
|
|
if (!checkWifiWan()) {
|
|
alert('tr_wifi_wan_error');
|
|
return;
|
|
}
|
|
|
|
for (var name in uci) {
|
|
var obj = uci[name];
|
|
if (!obj.pchanged)
|
|
continue;
|
|
|
|
var data = toUCI(obj);
|
|
send('/cgi-bin/misc', { func : 'set_config_file', name : name, data : data },
|
|
function(data) {
|
|
$('msg').textContent = data;
|
|
$('msg').focus();
|
|
init();
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|