From d77cc7b676ffe74c2ac75c32e5968f7f2e6654f7 Mon Sep 17 00:00:00 2001 From: Maxime Mouchet Date: Tue, 27 Aug 2019 16:21:37 +0200 Subject: [PATCH] PeeringDB lookup --- cmd/convert.go | 16 ++++++-- pkg/goasn/asn.go | 5 ++- pkg/goasn/ixp.go | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/cmd/convert.go b/cmd/convert.go index cbd8036..89d3da2 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -7,6 +7,7 @@ import ( "os" "github.com/maxmouchet/goasn/pkg/goasn" + "github.com/maxmouchet/goasn/pkg/peeringdb" "github.com/spf13/cobra" ) @@ -25,8 +26,19 @@ to quickly create a Cobra application.`, // TODO: Get bool directly singleAS := cmd.Flag("single-as").Value.String() == "true" + // TMP + + var db peeringdb.DB + err := db.FromAPI() + check(err) + + tree, err := goasn.NewIXPTree(db) + check(err) + + fmt.Println(tree.LookupStr("8.8.8.8")) + fmt.Println(tree.LookupStr("2001:7f8:1::64")) + for _, path := range args { - // goasn. entries, err := goasn.RIBFromMRT(path) log.Println(len(entries), err) @@ -35,8 +47,6 @@ to quickly create a Cobra application.`, origins[i] = goasn.NewPrefixOrigin(entry) } - // json. - b, err := goasn.ASNDatabase{origins}.MarshalText(singleAS) check(err) diff --git a/pkg/goasn/asn.go b/pkg/goasn/asn.go index 76a3def..ec4e6f5 100644 --- a/pkg/goasn/asn.go +++ b/pkg/goasn/asn.go @@ -45,14 +45,15 @@ func NewASNTree(prefixes []PrefixOrigin) (*ASNTree, error) { } } - db := ASNTree{ + tree := ASNTree{ treeV4: treeV4, treeV6: treeV6, } - return &db, nil + return &tree, nil } +// TODO: Detect file type (txt, json, ...) func NewASNTreeFromFile(path string) (*ASNTree, error) { b, err := ioutil.ReadFile(path) if err != nil { diff --git a/pkg/goasn/ixp.go b/pkg/goasn/ixp.go index 7f2a1d6..5aa1bf6 100644 --- a/pkg/goasn/ixp.go +++ b/pkg/goasn/ixp.go @@ -1,9 +1,12 @@ package goasn import ( + "errors" "net" + "github.com/kentik/patricia" "github.com/kentik/patricia/string_tree" + "github.com/maxmouchet/goasn/pkg/peeringdb" ) type IXPTree struct { @@ -16,3 +19,99 @@ type PrefixIXP struct { Prefix net.IPNet `json:"prefix"` IXP string `json:"ixp"` } + +func NewIXPTree(db peeringdb.DB) (*IXPTree, error) { + treeV4 := string_tree.NewTreeV4() + treeV6 := string_tree.NewTreeV6() + + ixsByID := make(map[int]peeringdb.IX) + for _, ix := range db.IXs { + ixsByID[ix.ID] = ix + } + + ixLansByID := make(map[int]peeringdb.LAN) + for _, ixlan := range db.LANs { + ixLansByID[ixlan.ID] = ixlan + } + + ixpfxByIX := make(map[int][]net.IPNet) + for _, ixpfx := range db.Prefixes { + lan := ixLansByID[ixpfx.IXLanID] + _, ip, err := net.ParseCIDR(ixpfx.Prefix) + if err != nil { + return nil, err + } + ixpfxByIX[lan.IXID] = append(ixpfxByIX[lan.IXID], *ip) + } + + for ixID, pfxs := range ixpfxByIX { + ixp := ixsByID[ixID] + for _, pfx := range pfxs { + addrV4, addrV6, err := patricia.ParseFromIPAddr(&pfx) + if err != nil { + return nil, err + } + if addrV4 != nil { + _, _, err = treeV4.Add(*addrV4, ixp.Name, nil) + } + if addrV6 != nil { + _, _, err = treeV6.Add(*addrV6, ixp.Name, nil) + } + if err != nil { + return nil, err + } + } + } + + tree := IXPTree{ + treeV4: treeV4, + treeV6: treeV6, + } + + return &tree, nil +} + +// TODO: New IXPTreeFromFile +// Requires marshaling, ... + +func (t IXPTree) LookupIP(ip net.IP) (string, error) { + if addrV4 := ip.To4(); addrV4 != nil { + addr := patricia.NewIPv4AddressFromBytes(addrV4, uint(32)) + _, ixp, err := t.treeV4.FindDeepestTag(addr) + return ixp, err + } + if addrV6 := ip.To16(); addrV6 != nil { + addr := patricia.NewIPv6Address(addrV6, 128) + _, ixp, err := t.treeV6.FindDeepestTag(addr) + return ixp, err + } + return "", errors.New("Invalid IP address") +} + +func (t IXPTree) LookupIPMultiple(ips []net.IP) ([]string, error) { + ixps := make([]string, len(ips)) + for i, ip := range ips { + ixp, err := t.LookupIP(ip) + if err != nil { + return nil, err + } + ixps[i] = ixp + } + return ixps, nil +} + +func (t IXPTree) LookupStr(str string) (string, error) { + return t.LookupIP(net.ParseIP(str)) +} + +func (t IXPTree) LookupStrMultiple(strs []string) ([]string, error) { + ixps := make([]string, len(strs)) + for i, str := range strs { + ixp, err := t.LookupStr(str) + if err != nil { + return nil, err + } + ixps[i] = ixp + } + return ixps, nil +}