1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
|
/*
Package iana imports the Internet Assigned Numbers Authority (IANA) IP Special
Registries as a data structure and implements functions to compare the reserved
networks against iplib.Net objects. The IANA registry is used to reserve
portions of IP network space for special use, examples being the IPv4 Private
Use blocks (10.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) and the IPv6 netblock
set aside for documentation purposes (2001:db8::/32).
Note that this package does not contain historical reservations. So IPv6
2001:10::/28 (ORCHIDv1) is listed in the document as "deprecated" and not
present in this library.
The data-set for the IANA registries is available from:
- https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
- https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
*/
package iana
import (
"net"
"sort"
"github.com/c-robinson/iplib"
)
// Registry holds the aggregated network list from IANA's v4 and v6 registries.
// Only the following fields were imported: Address Block, Name, RFC,
// Forwardable, Globally Reachable and Reserved-by-Protocol
var Registry []*Reservation
// Reservation describes an entry in the IANA IP Special Registry
type Reservation struct {
// Network is the reserved network
Network iplib.Net
// Title is a name given to the reservation
Title string
// RFC is the list of relevant RFCs
RFC []string
// true if a router may forward packets bound for this network between
// external interfaces
Forwardable bool
// true if a router may pass packets bound for this network outside of
// a private network
Global bool
// true if an IP implementation must implement this policy in order to
// be compliant
Reserved bool
}
func init() {
Registry = []*Reservation{
{getFromCIDR("0.0.0.0/8"), "This host on this network", []string{"RFC1122"}, false, false, true},
{getFromCIDR("10.0.0.0/8"), "Private-Use", []string{"RFC1918"}, true, false, false},
{getFromCIDR("100.64.0.0/10"), "Shared Address Space", []string{"RFC6598"}, false, false, true},
{getFromCIDR("127.0.0.0/8"), "Loopback", []string{"RFC1122"}, false, false, true},
{getFromCIDR("169.254.0.0/16"), "Link Local", []string{"RFC3927"}, false, false, true},
{getFromCIDR("172.16.0.0/12"), "Private-Use", []string{"RFC1918"}, true, false, false},
{getFromCIDR("192.0.0.0/24"), "IETF Protocol Assignments", []string{"RFC6890"}, false, false, false},
{getFromCIDR("192.0.0.0/29"), "IPv4 Service Continuity Prefix", []string{"RFC7335"}, true, false, false},
{getFromCIDR("192.0.0.8/32"), "IPv4 dummy address", []string{"RFC7600"}, false, false, false},
{getFromCIDR("192.0.0.9/32"), "Port Control Protocol Anycast", []string{"RFC7723"}, true, true, true},
{getFromCIDR("192.0.0.10/32"), "Traversal Using Relays around NAT Anycast", []string{"RFC8155"}, true, true, false},
{getFromCIDR("192.0.0.170/32"), "NAT64/DNS64 Discovery", []string{"RFC7050"}, false, false, true},
{getFromCIDR("192.0.0.171/32"), "NAT64/DNS64 Discovery", []string{"RFC7050"}, false, false, true},
{getFromCIDR("192.0.2.0/24"), "Documentation (TEST-NET-1)", []string{"RFC5737"}, false, false, false},
{getFromCIDR("192.31.196.0/24"), "AS112-v4", []string{"RFC7535"}, true, true, false},
{getFromCIDR("192.52.193.0/24"), "AMT", []string{"RFC7450"}, true, true, false},
{getFromCIDR("192.168.0.0/16"), "Private-Use", []string{"RFC1918"}, true, false, false},
{getFromCIDR("192.175.48.0/24"), "Direct Delegation AS112 Service", []string{"RFC7534"}, true, true, false},
{getFromCIDR("198.18.0.0/15"), "Benchmarking", []string{"RFC2544"}, true, false, false},
{getFromCIDR("198.51.100.0/24"), "Documentation (TEST-NET-2)", []string{"RFC5737"}, false, false, false},
{getFromCIDR("203.0.113.0/24"), "Documentation (TEST-NET-3)", []string{"RFC5737"}, false, false, false},
{getFromCIDR("240.0.0.0/4"), "Reserved", []string{"RFC1112"}, false, false, true},
{getFromCIDR("255.255.255.255/32"), "Limited Broadcast", []string{"RFC8190", "RFC919"}, false, false, true},
{getFromCIDR("::1/128"), "Loopback Address", []string{"RFC4291"}, false, false, true},
{getFromCIDR("::/128"), "Unspecified Address", []string{"RFC4291"}, false, false, true},
{getFromCIDR("::ffff:0:0/96"), "IPv4-mapped Address", []string{"RFC4291"}, false, false, true},
{getFromCIDR("64:ff9b::/96"), "IPv4-IPv6 Translation", []string{"RFC6052"}, true, true, false},
{getFromCIDR("64:ff9b:1::/48"), "IPv4-IPv6 Translation", []string{"RFC8215"}, true, false, false},
{getFromCIDR("100::/64"), "Discard-Only Address Block", []string{"RFC6666"}, true, false, false},
{getFromCIDR("2001::/23"), "IETF Protocol Assignments", []string{"RFC2928"}, false, false, false},
{getFromCIDR("2001::/32"), "TEREDO", []string{"RFC4380", "RFC8190"}, true, true, false},
{getFromCIDR("2001:1::1/128"), "Port Control Protocol Anycast", []string{"RFC7723"}, true, true, false},
{getFromCIDR("2001:1::2/128"), "Traversal Using Relays around NAT Anycast", []string{"RFC8155"}, true, true, false},
{getFromCIDR("2001:2::/48"), "Benchmarking", []string{"RFC5180", "RFC1752"}, true, false, false},
{getFromCIDR("2001:3::/32"), "AMT", []string{"RFC7450"}, true, true, false},
{getFromCIDR("2001:4:112::/48"), "AS112-v6", []string{"RFC7535"}, true, true, false},
{getFromCIDR("2001:5::/32"), "EID Space for LISP (Managed by RIPE NCC)", []string{"RFC7954"}, true, true, true},
{getFromCIDR("2001:20::/28"), "ORCHIDv2", []string{"RFC7343"}, true, true, false},
{getFromCIDR("2001:db8::/32"), "Documentation", []string{"RFC3849"}, false, false, false},
{getFromCIDR("2002::/16"), "6to4", []string{"RFC3056"}, true, true, false},
{getFromCIDR("2620:4f:8000::/48"), "Direct Delegation AS112 Service", []string{"RFC7534"}, true, true, false},
{getFromCIDR("fc00::/7"), "Unique-Local", []string{"RFC4193", "RFC8190"}, true, false, false},
{getFromCIDR("fe80::/10"), "Link-Local Unicast", []string{"RFC4291"}, false, false, true},
}
}
// GetReservationsForNetwork returns a list of any IANA reserved networks
// that are either part of the supplied network or that the supplied network
// is part of
func GetReservationsForNetwork(n iplib.Net) []*Reservation {
reservations := []*Reservation{}
for _, r := range Registry {
if iplib.EffectiveVersion(r.Network.IP()) != iplib.EffectiveVersion(n.IP()) {
continue
}
if r.Network.ContainsNet(n) || n.ContainsNet(r.Network) {
reservations = append(reservations, r)
}
if r.Title == "IPv4-mapped Address" {
if n4, ok := n.(iplib.Net4); ok {
if n4.Is4in6() {
reservations = append(reservations, r)
}
}
}
}
return reservations
}
// GetReservationsForIP returns a list of any IANA reserved networks that
// the supplied IP is part of
func GetReservationsForIP(ip net.IP) []*Reservation {
reservations := []*Reservation{}
for _, r := range Registry {
if r.Network.Contains(ip) {
if iplib.EffectiveVersion(ip) == 4 && r.Title == "IPv4-mapped Address" {
continue
}
reservations = append(reservations, r)
}
}
return reservations
}
// GetRFCsForNetwork returns a list of all RFCs that apply to the given
// network
func GetRFCsForNetwork(n iplib.Net) []string {
rfclist := []string{}
reservations := GetReservationsForNetwork(n)
if len(reservations) > 0 {
for _, r := range reservations {
LOOP:
for _, rfc := range r.RFC {
for _, xrfc := range rfclist {
if xrfc == rfc {
continue LOOP
}
}
rfclist = append(rfclist, rfc)
}
}
sort.Strings(rfclist)
}
return rfclist
}
// IsForwardable will return false if the given iplib.Net contains or is
// contained in a network that is marked not-forwardable in the IANA registry.
// IANA defines a forwardable network as one where "...a router may forward an
// IP datagram whose destination address is drawn from the allocated special-
// purpose address block between external interfaces." The default is 'true'
func IsForwardable(n iplib.Net) bool {
reservations := GetReservationsForNetwork(n)
for _, r := range reservations {
if r.Forwardable == false {
return false
}
}
return true
}
// IsGlobal will return false if the given iplib.Net contains or is contained
// in a network that is marked not-global in the IANA registry. IANA defines a
// global network as one where "...an IP datagram whose destination address is
// drawn from the allocated special-purpose address block is forwardable
// beyond a specified administrative domain." The default is 'true'
func IsGlobal(n iplib.Net) bool {
reservations := GetReservationsForNetwork(n)
for _, r := range reservations {
if r.Global == false {
return false
}
}
return true
}
// IsReserved will return true if the given iplib.Net contains or is
// contained in a network that is marked reserved-by-protocol in the IANA
// registry. IANA defines a reserved network as one where "...the RFC that
// created the special-purpose address block requires all compliant IP
// implementations to behave in a special way when processing packets either
// to or from addresses contained by the address block." The default is 'false'
func IsReserved(n iplib.Net) bool {
reservations := GetReservationsForNetwork(n)
for _, r := range reservations {
if r.Reserved == true {
return true
}
}
return false
}
func getFromCIDR(s string) iplib.Net {
_, n, _ := iplib.ParseCIDR(s)
return n
}
|