github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/p2p/netaddress.go (about)

     1  // Modified for Bytom
     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  	"errors"
     9  	"flag"
    10  	"net"
    11  	"strconv"
    12  	"time"
    13  
    14  	"github.com/btcsuite/go-socks/socks"
    15  	cmn "github.com/tendermint/tmlibs/common"
    16  )
    17  
    18  // NetAddress defines information about a peer on the network
    19  // including its IP address, and port.
    20  type NetAddress struct {
    21  	IP    net.IP
    22  	Port  uint16
    23  	str   string
    24  	isLAN bool
    25  }
    26  
    27  // NewNetAddress returns a new NetAddress using the provided TCP
    28  // address. When testing, other net.Addr (except TCP) will result in
    29  // using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will
    30  // panic.
    31  // TODO: socks proxies?
    32  func NewNetAddress(addr net.Addr) *NetAddress {
    33  	tcpAddr, ok := addr.(*net.TCPAddr)
    34  	if !ok {
    35  		if flag.Lookup("test.v") == nil { // normal run
    36  			cmn.PanicSanity(cmn.Fmt("Only TCPAddrs are supported. Got: %v", addr))
    37  		} else { // in testing
    38  			return NewNetAddressIPPort(net.IP("0.0.0.0"), 0)
    39  		}
    40  	}
    41  	ip := tcpAddr.IP
    42  	port := uint16(tcpAddr.Port)
    43  	return NewNetAddressIPPort(ip, port)
    44  }
    45  
    46  // NewNetAddressString returns a new NetAddress using the provided
    47  // address in the form of "IP:Port". Also resolves the host if host
    48  // is not an IP.
    49  func NewNetAddressString(addr string) (*NetAddress, error) {
    50  	host, portStr, err := net.SplitHostPort(addr)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	ip := net.ParseIP(host)
    56  	if ip == nil {
    57  		if len(host) > 0 {
    58  			ips, err := net.LookupIP(host)
    59  			if err != nil {
    60  				return nil, err
    61  			}
    62  			ip = ips[0]
    63  		}
    64  	}
    65  
    66  	port, err := strconv.ParseUint(portStr, 10, 16)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	na := NewNetAddressIPPort(ip, uint16(port))
    72  	return na, nil
    73  }
    74  
    75  // NewNetAddressStrings returns an array of NetAddress'es build using
    76  // the provided strings.
    77  func NewNetAddressStrings(addrs []string) ([]*NetAddress, error) {
    78  	netAddrs := make([]*NetAddress, len(addrs))
    79  	for i, addr := range addrs {
    80  		netAddr, err := NewNetAddressString(addr)
    81  		if err != nil {
    82  			return nil, errors.New(cmn.Fmt("Error in address %s: %v", addr, err))
    83  		}
    84  		netAddrs[i] = netAddr
    85  	}
    86  	return netAddrs, nil
    87  }
    88  
    89  // NewNetAddressIPPort returns a new NetAddress using the provided IP
    90  // and port number.
    91  func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress {
    92  	return &NetAddress{
    93  		IP:   ip,
    94  		Port: port,
    95  		str: net.JoinHostPort(
    96  			ip.String(),
    97  			strconv.FormatUint(uint64(port), 10),
    98  		),
    99  	}
   100  }
   101  
   102  // NewLANNetAddressIPPort returns a new LAN NetAddress using the provided IP
   103  // and port number.
   104  func NewLANNetAddressIPPort(ip net.IP, port uint16) *NetAddress {
   105  	return &NetAddress{
   106  		IP:   ip,
   107  		Port: port,
   108  		str: net.JoinHostPort(
   109  			ip.String(),
   110  			strconv.FormatUint(uint64(port), 10),
   111  		),
   112  		isLAN: true,
   113  	}
   114  }
   115  
   116  // Equals reports whether na and other are the same addresses.
   117  func (na *NetAddress) Equals(other interface{}) bool {
   118  	if o, ok := other.(*NetAddress); ok {
   119  		return na.String() == o.String()
   120  	}
   121  	return false
   122  }
   123  
   124  // String representation.
   125  func (na *NetAddress) String() string {
   126  	if na.str == "" {
   127  		na.str = net.JoinHostPort(
   128  			na.IP.String(),
   129  			strconv.FormatUint(uint64(na.Port), 10),
   130  		)
   131  	}
   132  	return na.str
   133  }
   134  
   135  //DialString dial address string representation
   136  func (na *NetAddress) DialString() string {
   137  	return net.JoinHostPort(
   138  		na.IP.String(),
   139  		strconv.FormatUint(uint64(na.Port), 10),
   140  	)
   141  }
   142  
   143  // Dial calls net.Dial on the address.
   144  func (na *NetAddress) Dial() (net.Conn, error) {
   145  	conn, err := net.Dial("tcp", na.DialString())
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	return conn, nil
   150  }
   151  
   152  // DialTimeout calls net.DialTimeout on the address.
   153  func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) {
   154  	conn, err := net.DialTimeout("tcp", na.DialString(), timeout)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	return conn, nil
   159  }
   160  
   161  // DialTimeoutWithProxy calls socks.Proxy.DialTimeout on the address.
   162  func (na *NetAddress) DialTimeoutWithProxy(proxy *socks.Proxy, timeout time.Duration) (net.Conn, error) {
   163  	conn, err := proxy.DialTimeout("tcp", na.DialString(), timeout)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	return conn, nil
   168  }
   169  
   170  // Routable returns true if the address is routable.
   171  func (na *NetAddress) Routable() bool {
   172  	// TODO(oga) bitcoind doesn't include RFC3849 here, but should we?
   173  	return na.Valid() && !(na.RFC1918() || na.RFC3927() || na.RFC4862() ||
   174  		na.RFC4193() || na.RFC4843() || na.Local())
   175  }
   176  
   177  // Valid For IPv4 these are either a 0 or all bits set address. For IPv6 a zero
   178  // address or one that matches the RFC3849 documentation address format.
   179  func (na *NetAddress) Valid() bool {
   180  	return na.IP != nil && !(na.IP.IsUnspecified() || na.RFC3849() ||
   181  		na.IP.Equal(net.IPv4bcast))
   182  }
   183  
   184  // Local returns true if it is a local address.
   185  func (na *NetAddress) Local() bool {
   186  	return na.IP.IsLoopback() || zero4.Contains(na.IP)
   187  }
   188  
   189  // ReachabilityTo checks whenever o can be reached from na.
   190  func (na *NetAddress) ReachabilityTo(o *NetAddress) int {
   191  	const (
   192  		Unreachable = 0
   193  		Default     = iota
   194  		Teredo
   195  		Ipv6Weak
   196  		Ipv4
   197  		Ipv6Strong
   198  	)
   199  	if !na.Routable() {
   200  		return Unreachable
   201  	} else if na.RFC4380() {
   202  		if !o.Routable() {
   203  			return Default
   204  		} else if o.RFC4380() {
   205  			return Teredo
   206  		} else if o.IP.To4() != nil {
   207  			return Ipv4
   208  		}
   209  		return Ipv6Weak
   210  	} else if na.IP.To4() != nil {
   211  		if o.Routable() && o.IP.To4() != nil {
   212  			return Ipv4
   213  		}
   214  		return Default
   215  	}
   216  
   217  	var tunnelled bool
   218  	// Is our v6 is tunnelled?
   219  	if o.RFC3964() || o.RFC6052() || o.RFC6145() {
   220  		tunnelled = true
   221  	}
   222  	if !o.Routable() {
   223  		return Default
   224  	} else if o.RFC4380() {
   225  		return Teredo
   226  	} else if o.IP.To4() != nil {
   227  		return Ipv4
   228  	} else if tunnelled {
   229  		// only prioritise ipv6 if we aren't tunnelling it.
   230  		return Ipv6Weak
   231  	}
   232  	return Ipv6Strong
   233  }
   234  
   235  var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)}
   236  var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)}
   237  var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)}
   238  var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)}
   239  var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)}
   240  var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)}
   241  var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)}
   242  var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)}
   243  var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)}
   244  var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)}
   245  var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)}
   246  var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)}
   247  var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)}
   248  
   249  // RFC1918 IPv4 Private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
   250  func (na *NetAddress) RFC1918() bool {
   251  	return rfc1918_10.Contains(na.IP) || rfc1918_192.Contains(na.IP) || rfc1918_172.Contains(na.IP)
   252  }
   253  
   254  // RFC3849 IPv6 Documentation address  (2001:0DB8::/32)
   255  func (na *NetAddress) RFC3849() bool {
   256  	return rfc3849.Contains(na.IP)
   257  }
   258  
   259  // RFC3927 IPv4 Autoconfig (169.254.0.0/16)
   260  func (na *NetAddress) RFC3927() bool {
   261  	return rfc3927.Contains(na.IP)
   262  }
   263  
   264  // RFC3964 IPv6 6to4 (2002::/16)
   265  func (na *NetAddress) RFC3964() bool {
   266  	return rfc3964.Contains(na.IP)
   267  }
   268  
   269  // RFC4193 IPv6 unique local (FC00::/7)
   270  func (na *NetAddress) RFC4193() bool {
   271  	return rfc4193.Contains(na.IP)
   272  }
   273  
   274  // RFC4380 IPv6 Teredo tunneling (2001::/32)
   275  func (na *NetAddress) RFC4380() bool {
   276  	return rfc4380.Contains(na.IP)
   277  }
   278  
   279  // RFC4843 IPv6 ORCHID: (2001:10::/28)
   280  func (na *NetAddress) RFC4843() bool {
   281  	return rfc4843.Contains(na.IP)
   282  }
   283  
   284  // RFC4862 IPv6 Autoconfig (FE80::/64)
   285  func (na *NetAddress) RFC4862() bool {
   286  	return rfc4862.Contains(na.IP)
   287  }
   288  
   289  // RFC6052 IPv6 well known prefix (64:FF9B::/96)
   290  func (na *NetAddress) RFC6052() bool {
   291  	return rfc6052.Contains(na.IP)
   292  }
   293  
   294  // RFC6145 IPv6 IPv4 translated address ::FFFF:0:0:0/96
   295  func (na *NetAddress) RFC6145() bool {
   296  	return rfc6145.Contains(na.IP)
   297  }