diff --git a/go/pkg/pass1/cut-netspoc.go b/go/pkg/pass1/cut-netspoc.go index 9040acf6..d259f59f 100644 --- a/go/pkg/pass1/cut-netspoc.go +++ b/go/pkg/pass1/cut-netspoc.go @@ -439,8 +439,8 @@ func (c *spoc) markAndSubstElements( } func (c *spoc) markElements( - toplevel []ast.Toplevel, m map[string]*ast.TopList, isUsed map[string]bool) { - + toplevel []ast.Toplevel, m map[string]*ast.TopList, isUsed map[string]bool, +) { for _, top := range toplevel { if x, ok := top.(*ast.Service); ok { typedName := x.Name @@ -448,15 +448,46 @@ func (c *spoc) markElements( continue } v6 := x.IPV6 - c.markAndSubstElements(&x.User.Elements, "user of "+typedName, v6, m, isUsed) + c.markAndSubstElements( + &x.User.Elements, "user of "+typedName, v6, m, isUsed) for _, r := range x.Rules { - c.markAndSubstElements(&r.Src.Elements, "src of "+typedName, v6, m, isUsed) - c.markAndSubstElements(&r.Dst.Elements, "dst of "+typedName, v6, m, isUsed) + if !hasUserInList(r.Src.Elements) { + c.markAndSubstElements( + &r.Src.Elements, "src of "+typedName, v6, m, isUsed) + } + if !hasUserInList(r.Dst.Elements) { + c.markAndSubstElements( + &r.Dst.Elements, "dst of "+typedName, v6, m, isUsed) + } } } } } +func hasUserInList(l []ast.Element) bool { + for _, el := range l { + if hasUser(el) { + return true + } + } + return false +} + +func hasUser(el ast.Element) bool { + switch x := el.(type) { + case *ast.User: + return true + case ast.AutoElem: + return hasUserInList(x.GetElements()) + case *ast.Intersection: + return hasUserInList(x.Elements) + case *ast.Complement: + return hasUser(x.Element) + default: + return false + } +} + func (c *spoc) collectGroups(toplevel []ast.Toplevel) map[string]*ast.TopList { m := make(map[string]*ast.TopList) for _, top := range toplevel { diff --git a/go/testdata/cut-netspoc/cut-netspoc.t b/go/testdata/cut-netspoc/cut-netspoc.t index ee0ac63c..87fd9689 100644 --- a/go/testdata/cut-netspoc/cut-netspoc.t +++ b/go/testdata/cut-netspoc/cut-netspoc.t @@ -206,6 +206,31 @@ service:test = { } =END= +############################################################ +=TITLE=User in src and dst +=INPUT= +[[topo]] +service:test = { + user = interface:asa1.[all]; + permit src = network:[user]; dst = user; prt = icmp 8; +} +=OUTPUT= +network:n1 = { ip = 10.1.1.0/24; } +network:n2 = { ip = 10.1.2.0/24; } +router:asa1 = { + managed; + model = ASA; + interface:n1 = { ip = 10.1.1.1; hardware = n1; } + interface:n2 = { ip = 10.1.2.1; hardware = n2; } +} +service:test = { + user = interface:asa1.[all]; + permit src = network:[user]; + dst = user; + prt = icmp 8; +} +=END= + ############################################################ =TITLE=Auto interface at unmanaged router =INPUT= @@ -3165,7 +3190,7 @@ service:s1 = { =END= ############################################################ =TITLE=Intersection with user -=INPUT= +=TEMPL=input network:n1 = { ip = 10.1.1.0/24; } network:n2 = { ip = 10.1.2.0/24; } network:n3 = { ip = 10.1.3.0/24; } @@ -3177,17 +3202,19 @@ router:r1 = { interface:n3 = { ip = 10.1.3.1; hardware = n3; } } service:s1 = { - user = network:n1, network:n2 + user = network:n1, + network:n2, ; - permit src = user &! network:n2; + permit src = user + &! network:n2 + ; dst = network:n3; prt = tcp 80; } -=END= -# Valid for netspoc, but not supported by cut-netspoc. -=ERROR= -Error: Unexpected reference to 'user' in intersection of src of service:s1 -Warning: Useless delete of network:n2 in src of service:s1 +=INPUT= +[[input]] +=OUTPUT= +[[input]] =END= ############################################################