Skip to content

Commit 39768b5

Browse files
committed
Fixed handling of 'ipv4_only' with 'foreach'
This closes #52
1 parent fb13cc0 commit 39768b5

File tree

2 files changed

+116
-17
lines changed

2 files changed

+116
-17
lines changed

go/pkg/pass1/normalize-services.go

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package pass1
22

33
import (
4+
"fmt"
45
"slices"
56
)
67

@@ -160,6 +161,7 @@ func (c *spoc) splitCombined46(l groupObjList, s *service,
160161
} else if check && obj.isIPv6() != s.ipV6Only {
161162
c.err("Must not use %s %s with 'ipv%s_only' of %s",
162163
ipvx(obj.isIPv6()), obj, cond(s.ipV6Only, "6", "4"), s)
164+
continue
163165
}
164166
if obj.isIPv6() {
165167
v6.push(obj)
@@ -171,9 +173,6 @@ func (c *spoc) splitCombined46(l groupObjList, s *service,
171173
}
172174

173175
func (c *spoc) checkCombined46(v4, v6 groupObjList, s *service) {
174-
if s.ipV4Only || s.ipV6Only {
175-
return
176-
}
177176
isOtherAggInCluster := func(ob groupObj) bool {
178177
if agg, ok := ob.(*network); ok && agg.isAggregate {
179178
if z := agg.zone; z != z.cluster[0] {
@@ -248,14 +247,6 @@ func (c *spoc) normalizeSrcDstList(
248247
c.checkCombined46(dstList4, dstList6, s)
249248
}
250249
} else {
251-
if s.ipV4Only {
252-
c.err("Must not use 'ipv4_only' in %s,"+
253-
" because no combined IPv4/IPv6 objects are in use", s)
254-
}
255-
if s.ipV6Only {
256-
c.err("Must not use 'ipv6_only' in %s,"+
257-
" because no combined IPv4/IPv6 objects are in use", s)
258-
}
259250
if srcList4 != nil && dstList6 != nil {
260251
c.err("Must not use IPv4 %s and IPv6 %s together in %s",
261252
srcList4[0], dstList6[0], s)
@@ -324,7 +315,7 @@ func (c *spoc) normalizeSrcDstList(
324315
func (c *spoc) normalizeServiceRules(s *service, sRules *serviceRules) {
325316
user := c.expandUser(s)
326317
hasRules := false
327-
for _, uRule := range s.rules {
318+
for i, uRule := range s.rules {
328319
deny := uRule.action == "deny"
329320
var store *serviceRuleList
330321
if deny {
@@ -338,8 +329,10 @@ func (c *spoc) normalizeServiceRules(s *service, sRules *serviceRules) {
338329
continue
339330
}
340331
simplePrtList, complexPrtList := classifyProtocols(prtList)
332+
has46 := false
341333
process := func(elt groupObjList) {
342-
srcDstListPairs, has46 := c.normalizeSrcDstList(uRule, elt, s)
334+
srcDstListPairs, is46Rule := c.normalizeSrcDstList(uRule, elt, s)
335+
has46 = has46 || is46Rule
343336
for _, srcDstList := range srcDstListPairs {
344337
srcList, dstList := srcDstList[0], srcDstList[1]
345338
if srcList != nil || dstList != nil {
@@ -404,6 +397,25 @@ func (c *spoc) normalizeServiceRules(s *service, sRules *serviceRules) {
404397
} else {
405398
process(user)
406399
}
400+
if !has46 {
401+
inRule := func() string {
402+
if len(s.rules) > 1 {
403+
return fmt.Sprintf("for rule %d of %s", i+1, s)
404+
} else {
405+
return fmt.Sprintf("in %s", s)
406+
}
407+
}
408+
if s.ipV4Only {
409+
c.warn("Ignoring 'ipv4_only' %s,"+
410+
" because no combined IPv4/IPv6 objects are in use",
411+
inRule())
412+
}
413+
if s.ipV6Only {
414+
c.warn("Ignoring 'ipv6_only' %s,"+
415+
" because no combined IPv4/IPv6 objects are in use",
416+
inRule())
417+
}
418+
}
407419
}
408420
if !hasRules && len(user) == 0 {
409421
c.warn("Must not define %s with empty users and empty rules", s.name)

go/testdata/ipv46-combined.t

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,15 @@ network:n1 = { ip6 = 2001:db8:1:1::/64; }
150150
network:n2 = { ip6 = 2001:db8:1:2::/64; }
151151
network:n3 = { ip = 10.1.3.0/24; }
152152
network:n4 = { ip = 10.1.4.0/24; }
153+
network:n5 = { ip = 10.1.5.0/24; ip6 = 2001:db8:1:5::/64; }
153154
router:r1 = {
154155
managed;
155156
model = ASA;
156157
interface:n1 = { ip6 = 2001:db8:1:1::1; hardware = n1; }
157158
interface:n2 = { ip6 = 2001:db8:1:2::1; hardware = n2; }
158159
interface:n3 = { ip = 10.1.3.1; hardware = n3; }
159160
interface:n4 = { ip = 10.1.4.1; hardware = n4; }
161+
interface:n5 = { ip = 10.1.5.1; ip6 = 2001:db8:1:5::1; hardware = n5; }
160162
}
161163

162164
service:s1 = {
@@ -167,11 +169,12 @@ service:s1 = {
167169
service:s2 = {
168170
ipv4_only;
169171
user = network:n3;
170-
permit src = user; dst = network:n4; prt = tcp 80;
172+
permit src = user; dst = network:n5; prt = tcp 80;
173+
permit src = user; dst = network:n4; prt = tcp 81;
171174
}
172-
=ERROR=
173-
Error: Must not use 'ipv6_only' in service:s1, because no combined IPv4/IPv6 objects are in use
174-
Error: Must not use 'ipv4_only' in service:s2, because no combined IPv4/IPv6 objects are in use
175+
=WARNING=
176+
Warning: Ignoring 'ipv6_only' in service:s1, because no combined IPv4/IPv6 objects are in use
177+
Warning: Ignoring 'ipv4_only' for rule 2 of service:s2, because no combined IPv4/IPv6 objects are in use
175178
=END=
176179

177180
############################################################
@@ -237,6 +240,40 @@ service:s1 = {
237240
Error: Must not use only IPv6 part of dual stack object network:n1 in service:s1
238241
=END=
239242

243+
############################################################
244+
=TITLE=Dual stack aggregates in zone cluster
245+
# Must not show this error message:
246+
# Must not use only IPv4 part of dual stack object any:[network:n1]
247+
=INPUT=
248+
network:n0 = { ip = 10.1.0.0/24; ip6 = 2001:db8:1:0::/64; }
249+
network:n1 = { ip = 10.1.1.0/24; ip6 = 2001:db8:1:1::/64; }
250+
network:n2 = { ip = 10.1.2.0/24; ip6 = 2001:db8:1:2::/64; }
251+
router:u = {
252+
managed = routing_only;
253+
model = IOS;
254+
interface:n0 = { ip = 10.1.0.1; ip6 = 2001:db8:1:0::1; hardware = n0; }
255+
interface:n1 = { ip = 10.1.1.2; ip6 = 2001:db8:1:1::2; hardware = n1; }
256+
}
257+
router:r1 = {
258+
managed;
259+
routing = manual;
260+
model = IOS;
261+
interface:n1 = { ip = 10.1.1.1; ip6 = 2001:db8:1:1::1; hardware = n1; }
262+
interface:n2 = { ip = 10.1.2.1; ip6 = 2001:db8:1:2::1; hardware = n2; }
263+
}
264+
service:s1 = {
265+
user = any:[network:n0];
266+
permit src = network:n2; dst = user; prt = tcp 80;
267+
}
268+
=OUTPUT=
269+
--r1
270+
ip access-list extended n2_in
271+
deny ip any host 10.1.1.1
272+
deny ip any host 10.1.2.1
273+
permit tcp 10.1.2.0 0.0.0.255 any eq 80
274+
deny ip any any
275+
=END=
276+
240277
############################################################
241278
=TITLE=Aggregate from IPv6 network in dual stack zone cluster
242279
=INPUT=
@@ -2259,3 +2296,53 @@ service:s4 = {
22592296
permit src = network:[user]; dst = user; prt = tcp 22;
22602297
}
22612298
=WARNING=NONE
2299+
2300+
############################################################
2301+
=TITLE=V4 only and dual stack objects in service with ipv4_only + foreach
2302+
=INPUT=
2303+
network:n1 = { ip = 10.1.1.0/24; }
2304+
network:n2 = { ip = 10.1.2.0/24; ip6 = 2001:db8:1:2::/64; }
2305+
router:r1 = {
2306+
managed;
2307+
model = IOS;
2308+
interface:n1 = { ip = 10.1.1.1; hardware = n1; }
2309+
interface:n2 = { ip = 10.1.2.1; ip6 = 2001:db8:1:2::1; hardware = n2; }
2310+
}
2311+
service:s1 = {
2312+
ipv4_only;
2313+
user = foreach interface:r1.[all];
2314+
permit src = any:[user]; dst = user; prt = icmp 8;
2315+
}
2316+
=OUTPUT=
2317+
--r1
2318+
! [ ACL ]
2319+
ip access-list extended n1_in
2320+
permit icmp any host 10.1.1.1 8
2321+
deny ip any any
2322+
--
2323+
ip access-list extended n2_in
2324+
permit icmp any host 10.1.2.1 8
2325+
deny ip any any
2326+
--ipv6/r1
2327+
! [ ACL ]
2328+
ipv6 access-list n2_in
2329+
deny ipv6 any any
2330+
=END=
2331+
2332+
############################################################
2333+
=TITLE=Service with ipv4_only + foreach having only v4 objects
2334+
=INPUT=
2335+
network:n1 = { ip = 10.1.1.0/24; }
2336+
router:r1 = {
2337+
managed;
2338+
model = IOS;
2339+
interface:n1 = { ip = 10.1.1.1; hardware = n1; }
2340+
}
2341+
service:s1 = {
2342+
ipv4_only;
2343+
user = foreach interface:r1.[all];
2344+
permit src = any:[user]; dst = user; prt = icmp 8;
2345+
}
2346+
=WARNING=
2347+
Warning: Ignoring 'ipv4_only' in service:s1, because no combined IPv4/IPv6 objects are in use
2348+
=END=

0 commit comments

Comments
 (0)