mirror of
https://github.com/unraid/webgui.git
synced 2025-12-31 14:40:36 -06:00
163 lines
6.4 KiB
PHP
Executable File
163 lines
6.4 KiB
PHP
Executable File
#!/usr/bin/php -q
|
|
<?PHP
|
|
/* Copyright 2005-2025, Lime Technology
|
|
* Copyright 2012-2025, Bergware International.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*/
|
|
?>
|
|
<?
|
|
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
|
require_once "$docroot/webGui/include/Wrappers.php";
|
|
|
|
// exit when missing parameters
|
|
if ($argc == 1) exit;
|
|
|
|
$set = $ifname = $argv[1];
|
|
$run = $set !== 'none';
|
|
$dns = $set === 'renew';
|
|
$ini = parse_ini_file('/var/local/emhttp/network.ini',true); ksort($ini,SORT_NATURAL);
|
|
$cfg = '/boot/config/network.cfg';
|
|
|
|
function port_exists($port) {
|
|
$sys = '/sys/class/net';
|
|
return file_exists("$sys/$port");
|
|
}
|
|
|
|
function port($x) {
|
|
$sys = '/sys/class/net';
|
|
return file_exists("$sys/br{$x}") ? "br{$x}" : (file_exists("$sys/bond{$x}") ? "bond{$x}" : (file_exists("$sys/eth{$x}") ? "eth{$x}" : false));
|
|
}
|
|
|
|
function update_wireguard($ifname) {
|
|
$nic = port(0);
|
|
if (!in_array($ifname,['br0','bond0','eth0']) || !$nic) return;
|
|
exec("wg show interfaces | tr ' ' '\n'",$active);
|
|
foreach (glob("/etc/wireguard/*.conf",GLOB_NOSORT) as $wg) {
|
|
$vtun = basename($wg,'.conf');
|
|
// interface has changed?
|
|
if (exec("grep -Pom1 ' dev $nic ' $wg")=='') {
|
|
my_logger("updated wireguard $vtun configuration", 'netconfig');
|
|
exec("sed -ri 's/ dev (br0|bond0|eth0) / dev $nic /' $wg");
|
|
}
|
|
// restart active wireguard tunnels
|
|
if (in_array($vtun,$active)) exec("wg-quick down $vtun; sleep 1; wg-quick up $vtun");
|
|
}
|
|
}
|
|
|
|
function ifname($name) {
|
|
global $old;
|
|
if (!$name) return;
|
|
for ($i=0; $i<$old['SYSNICS']; $i++) {
|
|
$nics = $old['BONDNICS'][$i] ?? $old['BRNICS'][$i] ?? '';
|
|
if (strpos("$nics ","$name ")!==false) return $old['IFNAME'][$i];
|
|
}
|
|
return $name;
|
|
}
|
|
|
|
function bond_nics(&$bond,$nic) {
|
|
$bond['BONDNICS'] = str_replace(',',' ',$bond['BONDNICS']);
|
|
return explode(' ',preg_replace("/$nic ?/","",$bond['BONDNICS']));
|
|
}
|
|
|
|
function bridge_nics(&$bridge,$nic) {
|
|
$bridge['BRNICS'] = str_replace(',',' ',$bridge['BRNICS']);
|
|
return explode(' ',preg_replace("/$nic ?/","",$bridge['BRNICS']));
|
|
}
|
|
|
|
// stop interface with existing (old) configuration
|
|
// don't execute when only interface description has changed
|
|
if ($run) {
|
|
if ($dns) {
|
|
$cmd = 'start_renew';
|
|
$ifname = port(0);
|
|
if ($ifname) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$ifname}_stop_renew")." >/dev/null");
|
|
} else {
|
|
$cmd = 'start';
|
|
$old = [];
|
|
if (file_exists($cfg)) {
|
|
$old = parse_ini_string(preg_replace(['/^#/m',"/\r/m"],[';',''],file_get_contents($cfg)));
|
|
if (isset($old['SYSNICS'])) {
|
|
// new syntax
|
|
$ifname = ifname($set);
|
|
} else {
|
|
// legacy syntax
|
|
if ($set=='eth0') $ifname = $old['BRIDGING']=='yes' ? ($old['BRNAME'] ?? 'br0') : ($old['BONDING']=='yes' ? ($old['BONDNAME'] ?? 'bond0') : $set);
|
|
}
|
|
}
|
|
exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$ifname}_stop")." >/dev/null");
|
|
if ($ini[$set]['BONDING']=='yes') {
|
|
// release additional NICs in bond
|
|
foreach (bond_nics($ini[$set],$set) as $nic) {
|
|
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
|
if ($nic && $nic!=$ifname && port_exists($nic)) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$nic}_stop")." >/dev/null");
|
|
}
|
|
} elseif ($ini[$set]['BRIDGING']=='yes') {
|
|
// release additional NICs in bridge
|
|
foreach (bridge_nics($ini[$set],$set) as $nic) {
|
|
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
|
if ($nic && $nic!=$ifname && port_exists($nic)) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$nic}_stop")." >/dev/null");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// create configuration file for all available interfaces
|
|
$i = 0; $new = ["# Generated settings:"];
|
|
foreach ($ini as $name => $port) {
|
|
$bonding = $port['BONDING']=='yes';
|
|
$bridging = $port['BRIDGING']=='yes';
|
|
if (!port_exists($name)) continue;
|
|
if ($bonding && in_array($name,bond_nics($port,$name))) continue;
|
|
if ($bridging && in_array($name,bridge_nics($port,$name))) continue;
|
|
$trunk = $port['TYPE']=='trunk';
|
|
$j = 0; $x0 = 0;
|
|
$iface = $bridging ? $port['BRNAME'] : ($bonding ? $port['BONDNAME'] : $name);
|
|
$new[] = "IFNAME[$i]=\"$iface\"";
|
|
if ($set==$name) $ifname = $iface;
|
|
foreach ($port as $key => $val) {
|
|
if (!strlen($val)) continue;
|
|
if (preg_match('/^(TYPE|BONDING$|BRIDGING)/',$key)) continue;
|
|
if (!$bonding && preg_match('/^(BONDING_MODE|BONDING_MIIMON|BONDNICS|BONDNAME)/',$key)) continue;
|
|
if (!$bridging && preg_match('/^(BRSTP|BRFD|BRNICS|BRNAME)/',$key)) continue;
|
|
[$item,$x] = array_pad(explode(':',$key,2),2,0);
|
|
if ($trunk && $x>0 && preg_match('/^(VLANID|USE_DHCP6?|IPADDR6?|NETMASK6?|GATEWAY6?|METRIC|PRIVACY6|DESCRIPTION|PROTOCOL)/',$key)) {
|
|
if ($x0 != $x) {$x0 = $x; $j++;}
|
|
$vlan = ",$j]";
|
|
} else $vlan = '';
|
|
if (!$vlan && preg_match('/^VLANID/',$key)) continue;
|
|
if ($item=='DHCP_KEEPRESOLV') $DHCP_KEEPRESOLV = $val;
|
|
if ($item=='DHCP6_KEEPRESOLV') $DHCP6_KEEPRESOLV = $val;
|
|
if ($item=='PROTOCOL') $PROTOCOL = $val;
|
|
if ($item=='USE_DHCP') $USE_DHCP = $val;
|
|
if ($item=='USE_DHCP6') $USE_DHCP6 = $val;
|
|
if (in_array($item,['IPADDR','NETMASK','GATEWAY']) && $USE_DHCP!='no') continue;
|
|
if (in_array($item,['IPADDR6','NETMASK6','GATEWAY6']) && $USE_DHCP6!='no') continue;
|
|
if (preg_match('/^DNS_SERVER/',$key) && isset($DHCP_KEEPRESOLV) && $DHCP_KEEPRESOLV=='no') continue;
|
|
if (preg_match('/^DNS6_SERVER/',$key) && isset($DHCP6_KEEPRESOLV) && $DHCP6_KEEPRESOLV=='no') continue;
|
|
if ($item=='PRIVACY6' && $PROTOCOL=='ipv4') continue;
|
|
if ($item=='METRIC' && $PROTOCOL=='ipv6') continue;
|
|
if ($item=='METRIC6' && $PROTOCOL=='ipv4') continue;
|
|
$new[] = $item.(preg_match('/^(DNS6?_SERVER|DHCP6?_KEEPRESOLV)/',$key)?'':'['.$i.($vlan?'':']')).$vlan."=\"$val\"";
|
|
}
|
|
if ($trunk) $new[] = "VLANS[$i]=\"".($j+1)."\"";
|
|
$i++;
|
|
}
|
|
$new[] = "SYSNICS=\"$i\"";
|
|
file_put_contents($cfg,implode("\r\n",$new)."\r\n");
|
|
|
|
// start interface with updated (new) configuration
|
|
// don't execute when only interface description has changed
|
|
if ($run) {
|
|
exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$ifname}_{$cmd}")." >/dev/null");
|
|
exec("/usr/local/sbin/create_network_ini ".escapeshellarg($ifname)." &>/dev/null &");
|
|
if (!$dns) update_wireguard($ifname);
|
|
}
|
|
exit(0);
|
|
?>
|