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

94 lines
2.4 KiB
Go
Raw Normal View History

2022-04-01 16:16:46 +00:00
package asnutil
import (
2024-06-05 20:10:03 +00:00
_ "embed"
"encoding/binary"
2022-04-01 16:16:46 +00:00
"errors"
2024-06-05 20:10:03 +00:00
"math"
2022-04-01 16:16:46 +00:00
"net"
2024-06-05 20:10:03 +00:00
"strconv"
2022-04-01 16:16:46 +00:00
)
2024-06-05 20:10:03 +00:00
//go:embed sorted-network-list.bin
var dataset string
2022-04-01 16:16:46 +00:00
2024-06-05 20:10:03 +00:00
const entrySize = 8*2 + 4 // start, end 8 bytes; asn 4 bytes
2022-04-01 16:16:46 +00:00
2024-06-05 20:10:03 +00:00
func readEntry(index uint) (start, end uint64, asn uint32) {
base := entrySize * index
b := dataset[base : base+entrySize]
start = uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
b = b[8:]
end = uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
b = b[8:]
asn = uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
return
2022-04-01 16:16:46 +00:00
}
// AsnForIPv6 returns the AS number for the given IPv6 address.
2024-06-05 20:10:03 +00:00
// If no mapping exists for the given network, this function will return a zero ASN number.
func AsnForIPv6(ip net.IP) (asn uint32) {
ip = ip.To16()
if ip == nil {
return
2022-04-01 16:16:46 +00:00
}
2024-06-05 20:10:03 +00:00
return AsnForIPv6Network(binary.BigEndian.Uint64(ip))
}
2022-04-01 16:16:46 +00:00
2024-06-05 20:10:03 +00:00
func init() {
if len(dataset) > math.MaxUint/2 {
panic("list is too big and would overflow in binary search")
2022-04-01 16:16:46 +00:00
}
}
2024-06-05 20:10:03 +00:00
// AsnForIPv6Network returns the AS number for the given IPv6 network.
// If no mapping exists for the given network, this function will return a zero ASN number.
// network is the first 64 bits of the ip address interpreted as big endian.
func AsnForIPv6Network(network uint64) (asn uint32) {
n := uint(len(dataset)) / entrySize
var i, j uint = 0, n
for i < j {
h := (i + j) / 2 // wont overflow since the list can't be that large
start, end, asn := readEntry(h)
if start <= network {
if network <= end {
return asn
}
i = h + 1
} else {
j = h
2022-04-01 16:16:46 +00:00
}
}
2024-06-05 20:10:03 +00:00
if i >= n {
return 0
}
start, end, asn := readEntry(i)
if start <= network && network <= end {
return asn
}
return 0
2022-04-01 16:16:46 +00:00
}
2024-06-05 20:10:03 +00:00
// Deprecated: use [AsnForIPv6] or [AsnForIPv6Network], they do not allocate.
var Store backwardCompat
type backwardCompat struct{}
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.
2024-06-05 20:10:03 +00:00
func (backwardCompat) AsnForIPv6(ip net.IP) (string, error) {
ip = ip.To16()
if ip == nil {
return "", errors.New("ONLY IPv6 addresses supported")
}
2022-04-01 16:16:46 +00:00
2024-06-05 20:10:03 +00:00
asn := AsnForIPv6Network(binary.BigEndian.Uint64(ip))
if asn == 0 {
return "", nil
2023-05-19 20:23:55 +00:00
}
2024-06-05 20:10:03 +00:00
return strconv.FormatUint(uint64(asn), 10), nil
2022-04-01 16:16:46 +00:00
}
2024-06-05 20:10:03 +00:00
func (backwardCompat) Init() {}