import type { Server, VxlanTunnel } from "./data" /** RouterOS string literals: https://help.mikrotik.com/docs/spaces/ROS/pages/47579229/Scripting */ export function quoteRosString(value: string): string { return '"' + value.replace(/[\\"$\x00-\x1f\x7f]/g, char => { if (char === "\\" || char === '"' || char === "$") return "\\" + char return "\\" + char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0") }) + '"' } const commentLine = (value: string) => value.replace(/[\r\n\x00-\x1f\x7f]/g, " ") /** A configuration fragment, not a full RouterOS export: bridge/FDB are not available in this API. */ export function generateVxlanRsc(t: VxlanTunnel, servers: Record): string { const server = servers[t.serverId] const lines = [`# VXLAN — ${commentLine(t.name)} · VNI ${t.vni}`] if (server) lines.push(`# Сервер: ${commentLine(server.name)} (${commentLine(server.host)})`) lines.push("# RouterOS 7.x · интерфейс и статические VTEP; bridge/FDB не включены", "") const args = [ `name=${quoteRosString(t.name)}`, `vni=${t.vni}`, `port=${t.dstPort}`, `arp=${quoteRosString(t.arpMode ?? (t.arpProxy ? "proxy-arp" : "enabled"))}`, `learning=${t.macLearning ? "yes" : "no"}`, `disabled=${t.enabled ? "no" : "yes"}`, `comment=${quoteRosString(t.comment)}`, ] if (t.vtepIp) args.push(`local-address=${quoteRosString(t.vtepIp)}`) lines.push("/interface/vxlan/add " + args.join(" ")) for (const remote of t.remoteVteps) lines.push(`/interface/vxlan/vteps/add interface=${quoteRosString(t.name)} remote-ip=${quoteRosString(remote)}`) return lines.join("\n") + "\n" }