gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/tcpip/tcpip_test.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package tcpip
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"io"
    21  	"net"
    22  	"testing"
    23  
    24  	"github.com/google/go-cmp/cmp"
    25  )
    26  
    27  func TestLimitedWriter_Write(t *testing.T) {
    28  	var b bytes.Buffer
    29  	l := LimitedWriter{
    30  		W: &b,
    31  		N: 5,
    32  	}
    33  	if n, err := l.Write([]byte{0, 1, 2}); err != nil {
    34  		t.Errorf("got l.Write(3/5) = (_, %s), want nil", err)
    35  	} else if n != 3 {
    36  		t.Errorf("got l.Write(3/5) = (%d, _), want 3", n)
    37  	}
    38  	if n, err := l.Write([]byte{3, 4, 5}); err != io.ErrShortWrite {
    39  		t.Errorf("got l.Write(3/2) = (_, %s), want io.ErrShortWrite", err)
    40  	} else if n != 2 {
    41  		t.Errorf("got l.Write(3/2) = (%d, _), want 2", n)
    42  	}
    43  	if l.N != 0 {
    44  		t.Errorf("got l.N = %d, want 0", l.N)
    45  	}
    46  	l.N = 1
    47  	if n, err := l.Write([]byte{5}); err != nil {
    48  		t.Errorf("got l.Write(1/1) = (_, %s), want nil", err)
    49  	} else if n != 1 {
    50  		t.Errorf("got l.Write(1/1) = (%d, _), want 1", n)
    51  	}
    52  	if diff := cmp.Diff(b.Bytes(), []byte{0, 1, 2, 3, 4, 5}); diff != "" {
    53  		t.Errorf("%T wrote incorrect data: (-want +got):\n%s", l, diff)
    54  	}
    55  }
    56  
    57  func TestSubnetContains(t *testing.T) {
    58  	tests := []struct {
    59  		s    string
    60  		m    string
    61  		a    string
    62  		want bool
    63  	}{
    64  		{"\xa0", "\xf0", "\x90", false},
    65  		{"\xa0", "\xf0", "\xa0", true},
    66  		{"\xa0", "\xf0", "\xa5", true},
    67  		{"\xa0", "\xf0", "\xaf", true},
    68  		{"\xa0", "\xf0", "\xb0", false},
    69  		{"\xa0", "\xf0", "", false},
    70  		{"\xc2\x80", "\xff\xf0", "\xc2\x80", true},
    71  		{"\xc2\x80", "\xff\xf0", "\xc2\x00", false},
    72  		{"\xc2\x00", "\xff\xf0", "\xc2\x00", true},
    73  		{"\xc2\x00", "\xff\xf0", "\xc2\x80", false},
    74  	}
    75  	for _, tt := range tests {
    76  		s, err := NewSubnet(AddrFromSlice(padTo4(tt.s)), MaskFromBytes(padTo4(tt.m)))
    77  		if err != nil {
    78  			t.Errorf("NewSubnet(%v, %v) = %v", tt.s, tt.m, err)
    79  			continue
    80  		}
    81  		if got := s.Contains(AddrFromSlice(padTo4(tt.a))); got != tt.want {
    82  			t.Errorf("Subnet(%v).Contains(%v) = %v, want %v", s, tt.a, got, tt.want)
    83  		}
    84  	}
    85  }
    86  
    87  func TestSubnetContainsDifferentLength(t *testing.T) {
    88  	s, err := NewSubnet(AddrFromSlice([]byte("\xa0\x00\x00\x00")), MaskFromBytes([]byte("\xf0\x00\x00\x00")))
    89  	if err != nil {
    90  		t.Fatalf("NewSubnet(a0::, f0::) = %v", err)
    91  	}
    92  	if got := s.Contains(AddrFrom16Slice([]byte("\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"))); got != false {
    93  		t.Fatalf("Subnet(%v).Contains(a0::) = %v, want %v", s, got, false)
    94  	}
    95  }
    96  
    97  func TestSubnetBits(t *testing.T) {
    98  	tests := []struct {
    99  		a     string
   100  		want1 int
   101  		want0 int
   102  	}{
   103  		{"\x00", 0, 32},
   104  		{"\x36", 0, 32},
   105  		{"\x5c", 0, 32},
   106  		{"\x5c\x5c", 0, 32},
   107  		{"\x5c\x36", 0, 32},
   108  		{"\x36\x5c", 0, 32},
   109  		{"\x36\x36", 0, 32},
   110  		{"\xff", 8, 24},
   111  		{"\xff\xff", 16, 16},
   112  	}
   113  	for _, tt := range tests {
   114  		s := &Subnet{mask: MaskFromBytes(padTo4(tt.a))}
   115  		got1, got0 := s.Bits()
   116  		if got1 != tt.want1 || got0 != tt.want0 {
   117  			t.Errorf("Subnet{mask: %x}.Bits() = %d, %d, want %d, %d", tt.a, got1, got0, tt.want1, tt.want0)
   118  		}
   119  	}
   120  }
   121  
   122  func TestSubnetPrefix(t *testing.T) {
   123  	tests := []struct {
   124  		a    string
   125  		want int
   126  	}{
   127  		{"\x00", 0},
   128  		{"\x00\x00", 0},
   129  		{"\x36", 0},
   130  		{"\x86", 1},
   131  		{"\xc5", 2},
   132  		{"\xff\x00", 8},
   133  		{"\xff\x36", 8},
   134  		{"\xff\x8c", 9},
   135  		{"\xff\xc8", 10},
   136  		{"\xff", 8},
   137  		{"\xff\xff", 16},
   138  	}
   139  	for _, tt := range tests {
   140  		s := &Subnet{mask: MaskFromBytes(padTo4(tt.a))}
   141  		got := s.Prefix()
   142  		if got != tt.want {
   143  			t.Errorf("Subnet{mask: %x}.Bits() = %d want %d", tt.a, got, tt.want)
   144  		}
   145  	}
   146  }
   147  
   148  func TestSubnetCreation(t *testing.T) {
   149  	tests := []struct {
   150  		a    string
   151  		m    string
   152  		want error
   153  	}{
   154  		{"\xa0", "\xf0", nil},
   155  		{"\xaa", "\xf0", errSubnetAddressMasked},
   156  		{"", "", nil},
   157  	}
   158  	for _, tt := range tests {
   159  		if _, err := NewSubnet(AddrFromSlice(padTo4(tt.a)), MaskFromBytes(padTo4(tt.m))); err != tt.want {
   160  			t.Errorf("NewSubnet(%v, %v) = %v, want %v", tt.a, tt.m, err, tt.want)
   161  		}
   162  	}
   163  }
   164  
   165  func TestSubnetCreationDifferentLength(t *testing.T) {
   166  	addr := []byte("\xa0\xa0\x00\x00")
   167  	mask := []byte("\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
   168  	if _, err := NewSubnet(AddrFromSlice(addr), MaskFromBytes(mask)); err != errSubnetLengthMismatch {
   169  		t.Errorf("NewSubnet(%v, %v) = %v, want %v", addr, mask, err, errSubnetLengthMismatch)
   170  	}
   171  }
   172  
   173  func TestAddressString(t *testing.T) {
   174  	for _, want := range []string{
   175  		// Taken from stdlib.
   176  		"2001:db8::123:12:1",
   177  		"2001:db8::1",
   178  		"2001:db8:0:1:0:1:0:1",
   179  		"2001:db8:1:0:1:0:1:0",
   180  		"2001::1:0:0:1",
   181  		"2001:db8:0:0:1::",
   182  		"2001:db8::1:0:0:1",
   183  		"2001:db8::a:b:c:d",
   184  
   185  		// Leading zeros.
   186  		"::1",
   187  		// Trailing zeros.
   188  		"8::",
   189  		// No zeros.
   190  		"1:1:1:1:1:1:1:1",
   191  		// Longer sequence is after other zeros, but not at the end.
   192  		"1:0:0:1::1",
   193  		// Longer sequence is at the beginning, shorter sequence is at
   194  		// the end.
   195  		"::1:1:1:0:0",
   196  		// Longer sequence is not at the beginning, shorter sequence is
   197  		// at the end.
   198  		"1::1:1:0:0",
   199  		// Longer sequence is at the beginning, shorter sequence is not
   200  		// at the end.
   201  		"::1:1:0:0:1",
   202  		// Neither sequence is at an end, longer is after shorter.
   203  		"1:0:0:1::1",
   204  		// Shorter sequence is at the beginning, longer sequence is not
   205  		// at the end.
   206  		"0:0:1:1::1",
   207  		// Shorter sequence is at the beginning, longer sequence is at
   208  		// the end.
   209  		"0:0:1:1:1::",
   210  		// Short sequences at both ends, longer one in the middle.
   211  		"0:1:1::1:1:0",
   212  		// Short sequences at both ends, longer one in the middle.
   213  		"0:1::1:0:0",
   214  		// Short sequences at both ends, longer one in the middle.
   215  		"0:0:1::1:0",
   216  		// Longer sequence surrounded by shorter sequences, but none at
   217  		// the end.
   218  		"1:0:1::1:0:1",
   219  	} {
   220  		addr := AddrFromSlice(net.ParseIP(want))
   221  		if got := addr.String(); got != want {
   222  			t.Errorf("Address(%x).String() = '%s', want = '%s'", addr, got, want)
   223  		}
   224  	}
   225  }
   226  
   227  func TestAddressWithPrefixSubnet(t *testing.T) {
   228  	tests := []struct {
   229  		addr       string
   230  		prefixLen  int
   231  		subnetAddr string
   232  		subnetMask string
   233  	}{
   234  		{"\xaa\x55\x33\x42", -1, "\x00\x00\x00\x00", "\x00\x00\x00\x00"},
   235  		{"\xaa\x55\x33\x42", 0, "\x00\x00\x00\x00", "\x00\x00\x00\x00"},
   236  		{"\xaa\x55\x33\x42", 1, "\x80\x00\x00\x00", "\x80\x00\x00\x00"},
   237  		{"\xaa\x55\x33\x42", 7, "\xaa\x00\x00\x00", "\xfe\x00\x00\x00"},
   238  		{"\xaa\x55\x33\x42", 8, "\xaa\x00\x00\x00", "\xff\x00\x00\x00"},
   239  		{"\xaa\x55\x33\x42", 24, "\xaa\x55\x33\x00", "\xff\xff\xff\x00"},
   240  		{"\xaa\x55\x33\x42", 31, "\xaa\x55\x33\x42", "\xff\xff\xff\xfe"},
   241  		{"\xaa\x55\x33\x42", 32, "\xaa\x55\x33\x42", "\xff\xff\xff\xff"},
   242  		{"\xaa\x55\x33\x42", 33, "\xaa\x55\x33\x42", "\xff\xff\xff\xff"},
   243  	}
   244  	for _, tt := range tests {
   245  		ap := AddressWithPrefix{Address: AddrFromSlice([]byte(tt.addr)), PrefixLen: tt.prefixLen}
   246  		gotSubnet := ap.Subnet()
   247  		wantSubnet, err := NewSubnet(AddrFromSlice([]byte(tt.subnetAddr)), MaskFromBytes([]byte(tt.subnetMask)))
   248  		if err != nil {
   249  			t.Errorf("NewSubnet(%q, %q) failed: %s", tt.subnetAddr, tt.subnetMask, err)
   250  			continue
   251  		}
   252  		if gotSubnet != wantSubnet {
   253  			t.Errorf("got subnet = %q, want = %q", gotSubnet, wantSubnet)
   254  		}
   255  	}
   256  }
   257  
   258  func TestAddressUnspecified(t *testing.T) {
   259  	tests := []struct {
   260  		addr        string
   261  		unspecified bool
   262  	}{
   263  		{
   264  			addr:        "",
   265  			unspecified: true,
   266  		},
   267  		{
   268  			addr:        "\x00",
   269  			unspecified: true,
   270  		},
   271  		{
   272  			addr:        "\x01",
   273  			unspecified: false,
   274  		},
   275  		{
   276  			addr:        "\x00\x00",
   277  			unspecified: true,
   278  		},
   279  		{
   280  			addr:        "\x01\x00",
   281  			unspecified: false,
   282  		},
   283  		{
   284  			addr:        "\x00\x01",
   285  			unspecified: false,
   286  		},
   287  		{
   288  			addr:        "\x01\x01",
   289  			unspecified: false,
   290  		},
   291  	}
   292  
   293  	for _, test := range tests {
   294  		t.Run(fmt.Sprintf("addr=%s", test.addr), func(t *testing.T) {
   295  			if got := AddrFromSlice(padTo4(test.addr)).Unspecified(); got != test.unspecified {
   296  				t.Fatalf("got addr.Unspecified() = %t, want = %t", got, test.unspecified)
   297  			}
   298  		})
   299  	}
   300  }
   301  
   302  func TestAddressMatchingPrefix(t *testing.T) {
   303  	tests := []struct {
   304  		addrA  string
   305  		addrB  string
   306  		prefix uint8
   307  	}{
   308  		{
   309  			addrA:  "\x01\x01",
   310  			addrB:  "\x01\x01",
   311  			prefix: 32,
   312  		},
   313  		{
   314  			addrA:  "\x01\x01",
   315  			addrB:  "\x01\x00",
   316  			prefix: 15,
   317  		},
   318  		{
   319  			addrA:  "\x01\x01",
   320  			addrB:  "\x81\x00",
   321  			prefix: 0,
   322  		},
   323  		{
   324  			addrA:  "\x01\x01",
   325  			addrB:  "\x01\x80",
   326  			prefix: 8,
   327  		},
   328  		{
   329  			addrA:  "\x01\x01",
   330  			addrB:  "\x02\x80",
   331  			prefix: 6,
   332  		},
   333  	}
   334  
   335  	for _, test := range tests {
   336  		if got := AddrFromSlice(padTo4(test.addrA)).MatchingPrefix(AddrFromSlice(padTo4(test.addrB))); got != test.prefix {
   337  			t.Errorf("got (%s).MatchingPrefix(%s) = %d, want = %d", test.addrA, test.addrB, got, test.prefix)
   338  		}
   339  	}
   340  }
   341  
   342  func padTo4(partial string) []byte {
   343  	for len(partial) < 4 {
   344  		partial += "\x00"
   345  	}
   346  	return []byte(partial)
   347  }