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