"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "go/pkg/pass2/cisco.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.

cisco.go  (Netspoc-6.026):cisco.go  (Netspoc-6.027)
package pass2 package pass2
import ( import (
"bytes"
"fmt" "fmt"
"github.com/hknutzen/Netspoc/go/pkg/jcode" "github.com/hknutzen/Netspoc/go/pkg/jcode"
"net" "inet.af/netaddr"
"os" "os"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
) )
func optimizeRedundantRules(cmp, chg ruleTree) bool { func optimizeRedundantRules(cmp, chg ruleTree) bool {
changed := false changed := false
for deny, chg := range chg { for deny, chg := range chg {
for { for {
skipping to change at line 345 skipping to change at line 344
denyRules.push(rule) denyRules.push(rule)
} else if rule.prt == prtEsp || rule.prt == prtAh || rule.log != "" { } else if rule.prt == prtEsp || rule.prt == prtAh || rule.log != "" {
cryptoRules.push(rule) cryptoRules.push(rule)
} else { } else {
permitRules.push(rule) permitRules.push(rule)
} }
} }
// Sort crypto rules. // Sort crypto rules.
cmpAddr := func(a, b *ipNet) int { cmpAddr := func(a, b *ipNet) int {
if val := bytes.Compare(a.IP, b.IP); val != 0 { if val := a.IP.Compare(b.IP); val != 0 {
return val return val
} }
return bytes.Compare(a.Mask, b.Mask) if a.Bits < b.Bits {
return -1
}
if a.Bits > b.Bits {
return 1
}
return 0
} }
sort.Slice(cryptoRules, func(i, j int) bool { sort.Slice(cryptoRules, func(i, j int) bool {
switch strings.Compare( switch strings.Compare(
cryptoRules[i].prt.protocol, cryptoRules[i].prt.protocol,
cryptoRules[j].prt.protocol) { cryptoRules[j].prt.protocol) {
case -1: case -1:
return true return true
case 1: case 1:
return false return false
} }
skipping to change at line 375 skipping to change at line 380
return cmpAddr(cryptoRules[i].dst, cryptoRules[j].dst) == -1 return cmpAddr(cryptoRules[i].dst, cryptoRules[j].dst) == -1
}) })
return append(denyRules, append(cryptoRules, permitRules...)...) return append(denyRules, append(cryptoRules, permitRules...)...)
} }
func createGroup(elements []*ipNet, aclInfo *aclInfo, routerData *routerData) *o bjGroup { func createGroup(elements []*ipNet, aclInfo *aclInfo, routerData *routerData) *o bjGroup {
name := "g" + strconv.Itoa(routerData.objGroupCounter) name := "g" + strconv.Itoa(routerData.objGroupCounter)
if routerData.ipv6 { if routerData.ipv6 {
name = "v6" + name name = "v6" + name
} }
groupRef := &ipNet{IPNet: nil, name: name} // Use zero value IP to mark group.
// Note that "0.0.0.0" and "::" are not the zero value.
groupRef := &ipNet{name: name}
group := &objGroup{ group := &objGroup{
name: name, name: name,
elements: elements, elements: elements,
ref: groupRef, ref: groupRef,
} }
routerData.objGroupCounter++ routerData.objGroupCounter++
// Store group for later printing of its definition. // Store group for later printing of its definition.
aclInfo.objectGroups = append(aclInfo.objectGroups, group) aclInfo.objectGroups = append(aclInfo.objectGroups, group)
return group return group
skipping to change at line 458 skipping to change at line 465
set = func(r *ciscoRule, e *ipNet) { r.dst = e } set = func(r *ciscoRule, e *ipNet) { r.dst = e }
} else { } else {
get = func(r *ciscoRule) *ipNet { return r.src } get = func(r *ciscoRule) *ipNet { return r.src }
set = func(r *ciscoRule, e *ipNet) { r.src = e } set = func(r *ciscoRule, e *ipNet) { r.src = e }
} }
// Sort by IP address. Adjacent networks will be adjacent elements then. // Sort by IP address. Adjacent networks will be adjacent elements then.
// Precondition is, that list already has been optimized and // Precondition is, that list already has been optimized and
// therefore has no redundant elements. // therefore has no redundant elements.
sort.Slice(rules, func(i, j int) bool { sort.Slice(rules, func(i, j int) bool {
return bytes.Compare(get(rules[i]).IP, get(rules[j]).IP) == -1 return get(rules[i]).IP.Less(get(rules[j]).IP)
}) })
// Find left and rigth part with identical mask and combine them // Find left and rigth part with identical mask and combine them
// into next larger network. // into next larger network.
// Compare up to last but one element. // Compare up to last but one element.
for i := 0; i < len(rules)-1; i++ { for i := 0; i < len(rules)-1; i++ {
element1 := get(rules[i]) element1 := get(rules[i])
element2 := get(rules[i+1]) element2 := get(rules[i+1])
mask := element1.Mask prefix := element1.Bits
if bytes.Compare(mask, element2.Mask) != 0 { if prefix != element2.Bits {
continue continue
} }
prefix, bits := mask.Size()
prefix-- prefix--
upMask := net.CIDRMask(prefix, bits)
ip1 := element1.IP ip1 := element1.IP
ip2 := element2.IP ip2 := element2.IP
if bytes.Compare(ip1.Mask(upMask), ip2.Mask(upMask)) != 0 { up1, _ := ip1.Prefix(prefix)
up2, _ := ip2.Prefix(prefix)
if up1.IP != up2.IP {
continue continue
} }
upElement := getIPObj(ip1, upMask, ipNet2obj) upElement := getIPObj(ip1, prefix, ipNet2obj)
// Substitute left part by combined network. // Substitute left part by combined network.
set(rules[i], upElement) set(rules[i], upElement)
// Mark right part as deleted and remove it at [i+1]. // Mark right part as deleted and remove it at [i+1].
rules[i+1].deleted = true rules[i+1].deleted = true
copy(rules[i+1:], rules[i+2:]) // Shift [:i+2] left one index. copy(rules[i+1:], rules[i+2:]) // Shift [:i+2] left one index.
rules = rules[:len(rules)-1] rules = rules[:len(rules)-1]
if i > 0 { if i > 0 {
up2Mask := net.CIDRMask(prefix-1, bits)
// Check previous network again, if newly created network // Check previous network again, if newly created network
// is right part, i.e. lowest bit of network part is set. // is right part, i.e. lowest bit of network part is set.
if !ip1.Equal(ip1.Mask(up2Mask)) { up3, _ := ip1.Prefix(prefix - 1)
if ip1 != up3.IP {
i-- i--
} }
} }
// Only one element left. // Only one element left.
// Condition of for-loop isn't effective, because of 'i--' below. // Condition of for-loop isn't effective, because of 'i--' below.
if i >= len(rules)-1 { if i >= len(rules)-1 {
break break
} }
skipping to change at line 600 skipping to change at line 606
var smallest *ipNet var smallest *ipNet
for i, rule := range list { for i, rule := range list {
var el *ipNet var el *ipNet
if thisIsDst { if thisIsDst {
el = rule.dst el = rule.dst
} else { } else {
el = rule.src el = rule.src
} }
if smallest == nil { if smallest == nil {
smallest = el smallest = el
} else if bytes.Compare(el.IP, smallest.IP) == -1 { } else if el.IP.Less(smallest.IP) {
smallest = el smallest = el
} }
elements[i] = el elements[i] = el
} }
size := len(elements) size := len(elements)
// Use size and smallest element as keys for efficient lo okup. // Use size and smallest element as keys for efficient lo okup.
// Name of element is used, because elements are regenera ted // Name of element is used, because elements are regenera ted
// between processing of different ACLs. // between processing of different ACLs.
key := groupKey{size, smallest.name} key := groupKey{size, smallest.name}
skipping to change at line 797 skipping to change at line 803
addLocalDenyRules(aclInfo, routerData) addLocalDenyRules(aclInfo, routerData)
} else if !hasFinalPermit { } else if !hasFinalPermit {
addFinalPermitDenyRule(aclInfo, addDeny, addPermit) addFinalPermitDenyRule(aclInfo, addDeny, addPermit)
} }
} }
// Given IP or group object, return its address in Cisco syntax. // Given IP or group object, return its address in Cisco syntax.
func ciscoACLAddr(obj *ipNet, model string) string { func ciscoACLAddr(obj *ipNet, model string) string {
// Object group. // Object group.
if obj.IPNet == nil { if obj.IPPrefix.IsZero() {
var keyword string var keyword string
if model == "NX-OS" { if model == "NX-OS" {
keyword = "addrgroup" keyword = "addrgroup"
} else { } else {
keyword = "object-group" keyword = "object-group"
} }
return keyword + " " + obj.name return keyword + " " + obj.name
} }
prefix, bits := obj.Mask.Size() prefix := obj.Bits
ip := obj.IP
if prefix == 0 { if prefix == 0 {
if model == "ASA" { if model == "ASA" {
if bits == 32 { if ip.Is4() {
return "any4" return "any4"
} }
return "any6" return "any6"
} }
return "any" return "any"
} }
if model == "NX-OS" { if model == "NX-OS" {
return obj.name return obj.name
} }
ip := obj.IP
ipCode := ip.String() ipCode := ip.String()
if prefix == bits { if obj.IPPrefix.IsSingleIP() {
return "host " + ipCode return "host " + ipCode
} }
if bits == 128 { if ip.Is6() {
return obj.name return obj.name
} }
mask := net.IP(obj.Mask)
maskNet, _ := netaddr.IPv4(255, 255, 255, 255).Prefix(prefix)
bytes := maskNet.IP.As4()
// Inverse mask bits. // Inverse mask bits.
// Must not inverse original mask, shared by multiple rules.
if model == "NX-OS" || model == "IOS" { if model == "NX-OS" || model == "IOS" {
copy := make([]byte, len(mask)) for i, byte := range bytes {
for i, byte := range mask { bytes[i] = ^byte
copy[i] = ^byte
} }
mask = copy
} }
maskCode := mask.String() maskCode := netaddr.IPv4(bytes[0], bytes[1], bytes[2], bytes[3]).String()
return ipCode + " " + maskCode return ipCode + " " + maskCode
} }
func printObjectGroups(fd *os.File, aclInfo *aclInfo, model string) { func printObjectGroups(fd *os.File, aclInfo *aclInfo, model string) {
var keyword string var keyword string
if model == "NX-OS" { if model == "NX-OS" {
keyword = "object-group ip address" keyword = "object-group ip address"
} else { } else {
keyword = "object-group network" keyword = "object-group network"
} }
for _, group := range aclInfo.objectGroups { for _, group := range aclInfo.objectGroups {
numbered := 10 numbered := 10
fmt.Fprintln(fd, keyword, group.name) fmt.Fprintln(fd, keyword, group.name)
for _, element := range group.elements { for _, element := range group.elements {
// Reject network with mask = 0 in group. // Reject network with mask = 0 in group.
// This occurs if optimization didn't work correctly. // This occurs if optimization didn't work correctly.
if size, _ := element.Mask.Size(); size == 0 { if element.Bits == 0 {
panic("Unexpected network with mask 0 in object-g roup") panic("Unexpected network with mask 0 in object-g roup")
} }
adr := ciscoACLAddr(element, model) adr := ciscoACLAddr(element, model)
if model == "NX-OS" { if model == "NX-OS" {
fmt.Fprintln(fd, "", numbered, adr) fmt.Fprintln(fd, "", numbered, adr)
numbered += 10 numbered += 10
} else { } else {
fmt.Fprintln(fd, " network-object", adr) fmt.Fprintln(fd, " network-object", adr)
} }
} }
 End of changes. 26 change blocks. 
30 lines changed or deleted 35 lines changed or added

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