Browse code

libnetwork: Controller: combine iptablesEnabled and ip6tablesEnabled

These functions were mostly identical, except for iptables being enabled
by default (unless explicitly disabled by config).

Rewrite the function to a enabledIptablesVersions, which returns the list
of iptables-versions that are enabled for the controller. This prevents
having to acquire a lock twice, and simplifies arrangeUserFilterRule, which
can now just iterate over the enabled versions.

Also moving this function to a linux-only file, as other platforms don't have
the iptables types defined.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2023/07/16 21:16:26
Showing 4 changed files
... ...
@@ -64,7 +64,6 @@ import (
64 64
 	"github.com/docker/docker/libnetwork/drvregistry"
65 65
 	"github.com/docker/docker/libnetwork/ipamapi"
66 66
 	"github.com/docker/docker/libnetwork/netlabel"
67
-	"github.com/docker/docker/libnetwork/options"
68 67
 	"github.com/docker/docker/libnetwork/osl"
69 68
 	"github.com/docker/docker/libnetwork/types"
70 69
 	"github.com/docker/docker/pkg/plugingetter"
... ...
@@ -1135,41 +1134,3 @@ func (c *Controller) IsDiagnosticEnabled() bool {
1135 1135
 	defer c.mu.Unlock()
1136 1136
 	return c.DiagnosticServer.IsDiagnosticEnabled()
1137 1137
 }
1138
-
1139
-func (c *Controller) iptablesEnabled() bool {
1140
-	c.mu.Lock()
1141
-	defer c.mu.Unlock()
1142
-
1143
-	if c.cfg == nil {
1144
-		return false
1145
-	}
1146
-	// parse map cfg["bridge"]["generic"]["EnableIPTable"]
1147
-	cfgBridge := c.cfg.DriverConfig("bridge")
1148
-	cfgGeneric, ok := cfgBridge[netlabel.GenericData].(options.Generic)
1149
-	if !ok {
1150
-		return false
1151
-	}
1152
-	enabled, ok := cfgGeneric["EnableIPTables"].(bool)
1153
-	if !ok {
1154
-		// unless user explicitly stated, assume iptable is enabled
1155
-		enabled = true
1156
-	}
1157
-	return enabled
1158
-}
1159
-
1160
-func (c *Controller) ip6tablesEnabled() bool {
1161
-	c.mu.Lock()
1162
-	defer c.mu.Unlock()
1163
-
1164
-	if c.cfg == nil {
1165
-		return false
1166
-	}
1167
-	// parse map cfg["bridge"]["generic"]["EnableIP6Table"]
1168
-	cfgBridge := c.cfg.DriverConfig("bridge")
1169
-	cfgGeneric, ok := cfgBridge[netlabel.GenericData].(options.Generic)
1170
-	if !ok {
1171
-		return false
1172
-	}
1173
-	enabled, _ := cfgGeneric["EnableIP6Tables"].(bool)
1174
-	return enabled
1175
-}
1176 1138
new file mode 100644
... ...
@@ -0,0 +1,33 @@
0
+package libnetwork
1
+
2
+import (
3
+	"github.com/docker/docker/libnetwork/iptables"
4
+	"github.com/docker/docker/libnetwork/netlabel"
5
+	"github.com/docker/docker/libnetwork/options"
6
+)
7
+
8
+// enabledIptablesVersions returns the iptables versions that are enabled
9
+// for the controller.
10
+func (c *Controller) enabledIptablesVersions() []iptables.IPVersion {
11
+	c.mu.Lock()
12
+	defer c.mu.Unlock()
13
+	if c.cfg == nil {
14
+		return nil
15
+	}
16
+	// parse map cfg["bridge"]["generic"]["EnableIPTable"]
17
+	cfgBridge := c.cfg.DriverConfig("bridge")
18
+	cfgGeneric, ok := cfgBridge[netlabel.GenericData].(options.Generic)
19
+	if !ok {
20
+		return nil
21
+	}
22
+
23
+	var versions []iptables.IPVersion
24
+	if enabled, ok := cfgGeneric["EnableIPTables"].(bool); enabled || !ok {
25
+		// iptables is enabled unless user explicitly disabled it
26
+		versions = append(versions, iptables.IPv4)
27
+	}
28
+	if enabled, _ := cfgGeneric["EnableIP6Tables"].(bool); enabled {
29
+		versions = append(versions, iptables.IPv6)
30
+	}
31
+	return versions
32
+}
0 33
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+//go:build !linux
1
+
2
+package libnetwork
3
+
4
+// enabledIptablesVersions is a no-op on non-Linux systems.
5
+func (c *Controller) enabledIptablesVersions() []any {
6
+	return nil
7
+}
... ...
@@ -16,47 +16,33 @@ func setupArrangeUserFilterRule(c *Controller) {
16 16
 	iptables.OnReloaded(arrangeUserFilterRule)
17 17
 }
18 18
 
19
-// This chain allow users to configure firewall policies in a way that persists
20
-// docker operations/restarts. Docker will not delete or modify any pre-existing
21
-// rules from the DOCKER-USER filter chain.
22
-// Note once DOCKER-USER chain is created, docker engine does not remove it when
23
-// IPTableForwarding is disabled, because it contains rules configured by user that
24
-// are beyond docker engine's control.
19
+// arrangeUserFilterRule sets up the DOCKER-USER chain for each iptables version
20
+// (IPv4, IPv6) that's enabled in the controller's configuration.
21
+//
22
+// This chain allows users to configure firewall policies in a way that
23
+// persist daemon operations/restarts. The daemon does not delete or modify
24
+// any pre-existing rules from the DOCKER-USER filter chain.
25
+//
26
+// Once the DOCKER-USER chain is created, the daemon does not remove it when
27
+// IPTableForwarding is disabled, because it contains rules configured by user
28
+// that are beyond the daemon's control.
25 29
 func arrangeUserFilterRule() {
26 30
 	if ctrl == nil {
27 31
 		return
28 32
 	}
29 33
 
30
-	conds := []struct {
31
-		ipVer iptables.IPVersion
32
-		cond  bool
33
-	}{
34
-		{ipVer: iptables.IPv4, cond: ctrl.iptablesEnabled()},
35
-		{ipVer: iptables.IPv6, cond: ctrl.ip6tablesEnabled()},
36
-	}
37
-
38
-	for _, ipVerCond := range conds {
39
-		cond := ipVerCond.cond
40
-		if !cond {
41
-			continue
42
-		}
43
-
44
-		ipVer := ipVerCond.ipVer
45
-		iptable := iptables.GetIptable(ipVer)
46
-		_, err := iptable.NewChain(userChain, iptables.Filter, false)
47
-		if err != nil {
48
-			log.G(context.TODO()).WithError(err).Warnf("Failed to create %s %v chain", userChain, ipVer)
34
+	for _, ipVersion := range ctrl.enabledIptablesVersions() {
35
+		ipt := iptables.GetIptable(ipVersion)
36
+		if _, err := ipt.NewChain(userChain, iptables.Filter, false); err != nil {
37
+			log.G(context.TODO()).WithError(err).Warnf("Failed to create %s %v chain", userChain, ipVersion)
49 38
 			return
50 39
 		}
51
-
52
-		if err = iptable.AddReturnRule(userChain); err != nil {
53
-			log.G(context.TODO()).WithError(err).Warnf("Failed to add the RETURN rule for %s %v", userChain, ipVer)
40
+		if err := ipt.AddReturnRule(userChain); err != nil {
41
+			log.G(context.TODO()).WithError(err).Warnf("Failed to add the RETURN rule for %s %v", userChain, ipVersion)
54 42
 			return
55 43
 		}
56
-
57
-		err = iptable.EnsureJumpRule("FORWARD", userChain)
58
-		if err != nil {
59
-			log.G(context.TODO()).WithError(err).Warnf("Failed to ensure the jump rule for %s %v", userChain, ipVer)
44
+		if err := ipt.EnsureJumpRule("FORWARD", userChain); err != nil {
45
+			log.G(context.TODO()).WithError(err).Warnf("Failed to ensure the jump rule for %s %v", userChain, ipVersion)
60 46
 		}
61 47
 	}
62 48
 }