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 }