Files
alpine-router/handlers/overlap.go
2026-04-15 11:38:26 +03:00

172 lines
4.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)
}