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