check / check (push) Successful in 1m58s
`internal/ptr` asks Google, Cloudflare, AdGuard and Quad9 in turn, 2 seconds in all per address. It keeps answers in memory and writes them through to `cache.db`, opened by the new `internal/cachedb`. A reserved address is not sent to the resolvers. The cache holds at most 250,000 addresses. Judgement calls: - Each resolver gets an equal share of the time left, so a hung resolver does not use up the 2 seconds. - The negative TTL is the smaller of the SOA minimum and the SOA's own TTL (RFC 2308). - Names that are not host names are dropped, as `net.Resolver.LookupAddr` does. Model: opus-5-5
132 lines
3.5 KiB
Go
132 lines
3.5 KiB
Go
package bogon_test
|
|
|
|
import (
|
|
"net/netip"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"git.eeqj.de/sneak/routewatch/internal/bogon"
|
|
)
|
|
|
|
// privateUseTen is why a prefix or an address inside 10.0.0.0/8 is reserved.
|
|
const privateUseTen = "Private-Use (10.0.0.0/8)"
|
|
|
|
func TestPrefix(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
prefix string
|
|
// want is why the prefix is reserved, or "" when it is not.
|
|
want string
|
|
}{
|
|
{"10.1.2.0/24", privateUseTen},
|
|
{"10.0.0.0/8", privateUseTen},
|
|
{"192.0.2.0/24", "Documentation (TEST-NET-1) (192.0.2.0/24)"},
|
|
{"2001:db8:1::/48", "Documentation (2001:db8::/32)"},
|
|
{"fd00::/8", "Unique-Local (fc00::/7)"},
|
|
// Multicast space, from the IANA address space registries.
|
|
{"224.0.0.0/4", "Multicast (224.0.0.0/4)"},
|
|
{"239.255.0.0/16", "Multicast (224.0.0.0/4)"},
|
|
{"ff00::/8", "Multicast (ff00::/8)"},
|
|
{"ff02::/16", "Multicast (ff00::/8)"},
|
|
// The most specific block names the reason.
|
|
{"0.0.0.0/32", "This host on this network (0.0.0.0/32)"},
|
|
{"2001:2::/48", "Benchmarking (2001:2::/48)"},
|
|
// Blocks that may be announced, inside reserved blocks.
|
|
{"192.0.0.9/32", ""},
|
|
{"2001:4:112::/48", ""},
|
|
// Blocks that may be announced, inside no reserved block.
|
|
{"192.175.48.0/24", ""},
|
|
{"2002::/16", ""},
|
|
// A prefix that holds a reserved block is not inside it.
|
|
{"192.0.0.0/16", ""},
|
|
{"0.0.0.0/0", ""},
|
|
// Prefixes anyone may announce.
|
|
{"8.8.8.0/24", ""},
|
|
{"2001:4860::/32", ""},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.prefix, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
reason, reserved := bogon.Prefix(netip.MustParsePrefix(tc.prefix))
|
|
if reason != tc.want || reserved != (tc.want != "") {
|
|
t.Errorf("Prefix(%s) = %q, %v; want %q", tc.prefix, reason,
|
|
reserved, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAddr(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
addr string
|
|
// want is why the address is reserved, or "" when it is not.
|
|
want string
|
|
}{
|
|
{"10.0.0.1", privateUseTen},
|
|
{"fd00::1", "Unique-Local (fc00::/7)"},
|
|
// An IPv4 address written in IPv6 form counts as the IPv4 address.
|
|
{"::ffff:10.0.0.1", privateUseTen},
|
|
{"::ffff:8.8.8.8", ""},
|
|
// An address that may be announced, inside a reserved block.
|
|
{"192.0.0.9", ""},
|
|
// Addresses anyone may announce.
|
|
{"8.8.8.8", ""},
|
|
{"2001:4860:4860::8888", ""},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.addr, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
reason, reserved := bogon.Addr(netip.MustParseAddr(tc.addr))
|
|
if reason != tc.want || reserved != (tc.want != "") {
|
|
t.Errorf("Addr(%s) = %q, %v; want %q", tc.addr, reason,
|
|
reserved, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestASN(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
asn int
|
|
// want is why the AS number is reserved, or "" when it is not.
|
|
want string
|
|
}{
|
|
{23456, "AS_TRANS (AS23456)"},
|
|
{64496, "Documentation (AS64496-AS64511)"},
|
|
{64512, "Private-Use (AS64512-AS65534)"},
|
|
{65534, "Private-Use (AS64512-AS65534)"},
|
|
{65535, "Last 16-bit AS number (AS65535)"},
|
|
{65551, "Documentation (AS65536-AS65551)"},
|
|
{4200000000, "Private-Use (AS4200000000-AS4294967294)"},
|
|
{4294967295, "Last 32-bit AS number (AS4294967295)"},
|
|
// AS 0 means no known origin, and the AS112 project uses AS 112.
|
|
{0, ""},
|
|
{112, ""},
|
|
// Not handed out yet, which is not counted.
|
|
{65552, ""},
|
|
{15169, ""},
|
|
{64495, ""},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(strconv.Itoa(tc.asn), func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
reason, reserved := bogon.ASN(tc.asn)
|
|
if reason != tc.want || reserved != (tc.want != "") {
|
|
t.Errorf("ASN(%d) = %q, %v; want %q", tc.asn, reason, reserved,
|
|
tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|