Browse code

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

Guillaume J. Charmes authored on 2013/08/02 10:12:39
Showing 2 changed files
... ...
@@ -93,24 +93,29 @@ func iptables(args ...string) error {
93 93
 	return nil
94 94
 }
95 95
 
96
-func checkRouteOverlaps(dockerNetwork *net.IPNet) error {
97
-	output, err := ip("route")
98
-	if err != nil {
99
-		return err
100
-	}
101
-	utils.Debugf("Routes:\n\n%s", output)
102
-	for _, line := range strings.Split(output, "\n") {
96
+func checkRouteOverlaps(routes string, dockerNetwork *net.IPNet) error {
97
+	utils.Debugf("Routes:\n\n%s", routes)
98
+	for _, line := range strings.Split(routes, "\n") {
103 99
 		if strings.Trim(line, "\r\n\t ") == "" || strings.Contains(line, "default") {
104 100
 			continue
105 101
 		}
106
-		if _, network, err := net.ParseCIDR(strings.Split(line, " ")[0]); err != nil {
102
+		_, network, err := net.ParseCIDR(strings.Split(line, " ")[0])
103
+		if err != nil {
107 104
 			// is this a mask-less IP address?
108 105
 			if ip := net.ParseIP(strings.Split(line, " ")[0]); ip == nil {
109 106
 				// fail only if it's neither a network nor a mask-less IP address
110 107
 				return fmt.Errorf("Unexpected ip route output: %s (%s)", err, line)
108
+			} else {
109
+				_, network, err = net.ParseCIDR(ip.String() + "/32")
110
+				if err != nil {
111
+					return err
112
+				}
113
+			}
114
+		}
115
+		if err == nil && network != nil {
116
+			if networkOverlaps(dockerNetwork, network) {
117
+				return fmt.Errorf("Network %s is already routed: '%s'", dockerNetwork, line)
111 118
 			}
112
-		} else if networkOverlaps(dockerNetwork, network) {
113
-			return fmt.Errorf("Network %s is already routed: '%s'", dockerNetwork.String(), line)
114 119
 		}
115 120
 	}
116 121
 	return nil
... ...
@@ -146,7 +151,11 @@ func CreateBridgeIface(ifaceName string) error {
146 146
 		if err != nil {
147 147
 			return err
148 148
 		}
149
-		if err := checkRouteOverlaps(dockerNetwork); err == nil {
149
+		routes, err := ip("route")
150
+		if err != nil {
151
+			return err
152
+		}
153
+		if err := checkRouteOverlaps(routes, dockerNetwork); err == nil {
150 154
 			ifaceAddr = addr
151 155
 			break
152 156
 		} else {
... ...
@@ -383,3 +383,22 @@ func TestNetworkOverlaps(t *testing.T) {
383 383
 	//netX starts and ends before netY
384 384
 	AssertNoOverlap("172.16.1.1/25", "172.16.2.1/24", t)
385 385
 }
386
+
387
+func TestCheckRouteOverlaps(t *testing.T) {
388
+	routes := `default via 10.0.2.2 dev eth0
389
+10.0.2.0 dev eth0  proto kernel  scope link  src 10.0.2.15
390
+10.0.3.0/24 dev lxcbr0  proto kernel  scope link  src 10.0.3.1
391
+10.0.42.0/24 dev testdockbr0  proto kernel  scope link  src 10.0.42.1
392
+172.16.42.0/24 dev docker0  proto kernel  scope link  src 172.16.42.1
393
+192.168.142.0/24 dev eth1  proto kernel  scope link  src 192.168.142.142`
394
+
395
+	_, netX, _ := net.ParseCIDR("172.16.0.1/24")
396
+	if err := checkRouteOverlaps(routes, netX); err != nil {
397
+		t.Fatal(err)
398
+	}
399
+
400
+	_, netX, _ = net.ParseCIDR("10.0.2.0/24")
401
+	if err := checkRouteOverlaps(routes, netX); err == nil {
402
+		t.Fatalf("10.0.2.0/24 and 10.0.2.0 should overlap but it doesn't")
403
+	}
404
+}