summaryrefslogtreecommitdiff
path: root/vendor/github.com/coreos
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/coreos')
-rw-r--r--vendor/github.com/coreos/go-iptables/iptables/iptables.go97
1 files changed, 76 insertions, 21 deletions
diff --git a/vendor/github.com/coreos/go-iptables/iptables/iptables.go b/vendor/github.com/coreos/go-iptables/iptables/iptables.go
index 3b62fe205..8db2597a4 100644
--- a/vendor/github.com/coreos/go-iptables/iptables/iptables.go
+++ b/vendor/github.com/coreos/go-iptables/iptables/iptables.go
@@ -29,11 +29,15 @@ import (
// Adds the output of stderr to exec.ExitError
type Error struct {
exec.ExitError
- cmd exec.Cmd
- msg string
+ cmd exec.Cmd
+ msg string
+ exitStatus *int //for overriding
}
func (e *Error) ExitStatus() int {
+ if e.exitStatus != nil {
+ return *e.exitStatus
+ }
return e.Sys().(syscall.WaitStatus).ExitStatus()
}
@@ -65,6 +69,7 @@ type IPTables struct {
v1 int
v2 int
v3 int
+ mode string // the underlying iptables operating mode, e.g. nf_tables
}
// New creates a new IPTables.
@@ -81,12 +86,10 @@ func NewWithProtocol(proto Protocol) (*IPTables, error) {
return nil, err
}
vstring, err := getIptablesVersionString(path)
- v1, v2, v3, err := extractIptablesVersion(vstring)
+ v1, v2, v3, mode, err := extractIptablesVersion(vstring)
+
+ checkPresent, waitPresent, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3)
- checkPresent, waitPresent, randomFullyPresent, err := getIptablesCommandSupport(v1, v2, v3)
- if err != nil {
- return nil, fmt.Errorf("error checking iptables version: %v", err)
- }
ipt := IPTables{
path: path,
proto: proto,
@@ -96,6 +99,7 @@ func NewWithProtocol(proto Protocol) (*IPTables, error) {
v1: v1,
v2: v2,
v3: v3,
+ mode: mode,
}
return &ipt, nil
}
@@ -266,10 +270,27 @@ func (ipt *IPTables) executeList(args []string) ([]string, error) {
}
rules := strings.Split(stdout.String(), "\n")
+
+ // strip trailing newline
if len(rules) > 0 && rules[len(rules)-1] == "" {
rules = rules[:len(rules)-1]
}
+ // nftables mode doesn't return an error code when listing a non-existent
+ // chain. Patch that up.
+ if len(rules) == 0 && ipt.mode == "nf_tables" {
+ v := 1
+ return nil, &Error{
+ cmd: exec.Cmd{Args: args},
+ msg: "iptables: No chain/target/match by that name.",
+ exitStatus: &v,
+ }
+ }
+
+ for i, rule := range rules {
+ rules[i] = filterRuleOutput(rule)
+ }
+
return rules, nil
}
@@ -284,11 +305,18 @@ func (ipt *IPTables) NewChain(table, chain string) error {
func (ipt *IPTables) ClearChain(table, chain string) error {
err := ipt.NewChain(table, chain)
+ // the exit code for "this table already exists" is different for
+ // different iptables modes
+ existsErr := 1
+ if ipt.mode == "nf_tables" {
+ existsErr = 4
+ }
+
eerr, eok := err.(*Error)
switch {
case err == nil:
return nil
- case eok && eerr.ExitStatus() == 1:
+ case eok && eerr.ExitStatus() == existsErr:
// chain already exists. Flush (clear) it.
return ipt.run("-t", table, "-F", chain)
default:
@@ -357,7 +385,7 @@ func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error {
if err := cmd.Run(); err != nil {
switch e := err.(type) {
case *exec.ExitError:
- return &Error{*e, cmd, stderr.String()}
+ return &Error{*e, cmd, stderr.String(), nil}
default:
return err
}
@@ -376,36 +404,40 @@ func getIptablesCommand(proto Protocol) string {
}
// Checks if iptables has the "-C" and "--wait" flag
-func getIptablesCommandSupport(v1 int, v2 int, v3 int) (bool, bool, bool, error) {
-
- return iptablesHasCheckCommand(v1, v2, v3), iptablesHasWaitCommand(v1, v2, v3), iptablesHasRandomFully(v1, v2, v3), nil
+func getIptablesCommandSupport(v1 int, v2 int, v3 int) (bool, bool, bool) {
+ return iptablesHasCheckCommand(v1, v2, v3), iptablesHasWaitCommand(v1, v2, v3), iptablesHasRandomFully(v1, v2, v3)
}
-// 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]+)")
+// getIptablesVersion returns the first three components of the iptables version
+// and the operating mode (e.g. nf_tables or legacy)
+// e.g. "iptables v1.3.66" would return (1, 3, 66, legacy, nil)
+func extractIptablesVersion(str string) (int, int, int, string, error) {
+ versionMatcher := regexp.MustCompile(`v([0-9]+)\.([0-9]+)\.([0-9]+)(?:\s+\((\w+))?`)
result := versionMatcher.FindStringSubmatch(str)
if result == nil {
- return 0, 0, 0, fmt.Errorf("no iptables version found in string: %s", str)
+ 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
+ return 0, 0, 0, "", err
}
v2, err := strconv.Atoi(result[2])
if err != nil {
- return 0, 0, 0, err
+ return 0, 0, 0, "", err
}
v3, err := strconv.Atoi(result[3])
if err != nil {
- return 0, 0, 0, err
+ return 0, 0, 0, "", err
}
- return v1, v2, v3, nil
+ mode := "legacy"
+ if result[4] != "" {
+ mode = result[4]
+ }
+ return v1, v2, v3, mode, nil
}
// Runs "iptables --version" to get the version string
@@ -473,3 +505,26 @@ func (ipt *IPTables) existsForOldIptables(table, chain string, rulespec []string
}
return strings.Contains(stdout.String(), rs), nil
}
+
+// counterRegex is the regex used to detect nftables counter format
+var counterRegex = regexp.MustCompile(`^\[([0-9]+):([0-9]+)\] `)
+
+// filterRuleOutput works around some inconsistencies in output.
+// For example, when iptables is in legacy vs. nftables mode, it produces
+// different results.
+func filterRuleOutput(rule string) string {
+ out := rule
+
+ // work around an output difference in nftables mode where counters
+ // are output in iptables-save format, rather than iptables -S format
+ // The string begins with "[0:0]"
+ //
+ // Fixes #49
+ if groups := counterRegex.FindStringSubmatch(out); groups != nil {
+ // drop the brackets
+ out = out[len(groups[0]):]
+ out = fmt.Sprintf("%s -c %s %s", out, groups[1], groups[2])
+ }
+
+ return out
+}