diff --git a/Makefile b/Makefile index f69d0969..8559d21b 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ $(WEAVER_EXE) $(WEAVEDNS_EXE) $(WEAVEPROXY_EXE) $(NETCHECK_EXE): common/*.go com $(WEAVER_EXE): router/*.go ipam/*.go ipam/*/*.go prog/weaver/main.go $(WEAVEDNS_EXE): nameserver/*.go prog/weavedns/main.go $(WEAVEPROXY_EXE): proxy/*.go prog/weaveproxy/main.go +$(NETCHECK_EXE): prog/netcheck/netcheck.go # Sigproxy and weavewait need separate rules as they fail the netgo check in # the main build stanza due to not importing net package diff --git a/net/route.go b/net/route.go index 0d8a1bab..80df987a 100644 --- a/net/route.go +++ b/net/route.go @@ -16,7 +16,7 @@ func CheckNetworkFree(subnet *net.IPNet) error { } for _, route := range routes { if route.Dst != nil && overlaps(route.Dst, subnet) { - return fmt.Errorf("network %s would overlap with route %s", subnet, route.Dst) + return fmt.Errorf("Network %s overlaps with existing route %s", subnet, route.Dst) } } return nil @@ -26,3 +26,18 @@ func CheckNetworkFree(subnet *net.IPNet) error { func overlaps(n1, n2 *net.IPNet) bool { return n1.Contains(n2.IP) || n2.Contains(n1.IP) } + +// 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) 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) { + return fmt.Errorf("Address %s overlaps with existing route %s", addr, route.Dst) + } + } + return nil +} diff --git a/prog/netcheck/netcheck.go b/prog/netcheck/netcheck.go index 383f5d9b..96a26ed4 100644 --- a/prog/netcheck/netcheck.go +++ b/prog/netcheck/netcheck.go @@ -1,4 +1,4 @@ -/* netcheck: check whether a given network overlaps with any existing routes */ +/* netcheck: check whether a given network or address overlaps with any existing routes */ package main import ( @@ -10,7 +10,7 @@ import ( ) func fatal(err error) { - fmt.Println(err) + fmt.Fprintln(os.Stderr, err) os.Exit(1) } @@ -19,12 +19,17 @@ func main() { os.Exit(0) } - ipRangeStr := os.Args[1] - _, ipnet, err := net.ParseCIDR(ipRangeStr) + cidrStr := os.Args[1] + addr, ipnet, err := net.ParseCIDR(cidrStr) if err != nil { fatal(err) } - if err := weavenet.CheckNetworkFree(ipnet); err != nil { + if ipnet.IP.Equal(addr) { + err = weavenet.CheckNetworkFree(ipnet) + } else { + err = weavenet.CheckAddressOverlap(addr) + } + if err != nil { fatal(err) } os.Exit(0) diff --git a/weave b/weave index 7d4c9f58..5bc53f69 100755 --- a/weave +++ b/weave @@ -858,6 +858,8 @@ ipam_cidrs() { IPAM_CIDRS="$IPAM_CIDRS $CIDR" ALL_CIDRS="$ALL_CIDRS $CIDR" else + # This is a plain IP address; warn if it clashes but carry on + command_exists netcheck && netcheck $1 || true ALL_CIDRS="$ALL_CIDRS $1" fi shift 1