Backport miscellaneous fixes to Unraid 7.1

This commit is contained in:
bergware
2025-06-07 13:44:19 +02:00
parent 0a5242f24b
commit 1fd6a2262f
12 changed files with 179 additions and 215 deletions

View File

@@ -25,23 +25,23 @@ exec("/etc/rc.d/rc.docker status >/dev/null",$dummy,$DockerStopped);
function strposX($s, $c, $n=1) {
$p = 0;
while ($n && $p=strpos($s,$c,$p)!==false) {$n--; $p+=strlen($c);}
while ($n && $p = strpos($s,$c,$p) !== false) {$n--; $p += strlen($c);}
return $p;
}
unset($custom,$other);
exec("ls --indicator-style=none /sys/class/net|grep -P '^br[0-9]'",$custom);
exec("ls --indicator-style=none /sys/class/net|grep -P '^(bond|eth|wlan)[0-9]'",$other);
$bridge = count($custom)>0;
exec("ls --indicator-style=none /sys/class/net | grep -P '^br[0-9]'",$custom);
exec("ls --indicator-style=none /sys/class/net | grep -P '^(bond|eth|wlan)[0-9]'",$other);
$bridge = count($custom) > 0;
$slaves = [];
foreach ($other as $network) {
if (substr($network,0,4)=='bond') {
if (substr($network,0,4) == 'bond') {
$br = str_replace('bond','br',$network);
$bond = "/sys/class/net/$network/bonding/slaves";
if (file_exists($bond)) $slaves = array_merge($slaves,explode(' ',str_replace("\n","",file_get_contents($bond))));
if (!in_array($br,$custom)) $custom[] = $network;
} elseif (substr($network,0,3)=='eth') {
} elseif ($bridge && substr($network,0,3) == 'eth') {
$br = str_replace('eth','br',$network);
$bond = str_replace('eth','bond',$network);
if (!in_array($br,$custom) && !in_array($bond,$custom)) $custom[] = $network;
@@ -50,18 +50,18 @@ foreach ($other as $network) {
}
}
$include = $include6 = $address = $address6 = $gateway = $gateway6 = $unset = $protocol = [];
$wide = false;
$wlan = (array)@parse_ini_file('/var/local/emhttp/wireless.ini');
$include = $include6 = $address = $address6 = $gateway = $gateway6 = $unset = $protocol = [];
$wide = false;
$wlan = (array)@parse_ini_file('/var/local/emhttp/wireless.ini');
foreach ($custom as $network) {
if (in_array($network,$slaves)) continue;
$ip4 = exec("ip -4 -br addr show $network scope global | awk '{print $3;exit}'");
$ip6 = exec("ip -6 -br addr show $network scope global -temporary -deprecated | awk '{print $3;exit}'");
$gw4 = $ip4 ? exec("ip -4 route show dev $network default | awk '{print $3;exit}'") : '';
$gw6 = $ip6 ? exec("ip -6 route show dev $network default | awk '{print $3;exit}'") : '';
$route4 = $ip4 ? exec("ip -4 route show dev $network $ip4 | awk '{print $1;exit}'") : '';
$route6 = $ip6 ? exec("ip -6 route show dev $network | awk '/^".substr($ip6,0,strposX($ip6,':',4))."/{print $1;exit}'") : '';
$ip4 = exec("ip -4 -br addr show scope global primary dev $network | awk '{print $3;exit}'");
$ip6 = exec("ip -6 -br addr show scope global primary -deprecated dev $network | awk '{print $3;exit}'");
$gw4 = $ip4 ? exec("ip -4 route show to default dev $network | awk '{print $3;exit}'") : '';
$gw6 = $ip6 ? exec("ip -6 route show to default dev $network | awk '{print $3;exit}'") : '';
$route4 = $ip4 ? exec("ip -4 route show dev $network | awk '$1 !~ /^default/ {print $1;exit}'") : '';
$route6 = $ip6 ? exec("ip -6 route show dev $network | awk '$1 !~ /^(default|f[a-f])/ {print $1;exit}'") : '';
if (substr($network,0,4) != 'wlan') {
[$eth,$vlan] = my_explode('.',$network);
$eth = str_replace(['bond','br'],'eth',$eth);
@@ -89,6 +89,7 @@ foreach ($custom as $network) {
}
if ($protocol[$network] != 'ipv4') $wide = true;
}
$ip4class = $wide ? 'ip6' : 'ip4';
$gw4class = $wide ? 'gw6' : 'gw4';
@@ -114,15 +115,6 @@ function base_net($route) {
return substr(explode('/',$route)[0],0,-2);
}
function hide_wlan($network) {
return $network=='wlan0' && lan_port(DockerUtil::port(),true)==1;
}
function hide_eth($network) {
$mgmt_port = ['br0','bond0','eth0'];
return in_array($network,$mgmt_port) && lan_port('wlan0',true)==1;
}
$bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c';
//Check if docker.cfg does exist
@@ -275,8 +267,8 @@ _(Template Authoring Mode)_:
_(Docker custom network type)_:
: <select name="DOCKER_NETWORK_TYPE">
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '1', _('ipvlan'), $bridge?'':'disabled')?>
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '', _('macvlan'), $bridge?'':'selected')?>
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '1', _('ipvlan'), $bridge ? '' : 'disabled')?>
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '', _('macvlan'), $bridge ? '' : 'selected')?>
</select>&nbsp;_(Please read the Help carefully)_. _(Misconfiguration can cause problems)_.
:docker_custom_network_type_help:
@@ -302,14 +294,9 @@ _(Preserve user defined networks)_:
$net = normalize($network);
$docker_auto = "DOCKER_AUTO_$net";
$docker_dhcp = "DOCKER_DHCP_$net";
$hide_wlan = hide_wlan($network);
?>
<input type="hidden" name="<?=$docker_auto?>" value="<?=_var($dockercfg,$docker_auto)?>">
<?if ($hide_wlan):?>
<div markdown="1" style="display:none">
<?endif;?>
_(IPv4 custom network on interface)_ <?=$network?> (_(optional)_):
<?
$auto = _var($dockercfg,$docker_auto) == '' || str_contains(_var($dockercfg,$docker_auto), '4');
@@ -336,27 +323,24 @@ _(IPv4 custom network on interface)_ <?=$network?> (_(optional)_):
**_(DHCP pool)_:**<span id="<?=$docker_dhcp?>_net" class="net <?=$dhcpDisabled?>"><?=$prefix?>.</span>
</span>
<?
for ($b=$box; $b<=3; $b++) {
for ($b = $box; $b <= 3; $b++) {
switch ($b) {
case 1: $step = floor($size/65536)%256; break;
case 2: $step = floor($size/256)%256; break;
case 3: $step = $size%256; break;
}
if ($step===0) $step = 256;
if ($step === 0) $step = 256;
echo "<select id=\"{$docker_dhcp}_{$b}\" class=\"net\" $dhcpDisabled>";
for ($n=$net[$b]; $n<=$max[$b]; $n++) echo mk_option($net_user[$b],$n,$n,$n%$step==0?'':'class="hide"');
for ($n = $net[$b]; $n <= $max[$b]; $n++) echo mk_option($net_user[$b],$n,$n,$n%$step==0?'':'class="hide"');
echo "</select>";
}
echo "/ ";
echo "<select id=\"{$docker_dhcp}_mask\" class=\"mask\" onchange=\"changeMask(this.id,this.value)\" $dhcpDisabled>";
for ($m=$mask+1; $m<=30; $m++) echo mk_option($mask_user,$m,$m);
for ($m = $mask+1; $m <= 30; $m++) echo mk_option($mask_user,$m,$m);
echo "</select><span id=\"{$docker_dhcp}_size\" style=\"".($dhcp?'':'display:none')."\">($size "._('hosts').")</span>";
echo "<input type=\"hidden\" name=\"$docker_dhcp\" value=\"\">";
?>
<?if ($hide_wlan):?>
</div>
<?endif;?>
<?endforeach;?>
<?if ($include):?>
@@ -370,48 +354,35 @@ $port = normalize($network);
[$range,$size] = my_explode('/',_var($dockercfg,"DOCKER_RANGE_$port"));
$disabled = $subnet ? '':'disabled';
$dhcpDisabled = $range ? '':'disabled';
$hide_eth = hide_eth($network);
?>
<?if ($protocol[$network] != 'ipv6'):?>
<?if ($hide_eth):?>
<div markdown="1" style="display:none">
<?endif;?>
<?if ($protocol[$network] != 'ipv6' && ($network != 'wlan0' || lan_port('wlan0',true) == 1)):?>
_(IPv4 custom network on interface)_ <?=$network?> (_(optional)_):
: <input type="checkbox" id="DOCKER_CUSTOM_<?=$port?>_edit" onchange="changeCustom(this.id,4)"<?=$subnet?'checked':''?>><span id="DOCKER_CUSTOM_<?=$port?>_line" class="<?=$subnet?'':'disabled'?>">
<span class="<?=$ip4class?>">**_(Subnet)_:** <input type="text" id="DOCKER_CUSTOM_<?=$port?>_net" name="DOCKER_SUBNET_<?=$port?>" class="ip4" value="<?=$subnet?>" title="_(IPv4 address A.B.C.D)_"<?=$disabled?>>/
<select id="DOCKER_CUSTOM_<?=$port?>_mask" name="DOCKER_MASK_<?=$port?>" class="mask"<?=$disabled?>>
<?for ($m=25; $m<=30; $m++) echo mk_option($mask?:24,$m,$m)?></select>
<?for ($m=16; $m<=30; $m++) echo mk_option($mask?:24,$m,$m)?></select>
</span>
<span class="<?=$gw4class?>">**_(Gateway)_:** <input type="text" id="DOCKER_CUSTOM_<?=$port?>_gw" name="DOCKER_GATEWAY_<?=$port?>" class="ip4" value="<?=htmlspecialchars(_var($dockercfg,"DOCKER_GATEWAY_$port"))?>" title="_(IPv4 address A.B.C.D)_"<?=$disabled?>></span>
<input type="checkbox" id="DOCKER_CUSTOM_<?=$port?>_dhcp" onchange="customDHCP(this.id,4)"<?=$subnet?'checked':''?><?=$dhcpDisabled?>>
**_(DHCP pool)_:** <input type="text" id="DOCKER_CUSTOM_<?=$port?>_pool" name="DOCKER_RANGE_<?=$port?>" class="ip4" value="<?=$range?>" title="_(IPv4 address A.B.C.D)_"<?=$disabled?>>/
<select id="DOCKER_CUSTOM_<?=$port?>_size" name="DOCKER_SIZE_<?=$port?>" class="mask" onchange="changeHosts(this.id,this.value)"<?=$disabled?>>
<?for ($m=16; $m<=30; $m++) echo mk_option($size?:25,$m,$m)?></select>
<?for ($m=25; $m<=30; $m++) echo mk_option($size?:25,$m,$m)?></select>
<span id="DOCKER_CUSTOM_<?=$port?>_hosts" style="<?=$subnet?'':'display:none'?>">(<?=pow(2,32-($size?:25))?> _(hosts)_)</span></span>
<?endif;?>
<?if ($hide_eth):?>
</div>
<?endif;?>
<?endforeach;?>
<?if ($unset && $protocol[$network] != 'ipv6'):?>
:docker_exclude_interface_vlan_ipv4_help:
<?endif;?>
<?if ($include6):?>
<hr>
<?endif;?>
<?foreach ($include6 as $network => $route):?>
<?
$net = normalize($network);
$docker_auto = "DOCKER_AUTO_$net";
$docker_dhcp6 = "DOCKER_DHCP6_$net";
$hide_wlan = hide_wlan($network);
?>
<?if ($hide_wlan):?>
<div markdown="1" style="display:none">
<?endif;?>
<?if ($network != 'wlan0' || lan_port('wlan0',true) == 1):?>
_(IPv6 custom network on interface)_ <?=$network?> (_(optional)_):
<?
@@ -429,8 +400,6 @@ _(IPv6 custom network on interface)_ <?=$network?> (_(optional)_):
<span class="ip6">**_(Subnet)_:** <?=$route?></span>
<span class="gw6">**_(Gateway)_:** <?=$gateway6[$network]?></span>
<?if ($hide_wlan):?>
</div>
<?endif;?>
<?endforeach;?>
<?if ($include6):?>
@@ -444,12 +413,8 @@ $port = normalize($network);
[$range6,$size6] = my_explode('/',_var($dockercfg,"DOCKER_RANGE6_$port"));
$disabled = $subnet6 ? '':'disabled';
$dhcpDisabled = $range6 ? '':'disabled';
$hide_eth = hide_eth($network);
?>
<?if ($protocol[$network] != 'ipv4'):?>
<?if ($hide_eth):?>
<div markdown="1" style="display:none">
<?endif;?>
_(IPv6 custom network on interface)_ <?=$network?> (_(optional)_):
: <input type="checkbox" id="DOCKER_CUSTOM6_<?=$port?>_edit" onchange="changeCustom(this.id,6)"<?=$subnet6?'checked':''?>><span id="DOCKER_CUSTOM6_<?=$port?>_line" class="<?=$subnet6?'':'disabled'?>">
@@ -458,9 +423,6 @@ _(IPv6 custom network on interface)_ <?=$network?> (_(optional)_):
<?for ($m=64; $m<=120; $m+=8) echo mk_option($mask6?:64,$m,$m)?></select></span>
<span class="gw6">**_(Gateway)_:**<input type="text" id="DOCKER_CUSTOM6_<?=$port?>_gw" name="DOCKER_GATEWAY6_<?=$port?>" class="gw6" value="<?=_var($dockercfg,"DOCKER_GATEWAY6_$port")?>" title="_(IPv6 address nnnn:xxxx::yyyy)_"<?=$disabled?>></span>
<?if ($hide_eth):?>
</div>
<?endif;?>
<?endif;?>
<?endforeach;?>
<?if ($unset && $protocol[$network] != 'ipv4'):?>
@@ -518,32 +480,24 @@ _(Preserve user defined networks)_:
<?foreach ($include as $network => $route):?>
<?
$net = normalize($network);
$net = normalize($network);
$docker_dhcp = "DOCKER_DHCP_$net";
$hide_wlan = hide_wlan($network);
?>
<?if (isset($dockercfg[$docker_dhcp]) || empty($dockercfg["DOCKER_AUTO_$net"]) || $dockercfg["DOCKER_AUTO_$net"] != 'no'):?>
<?if ($hide_wlan):?>
<div markdown="1" style="display:none">
<?endif;?>
_(IPv4 custom network on interface)_ <?=$network?>:
: <span class="<?=$gw4class?>">**_(Subnet)_:** <?=$route?></span>
<span class="<?=$gw4class?>">**_(Gateway)_:** <?=$gateway[$network]?></span>
**_(DHCP pool)_:** <?=_var($dockercfg,$docker_dhcp) ?: "_(not set)_"?><?if (isset($dockercfg[$docker_dhcp])):?>&nbsp;&nbsp;(<?=pow(2,32-my_explode('/',$dockercfg[$docker_dhcp])[1])?> _(hosts)_)<?endif;?>
<?if ($hide_wlan):?>
</div>
<?endif;?>
<?endif;?>
<?endforeach;?>
<?foreach ($unset as $network):?>
<?
$port = normalize($network);
$hide_eth = hide_eth($network);
$port = normalize($network);
if (substr($network,0,4) != 'wlan') {
[$eth,$vlan] = my_explode('.',$network);
[$eth, $vlan] = my_explode('.',$network);
$eth = str_replace(['bond','br'],'eth',$eth);
if (!$vlan) {
$protocol = _var($$eth,'PROTOCOL:0','ipv4');
@@ -556,52 +510,38 @@ if (substr($network,0,4) != 'wlan') {
$protocol = empty($wlan['IP6']) ? 'ipv4' : 'ipv4+ipv6';
}
[$subnet,$mask] = my_explode('/',_var($dockercfg,"DOCKER_SUBNET_$port"));
[$range,$size] = my_explode('/',_var($dockercfg,"DOCKER_RANGE_$port"));
[$subnet, $mask] = my_explode('/',_var($dockercfg,"DOCKER_SUBNET_$port"));
[$range, $size] = my_explode('/',_var($dockercfg,"DOCKER_RANGE_$port"));
?>
<?if ($protocol != 'ipv6' && $subnet):?>
<?if ($hide_eth):?>
<div markdown="1" style="display:none">
<?endif;?>
_(IPv4 custom network on interface)_ <?=$network?>:
: <span class="<?=$gw4class?>">**_(Subnet)_:** <?=$subnet?>/<?=$mask?></span>
<span class="<?=$gw4class?>">**_(Gateway)_:** <?=_var($dockercfg,"DOCKER_GATEWAY_$port")?></span>
**_(DHCP pool)_:** <?=$range ? "$range/$size" : "_(not set)_"?><?if ($range):?>&nbsp;&nbsp;(<?=pow(2,32-($size?:25))?> _(hosts)_)<?endif;?>
<?if ($hide_eth):?>
</div>
<?endif;?>
<?endif;?>
<?endforeach;?>
<?foreach ($include6 as $network => $route):?>
<?
$net = normalize($network);
$net = normalize($network);
$docker_dhcp6 = "DOCKER_DHCP6_$net";
$hide_wlan = hide_wlan($network);
if (isset($dockercfg[$docker_dhcp6]) || empty($dockercfg["DOCKER_AUTO_$net"])):?>
if (isset($dockercfg[$docker_dhcp6]) || empty($dockercfg["DOCKER_AUTO_$net"]) || $dockercfg["DOCKER_AUTO_$net"] != 'no'):?>
<?$wide = true;?>
<?if ($hide_wlan):?>
<div markdown="1" style="display:none">
<?endif;?>
_(IPv6 custom network on interface)_ <?=$network?>:
: <span class="gw6">**_(Subnet)_:** <?=$route?></span>
<span class="gw6">**_(Gateway)_:** <?=$gateway6[$network]?></span>
<?if ($hide_wlan):?>
</div>
<?endif;?>
<?endif;?>
<?endforeach;?>
<?foreach ($unset as $network):?>
<?
$port = normalize($network);
$hide_eth = hide_eth($network);
$port = normalize($network);
if (substr($network,0,4) != 'wlan') {
[$eth,$vlan] = my_explode('.',$network);
[$eth, $vlan] = my_explode('.',$network);
$eth = str_replace(['bond','br'],'eth',$eth);
if (!$vlan) {
$protocol = _var($$eth,'PROTOCOL:0','ipv4');
@@ -614,21 +554,15 @@ if (substr($network,0,4) != 'wlan') {
$protocol = empty($wlan['IP6']) ? 'ipv4' : 'ipv4+ipv6';
}
[$subnet6,$mask6] = my_explode('/',_var($dockercfg,"DOCKER_SUBNET6_$port"));
[$range6,$size6] = my_explode('/',_var($dockercfg,"DOCKER_RANGE6_$port"));
[$subnet6, $mask6] = my_explode('/',_var($dockercfg,"DOCKER_SUBNET6_$port"));
[$range6, $size6] = my_explode('/',_var($dockercfg,"DOCKER_RANGE6_$port"));
?>
<?if ($protocol != 'ipv4' && $subnet6):?>
<?if ($hide_eth):?>
<div markdown="1" style="display:none">
<?endif;?>
_(IPv6 custom network on interface)_ <?=$network?>:
: <span class="gw6">**_(Subnet)_:** <?=$subnet6?>/<?=$mask6?></span>
<span class="gw6">**_(Gateway)_:** <?=_var($dockercfg,"DOCKER_GATEWAY6_$port")?></span>
<?if ($hide_eth):?>
</div>
<?endif;?>
<?endif;?>
<?endforeach;?>
</div>

View File

@@ -1230,9 +1230,8 @@ class Array2XML {
function getValidNetworks() {
global $lv;
$arrValidNetworks = [];
exec("ls --indicator-style=none /sys/class/net | grep -Po '^virbr[0-9]+'",$arrBridges);
exec("ls --indicator-style=none /sys/class/net | grep -Po '^(br|bond|eth|wlan)[0-9]+(\.[0-9]+)?'",$arrBridges);
// add 'virbr0' as default first choice
array_unshift($arrBridges, 'virbr0');
// remove redundant references of bridge and bond interfaces
$remove = [];
foreach ($arrBridges as $name) {
@@ -1240,7 +1239,7 @@ class Array2XML {
$remove = array_merge($remove, (array)@file("/sys/class/net/$name/bonding/slaves",FILE_IGNORE_NEW_LINES));
} elseif (substr($name,0,2) == 'br') {
$remove = array_merge($remove, array_map(function($n){return end(explode('/',$n));}, glob("/sys/class/net/$name/brif/*")));
}
}
}
$arrValidNetworks['bridges'] = array_diff($arrBridges, $remove);
@@ -1845,15 +1844,15 @@ class Array2XML {
$rtn = $lv->domain_define($xml);
if (is_resource($rtn)) {
$arrResponse = ['success' => true];
$arrResponse = ['success' => true];
write("addLog\0".htmlspecialchars(_("Creating XML successful")));
} else {
} else {
$lastvmerror = $lv->get_last_error();
$arrResponse = ['xml' => $xml,'error' => $lastvmerror];
write("addLog\0".htmlspecialchars(_("Creating XML Error:$lastvmerror")));
file_put_contents("/tmp/vmclonertn.debug", json_encode($arrResponse,JSON_PRETTY_PRINT));
}
return($rtn);
}

View File

@@ -40,6 +40,9 @@ $arrValidNetworks = getValidNetworks();
$strCPUModel = getHostCPUModel();
$templateslocation = "/boot/config/plugins/dynamix.vm.manager/savedtemplates.json";
// get MAC address of wireless interface (if existing)
$mac = file_exists('/sys/class/net/wlan0/address') ? trim(file_get_contents('/sys/class/net/wlan0/address')) : '';
if (is_file($templateslocation)){
$arrAllTemplates["User-templates"] = "";
$ut = json_decode(file_get_contents($templateslocation),true);
@@ -352,7 +355,7 @@ if ($snapshots!=null && count($snapshots) && !$boolNew) {
<table>
<tr class="<?=$snaphidden?>">
<td></td>
<td><span class="orange-text"><i class="fa fa-fw fa-warning"></i> _(Rename disabled, <?=$snapcount?> snapshot(s) exists)_.</span></td>
<td><span class="orange-text"><i class="fa fa-fw fa-warning"></i> <?=sprintf(_('Rename disabled, %s snapshot(s) exists'), $snapcount)?>.</span></td>
<td></td>
</tr>
<tr id="zfs-name" class="hidden">
@@ -2017,13 +2020,17 @@ foreach ($arrConfig['evdev'] as $i => $arrEvdev) {
var storageType = "<?=get_storage_fstype($arrConfig['template']['storage']);?>";
var storageLoc = "<?=$arrConfig['template']['storage']?>";
function updateMAC(index,port) {
$('input[name="nic['+index+'][mac]"').prop('disabled',port=='wlan0');
$('i.mac_generate.'+index).prop('disabled',port=='wlan0');
function updateMAC(index, port) {
var wlan0 = '<?=$mac?>'; // mac address of wlan0
var mac = $('input[name="nic['+index+'][mac]"');
mac.prop('disabled', port=='wlan0');
$('i.mac_generate.'+index).prop('disabled', port=='wlan0');
$('span.wlan0').removeClass('hidden');
if (port != 'wlan0') {
if (port == 'wlan0') {
mac.val(wlan0);
} else {
$('span.wlan0').addClass('hidden');
$('i.mac_generate.'+index).click();
if (wlan0 && mac.val()==wlan0) $('i.mac_generate.'+index).click();
}
}

View File

@@ -45,7 +45,7 @@
exit;
}
// create new VM template
if (isset($_POST['createvmtemplate'])) {
$reply = addtemplatexml($_POST);
@@ -116,7 +116,7 @@
<input type="button" value="_(Create)_" busyvalue="_(Creating)_..." readyvalue="_(Create)_" id="btnSubmit" />
<? } ?>
<input type="button" value="_(Cancel)_" id="btnCancel" />
<input type="button" value=" _(Create/Modify Template)_" busyvalue="_(Creating)_..." readyvalue="_(Create)_" id="btnTemplateSubmit" />
<? } else { ?>
@@ -217,12 +217,12 @@ $(function() {
$button.val($button.attr('busyvalue'));
swal({
title: "_(Template Name)_",
text: "_(Enter name:\nIf name already exists it will be replaced.)_",
text: "_(Enter name)_:\n_(If name already exists it will be replaced)_.",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
//animation: "slide-from-top",
inputPlaceholder: "_(Leaving blank will use OS name.)_"
inputPlaceholder: "_(Leaving blank will use OS name)_."
},
function(inputValue){
postdata=postdata+"&templatename="+inputValue;

View File

@@ -47,19 +47,16 @@ var dfm_read = {};
function dfm_footer(action, text) {
switch (action) {
case 'show':
$('#countdown').show();
$('#user-notice').show();
break;
case 'hide':
$('#countdown').hide();
$('#user-notice').hide();
break;
case 'write':
if ($('#countdown').html() == '') $('#countdown').html('<a class="hand" onclick="dfm_openDialog(true)" title="_(File Manager)_"><i class="icon-u-duplicate dfm"></i></a>');
$('#user-notice').html(text);
let icon = '<a class="hand" onclick="dfm_openDialog(true)" title="_(File Manager)_"><i class="icon-u-duplicate dfm"></i></a>';
$('#user-notice').html(icon + text);
break;
case 'clear':
$('#countdown').html('');
$('#user-notice').html('');
break;
}

View File

@@ -15,7 +15,7 @@ Tag="icon-ethernet"
*/
?>
<?
$members = parse_ini_file('state/network.ini',true);
$members = parse_ini_file('state/network.ini', true);
$build = false;
$template = "$docroot/webGui/EthX.page";
$ini = '/var/local/emhttp/network.ini';
@@ -35,7 +35,7 @@ $masks = [
];
// get available ethernet ports (excluding eth0)
exec("ls --indicator-style=none /sys/class/net|grep -P '^eth[1-9][0-9]*$'",$ports);
exec("ls --indicator-style=none /sys/class/net|grep -P '^eth[1-9][0-9]*$'", $ports);
function locked($source, $port) {
global $members;
@@ -61,7 +61,7 @@ function metric($eth) {
$bond = str_replace('eth', 'bond', $eth);
$port = file_exists("$system/$bridge") ? $bridge : (file_exists("$system/$bond") ? $bond : $eth);
$index = exec("cat $system/$port/ifindex 2>/dev/null");
return 1000 + ($index ?: exec("cat $system/*/ifindex | sort -n | tail -1") + 1);
return $index ?: exec("cat $system/*/ifindex | sort -n | tail -1") + 1;
}
// remove non-existing ethernet ports
@@ -204,7 +204,7 @@ function prepareSettings(form) {
$(form).find('select[name^="USE_DHCP:"]').each(function() {
var i = $(this).prop('name').split(':')[1];
var protocol = $(form).find('select[name="PROTOCOL:'+i+'"]').val() || 'ipv4';
var gw4 = (port == 'eth0') ? true : $(form).find('input[name="USE_GW4:'+i+'"]').prop('checked');
var gw4 = (port == 'eth0' && i == 0) ? true : $(form).find('input[name="USE_GW4:'+i+'"]').prop('checked');
if (protocol != 'ipv6' && $(this).val() != 'no') {
$(form).find('input[name="IPADDR:'+i+'"]').val('');
$(form).find('input[name="GATEWAY:'+i+'"]').val('');
@@ -214,7 +214,7 @@ function prepareSettings(form) {
$(form).find('select[name^="USE_DHCP6:"]').each(function() {
var i = $(this).prop('name').split(':')[1];
var protocol = $(form).find('select[name="PROTOCOL:'+i+'"]').val() || 'ipv4';
var gw6 = (port == 'eth0') ? true : $(form).find('input[name="USE_GW6:'+i+'"]').prop('checked');
var gw6 = (port == 'eth0' && i == 0) ? true : $(form).find('input[name="USE_GW6:'+i+'"]').prop('checked');
if (protocol != 'ipv4' && $(this).val() != 'no') {
$(form).find('input[name="IPADDR6:'+i+'"]').val('');
$(form).find('input[name="GATEWAY6:'+i+'"]').val('');
@@ -813,7 +813,7 @@ _(IPv4 address assignment)_:
<?=mk_option(_var($eth0,"USE_DHCP:$i"), 'no', _('Static'))?>
<?=mk_option(_var($eth0,"USE_DHCP:$i"), '', _('None'))?>
</select>
<span class="gw4-eth0-<?=$i?> hide"><input type="checkbox" name="USE_GW4:<?=$i?>" onchange="selectGW(this.form,4,<?=$i?>,'slow')" <?=_var($eth0,"USE_GW4:$i")?'checked':''?>><?=$enable?></span>
<span class="gw4-eth0-<?=$i?> hide"><input type="checkbox" name="USE_GW4:<?=$i?>" onchange="selectGW(this.form,4,<?=$i?>,'slow')" <?=_var($eth0,"METRIC:$i") == 0 ? '' : 'checked'?>><?=$enable?></span>
:eth_ipv4_address_assignment_help:
@@ -844,7 +844,7 @@ _(IPv6 address assignment)_:
<?=mk_option(_var($eth0,"USE_DHCP6:$i"), '', _('None'))?>
<?endif;?>
</select>
<span class="gw6-eth0-<?=$i?> hide"><input type="checkbox" name="USE_GW6:<?=$i?>" onchange="selectGW(this.form,6,<?=$i?>,'slow')" <?=_var($eth0,"USE_GW6:$i")?'checked':''?>><?=$enable?></span>
<span class="gw6-eth0-<?=$i?> hide"><input type="checkbox" name="USE_GW6:<?=$i?>" onchange="selectGW(this.form,6,<?=$i?>,'slow')" <?=_var($eth0,"METRIC6:$i") == 0 ? '' : 'checked'?>><?=$enable?></span>
:eth_ipv6_address_assignment_help:

View File

@@ -171,7 +171,7 @@ _(IPv4 address assignment)_:
<?=mk_option(_var($ethX,"USE_DHCP:0"), 'no', _('Static'))?>
<?=mk_option(_var($ethX,"USE_DHCP:0"), '', _('None'))?>
</select>
<span class="gw4-ethX-0 hide"><input type="checkbox" name="USE_GW4:0" onchange="selectGW(this.form,4,0,'slow')" <?=_var($ethX,"USE_GW4:0")?'checked':''?>><?=$enable?></span>
<span class="gw4-ethX-0 hide"><input type="checkbox" name="USE_GW4:0" onchange="selectGW(this.form,4,0,'slow')" <?=_var($ethX,"METRIC:0") == 0 ? '' : 'checked'?>><?=$enable?></span>
:eth_ipv4_address_assignment_help:
@@ -200,7 +200,7 @@ _(IPv6 address assignment)_:
<?=mk_option(_var($ethX,"USE_DHCP6:0"), 'no', _('Static'))?>
<?=mk_option(_var($ethX,"USE_DHCP6:0"), '', _('None'))?>
</select>
<span class="gw6-ethX-0 hide"><input type="checkbox" name="USE_GW6:0" onchange="selectGW(this.form,6,0,'slow')" <?=_var($ethX,"USE_GW6:0")?'checked':''?>><?=$enable?></span>
<span class="gw6-ethX-0 hide"><input type="checkbox" name="USE_GW6:0" onchange="selectGW(this.form,6,0,'slow')" <?=_var($ethX,"METRIC6:0") == 0 ? '' : 'checked'?>><?=$enable?></span>
:eth_ipv6_address_assignment_help:
@@ -278,7 +278,7 @@ _(IPv4 address assignment)_:
<?=mk_option(_var($ethX,"USE_DHCP:$i"), 'no', _('Static'))?>
<?=mk_option(_var($ethX,"USE_DHCP:$i"), '', _('None'))?>
</select>
<span class="gw4-ethX-<?=$i?> hide"><input type="checkbox" name="USE_GW4:<?=$i?>" onchange="selectGW(this.form,4,<?=$i?>,'slow')" <?=_var($ethX,"USE_GW4:$i")?'checked':''?>><?=$enable?></span>
<span class="gw4-ethX-<?=$i?> hide"><input type="checkbox" name="USE_GW4:<?=$i?>" onchange="selectGW(this.form,4,<?=$i?>,'slow')" <?=_var($ethX,"METRIC:$i") == 0 ? '' : 'checked'?>><?=$enable?></span>
:eth_ipv4_address_assignment_help:
@@ -307,7 +307,7 @@ _(IPv6 address assignment)_:
<?=mk_option(_var($ethX,"USE_DHCP6:$i"), 'no', _('Static'))?>
<?=mk_option(_var($ethX,"USE_DHCP6:$i"), '', _('None'))?>
</select>
<span class="gw6-ethX-<?=$i?> hide"><input type="checkbox" name="USE_GW6:<?=$i?>" onchange="selectGW(this.form,6,<?=$i?>,'slow')" <?=_var($ethX,"USE_GW6:$i")?'checked':''?>><?=$enable?></span>
<span class="gw6-ethX-<?=$i?> hide"><input type="checkbox" name="USE_GW6:<?=$i?>" onchange="selectGW(this.form,6,<?=$i?>,'slow')" <?=_var($ethX,"METRIC6:$i") == 0 ? '' : 'checked'?>><?=$enable?></span>
:eth_ipv6_address_assignment_help:

View File

@@ -35,11 +35,6 @@ TMP=/var/tmp/network.tmp
# run & log functions
. /etc/rc.d/rc.runlog
# return interface index
index(){
cat $SYSTEM/$1/ifindex 2>/dev/null
}
# return active interface
active(){
if [[ -e $SYSTEM/${1/eth/br} ]]; then
@@ -346,7 +341,7 @@ docker_network_start(){
SUBNET=; GATEWAY=; SERVER=; RANGE=;
[[ -z ${!AUTO} || ${!AUTO} =~ "4" ]] && IPV4=$(ip -4 -br addr show scope global primary dev $NETWORK | awk '{print $3;exit}') || IPV4=
if [[ -n $IPV4 ]]; then
SUBNET=$(ip -4 route show to $IPV4 dev $NETWORK | awk '{print $1;exit}')
SUBNET=$(ip -4 route show dev $NETWORK | awk '$1 !~ /^default/ {print $1;exit}')
SERVER=${IPV4%/*}
DHCP=${NETWORK/./_}
DHCP=DOCKER_DHCP_${DHCP^^}
@@ -355,9 +350,9 @@ docker_network_start(){
fi
SUBNET6=; GATEWAY6=; SERVER6=;
# get IPv6 address - ignore any /128 networks
[[ -z ${!AUTO} || ${!AUTO} =~ "6" ]] && IPV6=$(ip -6 -br addr show scope global primary -deprecated dev $NETWORK | awk -v RS='[[:space:]]+' '(NR>2){print}' | grep -Pvm1 '^.+/128|^$') || IPV6=
[[ -z ${!AUTO} || ${!AUTO} =~ "6" ]] && IPV6=$(ip -6 -br addr show scope global primary -deprecated dev $NETWORK | awk -v RS='[[:space:]]+' '(NR>2){print}' | grep -Pvm1 '^f[a-f]|^$') || IPV6=
if [[ -n $IPV6 ]]; then
SUBNET6=$(ip -6 route show to $IPV6 dev $NETWORK | awk '{print $1;exit}')
SUBNET6=$(ip -6 route show dev $NETWORK | awk '$1 !~ /^(default|f[a-f])/ {print $1;exit}')
SERVER6=${IPV6%/*}
GATEWAY6=$(ip -6 route show to default dev $NETWORK | awk '{print $3;exit}')
# replace link local address for first address in subnet
@@ -421,14 +416,13 @@ docker_network_start(){
if [[ $TYPE == br ]]; then
LINK=shim-$NETWORK
if [[ $DOCKER_ALLOW_ACCESS == yes && -n $IPV4 ]]; then
IPV4="$IPV4 metric $((1000 - 1 + $(index $NETWORK)))"
# create shim interface
[[ -e $SYSTEM/$LINK ]] || run ip link add link $NETWORK name $LINK type $ATTACH mode $MODE
# disable IPv6 on shim interface
echo 1 >$CONF6/$LINK/disable_ipv6
run ip -6 addr flush dev $LINK
# copy parent IPv4 address to shim interface
run ip addr add $IPV4 dev $LINK
run ip addr add $IPV4 dev $LINK metric 0
run ip link set $LINK up
log "created network $LINK for host access"
elif [[ -e $SYSTEM/$LINK ]]; then
@@ -440,22 +434,19 @@ docker_network_start(){
else
if [[ $TYPE == wlan ]]; then
VHOST=shim-$NETWORK
INDEX=3000
else
VHOST=vhost${NETWORK//[^0-9.]/}
INDEX=1000
fi
INDEX=$(($INDEX - 1 + $(index $NETWORK)))
if [[ -n $IPV4 && $DOCKER_ALLOW_ACCESS == yes ]]; then
# disable IPv6 on vhost interface
echo 1 >$CONF6/$VHOST/disable_ipv6
run ip -6 addr flush dev $VHOST
# copy parent IPv4 address to vhost interface
[[ -z $(ipv4_exist $VHOST ${IPV4%/*}) ]] && run ip addr add $IPV4 metric $INDEX dev $VHOST
[[ -z $(ipv4_exist $VHOST ${IPV4%/*}) ]] && run ip addr add $IPV4 dev $VHOST metric 0
log "created network $VHOST for host access"
elif [[ -n $IPV4 && -e $SYSTEM/$VHOST && -n $(ipv4_exist $VHOST ${IPV4%/*}) ]]; then
# remove parent IPv4 address from vhost interface
run ip addr del $IPV4 metric $INDEX dev $VHOST
run ip addr del $IPV4 dev $VHOST metric 0
fi
fi
fi

View File

@@ -7,7 +7,7 @@
# @(#)/etc/rc.d/rc.inet1 10.2 Sun Jul 24 12:45:56 PDT 2005 (pjv)
# LimeTech - modified for Unraid OS
# Bergware - modified for Unraid OS, May 2025
# Bergware - modified for Unraid OS, June 2025
# Adapted by Bergware for use in Unraid OS - April 2016
# - improved interface configuration
@@ -84,6 +84,10 @@
# Adapted by Bergware for use in Unraid OS - May 2025
# - improved metric value to interface IP assignment
# Adapted by Bergware for use in Unraid OS - June 2025
# - revert metric assignment to static addresses
# - remove duplicate ipv6 parameters
###########
# LOGGING #
###########
@@ -324,26 +328,26 @@ ipv6_up(){
ipv6_ra(){
echo $2 >$CONF6/$1/accept_ra
echo $2 >$CONF6/$1/accept_ra_defrtr
echo $3 >$CONF6/$1/autoconf
echo $2 >$CONF6/$1/autoconf
}
# enable/disable ipv6 assignment per interface
ipv6_conf(){
[[ -d $CONF6/${IFACE/$1/$2} ]] && ipv6_ra ${IFACE/$1/$2} $4 $5
[[ -d $CONF6/${IFACE/$1/$3} ]] && ipv6_ra ${IFACE/$1/$3} $4 $5
[[ -d $CONF6/${IFACE/$1/$2} ]] && ipv6_ra ${IFACE/$1/$2} $4
[[ -d $CONF6/${IFACE/$1/$3} ]] && ipv6_ra ${IFACE/$1/$3} $4
}
# enable/disable ipv6 assignment per interface
ipv6_addr(){
[[ -d $CONF6/$IFACE ]] && ipv6_ra $IFACE $1 $2
[[ -d $CONF6/$VHOST ]] && ipv6_ra $VHOST $1 $2
[[ -d $CONF6/$IFACE ]] && ipv6_ra $IFACE $1
[[ -d $CONF6/$VHOST ]] && ipv6_ra $VHOST $1
# repeat action on related interfaces
if [[ ${IFACE:0:4} == bond ]]; then
ipv6_conf bond br eth $1 $2
ipv6_conf bond br eth $1
elif [[ ${IFACE:0:2} == br ]]; then
ipv6_conf br bond eth $1 $2
ipv6_conf br bond eth $1
else
ipv6_conf eth bond br $1 $2
ipv6_conf eth bond br $1
fi
sleep 1
}
@@ -366,7 +370,7 @@ ipaddr_up(){
fi
if [[ $DHCP == yes ]]; then
# bring up interface using DHCP/SLAAC
[[ -z $RENEW ]] && ipv6_addr 1 1
[[ -z $RENEW ]] && ipv6_addr 1
DHCP_OPTIONS="-q -n -p -t ${DHCP_TIMEOUT[$i]:-10}"
[[ -n $DHCP_HOSTNAME ]] && DHCP_OPTIONS="$DHCP_OPTIONS -h $DHCP_HOSTNAME"
[[ $DHCP_KEEP_RESOLV == yes ]] && DHCP_OPTIONS="$DHCP_OPTIONS -C resolv.conf"
@@ -393,27 +397,25 @@ ipaddr_up(){
# bring up interface using static IP address
if carrier $IFACE; then STATE="UP"; else STATE="DOWN"; fi
log "interface $IFACE is $STATE, setting static $IP address"
ipv6_addr 0 1
INDEX=$(index $IFACE)
INDEX=$((1000 + ${INDEX:-$(($(index * | sort -n | tail -1) + 1))}))
ipv6_addr 0
if [[ $IP != ipv6 ]]; then
[[ $j -eq 0 ]] && ADDR=${IPADDR[$i]} || ADDR=${IPADDR[$i,$j]}
if [[ -n $ADDR ]]; then
[[ $j -eq 0 ]] && MASK=${NETMASK[$i]} || MASK=${NETMASK[$i,$j]}
[[ -n $MASK ]] && run ip -4 addr add $(unzero $ADDR)/$MASK metric $INDEX dev $IFACE
[[ -n $MASK ]] && run ip -4 addr add $(unzero $ADDR)/$MASK dev $IFACE metric 1
fi
fi
if [[ $IP != ipv4 ]]; then
[[ $j -eq 0 ]] && ADDR6=${IPADDR6[$i]} || ADDR6=${IPADDR6[$i,$j]}
if [[ -n $ADDR6 ]]; then
[[ $j -eq 0 ]] && MASK6=${NETMASK6[$i]} || MASK6=${NETMASK6[$i,$j]}
[[ -n $MASK6 ]] && run ip -6 addr add $(unzero6 $ADDR6)/$MASK6 metric $INDEX dev $IFACE
[[ -n $MASK6 ]] && run ip -6 addr add $(unzero6 $ADDR6)/$MASK6 dev $IFACE metric 1
[[ -n $PRIV6 && -d $CONF6/$IFACE ]] && echo 0 >$CONF6/$IFACE/use_tempaddr
fi
fi
else
# bring up interface without IP address
ipv6_addr 0 0
ipv6_addr 0
ipaddr_down
fi
}

View File

@@ -6,6 +6,9 @@
#
# Bergware - created for Unraid OS, January 2025
# Adapted by Bergware for use in Unraid OS - June 2025
# - put metric value at end of assignment
DAEMON="WiFi network"
CALLER="wifi"
INI="/var/local/emhttp/wireless.ini"
@@ -142,17 +145,17 @@ ipaddr_up(){
INDEX=$((3000 + ${INDEX:-$(($(index * | sort -n | tail -1) + 1))}))
if [[ $IP == ipv4 ]]; then
if [[ -n $IP4 && -n $MASK4 ]]; then
run ip -4 addr add $(unzero $IP4)/$MASK4 metric $INDEX dev $PORT
run ip -4 addr add $(unzero $IP4)/$MASK4 dev $PORT metric $INDEX
# re-add IPv4 address of parent (if docker is running)
if [[ $(var DOCKER_ALLOW_ACCESS $DOCKER) == yes && -S /var/run/docker.sock ]]; then
ip addr add $(unzero $IP4)/$MASK4 metric $(($INDEX - 1)) dev shim-$PORT
ip addr add $(unzero $IP4)/$MASK4 dev shim-$PORT metric $(($INDEX - 1))
fi
fi
[[ -n $GATEWAY4 ]] && run ip -4 route add default via $GATEWAY4 metric $INDEX dev $PORT
[[ -n $GATEWAY4 ]] && run ip -4 route add default via $GATEWAY4 dev $PORT metric $INDEX
fi
if [[ $IP == ipv6 ]]; then
[[ -n $IP6 && -n $MASK6 ]] && run ip -6 addr add $(unzero6 $IP6)/$MASK6 metric $INDEX dev $PORT
[[ -n $GATEWAY6 ]] && run ip -6 route add default via $GATEWAY6 metric $INDEX dev $PORT
[[ -n $IP6 && -n $MASK6 ]] && run ip -6 addr add $(unzero6 $IP6)/$MASK6 dev $PORT metric $INDEX
[[ -n $GATEWAY6 ]] && run ip -6 route add default via $GATEWAY6 dev $PORT metric $INDEX
fi
fi
if [[ $DNS == yes ]]; then
@@ -283,7 +286,7 @@ wifi_stop(){
IPV4=$(ip -4 -br addr show scope global primary dev shim-$PORT | awk '{print $3,$4,$5;exit}')
[[ -n $IPV4 ]] && run ip addr del $IPV4 dev shim-$PORT
run ip addr flush dev $PORT
run pkill wpa_supplicant
run pkill --ns $$ wpa_supplicant
run iw dev $PORT disconnect
run rm -f $INI
# restart services when static assignments

View File

@@ -145,7 +145,6 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do
echo "DESCRIPTION:0=\"${DESCRIPTION[$i]}\"" >>$INI
echo "PROTOCOL:0=\"${PROTOCOL[$i]}\"" >>$INI
echo "USE_DHCP:0=\"${USE_DHCP[$i]}\"" >>$INI
echo "USE_GW4:0=\"${USE_GW4[$i]}\"" >>$INI
if [[ ${USE_DHCP[$i]} == yes ]]; then
# get dhcp assigned ipv4 address & mask
NET=($(ip -4 -br addr show scope global primary dev $IFACE | awk '{sub("/"," ",$3);print $3;exit}'))
@@ -162,10 +161,12 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do
echo "METRIC:0=\"${METRIC[$i]}\"" >>$INI
# store static ipv4 assignment
IPV4="$(ip -4 -br addr show scope global primary dev $IFACE | awk '{$2="";print;exit}')"
[[ -n $IPV4 ]] && echo "$IPV4" >>$STA
if [[ -n $IPV4 ]]; then
echo "$IPV4" >>$STA
echo "$IFACE GW4 $(ip -4 route show to default dev $IFACE)" >>$STA
fi
fi
echo "USE_DHCP6:0=\"${USE_DHCP6[$i]}\"" >>$INI
echo "USE_GW6:0=\"${USE_GW6[$i]}\"" >>$INI
if [[ ${USE_DHCP6[$i]} == yes ]]; then
# get auto assigned ipv6 address & prefix
NET6=($(ip -6 -br addr show scope global primary -deprecated dev $IFACE | awk '{sub("/"," ",$3);print $3;exit}'))
@@ -184,21 +185,23 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do
echo "PRIVACY6:0=\"\"" >>$INI
# store static ipv6 assignment
IPV6="$(ip -6 -br addr show scope global primary -deprecated dev $IFACE | awk '{$2="";print;exit}')"
[[ -n $IPV6 ]] && echo "$IPV6" >>$STA
if [[ -n $IPV6 ]]; then
echo "$IPV6" >>$STA
echo "$IFACE GW6 $(ip -6 route show to default dev $IFACE)" >>$STA
fi
fi
echo "USE_MTU=\"${USE_MTU[$i]}\"" >>$INI
echo "MTU=\"${MTU[$i]}\"" >>$INI
if [[ -n ${VLANS[$i]} ]]; then
# process VLAN interfaces
echo "TYPE=\"trunk\"" >>$INI
for ((j=1;j<${VLANS[$i]};j++)); do
for ((j=1; j<${VLANS[$i]}; j++)); do
echo "VLANID:$j=\"${VLANID[$i,$j]}\"" >>$INI
echo "DESCRIPTION:$j=\"${DESCRIPTION[$i,$j]}\"" >>$INI
echo "PROTOCOL:$j=\"${PROTOCOL[$i,$j]}\"" >>$INI
echo "USE_DHCP:$j=\"${USE_DHCP[$i,$j]}\"" >>$INI
echo "USE_GW4:$j=\"${USE_GW4[$i,$j]}\"" >>$INI
DEV=$IFACE.${VLANID[$i,$j]}
if [[ ${USE_DHCP[$i,$j]} == yes ]]; then
DEV=$IFACE.${VLANID[$i,$j]}
# get dhcp assigned ipv4 address & cidr2mask
NET=($(ip -4 -br addr show scope global primary dev $DEV | awk '{sub("/"," ",$3);print $3;exit}'))
GW=$(ip -4 route show to default dev $DEV | awk '{print $3;exit}')
@@ -214,12 +217,14 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do
echo "METRIC:$j=\"${METRIC[$i,$j]}\"" >>$INI
# store static ipv4 assignment
IPV4="$(ip -4 -br addr show scope global primary dev $DEV | awk '{$2="";print;exit}')"
[[ -n $IPV4 ]] && echo "$IPV4" >>$STA
if [[ -n $IPV4 ]]; then
echo "${IPV4/@$IFACE/}" >>$STA
echo "$DEV GW4 $(ip -4 route show to default dev $DEV)" >>$STA
fi
fi
echo "USE_DHCP6:$j=\"${USE_DHCP6[$i,$j]}\"" >>$INI
echo "USE_GW6:$j=\"${USE_GW6[$i,$j]}\"" >>$INI
DEV=$IFACE.${VLANID[$i,$j]}
if [[ ${USE_DHCP6[$i,$j]} == yes ]]; then
DEV=$IFACE.${VLANID[$i,$j]}
# get auto assigned ipv6 address & prefix
NET6=($(ip -6 -br addr show scope global primary -deprecated dev $DEV | awk '{sub("/"," ",$3);print $3;exit}'))
GW6=$(ip -6 route show to default dev $DEV | awk '{print $3;exit}')
@@ -237,7 +242,10 @@ for ((i=0; i<${SYSNICS:-1}; i++)); do
echo "PRIVACY6:$j=\"\"" >>$INI
# store static ipv6 assignment
IPV6="$(ip -6 -br addr show scope global primary -deprecated dev $DEV | awk '{$2="";print;exit}')"
[[ -n $IPV6 ]] && echo "$IPV6" >>$STA
if [[ -n $IPV6 ]]; then
echo "${IPV6/@$IFACE/}" >>$STA
echo "$DEV GW6 $(ip -6 route show to default dev $DEV)" >>$STA
fi
fi
done
else

View File

@@ -14,56 +14,79 @@
FILE=/var/local/emhttp/statics.ini
SYSTEM=/sys/class/net
state(){
cat $SYSTEM/$1/operstate 2>/dev/null
}
md5(){
[[ -r $FILE ]] && md5sum $FILE | awk '{print $1;exit}'
}
switch(){
local n status
[[ -z $1 ]] && return 1
status=3
# state should stay different for at least 3 seconds
for n in {1..3}; do
[[ $(state $1) != $2 ]] && ((status--))
wlan(){
[[ -e $SYSTEM/wlan0 ]]
}
carrier(){
cat $SYSTEM/$1/carrier 2>/dev/null
}
state(){
local n NEW OLD HOLD
OLD=$(carrier $1)
HOLD=4
# new state should hold for at least 4 seconds
for n in {1..4}; do
sleep 1
NEW=$(carrier $1)
[[ $NEW != $OLD ]] && ((HOLD--))
done
[[ $status -eq 0 ]]
[[ $HOLD -eq 0 ]] && echo $NEW || echo $OLD
}
init(){
PORT=(); STATE=();
TASK=()
if [[ -r $FILE ]]; then
# initialize values from file, maintained by 'create_network_ini'
while IFS=$'\n' read -r ROW; do
PORT+=("$ROW")
STATE+=($(state ${ROW%% *}))
TASK+=("$ROW")
done <$FILE
fi
MD5=$(md5)
}
while :; do
# monitor file content changes
[[ $MD5 != $(md5) ]] && init
LAST=
for i in ${!PORT[@]}; do
INT=${PORT[$i]%% *}
# did interface state change?
if switch $INT ${STATE[$i]}; then
NEW=$(state $INT)
STATE[$i]=$NEW
if [[ $NEW == up ]]; then
ip addr add dev ${PORT[$i]}
elif [[ $NEW == down && $INT != $LAST ]]; then
ip addr flush scope global dev $INT
fi
fi
LAST=$INT
done
if wlan; then
# monitor file content changes
[[ $MD5 != $(md5) ]] && init
LAST=
for i in ${!TASK[@]}; do
ADDR=(${TASK[$i]})
PORT=${ADDR[0]}
[[ $LAST != $PORT ]] && STATE=$(state $PORT)
case $STATE in
1) # up
case ${ADDR[1]} in
GW4)
# no existing default and new default is defined?
ROUTE=$(ip -4 route show to default dev $PORT)
[[ -z $ROUTE && "${TASK[$i]}" =~ "default" ]] && ip -4 route add dev ${TASK[$i]/GW4/}
;;
GW6)
# no existing default and new default is defined?
ROUTE=$(ip -6 route show to default dev $PORT)
[[ -z $ROUTE && "${TASK[$i]}" =~ "default" ]] && ip -6 route add dev ${TASK[$i]/GW6/}
;;
*)
# IP address not present? create it
[[ "$(ip -br addr show dev $PORT)" =~ "${ADDR[1]}" ]] || ip addr add dev ${TASK[$i]}
;;
esac
;;
0) # down
# IP address present, remove it
[[ "$(ip -br addr show dev $PORT)" =~ "${ADDR[1]}" ]] && ip addr del dev ${TASK[$i]}
;;
esac
LAST=$PORT
done
fi
# check every 3 seconds
sleep 3
done &