Browse code

Fix duplicate iptables rules

If iptables version is < 1.4.11, try to delete the rule vs. checking if it exists. Fixes #6831.

Docker-DCO-1.1-Signed-off-by: Jessica Frazelle <jfrazelle@users.noreply.github.com> (github: jfrazelle)

Jessica Frazelle authored on 2014/07/10 13:22:01
Showing 1 changed files
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"net"
7 7
 	"os"
8 8
 	"os/exec"
9
+	"regexp"
9 10
 	"strconv"
10 11
 	"strings"
11 12
 )
... ...
@@ -141,10 +142,27 @@ func (c *Chain) Remove() error {
141 141
 
142 142
 // Check if an existing rule exists
143 143
 func Exists(args ...string) bool {
144
-	if _, err := Raw(append([]string{"-C"}, args...)...); err != nil {
145
-		return false
144
+	// iptables -C, --check option was added in v.1.4.11
145
+	// http://ftp.netfilter.org/pub/iptables/changes-iptables-1.4.11.txt
146
+
147
+	// try -C
148
+	// if exit status is 0 then return true, the rule exists
149
+	if _, err := Raw(append([]string{"-C"}, args...)...); err == nil {
150
+		return true
146 151
 	}
147
-	return true
152
+
153
+	// parse iptables-save for the rule
154
+	rule := strings.Replace(strings.Join(args, " "), "-t nat ", "", -1)
155
+	existingRules, _ := exec.Command("iptables-save").Output()
156
+
157
+	// regex to replace ips in rule
158
+	// because MASQUERADE rule will not be exactly what was passed
159
+	re := regexp.MustCompile(`[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2}`)
160
+
161
+	return strings.Contains(
162
+		re.ReplaceAllString(string(existingRules), "?"),
163
+		re.ReplaceAllString(rule, "?"),
164
+	)
148 165
 }
149 166
 
150 167
 func Raw(args ...string) ([]byte, error) {