mirror of
https://github.com/bgp/stayrtr.git
synced 2024-05-06 15:54:54 +00:00
@ -180,24 +180,29 @@ func decodeJSON(data []byte) (*prefixfile.VRPList, error) {
|
|||||||
return &vrplistjson, err
|
return &vrplistjson, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPrefixLengths(prefix *net.IPNet, maxLength uint8) bool {
|
func isValidPrefixLength(prefix *net.IPNet, maxLength uint8) bool {
|
||||||
plen, max := net.IPMask.Size(prefix.Mask)
|
plen, max := net.IPMask.Size(prefix.Mask)
|
||||||
|
|
||||||
if uint8(plen) > maxLength || maxLength > uint8(max) {
|
if plen == 0 || uint8(plen) > maxLength || maxLength > uint8(max) {
|
||||||
log.Errorf("%s Maxlength wrong: %d - %d", prefix, plen, maxLength)
|
log.Errorf("%s Maxlength wrong: %d - %d", prefix, plen, maxLength)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processData will take a slice of prefix.VRPJson and attempt to convert them to a slice of rtr.VRP.
|
||||||
|
// Will check the following:
|
||||||
|
// 1 - The prefix is a valid prefix
|
||||||
|
// 2 - The ASN is a valid ASN
|
||||||
|
// 3 - The MaxLength is valid
|
||||||
|
// Will return a deduped slice, as well as total VRPs, IPv4 VRPs, and IPv6 VRPs
|
||||||
func processData(vrplistjson []prefixfile.VRPJson) ([]rtr.VRP, int, int, int) {
|
func processData(vrplistjson []prefixfile.VRPJson) ([]rtr.VRP, int, int, int) {
|
||||||
filterDuplicates := make(map[string]bool)
|
filterDuplicates := make(map[string]bool)
|
||||||
|
|
||||||
vrplist := make([]rtr.VRP, 0)
|
var vrplist []rtr.VRP
|
||||||
|
|
||||||
var count int
|
|
||||||
var countv4 int
|
var countv4 int
|
||||||
var countv6 int
|
var countv6 int
|
||||||
|
|
||||||
for _, v := range vrplistjson {
|
for _, v := range vrplistjson {
|
||||||
prefix, err := v.GetPrefix2()
|
prefix, err := v.GetPrefix2()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -210,24 +215,22 @@ func processData(vrplistjson []prefixfile.VRPJson) ([]rtr.VRP, int, int, int) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !checkPrefixLengths(prefix, v.Length) {
|
if !isValidPrefixLength(prefix, v.Length) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if prefix.IP.To4() != nil {
|
if prefix.IP.To4() != nil {
|
||||||
countv4++
|
countv4++
|
||||||
} else if prefix.IP.To16() != nil {
|
} else {
|
||||||
countv6++
|
countv6++
|
||||||
}
|
}
|
||||||
count++
|
|
||||||
|
|
||||||
key := fmt.Sprintf("%s,%d,%d", prefix, asn, v.Length)
|
key := fmt.Sprintf("%s,%d,%d", prefix, asn, v.Length)
|
||||||
_, exists := filterDuplicates[key]
|
_, exists := filterDuplicates[key]
|
||||||
if !exists {
|
if exists {
|
||||||
filterDuplicates[key] = true
|
|
||||||
} else {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
filterDuplicates[key] = true
|
||||||
|
|
||||||
vrp := rtr.VRP{
|
vrp := rtr.VRP{
|
||||||
Prefix: *prefix,
|
Prefix: *prefix,
|
||||||
@ -236,7 +239,7 @@ func processData(vrplistjson []prefixfile.VRPJson) ([]rtr.VRP, int, int, int) {
|
|||||||
}
|
}
|
||||||
vrplist = append(vrplist, vrp)
|
vrplist = append(vrplist, vrp)
|
||||||
}
|
}
|
||||||
return vrplist, count, countv4, countv6
|
return vrplist, countv4 + countv6, countv4, countv6
|
||||||
}
|
}
|
||||||
|
|
||||||
type IdenticalFile struct {
|
type IdenticalFile struct {
|
||||||
@ -272,8 +275,7 @@ func (s *state) updateFromNewState() error {
|
|||||||
|
|
||||||
vrps, count, countv4, countv6 := processData(vrpsjson)
|
vrps, count, countv4, countv6 := processData(vrpsjson)
|
||||||
|
|
||||||
log.Infof("New update (%v uniques, %v total prefixes).",
|
log.Infof("New update (%v uniques, %v total prefixes).", len(vrps), count)
|
||||||
len(vrps), count)
|
|
||||||
|
|
||||||
s.server.AddVRPs(vrps)
|
s.server.AddVRPs(vrps)
|
||||||
|
|
||||||
|
124
cmd/stayrtr/stayrtr_test.go
Normal file
124
cmd/stayrtr/stayrtr_test.go
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
rtr "github.com/bgp/stayrtr/lib"
|
||||||
|
"github.com/bgp/stayrtr/prefixfile"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProcessData(t *testing.T) {
|
||||||
|
var stuff []prefixfile.VRPJson
|
||||||
|
stuff = append(stuff,
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.0.0/24",
|
||||||
|
Length: 24,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.0.0/24",
|
||||||
|
Length: 24,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "2001:db8::/32",
|
||||||
|
Length: 33,
|
||||||
|
ASN: "AS123",
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.1.0/24",
|
||||||
|
Length: 25,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
// Invalid. Length is 0
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.1.0/24",
|
||||||
|
Length: 0,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
// Invalid. Length less than prefix length
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.1.0/24",
|
||||||
|
Length: 16,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
// Invalid. 129 is invalid for IPv6
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "2001:db8::/32",
|
||||||
|
Length: 129,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
// Invalid. 33 is invalid for IPv4
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.1.0/24",
|
||||||
|
Length: 33,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
// Invalid. Not a prefix
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.1.0",
|
||||||
|
Length: 24,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
// Invalid. Not a prefix
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "👻",
|
||||||
|
Length: 24,
|
||||||
|
ASN: 123,
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
// Invalid. Invalid ASN string
|
||||||
|
prefixfile.VRPJson{
|
||||||
|
Prefix: "192.168.1.0/22",
|
||||||
|
Length: 22,
|
||||||
|
ASN: "ASN123",
|
||||||
|
TA: "testrir",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
got, count, v4count, v6count := processData(stuff)
|
||||||
|
want := []rtr.VRP{
|
||||||
|
{
|
||||||
|
Prefix: MustParseIPNet("192.168.0.0/24"),
|
||||||
|
MaxLen: 24,
|
||||||
|
ASN: 123,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Prefix: MustParseIPNet("2001:db8::/32"),
|
||||||
|
MaxLen: 33,
|
||||||
|
ASN: 123,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Prefix: MustParseIPNet("192.168.1.0/24"),
|
||||||
|
MaxLen: 25,
|
||||||
|
ASN: 123,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if count != 3 || v4count != 2 || v6count != 1 {
|
||||||
|
t.Errorf("Wanted count = 3, v4count = 2, v6count = 1, but got %d, %d, %d", count, v4count, v6count)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cmp.Equal(got, want) {
|
||||||
|
t.Errorf("Want (%+v), Got (%+v)", want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParseIPNet is a test helper function to return a net.IPNet
|
||||||
|
// This should only be called in test code, and it'll panic on test set up
|
||||||
|
// if unable to parse.
|
||||||
|
func MustParseIPNet(prefix string) net.IPNet {
|
||||||
|
_, ipnet, err := net.ParseCIDR(prefix)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return *ipnet
|
||||||
|
}
|
@ -1,3 +1,5 @@
|
|||||||
|
// rfc8416
|
||||||
|
|
||||||
package prefixfile
|
package prefixfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
Reference in New Issue
Block a user