|
@@ -2234,49 +2234,1090 @@ func (e *Executor) handleRoutingBGP(parts []string, user *auth.PublicUser) strin
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func parseCLIEnableDisable(val string, defaultVal bool) bool {
|
|
|
|
|
+ v := strings.ToLower(strings.TrimSpace(val))
|
|
|
|
|
+ if v == "yes" || v == "true" || v == "1" || v == "enable" || v == "enabled" {
|
|
|
|
|
+ return true
|
|
|
|
|
+ }
|
|
|
|
|
+ if v == "no" || v == "false" || v == "0" || v == "disable" || v == "disabled" {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+ return defaultVal
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (e *Executor) handleRoutingOSPF(parts []string, user *auth.PublicUser) string {
|
|
func (e *Executor) handleRoutingOSPF(parts []string, user *auth.PublicUser) string {
|
|
|
- if len(parts) == 0 || parts[0] == "instance" {
|
|
|
|
|
|
|
+ if len(parts) == 0 {
|
|
|
|
|
+ return e.handleOSPFInstance([]string{"print"}, user)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sub := strings.ToLower(parts[0])
|
|
|
|
|
+ switch sub {
|
|
|
|
|
+ case "instance", "instances":
|
|
|
|
|
+ return e.handleOSPFInstance(parts[1:], user)
|
|
|
|
|
+ case "area", "areas":
|
|
|
|
|
+ if len(parts) > 1 && (strings.EqualFold(parts[1], "range") || strings.EqualFold(parts[1], "ranges")) {
|
|
|
|
|
+ return e.handleOSPFAreaRange(parts[2:], user)
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.handleOSPFArea(parts[1:], user)
|
|
|
|
|
+ case "area-range", "area-ranges", "range", "ranges":
|
|
|
|
|
+ return e.handleOSPFAreaRange(parts[1:], user)
|
|
|
|
|
+ case "interface", "interfaces", "template", "templates", "interface-template", "interface-templates":
|
|
|
|
|
+ return e.handleOSPFInterface(parts[1:], user)
|
|
|
|
|
+ case "static-neighbor", "static-neighbors":
|
|
|
|
|
+ return e.handleOSPFStaticNeighbor(parts[1:], user)
|
|
|
|
|
+ case "neighbor", "neighbors":
|
|
|
|
|
+ return e.handleOSPFNeighborLive(parts[1:], user)
|
|
|
|
|
+ case "lsa", "lsadb":
|
|
|
|
|
+ return e.handleOSPFLSA(parts[1:], user)
|
|
|
|
|
+ case "route", "routes":
|
|
|
|
|
+ return e.handleOSPFRoute(parts[1:], user)
|
|
|
|
|
+ default:
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf [instance|area|area-range|interface|static-neighbor|neighbor|lsa|routes]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFInstance(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ if len(parts) == 0 || parts[0] == "print" || parts[0] == "pr" {
|
|
|
instances := e.dynRoutingMgr.ListOSPFInstances()
|
|
instances := e.dynRoutingMgr.ListOSPFInstances()
|
|
|
- tbl := NewTable("NAME", "ROUTER-ID", "VERSION", "STATUS")
|
|
|
|
|
- for _, inst := range instances {
|
|
|
|
|
|
|
+ tbl := NewTable("#", "NAME", "ROUTER-ID", "VERSION", "REDISTRIBUTE", "DEFAULT-METRIC", "STATUS")
|
|
|
|
|
+ for idx, inst := range instances {
|
|
|
st := "enabled"
|
|
st := "enabled"
|
|
|
if inst.Disabled {
|
|
if inst.Disabled {
|
|
|
st = "disabled"
|
|
st = "disabled"
|
|
|
}
|
|
}
|
|
|
- tbl.AddRow(inst.Name, inst.RouterID, fmt.Sprintf("%d", inst.Version), st)
|
|
|
|
|
|
|
+ var redist []string
|
|
|
|
|
+ if inst.RedistributeConnected {
|
|
|
|
|
+ redist = append(redist, "connected")
|
|
|
|
|
+ }
|
|
|
|
|
+ if inst.RedistributeStatic {
|
|
|
|
|
+ redist = append(redist, "static")
|
|
|
|
|
+ }
|
|
|
|
|
+ if inst.RedistributeBGP {
|
|
|
|
|
+ redist = append(redist, "bgp")
|
|
|
|
|
+ }
|
|
|
|
|
+ redistStr := "-"
|
|
|
|
|
+ if len(redist) > 0 {
|
|
|
|
|
+ redistStr = strings.Join(redist, ",")
|
|
|
|
|
+ }
|
|
|
|
|
+ metricStr := "-"
|
|
|
|
|
+ if inst.DefaultMetric > 0 {
|
|
|
|
|
+ metricStr = fmt.Sprintf("%d", inst.DefaultMetric)
|
|
|
|
|
+ }
|
|
|
|
|
+ tbl.AddRow(fmt.Sprintf("%d", idx), inst.Name, inst.RouterID, fmt.Sprintf("%d", inst.Version), redistStr, metricStr, st)
|
|
|
}
|
|
}
|
|
|
return tbl.String()
|
|
return tbl.String()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if user.Role == auth.RoleRead {
|
|
|
|
|
+ return ColorRed + "Permission denied: viewer role cannot modify OSPF\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
sub := strings.ToLower(parts[0])
|
|
sub := strings.ToLower(parts[0])
|
|
|
switch sub {
|
|
switch sub {
|
|
|
- case "area", "areas":
|
|
|
|
|
|
|
+ case "add":
|
|
|
|
|
+ _, params := parseArgs(parts[1:])
|
|
|
|
|
+ name := params["name"]
|
|
|
|
|
+ if name == "" {
|
|
|
|
|
+ name = "Default"
|
|
|
|
|
+ }
|
|
|
|
|
+ routerID := params["router-id"]
|
|
|
|
|
+ version := 2
|
|
|
|
|
+ if vStr, ok := params["version"]; ok && vStr != "" {
|
|
|
|
|
+ if v, err := strconv.Atoi(vStr); err == nil && (v == 2 || v == 3) {
|
|
|
|
|
+ version = v
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ redistConn := parseCLIEnableDisable(params["redistribute-connected"], false)
|
|
|
|
|
+ redistStat := parseCLIEnableDisable(params["redistribute-static"], false)
|
|
|
|
|
+ redistBGP := parseCLIEnableDisable(params["redistribute-bgp"], false)
|
|
|
|
|
+ metric := 0
|
|
|
|
|
+ if mStr, ok := params["default-metric"]; ok && mStr != "" {
|
|
|
|
|
+ metric, _ = strconv.Atoi(mStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ disabled := parseCLIEnableDisable(params["disabled"], false)
|
|
|
|
|
+ vrf := params["vrf"]
|
|
|
|
|
+ if vrf == "" {
|
|
|
|
|
+ vrf = "main"
|
|
|
|
|
+ }
|
|
|
|
|
+ rt := params["routing-table"]
|
|
|
|
|
+ if rt == "" {
|
|
|
|
|
+ rt = "main"
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ inst := dynamicrouting.OSPFInstance{
|
|
|
|
|
+ Name: name,
|
|
|
|
|
+ Version: version,
|
|
|
|
|
+ VRF: vrf,
|
|
|
|
|
+ RouterID: routerID,
|
|
|
|
|
+ RoutingTable: rt,
|
|
|
|
|
+ Enabled: !disabled,
|
|
|
|
|
+ Disabled: disabled,
|
|
|
|
|
+ RedistributeConnected: redistConn,
|
|
|
|
|
+ RedistributeStatic: redistStat,
|
|
|
|
|
+ RedistributeBGP: redistBGP,
|
|
|
|
|
+ DefaultMetric: metric,
|
|
|
|
|
+ Comment: params["comment"],
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFInstance(&inst); err != nil {
|
|
|
|
|
+ return ColorRed + "Error saving OSPF instance: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF instance %s saved.\n", name) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "set":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 && params["numbers"] == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf instance set <number|name> [router-id=...] [redistribute-connected=yes/no] ...\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else {
|
|
|
|
|
+ target = params["numbers"]
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ instances := e.dynRoutingMgr.ListOSPFInstances()
|
|
|
|
|
+ var targetInst *dynamicrouting.OSPFInstance
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(instances) {
|
|
|
|
|
+ targetInst = &instances[idx]
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for i := range instances {
|
|
|
|
|
+ if strings.EqualFold(instances[i].Name, target) || instances[i].ID == target {
|
|
|
|
|
+ targetInst = &instances[i]
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if targetInst == nil {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF instance %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if v, ok := params["name"]; ok && v != "" {
|
|
|
|
|
+ targetInst.Name = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["router-id"]; ok {
|
|
|
|
|
+ targetInst.RouterID = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["redistribute-connected"]; ok {
|
|
|
|
|
+ targetInst.RedistributeConnected = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["redistribute-static"]; ok {
|
|
|
|
|
+ targetInst.RedistributeStatic = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["redistribute-bgp"]; ok {
|
|
|
|
|
+ targetInst.RedistributeBGP = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["default-metric"]; ok {
|
|
|
|
|
+ targetInst.DefaultMetric, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["disabled"]; ok {
|
|
|
|
|
+ targetInst.Disabled = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ targetInst.Enabled = !targetInst.Disabled
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["comment"]; ok {
|
|
|
|
|
+ targetInst.Comment = v
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFInstance(targetInst); err != nil {
|
|
|
|
|
+ return ColorRed + "Error updating OSPF instance: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF instance %s updated.\n", targetInst.Name) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "remove", "rem", "delete":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf instance remove <number|name>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ instances := e.dynRoutingMgr.ListOSPFInstances()
|
|
|
|
|
+ idToDelete := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(instances) {
|
|
|
|
|
+ idToDelete = instances[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, inst := range instances {
|
|
|
|
|
+ if strings.EqualFold(inst.Name, target) || inst.ID == target {
|
|
|
|
|
+ idToDelete = inst.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if idToDelete == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF instance %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.DeleteOSPFInstance(idToDelete); err != nil {
|
|
|
|
|
+ return ColorRed + "Error deleting OSPF instance: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF instance %s removed.\n", target) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "enable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf instance enable <number|name>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFInstanceStateByTarget(pos[0], false)
|
|
|
|
|
+
|
|
|
|
|
+ case "disable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf instance disable <number|name>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFInstanceStateByTarget(pos[0], true)
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf instance [print|add|set|remove|enable|disable]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFArea(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ if len(parts) == 0 || parts[0] == "print" || parts[0] == "pr" {
|
|
|
areas := e.dynRoutingMgr.ListOSPFAreas()
|
|
areas := e.dynRoutingMgr.ListOSPFAreas()
|
|
|
- tbl := NewTable("NAME", "AREA-ID", "INSTANCE", "TYPE")
|
|
|
|
|
- for _, a := range areas {
|
|
|
|
|
- tbl.AddRow(a.Name, a.AreaID, a.Instance, a.AreaType)
|
|
|
|
|
|
|
+ tbl := NewTable("#", "NAME", "AREA-ID", "INSTANCE", "TYPE", "DEFAULT-COST", "NO-SUMMARIES", "STATUS")
|
|
|
|
|
+ for idx, a := range areas {
|
|
|
|
|
+ st := "enabled"
|
|
|
|
|
+ if a.Disabled {
|
|
|
|
|
+ st = "disabled"
|
|
|
|
|
+ }
|
|
|
|
|
+ costStr := "-"
|
|
|
|
|
+ if a.DefaultCost > 0 {
|
|
|
|
|
+ costStr = fmt.Sprintf("%d", a.DefaultCost)
|
|
|
|
|
+ }
|
|
|
|
|
+ tbl.AddRow(fmt.Sprintf("%d", idx), a.Name, a.AreaID, a.Instance, a.AreaType, costStr, fmt.Sprintf("%t", a.NoSummaries), st)
|
|
|
|
|
+ }
|
|
|
|
|
+ return tbl.String()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if user.Role == auth.RoleRead {
|
|
|
|
|
+ return ColorRed + "Permission denied: viewer role cannot modify OSPF\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sub := strings.ToLower(parts[0])
|
|
|
|
|
+ switch sub {
|
|
|
|
|
+ case "add":
|
|
|
|
|
+ _, params := parseArgs(parts[1:])
|
|
|
|
|
+ name := params["name"]
|
|
|
|
|
+ if name == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area add name=<name> [area-id=...] [instance=...] [type=default|stub|nssa]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ areaID := params["area-id"]
|
|
|
|
|
+ if areaID == "" {
|
|
|
|
|
+ areaID = "0.0.0.0"
|
|
|
|
|
+ }
|
|
|
|
|
+ instName := params["instance"]
|
|
|
|
|
+ if instName == "" {
|
|
|
|
|
+ instName = "Default"
|
|
|
|
|
+ }
|
|
|
|
|
+ areaType := params["type"]
|
|
|
|
|
+ if areaType == "" {
|
|
|
|
|
+ areaType = "default"
|
|
|
|
|
+ }
|
|
|
|
|
+ defaultCost := 0
|
|
|
|
|
+ if cStr, ok := params["default-cost"]; ok && cStr != "" {
|
|
|
|
|
+ defaultCost, _ = strconv.Atoi(cStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ noSummaries := parseCLIEnableDisable(params["no-summaries"], false)
|
|
|
|
|
+ disabled := parseCLIEnableDisable(params["disabled"], false)
|
|
|
|
|
+
|
|
|
|
|
+ area := dynamicrouting.OSPFArea{
|
|
|
|
|
+ Name: name,
|
|
|
|
|
+ AreaID: areaID,
|
|
|
|
|
+ Instance: instName,
|
|
|
|
|
+ AreaType: areaType,
|
|
|
|
|
+ DefaultCost: defaultCost,
|
|
|
|
|
+ NoSummaries: noSummaries,
|
|
|
|
|
+ Disabled: disabled,
|
|
|
|
|
+ Comment: params["comment"],
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFArea(area); err != nil {
|
|
|
|
|
+ return ColorRed + "Error saving OSPF area: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF area %s saved.\n", name) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "set":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area set <number|name> [area-id=...] [type=...] ...\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ areas := e.dynRoutingMgr.ListOSPFAreas()
|
|
|
|
|
+ var targetArea *dynamicrouting.OSPFArea
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(areas) {
|
|
|
|
|
+ targetArea = &areas[idx]
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for i := range areas {
|
|
|
|
|
+ if strings.EqualFold(areas[i].Name, target) || areas[i].ID == target {
|
|
|
|
|
+ targetArea = &areas[i]
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if targetArea == nil {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF area %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if v, ok := params["name"]; ok && v != "" {
|
|
|
|
|
+ targetArea.Name = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["area-id"]; ok && v != "" {
|
|
|
|
|
+ targetArea.AreaID = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["instance"]; ok && v != "" {
|
|
|
|
|
+ targetArea.Instance = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["type"]; ok && v != "" {
|
|
|
|
|
+ targetArea.AreaType = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["default-cost"]; ok {
|
|
|
|
|
+ targetArea.DefaultCost, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["no-summaries"]; ok {
|
|
|
|
|
+ targetArea.NoSummaries = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["disabled"]; ok {
|
|
|
|
|
+ targetArea.Disabled = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["comment"]; ok {
|
|
|
|
|
+ targetArea.Comment = v
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFArea(*targetArea); err != nil {
|
|
|
|
|
+ return ColorRed + "Error updating OSPF area: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF area %s updated.\n", targetArea.Name) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "remove", "rem", "delete":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area remove <number|name>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ areas := e.dynRoutingMgr.ListOSPFAreas()
|
|
|
|
|
+ idToDelete := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(areas) {
|
|
|
|
|
+ idToDelete = areas[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, a := range areas {
|
|
|
|
|
+ if strings.EqualFold(a.Name, target) || a.ID == target {
|
|
|
|
|
+ idToDelete = a.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if idToDelete == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF area %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.DeleteOSPFArea(idToDelete); err != nil {
|
|
|
|
|
+ return ColorRed + "Error deleting OSPF area: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF area %s removed.\n", target) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "enable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area enable <number|name>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFAreaStateByTarget(pos[0], false)
|
|
|
|
|
+
|
|
|
|
|
+ case "disable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area disable <number|name>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFAreaStateByTarget(pos[0], true)
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area [print|add|set|remove|enable|disable]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFAreaRange(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ if len(parts) == 0 || parts[0] == "print" || parts[0] == "pr" {
|
|
|
|
|
+ ranges := e.dynRoutingMgr.ListOSPFAreaRanges()
|
|
|
|
|
+ tbl := NewTable("#", "PREFIX", "AREA", "COST", "ADVERTISE", "STATUS")
|
|
|
|
|
+ for idx, r := range ranges {
|
|
|
|
|
+ st := "enabled"
|
|
|
|
|
+ if r.Disabled {
|
|
|
|
|
+ st = "disabled"
|
|
|
|
|
+ }
|
|
|
|
|
+ tbl.AddRow(fmt.Sprintf("%d", idx), r.Prefix, r.Area, fmt.Sprintf("%d", r.Cost), fmt.Sprintf("%t", r.Advertise), st)
|
|
|
}
|
|
}
|
|
|
return tbl.String()
|
|
return tbl.String()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if user.Role == auth.RoleRead {
|
|
|
|
|
+ return ColorRed + "Permission denied: viewer role cannot modify OSPF\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sub := strings.ToLower(parts[0])
|
|
|
|
|
+ switch sub {
|
|
|
|
|
+ case "add":
|
|
|
|
|
+ _, params := parseArgs(parts[1:])
|
|
|
|
|
+ prefix := params["prefix"]
|
|
|
|
|
+ if prefix == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area range add prefix=<cidr> [area=...] [cost=...] [advertise=yes/no]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ area := params["area"]
|
|
|
|
|
+ if area == "" {
|
|
|
|
|
+ area = "Default"
|
|
|
|
|
+ }
|
|
|
|
|
+ cost := 1
|
|
|
|
|
+ if cStr, ok := params["cost"]; ok && cStr != "" {
|
|
|
|
|
+ cost, _ = strconv.Atoi(cStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ adv := true
|
|
|
|
|
+ if aStr, ok := params["advertise"]; ok && aStr != "" {
|
|
|
|
|
+ adv = parseCLIEnableDisable(aStr, true)
|
|
|
|
|
+ }
|
|
|
|
|
+ disabled := parseCLIEnableDisable(params["disabled"], false)
|
|
|
|
|
+
|
|
|
|
|
+ ar := dynamicrouting.OSPFAreaRange{
|
|
|
|
|
+ Prefix: prefix,
|
|
|
|
|
+ Area: area,
|
|
|
|
|
+ Cost: cost,
|
|
|
|
|
+ Advertise: adv,
|
|
|
|
|
+ Disabled: disabled,
|
|
|
|
|
+ Comment: params["comment"],
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFAreaRange(ar); err != nil {
|
|
|
|
|
+ return ColorRed + "Error saving area range: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("Area range %s added.\n", prefix) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "set":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area range set <number|prefix> [cost=...] [advertise=yes/no]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ranges := e.dynRoutingMgr.ListOSPFAreaRanges()
|
|
|
|
|
+ var targetRange *dynamicrouting.OSPFAreaRange
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(ranges) {
|
|
|
|
|
+ targetRange = &ranges[idx]
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for i := range ranges {
|
|
|
|
|
+ if strings.EqualFold(ranges[i].Prefix, target) || ranges[i].ID == target {
|
|
|
|
|
+ targetRange = &ranges[i]
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if targetRange == nil {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("Area range %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if v, ok := params["prefix"]; ok && v != "" {
|
|
|
|
|
+ targetRange.Prefix = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["area"]; ok && v != "" {
|
|
|
|
|
+ targetRange.Area = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["cost"]; ok {
|
|
|
|
|
+ targetRange.Cost, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["advertise"]; ok {
|
|
|
|
|
+ targetRange.Advertise = parseCLIEnableDisable(v, true)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["disabled"]; ok {
|
|
|
|
|
+ targetRange.Disabled = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["comment"]; ok {
|
|
|
|
|
+ targetRange.Comment = v
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFAreaRange(*targetRange); err != nil {
|
|
|
|
|
+ return ColorRed + "Error updating area range: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("Area range %s updated.\n", targetRange.Prefix) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "remove", "rem", "delete":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area range remove <number|prefix>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ranges := e.dynRoutingMgr.ListOSPFAreaRanges()
|
|
|
|
|
+ idToDelete := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(ranges) {
|
|
|
|
|
+ idToDelete = ranges[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, r := range ranges {
|
|
|
|
|
+ if strings.EqualFold(r.Prefix, target) || r.ID == target {
|
|
|
|
|
+ idToDelete = r.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if idToDelete == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("Area range %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.DeleteOSPFAreaRange(idToDelete); err != nil {
|
|
|
|
|
+ return ColorRed + "Error deleting area range: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("Area range %s removed.\n", target) + ColorReset
|
|
|
|
|
|
|
|
- case "interface", "interfaces":
|
|
|
|
|
|
|
+ default:
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf area range [print|add|set|remove]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFInterface(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ if len(parts) == 0 || parts[0] == "print" || parts[0] == "pr" {
|
|
|
ifaces := e.dynRoutingMgr.ListOSPFInterfaces()
|
|
ifaces := e.dynRoutingMgr.ListOSPFInterfaces()
|
|
|
- tbl := NewTable("INTERFACE", "AREA", "COST", "PRIORITY", "NETWORK-TYPE")
|
|
|
|
|
- for _, i := range ifaces {
|
|
|
|
|
- tbl.AddRow(i.Interface, i.Area, fmt.Sprintf("%d", i.Cost), fmt.Sprintf("%d", i.Priority), i.NetworkType)
|
|
|
|
|
|
|
+ tbl := NewTable("#", "INTERFACE", "AREA", "NETWORKS", "TYPE", "COST", "PRIORITY", "PASSIVE", "AUTH", "STATUS")
|
|
|
|
|
+ for idx, i := range ifaces {
|
|
|
|
|
+ st := "enabled"
|
|
|
|
|
+ if i.Disabled {
|
|
|
|
|
+ st = "disabled"
|
|
|
|
|
+ }
|
|
|
|
|
+ ifaceName := i.Interfaces
|
|
|
|
|
+ if ifaceName == "" {
|
|
|
|
|
+ ifaceName = i.Interface
|
|
|
|
|
+ }
|
|
|
|
|
+ if ifaceName == "" {
|
|
|
|
|
+ ifaceName = "*"
|
|
|
|
|
+ }
|
|
|
|
|
+ nets := i.Networks
|
|
|
|
|
+ if nets == "" {
|
|
|
|
|
+ nets = i.Network
|
|
|
|
|
+ }
|
|
|
|
|
+ if nets == "" {
|
|
|
|
|
+ nets = "-"
|
|
|
|
|
+ }
|
|
|
|
|
+ authStr := i.Auth
|
|
|
|
|
+ if authStr == "" {
|
|
|
|
|
+ authStr = i.AuthType
|
|
|
|
|
+ }
|
|
|
|
|
+ if authStr == "" {
|
|
|
|
|
+ authStr = "none"
|
|
|
|
|
+ }
|
|
|
|
|
+ tbl.AddRow(fmt.Sprintf("%d", idx), ifaceName, i.Area, nets, i.NetworkType, fmt.Sprintf("%d", i.Cost), fmt.Sprintf("%d", i.Priority), fmt.Sprintf("%t", i.Passive), authStr, st)
|
|
|
}
|
|
}
|
|
|
return tbl.String()
|
|
return tbl.String()
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- case "neighbor", "neighbors":
|
|
|
|
|
- neighbors := e.dynRoutingMgr.GetOSPFNeighbors()
|
|
|
|
|
- tbl := NewTable("ROUTER-ID", "ADDRESS", "INTERFACE", "STATE", "PRIORITY")
|
|
|
|
|
- for _, n := range neighbors {
|
|
|
|
|
- tbl.AddRow(n.NeighborID, n.Address, n.Interface, n.State, fmt.Sprintf("%d", n.Priority))
|
|
|
|
|
|
|
+ if user.Role == auth.RoleRead {
|
|
|
|
|
+ return ColorRed + "Permission denied: viewer role cannot modify OSPF\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sub := strings.ToLower(parts[0])
|
|
|
|
|
+ switch sub {
|
|
|
|
|
+ case "add":
|
|
|
|
|
+ _, params := parseArgs(parts[1:])
|
|
|
|
|
+ ifaceName := params["interface"]
|
|
|
|
|
+ if ifaceName == "" {
|
|
|
|
|
+ ifaceName = params["interfaces"]
|
|
|
|
|
+ }
|
|
|
|
|
+ if ifaceName == "" {
|
|
|
|
|
+ ifaceName = "*"
|
|
|
|
|
+ }
|
|
|
|
|
+ area := params["area"]
|
|
|
|
|
+ if area == "" {
|
|
|
|
|
+ area = "Default"
|
|
|
|
|
+ }
|
|
|
|
|
+ nets := params["networks"]
|
|
|
|
|
+ if nets == "" {
|
|
|
|
|
+ nets = params["network"]
|
|
|
|
|
+ }
|
|
|
|
|
+ netType := params["network-type"]
|
|
|
|
|
+ if netType == "" {
|
|
|
|
|
+ netType = "broadcast"
|
|
|
|
|
+ }
|
|
|
|
|
+ cost := 1
|
|
|
|
|
+ if cStr, ok := params["cost"]; ok && cStr != "" {
|
|
|
|
|
+ cost, _ = strconv.Atoi(cStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ pri := 128
|
|
|
|
|
+ if pStr, ok := params["priority"]; ok && pStr != "" {
|
|
|
|
|
+ pri, _ = strconv.Atoi(pStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ hello := 10
|
|
|
|
|
+ if hStr, ok := params["hello-interval"]; ok && hStr != "" {
|
|
|
|
|
+ hello, _ = strconv.Atoi(hStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ dead := 40
|
|
|
|
|
+ if dStr, ok := params["dead-interval"]; ok && dStr != "" {
|
|
|
|
|
+ dead, _ = strconv.Atoi(dStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ passive := parseCLIEnableDisable(params["passive"], false)
|
|
|
|
|
+ authType := params["auth"]
|
|
|
|
|
+ if authType == "" {
|
|
|
|
|
+ authType = params["auth-type"]
|
|
|
|
|
+ }
|
|
|
|
|
+ authKey := params["auth-key"]
|
|
|
|
|
+ disabled := parseCLIEnableDisable(params["disabled"], false)
|
|
|
|
|
+
|
|
|
|
|
+ iface := dynamicrouting.OSPFInterface{
|
|
|
|
|
+ Interfaces: ifaceName,
|
|
|
|
|
+ Interface: ifaceName,
|
|
|
|
|
+ Area: area,
|
|
|
|
|
+ Networks: nets,
|
|
|
|
|
+ Network: nets,
|
|
|
|
|
+ NetworkType: netType,
|
|
|
|
|
+ Cost: cost,
|
|
|
|
|
+ Priority: pri,
|
|
|
|
|
+ HelloInterval: hello,
|
|
|
|
|
+ DeadInterval: dead,
|
|
|
|
|
+ Passive: passive,
|
|
|
|
|
+ Auth: authType,
|
|
|
|
|
+ AuthType: authType,
|
|
|
|
|
+ AuthKey: authKey,
|
|
|
|
|
+ Disabled: disabled,
|
|
|
|
|
+ Comment: params["comment"],
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFInterface(iface); err != nil {
|
|
|
|
|
+ return ColorRed + "Error saving OSPF interface template: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF interface template %s saved.\n", ifaceName) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "set":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf interface set <number|id> [cost=...] [priority=...] ...\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ifaces := e.dynRoutingMgr.ListOSPFInterfaces()
|
|
|
|
|
+ var targetIface *dynamicrouting.OSPFInterface
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(ifaces) {
|
|
|
|
|
+ targetIface = &ifaces[idx]
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for i := range ifaces {
|
|
|
|
|
+ if ifaces[i].ID == target || ifaces[i].Interfaces == target || ifaces[i].Interface == target {
|
|
|
|
|
+ targetIface = &ifaces[i]
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if targetIface == nil {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF interface template %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if v, ok := params["interface"]; ok && v != "" {
|
|
|
|
|
+ targetIface.Interface = v
|
|
|
|
|
+ targetIface.Interfaces = v
|
|
|
|
|
+ } else if v, ok := params["interfaces"]; ok && v != "" {
|
|
|
|
|
+ targetIface.Interface = v
|
|
|
|
|
+ targetIface.Interfaces = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["area"]; ok && v != "" {
|
|
|
|
|
+ targetIface.Area = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["networks"]; ok {
|
|
|
|
|
+ targetIface.Networks = v
|
|
|
|
|
+ targetIface.Network = v
|
|
|
|
|
+ } else if v, ok := params["network"]; ok {
|
|
|
|
|
+ targetIface.Networks = v
|
|
|
|
|
+ targetIface.Network = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["network-type"]; ok && v != "" {
|
|
|
|
|
+ targetIface.NetworkType = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["cost"]; ok {
|
|
|
|
|
+ targetIface.Cost, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["priority"]; ok {
|
|
|
|
|
+ targetIface.Priority, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["hello-interval"]; ok {
|
|
|
|
|
+ targetIface.HelloInterval, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["dead-interval"]; ok {
|
|
|
|
|
+ targetIface.DeadInterval, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["passive"]; ok {
|
|
|
|
|
+ targetIface.Passive = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["auth"]; ok {
|
|
|
|
|
+ targetIface.Auth = v
|
|
|
|
|
+ targetIface.AuthType = v
|
|
|
|
|
+ } else if v, ok := params["auth-type"]; ok {
|
|
|
|
|
+ targetIface.Auth = v
|
|
|
|
|
+ targetIface.AuthType = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["auth-key"]; ok {
|
|
|
|
|
+ targetIface.AuthKey = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["disabled"]; ok {
|
|
|
|
|
+ targetIface.Disabled = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["comment"]; ok {
|
|
|
|
|
+ targetIface.Comment = v
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFInterface(*targetIface); err != nil {
|
|
|
|
|
+ return ColorRed + "Error updating OSPF interface template: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF interface template %s updated.\n", targetIface.ID) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "remove", "rem", "delete":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf interface remove <number|id>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ifaces := e.dynRoutingMgr.ListOSPFInterfaces()
|
|
|
|
|
+ idToDelete := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(ifaces) {
|
|
|
|
|
+ idToDelete = ifaces[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, i := range ifaces {
|
|
|
|
|
+ if i.ID == target || i.Interfaces == target || i.Interface == target {
|
|
|
|
|
+ idToDelete = i.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if idToDelete == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF interface template %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.DeleteOSPFInterface(idToDelete); err != nil {
|
|
|
|
|
+ return ColorRed + "Error deleting OSPF interface template: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF interface template %s removed.\n", target) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "enable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf interface enable <number|id>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFInterfaceStateByTarget(pos[0], false)
|
|
|
|
|
+
|
|
|
|
|
+ case "disable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf interface disable <number|id>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFInterfaceStateByTarget(pos[0], true)
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf interface [print|add|set|remove|enable|disable]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFStaticNeighbor(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ if len(parts) == 0 || parts[0] == "print" || parts[0] == "pr" {
|
|
|
|
|
+ nbrs := e.dynRoutingMgr.ListOSPFStaticNeighbors()
|
|
|
|
|
+ tbl := NewTable("#", "ADDRESS", "AREA", "POLL-INTERVAL", "COST", "STATUS")
|
|
|
|
|
+ for idx, n := range nbrs {
|
|
|
|
|
+ st := "enabled"
|
|
|
|
|
+ if n.Disabled {
|
|
|
|
|
+ st = "disabled"
|
|
|
|
|
+ }
|
|
|
|
|
+ tbl.AddRow(fmt.Sprintf("%d", idx), n.Address, n.Area, fmt.Sprintf("%d", n.PollInterval), fmt.Sprintf("%d", n.Cost), st)
|
|
|
}
|
|
}
|
|
|
return tbl.String()
|
|
return tbl.String()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if user.Role == auth.RoleRead {
|
|
|
|
|
+ return ColorRed + "Permission denied: viewer role cannot modify OSPF\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sub := strings.ToLower(parts[0])
|
|
|
|
|
+ switch sub {
|
|
|
|
|
+ case "add":
|
|
|
|
|
+ _, params := parseArgs(parts[1:])
|
|
|
|
|
+ addr := params["address"]
|
|
|
|
|
+ if addr == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf static-neighbor add address=<ip> [area=...] [poll-interval=...] [cost=...]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ area := params["area"]
|
|
|
|
|
+ if area == "" {
|
|
|
|
|
+ area = "Default"
|
|
|
|
|
+ }
|
|
|
|
|
+ poll := 120
|
|
|
|
|
+ if pStr, ok := params["poll-interval"]; ok && pStr != "" {
|
|
|
|
|
+ poll, _ = strconv.Atoi(pStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ cost := 1
|
|
|
|
|
+ if cStr, ok := params["cost"]; ok && cStr != "" {
|
|
|
|
|
+ cost, _ = strconv.Atoi(cStr)
|
|
|
|
|
+ }
|
|
|
|
|
+ disabled := parseCLIEnableDisable(params["disabled"], false)
|
|
|
|
|
+
|
|
|
|
|
+ snbr := dynamicrouting.OSPFStaticNeighbor{
|
|
|
|
|
+ Address: addr,
|
|
|
|
|
+ Area: area,
|
|
|
|
|
+ PollInterval: poll,
|
|
|
|
|
+ Cost: cost,
|
|
|
|
|
+ Disabled: disabled,
|
|
|
|
|
+ Comment: params["comment"],
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFStaticNeighbor(snbr); err != nil {
|
|
|
|
|
+ return ColorRed + "Error saving static neighbor: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF static neighbor %s saved.\n", addr) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "set":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf static-neighbor set <number|address> [poll-interval=...] [cost=...]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nbrs := e.dynRoutingMgr.ListOSPFStaticNeighbors()
|
|
|
|
|
+ var targetNbr *dynamicrouting.OSPFStaticNeighbor
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(nbrs) {
|
|
|
|
|
+ targetNbr = &nbrs[idx]
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for i := range nbrs {
|
|
|
|
|
+ if nbrs[i].Address == target || nbrs[i].ID == target {
|
|
|
|
|
+ targetNbr = &nbrs[i]
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if targetNbr == nil {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("Static neighbor %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if v, ok := params["address"]; ok && v != "" {
|
|
|
|
|
+ targetNbr.Address = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["area"]; ok && v != "" {
|
|
|
|
|
+ targetNbr.Area = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["poll-interval"]; ok {
|
|
|
|
|
+ targetNbr.PollInterval, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["cost"]; ok {
|
|
|
|
|
+ targetNbr.Cost, _ = strconv.Atoi(v)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["disabled"]; ok {
|
|
|
|
|
+ targetNbr.Disabled = parseCLIEnableDisable(v, false)
|
|
|
|
|
+ }
|
|
|
|
|
+ if v, ok := params["comment"]; ok {
|
|
|
|
|
+ targetNbr.Comment = v
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if err := e.dynRoutingMgr.SaveOSPFStaticNeighbor(*targetNbr); err != nil {
|
|
|
|
|
+ return ColorRed + "Error updating static neighbor: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF static neighbor %s updated.\n", targetNbr.Address) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "remove", "rem", "delete":
|
|
|
|
|
+ pos, params := parseArgs(parts[1:])
|
|
|
|
|
+ target := ""
|
|
|
|
|
+ if len(pos) > 0 {
|
|
|
|
|
+ target = pos[0]
|
|
|
|
|
+ } else if v, ok := params["numbers"]; ok {
|
|
|
|
|
+ target = v
|
|
|
|
|
+ }
|
|
|
|
|
+ if target == "" {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf static-neighbor remove <number|address>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nbrs := e.dynRoutingMgr.ListOSPFStaticNeighbors()
|
|
|
|
|
+ idToDelete := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(nbrs) {
|
|
|
|
|
+ idToDelete = nbrs[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, n := range nbrs {
|
|
|
|
|
+ if n.Address == target || n.ID == target {
|
|
|
|
|
+ idToDelete = n.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if idToDelete == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("Static neighbor %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.DeleteOSPFStaticNeighbor(idToDelete); err != nil {
|
|
|
|
|
+ return ColorRed + "Error deleting static neighbor: " + err.Error() + ColorReset + "\n"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF static neighbor %s removed.\n", target) + ColorReset
|
|
|
|
|
+
|
|
|
|
|
+ case "enable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf static-neighbor enable <number|address>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFStaticNeighborStateByTarget(pos[0], false)
|
|
|
|
|
+
|
|
|
|
|
+ case "disable":
|
|
|
|
|
+ pos, _ := parseArgs(parts[1:])
|
|
|
|
|
+ if len(pos) == 0 {
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf static-neighbor disable <number|address>\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ return e.setOSPFStaticNeighborStateByTarget(pos[0], true)
|
|
|
|
|
|
|
|
default:
|
|
default:
|
|
|
- return ColorRed + "Usage: /routing ospf [instance|area|interface|neighbor]\n" + ColorReset
|
|
|
|
|
|
|
+ return ColorRed + "Usage: /routing ospf static-neighbor [print|add|set|remove|enable|disable]\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFNeighborLive(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ neighbors := e.dynRoutingMgr.GetOSPFNeighbors()
|
|
|
|
|
+ tbl := NewTable("ROUTER-ID", "ADDRESS", "INTERFACE", "STATE", "PRIORITY", "DEAD-TIMER")
|
|
|
|
|
+ for _, n := range neighbors {
|
|
|
|
|
+ tbl.AddRow(n.NeighborID, n.Address, n.Interface, n.State, fmt.Sprintf("%d", n.Priority), n.DeadTimer)
|
|
|
|
|
+ }
|
|
|
|
|
+ return tbl.String()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFLSA(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ lsas := e.dynRoutingMgr.GetOSPFLSA()
|
|
|
|
|
+ tbl := NewTable("TYPE", "LS-ID", "ROUTER-ID", "AGE", "SEQUENCE")
|
|
|
|
|
+ for _, l := range lsas {
|
|
|
|
|
+ tbl.AddRow(l.Type, l.ID, l.Originator, fmt.Sprintf("%d", l.Age), l.Sequence)
|
|
|
|
|
+ }
|
|
|
|
|
+ return tbl.String()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) handleOSPFRoute(parts []string, user *auth.PublicUser) string {
|
|
|
|
|
+ routes := e.dynRoutingMgr.GetOSPFRoutes()
|
|
|
|
|
+ tbl := NewTable("PREFIX", "NEXT-HOP", "INTERFACE", "COST", "TYPE")
|
|
|
|
|
+ for _, r := range routes {
|
|
|
|
|
+ tbl.AddRow(r.Prefix, r.NextHop, r.Interface, fmt.Sprintf("%d", r.Cost), r.RouteType)
|
|
|
|
|
+ }
|
|
|
|
|
+ return tbl.String()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) setOSPFInstanceStateByTarget(target string, disabled bool) string {
|
|
|
|
|
+ instances := e.dynRoutingMgr.ListOSPFInstances()
|
|
|
|
|
+ id := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(instances) {
|
|
|
|
|
+ id = instances[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, inst := range instances {
|
|
|
|
|
+ if strings.EqualFold(inst.Name, target) || inst.ID == target {
|
|
|
|
|
+ id = inst.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if id == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF instance %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SetOSPFInstanceState(id, disabled); err != nil {
|
|
|
|
|
+ return ColorRed + "Error: " + err.Error() + "\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ action := "enabled"
|
|
|
|
|
+ if disabled {
|
|
|
|
|
+ action = "disabled"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF instance %s %s.\n", target, action) + ColorReset
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) setOSPFAreaStateByTarget(target string, disabled bool) string {
|
|
|
|
|
+ areas := e.dynRoutingMgr.ListOSPFAreas()
|
|
|
|
|
+ id := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(areas) {
|
|
|
|
|
+ id = areas[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, a := range areas {
|
|
|
|
|
+ if strings.EqualFold(a.Name, target) || a.ID == target {
|
|
|
|
|
+ id = a.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if id == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF area %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SetOSPFAreaState(id, disabled); err != nil {
|
|
|
|
|
+ return ColorRed + "Error: " + err.Error() + "\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ action := "enabled"
|
|
|
|
|
+ if disabled {
|
|
|
|
|
+ action = "disabled"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF area %s %s.\n", target, action) + ColorReset
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) setOSPFInterfaceStateByTarget(target string, disabled bool) string {
|
|
|
|
|
+ ifaces := e.dynRoutingMgr.ListOSPFInterfaces()
|
|
|
|
|
+ id := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(ifaces) {
|
|
|
|
|
+ id = ifaces[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, i := range ifaces {
|
|
|
|
|
+ if i.ID == target || i.Interfaces == target || i.Interface == target {
|
|
|
|
|
+ id = i.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if id == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("OSPF interface template %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SetOSPFInterfaceState(id, disabled); err != nil {
|
|
|
|
|
+ return ColorRed + "Error: " + err.Error() + "\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ action := "enabled"
|
|
|
|
|
+ if disabled {
|
|
|
|
|
+ action = "disabled"
|
|
|
|
|
+ }
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("OSPF interface template %s %s.\n", target, action) + ColorReset
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (e *Executor) setOSPFStaticNeighborStateByTarget(target string, disabled bool) string {
|
|
|
|
|
+ nbrs := e.dynRoutingMgr.ListOSPFStaticNeighbors()
|
|
|
|
|
+ id := ""
|
|
|
|
|
+ if idx, err := strconv.Atoi(target); err == nil && idx >= 0 && idx < len(nbrs) {
|
|
|
|
|
+ id = nbrs[idx].ID
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for _, n := range nbrs {
|
|
|
|
|
+ if n.Address == target || n.ID == target {
|
|
|
|
|
+ id = n.ID
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if id == "" {
|
|
|
|
|
+ return ColorRed + fmt.Sprintf("Static neighbor %q not found\n", target) + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ if err := e.dynRoutingMgr.SetOSPFStaticNeighborState(id, disabled); err != nil {
|
|
|
|
|
+ return ColorRed + "Error: " + err.Error() + "\n" + ColorReset
|
|
|
|
|
+ }
|
|
|
|
|
+ action := "enabled"
|
|
|
|
|
+ if disabled {
|
|
|
|
|
+ action = "disabled"
|
|
|
}
|
|
}
|
|
|
|
|
+ return ColorGreen + fmt.Sprintf("Static neighbor %s %s.\n", target, action) + ColorReset
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (e *Executor) handleRoutingFilter(parts []string, user *auth.PublicUser) string {
|
|
func (e *Executor) handleRoutingFilter(parts []string, user *auth.PublicUser) string {
|