$interface, 'method' => $_POST['method'] ?? '', 'ip' => $_POST['ip'] ?? '', 'gateway' => $_POST['gateway'] ?? '', 'dns' => $_POST['dns'] ?? '', 'multicast' => $multicast ]; $network_config[$interface] = $config; file_put_contents($config_file, json_encode($network_config, JSON_PRETTY_PRINT)); // Generate netplan configuration generate_netplan_config($network_config); } elseif ($action === 'toggle') { // Toggle interface state $current_status = $interface_data[$interface]['status'] ?? 'down'; if ($current_status === 'up') { exec("sudo ip link set $interface down", $output, $return_code); } else { exec("sudo ip link set $interface up", $output, $return_code); } } } } // Generate netplan configuration file function generate_netplan_config($config) { // Create backup of cloud-init configuration $cloud_init_file = '/etc/netplan/50-cloud-init.yaml'; $backup_file = '/var/www/50-cloud-init.yaml_backup'; $source_file = '/var/www/50-cloud-init.yaml'; exec('sudo cp /etc/netplan/50-cloud-init.yaml /var/www/50-cloud-init.yaml_backup'); $netplan_content = "network:\n version: 2\n ethernets:\n"; foreach ($config as $interface => $settings) { // Skip virtual interfaces and loopback if ( strpos($interface, 'enx') === 0 || strpos($interface, 'docker') === 0 || strpos($interface, 'br-') === 0 || strpos($interface, 'veth') === 0 || $interface === 'lo' ) { continue; } $netplan_content .= " $interface:\n"; switch ($settings['method']) { case 'dhcp': $netplan_content .= " dhcp4: true\n"; break; case 'static': $netplan_content .= " addresses:\n - " . $settings['ip'] . "/24\n"; if (!empty($settings['gateway'])) { $netplan_content .= " gateway4: " . $settings['gateway'] . "\n"; } if (!empty($settings['dns'])) { $netplan_content .= " nameservers:\n addresses:\n - " . $settings['dns'] . "\n"; } break; case 'disable': default: $netplan_content .= " dhcp4: false\n"; break; } } // Write to netplan file file_put_contents('/var/www/50-cloud-init.yaml', $netplan_content); // Apply netplan configuration with validation $output = []; $return_code = 0; // Run netplan try to validate configuration exec('sudo cp /var/www/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml', $output, $return_code); exec('sudo netplan try', $output, $return_code); if ($return_code !== 0) { if (file_exists($backup_file)) { exec('sudo cp /var/www/50-cloud-init.yaml_backup /etc/netplan/50-cloud-init.yaml', $output, $return_code); exec('sudo netplan apply', $output, $return_code); } } } // Get network interfaces excluding specific ones $interfaces = []; $output = []; exec('ip addr show', $output); $current_interface = null; $interface_data = []; foreach ($output as $line) { // Match interface name if (preg_match('/^\d+:\s+([a-zA-Z0-9]+):/', $line, $matches)) { $current_interface = $matches[1]; // Skip interfaces we want to exclude if (strpos($current_interface, 'enx') === 0) { $current_interface = null; continue; } if ($current_interface === 'lo') { $current_interface = null; continue; } // Check if interface is a bridge or docker interface if ( strpos($current_interface, 'docker') === 0 || strpos($current_interface, 'br-') === 0 || strpos($current_interface, 'veth') === 0 ) { $current_interface = null; continue; } $interface_data[$current_interface] = [ 'name' => $current_interface, 'ip' => '', 'mac' => '', 'status' => 'down', 'config' => $network_config[$current_interface] ?? null ]; } // Extract IP address if ($current_interface && preg_match('/inet\s+(\d+\.\d+\.\d+\.\d+)/', $line, $matches)) { $interface_data[$current_interface]['ip'] = $matches[1]; } // Extract MAC address if ($current_interface && preg_match('/link\/ether\s+([a-f0-9:]+)/', $line, $matches)) { $interface_data[$current_interface]['mac'] = $matches[1]; } // Check if interface is up if ($current_interface && strpos($line, 'state UP') !== false) { $interface_data[$current_interface]['status'] = 'up'; } } // Get selected interface from GET parameter or first interface $selected_interface = $_GET['interface'] ?? array_keys($interface_data)[0] ?? null; ?>
IP Address:
MAC Address: