172 lines
4.0 KiB
Go
172 lines
4.0 KiB
Go
|
|
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)
|
|||
|
|
}
|