github.com/vpnishe/netstack@v1.10.6/tcpip/header/ndp_test.go (about)

     1  // Copyright 2019 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 header
    16  
    17  import (
    18  	"bytes"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/vpnishe/netstack/tcpip"
    23  )
    24  
    25  // TestNDPNeighborSolicit tests the functions of NDPNeighborSolicit.
    26  func TestNDPNeighborSolicit(t *testing.T) {
    27  	b := []byte{
    28  		0, 0, 0, 0,
    29  		1, 2, 3, 4,
    30  		5, 6, 7, 8,
    31  		9, 10, 11, 12,
    32  		13, 14, 15, 16,
    33  	}
    34  
    35  	// Test getting the Target Address.
    36  	ns := NDPNeighborSolicit(b)
    37  	addr := tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10")
    38  	if got := ns.TargetAddress(); got != addr {
    39  		t.Errorf("got ns.TargetAddress = %s, want %s", got, addr)
    40  	}
    41  
    42  	// Test updating the Target Address.
    43  	addr2 := tcpip.Address("\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x11")
    44  	ns.SetTargetAddress(addr2)
    45  	if got := ns.TargetAddress(); got != addr2 {
    46  		t.Errorf("got ns.TargetAddress = %s, want %s", got, addr2)
    47  	}
    48  	// Make sure the address got updated in the backing buffer.
    49  	if got := tcpip.Address(b[ndpNSTargetAddessOffset:][:IPv6AddressSize]); got != addr2 {
    50  		t.Errorf("got targetaddress buffer = %s, want %s", got, addr2)
    51  	}
    52  }
    53  
    54  // TestNDPNeighborAdvert tests the functions of NDPNeighborAdvert.
    55  func TestNDPNeighborAdvert(t *testing.T) {
    56  	b := []byte{
    57  		160, 0, 0, 0,
    58  		1, 2, 3, 4,
    59  		5, 6, 7, 8,
    60  		9, 10, 11, 12,
    61  		13, 14, 15, 16,
    62  	}
    63  
    64  	// Test getting the Target Address.
    65  	na := NDPNeighborAdvert(b)
    66  	addr := tcpip.Address("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10")
    67  	if got := na.TargetAddress(); got != addr {
    68  		t.Errorf("got TargetAddress = %s, want %s", got, addr)
    69  	}
    70  
    71  	// Test getting the Router Flag.
    72  	if got := na.RouterFlag(); !got {
    73  		t.Errorf("got RouterFlag = false, want = true")
    74  	}
    75  
    76  	// Test getting the Solicited Flag.
    77  	if got := na.SolicitedFlag(); got {
    78  		t.Errorf("got SolicitedFlag = true, want = false")
    79  	}
    80  
    81  	// Test getting the Override Flag.
    82  	if got := na.OverrideFlag(); !got {
    83  		t.Errorf("got OverrideFlag = false, want = true")
    84  	}
    85  
    86  	// Test updating the Target Address.
    87  	addr2 := tcpip.Address("\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x11")
    88  	na.SetTargetAddress(addr2)
    89  	if got := na.TargetAddress(); got != addr2 {
    90  		t.Errorf("got TargetAddress = %s, want %s", got, addr2)
    91  	}
    92  	// Make sure the address got updated in the backing buffer.
    93  	if got := tcpip.Address(b[ndpNATargetAddressOffset:][:IPv6AddressSize]); got != addr2 {
    94  		t.Errorf("got targetaddress buffer = %s, want %s", got, addr2)
    95  	}
    96  
    97  	// Test updating the Router Flag.
    98  	na.SetRouterFlag(false)
    99  	if got := na.RouterFlag(); got {
   100  		t.Errorf("got RouterFlag = true, want = false")
   101  	}
   102  
   103  	// Test updating the Solicited Flag.
   104  	na.SetSolicitedFlag(true)
   105  	if got := na.SolicitedFlag(); !got {
   106  		t.Errorf("got SolicitedFlag = false, want = true")
   107  	}
   108  
   109  	// Test updating the Override Flag.
   110  	na.SetOverrideFlag(false)
   111  	if got := na.OverrideFlag(); got {
   112  		t.Errorf("got OverrideFlag = true, want = false")
   113  	}
   114  
   115  	// Make sure flags got updated in the backing buffer.
   116  	if got := b[ndpNAFlagsOffset]; got != 64 {
   117  		t.Errorf("got flags byte = %d, want = 64")
   118  	}
   119  }
   120  
   121  func TestNDPRouterAdvert(t *testing.T) {
   122  	b := []byte{
   123  		64, 128, 1, 2,
   124  		3, 4, 5, 6,
   125  		7, 8, 9, 10,
   126  	}
   127  
   128  	ra := NDPRouterAdvert(b)
   129  
   130  	if got := ra.CurrHopLimit(); got != 64 {
   131  		t.Errorf("got ra.CurrHopLimit = %d, want = 64", got)
   132  	}
   133  
   134  	if got := ra.ManagedAddrConfFlag(); !got {
   135  		t.Errorf("got ManagedAddrConfFlag = false, want = true")
   136  	}
   137  
   138  	if got := ra.OtherConfFlag(); got {
   139  		t.Errorf("got OtherConfFlag = true, want = false")
   140  	}
   141  
   142  	if got, want := ra.RouterLifetime(), time.Second*258; got != want {
   143  		t.Errorf("got ra.RouterLifetime = %d, want = %d", got, want)
   144  	}
   145  
   146  	if got, want := ra.ReachableTime(), time.Millisecond*50595078; got != want {
   147  		t.Errorf("got ra.ReachableTime = %d, want = %d", got, want)
   148  	}
   149  
   150  	if got, want := ra.RetransTimer(), time.Millisecond*117967114; got != want {
   151  		t.Errorf("got ra.RetransTimer = %d, want = %d", got, want)
   152  	}
   153  }
   154  
   155  // TestNDPTargetLinkLayerAddressOptionEthernetAddress tests getting the
   156  // Ethernet address from an NDPTargetLinkLayerAddressOption.
   157  func TestNDPTargetLinkLayerAddressOptionEthernetAddress(t *testing.T) {
   158  	tests := []struct {
   159  		name     string
   160  		buf      []byte
   161  		expected tcpip.LinkAddress
   162  	}{
   163  		{
   164  			"ValidMAC",
   165  			[]byte{1, 2, 3, 4, 5, 6},
   166  			tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06"),
   167  		},
   168  		{
   169  			"TLLBodyTooShort",
   170  			[]byte{1, 2, 3, 4, 5},
   171  			tcpip.LinkAddress([]byte(nil)),
   172  		},
   173  		{
   174  			"TLLBodyLargerThanNeeded",
   175  			[]byte{1, 2, 3, 4, 5, 6, 7, 8},
   176  			tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06"),
   177  		},
   178  	}
   179  
   180  	for _, test := range tests {
   181  		t.Run(test.name, func(t *testing.T) {
   182  			tll := NDPTargetLinkLayerAddressOption(test.buf)
   183  			if got := tll.EthernetAddress(); got != test.expected {
   184  				t.Errorf("got tll.EthernetAddress = %s, want = %s", got, test.expected)
   185  			}
   186  		})
   187  	}
   188  
   189  }
   190  
   191  // TestNDPTargetLinkLayerAddressOptionSerialize tests serializing a
   192  // NDPTargetLinkLayerAddressOption.
   193  func TestNDPTargetLinkLayerAddressOptionSerialize(t *testing.T) {
   194  	tests := []struct {
   195  		name        string
   196  		buf         []byte
   197  		expectedBuf []byte
   198  		addr        tcpip.LinkAddress
   199  	}{
   200  		{
   201  			"Ethernet",
   202  			make([]byte, 8),
   203  			[]byte{2, 1, 1, 2, 3, 4, 5, 6},
   204  			"\x01\x02\x03\x04\x05\x06",
   205  		},
   206  		{
   207  			"Padding",
   208  			[]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
   209  			[]byte{2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0},
   210  			"\x01\x02\x03\x04\x05\x06\x07\x08",
   211  		},
   212  		{
   213  			"Empty",
   214  			[]byte{},
   215  			[]byte{},
   216  			"",
   217  		},
   218  	}
   219  
   220  	for _, test := range tests {
   221  		t.Run(test.name, func(t *testing.T) {
   222  			opts := NDPOptions(test.buf)
   223  			serializer := NDPOptionsSerializer{
   224  				NDPTargetLinkLayerAddressOption(test.addr),
   225  			}
   226  			if got, want := int(serializer.Length()), len(test.expectedBuf); got != want {
   227  				t.Fatalf("got Length = %d, want = %d", got, want)
   228  			}
   229  			opts.Serialize(serializer)
   230  			if !bytes.Equal(test.buf, test.expectedBuf) {
   231  				t.Fatalf("got b = %d, want = %d", test.buf, test.expectedBuf)
   232  			}
   233  
   234  			it, err := opts.Iter(true)
   235  			if err != nil {
   236  				t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
   237  			}
   238  
   239  			if len(test.expectedBuf) > 0 {
   240  				next, done, err := it.Next()
   241  				if err != nil {
   242  					t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
   243  				}
   244  				if done {
   245  					t.Fatal("got Next = (_, true, _), want = (_, false, _)")
   246  				}
   247  				if got := next.Type(); got != NDPTargetLinkLayerAddressOptionType {
   248  					t.Fatalf("got Type %= %d, want = %d", got, NDPTargetLinkLayerAddressOptionType)
   249  				}
   250  				tll := next.(NDPTargetLinkLayerAddressOption)
   251  				if got, want := []byte(tll), test.expectedBuf[2:]; !bytes.Equal(got, want) {
   252  					t.Fatalf("got Next = (%x, _, _), want = (%x, _, _)", got, want)
   253  				}
   254  
   255  				if got, want := tll.EthernetAddress(), tcpip.LinkAddress(test.expectedBuf[2:][:EthernetAddressSize]); got != want {
   256  					t.Errorf("got tll.MACAddress = %s, want = %s", got, want)
   257  				}
   258  			}
   259  
   260  			// Iterator should not return anything else.
   261  			next, done, err := it.Next()
   262  			if err != nil {
   263  				t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
   264  			}
   265  			if !done {
   266  				t.Error("got Next = (_, false, _), want = (_, true, _)")
   267  			}
   268  			if next != nil {
   269  				t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
   270  			}
   271  		})
   272  	}
   273  }
   274  
   275  // TestNDPPrefixInformationOption tests the field getters and serialization of a
   276  // NDPPrefixInformation.
   277  func TestNDPPrefixInformationOption(t *testing.T) {
   278  	b := []byte{
   279  		43, 127,
   280  		1, 2, 3, 4,
   281  		5, 6, 7, 8,
   282  		5, 5, 5, 5,
   283  		9, 10, 11, 12,
   284  		13, 14, 15, 16,
   285  		17, 18, 19, 20,
   286  		21, 22, 23, 24,
   287  	}
   288  
   289  	targetBuf := []byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
   290  	opts := NDPOptions(targetBuf)
   291  	serializer := NDPOptionsSerializer{
   292  		NDPPrefixInformation(b),
   293  	}
   294  	opts.Serialize(serializer)
   295  	expectedBuf := []byte{
   296  		3, 4, 43, 64,
   297  		1, 2, 3, 4,
   298  		5, 6, 7, 8,
   299  		0, 0, 0, 0,
   300  		9, 10, 11, 12,
   301  		13, 14, 15, 16,
   302  		17, 18, 19, 20,
   303  		21, 22, 23, 24,
   304  	}
   305  	if !bytes.Equal(targetBuf, expectedBuf) {
   306  		t.Fatalf("got targetBuf = %x, want = %x", targetBuf, expectedBuf)
   307  	}
   308  
   309  	it, err := opts.Iter(true)
   310  	if err != nil {
   311  		t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
   312  	}
   313  
   314  	next, done, err := it.Next()
   315  	if err != nil {
   316  		t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
   317  	}
   318  	if done {
   319  		t.Fatal("got Next = (_, true, _), want = (_, false, _)")
   320  	}
   321  	if got := next.Type(); got != NDPPrefixInformationType {
   322  		t.Errorf("got Type = %d, want = %d", got, NDPPrefixInformationType)
   323  	}
   324  
   325  	pi := next.(NDPPrefixInformation)
   326  
   327  	if got := pi.Type(); got != 3 {
   328  		t.Errorf("got Type = %d, want = 3", got)
   329  	}
   330  
   331  	if got := pi.Length(); got != 30 {
   332  		t.Errorf("got Length = %d, want = 30", got)
   333  	}
   334  
   335  	if got := pi.PrefixLength(); got != 43 {
   336  		t.Errorf("got PrefixLength = %d, want = 43", got)
   337  	}
   338  
   339  	if pi.OnLinkFlag() {
   340  		t.Error("got OnLinkFlag = true, want = false")
   341  	}
   342  
   343  	if !pi.AutonomousAddressConfigurationFlag() {
   344  		t.Error("got AutonomousAddressConfigurationFlag = false, want = true")
   345  	}
   346  
   347  	if got, want := pi.ValidLifetime(), 16909060*time.Second; got != want {
   348  		t.Errorf("got ValidLifetime = %d, want = %d", got, want)
   349  	}
   350  
   351  	if got, want := pi.PreferredLifetime(), 84281096*time.Second; got != want {
   352  		t.Errorf("got PreferredLifetime = %d, want = %d", got, want)
   353  	}
   354  
   355  	if got, want := pi.Prefix(), tcpip.Address("\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18"); got != want {
   356  		t.Errorf("got Prefix = %s, want = %s", got, want)
   357  	}
   358  
   359  	// Iterator should not return anything else.
   360  	next, done, err = it.Next()
   361  	if err != nil {
   362  		t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
   363  	}
   364  	if !done {
   365  		t.Error("got Next = (_, false, _), want = (_, true, _)")
   366  	}
   367  	if next != nil {
   368  		t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
   369  	}
   370  }
   371  
   372  // TestNDPOptionsIterCheck tests that Iter will return false if the NDPOptions
   373  // the iterator was returned for is malformed.
   374  func TestNDPOptionsIterCheck(t *testing.T) {
   375  	tests := []struct {
   376  		name     string
   377  		buf      []byte
   378  		expected error
   379  	}{
   380  		{
   381  			"ZeroLengthField",
   382  			[]byte{0, 0, 0, 0, 0, 0, 0, 0},
   383  			ErrNDPOptZeroLength,
   384  		},
   385  		{
   386  			"ValidTargetLinkLayerAddressOption",
   387  			[]byte{2, 1, 1, 2, 3, 4, 5, 6},
   388  			nil,
   389  		},
   390  		{
   391  			"TooSmallTargetLinkLayerAddressOption",
   392  			[]byte{2, 1, 1, 2, 3, 4, 5},
   393  			ErrNDPOptBufExhausted,
   394  		},
   395  		{
   396  			"ValidPrefixInformation",
   397  			[]byte{
   398  				3, 4, 43, 64,
   399  				1, 2, 3, 4,
   400  				5, 6, 7, 8,
   401  				0, 0, 0, 0,
   402  				9, 10, 11, 12,
   403  				13, 14, 15, 16,
   404  				17, 18, 19, 20,
   405  				21, 22, 23, 24,
   406  			},
   407  			nil,
   408  		},
   409  		{
   410  			"TooSmallPrefixInformation",
   411  			[]byte{
   412  				3, 4, 43, 64,
   413  				1, 2, 3, 4,
   414  				5, 6, 7, 8,
   415  				0, 0, 0, 0,
   416  				9, 10, 11, 12,
   417  				13, 14, 15, 16,
   418  				17, 18, 19, 20,
   419  				21, 22, 23,
   420  			},
   421  			ErrNDPOptBufExhausted,
   422  		},
   423  		{
   424  			"InvalidPrefixInformationLength",
   425  			[]byte{
   426  				3, 3, 43, 64,
   427  				1, 2, 3, 4,
   428  				5, 6, 7, 8,
   429  				0, 0, 0, 0,
   430  				9, 10, 11, 12,
   431  				13, 14, 15, 16,
   432  			},
   433  			ErrNDPOptMalformedBody,
   434  		},
   435  		{
   436  			"ValidTargetLinkLayerAddressWithPrefixInformation",
   437  			[]byte{
   438  				// Target Link-Layer Address.
   439  				2, 1, 1, 2, 3, 4, 5, 6,
   440  
   441  				// Prefix information.
   442  				3, 4, 43, 64,
   443  				1, 2, 3, 4,
   444  				5, 6, 7, 8,
   445  				0, 0, 0, 0,
   446  				9, 10, 11, 12,
   447  				13, 14, 15, 16,
   448  				17, 18, 19, 20,
   449  				21, 22, 23, 24,
   450  			},
   451  			nil,
   452  		},
   453  		{
   454  			"ValidTargetLinkLayerAddressWithPrefixInformationWithUnrecognized",
   455  			[]byte{
   456  				// Target Link-Layer Address.
   457  				2, 1, 1, 2, 3, 4, 5, 6,
   458  
   459  				// 255 is an unrecognized type. If 255 ends up
   460  				// being the type for some recognized type,
   461  				// update 255 to some other unrecognized value.
   462  				255, 2, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8,
   463  
   464  				// Prefix information.
   465  				3, 4, 43, 64,
   466  				1, 2, 3, 4,
   467  				5, 6, 7, 8,
   468  				0, 0, 0, 0,
   469  				9, 10, 11, 12,
   470  				13, 14, 15, 16,
   471  				17, 18, 19, 20,
   472  				21, 22, 23, 24,
   473  			},
   474  			nil,
   475  		},
   476  	}
   477  
   478  	for _, test := range tests {
   479  		t.Run(test.name, func(t *testing.T) {
   480  			opts := NDPOptions(test.buf)
   481  
   482  			if _, err := opts.Iter(true); err != test.expected {
   483  				t.Fatalf("got Iter(true) = (_, %v), want = (_, %v)", err, test.expected)
   484  			}
   485  
   486  			// test.buf may be malformed but we chose not to check
   487  			// the iterator so it must return true.
   488  			if _, err := opts.Iter(false); err != nil {
   489  				t.Fatalf("got Iter(false) = (_, %s), want = (_, nil)", err)
   490  			}
   491  		})
   492  	}
   493  }
   494  
   495  // TestNDPOptionsIter tests that we can iterator over a valid NDPOptions. Note,
   496  // this test does not actually check any of the option's getters, it simply
   497  // checks the option Type and Body. We have other tests that tests the option
   498  // field gettings given an option body and don't need to duplicate those tests
   499  // here.
   500  func TestNDPOptionsIter(t *testing.T) {
   501  	buf := []byte{
   502  		// Target Link-Layer Address.
   503  		2, 1, 1, 2, 3, 4, 5, 6,
   504  
   505  		// 255 is an unrecognized type. If 255 ends up being the type
   506  		// for some recognized type, update 255 to some other
   507  		// unrecognized value. Note, this option should be skipped when
   508  		// iterating.
   509  		255, 2, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8,
   510  
   511  		// Prefix information.
   512  		3, 4, 43, 64,
   513  		1, 2, 3, 4,
   514  		5, 6, 7, 8,
   515  		0, 0, 0, 0,
   516  		9, 10, 11, 12,
   517  		13, 14, 15, 16,
   518  		17, 18, 19, 20,
   519  		21, 22, 23, 24,
   520  	}
   521  
   522  	opts := NDPOptions(buf)
   523  	it, err := opts.Iter(true)
   524  	if err != nil {
   525  		t.Fatalf("got Iter = (_, %s), want = (_, nil)", err)
   526  	}
   527  
   528  	// Test the first (Taret Link-Layer) option.
   529  	next, done, err := it.Next()
   530  	if err != nil {
   531  		t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
   532  	}
   533  	if done {
   534  		t.Fatal("got Next = (_, true, _), want = (_, false, _)")
   535  	}
   536  	if got, want := []byte(next.(NDPTargetLinkLayerAddressOption)), buf[2:][:6]; !bytes.Equal(got, want) {
   537  		t.Errorf("got Next = (%x, _, _), want = (%x, _, _)", got, want)
   538  	}
   539  	if got := next.Type(); got != NDPTargetLinkLayerAddressOptionType {
   540  		t.Errorf("got Type = %d, want = %d", got, NDPTargetLinkLayerAddressOptionType)
   541  	}
   542  
   543  	// Test the next (Prefix Information) option.
   544  	// Note, the unrecognized option should be skipped.
   545  	next, done, err = it.Next()
   546  	if err != nil {
   547  		t.Fatalf("got Next = (_, _, %s), want = (_, _, nil)", err)
   548  	}
   549  	if done {
   550  		t.Fatal("got Next = (_, true, _), want = (_, false, _)")
   551  	}
   552  	if got, want := next.(NDPPrefixInformation), buf[26:][:30]; !bytes.Equal(got, want) {
   553  		t.Errorf("got Next = (%x, _, _), want = (%x, _, _)", got, want)
   554  	}
   555  	if got := next.Type(); got != NDPPrefixInformationType {
   556  		t.Errorf("got Type = %d, want = %d", got, NDPPrefixInformationType)
   557  	}
   558  
   559  	// Iterator should not return anything else.
   560  	next, done, err = it.Next()
   561  	if err != nil {
   562  		t.Errorf("got Next = (_, _, %s), want = (_, _, nil)", err)
   563  	}
   564  	if !done {
   565  		t.Error("got Next = (_, false, _), want = (_, true, _)")
   566  	}
   567  	if next != nil {
   568  		t.Errorf("got Next = (%x, _, _), want = (nil, _, _)", next)
   569  	}
   570  }