"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "go/pkg/pass1/nat.go" between
Netspoc-6.026.tar.gz and Netspoc-6.027.tar.gz

About: NetSPoC is a network security policy compiler (using its own description language) to manage all the packet filter devices inside your network topology.

nat.go  (Netspoc-6.026):nat.go  (Netspoc-6.027)
skipping to change at line 125 skipping to change at line 125
} }
// Mark invalid NAT transitions. // Mark invalid NAT transitions.
// A transition from nat:t1 to nat:t2 occurs at an interface I // A transition from nat:t1 to nat:t2 occurs at an interface I
// - if nat:t1 was active previously // - if nat:t1 was active previously
// - and nat:t2 is activated at I with "bind_nat = t2". // - and nat:t2 is activated at I with "bind_nat = t2".
// This transition is invalid // This transition is invalid
// - if a network:n1 exists having NAT definitions for both t1 and t2 // - if a network:n1 exists having NAT definitions for both t1 and t2
// - and some other network:n2 exists having a NAT definition for t1, // - and some other network:n2 exists having a NAT definition for t1,
// but not for t2. // but not for t2.
func markInvalidNatTransitions(multi map[string][]natMap) map[string]natMap { func markInvalidNatTransitions(multi map[string][]natTagMap) map[string]natTagMa
result := make(map[string]natMap) p {
result := make(map[string]natTagMap)
for _, list := range multi { for _, list := range multi {
if len(list) == 1 { if len(list) == 1 {
continue continue
} }
union := make(map[string]bool) union := make(map[string]bool)
for _, multiNatMap := range list { for _, multiNatMap := range list {
for tag, _ := range multiNatMap { for tag, _ := range multiNatMap {
union[tag] = true union[tag] = true
} }
} }
skipping to change at line 152 skipping to change at line 152
var missing stringList var missing stringList
for tag, _ := range union { for tag, _ := range union {
if multiNatMap[tag] == nil { if multiNatMap[tag] == nil {
missing.push(tag) missing.push(tag)
} }
} }
for tag1, _ := range multiNatMap { for tag1, _ := range multiNatMap {
natNet := multiNatMap[tag1] natNet := multiNatMap[tag1]
m := result[tag1] m := result[tag1]
if m == nil { if m == nil {
m = make(natMap) m = make(natTagMap)
result[tag1] = m result[tag1] = m
} }
for _, tag2 := range missing { for _, tag2 := range missing {
m[tag2] = natNet m[tag2] = natNet
} }
} }
} }
} }
return result return result
} }
skipping to change at line 177 skipping to change at line 177
// and arrays of NAT maps containing the key NAT tag as values. // and arrays of NAT maps containing the key NAT tag as values.
// Comments: Also checks consistency of multi NAT tags at one network. If // Comments: Also checks consistency of multi NAT tags at one network. If
// non hidden NAT tags are grouped at one network, the same NAT // non hidden NAT tags are grouped at one network, the same NAT
// tags must be used as group in all other occurrences to avoid // tags must be used as group in all other occurrences to avoid
// ambiguities: Suppose tags A and B are both defined at network n1, // ambiguities: Suppose tags A and B are both defined at network n1,
// but only A is defined at network n2. An occurence of // but only A is defined at network n2. An occurence of
// bind_nat = A activates NAT:A. A successive bind_nat = B activates // bind_nat = A activates NAT:A. A successive bind_nat = B activates
// NAT:B, but implicitly disables NAT:A, as for n1 only one NAT can be // NAT:B, but implicitly disables NAT:A, as for n1 only one NAT can be
// active at a time. As NAT:A can not be active (n2) and inactive // active at a time. As NAT:A can not be active (n2) and inactive
// (n1) in the same NAT domain, this restriction is needed. // (n1) in the same NAT domain, this restriction is needed.
func (c *spoc) generateMultinatDefLookup(natType map[string]string) map[string][ func (c *spoc) generateMultinatDefLookup(natType map[string]string) map[string][
]natMap { ]natTagMap {
multi := make(map[string][]natMap) multi := make(map[string][]natTagMap)
// Check if two natMaps contain the same keys. Values can be different. // Check if two natTagMaps contain the same keys. Values can be different
keysEq := func(m1, m2 natMap) bool { .
keysEq := func(m1, m2 natTagMap) bool {
if len(m1) != len(m2) { if len(m1) != len(m2) {
return false return false
} }
for tag, _ := range m1 { for tag, _ := range m1 {
if m2[tag] == nil { if m2[tag] == nil {
return false return false
} }
} }
return true return true
} }
skipping to change at line 225 skipping to change at line 225
// Check for subset relation. Keep supers et only. // Check for subset relation. Keep supers et only.
for i, map2 := range list { for i, map2 := range list {
var common stringList var common stringList
for tag, _ := range map1 { for tag, _ := range map1 {
if map2[tag] != nil { if map2[tag] != nil {
common.push(tag) common.push(tag)
} }
} }
if len(common) == len(map1) { if len(common) == len(map1) {
// Ignore new natMap, bec ause it is subset. // Ignore new natTagMap, because it is subset.
continue NAT_TAG continue NAT_TAG
} else if len(common) == len(map2 ) { } else if len(common) == len(map2 ) {
// Replace previous natMa p by new superset. // Replace previous natTa gMap by new superset.
list[i] = map1 list[i] = map1
continue NAT_TAG continue NAT_TAG
} }
} }
} }
} }
multi[tag] = append(multi[tag], map1) multi[tag] = append(multi[tag], map1)
} }
} }
skipping to change at line 372 skipping to change at line 372
r, names1, names2) r, names1, names2)
continue continue
} }
// Mark router as domain limiting, // Mark router as domain limiting,
// 1. add router as domain border, // 1. add router as domain border,
// 2. initialized NAT set for model.aclUseRealIP // 2. initialized NAT set for model.aclUseRealIP
if r.natTags == nil { if r.natTags == nil {
r.natTags = make(map[*natDomain]stringLis t) r.natTags = make(map[*natDomain]stringLis t)
if r.model != nil && r.model.aclUseRealIP { if r.model != nil && r.model.aclUseRealIP {
natSet := make(map[string]bool) natSet := make(natSet)
r.natSet = &natSet r.natSet = natSet
} }
} }
r.natTags[d] = natTags r.natTags[d] = natTags
d.routers = append(d.routers, r) d.routers = append(d.routers, r)
//debug("ADD to %s: %s", r, d.name) //debug("ADD to %s: %s", r, d.name)
r.natDomains = append(r.natDomains, d) r.natDomains = append(r.natDomains, d)
} }
// Routers with same NAT tag at every interface may occur with VPN. // Routers with same NAT tag at every interface may occur with VPN.
onlyVPN := true onlyVPN := true
skipping to change at line 410 skipping to change at line 410
} }
} }
} }
var result []*natDomain var result []*natDomain
for _, z := range c.allZones { for _, z := range c.allZones {
if z.natDomain != nil { if z.natDomain != nil {
continue continue
} }
name := "nat_domain:" + strings.SplitN(z.name, ":", 2)[1] name := "nat_domain:" + strings.SplitN(z.name, ":", 2)[1]
natSet := make(map[string]bool) natSet := make(natSet)
d := &natDomain{ d := &natDomain{
name: name, name: name,
natSet: &natSet, natSet: natSet,
} }
result = append(result, d) result = append(result, d)
setNatDomain(z, d, nil) setNatDomain(z, d, nil)
} }
if len(natErrSeen) > 0 { if len(natErrSeen) > 0 {
return nil return nil
} }
return result return result
} }
//############################################################################# //#############################################################################
// Purpose : Show interfaces, where bind_nat for NAT tag is missing. // Purpose : Show interfaces, where bind_nat for NAT tag is missing.
func (c *spoc) errMissingBindNat( func (c *spoc) errMissingBindNat(
inRouter *router, d *natDomain, tag string, multinatMaps []natMap) { inRouter *router, d *natDomain, tag string, multinatMaps []natTagMap) {
// Collect interfaces where bind_nat for natTag is applied correctly. // Collect interfaces where bind_nat for natTag is applied correctly.
// First, add interface between inRouter and d. // First, add interface between inRouter and d.
// Other interfaces are added later, during traversal. // Other interfaces are added later, during traversal.
var natIntf intfList var natIntf intfList
for _, intf := range getNatDomainBorders(d) { for _, intf := range getNatDomainBorders(d) {
if intf.router == inRouter { if intf.router == inRouter {
natIntf.push(intf) natIntf.push(intf)
} }
} }
skipping to change at line 662 skipping to change at line 662
//############################################################################# //#############################################################################
// Purpose: Show errors for invalid transitions of grouped NAT tags. // Purpose: Show errors for invalid transitions of grouped NAT tags.
// Parameter: tag: NAT tag that is distributed during domain traversal. // Parameter: tag: NAT tag that is distributed during domain traversal.
// tag2: NAT tag that implicitly deactivates tag. // tag2: NAT tag that implicitly deactivates tag.
// nat: NAT map of network with both tag and tag2 defined. // nat: NAT map of network with both tag and tag2 defined.
// invalid: Map from NAT tags t1, t2 to network, // invalid: Map from NAT tags t1, t2 to network,
// where transition from t1 to t2 is invalid. // where transition from t1 to t2 is invalid.
// r: router where NAT transition occurs at. // r: router where NAT transition occurs at.
func (c *spoc) checkForProperNatTransition( func (c *spoc) checkForProperNatTransition(
tag, tag2 string, nat natMap, invalid map[string]natMap, r *router) { tag, tag2 string, nat natTagMap, invalid map[string]natTagMap, r *router) {
natInfo := nat[tag] natInfo := nat[tag]
nextInfo := nat[tag2] nextInfo := nat[tag2]
// Transition from hidden NAT to any other NAT is invalid. // Transition from hidden NAT to any other NAT is invalid.
// Even hidden to hidden is not allowed, since relaxed multi NAT rules // Even hidden to hidden is not allowed, since relaxed multi NAT rules
// for hidden NAT could lead to inconsistent NAT set. // for hidden NAT could lead to inconsistent NAT set.
if natInfo.hidden { if natInfo.hidden {
// Use nextInfo.name and not natInfo.name because // Use nextInfo.name and not natInfo.name because
skipping to change at line 709 skipping to change at line 709
// tag: NAT tag that is to be distributed. // tag: NAT tag that is to be distributed.
// multinatMaps: List of multi NAT maps containing nat_tag. // multinatMaps: List of multi NAT maps containing nat_tag.
// invalid: Map with pairs of NAT tags as keys, // invalid: Map with pairs of NAT tags as keys,
// where transition from first to second tag is invalid. // where transition from first to second tag is invalid.
// Results: All domains, where NAT tag is active contain 'tag' in their // Results: All domains, where NAT tag is active contain 'tag' in their
// natSet. // natSet.
// Returns: false on success, // Returns: false on success,
// true on error, if same NAT tag is reached twice. // true on error, if same NAT tag is reached twice.
func (c *spoc) distributeNat1( func (c *spoc) distributeNat1(
inRouter *router, d *natDomain, tag string, inRouter *router, d *natDomain, tag string,
multinatMaps []natMap, invalid map[string]natMap) bool { multinatMaps []natTagMap, invalid map[string]natTagMap) bool {
//debug("nat:%s at %s from %s", tag, d.name, inRouter) //debug("nat:%s at %s from %s", tag, d.name, inRouter)
// Loop found or domain was processed by earlier call of distributeNat. // Loop found or domain was processed by earlier call of distributeNat.
natSet := *d.natSet natSet := d.natSet
if natSet[tag] { if natSet[tag] {
return false return false
} }
natSet[tag] = true natSet[tag] = true
// Find adjacent domains with active 'tag' to proceed traversal. // Find adjacent domains with active 'tag' to proceed traversal.
ROUTER: ROUTER:
for _, r := range d.routers { for _, r := range d.routers {
if r == inRouter { if r == inRouter {
continue continue
skipping to change at line 737 skipping to change at line 737
// 'tag' is deactivated at routers domain facing interface. // 'tag' is deactivated at routers domain facing interface.
inNatTags := dom2tags[d] inNatTags := dom2tags[d]
for _, tag2 := range inNatTags { for _, tag2 := range inNatTags {
if tag2 == tag { if tag2 == tag {
continue ROUTER continue ROUTER
} }
} }
if r.model != nil && r.model.aclUseRealIP { if r.model != nil && r.model.aclUseRealIP {
(*r.natSet)[tag] = true r.natSet[tag] = true
} }
// Check whether tag is active in adjacent NAT domains. // Check whether tag is active in adjacent NAT domains.
DOMAIN: DOMAIN:
for _, outDom := range r.natDomains { for _, outDom := range r.natDomains {
if outDom == d { if outDom == d {
continue continue
} }
outNatTags := dom2tags[outDom] outNatTags := dom2tags[outDom]
skipping to change at line 794 skipping to change at line 794
// error message, if called function returns an error value. // error message, if called function returns an error value.
// Parameters: in: router the depth first traversal starts at. // Parameters: in: router the depth first traversal starts at.
// d: Domain the depth first traversal starts at. // d: Domain the depth first traversal starts at.
// tag: NAT tag that is to be distributed. // tag: NAT tag that is to be distributed.
// multinatMaps: List of multi NAT maps containing nat_tag. // multinatMaps: List of multi NAT maps containing nat_tag.
// invalid: Map with pairs of NAT tags as keys, // invalid: Map with pairs of NAT tags as keys,
// where transition from first to second tag is invalid. // where transition from first to second tag is invalid.
// Returns: true if NAT errors have occured. // Returns: true if NAT errors have occured.
func (c *spoc) distributeNat( func (c *spoc) distributeNat(
in *router, d *natDomain, tag string, in *router, d *natDomain, tag string,
multinatMaps []natMap, invalid map[string]natMap) bool { multinatMaps []natTagMap, invalid map[string]natTagMap) bool {
if c.distributeNat1(in, d, tag, multinatMaps, invalid) { if c.distributeNat1(in, d, tag, multinatMaps, invalid) {
c.errMissingBindNat(in, d, tag, multinatMaps) c.errMissingBindNat(in, d, tag, multinatMaps)
return true return true
} }
return false return false
} }
//############################################################################# //#############################################################################
// Purpose: Distribute NAT tags to domains they are active in. // Purpose: Distribute NAT tags to domains they are active in.
// Returns: true if NAT errors have occured. // Returns: true if NAT errors have occured.
func (c *spoc) distributeNatTagsToNatDomains( func (c *spoc) distributeNatTagsToNatDomains(
multi map[string][]natMap, doms []*natDomain) bool { multi map[string][]natTagMap, doms []*natDomain) bool {
invalid := markInvalidNatTransitions(multi) invalid := markInvalidNatTransitions(multi)
var natErrors bool var natErrors bool
for _, d := range doms { for _, d := range doms {
for _, r := range d.routers { for _, r := range d.routers {
natTags := r.natTags[d] natTags := r.natTags[d]
// debug("%s %s: %s", d.name, r, strings.Join(natTags, ", ") // debug("%s %s: %s", d.name, r, strings.Join(natTags, ", ")
for _, tag := range natTags { for _, tag := range natTags {
multinatMaps := multi[tag] multinatMaps := multi[tag]
natErrors = natErrors =
skipping to change at line 829 skipping to change at line 829
} }
} }
} }
return natErrors return natErrors
} }
//############################################################################ //############################################################################
// Purpose: For networks with multiple NAT definitions, at most one NAT // Purpose: For networks with multiple NAT definitions, at most one NAT
// definition must be active in a domain. Show error otherwise. // definition must be active in a domain. Show error otherwise.
func (c *spoc) checkMultinatErrors( func (c *spoc) checkMultinatErrors(
multi map[string][]natMap, doms []*natDomain) { multi map[string][]natTagMap, doms []*natDomain) {
for _, d := range doms { for _, d := range doms {
seen := make(map[string]bool) seen := make(map[string]bool)
natSet := *d.natSet natSet := d.natSet
var errors stringList var errors stringList
for tag, _ := range natSet { for tag, _ := range natSet {
for _, m := range multi[tag] { for _, m := range multi[tag] {
for tag2, natNet := range m { for tag2, natNet := range m {
if tag2 == tag { if tag2 == tag {
continue continue
} }
if !natSet[tag2] { if !natSet[tag2] {
continue continue
} }
skipping to change at line 872 skipping to change at line 872
c.err(m) c.err(m)
} }
} }
} }
//############################################################################ //############################################################################
// Purpose: Network which has translation with tag 'tag' must not be located // Purpose: Network which has translation with tag 'tag' must not be located
// in domain where this tag is active. // in domain where this tag is active.
func (c *spoc) checkNatNetworkLocation(doms []*natDomain) { func (c *spoc) checkNatNetworkLocation(doms []*natDomain) {
for _, d := range doms { for _, d := range doms {
natSet := *d.natSet natSet := d.natSet
for _, z := range d.zones { for _, z := range d.zones {
for _, n := range z.networks { for _, n := range z.networks {
natMap := n.nat natMap := n.nat
var messages stringList var messages stringList
for tag, _ := range natMap { for tag, _ := range natMap {
if natSet[tag] { if natSet[tag] {
var list stringerList var list stringerList
for _, r := range d.routers { for _, r := range d.routers {
list = append(list, r) list = append(list, r)
} }
skipping to change at line 966 skipping to change at line 966
} }
var tags stringList var tags stringList
for tag, _ := range obj.nat { for tag, _ := range obj.nat {
tags.push(tag) tags.push(tag)
} }
sort.Strings(tags) sort.Strings(tags)
for _, tag := range tags { for _, tag := range tags {
objIP := nat[tag] objIP := nat[tag]
natNet := n.nat[tag] natNet := n.nat[tag]
if natNet != nil && natNet.dynamic { if natNet != nil && natNet.dynamic {
if !matchIp(objIP, natNet.ip, natNet.mask ) { if !natNet.ipp.Contains(objIP) {
c.err("nat:%s: IP of %s doesn't m atch IP/mask of %s", c.err("nat:%s: IP of %s doesn't m atch IP/mask of %s",
tag, obj, n) tag, obj, n)
} }
} else { } else {
c.warn( c.warn(
"Ignoring nat:%s at %s because %s has static NAT definition", "Ignoring nat:%s at %s because %s has static NAT definition",
tag, obj, n) tag, obj, n)
} }
} }
} }
skipping to change at line 1003 skipping to change at line 1003
for _, n := range c.allNetworks { for _, n := range c.allNetworks {
for tag, _ := range n.nat { for tag, _ := range n.nat {
info := n.nat[tag] info := n.nat[tag]
if !info.dynamic || info.identity || info.hidden { if !info.dynamic || info.identity || info.hidden {
continue continue
} }
for _, intf := range n.interfaces { for _, intf := range n.interfaces {
intfNat := intf.nat intfNat := intf.nat
// Interface has static translation, // Interface has static translation,
if intfNat[tag] != nil { if _, found := intfNat[tag]; found {
continue continue
} }
r := intf.router r := intf.router
if !r.needProtect { if !r.needProtect {
continue continue
} }
for _, bindIntf := range r.interfaces { for _, bindIntf := range r.interfaces {
for _, tag2 := range bindIntf.bindNat { for _, tag2 := range bindIntf.bindNat {
if tag2 == tag { if tag2 == tag {
skipping to change at line 1027 skipping to change at line 1027
" This is n't supported for model %s.", " This is n't supported for model %s.",
tag, intf, bindIn tf, r.model.name) tag, intf, bindIn tf, r.model.name)
} }
} }
} }
} }
} }
} }
} }
// Convert natSet to natMap for faster access from network to NAT network.
func (c *spoc) convertNatSetToNatMap(doms []*natDomain) {
// Collect domains, where tag T is active.
tag2doms := make(map[string][]*natDomain)
for _, d := range doms {
for tag := range d.natSet {
tag2doms[tag] = append(tag2doms[tag], d)
}
//d.natSet = nil
d.natMap = make(map[*network]*network)
}
// Add network with NAT tag T to natMap of domain, where T is active.
for _, n := range c.allNetworks {
for tag, nat := range n.nat {
for _, d := range tag2doms[tag] {
d.natMap[n] = nat
}
}
}
// Collect routers, where tag T is active.
tag2routers := make(map[string][]*router)
for _, r := range c.managedRouters {
if ns := r.natSet; ns != nil {
for tag := range ns {
tag2routers[tag] = append(tag2routers[tag], r)
}
r.natSet = nil // No longer used.
r.natMap = make(map[*network]*network)
}
}
// Add network with NAT tag T to natMap of router, where T is active.
for _, n := range c.allNetworks {
for tag, nat := range n.nat {
for _, r := range tag2routers[tag] {
r.natMap[n] = nat
}
}
}
}
//############################################################################ //############################################################################
// Result : natSet is stored at logical and hardware interfaces of // Result : natMap is stored at logical and hardware interfaces of
// managed and semi managed routers. // managed and semi managed routers.
// Comment: Neccessary at semi managed routers to calculate .up relation // Comment: Neccessary at semi managed routers to calculate .up relation
// between subnets. // between subnets.
func distributeNatSetsToInterfaces(doms []*natDomain) { func distributeNatMapsToInterfaces(doms []*natDomain) {
for _, d := range doms { for _, d := range doms {
natSet := d.natSet m := d.natMap
for _, z := range d.zones { for _, z := range d.zones {
for _, intf := range z.interfaces { for _, intf := range z.interfaces {
r := intf.router
if r.managed == "" && !r.semiManaged {
continue
}
// debug("%s: NAT %s", d.name, intf) // debug("%s: NAT %s", d.name, intf)
intf.natSet = natSet intf.natMap = m
r := intf.router
if r.managed != "" || r.routingOnly { if r.managed != "" || r.routingOnly {
if r.model.aclUseRealIP { if r.model.aclUseRealIP {
// Set natSet of router inside NA T domain. // Set natSet of router inside NA T domain.
if r.natSet == nil { if r.natMap == nil {
r.natSet = natSet r.natMap = m
} }
} }
if intf.ipType != tunnelIP { if intf.ipType != tunnelIP {
intf.hardware.natSet = natSet intf.hardware.natMap = m
} }
} }
} }
} }
} }
} }
//############################################################################ //############################################################################
// Purpose : Determine NAT domains and generate NAT set // Purpose : Determine NAT domains and generate NAT set
// for every NAT domain. // for every NAT domain.
func (c *spoc) distributeNatInfo() ( func (c *spoc) distributeNatInfo() (
[]*natDomain, map[string]string, map[string][]natMap) { []*natDomain, map[string]string, map[string][]natTagMap) {
c.progress("Distributing NAT") c.progress("Distributing NAT")
natType := c.getLookupMapForNatType() natType := c.getLookupMapForNatType()
c.checkNatDefinitions(natType) c.checkNatDefinitions(natType)
natdomains := c.findNatDomains() natdomains := c.findNatDomains()
multi := c.generateMultinatDefLookup(natType) multi := c.generateMultinatDefLookup(natType)
natErrors := c.distributeNatTagsToNatDomains(multi, natdomains) natErrors := c.distributeNatTagsToNatDomains(multi, natdomains)
c.checkMultinatErrors(multi, natdomains) c.checkMultinatErrors(multi, natdomains)
if !natErrors { if !natErrors {
c.checkNatNetworkLocation(natdomains) c.checkNatNetworkLocation(natdomains)
c.CheckUselessBindNat(natdomains) c.CheckUselessBindNat(natdomains)
} }
c.checkNatCompatibility() c.checkNatCompatibility()
c.checkInterfacesWithDynamicNat() c.checkInterfacesWithDynamicNat()
distributeNatSetsToInterfaces(natdomains) c.convertNatSetToNatMap(natdomains)
distributeNatMapsToInterfaces(natdomains)
return natdomains, natType, multi return natdomains, natType, multi
} }
// Combine different natSets into a single natSet in a way // Combine different natSets into a single natSet in a way
// that NAT mapping remains mostly identical. // that NAT mapping remains mostly identical.
// Single NAT tags remain active if they are active in all sets. // Single NAT tags remain active if they are active in all sets.
// Different real NAT tags of a multi NAT set can't be combined. // Different real NAT tags of a multi NAT set can't be combined.
// In this case NAT is disabled for this multi NAT set. // In this case NAT is disabled for this multi NAT set.
// Hidden NAT tag is ignored if combined with a real NAT tag, // Hidden NAT tag is ignored if combined with a real NAT tag,
// because hidden tag doesn't affect address calculation. // because hidden tag doesn't affect address calculation.
// Multiple hidden tags without real tag are ignored. // Multiple hidden tags without real tag are ignored.
func combineNatSets(sets []natSet, multi map[string][]natMap, natType map[string ]string) natSet { func combineNatSets(sets []natSet, multi map[string][]natTagMap, natType map[str ing]string) natSet {
if len(sets) == 1 { if len(sets) == 1 {
return sets[0] return sets[0]
} }
// Collect single NAT tags and multi NAT maps. // Collect single NAT tags and multi NAT maps.
combined := make(map[string]bool) combined := make(natSet)
var activeMulti []map[string]*network var activeMulti []map[string]*network
seen := make(map[string]bool) seen := make(map[string]bool)
for _, set := range sets { for _, set := range sets {
for tag, _ := range *set { for tag, _ := range set {
if list := multi[tag]; list != nil { if list := multi[tag]; list != nil {
for _, multiNatMap := range list { for _, multiNatMap := range list {
allSeen := true allSeen := true
for tag, _ := range multiNatMap { for tag, _ := range multiNatMap {
if !seen[tag] { if !seen[tag] {
allSeen = false allSeen = false
seen[tag] = true seen[tag] = true
} }
} }
if !allSeen { if !allSeen {
skipping to change at line 1130 skipping to change at line 1168
} }
} }
// Build intersection for NAT tags of all sets. // Build intersection for NAT tags of all sets.
activeMultiSets := make([]map[string]bool, len(activeMulti)) activeMultiSets := make([]map[string]bool, len(activeMulti))
for i, _ := range activeMultiSets { for i, _ := range activeMultiSets {
activeMultiSets[i] = make(map[string]bool) activeMultiSets[i] = make(map[string]bool)
} }
for _, set := range sets { for _, set := range sets {
for tag, _ := range combined { for tag, _ := range combined {
if (*set)[tag] { if set[tag] {
continue continue
} }
if multi[tag] != nil { if multi[tag] != nil {
continue continue
} }
delete(combined, tag) delete(combined, tag)
} }
for i, multiNatMap := range activeMulti { for i, multiNatMap := range activeMulti {
active := "" active := ""
for tag, _ := range multiNatMap { for tag, _ := range multiNatMap {
if (*set)[tag] { if set[tag] {
active = tag active = tag
break break
} }
} }
activeMultiSets[i][active] = true activeMultiSets[i][active] = true
} }
} }
// Process multi NAT tags. // Process multi NAT tags.
// Collect to be added and to be ignored tags. // Collect to be added and to be ignored tags.
skipping to change at line 1195 skipping to change at line 1233
} }
ignore[tag] = true ignore[tag] = true
} }
} }
for tag, _ := range toAdd { for tag, _ := range toAdd {
if ignore[tag] { if ignore[tag] {
continue continue
} }
combined[tag] = true combined[tag] = true
} }
return &combined return combined
} }
 End of changes. 37 change blocks. 
46 lines changed or deleted 86 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)