Bladeren bron

Merge pull request #92 from mindscratch/issue-91-support-old-iptables

iptables: support iptables older than 1.4.11
Eugene Yakubovich 10 jaren geleden
bovenliggende
commit
a7b435a920
1 gewijzigde bestanden met toevoegingen van 99 en 2 verwijderingen
  1. 99 2
      pkg/ip/iptables.go

+ 99 - 2
pkg/ip/iptables.go

@@ -1,7 +1,13 @@
 package ip
 
 import (
+	"bytes"
+	"fmt"
+	log "github.com/coreos/flannel/Godeps/_workspace/src/github.com/golang/glog"
 	"os/exec"
+	"regexp"
+	"strconv"
+	"strings"
 	"syscall"
 )
 
@@ -19,9 +25,19 @@ func NewIPTables() (*IPTables, error) {
 }
 
 func (ipt *IPTables) Exists(table string, args ...string) (bool, error) {
-	cmd := append([]string{"-t", table, "-C"}, args...)
-	err := exec.Command(ipt.path, cmd...).Run()
+	checkPresent, err := getIptablesHasCheckCommand()
+	if err != nil {
+		log.Warningf("Error checking iptables version, assuming version at least 1.4.11: %v\n", err)
+		checkPresent = true
+	}
 
+	if !checkPresent {
+		cmd := append([]string{"-A"}, args...)
+		return existsForOldIpTables(table, strings.Join(cmd, " "))
+	} else {
+		cmd := append([]string{"-t", table, "-C"}, args...)
+		err = exec.Command(ipt.path, cmd...).Run()
+	}
 	switch {
 	case err == nil:
 		return true, nil
@@ -66,3 +82,84 @@ func (ipt *IPTables) ClearChain(table, chain string) error {
 		return err
 	}
 }
+
+// Checks if iptables has the "-C" flag
+func getIptablesHasCheckCommand() (bool, error) {
+	vstring, err := getIptablesVersionString()
+	if err != nil {
+		return false, err
+	}
+
+	v1, v2, v3, err := extractIptablesVersion(vstring)
+	if err != nil {
+		return false, err
+	}
+
+	return iptablesHasCheckCommand(v1, v2, v3), nil
+}
+
+// getIptablesVersion returns the first three components of the iptables version.
+// e.g. "iptables v1.3.66" would return (1, 3, 66, nil)
+func extractIptablesVersion(str string) (int, int, int, error) {
+	versionMatcher := regexp.MustCompile("v([0-9]+)\\.([0-9]+)\\.([0-9]+)")
+	result := versionMatcher.FindStringSubmatch(str)
+	if result == nil {
+		return 0, 0, 0, fmt.Errorf("no iptables version found in string: %s", str)
+	}
+
+	v1, err := strconv.Atoi(result[1])
+	if err != nil {
+		return 0, 0, 0, err
+	}
+
+	v2, err := strconv.Atoi(result[2])
+	if err != nil {
+		return 0, 0, 0, err
+	}
+
+	v3, err := strconv.Atoi(result[3])
+	if err != nil {
+		return 0, 0, 0, err
+	}
+
+	return v1, v2, v3, nil
+}
+
+// Runs "iptables --version" to get the version string
+func getIptablesVersionString() (string, error) {
+	cmd := exec.Command("iptables", "--version")
+	var out bytes.Buffer
+	cmd.Stdout = &out
+	err := cmd.Run()
+	if err != nil {
+		return "", err
+	}
+	return out.String(), nil
+}
+
+// Checks if an iptables version is after 1.4.11, when --check was added
+func iptablesHasCheckCommand(v1 int, v2 int, v3 int) bool {
+	if v1 > 1 {
+		return true
+	}
+	if v1 == 1 && v2 > 4 {
+		return true
+	}
+	if v1 == 1 && v2 == 4 && v3 >= 11 {
+		return true
+	}
+	return false
+}
+
+// Checks if a rule specification exists for a table
+func existsForOldIpTables(table string, ruleSpec string) (bool, error) {
+	cmd := exec.Command("iptables", "-t", table, "-S")
+	var out bytes.Buffer
+	cmd.Stdout = &out
+	err := cmd.Run()
+	if err != nil {
+		return false, err
+	}
+	rules := out.String()
+	return strings.Contains(rules, ruleSpec), nil
+}