Newer
Older
"github.com/bio-routing/bio-rd/net/api"
// NewPrefixFromProtoPrefix creates a Prefix from a proto Prefix
func NewPrefixFromProtoPrefix(pfx api.Prefix) Prefix {
return Prefix{
addr: IPFromProtoIP(*pfx.Address),
pfxlen: uint8(pfx.Pfxlen),
}
}
// PrefixFromString converts prefix from string representation to Prefix
func PrefixFromString(s string) (Prefix, error) {
parts := strings.Split(s, "/")
if len(parts) != 2 {
return Prefix{}, fmt.Errorf("Invalid format: %q", s)
}
ip, err := IPFromString(parts[0])
if err != nil {
return Prefix{}, err
}
l, err := strconv.Atoi(parts[1])
if err != nil {
return Prefix{}, errors.Wrap(err, "Unable to convert to int")
}
return Prefix{
addr: ip,
pfxlen: uint8(l),
}, nil
}
func (pfx Prefix) ToProto() *api.Prefix {
return &api.Prefix{
Address: pfx.addr.ToProto(),
Pfxlen: uint32(pfx.pfxlen),
}
}
func NewPfx(addr IP, pfxlen uint8) Prefix {
// NewPfxFromIPNet creates a Prefix object from an gonet.IPNet object
func NewPfxFromIPNet(ipNet *gonet.IPNet) Prefix {
ones, _ := ipNet.Mask.Size()
ip, _ := IPFromBytes(ipNet.IP)
return Prefix{
addr: ip,
pfxlen: uint8(ones),
}
}
// 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, errors.Wrapf(err, "Unable to convert %q to int", parts[i])
}
if y > 255 {
return 0, fmt.Errorf("%d is too big for a uint8", y)
}
}
return ret, nil
}
// Addr returns the address of the prefix
func (pfx Prefix) Addr() IP {
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)
// GetIPNet returns the gonet.IP object for a Prefix object
func (pfx Prefix) GetIPNet() *gonet.IPNet {
var dstNetwork gonet.IPNet
dstNetwork.IP = pfx.Addr().Bytes()
pfxLen := int(pfx.Pfxlen())
if pfx.Addr().IsIPv4() {
func (pfx Prefix) Contains(x Prefix) bool {
return pfx.containsIPv4(x)
}
}
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) containsIPv6(x Prefix) bool {
var maskHigh, maskLow uint64
if pfx.pfxlen <= 64 {
maskHigh = math.MaxUint32 << (64 - pfx.pfxlen)
maskLow = uint64(0)
} else {
maskHigh = math.MaxUint32
maskLow = math.MaxUint32 << (128 - pfx.pfxlen)
}
return pfx.addr.higher&maskHigh&maskHigh == x.addr.higher&maskHigh&maskHigh &&
pfx.addr.lower&maskHigh&maskLow == x.addr.lower&maskHigh&maskLow
}
func (pfx Prefix) Equal(x Prefix) bool {
func (pfx Prefix) GetSupernet(x Prefix) Prefix {
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)),
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
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)
}