소스 검색

Make sure the routes IP are taken into consideration + add unit test for network overlap detection

Guillaume J. Charmes 12 년 전
부모
커밋
f5a8e90d10
2개의 변경된 파일39개의 추가작업 그리고 11개의 파일을 삭제
  1. 20 11
      network.go
  2. 19 0
      network_test.go

+ 20 - 11
network.go

@@ -93,24 +93,29 @@ func iptables(args ...string) error {
 	return nil
 	return nil
 }
 }
 
 
-func checkRouteOverlaps(dockerNetwork *net.IPNet) error {
-	output, err := ip("route")
-	if err != nil {
-		return err
-	}
-	utils.Debugf("Routes:\n\n%s", output)
-	for _, line := range strings.Split(output, "\n") {
+func checkRouteOverlaps(routes string, dockerNetwork *net.IPNet) error {
+	utils.Debugf("Routes:\n\n%s", routes)
+	for _, line := range strings.Split(routes, "\n") {
 		if strings.Trim(line, "\r\n\t ") == "" || strings.Contains(line, "default") {
 		if strings.Trim(line, "\r\n\t ") == "" || strings.Contains(line, "default") {
 			continue
 			continue
 		}
 		}
-		if _, network, err := net.ParseCIDR(strings.Split(line, " ")[0]); err != nil {
+		_, network, err := net.ParseCIDR(strings.Split(line, " ")[0])
+		if err != nil {
 			// is this a mask-less IP address?
 			// is this a mask-less IP address?
 			if ip := net.ParseIP(strings.Split(line, " ")[0]); ip == nil {
 			if ip := net.ParseIP(strings.Split(line, " ")[0]); ip == nil {
 				// fail only if it's neither a network nor a mask-less IP address
 				// fail only if it's neither a network nor a mask-less IP address
 				return fmt.Errorf("Unexpected ip route output: %s (%s)", err, line)
 				return fmt.Errorf("Unexpected ip route output: %s (%s)", err, line)
+			} else {
+				_, network, err = net.ParseCIDR(ip.String() + "/32")
+				if err != nil {
+					return err
+				}
+			}
+		}
+		if err == nil && network != nil {
+			if networkOverlaps(dockerNetwork, network) {
+				return fmt.Errorf("Network %s is already routed: '%s'", dockerNetwork, line)
 			}
 			}
-		} else if networkOverlaps(dockerNetwork, network) {
-			return fmt.Errorf("Network %s is already routed: '%s'", dockerNetwork.String(), line)
 		}
 		}
 	}
 	}
 	return nil
 	return nil
@@ -146,7 +151,11 @@ func CreateBridgeIface(ifaceName string) error {
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		if err := checkRouteOverlaps(dockerNetwork); err == nil {
+		routes, err := ip("route")
+		if err != nil {
+			return err
+		}
+		if err := checkRouteOverlaps(routes, dockerNetwork); err == nil {
 			ifaceAddr = addr
 			ifaceAddr = addr
 			break
 			break
 		} else {
 		} else {

+ 19 - 0
network_test.go

@@ -383,3 +383,22 @@ func TestNetworkOverlaps(t *testing.T) {
 	//netX starts and ends before netY
 	//netX starts and ends before netY
 	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
 	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
 }
 }
+
+func TestCheckRouteOverlaps(t *testing.T) {
+	routes := `default via 10.0.2.2 dev eth0
+10.0.2.0 dev eth0  proto kernel  scope link  src 10.0.2.15
+10.0.3.0/24 dev lxcbr0  proto kernel  scope link  src 10.0.3.1
+10.0.42.0/24 dev testdockbr0  proto kernel  scope link  src 10.0.42.1
+172.16.42.0/24 dev docker0  proto kernel  scope link  src 172.16.42.1
+192.168.142.0/24 dev eth1  proto kernel  scope link  src 192.168.142.142`
+
+	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
+	if err := checkRouteOverlaps(routes, netX); err != nil {
+		t.Fatal(err)
+	}
+
+	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
+	if err := checkRouteOverlaps(routes, netX); err == nil {
+		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
+	}
+}