Explorar el Código

deps: Update go-iptables version

This is for better compatibility with older versions of iptables
Tom Denham hace 8 años
padre
commit
80281c75a1

+ 3 - 3
glide.lock

@@ -1,5 +1,5 @@
-hash: 17c68b031c830c07db965733785b9c1575b542503c07ad742a00972e59310ffc
-updated: 2016-07-12T01:03:53.553504535-04:00
+hash: 580902b18b5765bf69f0327c9024ea6f41b626c8c5eaf07f5fd42bf114ce6d0d
+updated: 2016-07-18T13:31:14.645698311-07:00
 imports:
 - name: github.com/aws/aws-sdk-go
   version: 5c0313fff8cd85670ae4fc996254dd7d66cb4cf7
@@ -31,7 +31,7 @@ imports:
   - pkg/types
   - pkg/runtime
 - name: github.com/coreos/go-iptables
-  version: 74b0926558061d3a23824e9c18c9cf9c1b9c11f4
+  version: fbb73372b87f6e89951c2b6b31470c2c9d5cfae3
   subpackages:
   - iptables
 - name: github.com/coreos/go-systemd

+ 1 - 1
glide.yaml

@@ -21,7 +21,7 @@ import:
   - pkg/transport
   - pkg/types
 - package: github.com/coreos/go-iptables
-  version: 74b0926558061d3a23824e9c18c9cf9c1b9c11f4
+  version: v0.1.0
   subpackages:
   - iptables
 - package: github.com/coreos/go-systemd

+ 17 - 1
vendor/github.com/coreos/go-iptables/.travis.yml

@@ -1,9 +1,25 @@
 language: go
+sudo: required
+dist: trusty
+
 go:
   - 1.4
+  - 1.5.3
+  - 1.6
+  - tip
+
+env:
+  global:
+    - TOOLS_CMD=golang.org/x/tools/cmd
+    - PATH=$GOROOT/bin:$PATH
+    - SUDO_PERMITTED=1
+
+matrix:
+  allow_failures:
+    - go: tip
 
 install:
  - go get golang.org/x/tools/cmd/cover
 
 script:
- - ./build-check
+ - ./test

+ 2 - 1
vendor/github.com/coreos/go-iptables/build

@@ -1,4 +1,5 @@
-#!/bin/bash -e
+#!/usr/bin/env bash
+set -e
 
 ORG_PATH="github.com/coreos"
 REPO_PATH="${ORG_PATH}/go-iptables"

+ 0 - 36
vendor/github.com/coreos/go-iptables/build-check

@@ -1,36 +0,0 @@
-#!/bin/bash -e
-#
-# Run all go-iptables tests
-#   ./test
-#   ./test -v
-#
-# Run tests for one package
-#   PKG=./unit ./test
-#   PKG=ssh ./test
-#
-
-# Invoke ./cover for HTML output
-COVER=${COVER:-"-cover"}
-
-source ./build
-
-FORMATTABLE="iptables"
-
-# user has not provided PKG override
-if [ -z "$PKG" ]; then
-	FMT=$FORMATTABLE
-
-# user has provided PKG override
-else
-	# strip out slashes and dots from PKG=./foo/
-	FMT=${PKG//\//}
-fi
-
-echo "Checking gofmt..."
-fmtRes=$(gofmt -l $FMT)
-if [ -n "${fmtRes}" ]; then
-	echo -e "gofmt checking failed:\n${fmtRes}"
-	exit 255
-fi
-
-echo "Success"

+ 90 - 51
vendor/github.com/coreos/go-iptables/iptables/iptables.go

@@ -17,7 +17,7 @@ package iptables
 import (
 	"bytes"
 	"fmt"
-	"log"
+	"io"
 	"os/exec"
 	"regexp"
 	"strconv"
@@ -40,7 +40,9 @@ func (e *Error) Error() string {
 }
 
 type IPTables struct {
-	path string
+	path     string
+	hasCheck bool
+	hasWait  bool
 }
 
 func New() (*IPTables, error) {
@@ -48,33 +50,34 @@ func New() (*IPTables, error) {
 	if err != nil {
 		return nil, err
 	}
-
-	return &IPTables{path}, nil
+	checkPresent, waitPresent, err := getIptablesCommandSupport()
+	if err != nil {
+		return nil, fmt.Errorf("error checking iptables version: %v", err)
+	}
+	ipt := IPTables{
+		path:     path,
+		hasCheck: checkPresent,
+		hasWait:  waitPresent,
+	}
+	return &ipt, nil
 }
 
 // Exists checks if given rulespec in specified table/chain exists
 func (ipt *IPTables) Exists(table, chain string, rulespec ...string) (bool, error) {
-	checkPresent, err := getIptablesHasCheckCommand()
-	if err != nil {
-		log.Printf("Error checking iptables version, assuming version at least 1.4.11: %v", err)
-		checkPresent = true
-	}
+	if !ipt.hasCheck {
+		return ipt.existsForOldIptables(table, chain, rulespec)
 
-	if !checkPresent {
-		cmd := append([]string{"-A", chain}, rulespec...)
-		return existsForOldIpTables(table, strings.Join(cmd, " "))
-	} else {
-		cmd := append([]string{"-t", table, "-C", chain}, rulespec...)
-		err := ipt.run(cmd...)
-
-		switch {
-		case err == nil:
-			return true, nil
-		case err.(*Error).ExitStatus() == 1:
-			return false, nil
-		default:
-			return false, err
-		}
+	}
+	cmd := append([]string{"-t", table, "-C", chain}, rulespec...)
+	err := ipt.run(cmd...)
+	eerr, eok := err.(*Error)
+	switch {
+	case err == nil:
+		return true, nil
+	case eok && eerr.ExitStatus() == 1:
+		return false, nil
+	default:
+		return false, err
 	}
 }
 
@@ -112,16 +115,10 @@ func (ipt *IPTables) Delete(table, chain string, rulespec ...string) error {
 
 // List rules in specified table/chain
 func (ipt *IPTables) List(table, chain string) ([]string, error) {
-	var stdout, stderr bytes.Buffer
-	cmd := exec.Cmd{
-		Path:   ipt.path,
-		Args:   []string{ipt.path, "--wait", "-t", table, "-S", chain},
-		Stdout: &stdout,
-		Stderr: &stderr,
-	}
-
-	if err := cmd.Run(); err != nil {
-		return nil, &Error{*(err.(*exec.ExitError)), stderr.String()}
+	args := []string{"-t", table, "-S", chain}
+	var stdout bytes.Buffer
+	if err := ipt.runWithOutput(args, &stdout); err != nil {
+		return nil, err
 	}
 
 	rules := strings.Split(stdout.String(), "\n")
@@ -136,15 +133,16 @@ func (ipt *IPTables) NewChain(table, chain string) error {
 	return ipt.run("-t", table, "-N", chain)
 }
 
-// ClearChain flushed (deletes all rules) in the specifed table/chain.
-// If the chain does not exist, new one will be created
+// ClearChain flushed (deletes all rules) in the specified table/chain.
+// If the chain does not exist, a new one will be created
 func (ipt *IPTables) ClearChain(table, chain string) error {
 	err := ipt.NewChain(table, chain)
 
+	eerr, eok := err.(*Error)
 	switch {
 	case err == nil:
 		return nil
-	case err.(*Error).ExitStatus() == 1:
+	case eok && eerr.ExitStatus() == 1:
 		// chain already exists. Flush (clear) it.
 		return ipt.run("-t", table, "-F", chain)
 	default:
@@ -152,18 +150,46 @@ func (ipt *IPTables) ClearChain(table, chain string) error {
 	}
 }
 
+// RenameChain renames the old chain to the new one.
+func (ipt *IPTables) RenameChain(table, oldChain, newChain string) error {
+	return ipt.run("-t", table, "-E", oldChain, newChain)
+}
+
 // DeleteChain deletes the chain in the specified table.
 // The chain must be empty
 func (ipt *IPTables) DeleteChain(table, chain string) error {
 	return ipt.run("-t", table, "-X", chain)
 }
 
+// run runs an iptables command with the given arguments, ignoring
+// any stdout output
 func (ipt *IPTables) run(args ...string) error {
+	return ipt.runWithOutput(args, nil)
+}
+
+// runWithOutput runs an iptables command with the given arguments,
+// writing any stdout output to the given writer
+func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error {
+	args = append([]string{ipt.path}, args...)
+	if ipt.hasWait {
+		args = append(args, "--wait")
+	} else {
+		fmu, err := newXtablesFileLock()
+		if err != nil {
+			return err
+		}
+		ul, err := fmu.tryLock()
+		if err != nil {
+			return err
+		}
+		defer ul.Unlock()
+	}
+
 	var stderr bytes.Buffer
-	args = append([]string{"--wait"}, args...)
 	cmd := exec.Cmd{
 		Path:   ipt.path,
-		Args:   append([]string{ipt.path}, args...),
+		Args:   args,
+		Stdout: stdout,
 		Stderr: &stderr,
 	}
 
@@ -174,19 +200,19 @@ func (ipt *IPTables) run(args ...string) error {
 	return nil
 }
 
-// Checks if iptables has the "-C" flag
-func getIptablesHasCheckCommand() (bool, error) {
+// Checks if iptables has the "-C" and "--wait" flag
+func getIptablesCommandSupport() (bool, bool, error) {
 	vstring, err := getIptablesVersionString()
 	if err != nil {
-		return false, err
+		return false, false, err
 	}
 
 	v1, v2, v3, err := extractIptablesVersion(vstring)
 	if err != nil {
-		return false, err
+		return false, false, err
 	}
 
-	return iptablesHasCheckCommand(v1, v2, v3), nil
+	return iptablesHasCheckCommand(v1, v2, v3), iptablesHasWaitCommand(v1, v2, v3), nil
 }
 
 // getIptablesVersion returns the first three components of the iptables version.
@@ -242,15 +268,28 @@ func iptablesHasCheckCommand(v1 int, v2 int, v3 int) bool {
 	return false
 }
 
+// Checks if an iptables version is after 1.4.20, when --wait was added
+func iptablesHasWaitCommand(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 >= 20 {
+		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()
+func (ipt *IPTables) existsForOldIptables(table, chain string, rulespec []string) (bool, error) {
+	rs := strings.Join(append([]string{"-A", chain}, rulespec...), " ")
+	args := []string{"-t", table, "-S"}
+	var stdout bytes.Buffer
+	err := ipt.runWithOutput(args, &stdout)
 	if err != nil {
 		return false, err
 	}
-	rules := out.String()
-	return strings.Contains(rules, ruleSpec), nil
+	return strings.Contains(stdout.String(), rs), nil
 }

+ 65 - 12
vendor/github.com/coreos/go-iptables/iptables/iptables_test.go

@@ -16,6 +16,7 @@ package iptables
 
 import (
 	"crypto/rand"
+	"fmt"
 	"math/big"
 	"reflect"
 	"testing"
@@ -30,16 +31,46 @@ func randChain(t *testing.T) string {
 	return "TEST-" + n.String()
 }
 
-func TestChain(t *testing.T) {
-	chain := randChain(t)
-
+// Create an array of IPTables with different hasWait/hasCheck to
+// test different behaviours
+func mustTestableIptables() []*IPTables {
 	ipt, err := New()
 	if err != nil {
-		t.Fatalf("New failed: %v", err)
+		panic(fmt.Sprintf("New failed: %v", err))
+	}
+	ipts := []*IPTables{ipt}
+	// ensure we check one variant without built-in locking
+	if ipt.hasWait {
+		iptNoWait := &IPTables{
+			path:    ipt.path,
+			hasWait: false,
+		}
+		ipts = append(ipts, iptNoWait)
+	}
+	// ensure we check one variant without built-in checking
+	if ipt.hasCheck {
+		iptNoCheck := &IPTables{
+			path:     ipt.path,
+			hasCheck: false,
+		}
+		ipts = append(ipts, iptNoCheck)
+	}
+	return ipts
+}
+
+func TestChain(t *testing.T) {
+	for _, ipt := range mustTestableIptables() {
+		runChainTests(t, ipt)
 	}
+}
+
+func runChainTests(t *testing.T, ipt *IPTables) {
+	t.Logf("testing iptables (hasWait=%t, hasCheck=%t)", ipt.hasWait, ipt.hasCheck)
+
+	chain := randChain(t)
 
 	// chain shouldn't exist, this will create new
-	err = ipt.ClearChain("filter", chain)
+	err := ipt.ClearChain("filter", chain)
 	if err != nil {
 		t.Fatalf("ClearChain (of missing) failed: %v", err)
 	}
@@ -67,23 +98,33 @@ func TestChain(t *testing.T) {
 		t.Fatalf("ClearChain (of non-empty) failed: %v", err)
 	}
 
+	// rename the chain
+	newChain := randChain(t)
+	err = ipt.RenameChain("filter", chain, newChain)
+	if err != nil {
+		t.Fatalf("RenameChain failed: %v", err)
+	}
+
 	// chain empty, should be ok
-	err = ipt.DeleteChain("filter", chain)
+	err = ipt.DeleteChain("filter", newChain)
 	if err != nil {
 		t.Fatalf("DeleteChain of empty chain failed: %v", err)
 	}
 }
 
 func TestRules(t *testing.T) {
-	chain := randChain(t)
-
-	ipt, err := New()
-	if err != nil {
-		t.Fatalf("New failed: %v", err)
+	for _, ipt := range mustTestableIptables() {
+		runRulesTests(t, ipt)
 	}
+}
+
+func runRulesTests(t *testing.T, ipt *IPTables) {
+	t.Logf("testing iptables (hasWait=%t, hasCheck=%t)", ipt.hasWait, ipt.hasCheck)
+
+	chain := randChain(t)
 
 	// chain shouldn't exist, this will create new
-	err = ipt.ClearChain("filter", chain)
+	err := ipt.ClearChain("filter", chain)
 	if err != nil {
 		t.Fatalf("ClearChain (of missing) failed: %v", err)
 	}
@@ -133,4 +174,16 @@ func TestRules(t *testing.T) {
 	if !reflect.DeepEqual(rules, expected) {
 		t.Fatalf("List mismatch: \ngot  %#v \nneed %#v", rules, expected)
 	}
+
+	// Clear the chain that was created.
+	err = ipt.ClearChain("filter", chain)
+	if err != nil {
+		t.Fatalf("Failed to clear test chain: %v", err)
+	}
+
+	// Delete the chain that was created
+	err = ipt.DeleteChain("filter", chain)
+	if err != nil {
+		t.Fatalf("Failed to delete test chain: %v", err)
+	}
 }

+ 84 - 0
vendor/github.com/coreos/go-iptables/iptables/lock.go

@@ -0,0 +1,84 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package iptables
+
+import (
+	"os"
+	"sync"
+	"syscall"
+)
+
+const (
+	// In earlier versions of iptables, the xtables lock was implemented
+	// via a Unix socket, but now flock is used via this lockfile:
+	// http://git.netfilter.org/iptables/commit/?id=aa562a660d1555b13cffbac1e744033e91f82707
+	// Note the LSB-conforming "/run" directory does not exist on old
+	// distributions, so assume "/var" is symlinked
+	xtablesLockFilePath = "/var/run/xtables.lock"
+
+	defaultFilePerm = 0600
+)
+
+type Unlocker interface {
+	Unlock() error
+}
+
+type nopUnlocker struct{}
+
+func (_ nopUnlocker) Unlock() error { return nil }
+
+type fileLock struct {
+	// mu is used to protect against concurrent invocations from within this process
+	mu sync.Mutex
+	fd int
+}
+
+// tryLock takes an exclusive lock on the xtables lock file without blocking.
+// This is best-effort only: if the exclusive lock would block (i.e. because
+// another process already holds it), no error is returned. Otherwise, any
+// error encountered during the locking operation is returned.
+// The returned Unlocker should be used to release the lock when the caller is
+// done invoking iptables commands.
+func (l *fileLock) tryLock() (Unlocker, error) {
+	l.mu.Lock()
+	err := syscall.Flock(l.fd, syscall.LOCK_EX|syscall.LOCK_NB)
+	switch err {
+	case syscall.EWOULDBLOCK:
+		l.mu.Unlock()
+		return nopUnlocker{}, nil
+	case nil:
+		return l, nil
+	default:
+		l.mu.Unlock()
+		return nil, err
+	}
+}
+
+// Unlock closes the underlying file, which implicitly unlocks it as well. It
+// also unlocks the associated mutex.
+func (l *fileLock) Unlock() error {
+	defer l.mu.Unlock()
+	return syscall.Close(l.fd)
+}
+
+// newXtablesFileLock opens a new lock on the xtables lockfile without
+// acquiring the lock
+func newXtablesFileLock() (*fileLock, error) {
+	fd, err := syscall.Open(xtablesLockFilePath, os.O_CREATE, defaultFilePerm)
+	if err != nil {
+		return nil, err
+	}
+	return &fileLock{fd: fd}, nil
+}

+ 13 - 8
vendor/github.com/coreos/go-iptables/test

@@ -1,4 +1,4 @@
-#!/bin/bash -e
+#!/usr/bin/env bash
 #
 # Run all go-iptables tests
 #   ./test
@@ -8,6 +8,7 @@
 #   PKG=./unit ./test
 #   PKG=ssh ./test
 #
+set -e
 
 # Invoke ./cover for HTML output
 COVER=${COVER:-"-cover"}
@@ -32,19 +33,23 @@ else
 	FMT="$TEST"
 fi
 
+echo "Checking gofmt..."
+fmtRes=$(gofmt -l $FMT)
+if [ -n "${fmtRes}" ]; then
+	echo -e "gofmt checking failed:\n${fmtRes}"
+	exit 255
+fi
+
 # split TEST into an array and prepend REPO_PATH to each local package
 split=(${TEST// / })
 TEST=${split[@]/#/${REPO_PATH}/}
 
 echo "Running tests..."
 go test -i ${TEST}
-go test ${COVER} $@ ${TEST}
-
-echo "Checking gofmt..."
-fmtRes=$(gofmt -l $FMT)
-if [ -n "${fmtRes}" ]; then
-	echo -e "gofmt checking failed:\n${fmtRes}"
-	exit 255
+if [[ -z "$SUDO_PERMITTED" ]]; then
+    echo "Test aborted for safety reasons. Please set the SUDO_PERMITTED variable."
+    exit 1
 fi
 
+sudo -E bash -c "PATH=\$GOROOT/bin:\$PATH go test ${COVER} $@ ${TEST}"
 echo "Success"