Files

172 lines
4.0 KiB
Go
Raw Permalink Normal View History

2026-04-15 11:38:26 +03:00
package handlers
import (
"nano-router/config"
"nano-router/dhcp"
"nano-router/network"
"net/http"
"strings"
)
func collectAllSubnets(excludeIface string) []network.SubnetOverlap {
var result []network.SubnetOverlap
appCfg, _ := config.Load()
if appCfg != nil {
for name, ic := range appCfg.Interfaces {
if name == excludeIface {
continue
}
addr, mask := resolveIfaceIP(name, ic.Mode, ic.Address, ic.Netmask)
if addr != "" && mask != "" {
result = append(result, network.SubnetOverlap{
Interface: name,
Label: ic.Label,
Subnet: addr + "/" + mask,
})
}
}
}
for name, pcfg := range network.GetAllPending() {
if name == excludeIface {
continue
}
addr, mask := resolveIfaceIP(name, pcfg.Mode, pcfg.Address, pcfg.Netmask)
if addr != "" && mask != "" {
result = append(result, network.SubnetOverlap{
Interface: name,
Label: pcfg.Label,
Subnet: addr + "/" + mask,
})
}
}
names, _ := network.GetInterfaces()
for _, name := range names {
if name == excludeIface {
continue
}
s, err := network.GetInterfaceStats(name)
if err != nil || s.IPv4 == "" || s.IPv4Mask == "" {
continue
}
var mode string
if appCfg != nil && appCfg.Interfaces != nil {
if ic, ok := appCfg.Interfaces[name]; ok {
mode = ic.Mode
}
}
if mode == "dhcp" {
result = append(result, network.SubnetOverlap{
Interface: name,
Subnet: s.IPv4 + "/" + s.IPv4Mask,
})
}
}
if appCfg != nil {
for _, pool := range appCfg.DHCP.Pools {
if pool.Interface == excludeIface {
continue
}
if pool.Subnet != "" && pool.Netmask != "" {
result = append(result, network.SubnetOverlap{
Interface: pool.Interface,
Subnet: pool.Subnet + "/" + pool.Netmask,
})
}
}
}
return result
}
func resolveIfaceIP(name, mode, addr, mask string) (string, string) {
if mode == "static" && addr != "" && mask != "" {
return addr, mask
}
if mode == "dhcp" {
s, err := network.GetInterfaceStats(name)
if err != nil {
return "", ""
}
if s.IPv4 != "" && s.IPv4Mask != "" {
return s.IPv4, s.IPv4Mask
}
}
return "", ""
}
func collectAllSubnetsForDHCP(excludeIface string) []network.SubnetOverlap {
result := collectAllSubnets(excludeIface)
cfg, _ := dhcp.Load()
if cfg != nil {
for _, pool := range cfg.Pools {
if pool.Interface == excludeIface {
continue
}
if pool.Subnet != "" && pool.Netmask != "" {
result = append(result, network.SubnetOverlap{
Interface: pool.Interface,
Subnet: pool.Subnet + "/" + pool.Netmask,
})
}
}
}
return result
}
func checkInterfaceOverlap(cfg *network.InterfaceConfig) (string, bool) {
if cfg.Mode != "static" || cfg.Address == "" || cfg.Netmask == "" {
return "", false
}
all := collectAllSubnets(cfg.Name)
overlaps := network.CheckOverlap(cfg.Address, cfg.Netmask, cfg.Name, all)
if len(overlaps) > 0 {
var names []string
for _, o := range overlaps {
label := o.Interface
if o.Label != "" {
label = o.Label + " (" + o.Interface + ")"
}
names = append(names, label)
}
return "IP-адрес пересекается с подсетью интерфейса " + strings.Join(names, ", "), true
}
return "", false
}
func checkDHCPPoolOverlap(subnet, mask, iface string) (string, bool) {
if subnet == "" || mask == "" {
return "", false
}
all := collectAllSubnetsForDHCP(iface)
overlaps := network.CheckOverlap(subnet, mask, iface, all)
if len(overlaps) > 0 {
var names []string
for _, o := range overlaps {
label := o.Interface
if o.Label != "" {
label = o.Label + " (" + o.Interface + ")"
}
names = append(names, label)
}
return "Подсеть пересекается с " + strings.Join(names, ", "), true
}
return "", false
}
func HandleSubnets(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
fail(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
exclude := r.URL.Query().Get("exclude")
result := collectAllSubnets(exclude)
ok(w, result)
}