dynamic_routing_handlers.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. package api
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "proxmox-router/internal/dynamicrouting"
  6. )
  7. // Summary
  8. func (s *Server) handleDynamicRoutingSummary(w http.ResponseWriter, r *http.Request) {
  9. summary := s.dynRoutingMgr.GetSummary()
  10. writeJSON(w, http.StatusOK, summary)
  11. }
  12. // -------------------------------------------------------------
  13. // BGP Handlers
  14. // -------------------------------------------------------------
  15. func (s *Server) handleGetBGPInstance(w http.ResponseWriter, r *http.Request) {
  16. inst := s.dynRoutingMgr.GetBGPInstance()
  17. writeJSON(w, http.StatusOK, inst)
  18. }
  19. func (s *Server) handleUpdateBGPInstance(w http.ResponseWriter, r *http.Request) {
  20. var inst dynamicrouting.BGPInstance
  21. if err := json.NewDecoder(r.Body).Decode(&inst); err != nil {
  22. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  23. return
  24. }
  25. if err := s.dynRoutingMgr.UpdateBGPInstance(inst); err != nil {
  26. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  27. return
  28. }
  29. writeJSON(w, http.StatusOK, s.dynRoutingMgr.GetBGPInstance())
  30. }
  31. func (s *Server) handleListBGPPeers(w http.ResponseWriter, r *http.Request) {
  32. peers := s.dynRoutingMgr.ListBGPPeers()
  33. if peers == nil {
  34. peers = []dynamicrouting.BGPPeer{}
  35. }
  36. writeJSON(w, http.StatusOK, peers)
  37. }
  38. func (s *Server) handleSaveBGPPeer(w http.ResponseWriter, r *http.Request) {
  39. var peer dynamicrouting.BGPPeer
  40. if err := json.NewDecoder(r.Body).Decode(&peer); err != nil {
  41. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  42. return
  43. }
  44. if peer.RemoteAddress == "" || peer.RemoteAS == 0 {
  45. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "remote_address and remote_as are required"})
  46. return
  47. }
  48. if err := s.dynRoutingMgr.SaveBGPPeer(&peer); err != nil {
  49. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  50. return
  51. }
  52. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "peer": peer})
  53. }
  54. func (s *Server) handleDeleteBGPPeer(w http.ResponseWriter, r *http.Request) {
  55. id := r.PathValue("id")
  56. if id == "" {
  57. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing peer id"})
  58. return
  59. }
  60. if err := s.dynRoutingMgr.DeleteBGPPeer(id); err != nil {
  61. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  62. return
  63. }
  64. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  65. }
  66. func (s *Server) handleSetBGPPeerState(w http.ResponseWriter, r *http.Request) {
  67. id := r.PathValue("id")
  68. var req struct {
  69. Disabled bool `json:"disabled"`
  70. }
  71. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  72. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON"})
  73. return
  74. }
  75. if err := s.dynRoutingMgr.SetBGPPeerState(id, req.Disabled); err != nil {
  76. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  77. return
  78. }
  79. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "disabled": req.Disabled})
  80. }
  81. func (s *Server) handleListBGPNetworks(w http.ResponseWriter, r *http.Request) {
  82. nets := s.dynRoutingMgr.ListBGPNetworks()
  83. if nets == nil {
  84. nets = []dynamicrouting.BGPNetwork{}
  85. }
  86. writeJSON(w, http.StatusOK, nets)
  87. }
  88. func (s *Server) handleSaveBGPNetwork(w http.ResponseWriter, r *http.Request) {
  89. var net dynamicrouting.BGPNetwork
  90. if err := json.NewDecoder(r.Body).Decode(&net); err != nil {
  91. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  92. return
  93. }
  94. if net.Network == "" {
  95. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "network (CIDR) is required"})
  96. return
  97. }
  98. if err := s.dynRoutingMgr.SaveBGPNetwork(net); err != nil {
  99. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  100. return
  101. }
  102. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "network": net})
  103. }
  104. func (s *Server) handleDeleteBGPNetwork(w http.ResponseWriter, r *http.Request) {
  105. id := r.PathValue("id")
  106. if id == "" {
  107. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing network id"})
  108. return
  109. }
  110. if err := s.dynRoutingMgr.DeleteBGPNetwork(id); err != nil {
  111. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  112. return
  113. }
  114. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  115. }
  116. func (s *Server) handleGetBGPRoutes(w http.ResponseWriter, r *http.Request) {
  117. routes := s.dynRoutingMgr.GetBGPRoutes()
  118. if routes == nil {
  119. routes = []dynamicrouting.BGPRoute{}
  120. }
  121. writeJSON(w, http.StatusOK, routes)
  122. }
  123. // -------------------------------------------------------------
  124. // OSPF Handlers (RouterOS v7 Style OSPF)
  125. // -------------------------------------------------------------
  126. func (s *Server) handleListOSPFInstances(w http.ResponseWriter, r *http.Request) {
  127. insts := s.dynRoutingMgr.ListOSPFInstances()
  128. if insts == nil {
  129. insts = []dynamicrouting.OSPFInstance{}
  130. }
  131. writeJSON(w, http.StatusOK, insts)
  132. }
  133. func (s *Server) handleSaveOSPFInstance(w http.ResponseWriter, r *http.Request) {
  134. var inst dynamicrouting.OSPFInstance
  135. if err := json.NewDecoder(r.Body).Decode(&inst); err != nil {
  136. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  137. return
  138. }
  139. if err := s.dynRoutingMgr.SaveOSPFInstance(&inst); err != nil {
  140. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  141. return
  142. }
  143. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "instance": inst})
  144. }
  145. func (s *Server) handleDeleteOSPFInstance(w http.ResponseWriter, r *http.Request) {
  146. id := r.PathValue("id")
  147. if id == "" {
  148. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing instance id"})
  149. return
  150. }
  151. if err := s.dynRoutingMgr.DeleteOSPFInstance(id); err != nil {
  152. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  153. return
  154. }
  155. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  156. }
  157. func (s *Server) handleSetOSPFInstanceState(w http.ResponseWriter, r *http.Request) {
  158. id := r.PathValue("id")
  159. var req struct {
  160. Disabled bool `json:"disabled"`
  161. }
  162. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  163. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON"})
  164. return
  165. }
  166. if err := s.dynRoutingMgr.SetOSPFInstanceState(id, req.Disabled); err != nil {
  167. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  168. return
  169. }
  170. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "disabled": req.Disabled})
  171. }
  172. func (s *Server) handleGetOSPFInstance(w http.ResponseWriter, r *http.Request) {
  173. inst := s.dynRoutingMgr.GetOSPFInstance()
  174. writeJSON(w, http.StatusOK, inst)
  175. }
  176. func (s *Server) handleUpdateOSPFInstance(w http.ResponseWriter, r *http.Request) {
  177. var inst dynamicrouting.OSPFInstance
  178. if err := json.NewDecoder(r.Body).Decode(&inst); err != nil {
  179. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  180. return
  181. }
  182. if err := s.dynRoutingMgr.UpdateOSPFInstance(inst); err != nil {
  183. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  184. return
  185. }
  186. writeJSON(w, http.StatusOK, s.dynRoutingMgr.GetOSPFInstance())
  187. }
  188. func (s *Server) handleListOSPFAreas(w http.ResponseWriter, r *http.Request) {
  189. areas := s.dynRoutingMgr.ListOSPFAreas()
  190. if areas == nil {
  191. areas = []dynamicrouting.OSPFArea{}
  192. }
  193. writeJSON(w, http.StatusOK, areas)
  194. }
  195. func (s *Server) handleSaveOSPFArea(w http.ResponseWriter, r *http.Request) {
  196. var area dynamicrouting.OSPFArea
  197. if err := json.NewDecoder(r.Body).Decode(&area); err != nil {
  198. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  199. return
  200. }
  201. if area.AreaID == "" {
  202. area.AreaID = "0.0.0.0"
  203. }
  204. if err := s.dynRoutingMgr.SaveOSPFArea(area); err != nil {
  205. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  206. return
  207. }
  208. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "area": area})
  209. }
  210. func (s *Server) handleDeleteOSPFArea(w http.ResponseWriter, r *http.Request) {
  211. id := r.PathValue("id")
  212. if id == "" {
  213. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing area id"})
  214. return
  215. }
  216. if err := s.dynRoutingMgr.DeleteOSPFArea(id); err != nil {
  217. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  218. return
  219. }
  220. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  221. }
  222. func (s *Server) handleSetOSPFAreaState(w http.ResponseWriter, r *http.Request) {
  223. id := r.PathValue("id")
  224. var req struct {
  225. Disabled bool `json:"disabled"`
  226. }
  227. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  228. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON"})
  229. return
  230. }
  231. if err := s.dynRoutingMgr.SetOSPFAreaState(id, req.Disabled); err != nil {
  232. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  233. return
  234. }
  235. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "disabled": req.Disabled})
  236. }
  237. // Area Ranges
  238. func (s *Server) handleListOSPFAreaRanges(w http.ResponseWriter, r *http.Request) {
  239. ranges := s.dynRoutingMgr.ListOSPFAreaRanges()
  240. if ranges == nil {
  241. ranges = []dynamicrouting.OSPFAreaRange{}
  242. }
  243. writeJSON(w, http.StatusOK, ranges)
  244. }
  245. func (s *Server) handleSaveOSPFAreaRange(w http.ResponseWriter, r *http.Request) {
  246. var ar dynamicrouting.OSPFAreaRange
  247. if err := json.NewDecoder(r.Body).Decode(&ar); err != nil {
  248. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  249. return
  250. }
  251. if ar.Prefix == "" {
  252. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Prefix is required"})
  253. return
  254. }
  255. if err := s.dynRoutingMgr.SaveOSPFAreaRange(ar); err != nil {
  256. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  257. return
  258. }
  259. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "area_range": ar})
  260. }
  261. func (s *Server) handleDeleteOSPFAreaRange(w http.ResponseWriter, r *http.Request) {
  262. id := r.PathValue("id")
  263. if id == "" {
  264. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing range id"})
  265. return
  266. }
  267. if err := s.dynRoutingMgr.DeleteOSPFAreaRange(id); err != nil {
  268. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  269. return
  270. }
  271. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  272. }
  273. // Interface Templates
  274. func (s *Server) handleListOSPFInterfaces(w http.ResponseWriter, r *http.Request) {
  275. ifaces := s.dynRoutingMgr.ListOSPFInterfaces()
  276. if ifaces == nil {
  277. ifaces = []dynamicrouting.OSPFInterface{}
  278. }
  279. writeJSON(w, http.StatusOK, ifaces)
  280. }
  281. func (s *Server) handleSaveOSPFInterface(w http.ResponseWriter, r *http.Request) {
  282. var iface dynamicrouting.OSPFInterface
  283. if err := json.NewDecoder(r.Body).Decode(&iface); err != nil {
  284. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  285. return
  286. }
  287. if err := s.dynRoutingMgr.SaveOSPFInterface(iface); err != nil {
  288. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  289. return
  290. }
  291. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "interface": iface})
  292. }
  293. func (s *Server) handleDeleteOSPFInterface(w http.ResponseWriter, r *http.Request) {
  294. id := r.PathValue("id")
  295. if id == "" {
  296. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing interface id"})
  297. return
  298. }
  299. if err := s.dynRoutingMgr.DeleteOSPFInterface(id); err != nil {
  300. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  301. return
  302. }
  303. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  304. }
  305. func (s *Server) handleSetOSPFInterfaceState(w http.ResponseWriter, r *http.Request) {
  306. id := r.PathValue("id")
  307. var req struct {
  308. Disabled bool `json:"disabled"`
  309. }
  310. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  311. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON"})
  312. return
  313. }
  314. if err := s.dynRoutingMgr.SetOSPFInterfaceState(id, req.Disabled); err != nil {
  315. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  316. return
  317. }
  318. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "disabled": req.Disabled})
  319. }
  320. // Live Dynamic Interfaces
  321. func (s *Server) handleGetOSPFInterfacesLive(w http.ResponseWriter, r *http.Request) {
  322. live := s.dynRoutingMgr.GetOSPFInterfacesLive()
  323. if live == nil {
  324. live = []dynamicrouting.OSPFInterfaceLive{}
  325. }
  326. writeJSON(w, http.StatusOK, live)
  327. }
  328. // Static Neighbors
  329. func (s *Server) handleListOSPFStaticNeighbors(w http.ResponseWriter, r *http.Request) {
  330. nbrs := s.dynRoutingMgr.ListOSPFStaticNeighbors()
  331. if nbrs == nil {
  332. nbrs = []dynamicrouting.OSPFStaticNeighbor{}
  333. }
  334. writeJSON(w, http.StatusOK, nbrs)
  335. }
  336. func (s *Server) handleSaveOSPFStaticNeighbor(w http.ResponseWriter, r *http.Request) {
  337. var nbr dynamicrouting.OSPFStaticNeighbor
  338. if err := json.NewDecoder(r.Body).Decode(&nbr); err != nil {
  339. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  340. return
  341. }
  342. if nbr.Address == "" {
  343. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Address is required"})
  344. return
  345. }
  346. if err := s.dynRoutingMgr.SaveOSPFStaticNeighbor(nbr); err != nil {
  347. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  348. return
  349. }
  350. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "neighbor": nbr})
  351. }
  352. func (s *Server) handleDeleteOSPFStaticNeighbor(w http.ResponseWriter, r *http.Request) {
  353. id := r.PathValue("id")
  354. if id == "" {
  355. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing static neighbor id"})
  356. return
  357. }
  358. if err := s.dynRoutingMgr.DeleteOSPFStaticNeighbor(id); err != nil {
  359. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  360. return
  361. }
  362. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  363. }
  364. // Live Neighbors
  365. func (s *Server) handleGetOSPFNeighbors(w http.ResponseWriter, r *http.Request) {
  366. nbrs := s.dynRoutingMgr.GetOSPFNeighbors()
  367. if nbrs == nil {
  368. nbrs = []dynamicrouting.OSPFNeighbor{}
  369. }
  370. writeJSON(w, http.StatusOK, nbrs)
  371. }
  372. // Live LSA Database
  373. func (s *Server) handleGetOSPFLSA(w http.ResponseWriter, r *http.Request) {
  374. lsa := s.dynRoutingMgr.GetOSPFLSA()
  375. if lsa == nil {
  376. lsa = []dynamicrouting.OSPFLSA{}
  377. }
  378. writeJSON(w, http.StatusOK, lsa)
  379. }
  380. func (s *Server) handleGetOSPFRoutes(w http.ResponseWriter, r *http.Request) {
  381. routes := s.dynRoutingMgr.GetOSPFRoutes()
  382. if routes == nil {
  383. routes = []dynamicrouting.OSPFRoute{}
  384. }
  385. writeJSON(w, http.StatusOK, routes)
  386. }
  387. // -------------------------------------------------------------
  388. // Routing Filters Handlers (/routing filter)
  389. // -------------------------------------------------------------
  390. func (s *Server) handleListRoutingFilters(w http.ResponseWriter, r *http.Request) {
  391. filters := s.dynRoutingMgr.ListRoutingFilters()
  392. if filters == nil {
  393. filters = []dynamicrouting.RoutingFilterRule{}
  394. }
  395. writeJSON(w, http.StatusOK, filters)
  396. }
  397. func (s *Server) handleSaveRoutingFilter(w http.ResponseWriter, r *http.Request) {
  398. var rule dynamicrouting.RoutingFilterRule
  399. if err := json.NewDecoder(r.Body).Decode(&rule); err != nil {
  400. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON: " + err.Error()})
  401. return
  402. }
  403. if rule.Chain == "" {
  404. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Chain name is required"})
  405. return
  406. }
  407. if rule.Action == "" {
  408. rule.Action = "accept"
  409. }
  410. if err := s.dynRoutingMgr.SaveRoutingFilter(&rule); err != nil {
  411. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  412. return
  413. }
  414. writeJSON(w, http.StatusOK, map[string]string{"status": "success", "id": rule.ID})
  415. }
  416. func (s *Server) handleDeleteRoutingFilter(w http.ResponseWriter, r *http.Request) {
  417. id := r.PathValue("id")
  418. if id == "" {
  419. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing filter rule ID"})
  420. return
  421. }
  422. if err := s.dynRoutingMgr.DeleteRoutingFilter(id); err != nil {
  423. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  424. return
  425. }
  426. writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
  427. }
  428. func (s *Server) handleSetRoutingFilterState(w http.ResponseWriter, r *http.Request) {
  429. id := r.PathValue("id")
  430. if id == "" {
  431. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Missing filter rule ID"})
  432. return
  433. }
  434. var req struct {
  435. Disabled bool `json:"disabled"`
  436. }
  437. if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
  438. writeJSON(w, http.StatusBadRequest, map[string]string{"error": "Invalid JSON"})
  439. return
  440. }
  441. if err := s.dynRoutingMgr.SetRoutingFilterState(id, req.Disabled); err != nil {
  442. writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()})
  443. return
  444. }
  445. writeJSON(w, http.StatusOK, map[string]interface{}{"status": "success", "disabled": req.Disabled})
  446. }