"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "go/pkg/pass1/routes.go" between
Netspoc-6.025.tar.gz and Netspoc-6.026.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.

routes.go  (Netspoc-6.025):routes.go  (Netspoc-6.026)
package pass1 package pass1
import ( import (
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
) )
func intfListEq(l1, l2 []*routerIntf) bool { //############################################################################
if len(l1) != len(l2) { // Purpose : Generate and store routing information for all managed interfaces.
return false func (c *spoc) findActiveRoutes() {
} c.progress("Finding routes")
for i, e := range l1 {
if e != l2[i] {
return false
}
}
return true
}
func getIpv4Ipv6Routers() []*router {
result := make([]*router, 0, len(symTable.router)+len(symTable.router6))
for _, r := range symTable.router {
result = append(result, r)
}
for _, r := range symTable.router6 {
result = append(result, r)
}
return result
}
// Check, whether input interfaces belong to same redundancy group. // Mark interfaces of unmanaged routers such that no routes are collected
func isRedundanyGroup(intfs []*routerIntf) bool { .
list1 := intfs[0].redundancyIntfs for _, r := range c.allRouters {
if len(list1) == 0 { if r.semiManaged && !r.routingOnly {
return false for _, intf := range r.interfaces {
} intf.routing = routingInfo["dynamic"]
// Check for equality of lists.
for _, intf := range intfs[1:] {
list2 := intf.redundancyIntfs
if len(list2) != len(list1) {
return false
}
for i, obj := range list1 {
if obj != list2[i] {
return false
} }
} }
} }
return true
}
func getMainInterface(intf *routerIntf) *routerIntf { // Generate navigation information for routing inside zones.
if m := intf.mainIntf; m != nil { for _, z := range c.allZones {
return m setRoutesInZone(z)
} }
return intf
}
//####################################################################### // Generate pseudo rule set with all src dst pairs to determine routes fo
// Routing r.
//####################################################################### tree := c.generateRoutingTree()
// Generate routing info for every pseudo rule and store it in interfaces
.
c.generateRoutingInfo(tree)
c.addRoutingOnlyNetworks()
c.checkAndConvertRoutes()
}
type netMap map[*network]bool type netMap map[*network]bool
//############################################################################# //#############################################################################
// Get networks for routing. // Get networks for routing.
// Add largest supernet inside the zone, if available. // Add largest supernet inside the zone, if available.
// This is needed, because we use the supernet in // This is needed, because we use the supernet in
// secondary optimization too. // secondary optimization too.
// Moreover this reduces the number of routing entries. // Moreover this reduces the number of routing entries.
// It isn't sufficient to solely use the supernet because network and supernet // It isn't sufficient to solely use the supernet because network and supernet
skipping to change at line 359 skipping to change at line 333
// Identify hop interface(s). // Identify hop interface(s).
// Store hop interfaces and routing information within inIntf. // Store hop interfaces and routing information within inIntf.
if inNet == outNet { if inNet == outNet {
nMap := rMap[out] nMap := rMap[out]
if nMap == nil { if nMap == nil {
nMap = make(netMap) nMap = make(netMap)
rMap[out] = nMap rMap[out] = nMap
} }
for _, n := range natNets { for _, n := range natNets {
// debug("%s -> %s: %s", inIntf.name, outIntf.name, netwo rk.name) // debug("%s -> %s: %s", in, out, n)
nMap[n] = true nMap[n] = true
} }
} else { } else {
routeInZone := in.routeInZone routeInZone := in.routeInZone
hops := routeInZone[network00] hops := routeInZone[network00]
if hops == nil { if hops == nil {
hops = routeInZone[outNet] hops = routeInZone[outNet]
} }
for _, hop := range hops { for _, hop := range hops {
nMap := rMap[hop] nMap := rMap[hop]
if nMap == nil { if nMap == nil {
nMap = make(netMap) nMap = make(netMap)
rMap[hop] = nMap rMap[hop] = nMap
} }
for _, n := range natNets { for _, n := range natNets {
// debug("%s -> %s: %s", inIntf.name, hop.name, n etwork.name) // debug("%s -> %s: %s", in, hop, n)
nMap[n] = true nMap[n] = true
} }
} }
} }
} }
//############################################################################ //############################################################################
// Purpose : Generate routing information for a single interface at zone // Purpose : Generate routing information for a single interface at zone
// border. Store next hop interface to every destination network // border. Store next hop interface to every destination network
// inside zone within the given interface object. // inside zone within the given interface object.
skipping to change at line 642 skipping to change at line 616
func (c *spoc) generateRoutingInfo(tree routingTree) { func (c *spoc) generateRoutingInfo(tree routingTree) {
// Process every pseudo rule. Within its {path} attribute.... // Process every pseudo rule. Within its {path} attribute....
for _, pRule := range tree { for _, pRule := range tree {
// Collect data for every passed zone. // Collect data for every passed zone.
var path [][2]*routerIntf var path [][2]*routerIntf
var pathEntries []*routerIntf var pathEntries []*routerIntf
var pathExits []*routerIntf var pathExits []*routerIntf
getRoutePath := func(r *groupedRule, in, out *routerIntf) { getRoutePath := func(r *groupedRule, in, out *routerIntf) {
/* debug("collect: %s -> %s", r.srcPath.getName(), r.dstP ath.getName()) /* debug("collect: %s -> %s", r.srcPath, r.dstPath)
info := "" info := ""
if in != nil { if in != nil {
info += in.name info += in.name
} }
info += " -> " info += " -> "
if out != nil { if out != nil {
info += out.name info += out.name
} }
debug(info) debug(info)
*/ */
skipping to change at line 669 skipping to change at line 643
} else { } else {
// Zone contains rule destination. // Zone contains rule destination.
pathExits = append(pathExits, in) pathExits = append(pathExits, in)
} }
} }
c.pathWalk(&pRule.groupedRule, getRoutePath, "Zone") c.pathWalk(&pRule.groupedRule, getRoutePath, "Zone")
// Determine routing information for every interface pair. // Determine routing information for every interface pair.
for _, tuple := range path { for _, tuple := range path {
in, out := tuple[0], tuple[1] in, out := tuple[0], tuple[1]
// debug("%s => %s", inIntf.name, outIntf.name) // debug("%s => %s", in, out)
addPathRoutes(in, out, pRule.dstNetworks) addPathRoutes(in, out, pRule.dstNetworks)
addPathRoutes(out, in, pRule.srcNetworks) addPathRoutes(out, in, pRule.srcNetworks)
} }
// Determine routing information for intf of first zone on path. // Determine routing information for intf of first zone on path.
for _, entry := range pathEntries { for _, entry := range pathEntries {
// For src interfaces at managed routers, generate routes in // For src interfaces at managed routers, generate routes in
// both interfaces. // both interfaces.
SRC: SRC:
skipping to change at line 725 skipping to change at line 699
} }
addPathRoutes(dstIntf, exit, netMap) addPathRoutes(dstIntf, exit, netMap)
} }
// For dst networks, generate routes for zone interface o nly. // For dst networks, generate routes for zone interface o nly.
addEndRoutes(exit, pRule.dstNetworks) addEndRoutes(exit, pRule.dstNetworks)
} }
} }
} }
//############################################################################
// Purpose : Generate and store routing information for all managed interfaces.
func (c *spoc) findActiveRoutes() {
c.progress("Finding routes")
// Mark interfaces of unmanaged routers such that no routes are collected
.
for _, r := range c.allRouters {
if r.semiManaged && !r.routingOnly {
for _, intf := range r.interfaces {
intf.routing = routingInfo["dynamic"]
}
}
}
// Generate navigation information for routing inside zones.
for _, z := range c.allZones {
setRoutesInZone(z)
}
// Generate pseudo rule set with all src dst pairs to determine routes fo
r.
tree := c.generateRoutingTree()
// Generate routing info for every pseudo rule and store it in interfaces
.
c.generateRoutingInfo(tree)
c.addRoutingOnlyNetworks()
c.checkAndConvertRoutes()
}
// Add networks of locally attached zone to routing_only devices. // Add networks of locally attached zone to routing_only devices.
// This is needed because routes between networks inside zone can't be // This is needed because routes between networks inside zone can't be
// derived from packet filter rules. // derived from packet filter rules.
func (c *spoc) addRoutingOnlyNetworks() { func (c *spoc) addRoutingOnlyNetworks() {
for _, r := range c.routingOnlyRouters { for _, r := range c.routingOnlyRouters {
directly := make(netMap) directly := make(netMap)
for _, intf := range r.interfaces { for _, intf := range r.interfaces {
directly[intf.network] = true directly[intf.network] = true
} }
for _, intf := range r.interfaces { for _, intf := range r.interfaces {
if intf.routing != nil { if intf.routing != nil {
continue continue
} }
switch intf.ipType { switch intf.ipType {
case hasIP, unnumberedIP, negotiatedIP: case hasIP, unnumberedIP, negotiatedIP:
//debug("intf %s", intf) // debug("intf %s", intf)
z := intf.zone z := intf.zone
nMap := make(netMap) nMap := make(netMap)
for _, n := range z.networks { for _, n := range z.networks {
if !directly[n] { if !directly[n] {
//debug("add1 %s", n) // debug("add1 %s", n)
nMap[n] = true nMap[n] = true
} }
} }
addEndRoutes(intf, nMap) addEndRoutes(intf, nMap)
// Process other zones of cluster // Process other zones of cluster
for _, z2 := range z.cluster { for _, z2 := range z.cluster {
if z2 == z { if z2 == z {
continue continue
} }
for _, n := range z2.networks { for _, n := range z2.networks {
if !directly[n] { if !directly[n] {
c.singlePathWalk(intf, n, c.singlePathWalk(intf, n,
func(_ *groupedRu le, in, out *routerIntf) { func(_ *groupedRu le, in, out *routerIntf) {
//debug(" walk %s: %s %s", n, in, out) // debug( "walk %s: %s %s", n, in, out)
if in == intf { if in == intf {
/ /debug("add2 %s", n)
a ddPathRoutes(in, out, netMap{n: true}) a ddPathRoutes(in, out, netMap{n: true})
} }
}, "Zone") }, "Zone")
} }
} }
} }
} }
} }
} }
} }
func (c *spoc) checkAndConvertRoutes() {
l := append(c.managedRouters, c.routingOnlyRouters...)
for _, r := range l {
fixBridgedRoutes(r)
}
for _, r := range l {
c.adjustVPNRoutes(r)
c.checkDuplicateRoutes(r)
}
}
// Fix routes where bridged interface without IP address is used as
// next hop.
func fixBridgedRoutes(r *router) {
for _, intf := range r.interfaces {
if intf.routing != nil {
continue
}
if intf.network.ipType != bridgedIP {
continue
}
addRoutes := make(map[*routerIntf][]*network)
for hop, netMap := range intf.routes {
if hop.ipType != bridgedIP {
continue
}
for network, _ := range netMap {
realHops := fixBridgedHops(hop, network)
// Add real hops and networks later, after loop o
ver
// routes has been finished.
for _, rHop := range realHops {
addRoutes[rHop] = append(addRoutes[rHop],
network)
}
}
delete(intf.routes, hop)
}
for rHop, networks := range addRoutes {
nMap := intf.routes[rHop]
if nMap == nil {
nMap = make(netMap)
}
for _, n := range networks {
nMap[n] = true
}
intf.routes[rHop] = nMap
}
}
}
// Parameters: // Parameters:
// - a bridged interface without an IP address, not usable as hop. // - a bridged interface without an IP address, not usable as hop.
// - the network for which the hop was found. // - the network for which the hop was found.
// Result: // Result:
// - one or more layer 3 interfaces, usable as hop. // - one or more layer 3 interfaces, usable as hop.
// Non optimized version. // Non optimized version.
// Doesn't matter as long we have only a few bridged networks // Doesn't matter as long we have only a few bridged networks
// or don't use static routing at the border of bridged networks. // or don't use static routing at the border of bridged networks.
func fixBridgedHops(hop *routerIntf, n *network) intfList { func fixBridgedHops(hop *routerIntf, n *network) intfList {
var result intfList var result intfList
skipping to change at line 834 skipping to change at line 828
result.push(hop2) result.push(hop2)
} }
continue HOP continue HOP
} }
} }
} }
} }
return result return result
} }
func (c *spoc) checkAndConvertRoutes() { // Adjust routes through VPN tunnel to cleartext interface.
func (c *spoc) adjustVPNRoutes(r *router) {
// Fix routes where bridged interface without IP address is used as for _, intf := range r.interfaces {
// next hop. if intf.ipType != tunnelIP {
fixBridged := func(r *router) { continue
for _, intf := range r.interfaces { }
if intf.routing != nil { realIntf := intf.realIntf
continue if realIntf.routing != nil {
} continue
if intf.network.ipType != bridgedIP { }
tunnelRoutes := intf.routes
intf.routes = nil
realNet := realIntf.network
peer := intf.peer
realPeer := peer.realIntf
peerNet := realPeer.network
// Find hop to peer network and add tunneled networks to this hop
.
var hops intfList
// Peer network is directly connected.
if realNet == peerNet {
if realPeer.ipType == hasIP {
hops.push(realPeer)
} else {
c.err("%s used to reach software clients\n"+
" must not be directly connected to %s\n"
+
" Connect it to some network behind next
hop",
realPeer, realIntf)
continue continue
} }
addRoutes := make(map[*routerIntf][]*network) } else if realNet.zone == peerNet.zone {
for hop, netMap := range intf.routes { // Peer network is located in directly connected zone.
if hop.ipType != bridgedIP { routeInZone := realIntf.routeInZone
continue h := routeInZone[network00]
} if h == nil {
for network, _ := range netMap { h = routeInZone[peerNet]
realHops := fixBridgedHops(hop, network)
// Add real hops and networks later, afte
r loop over
// routes has been finished.
for _, rHop := range realHops {
addRoutes[rHop] = append(addRoute
s[rHop], network)
}
}
delete(intf.routes, hop)
} }
for rHop, networks := range addRoutes { hops = append(hops, h...)
nMap := intf.routes[rHop] } else {
if nMap == nil { // Find path to peer network to determine available hops.
nMap = make(netMap) var zoneHops intfList
} walk := func(_ *groupedRule, inIntf, outIntf *routerIntf)
for _, n := range networks { {
nMap[n] = true if inIntf == realIntf {
zoneHops.push(outIntf)
} }
intf.routes[rHop] = nMap
} }
} c.singlePathWalk(realIntf, peerNet, walk, "Zone")
} routeInZone := realIntf.routeInZone
for _, hop := range zoneHops {
checkAndConvert := func(r *router) { hopNet := hop.network
if hopNet == realNet {
// Adjust routes through VPN tunnel to cleartext interface. hops.push(hop)
for _, intf := range r.interfaces {
if intf.ipType != tunnelIP {
continue
}
realIntf := intf.realIntf
if realIntf.routing != nil {
continue
}
tunnelRoutes := intf.routes
intf.routes = nil
realNet := realIntf.network
peer := intf.peer
realPeer := peer.realIntf
peerNet := realPeer.network
// Find hop to peer network and add tunneled networks to
this hop.
var hops intfList
// Peer network is directly connected.
if realNet == peerNet {
if realPeer.ipType == hasIP {
hops.push(realPeer)
} else { } else {
c.err("%s used to reach software clients\ h := routeInZone[network00]
n"+ if h == nil {
" must not be directly connected h = routeInZone[hopNet]
to %s\n"+
" Connect it to some network behi
nd next hop",
realPeer, realIntf)
continue
}
} else if realNet.zone == peerNet.zone {
// Peer network is located in directly connected
zone.
routeInZone := realIntf.routeInZone
h := routeInZone[network00]
if h == nil {
h = routeInZone[peerNet]
}
hops = append(hops, h...)
} else {
// Find path to peer network to determine availab
le hops.
var zoneHops intfList
walk := func(_ *groupedRule, inIntf, outIntf *rou
terIntf) {
if inIntf == realIntf {
zoneHops.push(outIntf)
}
}
c.singlePathWalk(realIntf, peerNet, walk, "Zone")
routeInZone := realIntf.routeInZone
for _, hop := range zoneHops {
hopNet := hop.network
if hopNet == realNet {
hops.push(hop)
} else {
h := routeInZone[network00]
if h == nil {
h = routeInZone[hopNet]
}
hops = append(hops, h...)
} }
hops = append(hops, h...)
} }
} }
}
intfEq := func(list intfList) bool { intfEq := func(list intfList) bool {
i0 := list[0] i0 := list[0]
rest := list[1:] rest := list[1:]
for _, i := range rest { for _, i := range rest {
if i != i0 { if i != i0 {
return false return false
}
} }
return true
} }
redundEq := func(list intfList) bool { return true
r0 := list[0].redundancyIntfs }
if len(r0) == 0 { redundEq := func(list intfList) bool {
r0 := list[0].redundancyIntfs
if len(r0) == 0 {
return false
}
rest := list[1:]
for _, i := range rest {
if !intfListEq(i.redundancyIntfs, r0) {
return false return false
} }
rest := list[1:]
for _, i := range rest {
if !intfListEq(i.redundancyIntfs, r0) {
return false
}
}
return true
}
if !intfEq(hops) && !redundEq(hops) {
// This can only happen for vpn software clients.
// For hardware clients the route is known
// for the encrypted traffic which is allowed
// by genTunnelRules (even for negotiated interfa
ce).
count := len(hops)
c.err("Can't determine next hop to reach %s"+
" while moving routes\n"+
" of %s to %s.\n"+
" Exactly one route is needed,"+
" but %d candidates were found:\n%s",
peerNet, intf, realIntf, count, hops.name
List())
} }
return true
}
if !intfEq(hops) && !redundEq(hops) {
hop := hops[0] // This can only happen for vpn software clients.
routes := realIntf.routes // For hardware clients the route is known
if routes == nil { // for the encrypted traffic which is allowed
routes = make(map[*routerIntf]netMap) // by genTunnelRules (even for negotiated interface).
} count := len(hops)
hopRoutes := routes[hop] c.err("Can't determine next hop to reach %s"+
if hopRoutes == nil { " while moving routes\n"+
hopRoutes = make(netMap) " of %s to %s.\n"+
routes[hop] = hopRoutes " Exactly one route is needed,"+
} " but %d candidates were found:\n%s",
// debug("Use %s as hop for %s", hop.name, real_peer.name peerNet, intf, realIntf, count, hops.nameList())
) }
// Use found hop to reach tunneled networks in tunnel_rou hop := hops[0]
tes. routes := realIntf.routes
for _, tunnelNetHash := range tunnelRoutes { if routes == nil {
for tunnelNet, _ := range tunnelNetHash { routes = make(map[*routerIntf]netMap)
hopRoutes[tunnelNet] = true }
} hopRoutes := routes[hop]
} if hopRoutes == nil {
hopRoutes = make(netMap)
routes[hop] = hopRoutes
}
// debug("Use %s as hop for %s", hop, realPeer)
// Add route to reach peer interface. // Use found hop to reach tunneled networks in tunnel_routes.
if peerNet != realNet { for _, tunnelNetHash := range tunnelRoutes {
natSet := realIntf.natSet for tunnelNet, _ := range tunnelNetHash {
natNet := getNatNetwork(peerNet, natSet) hopRoutes[tunnelNet] = true
hopRoutes[natNet] = true
} }
}
realIntf.routes = routes // Add route to reach peer interface.
if peerNet != realNet {
natSet := realIntf.natSet
natNet := getNatNetwork(peerNet, natSet)
hopRoutes[natNet] = true
} }
// Remember, via which local interface a network is reached. realIntf.routes = routes
net2intf := make(map[*network]*routerIntf) }
}
func (c *spoc) checkDuplicateRoutes(r *router) {
if r.origRouter != nil {
return
}
// Remember, via which local interface a network is reached.
net2intf := make(map[*network]*routerIntf)
for _, intf := range r.interfaces { for _, intf := range getIntf(r) {
// Collect error messages for sorted / deterministic outp // Collect error messages for sorted / deterministic output.
ut. var errors stringList
var errors stringList
// Routing info not needed, because dynamic routing is in // Routing info not needed, because dynamic routing is in use.
use. if intf.routing != nil || intf.ipType == bridgedIP {
if intf.routing != nil || intf.ipType == bridgedIP { intf.routes = nil
intf.routes = nil continue
continue }
}
// Remember, via which remote interface a network is reac // Remember, via which remote interface a network is reached.
hed. net2hop := make(map[*network]*routerIntf)
net2hop := make(map[*network]*routerIntf)
// Remember, via which extra remote redundancy interfaces // Remember, via which extra remote redundancy interfaces network
networks s
// are reached. We use this to check, that all members of // are reached. We use this to check, that all members of a group
a group // of redundancy interfaces are used to reach a network.
// of redundancy interfaces are used to reach a network. // Otherwise it would be wrong to route to virtual interface.
// Otherwise it would be wrong to route to virtual interf var netBehindVirtHop []*network
ace. net2extraHops := make(map[*network]intfList)
var netBehindVirtHop []*network
net2extraHops := make(map[*network]intfList) // Abort, if more than one static route exists per network.
// Sort interfaces for deterministic output.
// Abort, if more than one static route exists per networ sorted := make([]*routerIntf, 0, len(intf.routes))
k. for hop, _ := range intf.routes {
// Sort interfaces for deterministic output. sorted = append(sorted, hop)
sorted := make([]*routerIntf, 0, len(intf.routes)) }
for hop, _ := range intf.routes { sort.Slice(sorted, func(i, j int) bool {
sorted = append(sorted, hop) return sorted[i].name < sorted[j].name
} })
sort.Slice(sorted, func(i, j int) bool { for _, hop := range sorted {
return sorted[i].name < sorted[j].name for n, _ := range intf.routes[hop] {
}) // debug("%s -> %s -> %s", intf, hop, n)
for _, hop := range sorted {
for n, _ := range intf.routes[hop] { // Check if network is reached via two different
// local interfaces.
// Check if network is reached via two di if intf2, ok := net2intf[n]; ok {
fferent if intf2 != intf {
// local interfaces. errors.push(
if intf2, ok := net2intf[n]; ok { fmt.Sprintf(
if intf2 != intf { "Two static route
errors.push( s for %s\n via %s and %s",
fmt.Sprintf( n, intf, intf2))
"Two stat
ic routes for %s\n via %s and %s",
n, intf,
intf2))
}
} else {
net2intf[n] = intf
} }
} else {
net2intf[n] = intf
}
// Check whether network is reached via d // Check whether network is reached via different
ifferent hops. hops.
// Abort, if these do not belong to same // Abort, if these do not belong to same redundan
redundancy group. cy group.
group := hop.redundancyIntfs group := hop.redundancyIntfs
if hop2, ok := net2hop[n]; ok { if hop2, ok := net2hop[n]; ok {
// If next hop belongs to same re // If next hop belongs to same redundancy
dundancy group, group,
// collect hops for detailed chec // collect hops for detailed check below.
k below. group2 := hop2.redundancyIntfs
group2 := hop2.redundancyIntfs if group != nil && intfListEq(group, grou
if group != nil && intfListEq(gro p2) {
up, group2) { delete(intf.routes[hop], n)
delete(intf.routes[hop], net2extraHops[n] =
n) append(net2extraHops[n],
net2extraHops[n] = hop)
append(net2extraH
ops[n], hop)
} else {
errors.push(
fmt.Sprintf(
"Two stat
ic routes for %s\n at %s via %s and %s",
n, intf,
hop, hop2))
}
} else { } else {
net2hop[n] = hop errors.push(
if group != nil { fmt.Sprintf(
netBehindVirtHop = append "Two static route
(netBehindVirtHop, n) s for %s\n at %s via %s and %s",
} n, intf, hop, hop
2))
}
} else {
net2hop[n] = hop
if group != nil {
netBehindVirtHop = append(netBehi
ndVirtHop, n)
} }
} }
} }
}
// Ensure correct routing at virtual interfaces. // Ensure correct routing at virtual interfaces.
// Check whether dst network is reached via all // Check whether dst network is reached via all
// redundancy interfaces. // redundancy interfaces.
for _, n := range netBehindVirtHop { for _, n := range netBehindVirtHop {
hop1 := net2hop[n] hop1 := net2hop[n]
extraHops := net2extraHops[n] extraHops := net2extraHops[n]
missing := len(hop1.redundancyIntfs) - len(extraH missing := len(hop1.redundancyIntfs) - len(extraHops) - 1
ops) - 1 if missing == 0 {
if missing == 0 { continue
continue }
}
// If dst network is reached via exactly one inte // If dst network is reached via exactly one interface,
rface, // move hop from virtual to physical interface.
// move hop from virtual to physical interface. // Destination is probably a loopback interface of same
// Destination is probably a loopback interface o // device.
f same physHop := hop1.origMain
// device. if len(extraHops) == 0 && physHop != nil {
physHop := hop1.origMain delete(intf.routes[hop1], n)
if len(extraHops) == 0 && physHop != nil { if intf.routes[physHop] == nil {
delete(intf.routes[hop1], n) intf.routes[physHop] = make(netMap)
if intf.routes[physHop] == nil {
intf.routes[physHop] = make(netMa
p)
}
intf.routes[physHop][n] = true
continue
} }
intf.routes[physHop][n] = true
// Show error message if dst network is reached b continue
y
// more than one but not by all redundancy interf
aces.
nameList := stringList{hop1.name}
for _, hop := range extraHops {
nameList.push(hop.name)
}
sort.Strings(nameList)
names := strings.Join(nameList, "\n - ")
errors.push(
fmt.Sprintf(
"Pathrestriction ambiguously affe
cts generation"+
" of static routes\n"+
" to interfaces wit
h virtual IP %s:\n"+
" %s is reached via\n"+
" - %s\n"+
" But %d interface(s) of
group are missing.\n"+
" Remaining paths must tr
averse\n"+
" - all interfaces or\n"+
" - exactly one interface
\n"+
" of this group.",
hop1.ip.String(), n.name, names,
missing))
}
// Show error messages of both tests above.
sort.Strings(errors)
for _, e := range errors {
c.err(e)
} }
// Show error message if dst network is reached by
// more than one but not by all redundancy interfaces.
nameList := stringList{hop1.name}
for _, hop := range extraHops {
nameList.push(hop.name)
}
sort.Strings(nameList)
names := strings.Join(nameList, "\n - ")
errors.push(
fmt.Sprintf(
"Pathrestriction ambiguously affects gene
ration"+
" of static routes\n"+
" to interfaces with virtua
l IP %s:\n"+
" %s is reached via\n"+
" - %s\n"+
" But %d interface(s) of group ar
e missing.\n"+
" Remaining paths must traverse\n
"+
" - all interfaces or\n"+
" - exactly one interface\n"+
" of this group.",
hop1.ip.String(), n.name, names, missing)
)
}
// Show error messages of both tests above.
sort.Strings(errors)
for _, e := range errors {
c.err(e)
} }
} }
l := append(c.managedRouters, c.routingOnlyRouters...) }
for _, r := range l {
fixBridged(r) func intfListEq(l1, l2 []*routerIntf) bool {
if len(l1) != len(l2) {
return false
} }
for _, r := range l { for i, e := range l1 {
checkAndConvert(r) if e != l2[i] {
return false
}
}
return true
}
func getIpv4Ipv6Routers() []*router {
result := make([]*router, 0, len(symTable.router)+len(symTable.router6))
for _, r := range symTable.router {
result = append(result, r)
} }
for _, r := range symTable.router6 {
result = append(result, r)
}
return result
}
// Check, whether input interfaces belong to same redundancy group.
func isRedundanyGroup(intfs []*routerIntf) bool {
list1 := intfs[0].redundancyIntfs
if len(list1) == 0 {
return false
}
// Check for equality of lists.
for _, intf := range intfs[1:] {
list2 := intf.redundancyIntfs
if len(list2) != len(list1) {
return false
}
for i, obj := range list1 {
if obj != list2[i] {
return false
}
}
}
return true
}
func getMainInterface(intf *routerIntf) *routerIntf {
if m := intf.mainIntf; m != nil {
return m
}
return intf
} }
 End of changes. 51 change blocks. 
401 lines changed or deleted 378 lines changed or added

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