14.04.2026 Update
This commit is contained in:
109
handlers/api.go
109
handlers/api.go
@@ -5,8 +5,8 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"alpine-router/config"
|
||||
"alpine-router/network"
|
||||
"nano-router/config"
|
||||
"nano-router/network"
|
||||
)
|
||||
|
||||
type apiResp struct {
|
||||
@@ -47,10 +47,16 @@ func HandleInterfaces(w http.ResponseWriter, r *http.Request) {
|
||||
*network.InterfaceStats
|
||||
Pending bool `json:"pending"`
|
||||
Label string `json:"label,omitempty"`
|
||||
NAT bool `json:"nat"`
|
||||
}
|
||||
|
||||
appCfg, _ := config.Load()
|
||||
|
||||
var natIfaces []string
|
||||
if appCfg != nil {
|
||||
natIfaces = appCfg.NAT.Interfaces
|
||||
}
|
||||
|
||||
result := make([]iface, 0, len(names))
|
||||
existingNames := map[string]bool{}
|
||||
for _, name := range names {
|
||||
@@ -64,15 +70,30 @@ func HandleInterfaces(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
hasPending := network.GetPendingConfig(name) != nil
|
||||
label := ""
|
||||
ifaceType := ""
|
||||
if appCfg != nil && appCfg.Interfaces != nil {
|
||||
if ic, ok := appCfg.Interfaces[name]; ok {
|
||||
label = ic.Label
|
||||
ifaceType = ic.Type
|
||||
}
|
||||
}
|
||||
result = append(result, iface{s, hasPending, label})
|
||||
s.Type = ifaceType
|
||||
if s.Type == "" && s.Gateway != "" {
|
||||
s.Type = "wan"
|
||||
}
|
||||
if s.Type == "" && s.Mode != "loopback" {
|
||||
s.Type = "lan"
|
||||
}
|
||||
isNAT := false
|
||||
for _, ni := range natIfaces {
|
||||
if ni == name {
|
||||
isNAT = true
|
||||
break
|
||||
}
|
||||
}
|
||||
result = append(result, iface{s, hasPending, label, isNAT})
|
||||
}
|
||||
|
||||
// Also include pending VLAN configs not yet present in the system.
|
||||
for name, cfg := range network.GetAllPending() {
|
||||
if existingNames[name] || !network.IsVLAN(name) {
|
||||
continue
|
||||
@@ -81,6 +102,7 @@ func HandleInterfaces(w http.ResponseWriter, r *http.Request) {
|
||||
Name: name,
|
||||
State: "unknown",
|
||||
Mode: cfg.Mode,
|
||||
Type: cfg.Type,
|
||||
IPv6: []string{},
|
||||
}
|
||||
if cfg.Mode == "static" {
|
||||
@@ -88,13 +110,26 @@ func HandleInterfaces(w http.ResponseWriter, r *http.Request) {
|
||||
s.IPv4Mask = cfg.Netmask
|
||||
s.Gateway = cfg.Gateway
|
||||
}
|
||||
if s.Type == "" && s.Gateway != "" {
|
||||
s.Type = "wan"
|
||||
}
|
||||
if s.Type == "" {
|
||||
s.Type = "lan"
|
||||
}
|
||||
label := cfg.Label
|
||||
if label == "" && appCfg != nil && appCfg.Interfaces != nil {
|
||||
if ic, ok := appCfg.Interfaces[name]; ok {
|
||||
label = ic.Label
|
||||
}
|
||||
}
|
||||
result = append(result, iface{s, true, label})
|
||||
isNAT := false
|
||||
for _, ni := range natIfaces {
|
||||
if ni == name {
|
||||
isNAT = true
|
||||
break
|
||||
}
|
||||
}
|
||||
result = append(result, iface{s, true, label, isNAT})
|
||||
}
|
||||
|
||||
ok(w, result)
|
||||
@@ -131,9 +166,9 @@ func HandleInterfaceAction(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
switch action {
|
||||
case "up":
|
||||
err = network.IfUp(name)
|
||||
err = network.LinkUp(name)
|
||||
case "down":
|
||||
err = network.IfDown(name)
|
||||
err = network.LinkDown(name)
|
||||
case "restart":
|
||||
err = network.IfRestart(name)
|
||||
case "delete":
|
||||
@@ -166,16 +201,21 @@ func HandleConfig(w http.ResponseWriter, r *http.Request) {
|
||||
case http.MethodGet:
|
||||
appCfg, _ := config.Load()
|
||||
label := ""
|
||||
ifaceType := ""
|
||||
if appCfg != nil && appCfg.Interfaces != nil {
|
||||
if ic, ok2 := appCfg.Interfaces[name]; ok2 {
|
||||
label = ic.Label
|
||||
ifaceType = ic.Type
|
||||
}
|
||||
}
|
||||
if cfg := network.GetPendingConfig(name); cfg != nil {
|
||||
if cfg.Label != "" {
|
||||
label = cfg.Label
|
||||
}
|
||||
ok(w, map[string]interface{}{"config": cfg, "pending": true, "label": label})
|
||||
if cfg.Type != "" {
|
||||
ifaceType = cfg.Type
|
||||
}
|
||||
ok(w, map[string]interface{}{"config": cfg, "pending": true, "label": label, "type": ifaceType})
|
||||
return
|
||||
}
|
||||
fileCfg, err := network.ParseConfig()
|
||||
@@ -184,12 +224,17 @@ func HandleConfig(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if cfg, exists := fileCfg[name]; exists {
|
||||
ok(w, map[string]interface{}{"config": cfg, "pending": false, "label": label})
|
||||
if ifaceType == "" {
|
||||
ifaceType = cfg.Type
|
||||
}
|
||||
ok(w, map[string]interface{}{"config": cfg, "pending": false, "label": label, "type": ifaceType})
|
||||
} else {
|
||||
defaultType := "lan"
|
||||
ok(w, map[string]interface{}{
|
||||
"config": &network.InterfaceConfig{Name: name, Auto: true, Mode: "dhcp", Extra: map[string]string{}},
|
||||
"config": &network.InterfaceConfig{Name: name, Auto: true, Mode: "dhcp", Type: defaultType, Extra: map[string]string{}},
|
||||
"pending": false,
|
||||
"label": label,
|
||||
"type": defaultType,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -200,6 +245,49 @@ func HandleConfig(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
cfg.Name = name
|
||||
|
||||
if cfg.Type != "wan" && cfg.Type != "lan" {
|
||||
fail(w, http.StatusBadRequest, "type must be 'wan' or 'lan'")
|
||||
return
|
||||
}
|
||||
if network.IsVLAN(name) && cfg.Type != "lan" {
|
||||
fail(w, http.StatusBadRequest, "VLAN interface must be type 'lan'")
|
||||
return
|
||||
}
|
||||
if cfg.Type == "lan" {
|
||||
if cfg.Mode == "dhcp" {
|
||||
fail(w, http.StatusBadRequest, "LAN interface cannot use DHCP mode")
|
||||
return
|
||||
}
|
||||
if cfg.Gateway != "" {
|
||||
fail(w, http.StatusBadRequest, "LAN interface cannot have a gateway")
|
||||
return
|
||||
}
|
||||
if len(cfg.DNS) > 0 {
|
||||
fail(w, http.StatusBadRequest, "LAN interface cannot have DNS servers")
|
||||
return
|
||||
}
|
||||
}
|
||||
if cfg.Type == "wan" && cfg.Mode == "static" && cfg.Address == "" {
|
||||
fail(w, http.StatusBadRequest, "WAN interface in static mode requires an IP address")
|
||||
return
|
||||
}
|
||||
if network.IsVLAN(name) {
|
||||
parent := network.VLANParent(name)
|
||||
appCfgCheck, _ := config.Load()
|
||||
if appCfgCheck != nil && appCfgCheck.Interfaces != nil {
|
||||
if pic, ok := appCfgCheck.Interfaces[parent]; ok && pic.Type == "wan" {
|
||||
fail(w, http.StatusBadRequest, "VLAN cannot be created on a WAN interface ("+parent+")")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if msg, overlaps := checkInterfaceOverlap(&cfg); overlaps {
|
||||
fail(w, http.StatusConflict, msg)
|
||||
return
|
||||
}
|
||||
|
||||
if cfg.Extra == nil {
|
||||
cfg.Extra = map[string]string{}
|
||||
}
|
||||
@@ -215,6 +303,7 @@ func HandleConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
appCfg.Interfaces[name] = &config.InterfaceConfig{
|
||||
Label: cfg.Label,
|
||||
Type: cfg.Type,
|
||||
Auto: cfg.Auto,
|
||||
Mode: cfg.Mode,
|
||||
Address: cfg.Address,
|
||||
|
||||
Reference in New Issue
Block a user