"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "go/pkg/pass1/convert-hosts.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.

convert-hosts.go  (Netspoc-6.026):convert-hosts.go  (Netspoc-6.027)
package pass1 package pass1
import ( import (
"bytes" "inet.af/netaddr"
"encoding/binary"
"fmt"
"net"
"strings" "strings"
) )
//################################################################### //###################################################################
// Convert hosts to subnets. // Convert hosts to subnets.
// Mark subnet relation of subnets. // Mark subnet relation of subnets.
//################################################################### //###################################################################
// Convert an IP range to a set of covering net.IPNet. func ipNATEqual(n1, n2 map[string]netaddr.IP) bool {
func splitIpRange(lo, hi net.IP) ([]net.IPNet, error) {
var l, h uint64
var result []net.IPNet
if len(lo) == 4 && len(hi) == 4 {
l = uint64(binary.BigEndian.Uint32(lo))
h = uint64(binary.BigEndian.Uint32(hi))
} else {
lo, hi = lo.To16(), hi.To16()
if bytes.Compare(lo[:8], hi[:8]) != 0 {
return result, fmt.Errorf(
"IP range doesn't fit into /64 network")
}
l, h = binary.BigEndian.Uint64(lo[8:]), binary.BigEndian.Uint64(h
i[8:])
}
if l > h {
return result, fmt.Errorf("Invalid IP range")
}
add := func(i, m uint64) {
var ip net.IP
var mask net.IPMask
if len(lo) == net.IPv4len {
ip = make(net.IP, net.IPv4len)
binary.BigEndian.PutUint32(ip, uint32(i))
mask = make(net.IPMask, net.IPv4len)
binary.BigEndian.PutUint32(mask, uint32(m))
} else {
ip = make(net.IP, net.IPv6len)
copy(ip, lo)
binary.BigEndian.PutUint64(ip[8:], i)
mask = net.CIDRMask(64, 128)
binary.BigEndian.PutUint64(mask[8:], m)
}
result = append(result, net.IPNet{IP: ip, Mask: mask})
}
IP:
for l <= h {
// 255.255.255.255, 127.255.255.255, ..., 0.0.0.3, 0.0.0.1, 0.0.0
.0
var invMask uint64 = 0xffffffffffffffff
for {
if l&invMask == 0 {
end := l | invMask
if end <= h {
add(l, ^invMask)
l = end + 1
continue IP
}
}
if invMask == 0 {
break
}
invMask >>= 1
}
}
return result, nil
}
func ipNATEqual(n1, n2 map[string]net.IP) bool {
if len(n1) != len(n2) { if len(n1) != len(n2) {
return false return false
} }
for tag, ip1 := range n1 { for tag, ip1 := range n1 {
ip2, ok := n2[tag] ip2, ok := n2[tag]
if !ok { if !ok {
return false return false
} }
if !ip1.Equal(ip2) { if ip1 != ip2 {
return false return false
} }
} }
return true return true
} }
func (c *spoc) checkHostCompatibility(obj, other *netObj) { func (c *spoc) checkHostCompatibility(obj, other *netObj) {
if !ipNATEqual(obj.nat, other.nat) { if !ipNATEqual(obj.nat, other.nat) {
c.err("Inconsistent NAT definition for %s and %s", c.err("Inconsistent NAT definition for %s and %s",
other.name, obj.name) other.name, obj.name)
skipping to change at line 108 skipping to change at line 47
} }
} }
func (c *spoc) convertHosts() { func (c *spoc) convertHosts() {
c.progress("Converting hosts to subnets") c.progress("Converting hosts to subnets")
for _, n := range c.allNetworks { for _, n := range c.allNetworks {
if n.ipType == unnumberedIP || n.ipType == tunnelIP { if n.ipType == unnumberedIP || n.ipType == tunnelIP {
continue continue
} }
ipv6 := n.ipV6 ipv6 := n.ipV6
var bitstrLen int var bitstrLen uint8
if ipv6 { if ipv6 {
bitstrLen = 128 bitstrLen = 128
} else { } else {
bitstrLen = 32 bitstrLen = 32
} }
subnetAref := make([]map[string]*subnet, bitstrLen) subnetAref := make([]map[netaddr.IP]*subnet, bitstrLen)
// Converts hosts and ranges to subnets. // Converts hosts and ranges to subnets.
// Eliminate duplicate subnets. // Eliminate duplicate subnets.
for _, host := range n.hosts { for _, host := range n.hosts {
var nets []net.IPNet var nets []netaddr.IPPrefix
name := host.name name := host.name
id := host.id id := host.id
if ip := host.ip; ip != nil { if !host.ip.IsZero() {
nets = []net.IPNet{{IP: ip, Mask: getHostMask(ipv nets = []netaddr.IPPrefix{{IP: host.ip, Bits: get
6)}} HostPrefix(ipv6)}}
if id != "" { if id != "" {
switch strings.Index(id, "@") { switch strings.Index(id, "@") {
case 0: case 0:
c.err("ID of %s must not start wi th character '@'", name) c.err("ID of %s must not start wi th character '@'", name)
case -1: case -1:
c.err("ID of %s must contain char acter '@'", name) c.err("ID of %s must contain char acter '@'", name)
} }
} }
} else { } else {
// Convert range. // Convert range.
l, err := splitIpRange(host.ipRange[0], host.ipRa l := host.ipRange.Prefixes()
nge[1])
if err != nil {
c.err("%s in %s", err, name)
}
if id != "" { if id != "" {
if len(l) > 1 { if len(l) > 1 {
c.err("Range of %s with ID must e xpand to exactly one subnet", c.err("Range of %s with ID must e xpand to exactly one subnet",
name) name)
} else if isHostMask(l[0].Mask) { } else if l[0].IsSingleIP() {
c.err("%s with ID must not have s ingle IP", name) c.err("%s with ID must not have s ingle IP", name)
} else if strings.Index(id, "@") > 0 { } else if strings.Index(id, "@") > 0 {
c.err("ID of %s must start with c haracter '@'"+ c.err("ID of %s must start with c haracter '@'"+
" or have no '@' at all", name) " or have no '@' at all", name)
} }
} }
nets = l nets = l
} }
for _, net := range nets { for _, ipp := range nets {
size, _ := net.Mask.Size() subnetSize := bitstrLen - ipp.Bits
subnetSize := bitstrLen - size ip2subnet := subnetAref[subnetSize]
str2subnet := subnetAref[subnetSize] if ip2subnet == nil {
if str2subnet == nil { ip2subnet = make(map[netaddr.IP]*subnet)
str2subnet = make(map[string]*subnet) subnetAref[subnetSize] = ip2subnet
subnetAref[subnetSize] = str2subnet
} }
if other := str2subnet[string(net.IP)]; other != nil { if other := ip2subnet[ipp.IP]; other != nil {
c.checkHostCompatibility(&host.netObj, &o ther.netObj) c.checkHostCompatibility(&host.netObj, &o ther.netObj)
host.subnets = append(host.subnets, other ) host.subnets = append(host.subnets, other )
} else { } else {
s := new(subnet) s := new(subnet)
s.name = name s.name = name
s.network = n s.network = n
s.ip = net.IP s.ipp = ipp
s.mask = net.Mask
s.nat = host.nat s.nat = host.nat
s.owner = host.owner s.owner = host.owner
s.id = id s.id = id
s.ldapId = host.ldapId s.ldapId = host.ldapId
s.radiusAttributes = host.radiusAttribute s s.radiusAttributes = host.radiusAttribute s
str2subnet[string(net.IP)] = s ip2subnet[ipp.IP] = s
host.subnets = append(host.subnets, s) host.subnets = append(host.subnets, s)
n.subnets = append(n.subnets, s) n.subnets = append(n.subnets, s)
} }
} }
} }
// Set {up} relation and // Set {up} relation and
// check compatibility of hosts in subnet relation. // check compatibility of hosts in subnet relation.
for i := 0; i < len(subnetAref); i++ { for i := 0; i < len(subnetAref); i++ {
ip2subnet := subnetAref[i] ip2subnet := subnetAref[i]
if ip2subnet == nil { for ip, subnet := range ip2subnet {
continue
}
for ipStr, subnet := range ip2subnet {
ip := net.IP(ipStr)
// Search for enclosing subnet. // Search for enclosing subnet.
for j := i + 1; j < len(subnetAref); j++ { for j := i + 1; j < len(subnetAref); j++ {
mask := net.CIDRMask(bitstrLen-j, bitstrL net, _ := ip.Prefix(bitstrLen - uint8(j))
en) ip = net.IP
ip = ip.Mask(mask) if up := subnetAref[j][ip]; up != nil {
if up := subnetAref[j][string(ip)]; up !=
nil {
subnet.up = up subnet.up = up
c.checkHostCompatibility(&subnet. netObj, &up.netObj) c.checkHostCompatibility(&subnet. netObj, &up.netObj)
break break
} }
} }
// Use network, if no enclosing subnet found. // Use network, if no enclosing subnet found.
if subnet.up == nil { if subnet.up == nil {
subnet.up = n subnet.up = n
} }
} }
} }
// Find adjacent subnets which build a larger subnet. // Find adjacent subnets which build a larger subnet.
s, bits := n.mask.Size() s := n.ipp.Bits
networkSize := bitstrLen - s networkSize := bitstrLen - s
for i := 0; i < len(subnetAref); i++ { for i := 0; i < len(subnetAref); i++ {
ip2subnet := subnetAref[i] ip2subnet := subnetAref[i]
if ip2subnet == nil { if ip2subnet == nil {
continue continue
} }
mask := net.CIDRMask(bitstrLen-i, bits) size := bitstrLen - uint8(i)
// Identify next supernet. // Identify next supernet.
upSubnetSize := i + 1 upSubnetSize := uint8(i + 1)
upMask := net.CIDRMask(bitstrLen-upSubnetSize, bits) upSize := bitstrLen - upSubnetSize
// Network mask and supernet mask differ in one bit.
// This bit distinguishes left and right subnet of supern
et:
// mask (/30) 255.255.255.11111100
// xor upmask (/29) ^255.255.255.11111000
// equals next bit = 0. 0. 0.00000100
// left subnet 10.0.0.16/30 -> 10. 0. 0.00010000
// right subnet 10.0.0.20/30 -> 10. 0. 0.00010100
next := make(net.IP, len(mask))
for i := 0; i < len(mask); i++ {
next[i] = upMask[i] ^ mask[i]
}
for ipStr, s := range ip2subnet { // left subnet 10.0.0.16/30
ip := net.IP(ipStr) // as range: 10.0.0.16-10.0.0.19
// add 1 to get IP of right subnet
// right subnet 10.0.0.20/30
for ip, s := range ip2subnet {
// Don't combine subnets with NAT // Don't combine subnets with NAT
// ToDo: This would be possible if all NAT addres ses // ToDo: This would be possible if all NAT addres ses
// match too. // match too.
if len(s.nat) != 0 { if len(s.nat) != 0 {
continue continue
} }
// Don't combine subnets having radius-ID. // Don't combine subnets having radius-ID.
if s.id != "" { if s.id != "" {
continue continue
} }
// Only take the left part of two adjacent subnet s, // Only take the left part of two adjacent subnet s,
// where lowest network bit is zero. // where lowest network bit is zero.
if !ip.Mask(mask).Equal(ip.Mask(upMask)) { net, _ := ip.Prefix(size)
upNet, _ := ip.Prefix(upSize)
if net.IP != upNet.IP {
continue continue
} }
nextIp := make(net.IP, len(ip)) // Calculate IP of right part.
for i := 0; i < len(ip); i++ { rg := s.ipp.Range()
nextIp[i] = ip[i] | next[i] nextIp := rg.To.Next()
}
// Find corresponding right part // Find corresponding right part
neighbor := ip2subnet[string(nextIp)] neighbor := ip2subnet[nextIp]
if neighbor == nil { if neighbor == nil {
continue continue
} }
s.neighbor = neighbor s.neighbor = neighbor
neighbor.hasNeighbor = true neighbor.hasNeighbor = true
var up someObj var up someObj
if upSubnetSize >= networkSize { if upSubnetSize >= networkSize {
// Larger subnet is whole network. // Larger subnet is whole network.
up = n up = n
} else { } else {
if upSubnetSize < len(subnetAref) { if upSubnetSize < uint8(len(subnetAref))
if upSub, ok := subnetAref[upSubn {
etSize][string(ip)]; ok { if upSub, ok := subnetAref[upSubn
etSize][ip]; ok {
up = upSub up = upSub
} }
} }
if up == nil { if up == nil {
pos := strings.Index(s.name, ":") pos := strings.Index(s.name, ":")
name := "autoSubnet" + s.name[pos :] name := "autoSubnet" + s.name[pos :]
u := new(subnet) u := new(subnet)
u.name = name u.name = name
u.network = n u.network = n
u.ip = ip u.ipp = upNet
u.mask = upMask
u.up = s.up u.up = s.up
upIP2subnet := subnetAref[upSubne tSize] upIP2subnet := subnetAref[upSubne tSize]
if upIP2subnet == nil { if upIP2subnet == nil {
upIP2subnet = make(map[st ring]*subnet) upIP2subnet = make(map[ne taddr.IP]*subnet)
subnetAref[upSubnetSize] = upIP2subnet subnetAref[upSubnetSize] = upIP2subnet
} }
upIP2subnet[string(ip)] = u upIP2subnet[ip] = u
n.subnets = append(n.subnets, u) n.subnets = append(n.subnets, u)
up = u up = u
} }
} }
s.up = up s.up = up
neighbor.up = up neighbor.up = up
} }
} }
// Attribute .up has been set for all subnets now. // Attribute .up has been set for all subnets now.
skipping to change at line 440 skipping to change at line 360
case *host: case *host:
for _, s := range x.subnets { for _, s := range x.subnets {
// Handle special case, w here network and subnet // Handle special case, w here network and subnet
// have identical address . // have identical address .
// E.g. range = 10.1.1.0- 10.1.1.255. // E.g. range = 10.1.1.0- 10.1.1.255.
// Convert subnet to netw ork, because // Convert subnet to netw ork, because
// - different objects wi th identical IP // - different objects wi th identical IP
// can't be checked for redundancy properly. // can't be checked for redundancy properly.
n := s.network n := s.network
if bytes.Compare(s.mask, n.mask) == 0 { if s.ipp.Bits == n.ipp.Bi ts {
if !n.hasIdHosts && !subnetWarningSeen[s] { if !n.hasIdHosts && !subnetWarningSeen[s] {
subnetWar ningSeen[s] = true subnetWar ningSeen[s] = true
c.warn( c.warn(
" Use %s instead of %s\n"+ " Use %s instead of %s\n"+
" because both have identical address", " because both have identical address",
n .name, s.name) n .name, s.name)
} }
result = append(r esult, n) result = append(r esult, n)
} else if h := subnet2hos t[s]; h != nil { } else if h := subnet2hos t[s]; h != nil {
c.warn("%s and %s overlap in %s of %s", c.warn("%s and %s overlap in %s of %s",
 End of changes. 27 change blocks. 
133 lines changed or deleted 48 lines changed or added

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