22 lines
1.7 KiB
TypeScript
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))
|
|
}
|