github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/p2p/netutil/net.go (about) 1 // Package netutil contains extensions to the net package. 2 package netutil 3 4 import ( 5 "bytes" 6 "errors" 7 "fmt" 8 "net" 9 "sort" 10 "strings" 11 ) 12 13 var lan4, lan6, special4, special6 Netlist 14 15 func init() { 16 // Lists from RFC 5735, RFC 5156, 17 // https://www.iana.org/assignments/iana-ipv4-special-registry/ 18 lan4.Add("0.0.0.0/8") // "This" network 19 lan4.Add("10.0.0.0/8") // Private Use 20 lan4.Add("172.16.0.0/12") // Private Use 21 lan4.Add("192.168.0.0/16") // Private Use 22 lan6.Add("fe80::/10") // Link-Local 23 lan6.Add("fc00::/7") // Unique-Local 24 special4.Add("192.0.0.0/29") // IPv4 Service Continuity 25 special4.Add("192.0.0.9/32") // PCP Anycast 26 special4.Add("192.0.0.170/32") // NAT64/DNS64 Discovery 27 special4.Add("192.0.0.171/32") // NAT64/DNS64 Discovery 28 special4.Add("192.0.2.0/24") // TEST-NET-1 29 special4.Add("192.31.196.0/24") // AS112 30 special4.Add("192.52.193.0/24") // AMT 31 special4.Add("192.88.99.0/24") // 6to4 Relay Anycast 32 special4.Add("192.175.48.0/24") // AS112 33 special4.Add("198.18.0.0/15") // Device Benchmark Testing 34 special4.Add("198.51.100.0/24") // TEST-NET-2 35 special4.Add("203.0.113.0/24") // TEST-NET-3 36 special4.Add("255.255.255.255/32") // Limited Broadcast 37 38 // http://www.iana.org/assignments/iana-ipv6-special-registry/ 39 special6.Add("100::/64") 40 special6.Add("2001::/32") 41 special6.Add("2001:1::1/128") 42 special6.Add("2001:2::/48") 43 special6.Add("2001:3::/32") 44 special6.Add("2001:4:112::/48") 45 special6.Add("2001:5::/32") 46 special6.Add("2001:10::/28") 47 special6.Add("2001:20::/28") 48 special6.Add("2001:db8::/32") 49 special6.Add("2002::/16") 50 } 51 52 // Netlist is a list of IP networks. 53 type Netlist []net.IPNet 54 55 // ParseNetlist parses a comma-separated list of CIDR masks. 56 // Whitespace and extra commas are ignored. 57 func ParseNetlist(s string) (*Netlist, error) { 58 ws := strings.NewReplacer(" ", "", "\n", "", "\t", "") 59 masks := strings.Split(ws.Replace(s), ",") 60 l := make(Netlist, 0) 61 for _, mask := range masks { 62 if mask == "" { 63 continue 64 } 65 _, n, err := net.ParseCIDR(mask) 66 if err != nil { 67 return nil, err 68 } 69 l = append(l, *n) 70 } 71 return &l, nil 72 } 73 74 // MarshalTOML implements toml.MarshalerRec. 75 func (l Netlist) MarshalTOML() interface{} { 76 list := make([]string, 0, len(l)) 77 for _, net := range l { 78 list = append(list, net.String()) 79 } 80 return list 81 } 82 83 // UnmarshalTOML implements toml.UnmarshalerRec. 84 func (l *Netlist) UnmarshalTOML(fn func(interface{}) error) error { 85 var masks []string 86 if err := fn(&masks); err != nil { 87 return err 88 } 89 for _, mask := range masks { 90 _, n, err := net.ParseCIDR(mask) 91 if err != nil { 92 return err 93 } 94 *l = append(*l, *n) 95 } 96 return nil 97 } 98 99 // Add parses a CIDR mask and appends it to the list. It panics for invalid masks and is 100 // intended to be used for setting up static lists. 101 func (l *Netlist) Add(cidr string) { 102 _, n, err := net.ParseCIDR(cidr) 103 if err != nil { 104 panic(err) 105 } 106 *l = append(*l, *n) 107 } 108 109 // Contains reports whether the given IP is contained in the list. 110 func (l *Netlist) Contains(ip net.IP) bool { 111 if l == nil { 112 return false 113 } 114 for _, net := range *l { 115 if net.Contains(ip) { 116 return true 117 } 118 } 119 return false 120 } 121 122 // IsLAN reports whether an IP is a local network address. 123 func IsLAN(ip net.IP) bool { 124 if ip.IsLoopback() { 125 return true 126 } 127 if v4 := ip.To4(); v4 != nil { 128 return lan4.Contains(v4) 129 } 130 return lan6.Contains(ip) 131 } 132 133 // IsSpecialNetwork reports whether an IP is located in a special-use network range 134 // This includes broadcast, multicast and documentation addresses. 135 func IsSpecialNetwork(ip net.IP) bool { 136 if ip.IsMulticast() { 137 return true 138 } 139 if v4 := ip.To4(); v4 != nil { 140 return special4.Contains(v4) 141 } 142 return special6.Contains(ip) 143 } 144 145 var ( 146 errInvalid = errors.New("invalid IP") 147 errUnspecified = errors.New("zero address") 148 errSpecial = errors.New("special network") 149 errLoopback = errors.New("loopback address from non-loopback host") 150 errLAN = errors.New("LAN address from WAN host") 151 ) 152 153 // CheckRelayIP reports whether an IP relayed from the given sender IP 154 // is a valid connection target. 155 // 156 // There are four rules: 157 // - Special network addresses are never valid. 158 // - Loopback addresses are OK if relayed by a loopback host. 159 // - LAN addresses are OK if relayed by a LAN host. 160 // - All other addresses are always acceptable. 161 func CheckRelayIP(sender, addr net.IP) error { 162 if len(addr) != net.IPv4len && len(addr) != net.IPv6len { 163 return errInvalid 164 } 165 if addr.IsUnspecified() { 166 return errUnspecified 167 } 168 if IsSpecialNetwork(addr) { 169 return errSpecial 170 } 171 if addr.IsLoopback() && !sender.IsLoopback() { 172 return errLoopback 173 } 174 if IsLAN(addr) && !IsLAN(sender) { 175 return errLAN 176 } 177 return nil 178 } 179 180 // SameNet reports whether two IP addresses have an equal prefix of the given bit length. 181 func SameNet(bits uint, ip, other net.IP) bool { 182 ip4, other4 := ip.To4(), other.To4() 183 switch { 184 case (ip4 == nil) != (other4 == nil): 185 return false 186 case ip4 != nil: 187 return sameNet(bits, ip4, other4) 188 default: 189 return sameNet(bits, ip.To16(), other.To16()) 190 } 191 } 192 193 func sameNet(bits uint, ip, other net.IP) bool { 194 nb := int(bits / 8) 195 mask := ^byte(0xFF >> (bits % 8)) 196 if mask != 0 && nb < len(ip) && ip[nb]&mask != other[nb]&mask { 197 return false 198 } 199 return nb <= len(ip) && bytes.Equal(ip[:nb], other[:nb]) 200 } 201 202 // DistinctNetSet tracks IPs, ensuring that at most N of them 203 // fall into the same network range. 204 type DistinctNetSet struct { 205 Subnet uint // number of common prefix bits 206 Limit uint // maximum number of IPs in each subnet 207 208 members map[string]uint 209 buf net.IP 210 } 211 212 // Add adds an IP address to the set. It returns false (and doesn't add the IP) if the 213 // number of existing IPs in the defined range exceeds the limit. 214 func (s *DistinctNetSet) Add(ip net.IP) bool { 215 key := s.key(ip) 216 n := s.members[string(key)] 217 if n < s.Limit { 218 s.members[string(key)] = n + 1 219 return true 220 } 221 return false 222 } 223 224 // Remove removes an IP from the set. 225 func (s *DistinctNetSet) Remove(ip net.IP) { 226 key := s.key(ip) 227 if n, ok := s.members[string(key)]; ok { 228 if n == 1 { 229 delete(s.members, string(key)) 230 } else { 231 s.members[string(key)] = n - 1 232 } 233 } 234 } 235 236 // Contains whether the given IP is contained in the set. 237 func (s DistinctNetSet) Contains(ip net.IP) bool { 238 key := s.key(ip) 239 _, ok := s.members[string(key)] 240 return ok 241 } 242 243 // Len returns the number of tracked IPs. 244 func (s DistinctNetSet) Len() int { 245 n := uint(0) 246 for _, i := range s.members { 247 n += i 248 } 249 return int(n) 250 } 251 252 // key encodes the map key for an address into a temporary buffer. 253 // 254 // The first byte of key is '4' or '6' to distinguish IPv4/IPv6 address types. 255 // The remainder of the key is the IP, truncated to the number of bits. 256 func (s *DistinctNetSet) key(ip net.IP) net.IP { 257 // Lazily initialize storage. 258 if s.members == nil { 259 s.members = make(map[string]uint) 260 s.buf = make(net.IP, 17) 261 } 262 // Canonicalize ip and bits. 263 typ := byte('6') 264 if ip4 := ip.To4(); ip4 != nil { 265 typ, ip = '4', ip4 266 } 267 bits := s.Subnet 268 if bits > uint(len(ip)*8) { 269 bits = uint(len(ip) * 8) 270 } 271 // Encode the prefix into s.buf. 272 nb := int(bits / 8) 273 mask := ^byte(0xFF >> (bits % 8)) 274 s.buf[0] = typ 275 buf := append(s.buf[:1], ip[:nb]...) 276 if nb < len(ip) && mask != 0 { 277 buf = append(buf, ip[nb]&mask) 278 } 279 return buf 280 } 281 282 // String implements fmt.Stringer 283 func (s DistinctNetSet) String() string { 284 var buf bytes.Buffer 285 buf.WriteString("{") 286 keys := make([]string, 0, len(s.members)) 287 for k := range s.members { 288 keys = append(keys, k) 289 } 290 sort.Strings(keys) 291 for i, k := range keys { 292 var ip net.IP 293 if k[0] == '4' { 294 ip = make(net.IP, 4) 295 } else { 296 ip = make(net.IP, 16) 297 } 298 copy(ip, k[1:]) 299 fmt.Fprintf(&buf, "%vĂ—%d", ip, s.members[k]) 300 if i != len(keys)-1 { 301 buf.WriteString(" ") 302 } 303 } 304 buf.WriteString("}") 305 return buf.String() 306 }