From 652f3d61828977454cf82cd883738433e947bbad Mon Sep 17 00:00:00 2001 From: Jana Radhakrishnan Date: Wed, 13 May 2015 03:27:22 +0000 Subject: [PATCH] Update resolvconf and iptables packages from docker Updated resolvconf and iptables packages based on upstream changes which we need for libnetwork rebase. There were docker engine changes based on this so we need this to be integrated now. Signed-off-by: Jana Radhakrishnan --- pkg/iptables/firewalld.go | 18 ++++++-------- pkg/iptables/iptables.go | 6 +++++ pkg/iptables/iptables_test.go | 40 ++++++++++++++++++++++++++++++++ pkg/resolvconf/dns/resolvconf.go | 17 ++++++++++++++ pkg/resolvconf/resolvconf.go | 12 ++-------- 5 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 pkg/resolvconf/dns/resolvconf.go diff --git a/pkg/iptables/firewalld.go b/pkg/iptables/firewalld.go index ee3fac5..f2b57ae 100644 --- a/pkg/iptables/firewalld.go +++ b/pkg/iptables/firewalld.go @@ -38,19 +38,18 @@ var ( ) // FirewalldInit initializes firewalld management code. -func FirewalldInit() { +func FirewalldInit() error { var err error - connection, err = newConnection() - - if err != nil { - logrus.Errorf("Failed to connect to D-Bus system bus: %s", err) + if connection, err = newConnection(); err != nil { + return fmt.Errorf("Failed to connect to D-Bus system bus: %v", err) } if connection != nil { go signalHandler() } firewalldRunning = checkRunning() + return nil } // New() establishes a connection to the system bus. @@ -151,7 +150,6 @@ func checkRunning() bool { logrus.Infof("Firewalld running: %t", err == nil) return err == nil } - logrus.Info("Firewalld not running") return false } @@ -160,10 +158,8 @@ func Passthrough(ipv IPV, args ...string) ([]byte, error) { var output string logrus.Debugf("Firewalld passthrough: %s, %s", ipv, args) - err := connection.sysobj.Call(dbusInterface+".direct.passthrough", 0, ipv, args).Store(&output) - if output != "" { - logrus.Debugf("passthrough output: %s", output) + if err := connection.sysobj.Call(dbusInterface+".direct.passthrough", 0, ipv, args).Store(&output); err != nil { + return nil, err } - - return []byte(output), err + return []byte(output), nil } diff --git a/pkg/iptables/iptables.go b/pkg/iptables/iptables.go index 77e1173..75c539a 100644 --- a/pkg/iptables/iptables.go +++ b/pkg/iptables/iptables.go @@ -8,6 +8,7 @@ import ( "regexp" "strconv" "strings" + "sync" "github.com/Sirupsen/logrus" ) @@ -36,6 +37,8 @@ const ( var ( iptablesPath string supportsXlock = false + // used to lock iptables commands if xtables lock is not supported + bestEffortLock sync.Mutex //ErrIptablesNotFound is returned when the rule is not found. ErrIptablesNotFound = errors.New("Iptables not found") ) @@ -303,6 +306,9 @@ func Raw(args ...string) ([]byte, error) { } if supportsXlock { args = append([]string{"--wait"}, args...) + } else { + bestEffortLock.Lock() + defer bestEffortLock.Unlock() } logrus.Debugf("%s, %v", iptablesPath, args) diff --git a/pkg/iptables/iptables_test.go b/pkg/iptables/iptables_test.go index f5f79c7..594493a 100644 --- a/pkg/iptables/iptables_test.go +++ b/pkg/iptables/iptables_test.go @@ -5,6 +5,7 @@ import ( "os/exec" "strconv" "strings" + "sync" "testing" _ "github.com/docker/libnetwork/netutils" @@ -171,6 +172,45 @@ func TestOutput(t *testing.T) { } } +func TestConcurrencyWithWait(t *testing.T) { + RunConcurrencyTest(t, true) +} + +func TestConcurrencyNoWait(t *testing.T) { + RunConcurrencyTest(t, false) +} + +// Runs 10 concurrent rule additions. This will fail if iptables +// is actually invoked simultaneously without --wait. +// Note that if iptables does not support the xtable lock on this +// system, then allowXlock has no effect -- it will always be off. +func RunConcurrencyTest(t *testing.T, allowXlock bool) { + var wg sync.WaitGroup + + if !allowXlock && supportsXlock { + supportsXlock = false + defer func() { supportsXlock = true }() + } + + ip := net.ParseIP("192.168.1.1") + port := 1234 + dstAddr := "172.17.0.1" + dstPort := 4321 + proto := "tcp" + + for i := 0; i < 10; i++ { + wg.Add(1) + go func() { + defer wg.Done() + err := natChain.Forward(Append, ip, port, proto, dstAddr, dstPort) + if err != nil { + t.Fatal(err) + } + }() + } + wg.Wait() +} + func TestCleanup(t *testing.T) { var err error var rules []byte diff --git a/pkg/resolvconf/dns/resolvconf.go b/pkg/resolvconf/dns/resolvconf.go new file mode 100644 index 0000000..d581a19 --- /dev/null +++ b/pkg/resolvconf/dns/resolvconf.go @@ -0,0 +1,17 @@ +package dns + +import ( + "regexp" +) + +// IPLocalhost is a regex patter for localhost IP address range. +const IPLocalhost = `((127\.([0-9]{1,3}.){2}[0-9]{1,3})|(::1))` + +var localhostIPRegexp = regexp.MustCompile(IPLocalhost) + +// IsLocalhost returns true if ip matches the localhost IP regular expression. +// Used for determining if nameserver settings are being passed which are +// localhost addresses +func IsLocalhost(ip string) bool { + return localhostIPRegexp.MatchString(ip) +} diff --git a/pkg/resolvconf/resolvconf.go b/pkg/resolvconf/resolvconf.go index d491fdd..ae6c4e6 100644 --- a/pkg/resolvconf/resolvconf.go +++ b/pkg/resolvconf/resolvconf.go @@ -10,6 +10,7 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/pkg/ioutils" + "github.com/docker/libnetwork/pkg/resolvconf/dns" ) var ( @@ -24,10 +25,8 @@ var ( // For readability and sufficiency for Docker purposes this seemed more reasonable than a // 1000+ character regexp with exact and complete IPv6 validation ipv6Address = `([0-9A-Fa-f]{0,4}:){2,7}([0-9A-Fa-f]{0,4})` - ipLocalhost = `((127\.([0-9]{1,3}.){2}[0-9]{1,3})|(::1))` - localhostIPRegexp = regexp.MustCompile(ipLocalhost) - localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipLocalhost + `\s*\n*`) + localhostNSRegexp = regexp.MustCompile(`(?m)^nameserver\s+` + dns.IPLocalhost + `\s*\n*`) nsIPv6Regexp = regexp.MustCompile(`(?m)^nameserver\s+` + ipv6Address + `\s*\n*`) nsRegexp = regexp.MustCompile(`^\s*nameserver\s*((` + ipv4Address + `)|(` + ipv6Address + `))\s*$`) searchRegexp = regexp.MustCompile(`^\s*search\s*(([^\s]+\s*)*)$`) @@ -128,13 +127,6 @@ func getLines(input []byte, commentMarker []byte) [][]byte { return output } -// IsLocalhost returns true if ip matches the localhost IP regular expression. -// Used for determining if nameserver settings are being passed which are -// localhost addresses -func IsLocalhost(ip string) bool { - return localhostIPRegexp.MatchString(ip) -} - // GetNameservers returns nameservers (if any) listed in /etc/resolv.conf func GetNameservers(resolvConf []byte) []string { nameservers := []string{}