diff --git a/daemon/networkdriver/bridge/driver.go b/daemon/networkdriver/bridge/driver.go index bea6218708..64772bfd70 100644 --- a/daemon/networkdriver/bridge/driver.go +++ b/daemon/networkdriver/bridge/driver.go @@ -232,7 +232,8 @@ func InitDriver(config *Config) error { logrus.Errorf("Error configuing iptables: %s", err) return err } - + // call this on Firewalld reload + iptables.OnReloaded(func() { setupIPTables(addrv4, config.InterContainerCommunication, config.EnableIpMasq) }) } if config.EnableIpForward { @@ -262,10 +263,16 @@ func InitDriver(config *Config) error { if err != nil { return err } + // call this on Firewalld reload + iptables.OnReloaded(func() { iptables.NewChain("DOCKER", bridgeIface, iptables.Nat) }) + chain, err := iptables.NewChain("DOCKER", bridgeIface, iptables.Filter) if err != nil { return err } + // call this on Firewalld reload + iptables.OnReloaded(func() { iptables.NewChain("DOCKER", bridgeIface, iptables.Filter) }) + portMapper.SetIptablesChain(chain) } @@ -298,6 +305,10 @@ func InitDriver(config *Config) error { // Block BridgeIP in IP allocator ipAllocator.RequestIP(bridgeIPv4Network, bridgeIPv4Network.IP) + if config.EnableIptables { + iptables.OnReloaded(portMapper.ReMapAll) // call this on Firewalld reload + } + return nil } diff --git a/daemon/networkdriver/portmapper/mapper.go b/daemon/networkdriver/portmapper/mapper.go index 8f79bae3f2..09952ba35b 100644 --- a/daemon/networkdriver/portmapper/mapper.go +++ b/daemon/networkdriver/portmapper/mapper.go @@ -132,6 +132,18 @@ func (pm *PortMapper) Map(container net.Addr, hostIP net.IP, hostPort int) (host return m.host, nil } +// re-apply all port mappings +func (pm *PortMapper) ReMapAll() { + logrus.Debugln("Re-applying all port mappings.") + for _, data := range pm.currentMappings { + containerIP, containerPort := getIPAndPort(data.container) + hostIP, hostPort := getIPAndPort(data.host) + if err := pm.forward(iptables.Append, data.proto, hostIP, hostPort, containerIP.String(), containerPort); err != nil { + logrus.Errorf("Error on iptables add: %s", err) + } + } +} + func (pm *PortMapper) Unmap(host net.Addr) error { pm.lock.Lock() defer pm.lock.Unlock() diff --git a/links/links.go b/links/links.go index 1ae8f23aea..8bbacdd3d7 100644 --- a/links/links.go +++ b/links/links.go @@ -7,6 +7,7 @@ import ( "github.com/docker/docker/daemon/networkdriver/bridge" "github.com/docker/docker/nat" + "github.com/docker/docker/pkg/iptables" ) type Link struct { @@ -143,6 +144,8 @@ func (l *Link) Enable() error { if err := l.toggle("-A", false); err != nil { return err } + // call this on Firewalld reload + iptables.OnReloaded(func() { l.toggle("-I", false) }) l.IsEnabled = true return nil } @@ -152,7 +155,8 @@ func (l *Link) Disable() { // exist in iptables // -D == iptables delete flag l.toggle("-D", true) - + // call this on Firewalld reload + iptables.OnReloaded(func() { l.toggle("-D", true) }) l.IsEnabled = false } diff --git a/pkg/iptables/firewalld.go b/pkg/iptables/firewalld.go index cb7e0b4b75..3087794131 100644 --- a/pkg/iptables/firewalld.go +++ b/pkg/iptables/firewalld.go @@ -1,8 +1,10 @@ package iptables import ( + "fmt" "github.com/Sirupsen/logrus" "github.com/godbus/dbus" + "strings" ) type IPV string @@ -26,7 +28,8 @@ type Conn struct { var ( connection *Conn - firewalldRunning bool // is Firewalld service running + firewalldRunning bool // is Firewalld service running + onReloaded []*func() // callbacks when Firewalld has been reloaded ) func FirewalldInit() { @@ -63,9 +66,75 @@ func (c *Conn) initConnection() error { // This never fails, even if the service is not running atm. c.sysobj = c.sysconn.Object(dbusInterface, dbus.ObjectPath(dbusPath)) + rule := fmt.Sprintf("type='signal',path='%s',interface='%s',sender='%s',member='Reloaded'", + dbusPath, dbusInterface, dbusInterface) + c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule) + + rule = fmt.Sprintf("type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged',path='/org/freedesktop/DBus',sender='org.freedesktop.DBus',arg0='%s'", + dbusInterface) + c.sysconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, rule) + + c.signal = make(chan *dbus.Signal, 10) + c.sysconn.Signal(c.signal) + go signalHandler() + return nil } +func signalHandler() { + if connection != nil { + for signal := range connection.signal { + if strings.Contains(signal.Name, "NameOwnerChanged") { + firewalldRunning = checkRunning() + dbusConnectionChanged(signal.Body) + } else if strings.Contains(signal.Name, "Reloaded") { + reloaded() + } + } + } +} + +func dbusConnectionChanged(args []interface{}) { + name := args[0].(string) + old_owner := args[1].(string) + new_owner := args[2].(string) + + if name != dbusInterface { + return + } + + if len(new_owner) > 0 { + connectionEstablished() + } else if len(old_owner) > 0 { + connectionLost() + } +} + +func connectionEstablished() { + reloaded() +} + +func connectionLost() { + // Doesn't do anything for now. Libvirt also doesn't react to this. +} + +// call all callbacks +func reloaded() { + for _, pf := range onReloaded { + (*pf)() + } +} + +// add callback +func OnReloaded(callback func()) { + for _, pf := range onReloaded { + if pf == &callback { + return + } + } + onReloaded = append(onReloaded, &callback) +} + // Call some remote method to see whether the service is actually running. func checkRunning() bool { var zone string