github.com/okex/exchain@v1.8.0/libs/tendermint/p2p/netaddress.go (about) 1 // Modified for Tendermint 2 // Originally Copyright (c) 2013-2014 Conformal Systems LLC. 3 // https://github.com/conformal/btcd/blob/master/LICENSE 4 5 package p2p 6 7 import ( 8 "encoding/hex" 9 "flag" 10 "fmt" 11 "net" 12 "strconv" 13 "strings" 14 "sync/atomic" 15 "time" 16 "unsafe" 17 18 "github.com/pkg/errors" 19 ) 20 21 // NetAddress defines information about a peer on the network 22 // including its ID, IP address, and port. 23 type NetAddress struct { 24 ID ID `json:"id"` 25 IP net.IP `json:"ip"` 26 Port uint16 `json:"port"` 27 28 // TODO: 29 // Name string `json:"name"` // optional DNS name 30 31 // memoize .String() 32 str *string 33 } 34 35 // IDAddressString returns id@hostPort. It strips the leading 36 // protocol from protocolHostPort if it exists. 37 func IDAddressString(id ID, protocolHostPort string) string { 38 hostPort := removeProtocolIfDefined(protocolHostPort) 39 return fmt.Sprintf("%s@%s", id, hostPort) 40 } 41 42 // NewNetAddress returns a new NetAddress using the provided TCP 43 // address. When testing, other net.Addr (except TCP) will result in 44 // using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will 45 // panic. Panics if ID is invalid. 46 // TODO: socks proxies? 47 func NewNetAddress(id ID, addr net.Addr) *NetAddress { 48 tcpAddr, ok := addr.(*net.TCPAddr) 49 if !ok { 50 if flag.Lookup("test.v") == nil { // normal run 51 panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr)) 52 } else { // in testing 53 netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0) 54 netAddr.ID = id 55 return netAddr 56 } 57 } 58 59 if err := validateID(id); err != nil { 60 panic(fmt.Sprintf("Invalid ID %v: %v (addr: %v)", id, err, addr)) 61 } 62 63 ip := tcpAddr.IP 64 port := uint16(tcpAddr.Port) 65 na := NewNetAddressIPPort(ip, port) 66 na.ID = id 67 return na 68 } 69 70 // NewNetAddressString returns a new NetAddress using the provided address in 71 // the form of "ID@IP:Port". 72 // Also resolves the host if host is not an IP. 73 // Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup) 74 func NewNetAddressString(addr string) (*NetAddress, error) { 75 addrWithoutProtocol := removeProtocolIfDefined(addr) 76 spl := strings.Split(addrWithoutProtocol, "@") 77 if len(spl) != 2 { 78 return nil, ErrNetAddressNoID{addr} 79 } 80 81 // get ID 82 if err := validateID(ID(spl[0])); err != nil { 83 return nil, ErrNetAddressInvalid{addrWithoutProtocol, err} 84 } 85 var id ID 86 id, addrWithoutProtocol = ID(spl[0]), spl[1] 87 88 // get host and port 89 host, portStr, err := net.SplitHostPort(addrWithoutProtocol) 90 if err != nil { 91 return nil, ErrNetAddressInvalid{addrWithoutProtocol, err} 92 } 93 if len(host) == 0 { 94 return nil, ErrNetAddressInvalid{ 95 addrWithoutProtocol, 96 errors.New("host is empty")} 97 } 98 99 ip := net.ParseIP(host) 100 if ip == nil { 101 ips, err := net.LookupIP(host) 102 if err != nil { 103 return nil, ErrNetAddressLookup{host, err} 104 } 105 ip = ips[0] 106 } 107 108 port, err := strconv.ParseUint(portStr, 10, 16) 109 if err != nil { 110 return nil, ErrNetAddressInvalid{portStr, err} 111 } 112 113 na := NewNetAddressIPPort(ip, uint16(port)) 114 na.ID = id 115 return na, nil 116 } 117 118 // NewNetAddressStrings returns an array of NetAddress'es build using 119 // the provided strings. 120 func NewNetAddressStrings(addrs []string) ([]*NetAddress, []error) { 121 netAddrs := make([]*NetAddress, 0) 122 errs := make([]error, 0) 123 for _, addr := range addrs { 124 netAddr, err := NewNetAddressString(addr) 125 if err != nil { 126 errs = append(errs, err) 127 } else { 128 netAddrs = append(netAddrs, netAddr) 129 } 130 } 131 return netAddrs, errs 132 } 133 134 // NewNetAddressIPPort returns a new NetAddress using the provided IP 135 // and port number. 136 func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress { 137 return &NetAddress{ 138 IP: ip, 139 Port: port, 140 } 141 } 142 143 // Equals reports whether na and other are the same addresses, 144 // including their ID, IP, and Port. 145 func (na *NetAddress) Equals(other interface{}) bool { 146 if o, ok := other.(*NetAddress); ok { 147 return na.String() == o.String() 148 } 149 return false 150 } 151 152 // Same returns true is na has the same non-empty ID or DialString as other. 153 func (na *NetAddress) Same(other interface{}) bool { 154 if o, ok := other.(*NetAddress); ok { 155 if na.DialString() == o.DialString() { 156 return true 157 } 158 if na.ID != "" && na.ID == o.ID { 159 return true 160 } 161 } 162 return false 163 } 164 165 func (na *NetAddress) safeLoadStr() *string { 166 return (*string)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&na.str)))) 167 } 168 169 func (na *NetAddress) safeStoreStr(addrStr string) { 170 atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&na.str)), unsafe.Pointer(&addrStr)) 171 } 172 173 // String representation: <ID>@<IP>:<PORT> 174 func (na *NetAddress) String() string { 175 if na == nil { 176 return "<nil-NetAddress>" 177 } 178 179 addrP := na.safeLoadStr() 180 if addrP == nil { 181 addrStr := na.DialString() 182 if na.ID != "" { 183 addrStr = IDAddressString(na.ID, addrStr) 184 } 185 addrP = &addrStr 186 na.safeStoreStr(addrStr) 187 } 188 189 return *addrP 190 } 191 192 func (na *NetAddress) DialString() string { 193 if na == nil { 194 return "<nil-NetAddress>" 195 } 196 return net.JoinHostPort( 197 na.IP.String(), 198 strconv.FormatUint(uint64(na.Port), 10), 199 ) 200 } 201 202 // Dial calls net.Dial on the address. 203 func (na *NetAddress) Dial() (net.Conn, error) { 204 conn, err := net.Dial("tcp", na.DialString()) 205 if err != nil { 206 return nil, err 207 } 208 return conn, nil 209 } 210 211 // DialTimeout calls net.DialTimeout on the address. 212 func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) { 213 conn, err := net.DialTimeout("tcp", na.DialString(), timeout) 214 if err != nil { 215 return nil, err 216 } 217 return conn, nil 218 } 219 220 // Routable returns true if the address is routable. 221 func (na *NetAddress) Routable() bool { 222 if err := na.Valid(); err != nil { 223 return false 224 } 225 // TODO(oga) bitcoind doesn't include RFC3849 here, but should we? 226 return !(na.RFC1918() || na.RFC3927() || na.RFC4862() || 227 na.RFC4193() || na.RFC4843() || na.Local()) 228 } 229 230 // For IPv4 these are either a 0 or all bits set address. For IPv6 a zero 231 // address or one that matches the RFC3849 documentation address format. 232 func (na *NetAddress) Valid() error { 233 if err := validateID(na.ID); err != nil { 234 return errors.Wrap(err, "invalid ID") 235 } 236 237 if na.IP == nil { 238 return errors.New("no IP") 239 } 240 if na.IP.IsUnspecified() || na.RFC3849() || na.IP.Equal(net.IPv4bcast) { 241 return errors.New("invalid IP") 242 } 243 return nil 244 } 245 246 // HasID returns true if the address has an ID. 247 // NOTE: It does not check whether the ID is valid or not. 248 func (na *NetAddress) HasID() bool { 249 return string(na.ID) != "" 250 } 251 252 // Local returns true if it is a local address. 253 func (na *NetAddress) Local() bool { 254 return na.IP.IsLoopback() || zero4.Contains(na.IP) 255 } 256 257 // ReachabilityTo checks whenever o can be reached from na. 258 func (na *NetAddress) ReachabilityTo(o *NetAddress) int { 259 const ( 260 Unreachable = 0 261 Default = iota 262 Teredo 263 Ipv6Weak 264 Ipv4 265 Ipv6Strong 266 ) 267 switch { 268 case !na.Routable(): 269 return Unreachable 270 case na.RFC4380(): 271 switch { 272 case !o.Routable(): 273 return Default 274 case o.RFC4380(): 275 return Teredo 276 case o.IP.To4() != nil: 277 return Ipv4 278 default: // ipv6 279 return Ipv6Weak 280 } 281 case na.IP.To4() != nil: 282 if o.Routable() && o.IP.To4() != nil { 283 return Ipv4 284 } 285 return Default 286 default: /* ipv6 */ 287 var tunnelled bool 288 // Is our v6 is tunnelled? 289 if o.RFC3964() || o.RFC6052() || o.RFC6145() { 290 tunnelled = true 291 } 292 switch { 293 case !o.Routable(): 294 return Default 295 case o.RFC4380(): 296 return Teredo 297 case o.IP.To4() != nil: 298 return Ipv4 299 case tunnelled: 300 // only prioritise ipv6 if we aren't tunnelling it. 301 return Ipv6Weak 302 } 303 return Ipv6Strong 304 } 305 } 306 307 // RFC1918: IPv4 Private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) 308 // RFC3849: IPv6 Documentation address (2001:0DB8::/32) 309 // RFC3927: IPv4 Autoconfig (169.254.0.0/16) 310 // RFC3964: IPv6 6to4 (2002::/16) 311 // RFC4193: IPv6 unique local (FC00::/7) 312 // RFC4380: IPv6 Teredo tunneling (2001::/32) 313 // RFC4843: IPv6 ORCHID: (2001:10::/28) 314 // RFC4862: IPv6 Autoconfig (FE80::/64) 315 // RFC6052: IPv6 well known prefix (64:FF9B::/96) 316 // RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96 317 var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)} 318 var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)} 319 var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)} 320 var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)} 321 var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)} 322 var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)} 323 var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)} 324 var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)} 325 var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)} 326 var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)} 327 var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)} 328 var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)} 329 var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)} 330 var ( 331 // onionCatNet defines the IPv6 address block used to support Tor. 332 // bitcoind encodes a .onion address as a 16 byte number by decoding the 333 // address prior to the .onion (i.e. the key hash) base32 into a ten 334 // byte number. It then stores the first 6 bytes of the address as 335 // 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43. 336 // 337 // This is the same range used by OnionCat, which is part part of the 338 // RFC4193 unique local IPv6 range. 339 // 340 // In summary the format is: 341 // { magic 6 bytes, 10 bytes base32 decode of key hash } 342 onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128) 343 ) 344 345 // ipNet returns a net.IPNet struct given the passed IP address string, number 346 // of one bits to include at the start of the mask, and the total number of bits 347 // for the mask. 348 func ipNet(ip string, ones, bits int) net.IPNet { 349 return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)} 350 } 351 352 func (na *NetAddress) RFC1918() bool { 353 return rfc1918_10.Contains(na.IP) || 354 rfc1918_192.Contains(na.IP) || 355 rfc1918_172.Contains(na.IP) 356 } 357 func (na *NetAddress) RFC3849() bool { return rfc3849.Contains(na.IP) } 358 func (na *NetAddress) RFC3927() bool { return rfc3927.Contains(na.IP) } 359 func (na *NetAddress) RFC3964() bool { return rfc3964.Contains(na.IP) } 360 func (na *NetAddress) RFC4193() bool { return rfc4193.Contains(na.IP) } 361 func (na *NetAddress) RFC4380() bool { return rfc4380.Contains(na.IP) } 362 func (na *NetAddress) RFC4843() bool { return rfc4843.Contains(na.IP) } 363 func (na *NetAddress) RFC4862() bool { return rfc4862.Contains(na.IP) } 364 func (na *NetAddress) RFC6052() bool { return rfc6052.Contains(na.IP) } 365 func (na *NetAddress) RFC6145() bool { return rfc6145.Contains(na.IP) } 366 func (na *NetAddress) OnionCatTor() bool { return onionCatNet.Contains(na.IP) } 367 368 func removeProtocolIfDefined(addr string) string { 369 if strings.Contains(addr, "://") { 370 return strings.Split(addr, "://")[1] 371 } 372 return addr 373 374 } 375 376 func validateID(id ID) error { 377 if len(id) == 0 { 378 return errors.New("no ID") 379 } 380 idBytes, err := hex.DecodeString(string(id)) 381 if err != nil { 382 return err 383 } 384 if len(idBytes) != IDByteLength { 385 return fmt.Errorf("invalid hex length - got %d, expected %d", len(idBytes), IDByteLength) 386 } 387 return nil 388 }