17
17
package iptables
18
18
19
19
import (
20
+ "fmt"
20
21
"regexp"
21
22
"testing"
22
23
23
24
"github.com/coreos/go-iptables/iptables"
24
25
)
25
26
26
- // forwardExists check that at least 2 rules are present in the CNI-HOSTPORT-DNAT chain
27
+ // ForwardExists check that at least 2 rules are present in the CNI-HOSTPORT-DNAT chain
27
28
// and checks for regex matches in the list of rules
28
- func ForwardExists (t * testing.T , ipt * iptables.IPTables , namespace , containerID string ) bool {
29
- rules , err := ipt .List ("nat" , "CNI-HOSTPORT-DNAT" )
29
+ func ForwardExists (t * testing.T , ipt * iptables.IPTables , chain , containerIP string , port int ) bool {
30
+ rules , err := ipt .List ("nat" , chain )
30
31
if err != nil {
31
32
t .Logf ("error listing rules in chain: %q\n " , err )
33
+ return false
32
34
}
33
35
34
36
if len (rules ) < 1 {
@@ -39,8 +41,9 @@ func ForwardExists(t *testing.T, ipt *iptables.IPTables, namespace, containerID
39
41
// here we check if at least one of the rules in the chain
40
42
// matches the required string to identify that the rule was applied
41
43
found := false
44
+ matchRule := `--dport ` + fmt .Sprintf ("%d" , port ) + ` .+ --to-destination ` + containerIP
42
45
for _ , rule := range rules {
43
- foundInRule , err := regexp .MatchString (namespace + "-" + containerID , rule )
46
+ foundInRule , err := regexp .MatchString (matchRule , rule )
44
47
if err != nil {
45
48
t .Logf ("error in match string: %q\n " , err )
46
49
return false
@@ -51,3 +54,46 @@ func ForwardExists(t *testing.T, ipt *iptables.IPTables, namespace, containerID
51
54
}
52
55
return found
53
56
}
57
+
58
+ // GetRedirectedChain returns the chain where the traffic is being redirected.
59
+ // This is how libcni manage its port maps.
60
+ // Suppose you have the following rule:
61
+ // -A CNI-HOSTPORT-DNAT -p tcp -m comment --comment "dnat name: \"bridge\" id: \"default-YYYYYY\"" -m multiport --dports 9999 -j CNI-DN-XXXXXX
62
+ // So the chain where the traffic is redirected is CNI-DN-XXXXXX
63
+ // Returns an empty string in case nothing was found.
64
+ func GetRedirectedChain (t * testing.T , ipt * iptables.IPTables , chain , namespace , containerID string ) string {
65
+ rules , err := ipt .List ("nat" , chain )
66
+ if err != nil {
67
+ t .Logf ("error listing rules in chain: %q\n " , err )
68
+ return ""
69
+ }
70
+
71
+ if len (rules ) < 1 {
72
+ t .Logf ("not enough rules: %d" , len (rules ))
73
+ return ""
74
+ }
75
+
76
+ var redirectedChain string
77
+ re := regexp .MustCompile (`-j\s+([^ ]+)` )
78
+ for _ , rule := range rules {
79
+ // first we verify the comment section is present: "dnat name: \"bridge\" id: \"default-YYYYYY\""
80
+ matchesContainer , err := regexp .MatchString (namespace + "-" + containerID , rule )
81
+ if err != nil {
82
+ t .Logf ("error in match string: %q\n " , err )
83
+ return ""
84
+ }
85
+ if matchesContainer {
86
+ // then we find the appropriate chain in the rule
87
+ matches := re .FindStringSubmatch (rule )
88
+ fmt .Println (matches )
89
+ if len (matches ) >= 2 {
90
+ redirectedChain = matches [1 ]
91
+ }
92
+ }
93
+ }
94
+ if redirectedChain == "" {
95
+ t .Logf ("no redirectced chain found" )
96
+ return ""
97
+ }
98
+ return redirectedChain
99
+ }
0 commit comments