verifyCsrfToken($_POST['csrf_token'] ?? '')) { $error = 'Invalid security token. Please try again.'; } else { $postAction = $_POST['action'] ?? ''; switch ($postAction) { case 'create': if (!hasPermission('create_peers')) { $error = 'You do not have permission to create nodes.'; break; } $asnId = $_POST['asn_id'] ?? ''; $name = trim($_POST['name'] ?? ''); $description = trim($_POST['description'] ?? ''); if (empty($asnId)) { $error = 'Please select an ASN.'; break; } if (empty($name)) { $error = 'Name is required.'; break; } $config = buildNodeConfigFromForm($_POST); $result = $nodeManager->create($asnId, $name, $description, $config); if ($result['success']) { $logger->log('node', 'Created node', ['name' => $name, 'asn_id' => $asnId]); header('Location: ?page=nodes&message=Node created successfully'); exit; } else { $error = $result['message']; } break; case 'update': if (!hasPermission('edit_peers')) { $error = 'You do not have permission to edit nodes.'; break; } $id = $_POST['id'] ?? ''; $name = trim($_POST['name'] ?? ''); $description = trim($_POST['description'] ?? ''); if (empty($name)) { $error = 'Name is required.'; break; } $config = buildNodeConfigFromForm($_POST); $result = $nodeManager->update($id, [ 'name' => $name, 'description' => $description, 'config' => $config, ]); if ($result['success']) { $logger->log('node', 'Updated node', ['id' => $id, 'name' => $name]); header('Location: ?page=nodes&message=Node updated successfully'); exit; } else { $error = $result['message']; } break; case 'delete': if (!hasPermission('delete_peers')) { $error = 'You do not have permission to delete nodes.'; break; } $id = $_POST['id'] ?? ''; $node = $nodeManager->get($id); if (!$node) { $error = 'Node not found.'; break; } $result = $nodeManager->delete($id); if ($result['success']) { $logger->log('node', 'Deleted node', ['name' => $node['name']]); header('Location: ?page=nodes&message=Node deleted successfully'); exit; } else { $error = $result['message']; } break; } } } // Get message from query string if (isset($_GET['message'])) { $message = $_GET['message']; } // Helper function to build config from form function buildNodeConfigFromForm(array $post): array { $config = []; // String fields $stringFields = [ 'router_id', 'source4', 'source6', 'hostname', 'bird_directory', 'bird_socket', 'cache_directory', 'irr_server', 'rtr_server', ]; foreach ($stringFields as $field) { if (isset($post[$field]) && $post[$field] !== '') { $config[$field] = trim($post[$field]); } } // Boolean fields $booleanFields = [ 'keep_filtered', 'rpki_filter', 'irr_filter', ]; foreach ($booleanFields as $field) { if (isset($post[$field])) { $config[$field] = $post[$field] === '1'; } } // Prefixes if (!empty($post['prefixes4'])) { $config['prefixes'] = array_filter(array_map('trim', explode(',', $post['prefixes4']))); } if (!empty($post['prefixes6'])) { $config['prefixes6'] = array_filter(array_map('trim', explode(',', $post['prefixes6']))); } // Templates if (!empty($post['templates'])) { $config['templates'] = array_filter(array_map('trim', explode(',', $post['templates']))); } return $config; } // Get node for edit $editNode = null; if ($action === 'edit' && $id) { $editNode = $nodeManager->get($id); if (!$editNode) { $error = 'Node not found.'; $action = 'list'; } } // Get all ASNs and nodes $asns = $asnManager->getAll(); $nodes = $nodeManager->getAll(); // Filter by ASN if specified $filterAsnId = $_GET['asn_id'] ?? ''; if ($filterAsnId) { $nodes = array_filter($nodes, fn($n) => $n['asn_id'] === $filterAsnId); } ?>

No nodes configured

Get started by creating your first node.

Create Node
get($node['asn_id']); $nodePeers = $peerManager->getByNode($node['id']); ?>
Name ASN Router ID Description Peers
AS - View Peers Edit
No ASNs found. You need to create an ASN before creating nodes. Create ASN

Basic Information

A unique name for this node (usually the hostname)

Network Configuration

These settings override the ASN defaults for this specific node.

Node-specific IPv4 prefixes (overrides ASN defaults)

Node-specific IPv6 prefixes (overrides ASN defaults)

BIRD Configuration

Filtering Options

Templates

Comma-separated list of default templates to use for this node