Files
MikrotikManager/backend/src/services/bgp-prefix-model.ts
T

22 lines
1.7 KiB
TypeScript

import { isIP } from "node:net"
import { nativeBgpRows } from "./bgp-export-model.js"
const flag = (value: unknown) => value === true || value === "true" || value === "yes" ? true : value === false || value === "false" || value === "no" ? false : null
/** A bounded route view, not a session's received/advertised attributes table. */
export function bgpPrefixRows(payload: unknown, table: string, family: 4 | 6) {
return nativeBgpRows(payload).flatMap(row => {
if (typeof row["routing-table"] !== "string" || !row["routing-table"]) throw new Error("Unknown route table")
if (row["routing-table"] !== table) return []
const other = ["static", "connect", "ospf", "rip", "dhcp", "vpn", "modem", "isis", "bgp-mpls-vpn", "slaac", "fantasy"].some(key => flag(row[key]) === true)
if (flag(row.bgp) !== true) {
if (!other && flag(row.bgp) !== false) throw new Error("Unknown route origin")
return []
}
if (flag(row.dynamic) !== true || other || typeof row["dst-address"] !== "string" || row["dst-address"].length > 300) throw new Error("Unconfirmed BGP route")
const [address, bits, extra] = row["dst-address"].split("/")
if (extra !== undefined || isIP(address) !== family || address.includes("%") || bits === undefined || !/^\d+$/.test(bits) || Number(bits) > (family === 4 ? 32 : 128)) throw new Error("Invalid BGP prefix")
const distance = typeof row.distance === "string" && /^\d+$/.test(row.distance) && Number(row.distance) <= 255 ? Number(row.distance) : null
return [{ id: row[".id"], family, table, prefix: row["dst-address"], active: flag(row.active), distance }]
}).sort((a, b) => a.prefix.localeCompare(b.prefix) || a.id.localeCompare(b.id))
}