github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/netutil/net.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:41</date>
    10  //</624450105394597888>
    11  
    12  
    13  //包netutil包含对网络包的扩展。
    14  package netutil
    15  
    16  import (
    17  	"bytes"
    18  	"errors"
    19  	"fmt"
    20  	"net"
    21  	"sort"
    22  	"strings"
    23  )
    24  
    25  var lan4, lan6, special4, special6 Netlist
    26  
    27  func init() {
    28  //来自RFC 5735、RFC 5156的列表,
    29  //https://www.iana.org/assignments/iana-ipv4-special-registry/
    30  lan4.Add("0.0.0.0/8")              //“这个”网络
    31  lan4.Add("10.0.0.0/8")             //私人使用
    32  lan4.Add("172.16.0.0/12")          //私人使用
    33  lan4.Add("192.168.0.0/16")         //私人使用
    34  lan6.Add("fe80::/10")              //链路本地
    35  lan6.Add("fc00::/7")               //独特的地方
    36  special4.Add("192.0.0.0/29")       //IPv4服务连续性
    37  special4.Add("192.0.0.9/32")       //PCP选播
    38  special4.Add("192.0.0.170/32")     //NAT64/DNS64发现
    39  special4.Add("192.0.0.171/32")     //NAT64/DNS64发现
    40  special4.Add("192.0.2.0/24")       //测试网络-1
    41  special4.Add("192.31.196.0/24")    //AS112
    42  special4.Add("192.52.193.0/24")    //AMT
    43  special4.Add("192.88.99.0/24")     //6to4继电器选播
    44  special4.Add("192.175.48.0/24")    //AS112
    45  special4.Add("198.18.0.0/15")      //设备基准测试
    46  special4.Add("198.51.100.0/24")    //测试网NET-2
    47  special4.Add("203.0.113.0/24")     //测试网-3
    48  special4.Add("255.255.255.255/32") //有限广播
    49  
    50  //http://www.iana.org/assignments/iana-ipv6-special-registry/
    51  	special6.Add("100::/64")
    52  	special6.Add("2001::/32")
    53  	special6.Add("2001:1::1/128")
    54  	special6.Add("2001:2::/48")
    55  	special6.Add("2001:3::/32")
    56  	special6.Add("2001:4:112::/48")
    57  	special6.Add("2001:5::/32")
    58  	special6.Add("2001:10::/28")
    59  	special6.Add("2001:20::/28")
    60  	special6.Add("2001:db8::/32")
    61  	special6.Add("2002::/16")
    62  }
    63  
    64  //netlist是IP网络的列表。
    65  type Netlist []net.IPNet
    66  
    67  //ParseNetList解析CIDR掩码的逗号分隔列表。
    68  //空白和多余的逗号将被忽略。
    69  func ParseNetlist(s string) (*Netlist, error) {
    70  	ws := strings.NewReplacer(" ", "", "\n", "", "\t", "")
    71  	masks := strings.Split(ws.Replace(s), ",")
    72  	l := make(Netlist, 0)
    73  	for _, mask := range masks {
    74  		if mask == "" {
    75  			continue
    76  		}
    77  		_, n, err := net.ParseCIDR(mask)
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  		l = append(l, *n)
    82  	}
    83  	return &l, nil
    84  }
    85  
    86  //marshaltoml实现toml.marshalerrec。
    87  func (l Netlist) MarshalTOML() interface{} {
    88  	list := make([]string, 0, len(l))
    89  	for _, net := range l {
    90  		list = append(list, net.String())
    91  	}
    92  	return list
    93  }
    94  
    95  //unmarshaltoml实现toml.unmarshalerrec。
    96  func (l *Netlist) UnmarshalTOML(fn func(interface{}) error) error {
    97  	var masks []string
    98  	if err := fn(&masks); err != nil {
    99  		return err
   100  	}
   101  	for _, mask := range masks {
   102  		_, n, err := net.ParseCIDR(mask)
   103  		if err != nil {
   104  			return err
   105  		}
   106  		*l = append(*l, *n)
   107  	}
   108  	return nil
   109  }
   110  
   111  //添加分析CIDR掩码并将其附加到列表中。它对无效的掩码感到恐慌,并且
   112  //用于设置静态列表。
   113  func (l *Netlist) Add(cidr string) {
   114  	_, n, err := net.ParseCIDR(cidr)
   115  	if err != nil {
   116  		panic(err)
   117  	}
   118  	*l = append(*l, *n)
   119  }
   120  
   121  //包含报告给定IP是否包含在列表中。
   122  func (l *Netlist) Contains(ip net.IP) bool {
   123  	if l == nil {
   124  		return false
   125  	}
   126  	for _, net := range *l {
   127  		if net.Contains(ip) {
   128  			return true
   129  		}
   130  	}
   131  	return false
   132  }
   133  
   134  //islan报告IP是否为本地网络地址。
   135  func IsLAN(ip net.IP) bool {
   136  	if ip.IsLoopback() {
   137  		return true
   138  	}
   139  	if v4 := ip.To4(); v4 != nil {
   140  		return lan4.Contains(v4)
   141  	}
   142  	return lan6.Contains(ip)
   143  }
   144  
   145  //IsSpecialNetwork报告IP是否位于专用网络范围内
   146  //这包括广播、多播和文档地址。
   147  func IsSpecialNetwork(ip net.IP) bool {
   148  	if ip.IsMulticast() {
   149  		return true
   150  	}
   151  	if v4 := ip.To4(); v4 != nil {
   152  		return special4.Contains(v4)
   153  	}
   154  	return special6.Contains(ip)
   155  }
   156  
   157  var (
   158  	errInvalid     = errors.New("invalid IP")
   159  	errUnspecified = errors.New("zero address")
   160  	errSpecial     = errors.New("special network")
   161  	errLoopback    = errors.New("loopback address from non-loopback host")
   162  	errLAN         = errors.New("LAN address from WAN host")
   163  )
   164  
   165  //checkrelayip报告是否从给定的发送方IP中继IP
   166  //是有效的连接目标。
   167  //
   168  //有四条规则:
   169  //-特殊网络地址永远无效。
   170  //-如果由回送主机中继,则回送地址正常。
   171  //-如果由LAN主机中继,则LAN地址正常。
   172  //-所有其他地址始终可以接受。
   173  func CheckRelayIP(sender, addr net.IP) error {
   174  	if len(addr) != net.IPv4len && len(addr) != net.IPv6len {
   175  		return errInvalid
   176  	}
   177  	if addr.IsUnspecified() {
   178  		return errUnspecified
   179  	}
   180  	if IsSpecialNetwork(addr) {
   181  		return errSpecial
   182  	}
   183  	if addr.IsLoopback() && !sender.IsLoopback() {
   184  		return errLoopback
   185  	}
   186  	if IsLAN(addr) && !IsLAN(sender) {
   187  		return errLAN
   188  	}
   189  	return nil
   190  }
   191  
   192  //Samenet报告两个IP地址是否具有相同的给定位长度前缀。
   193  func SameNet(bits uint, ip, other net.IP) bool {
   194  	ip4, other4 := ip.To4(), other.To4()
   195  	switch {
   196  	case (ip4 == nil) != (other4 == nil):
   197  		return false
   198  	case ip4 != nil:
   199  		return sameNet(bits, ip4, other4)
   200  	default:
   201  		return sameNet(bits, ip.To16(), other.To16())
   202  	}
   203  }
   204  
   205  func sameNet(bits uint, ip, other net.IP) bool {
   206  	nb := int(bits / 8)
   207  	mask := ^byte(0xFF >> (bits % 8))
   208  	if mask != 0 && nb < len(ip) && ip[nb]&mask != other[nb]&mask {
   209  		return false
   210  	}
   211  	return nb <= len(ip) && bytes.Equal(ip[:nb], other[:nb])
   212  }
   213  
   214  //DistinctNetset跟踪IP,确保最多N个IP
   215  //属于同一网络范围。
   216  type DistinctNetSet struct {
   217  Subnet uint //公共前缀位数
   218  Limit  uint //每个子网中的最大IP数
   219  
   220  	members map[string]uint
   221  	buf     net.IP
   222  }
   223  
   224  //添加将IP地址添加到集合中。如果
   225  //定义范围内的现有IP数超过限制。
   226  func (s *DistinctNetSet) Add(ip net.IP) bool {
   227  	key := s.key(ip)
   228  	n := s.members[string(key)]
   229  	if n < s.Limit {
   230  		s.members[string(key)] = n + 1
   231  		return true
   232  	}
   233  	return false
   234  }
   235  
   236  //移除从集合中移除IP。
   237  func (s *DistinctNetSet) Remove(ip net.IP) {
   238  	key := s.key(ip)
   239  	if n, ok := s.members[string(key)]; ok {
   240  		if n == 1 {
   241  			delete(s.members, string(key))
   242  		} else {
   243  			s.members[string(key)] = n - 1
   244  		}
   245  	}
   246  }
   247  
   248  //包含给定IP是否包含在集合中。
   249  func (s DistinctNetSet) Contains(ip net.IP) bool {
   250  	key := s.key(ip)
   251  	_, ok := s.members[string(key)]
   252  	return ok
   253  }
   254  
   255  //len返回跟踪的IP数。
   256  func (s DistinctNetSet) Len() int {
   257  	n := uint(0)
   258  	for _, i := range s.members {
   259  		n += i
   260  	}
   261  	return int(n)
   262  }
   263  
   264  //键将地址的映射键编码到临时缓冲区中。
   265  //
   266  //密钥的第一个字节是“4”或“6”,用于区分IPv4/IPv6地址类型。
   267  //密钥的其余部分是IP,截断为位数。
   268  func (s *DistinctNetSet) key(ip net.IP) net.IP {
   269  //延迟初始化存储。
   270  	if s.members == nil {
   271  		s.members = make(map[string]uint)
   272  		s.buf = make(net.IP, 17)
   273  	}
   274  //将IP和位规范化。
   275  	typ := byte('6')
   276  	if ip4 := ip.To4(); ip4 != nil {
   277  		typ, ip = '4', ip4
   278  	}
   279  	bits := s.Subnet
   280  	if bits > uint(len(ip)*8) {
   281  		bits = uint(len(ip) * 8)
   282  	}
   283  //将前缀编码为s.buf。
   284  	nb := int(bits / 8)
   285  	mask := ^byte(0xFF >> (bits % 8))
   286  	s.buf[0] = typ
   287  	buf := append(s.buf[:1], ip[:nb]...)
   288  	if nb < len(ip) && mask != 0 {
   289  		buf = append(buf, ip[nb]&mask)
   290  	}
   291  	return buf
   292  }
   293  
   294  //字符串实现fmt.stringer
   295  func (s DistinctNetSet) String() string {
   296  	var buf bytes.Buffer
   297  	buf.WriteString("{")
   298  	keys := make([]string, 0, len(s.members))
   299  	for k := range s.members {
   300  		keys = append(keys, k)
   301  	}
   302  	sort.Strings(keys)
   303  	for i, k := range keys {
   304  		var ip net.IP
   305  		if k[0] == '4' {
   306  			ip = make(net.IP, 4)
   307  		} else {
   308  			ip = make(net.IP, 16)
   309  		}
   310  		copy(ip, k[1:])
   311  		fmt.Fprintf(&buf, "%v×%d", ip, s.members[k])
   312  		if i != len(keys)-1 {
   313  			buf.WriteString(" ")
   314  		}
   315  	}
   316  	buf.WriteString("}")
   317  	return buf.String()
   318  }
   319