1 package addrmgr
2 3 import (
4 "fmt"
5 "net"
6 7 "github.com/p9c/p9/pkg/wire"
8 )
9 10 var (
11 // rfc1918Nets specifies the IPv4 private address blocks as defined by by RFC1918 (10.0.0.0/8, 172.16.0.0/12, and
12 // 192.168.0.0/16).
13 rfc1918Nets = []net.IPNet{
14 ipNet("10.0.0.0", 8, 32),
15 ipNet("172.16.0.0", 12, 32),
16 ipNet("192.168.0.0", 16, 32),
17 }
18 // rfc2544Net specifies the the IPv4 block as defined by RFC2544 (198.18.0.0/15)
19 rfc2544Net = ipNet("198.18.0.0", 15, 32)
20 // rfc3849Net specifies the IPv6 documentation address block as defined by RFC3849 (2001:DB8::/32).
21 rfc3849Net = ipNet("2001:DB8::", 32, 128)
22 // rfc3927Net specifies the IPv4 auto configuration address block as defined by RFC3927 (169.254.0.0/16).
23 rfc3927Net = ipNet("169.254.0.0", 16, 32)
24 // rfc3964Net specifies the IPv6 to IPv4 encapsulation address block as defined by RFC3964 (2002::/16).
25 rfc3964Net = ipNet("2002::", 16, 128)
26 // rfc4193Net specifies the IPv6 unique local address block as defined by RFC4193 (FC00::/7).
27 rfc4193Net = ipNet("FC00::", 7, 128)
28 // rfc4380Net specifies the IPv6 teredo tunneling over UDP address block as defined by RFC4380 (2001::/32).
29 rfc4380Net = ipNet("2001::", 32, 128)
30 // rfc4843Net specifies the IPv6 ORCHID address block as defined by RFC4843 (2001:10::/28).
31 rfc4843Net = ipNet("2001:10::", 28, 128)
32 // rfc4862Net specifies the IPv6 stateless address autoconfiguration address block as defined by RFC4862
33 // (FE80::/64).
34 rfc4862Net = ipNet("FE80::", 64, 128)
35 // rfc5737Net specifies the IPv4 documentation address blocks as defined by RFC5737 (192.0.2.0/24, 198.51.100.0/24,
36 // 203.0.113.0/24)
37 rfc5737Net = []net.IPNet{
38 ipNet("192.0.2.0", 24, 32),
39 ipNet("198.51.100.0", 24, 32),
40 ipNet("203.0.113.0", 24, 32),
41 }
42 // rfc6052Net specifies the IPv6 well-known prefix address block as defined by RFC6052 (64:FF9B::/96).
43 rfc6052Net = ipNet("64:FF9B::", 96, 128)
44 // rfc6145Net specifies the IPv6 to IPv4 translated address range as defined by RFC6145 (::FFFF:0:0:0/96).
45 rfc6145Net = ipNet("::FFFF:0:0:0", 96, 128)
46 // rfc6598Net specifies the IPv4 block as defined by RFC6598 (100.64.0.0/10)
47 rfc6598Net = ipNet("100.64.0.0", 10, 32)
48 // onionCatNet defines the IPv6 address block used to support Tor. bitcoind encodes a .onion address as a 16 byte
49 // number by decoding the address prior to the .onion (i.e. the key hash) base32 into a ten/ byte number. It then
50 // stores the first 6 bytes of the address as 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43. This is the same range used by
51 // OnionCat, which is part part of the RFC4193 unique local IPv6 range. In summary the format is: { magic 6 bytes,
52 // 10 bytes base32 decode of key hash }
53 onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128)
54 // zero4Net defines the IPv4 address block for address staring with 0 (0.0.0.0/8).
55 zero4Net = ipNet("0.0.0.0", 8, 32)
56 // heNet defines the Hurricane Electric IPv6 address block.
57 heNet = ipNet("2001:470::", 32, 128)
58 )
59 60 // ipNet returns a net.IPNet struct given the passed IP address string, number of one bits to include at the start of
61 // the mask, and the total number of bits for the mask.
62 func ipNet(ip string, ones, bits int) net.IPNet {
63 return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)}
64 }
65 66 // IsIPv4 returns whether or not the given address is an IPv4 address.
67 func IsIPv4(na *wire.NetAddress) bool {
68 return na.IP.To4() != nil
69 }
70 71 // IsLocal returns whether or not the given address is a local address.
72 func IsLocal(na *wire.NetAddress) bool {
73 return na.IP.IsLoopback() || zero4Net.Contains(na.IP)
74 }
75 76 // IsOnionCatTor returns whether or not the passed address is in the IPv6 range used by bitcoin to support Tor
77 // (fd87:d87e:eb43::/48). Note that this range is the same range used by OnionCat, which is part of the RFC4193 unique
78 // local IPv6 range.
79 func IsOnionCatTor(na *wire.NetAddress) bool {
80 return onionCatNet.Contains(na.IP)
81 }
82 83 // IsRFC1918 returns whether or not the passed address is part of the IPv4 private network address space as defined by
84 // RFC1918 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16).
85 func IsRFC1918(na *wire.NetAddress) bool {
86 for _, rfc := range rfc1918Nets {
87 if rfc.Contains(na.IP) {
88 return true
89 }
90 }
91 return false
92 }
93 94 // IsRFC2544 returns whether or not the passed address is part of the IPv4 address space as defined by RFC2544
95 // (198.18.0.0/15)
96 func IsRFC2544(na *wire.NetAddress) bool {
97 return rfc2544Net.Contains(na.IP)
98 }
99 100 // IsRFC3849 returns whether or not the passed address is part of the IPv6 documentation range as defined by RFC3849
101 // (2001:DB8::/32).
102 func IsRFC3849(na *wire.NetAddress) bool {
103 return rfc3849Net.Contains(na.IP)
104 }
105 106 // IsRFC3927 returns whether or not the passed address is part of the IPv4 autoconfiguration range as defined by RFC3927
107 // (169.254.0.0/16).
108 func IsRFC3927(na *wire.NetAddress) bool {
109 return rfc3927Net.Contains(na.IP)
110 }
111 112 // IsRFC3964 returns whether or not the passed address is part of the IPv6 to IPv4 encapsulation range as defined by
113 // RFC3964 (2002::/16).
114 func IsRFC3964(na *wire.NetAddress) bool {
115 return rfc3964Net.Contains(na.IP)
116 }
117 118 // IsRFC4193 returns whether or not the passed address is part of the IPv6 unique local range as defined by RFC4193
119 // (FC00::/7).
120 func IsRFC4193(na *wire.NetAddress) bool {
121 return rfc4193Net.Contains(na.IP)
122 }
123 124 // IsRFC4380 returns whether or not the passed address is part of the IPv6 teredo tunneling over UDP range as defined by
125 // RFC4380 (2001::/32).
126 func IsRFC4380(na *wire.NetAddress) bool {
127 return rfc4380Net.Contains(na.IP)
128 }
129 130 // IsRFC4843 returns whether or not the passed address is part of the IPv6 ORCHID range as defined by RFC4843
131 // (2001:10::/28).
132 func IsRFC4843(na *wire.NetAddress) bool {
133 return rfc4843Net.Contains(na.IP)
134 }
135 136 // IsRFC4862 returns whether or not the passed address is part of the IPv6 stateless address autoconfiguration range as
137 // defined by RFC4862 (FE80::/64).
138 func IsRFC4862(na *wire.NetAddress) bool {
139 return rfc4862Net.Contains(na.IP)
140 }
141 142 // IsRFC5737 returns whether or not the passed address is part of the IPv4 documentation address space as defined by
143 // RFC5737 (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
144 func IsRFC5737(na *wire.NetAddress) bool {
145 for _, rfc := range rfc5737Net {
146 if rfc.Contains(na.IP) {
147 return true
148 }
149 }
150 return false
151 }
152 153 // IsRFC6052 returns whether or not the passed address is part of the IPv6 well-known prefix range as defined by RFC6052
154 // (64:FF9B::/96).
155 func IsRFC6052(na *wire.NetAddress) bool {
156 return rfc6052Net.Contains(na.IP)
157 }
158 159 // IsRFC6145 returns whether or not the passed address is part of the IPv6 to IPv4 translated address range as defined
160 // by RFC6145 (::FFFF:0:0:0/96).
161 func IsRFC6145(na *wire.NetAddress) bool {
162 return rfc6145Net.Contains(na.IP)
163 }
164 165 // IsRFC6598 returns whether or not the passed address is part of the IPv4 shared address space specified by RFC6598
166 // (100.64.0.0/10)
167 func IsRFC6598(na *wire.NetAddress) bool {
168 return rfc6598Net.Contains(na.IP)
169 }
170 171 // IsValid returns whether or not the passed address is valid. The address is considered invalid under the following
172 // circumstances:
173 //
174 // IPv4: It is either a zero or all bits set address. I
175 //
176 // Pv6: It is either a zero or RFC3849 documentation address.
177 func IsValid(na *wire.NetAddress) bool {
178 // IsUnspecified returns if address is 0, so only all bits set, and RFC3849 need to be explicitly checked.
179 return na.IP != nil && !(na.IP.IsUnspecified() ||
180 na.IP.Equal(net.IPv4bcast))
181 }
182 183 // IsRoutable returns whether or not the passed address is routable over the public internet. This is true as long as
184 // the address is valid and is not in any reserved ranges.
185 func IsRoutable(na *wire.NetAddress) bool {
186 return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) || IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) || IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) || IsLocal(na) || (IsRFC4193(na) && !IsOnionCatTor(na)))
187 }
188 189 // GroupKey returns a string representing the network group an address is part of. This is the /16 for IPv4, the /32
190 // (/36 for he.net) for IPv6, the string "local" for a local address, the string "tor:key" where key is the /4 of the
191 // onion address for Tor address, and the string "unroutable" for an unroutable address.
192 func GroupKey(na *wire.NetAddress) string {
193 if IsLocal(na) {
194 return "local"
195 }
196 if !IsRoutable(na) {
197 return "unroutable"
198 }
199 if IsIPv4(na) {
200 return na.IP.Mask(net.CIDRMask(16, 32)).String()
201 }
202 if IsRFC6145(na) || IsRFC6052(na) {
203 // last four bytes are the ip address
204 ip := na.IP[12:16]
205 return ip.Mask(net.CIDRMask(16, 32)).String()
206 }
207 if IsRFC3964(na) {
208 ip := na.IP[2:6]
209 return ip.Mask(net.CIDRMask(16, 32)).String()
210 }
211 if IsRFC4380(na) {
212 // teredo tunnels have the last 4 bytes as the v4 address XOR 0xff.
213 ip := net.IP(make([]byte, 4))
214 for i, byt := range na.IP[12:16] {
215 ip[i] = byt ^ 0xff
216 }
217 return ip.Mask(net.CIDRMask(16, 32)).String()
218 }
219 if IsOnionCatTor(na) {
220 // group is keyed off the first 4 bits of the actual onion key.
221 return fmt.Sprintf("tor:%d", na.IP[6]&((1<<4)-1))
222 }
223 // OK, so now we know ourselves to be a IPv6 address. bitcoind uses /32 for everything, except for Hurricane
224 // Electric's (he.net) IP range, which it uses /36 for.
225 bits := 32
226 if heNet.Contains(na.IP) {
227 bits = 36
228 }
229 return na.IP.Mask(net.CIDRMask(bits, 128)).String()
230 }
231