@@ -78,6 +78,7 @@ func generateIptablesArgs(containerip string, m *PortMapping) ([]string, []strin
78
78
proto string
79
79
from string
80
80
to string
81
+ dport string
81
82
)
82
83
83
84
if strings .EqualFold (m .Protocol , "udp" ) {
@@ -90,16 +91,18 @@ func generateIptablesArgs(containerip string, m *PortMapping) ([]string, []strin
90
91
from = strconv .Itoa (m .FromPorts .Begin )
91
92
m .FromPorts .End = m .FromPorts .Begin
92
93
} else if m .FromPorts .End > m .FromPorts .Begin {
93
- from = fmt .Sprintf ("%d:%d" , m .FromPorts , m .FromPorts .End )
94
+ from = fmt .Sprintf ("%d:%d" , m .FromPorts . Begin , m .FromPorts .End )
94
95
} else {
95
96
return []string {}, []string {}, fmt .Errorf ("invalid from port range %d-%d" , m .FromPorts .Begin , m .FromPorts .End )
96
97
}
97
98
98
99
if m .ToPorts .End == 0 || m .ToPorts .End == m .ToPorts .Begin {
99
- to = net .JoinHostPort (containerip , strconv .Itoa (m .ToPorts .Begin ))
100
+ dport = strconv .Itoa (m .ToPorts .Begin )
101
+ to = net .JoinHostPort (containerip , dport )
100
102
m .ToPorts .End = m .ToPorts .Begin
101
103
} else if m .ToPorts .End > m .ToPorts .Begin {
102
- to = net .JoinHostPort (containerip , fmt .Sprintf ("%d-%d" , m .ToPorts , m .ToPorts .End ))
104
+ dport = fmt .Sprintf ("%d:%d" , m .ToPorts .Begin , m .ToPorts .End )
105
+ to = net .JoinHostPort (containerip , fmt .Sprintf ("%d-%d" , m .ToPorts .Begin , m .ToPorts .End ))
103
106
} else {
104
107
return []string {}, []string {}, fmt .Errorf ("invalid to port range %d-%d" , m .ToPorts .Begin , m .ToPorts .End )
105
108
}
@@ -112,42 +115,74 @@ func generateIptablesArgs(containerip string, m *PortMapping) ([]string, []strin
112
115
}
113
116
114
117
natArgs := []string {"-p" , proto , "-m" , proto , "--dport" , from , "-j" , "DNAT" , "--to-destination" , to }
115
- filterArgs := []string {"-d" , containerip , "-p" , proto , "-m" , proto , "--dport" , to , "-j" , "ACCEPT" }
118
+ filterArgs := []string {"-d" , containerip , "-p" , proto , "-m" , proto , "--dport" , dport , "-j" , "ACCEPT" }
116
119
117
120
return natArgs , filterArgs , nil
118
121
}
119
122
123
+ func parseRawResultOnHyper (output []byte , err error ) error {
124
+ if err != nil {
125
+ return err
126
+ } else if len (output ) != 0 {
127
+ return & iptables.ChainError {Chain : "HYPER" , Output : output }
128
+
129
+ }
130
+ return nil
131
+ }
132
+
120
133
func SetupPortMaps (containerip string , maps []* PortMapping ) error {
121
134
if disableIptables || len (maps ) == 0 {
122
135
return nil
123
136
}
124
137
138
+ var (
139
+ revert bool
140
+ revertRules = [][]string {}
141
+ )
142
+ defer func () {
143
+ if revert {
144
+ hlog .Log (hlog .WARNING , "revert portmapping rules..." )
145
+ for _ , r := range revertRules {
146
+ hlog .Log (hlog .INFO , "revert rule: %v" , r )
147
+ err := parseRawResultOnHyper (iptables .Raw (r ... ))
148
+ if err != nil {
149
+ hlog .Log (hlog .ERROR , "failed to revert rule: %v" , err )
150
+ err = nil //just ignore
151
+ }
152
+ }
153
+ }
154
+ }()
155
+
125
156
for _ , m := range maps {
126
157
127
158
natArgs , filterArgs , err := generateIptablesArgs (containerip , m )
128
159
if err != nil {
160
+ revert = true
129
161
return err
130
162
}
131
163
132
164
//check if this rule has already existed
133
165
if iptables .PortMapExists ("HYPER" , natArgs ) {
134
- return nil
166
+ continue
135
167
}
136
168
137
169
if iptables .PortMapUsed ("HYPER" , m .Protocol , m .FromPorts .Begin , m .FromPorts .End ) {
170
+ revert = true
138
171
return fmt .Errorf ("Host port %v has aleady been used" , m .FromPorts )
139
172
}
140
173
141
- err = iptables . OperatePortMap (iptables .Insert , "HYPER" , natArgs )
174
+ err = parseRawResultOnHyper (iptables .Raw ( append ([] string { "-t" , "nat" , "-I" , " HYPER"} , natArgs ... ) ... ) )
142
175
if err != nil {
143
- return err
176
+ revert = true
177
+ return fmt .Errorf ("Unable to setup NAT rule in HYPER chain: %s" , err )
144
178
}
179
+ revertRules = append (revertRules , append ([]string {"-t" , "nat" , "-D" , "HYPER" }, natArgs ... ))
145
180
146
- if output , err := iptables .Raw (append ([]string {"-I" , "HYPER" }, filterArgs ... )... ); err != nil {
147
- return fmt .Errorf ("Unable to setup forward rule in HYPER chain: %s" , err )
148
- } else if len (output ) != 0 {
149
- return & iptables.ChainError {Chain : "HYPER" , Output : output }
181
+ if err = parseRawResultOnHyper (iptables .Raw (append ([]string {"-I" , "HYPER" }, filterArgs ... )... )); err != nil {
182
+ revert = true
183
+ return fmt .Errorf ("Unable to setup FILTER rule in HYPER chain: %s" , err )
150
184
}
185
+ revertRules = append (revertRules , append ([]string {"-D" , "HYPER" }, filterArgs ... ))
151
186
152
187
i := m .FromPorts .Begin
153
188
j := m .ToPorts .Begin
@@ -163,6 +198,7 @@ func SetupPortMaps(containerip string, maps []*PortMapping) error {
163
198
164
199
for i <= m .FromPorts .End {
165
200
if err = PortMapper .AllocateMap (m .Protocol , i , containerip , j ); err != nil {
201
+ revert = true
166
202
return err
167
203
}
168
204
i ++
@@ -178,6 +214,7 @@ func ReleasePortMaps(containerip string, maps []*PortMapping) error {
178
214
return nil
179
215
}
180
216
217
+ release_loop:
181
218
for _ , m := range maps {
182
219
if ! strings .EqualFold (m .Protocol , "udp" ) {
183
220
m .Protocol = "tcp"
@@ -191,7 +228,7 @@ func ReleasePortMaps(containerip string, maps []*PortMapping) error {
191
228
for i := m .FromPorts .Begin ; i <= m .FromPorts .End ; i ++ {
192
229
err := PortMapper .ReleaseMap (m .Protocol , i )
193
230
if err != nil {
194
- continue
231
+ continue release_loop
195
232
}
196
233
}
197
234
0 commit comments