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) }