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