14.04.2026 Update
This commit is contained in:
172
handlers/overlap.go
Normal file
172
handlers/overlap.go
Normal file
@@ -0,0 +1,172 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user