File: iana.go

package info (click to toggle)
golang-github-c-robinson-iplib 1.0.3-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 316 kB
  • sloc: makefile: 2
file content (216 lines) | stat: -rw-r--r-- 9,439 bytes parent folder | download
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
}