Skip to content

Commit 80fd145

Browse files
committed
Check if supernet of missing dual stack part is present
This closes #30
1 parent 2236731 commit 80fd145

File tree

2 files changed

+79
-2
lines changed

2 files changed

+79
-2
lines changed

go/pkg/pass1/normalize-services.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package pass1
22

33
import (
44
"net/netip"
5+
"slices"
56
)
67

78
//#############################################################################
@@ -188,19 +189,45 @@ func (c *spoc) checkCombined46(v4, v6 groupObjList, s *service) {
188189
m[ob.String()] = true
189190
}
190191
}
192+
193+
// Check if supernet of dual stack network is used in service
194+
// because the network might be deleted by optimization.
195+
checkSup := func(l, ol groupObjList, nm string) bool {
196+
i := slices.IndexFunc(l, func(o groupObj) bool {
197+
return o.String() == nm
198+
})
199+
ob := l[i]
200+
if net, ok := ob.(*network); ok {
201+
otherPart := net.combined46
202+
up := otherPart.up
203+
for up != nil {
204+
if slices.ContainsFunc(ol, func(o groupObj) bool {
205+
return o == up
206+
}) {
207+
return true
208+
}
209+
up = up.up
210+
}
211+
}
212+
return false
213+
}
214+
191215
for _, ob := range v4 {
192216
if ob.isCombined46() && !isOtherAggInCluster(ob) {
193217
if m[ob.String()] {
194218
delete(m, ob.String())
195-
} else {
219+
} else if !checkSup(v4, v6, ob.String()) {
196220
c.err(
197221
"Must not use only IPv4 part of dual stack object %s in %s",
198222
ob, s)
199223
}
200224
}
201225
}
226+
202227
for nm := range m {
203-
c.err("Must not use only IPv6 part of dual stack object %s in %s", nm, s)
228+
if !checkSup(v6, v4, nm) {
229+
c.err("Must not use only IPv6 part of dual stack object %s in %s", nm, s)
230+
}
204231
}
205232
}
206233

go/testdata/ipv46-combined.t

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,56 @@ service:s1 = {
233233
Error: Must not use only IPv4 part of dual stack object network:n1 in service:s1
234234
=END=
235235

236+
############################################################
237+
=TITLE=Ignore optimized deletion of v4 subnet in rule if supernet is present
238+
=INPUT=
239+
network:sup0 = { ip = 10.1.0.0/16; }
240+
network:sup1 = { ip = 10.1.1.0/24; subnet_of = network:sup0; }
241+
network:n1 = { ip = 10.1.1.0/28; ip6 = 2001:db8:1::/64; subnet_of = network:sup1;}
242+
network:n2 = { ip = 10.2.2.0/24; ip6 = 2001:db8:2::/64; host:h2 = { ip = 10.2.2.2; ip6 = 2001:db8:2::2; }}
243+
244+
router:u1 = {
245+
interface:n1 = { ip = 10.1.1.2; }
246+
interface:sup0;
247+
interface:sup1;
248+
}
249+
250+
router:r1 = {
251+
managed;
252+
model = IOS;
253+
interface:n1 = { ip = 10.1.1.1; ip6 = 2001:db8:1::1; hardware = n1; }
254+
interface:n2 = { ip = 10.2.2.1; ip6 = 2001:db8:2::1; hardware = n2; }
255+
}
256+
service:s1 = {
257+
user = network:[any:[network:sup0]];
258+
permit src = user; dst = host:h2; prt = tcp 80;
259+
}
260+
=WARNING=NONE
261+
262+
############################################################
263+
=TITLE=Ignore optimized deletion of v6 subnet in rule if supernet is present
264+
=INPUT=
265+
network:sup = { ip6 = 2001:db8:1::/60; has_subnets; }
266+
network:n1 = { ip = 10.1.1.0/24; ip6 = 2001:db8:1:1::/64; }
267+
network:n2 = { ip = 10.1.2.0/24; ip6 = 2001:db8:9:2::/64; }
268+
router:u = {
269+
interface:sup;
270+
interface:n1;
271+
}
272+
router:r1 = {
273+
managed;
274+
routing = manual;
275+
model = IOS;
276+
interface:n1 = { ip = 10.1.1.1; ip6 = 2001:db8:1:1::1; hardware = n1; }
277+
interface:n2 = { ip = 10.1.2.1; ip6 = 2001:db8:9:2::1; hardware = n2; }
278+
}
279+
service:s1 = {
280+
user = network:[any:[network:sup]];
281+
permit src = user; dst = network:n2; prt = tcp 80;
282+
}
283+
=WARNING=NONE
284+
285+
236286
############################################################
237287
=TITLE=Must not use only v4 part of dual stack aggregate in zone cluster
238288
=INPUT=

0 commit comments

Comments
 (0)