ppp.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. package cli
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "debtik/internal/auth"
  7. "debtik/internal/vpn"
  8. )
  9. // ==================== PPP (/ppp) ====================
  10. func (e *Executor) handlePPP(parts []string, user *auth.PublicUser) string {
  11. if len(parts) == 0 {
  12. return ColorRed + "Usage: /ppp [profile|secret|active]\n" + ColorReset
  13. }
  14. sub := strings.ToLower(parts[0])
  15. switch sub {
  16. case "profile":
  17. return e.handlePPPProfile(parts[1:], user)
  18. case "secret":
  19. return e.handlePPPSecret(parts[1:], user)
  20. case "active":
  21. return e.handlePPPActive(parts[1:], user)
  22. default:
  23. return fmt.Sprintf(ColorRed+"Unknown ppp command %q. Usage: /ppp [profile|secret|active]\n"+ColorReset, sub)
  24. }
  25. }
  26. // ----------------- /ppp profile -----------------
  27. func (e *Executor) handlePPPProfile(parts []string, user *auth.PublicUser) string {
  28. if e.vpnMgr == nil || e.vpnMgr.PPPServer == nil {
  29. return ColorRed + "PPP server subsystem not available.\n" + ColorReset
  30. }
  31. mgr := e.vpnMgr.PPPServer
  32. action := "print"
  33. if len(parts) > 0 {
  34. action = strings.ToLower(parts[0])
  35. parts = parts[1:]
  36. }
  37. pos, params := parseArgs(parts)
  38. switch action {
  39. case "print", "pr", "show", "list":
  40. list := mgr.ListProfiles()
  41. tbl := NewTable("#", "NAME", "LOCAL-ADDRESS", "REMOTE-ADDRESS", "DNS-SERVERS", "ENCRYPTION", "ONLY-ONE", "COMMENT")
  42. for i, p := range list {
  43. tbl.AddRow(
  44. strconv.Itoa(i),
  45. p.Name,
  46. p.LocalAddress,
  47. p.RemoteAddress,
  48. p.DNSServers,
  49. p.UseEncryption,
  50. strconv.FormatBool(p.OnlyOne),
  51. p.Comment,
  52. )
  53. }
  54. return tbl.String()
  55. case "add":
  56. if user != nil && user.Role == auth.RoleRead {
  57. return ColorRed + "Permission denied: viewer cannot modify profiles\n" + ColorReset
  58. }
  59. name := params["name"]
  60. if name == "" {
  61. if len(pos) > 0 {
  62. name = pos[0]
  63. } else {
  64. return ColorRed + "Syntax error: name is required. Usage: /ppp profile add name=<name> [local-address=...] [remote-address=...]\n" + ColorReset
  65. }
  66. }
  67. p := vpn.PPPProfile{
  68. ID: name,
  69. Name: name,
  70. LocalAddress: params["local-address"],
  71. RemoteAddress: params["remote-address"],
  72. DNSServers: params["dns-server"],
  73. UseEncryption: params["use-encryption"],
  74. Comment: params["comment"],
  75. }
  76. if p.DNSServers == "" {
  77. p.DNSServers = params["dns-servers"]
  78. }
  79. if p.LocalAddress == "" {
  80. p.LocalAddress = "10.10.10.1"
  81. }
  82. if p.RemoteAddress == "" {
  83. p.RemoteAddress = "10.10.10.10-10.10.10.50"
  84. }
  85. if p.UseEncryption == "" {
  86. p.UseEncryption = "no"
  87. }
  88. if val, ok := params["only-one"]; ok {
  89. p.OnlyOne = val == "yes" || val == "true"
  90. } else {
  91. p.OnlyOne = true
  92. }
  93. if err := mgr.SaveProfile(&p); err != nil {
  94. return ColorRed + "Error adding profile: " + err.Error() + "\n" + ColorReset
  95. }
  96. return ColorGreen + fmt.Sprintf("PPP profile %q created successfully.\n", name) + ColorReset
  97. case "set":
  98. if user != nil && user.Role == auth.RoleRead {
  99. return ColorRed + "Permission denied: viewer cannot modify profiles\n" + ColorReset
  100. }
  101. if len(pos) == 0 {
  102. return ColorRed + "Syntax error: target profile name or index required. Usage: /ppp profile set <name> [params...]\n" + ColorReset
  103. }
  104. target := pos[0]
  105. prof := mgr.GetProfile(target)
  106. if prof == nil {
  107. // Check if numeric index was provided
  108. if idx, err := strconv.Atoi(target); err == nil {
  109. all := mgr.ListProfiles()
  110. if idx >= 0 && idx < len(all) {
  111. prof = all[idx]
  112. }
  113. }
  114. }
  115. if prof == nil {
  116. return ColorRed + fmt.Sprintf("Profile %q not found.\n", target) + ColorReset
  117. }
  118. if val, ok := params["local-address"]; ok {
  119. prof.LocalAddress = val
  120. }
  121. if val, ok := params["remote-address"]; ok {
  122. prof.RemoteAddress = val
  123. }
  124. if val, ok := params["dns-server"]; ok {
  125. prof.DNSServers = val
  126. }
  127. if val, ok := params["dns-servers"]; ok {
  128. prof.DNSServers = val
  129. }
  130. if val, ok := params["use-encryption"]; ok {
  131. prof.UseEncryption = val
  132. }
  133. if val, ok := params["only-one"]; ok {
  134. prof.OnlyOne = val == "yes" || val == "true"
  135. }
  136. if val, ok := params["comment"]; ok {
  137. prof.Comment = val
  138. }
  139. if err := mgr.SaveProfile(prof); err != nil {
  140. return ColorRed + "Error updating profile: " + err.Error() + "\n" + ColorReset
  141. }
  142. return ColorGreen + fmt.Sprintf("PPP profile %q updated successfully.\n", prof.Name) + ColorReset
  143. case "remove", "delete", "rem":
  144. if user != nil && user.Role == auth.RoleRead {
  145. return ColorRed + "Permission denied: viewer cannot delete profiles\n" + ColorReset
  146. }
  147. if len(pos) == 0 {
  148. return ColorRed + "Syntax error: target profile name or index required. Usage: /ppp profile remove <name>\n" + ColorReset
  149. }
  150. target := pos[0]
  151. if prof := mgr.GetProfile(target); prof == nil {
  152. if idx, err := strconv.Atoi(target); err == nil {
  153. all := mgr.ListProfiles()
  154. if idx >= 0 && idx < len(all) {
  155. target = all[idx].Name
  156. }
  157. }
  158. }
  159. if err := mgr.DeleteProfile(target); err != nil {
  160. return ColorRed + "Error deleting profile: " + err.Error() + "\n" + ColorReset
  161. }
  162. return ColorGreen + fmt.Sprintf("PPP profile %q removed successfully.\n", target) + ColorReset
  163. default:
  164. return ColorRed + fmt.Sprintf("Unknown action %q. Usage: /ppp profile [print|add|set|remove]\n", action) + ColorReset
  165. }
  166. }
  167. // ----------------- /ppp secret -----------------
  168. func (e *Executor) handlePPPSecret(parts []string, user *auth.PublicUser) string {
  169. if e.vpnMgr == nil || e.vpnMgr.PPPServer == nil {
  170. return ColorRed + "PPP server subsystem not available.\n" + ColorReset
  171. }
  172. mgr := e.vpnMgr.PPPServer
  173. action := "print"
  174. if len(parts) > 0 {
  175. action = strings.ToLower(parts[0])
  176. parts = parts[1:]
  177. }
  178. pos, params := parseArgs(parts)
  179. switch action {
  180. case "print", "pr", "show", "list":
  181. list := mgr.ListSecrets()
  182. tbl := NewTable("#", "FLAGS", "NAME", "SERVICE", "PROFILE", "LOCAL-ADDRESS", "REMOTE-ADDRESS", "CALLER-ID", "COMMENT")
  183. for i, s := range list {
  184. flags := " "
  185. if s.Disabled {
  186. flags = "X"
  187. }
  188. tbl.AddRow(
  189. strconv.Itoa(i),
  190. flags,
  191. s.Name,
  192. s.Service,
  193. s.Profile,
  194. s.LocalAddress,
  195. s.RemoteAddress,
  196. s.CallerID,
  197. s.Comment,
  198. )
  199. }
  200. return tbl.String()
  201. case "add":
  202. if user != nil && user.Role == auth.RoleRead {
  203. return ColorRed + "Permission denied: viewer cannot add secrets\n" + ColorReset
  204. }
  205. name := params["name"]
  206. pass := params["password"]
  207. if name == "" || pass == "" {
  208. return ColorRed + "Syntax error: name and password are required. Usage: /ppp secret add name=<user> password=<pass> [profile=...] [service=any|l2tp|pptp|pppoe]\n" + ColorReset
  209. }
  210. sec := vpn.PPPSecret{
  211. Name: name,
  212. Password: pass,
  213. Service: params["service"],
  214. Profile: params["profile"],
  215. LocalAddress: params["local-address"],
  216. RemoteAddress: params["remote-address"],
  217. CallerID: params["caller-id"],
  218. Comment: params["comment"],
  219. }
  220. if sec.Service == "" {
  221. sec.Service = "any"
  222. }
  223. if sec.Profile == "" {
  224. sec.Profile = "default"
  225. }
  226. if val, ok := params["disabled"]; ok {
  227. sec.Disabled = val == "yes" || val == "true"
  228. }
  229. if err := mgr.SaveSecret(&sec); err != nil {
  230. return ColorRed + "Error adding secret: " + err.Error() + "\n" + ColorReset
  231. }
  232. return ColorGreen + fmt.Sprintf("PPP secret %q created successfully.\n", name) + ColorReset
  233. case "set":
  234. if user != nil && user.Role == auth.RoleRead {
  235. return ColorRed + "Permission denied: viewer cannot modify secrets\n" + ColorReset
  236. }
  237. if len(pos) == 0 {
  238. return ColorRed + "Syntax error: target secret name or index required. Usage: /ppp secret set <name> [params...]\n" + ColorReset
  239. }
  240. target := pos[0]
  241. sec := findSecret(mgr, target)
  242. if sec == nil {
  243. return ColorRed + fmt.Sprintf("Secret %q not found.\n", target) + ColorReset
  244. }
  245. if val, ok := params["password"]; ok {
  246. sec.Password = val
  247. }
  248. if val, ok := params["profile"]; ok {
  249. sec.Profile = val
  250. }
  251. if val, ok := params["service"]; ok {
  252. sec.Service = val
  253. }
  254. if val, ok := params["local-address"]; ok {
  255. sec.LocalAddress = val
  256. }
  257. if val, ok := params["remote-address"]; ok {
  258. sec.RemoteAddress = val
  259. }
  260. if val, ok := params["caller-id"]; ok {
  261. sec.CallerID = val
  262. }
  263. if val, ok := params["comment"]; ok {
  264. sec.Comment = val
  265. }
  266. if val, ok := params["disabled"]; ok {
  267. sec.Disabled = val == "yes" || val == "true"
  268. }
  269. if err := mgr.SaveSecret(sec); err != nil {
  270. return ColorRed + "Error updating secret: " + err.Error() + "\n" + ColorReset
  271. }
  272. return ColorGreen + fmt.Sprintf("PPP secret %q updated successfully.\n", sec.Name) + ColorReset
  273. case "remove", "delete", "rem":
  274. if user != nil && user.Role == auth.RoleRead {
  275. return ColorRed + "Permission denied: viewer cannot delete secrets\n" + ColorReset
  276. }
  277. if len(pos) == 0 {
  278. return ColorRed + "Syntax error: target secret name or index required. Usage: /ppp secret remove <name>\n" + ColorReset
  279. }
  280. sec := findSecret(mgr, pos[0])
  281. if sec == nil {
  282. return ColorRed + fmt.Sprintf("Secret %q not found.\n", pos[0]) + ColorReset
  283. }
  284. if err := mgr.DeleteSecret(sec.ID); err != nil {
  285. return ColorRed + "Error deleting secret: " + err.Error() + "\n" + ColorReset
  286. }
  287. return ColorGreen + fmt.Sprintf("PPP secret %q removed successfully.\n", sec.Name) + ColorReset
  288. case "enable":
  289. if user != nil && user.Role == auth.RoleRead {
  290. return ColorRed + "Permission denied\n" + ColorReset
  291. }
  292. if len(pos) == 0 {
  293. return ColorRed + "Usage: /ppp secret enable <name>\n" + ColorReset
  294. }
  295. sec := findSecret(mgr, pos[0])
  296. if sec == nil {
  297. return ColorRed + fmt.Sprintf("Secret %q not found.\n", pos[0]) + ColorReset
  298. }
  299. if err := mgr.SetSecretState(sec.ID, false); err != nil {
  300. return ColorRed + err.Error() + "\n" + ColorReset
  301. }
  302. return ColorGreen + fmt.Sprintf("PPP secret %q enabled.\n", sec.Name) + ColorReset
  303. case "disable":
  304. if user != nil && user.Role == auth.RoleRead {
  305. return ColorRed + "Permission denied\n" + ColorReset
  306. }
  307. if len(pos) == 0 {
  308. return ColorRed + "Usage: /ppp secret disable <name>\n" + ColorReset
  309. }
  310. sec := findSecret(mgr, pos[0])
  311. if sec == nil {
  312. return ColorRed + fmt.Sprintf("Secret %q not found.\n", pos[0]) + ColorReset
  313. }
  314. if err := mgr.SetSecretState(sec.ID, true); err != nil {
  315. return ColorRed + err.Error() + "\n" + ColorReset
  316. }
  317. return ColorGreen + fmt.Sprintf("PPP secret %q disabled.\n", sec.Name) + ColorReset
  318. default:
  319. return ColorRed + fmt.Sprintf("Unknown action %q. Usage: /ppp secret [print|add|set|remove|enable|disable]\n", action) + ColorReset
  320. }
  321. }
  322. func findSecret(mgr *vpn.PPPServerManager, target string) *vpn.PPPSecret {
  323. list := mgr.ListSecrets()
  324. for _, s := range list {
  325. if s.ID == target || s.Name == target {
  326. return s
  327. }
  328. }
  329. if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(list) {
  330. return list[idx]
  331. }
  332. return nil
  333. }
  334. // ----------------- /ppp active -----------------
  335. func (e *Executor) handlePPPActive(parts []string, user *auth.PublicUser) string {
  336. if e.vpnMgr == nil || e.vpnMgr.PPPServer == nil {
  337. return ColorRed + "PPP server subsystem not available.\n" + ColorReset
  338. }
  339. mgr := e.vpnMgr.PPPServer
  340. action := "print"
  341. if len(parts) > 0 {
  342. action = strings.ToLower(parts[0])
  343. parts = parts[1:]
  344. }
  345. pos, _ := parseArgs(parts)
  346. switch action {
  347. case "print", "pr", "show", "list":
  348. list := mgr.ListActiveSessions()
  349. tbl := NewTable("#", "INTERFACE", "USER", "SERVICE", "CALLER-ID", "ADDRESS", "UPTIME", "RX", "TX")
  350. for i, s := range list {
  351. tbl.AddRow(
  352. strconv.Itoa(i),
  353. s.Interface,
  354. s.Username,
  355. s.Service,
  356. s.CallerID,
  357. s.Address,
  358. s.Uptime,
  359. s.RxHuman,
  360. s.TxHuman,
  361. )
  362. }
  363. return tbl.String()
  364. case "remove", "disconnect", "kill":
  365. if user != nil && user.Role == auth.RoleRead {
  366. return ColorRed + "Permission denied\n" + ColorReset
  367. }
  368. if len(pos) == 0 {
  369. return ColorRed + "Usage: /ppp active remove <interface>\n" + ColorReset
  370. }
  371. iface := pos[0]
  372. if err := mgr.DisconnectSession(iface); err != nil {
  373. return ColorRed + "Error disconnecting session: " + err.Error() + "\n" + ColorReset
  374. }
  375. return ColorGreen + fmt.Sprintf("Session on %s disconnected.\n", iface) + ColorReset
  376. default:
  377. return ColorRed + fmt.Sprintf("Unknown action %q. Usage: /ppp active [print|remove <iface>]\n", action) + ColorReset
  378. }
  379. }
  380. // ==================== INTERFACE VPN SERVERS ====================
  381. // ----------------- /interface l2tp-server server -----------------
  382. func (e *Executor) handleInterfaceL2TPServer(parts []string, user *auth.PublicUser) string {
  383. if e.vpnMgr == nil || e.vpnMgr.PPPServer == nil {
  384. return ColorRed + "VPN server subsystem not available.\n" + ColorReset
  385. }
  386. mgr := e.vpnMgr.PPPServer
  387. // Skip optional "server" subkeyword if present (e.g. /interface l2tp-server server print)
  388. if len(parts) > 0 && strings.ToLower(parts[0]) == "server" {
  389. parts = parts[1:]
  390. }
  391. action := "print"
  392. if len(parts) > 0 {
  393. action = strings.ToLower(parts[0])
  394. parts = parts[1:]
  395. }
  396. _, params := parseArgs(parts)
  397. switch action {
  398. case "print", "pr", "show":
  399. cfg := mgr.GetL2TPServer()
  400. tbl := NewTable("ENABLED", "PORT", "DEFAULT-PROFILE", "USE-IPSEC", "RUNNING", "ACTIVE-SESSIONS", "LAST-ERROR")
  401. tbl.AddRow(
  402. strconv.FormatBool(cfg.Enabled),
  403. strconv.Itoa(cfg.Port),
  404. cfg.DefaultProfile,
  405. cfg.UseIPSec,
  406. strconv.FormatBool(cfg.Running),
  407. strconv.Itoa(cfg.ActiveSessions),
  408. cfg.LastError,
  409. )
  410. return tbl.String()
  411. case "set":
  412. if user != nil && user.Role == auth.RoleRead {
  413. return ColorRed + "Permission denied\n" + ColorReset
  414. }
  415. cfg := mgr.GetL2TPServer()
  416. if val, ok := params["enabled"]; ok {
  417. cfg.Enabled = val == "yes" || val == "true"
  418. }
  419. if val, ok := params["port"]; ok {
  420. if p, err := strconv.Atoi(val); err == nil && p > 0 {
  421. cfg.Port = p
  422. }
  423. }
  424. if val, ok := params["default-profile"]; ok {
  425. cfg.DefaultProfile = val
  426. }
  427. if val, ok := params["use-ipsec"]; ok {
  428. cfg.UseIPSec = val
  429. }
  430. if val, ok := params["ipsec-secret"]; ok {
  431. cfg.IPSecSecret = val
  432. }
  433. if err := mgr.SetL2TPServer(cfg); err != nil {
  434. return ColorRed + "Error applying L2TP server: " + err.Error() + "\n" + ColorReset
  435. }
  436. return ColorGreen + "L2TP server configuration updated successfully.\n" + ColorReset
  437. default:
  438. return ColorRed + fmt.Sprintf("Unknown action %q. Usage: /interface l2tp-server server [print|set enabled=yes|no default-profile=...]\n", action) + ColorReset
  439. }
  440. }
  441. // ----------------- /interface pptp-server server -----------------
  442. func (e *Executor) handleInterfacePPTPServer(parts []string, user *auth.PublicUser) string {
  443. if e.vpnMgr == nil || e.vpnMgr.PPPServer == nil {
  444. return ColorRed + "VPN server subsystem not available.\n" + ColorReset
  445. }
  446. mgr := e.vpnMgr.PPPServer
  447. if len(parts) > 0 && strings.ToLower(parts[0]) == "server" {
  448. parts = parts[1:]
  449. }
  450. action := "print"
  451. if len(parts) > 0 {
  452. action = strings.ToLower(parts[0])
  453. parts = parts[1:]
  454. }
  455. _, params := parseArgs(parts)
  456. switch action {
  457. case "print", "pr", "show":
  458. cfg := mgr.GetPPTPServer()
  459. tbl := NewTable("ENABLED", "PORT", "DEFAULT-PROFILE", "REQUIRE-MPPE", "RUNNING", "ACTIVE-SESSIONS", "LAST-ERROR")
  460. tbl.AddRow(
  461. strconv.FormatBool(cfg.Enabled),
  462. strconv.Itoa(cfg.Port),
  463. cfg.DefaultProfile,
  464. strconv.FormatBool(cfg.RequireMPPE),
  465. strconv.FormatBool(cfg.Running),
  466. strconv.Itoa(cfg.ActiveSessions),
  467. cfg.LastError,
  468. )
  469. return tbl.String()
  470. case "set":
  471. if user != nil && user.Role == auth.RoleRead {
  472. return ColorRed + "Permission denied\n" + ColorReset
  473. }
  474. cfg := mgr.GetPPTPServer()
  475. if val, ok := params["enabled"]; ok {
  476. cfg.Enabled = val == "yes" || val == "true"
  477. }
  478. if val, ok := params["port"]; ok {
  479. if p, err := strconv.Atoi(val); err == nil && p > 0 {
  480. cfg.Port = p
  481. }
  482. }
  483. if val, ok := params["default-profile"]; ok {
  484. cfg.DefaultProfile = val
  485. }
  486. if val, ok := params["require-mppe"]; ok {
  487. cfg.RequireMPPE = val == "yes" || val == "true"
  488. }
  489. if err := mgr.SetPPTPServer(cfg); err != nil {
  490. return ColorRed + "Error applying PPTP server: " + err.Error() + "\n" + ColorReset
  491. }
  492. return ColorGreen + "PPTP server configuration updated successfully.\n" + ColorReset
  493. default:
  494. return ColorRed + fmt.Sprintf("Unknown action %q. Usage: /interface pptp-server server [print|set enabled=yes|no default-profile=...]\n", action) + ColorReset
  495. }
  496. }
  497. // ----------------- /interface pppoe-server server -----------------
  498. func (e *Executor) handleInterfacePPPoEServer(parts []string, user *auth.PublicUser) string {
  499. if e.vpnMgr == nil || e.vpnMgr.PPPServer == nil {
  500. return ColorRed + "VPN server subsystem not available.\n" + ColorReset
  501. }
  502. mgr := e.vpnMgr.PPPServer
  503. if len(parts) > 0 && strings.ToLower(parts[0]) == "server" {
  504. parts = parts[1:]
  505. }
  506. action := "print"
  507. if len(parts) > 0 {
  508. action = strings.ToLower(parts[0])
  509. parts = parts[1:]
  510. }
  511. _, params := parseArgs(parts)
  512. switch action {
  513. case "print", "pr", "show":
  514. cfg := mgr.GetPPPoEServer()
  515. tbl := NewTable("ENABLED", "SERVICE-NAME", "INTERFACE", "DEFAULT-PROFILE", "ONE-SESSION-PER-HOST", "RUNNING", "ACTIVE-SESSIONS", "LAST-ERROR")
  516. tbl.AddRow(
  517. strconv.FormatBool(cfg.Enabled),
  518. cfg.ServiceName,
  519. cfg.Interface,
  520. cfg.DefaultProfile,
  521. strconv.FormatBool(cfg.OneSessionPerHost),
  522. strconv.FormatBool(cfg.Running),
  523. strconv.Itoa(cfg.ActiveSessions),
  524. cfg.LastError,
  525. )
  526. return tbl.String()
  527. case "set":
  528. if user != nil && user.Role == auth.RoleRead {
  529. return ColorRed + "Permission denied\n" + ColorReset
  530. }
  531. cfg := mgr.GetPPPoEServer()
  532. if val, ok := params["enabled"]; ok {
  533. cfg.Enabled = val == "yes" || val == "true"
  534. }
  535. if val, ok := params["service-name"]; ok {
  536. cfg.ServiceName = val
  537. }
  538. if val, ok := params["interface"]; ok {
  539. cfg.Interface = val
  540. }
  541. if val, ok := params["default-profile"]; ok {
  542. cfg.DefaultProfile = val
  543. }
  544. if val, ok := params["one-session-per-host"]; ok {
  545. cfg.OneSessionPerHost = val == "yes" || val == "true"
  546. }
  547. if val, ok := params["max-mtu"]; ok {
  548. if m, err := strconv.Atoi(val); err == nil && m > 0 {
  549. cfg.MaxMTU = m
  550. }
  551. }
  552. if val, ok := params["max-mru"]; ok {
  553. if m, err := strconv.Atoi(val); err == nil && m > 0 {
  554. cfg.MaxMRU = m
  555. }
  556. }
  557. if err := mgr.SetPPPoEServer(cfg); err != nil {
  558. return ColorRed + "Error applying PPPoE server: " + err.Error() + "\n" + ColorReset
  559. }
  560. return ColorGreen + "PPPoE server configuration updated successfully.\n" + ColorReset
  561. default:
  562. return ColorRed + fmt.Sprintf("Unknown action %q. Usage: /interface pppoe-server server [print|set enabled=yes|no interface=... default-profile=...]\n", action) + ColorReset
  563. }
  564. }