status-go/vendor/github.com/libp2p/go-libp2p-asn-util/asn.go

96 lines
2.0 KiB
Go
Raw Normal View History

2022-04-01 16:16:46 +00:00
package asnutil
import (
"errors"
"fmt"
"net"
2023-05-19 20:23:55 +00:00
"sync"
2022-04-01 16:16:46 +00:00
"github.com/libp2p/go-cidranger"
)
2023-05-19 20:23:55 +00:00
var Store *lazyAsnStore
2022-04-01 16:16:46 +00:00
func init() {
2023-05-19 20:23:55 +00:00
Store = &lazyAsnStore{}
2022-04-01 16:16:46 +00:00
}
type networkWithAsn struct {
nn net.IPNet
asn string
}
func (e *networkWithAsn) Network() net.IPNet {
return e.nn
}
type asnStore struct {
cr cidranger.Ranger
}
// AsnForIPv6 returns the AS number for the given IPv6 address.
// If no mapping exists for the given IP, this function will
// return an empty ASN and a nil error.
func (a *asnStore) AsnForIPv6(ip net.IP) (string, error) {
if ip.To16() == nil {
return "", errors.New("ONLY IPv6 addresses supported for now")
}
ns, err := a.cr.ContainingNetworks(ip)
if err != nil {
return "", fmt.Errorf("failed to find matching networks for the given ip: %w", err)
}
if len(ns) == 0 {
return "", nil
}
// longest prefix match
n := ns[len(ns)-1].(*networkWithAsn)
return n.asn, nil
}
func newAsnStore() (*asnStore, error) {
cr := cidranger.NewPCTrieRanger()
for _, v := range ipv6CidrToAsnPairList {
_, nn, err := net.ParseCIDR(v.cidr)
2022-04-01 16:16:46 +00:00
if err != nil {
return nil, fmt.Errorf("failed to parse CIDR %s: %w", v.cidr, err)
2022-04-01 16:16:46 +00:00
}
if err := cr.Insert(&networkWithAsn{*nn, v.asn}); err != nil {
return nil, fmt.Errorf("failed to insert CIDR %s in Trie store: %w", v.cidr, err)
2022-04-01 16:16:46 +00:00
}
}
return &asnStore{cr}, nil
}
2023-05-19 20:23:55 +00:00
// lazyAsnStore builds the underlying trie on first call to AsnForIPv6.
// Alternatively, Init can be called to manually trigger initialization.
type lazyAsnStore struct {
store *asnStore
once sync.Once
2022-04-01 16:16:46 +00:00
}
// AsnForIPv6 returns the AS number for the given IPv6 address.
// If no mapping exists for the given IP, this function will
// return an empty ASN and a nil error.
2023-05-19 20:23:55 +00:00
func (a *lazyAsnStore) AsnForIPv6(ip net.IP) (string, error) {
a.once.Do(a.init)
2022-04-01 16:16:46 +00:00
return a.store.AsnForIPv6(ip)
}
2023-05-19 20:23:55 +00:00
func (a *lazyAsnStore) Init() {
a.once.Do(a.init)
}
2022-04-01 16:16:46 +00:00
2023-05-19 20:23:55 +00:00
func (a *lazyAsnStore) init() {
store, err := newAsnStore()
if err != nil {
panic(err)
}
a.store = store
2022-04-01 16:16:46 +00:00
}