import Refresh from '@mui/icons-material/Refresh' import { Alert, Box, Button, Stack } from '@mui/material' import { Grid, IPSEC_HEADS, Section, duration, ipsecRows, text } from './RouterPanel.tsx' import Toolbar from './Toolbar.tsx' import { DETAILS_SHAPE, request, type RouterDetails } from './api.ts' import { useRead } from './useRead.ts' /** Reads the router's /config. */ const readDetails = () => request('GET', '/config', DETAILS_SHAPE) /** * How long a site-to-site connection has been up: the age of its oldest established IKE SA; "down" without one, and * "unknown" when the router could not list its SAs. */ function uptimeOf(sas: RouterDetails['ipsec']['sas'], name: string) { if (sas === null) { return 'unknown' } const ages = sas.filter((sa) => sa.name === name && sa.state === 'ESTABLISHED' && sa.established !== undefined).map((sa) => Number(sa.established)) return ages.length === 0 ? 'down' : duration(Math.max(...ages)) } /** * The state of the router's site-to-site connections, from its /config: each with the identities and subnets the * router resolved for it and how long it has been up, and their IPsec security associations, child SAs, connections * and connection children. */ export default function SiteToSiteStatusPanel() { const { data: details, error, busy, refresh } = useRead(readDetails) const names = new Set((details?.network.site_to_site ?? []).map((connection) => connection.name)) const { sas, childSas, connections, children } = ipsecRows(details, (name) => names.has(name)) return ( {error && {error}} {details && (
[ connection.name, text(connection.local_identity), text(connection.remote_identity), text(connection.local_cidrs), text(connection.remote_cidrs), uptimeOf(details.ipsec.sas, connection.name), ])} />
)}
) }