Source file src/net/addrselect_test.go

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
     6  
     7  package net
     8  
     9  import (
    10  	"net/netip"
    11  	"reflect"
    12  	"testing"
    13  )
    14  
    15  func TestSortByRFC6724(t *testing.T) {
    16  	tests := []struct {
    17  		in      []IPAddr
    18  		srcs    []netip.Addr
    19  		want    []IPAddr
    20  		reverse bool // also test it starting backwards
    21  	}{
    22  		// Examples from RFC 6724 section 10.2:
    23  
    24  		// Prefer matching scope.
    25  		{
    26  			in: []IPAddr{
    27  				{IP: ParseIP("2001:db8:1::1")},
    28  				{IP: ParseIP("198.51.100.121")},
    29  			},
    30  			srcs: []netip.Addr{
    31  				netip.MustParseAddr("2001:db8:1::2"),
    32  				netip.MustParseAddr("169.254.13.78"),
    33  			},
    34  			want: []IPAddr{
    35  				{IP: ParseIP("2001:db8:1::1")},
    36  				{IP: ParseIP("198.51.100.121")},
    37  			},
    38  			reverse: true,
    39  		},
    40  
    41  		// Prefer matching scope.
    42  		{
    43  			in: []IPAddr{
    44  				{IP: ParseIP("2001:db8:1::1")},
    45  				{IP: ParseIP("198.51.100.121")},
    46  			},
    47  			srcs: []netip.Addr{
    48  				netip.MustParseAddr("fe80::1"),
    49  				netip.MustParseAddr("198.51.100.117"),
    50  			},
    51  			want: []IPAddr{
    52  				{IP: ParseIP("198.51.100.121")},
    53  				{IP: ParseIP("2001:db8:1::1")},
    54  			},
    55  			reverse: true,
    56  		},
    57  
    58  		// Prefer higher precedence.
    59  		{
    60  			in: []IPAddr{
    61  				{IP: ParseIP("2001:db8:1::1")},
    62  				{IP: ParseIP("10.1.2.3")},
    63  			},
    64  			srcs: []netip.Addr{
    65  				netip.MustParseAddr("2001:db8:1::2"),
    66  				netip.MustParseAddr("10.1.2.4"),
    67  			},
    68  			want: []IPAddr{
    69  				{IP: ParseIP("2001:db8:1::1")},
    70  				{IP: ParseIP("10.1.2.3")},
    71  			},
    72  			reverse: true,
    73  		},
    74  
    75  		// Prefer smaller scope.
    76  		{
    77  			in: []IPAddr{
    78  				{IP: ParseIP("2001:db8:1::1")},
    79  				{IP: ParseIP("fe80::1")},
    80  			},
    81  			srcs: []netip.Addr{
    82  				netip.MustParseAddr("2001:db8:1::2"),
    83  				netip.MustParseAddr("fe80::2"),
    84  			},
    85  			want: []IPAddr{
    86  				{IP: ParseIP("fe80::1")},
    87  				{IP: ParseIP("2001:db8:1::1")},
    88  			},
    89  			reverse: true,
    90  		},
    91  
    92  		// Issue 13283.  Having a 10/8 source address does not
    93  		// mean we should prefer 23/8 destination addresses.
    94  		{
    95  			in: []IPAddr{
    96  				{IP: ParseIP("54.83.193.112")},
    97  				{IP: ParseIP("184.72.238.214")},
    98  				{IP: ParseIP("23.23.172.185")},
    99  				{IP: ParseIP("75.101.148.21")},
   100  				{IP: ParseIP("23.23.134.56")},
   101  				{IP: ParseIP("23.21.50.150")},
   102  			},
   103  			srcs: []netip.Addr{
   104  				netip.MustParseAddr("10.2.3.4"),
   105  				netip.MustParseAddr("10.2.3.4"),
   106  				netip.MustParseAddr("10.2.3.4"),
   107  				netip.MustParseAddr("10.2.3.4"),
   108  				netip.MustParseAddr("10.2.3.4"),
   109  				netip.MustParseAddr("10.2.3.4"),
   110  			},
   111  			want: []IPAddr{
   112  				{IP: ParseIP("54.83.193.112")},
   113  				{IP: ParseIP("184.72.238.214")},
   114  				{IP: ParseIP("23.23.172.185")},
   115  				{IP: ParseIP("75.101.148.21")},
   116  				{IP: ParseIP("23.23.134.56")},
   117  				{IP: ParseIP("23.21.50.150")},
   118  			},
   119  			reverse: false,
   120  		},
   121  	}
   122  	for i, tt := range tests {
   123  		inCopy := make([]IPAddr, len(tt.in))
   124  		copy(inCopy, tt.in)
   125  		srcCopy := make([]netip.Addr, len(tt.in))
   126  		copy(srcCopy, tt.srcs)
   127  		sortByRFC6724withSrcs(inCopy, srcCopy)
   128  		if !reflect.DeepEqual(inCopy, tt.want) {
   129  			t.Errorf("test %d:\nin = %s\ngot: %s\nwant: %s\n", i, tt.in, inCopy, tt.want)
   130  		}
   131  		if tt.reverse {
   132  			copy(inCopy, tt.in)
   133  			copy(srcCopy, tt.srcs)
   134  			for j := 0; j < len(inCopy)/2; j++ {
   135  				k := len(inCopy) - j - 1
   136  				inCopy[j], inCopy[k] = inCopy[k], inCopy[j]
   137  				srcCopy[j], srcCopy[k] = srcCopy[k], srcCopy[j]
   138  			}
   139  			sortByRFC6724withSrcs(inCopy, srcCopy)
   140  			if !reflect.DeepEqual(inCopy, tt.want) {
   141  				t.Errorf("test %d, starting backwards:\nin = %s\ngot: %s\nwant: %s\n", i, tt.in, inCopy, tt.want)
   142  			}
   143  		}
   144  
   145  	}
   146  
   147  }
   148  
   149  func TestRFC6724PolicyTableOrder(t *testing.T) {
   150  	for i := 0; i < len(rfc6724policyTable)-1; i++ {
   151  		if !(rfc6724policyTable[i].Prefix.Bits() >= rfc6724policyTable[i+1].Prefix.Bits()) {
   152  			t.Errorf("rfc6724policyTable item number %d sorted in wrong order = %d bits, next item = %d bits;", i, rfc6724policyTable[i].Prefix.Bits(), rfc6724policyTable[i+1].Prefix.Bits())
   153  		}
   154  	}
   155  }
   156  
   157  func TestRFC6724PolicyTableContent(t *testing.T) {
   158  	expectedRfc6724policyTable := policyTable{
   159  		{
   160  			Prefix:     netip.MustParsePrefix("::1/128"),
   161  			Precedence: 50,
   162  			Label:      0,
   163  		},
   164  		{
   165  			Prefix:     netip.MustParsePrefix("::ffff:0:0/96"),
   166  			Precedence: 35,
   167  			Label:      4,
   168  		},
   169  		{
   170  			Prefix:     netip.MustParsePrefix("::/96"),
   171  			Precedence: 1,
   172  			Label:      3,
   173  		},
   174  		{
   175  			Prefix:     netip.MustParsePrefix("2001::/32"),
   176  			Precedence: 5,
   177  			Label:      5,
   178  		},
   179  		{
   180  			Prefix:     netip.MustParsePrefix("2002::/16"),
   181  			Precedence: 30,
   182  			Label:      2,
   183  		},
   184  		{
   185  			Prefix:     netip.MustParsePrefix("3ffe::/16"),
   186  			Precedence: 1,
   187  			Label:      12,
   188  		},
   189  		{
   190  			Prefix:     netip.MustParsePrefix("fec0::/10"),
   191  			Precedence: 1,
   192  			Label:      11,
   193  		},
   194  		{
   195  			Prefix:     netip.MustParsePrefix("fc00::/7"),
   196  			Precedence: 3,
   197  			Label:      13,
   198  		},
   199  		{
   200  			Prefix:     netip.MustParsePrefix("::/0"),
   201  			Precedence: 40,
   202  			Label:      1,
   203  		},
   204  	}
   205  	if !reflect.DeepEqual(rfc6724policyTable, expectedRfc6724policyTable) {
   206  		t.Errorf("rfc6724policyTable has wrong contend = %v; want %v", rfc6724policyTable, expectedRfc6724policyTable)
   207  	}
   208  }
   209  
   210  func TestRFC6724PolicyTableClassify(t *testing.T) {
   211  	tests := []struct {
   212  		ip   netip.Addr
   213  		want policyTableEntry
   214  	}{
   215  		{
   216  			ip: netip.MustParseAddr("127.0.0.1"),
   217  			want: policyTableEntry{
   218  				Prefix:     netip.MustParsePrefix("::ffff:0:0/96"),
   219  				Precedence: 35,
   220  				Label:      4,
   221  			},
   222  		},
   223  		{
   224  			ip: netip.MustParseAddr("2601:645:8002:a500:986f:1db8:c836:bd65"),
   225  			want: policyTableEntry{
   226  				Prefix:     netip.MustParsePrefix("::/0"),
   227  				Precedence: 40,
   228  				Label:      1,
   229  			},
   230  		},
   231  		{
   232  			ip: netip.MustParseAddr("::1"),
   233  			want: policyTableEntry{
   234  				Prefix:     netip.MustParsePrefix("::1/128"),
   235  				Precedence: 50,
   236  				Label:      0,
   237  			},
   238  		},
   239  		{
   240  			ip: netip.MustParseAddr("2002::ab12"),
   241  			want: policyTableEntry{
   242  				Prefix:     netip.MustParsePrefix("2002::/16"),
   243  				Precedence: 30,
   244  				Label:      2,
   245  			},
   246  		},
   247  	}
   248  	for i, tt := range tests {
   249  		got := rfc6724policyTable.Classify(tt.ip)
   250  		if !reflect.DeepEqual(got, tt.want) {
   251  			t.Errorf("%d. Classify(%s) = %v; want %v", i, tt.ip, got, tt.want)
   252  		}
   253  	}
   254  }
   255  
   256  func TestRFC6724ClassifyScope(t *testing.T) {
   257  	tests := []struct {
   258  		ip   netip.Addr
   259  		want scope
   260  	}{
   261  		{netip.MustParseAddr("127.0.0.1"), scopeLinkLocal},   // rfc6724#section-3.2
   262  		{netip.MustParseAddr("::1"), scopeLinkLocal},         // rfc4007#section-4
   263  		{netip.MustParseAddr("169.254.1.2"), scopeLinkLocal}, // rfc6724#section-3.2
   264  		{netip.MustParseAddr("fec0::1"), scopeSiteLocal},
   265  		{netip.MustParseAddr("8.8.8.8"), scopeGlobal},
   266  
   267  		{netip.MustParseAddr("ff02::"), scopeLinkLocal},  // IPv6 multicast
   268  		{netip.MustParseAddr("ff05::"), scopeSiteLocal},  // IPv6 multicast
   269  		{netip.MustParseAddr("ff04::"), scopeAdminLocal}, // IPv6 multicast
   270  		{netip.MustParseAddr("ff0e::"), scopeGlobal},     // IPv6 multicast
   271  
   272  		{netip.AddrFrom16([16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xe0, 0, 0, 0}), scopeGlobal}, // IPv4 link-local multicast as 16 bytes
   273  		{netip.AddrFrom16([16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xe0, 2, 2, 2}), scopeGlobal}, // IPv4 global multicast as 16 bytes
   274  		{netip.AddrFrom4([4]byte{0xe0, 0, 0, 0}), scopeGlobal},                                       // IPv4 link-local multicast as 4 bytes
   275  		{netip.AddrFrom4([4]byte{0xe0, 2, 2, 2}), scopeGlobal},                                       // IPv4 global multicast as 4 bytes
   276  	}
   277  	for i, tt := range tests {
   278  		got := classifyScope(tt.ip)
   279  		if got != tt.want {
   280  			t.Errorf("%d. classifyScope(%s) = %x; want %x", i, tt.ip, got, tt.want)
   281  		}
   282  	}
   283  }
   284  
   285  func TestRFC6724CommonPrefixLength(t *testing.T) {
   286  	tests := []struct {
   287  		a    netip.Addr
   288  		b    IP
   289  		want int
   290  	}{
   291  		{netip.MustParseAddr("fe80::1"), ParseIP("fe80::2"), 64},
   292  		{netip.MustParseAddr("fe81::1"), ParseIP("fe80::2"), 15},
   293  		{netip.MustParseAddr("127.0.0.1"), ParseIP("fe80::1"), 0}, // diff size
   294  		{netip.AddrFrom4([4]byte{1, 2, 3, 4}), IP{1, 2, 3, 4}, 32},
   295  		{netip.AddrFrom4([4]byte{1, 2, 255, 255}), IP{1, 2, 0, 0}, 16},
   296  		{netip.AddrFrom4([4]byte{1, 2, 127, 255}), IP{1, 2, 0, 0}, 17},
   297  		{netip.AddrFrom4([4]byte{1, 2, 63, 255}), IP{1, 2, 0, 0}, 18},
   298  		{netip.AddrFrom4([4]byte{1, 2, 31, 255}), IP{1, 2, 0, 0}, 19},
   299  		{netip.AddrFrom4([4]byte{1, 2, 15, 255}), IP{1, 2, 0, 0}, 20},
   300  		{netip.AddrFrom4([4]byte{1, 2, 7, 255}), IP{1, 2, 0, 0}, 21},
   301  		{netip.AddrFrom4([4]byte{1, 2, 3, 255}), IP{1, 2, 0, 0}, 22},
   302  		{netip.AddrFrom4([4]byte{1, 2, 1, 255}), IP{1, 2, 0, 0}, 23},
   303  		{netip.AddrFrom4([4]byte{1, 2, 0, 255}), IP{1, 2, 0, 0}, 24},
   304  	}
   305  	for i, tt := range tests {
   306  		got := commonPrefixLen(tt.a, tt.b)
   307  		if got != tt.want {
   308  			t.Errorf("%d. commonPrefixLen(%s, %s) = %d; want %d", i, tt.a, tt.b, got, tt.want)
   309  		}
   310  	}
   311  
   312  }
   313  

View as plain text