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