diff --git a/net/route.go b/net/route.go index bff99e2d..463f843b 100644 --- a/net/route.go +++ b/net/route.go @@ -9,21 +9,13 @@ import ( // A network is considered free if it does not overlap any existing // routes on this host. This is the same approach taken by Docker. -func CheckNetworkFree(subnet *net.IPNet, ignoreIfName string) error { - routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) - if err != nil { - return err - } - for _, route := range routes { +func CheckNetworkFree(subnet *net.IPNet, ignoreIfaceNames map[string]struct{}) error { + return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error { if route.Dst != nil && overlaps(route.Dst, subnet) { - if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil && link.Attrs().Name == ignoreIfName { - continue - } - return fmt.Errorf("Network %s overlaps with existing route %s on host.", subnet, route.Dst) } - } - return nil + return nil + }) } // Two networks overlap if the start-point of one is inside the other. @@ -33,17 +25,28 @@ func overlaps(n1, n2 *net.IPNet) bool { // For a specific address, we only care if it is actually *inside* an // existing route, because weave-local traffic never hits IP routing. -func CheckAddressOverlap(addr net.IP, ignoreIfName string) error { +func CheckAddressOverlap(addr net.IP, ignoreIfaceNames map[string]struct{}) error { + return forEachRoute(ignoreIfaceNames, func(route netlink.Route) error { + if route.Dst != nil && route.Dst.Contains(addr) { + return fmt.Errorf("Address %s overlaps with existing route %s on host.", addr, route.Dst) + } + return nil + }) +} + +func forEachRoute(ignoreIfaceNames map[string]struct{}, check func(netlink.Route) error) error { routes, err := netlink.RouteList(nil, netlink.FAMILY_V4) if err != nil { return err } for _, route := range routes { - if route.Dst != nil && route.Dst.Contains(addr) { - if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil && link.Attrs().Name == ignoreIfName { + if link, err := netlink.LinkByIndex(route.LinkIndex); err == nil { + if _, found := ignoreIfaceNames[link.Attrs().Name]; found { continue } - return fmt.Errorf("Address %s overlaps with existing route %s on host.", addr, route.Dst) + } + if err := check(route); err != nil { + return err } } return nil diff --git a/prog/netcheck/netcheck.go b/prog/netcheck/netcheck.go index 78261a0e..fe822f2e 100644 --- a/prog/netcheck/netcheck.go +++ b/prog/netcheck/netcheck.go @@ -15,10 +15,21 @@ func fatal(err error) { os.Exit(1) } -func main() { - var ignoreIfaceName string +type stringList map[string]struct{} - mflag.StringVar(&ignoreIfaceName, []string{"-ignore-iface"}, "", "name of interface to ignore)") +func (ss *stringList) Set(value string) error { + (*ss)[value] = struct{}{} + return nil +} + +func (ss *stringList) String() string { + return fmt.Sprintf("%v", *ss) +} + +func main() { + ignoreIfaceNames := make(stringList) + + mflag.Var(&ignoreIfaceNames, []string{"-ignore-iface"}, "name of interface to ignore)") mflag.Parse() if len(mflag.Args()) < 1 { @@ -32,9 +43,9 @@ func main() { fatal(err) } if ipnet.IP.Equal(addr) { - err = weavenet.CheckNetworkFree(ipnet, ignoreIfaceName) + err = weavenet.CheckNetworkFree(ipnet, ignoreIfaceNames) } else { - err = weavenet.CheckAddressOverlap(addr, ignoreIfaceName) + err = weavenet.CheckAddressOverlap(addr, ignoreIfaceNames) } if err != nil { fatal(err)