Newer
Older
package net
import (
"fmt"
"math"
"strconv"
"strings"
)
// Prefix represents an IPv4 prefix
type Prefix struct {
func NewPfx(addr IP, pfxlen uint8) Prefix {
addr: addr,
pfxlen: pfxlen,
}
}
// StrToAddr converts an IP address string to it's uint32 representation
func StrToAddr(x string) (uint32, error) {
parts := strings.Split(x, ".")
if len(parts) != 4 {
return 0, fmt.Errorf("Invalid format")
}
ret := uint32(0)
for i := 0; i < 4; i++ {
y, err := strconv.Atoi(parts[i])
if err != nil {
return 0, fmt.Errorf("Unable to convert %q to int: %v", parts[i], err)
}
if y > 255 {
return 0, fmt.Errorf("%d is too big for a uint8", y)
}
ret += uint32(math.Pow(256, float64(3-i))) * uint32(y)
}
return ret, nil
}
// Addr returns the address of the prefix
return pfx.addr
}
// Pfxlen returns the length of the prefix
func (pfx Prefix) Pfxlen() uint8 {
return pfx.pfxlen
}
// String returns a string representation of pfx
func (pfx Prefix) String() string {
return fmt.Sprintf("%s/%d", pfx.addr, pfx.pfxlen)
func (pfx Prefix) Contains(x Prefix) bool {
if pfx.addr.ipVersion == 4 {
return pfx.containsIPv4(x)
}
panic("No IPv6 support yet!")
}
func (pfx Prefix) containsIPv4(x Prefix) bool {
mask := uint32((math.MaxUint32 << (32 - pfx.pfxlen)))
return (pfx.addr.ToUint32() & mask) == (x.addr.ToUint32() & mask)
func (pfx Prefix) Equal(x Prefix) bool {
return pfx == x
func (pfx Prefix) GetSupernet(x Prefix) Prefix {
if pfx.addr.ipVersion == 4 {
return pfx.supernetIPv4(x)
}
return pfx.supernetIPv6(x)
}
func (pfx Prefix) supernetIPv4(x Prefix) Prefix {
a := pfx.addr.ToUint32() >> (32 - maxPfxLen)
b := x.addr.ToUint32() >> (32 - maxPfxLen)
for i := 0; a != b; i++ {
a = a >> 1
b = b >> 1
maxPfxLen--
}
addr: IPv4(a << (32 - maxPfxLen)),
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
func (pfx Prefix) supernetIPv6(x Prefix) Prefix {
maxPfxLen := min(pfx.pfxlen, x.pfxlen)
a := pfx.addr.BitAtPosition(1)
b := x.addr.BitAtPosition(1)
pfxLen := uint8(0)
mask := uint64(0)
for a == b && pfxLen < maxPfxLen {
a = pfx.addr.BitAtPosition(pfxLen + 2)
b = x.addr.BitAtPosition(pfxLen + 2)
pfxLen++
if pfxLen == 64 {
mask = 0
}
m := pfxLen % 64
mask = mask + uint64(1)<<(64-m)
}
if pfxLen == 0 {
return NewPfx(IPv6(0, 0), pfxLen)
}
if pfxLen > 64 {
return NewPfx(IPv6(pfx.addr.higher, pfx.addr.lower&mask), pfxLen)
}
return NewPfx(IPv6(pfx.addr.higher&mask, 0), pfxLen)
}