github.com/vishvananda/netlink@v1.3.1/xfrm_state_linux_test.go (about)

     1  package netlink
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"net"
     7  	"testing"
     8  	"time"
     9  )
    10  
    11  func TestXfrmStateAddGetDel(t *testing.T) {
    12  	for _, s := range []*XfrmState{
    13  		getBaseState(),
    14  		getAeadState(),
    15  		getBaseStateV6oV4(),
    16  		getBaseStateV4oV6(),
    17  	} {
    18  		testXfrmStateAddGetDel(t, s)
    19  	}
    20  }
    21  
    22  func testXfrmStateAddGetDel(t *testing.T, state *XfrmState) {
    23  	tearDown := setUpNetlinkTest(t)
    24  	defer tearDown()
    25  	if err := XfrmStateAdd(state); err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	states, err := XfrmStateList(FAMILY_ALL)
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  	if len(states) != 1 {
    33  		t.Fatal("State not added properly")
    34  	}
    35  
    36  	if !compareStates(state, &states[0]) {
    37  		t.Fatalf("unexpected states returned")
    38  	}
    39  
    40  	// Get specific state
    41  	sa, err := XfrmStateGet(state)
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  
    46  	if !compareStates(state, sa) {
    47  		t.Fatalf("unexpected state returned")
    48  	}
    49  
    50  	if err = XfrmStateDel(state); err != nil {
    51  		t.Fatal(err)
    52  	}
    53  
    54  	states, err = XfrmStateList(FAMILY_ALL)
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	if len(states) != 0 {
    59  		t.Fatal("State not removed properly")
    60  	}
    61  
    62  	if _, err := XfrmStateGet(state); err == nil {
    63  		t.Fatalf("Unexpected success")
    64  	}
    65  }
    66  
    67  func TestXfrmStateAllocSpi(t *testing.T) {
    68  	defer setUpNetlinkTest(t)()
    69  
    70  	state := getBaseState()
    71  	state.Spi = 0
    72  	state.Auth = nil
    73  	state.Crypt = nil
    74  	rstate, err := XfrmStateAllocSpi(state)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	if rstate.Spi == 0 {
    79  		t.Fatalf("SPI is not allocated")
    80  	}
    81  	rstate.Spi = 0
    82  
    83  	if !compareStates(state, rstate) {
    84  		t.Fatalf("State not properly allocated")
    85  	}
    86  }
    87  
    88  func TestXfrmStateFlush(t *testing.T) {
    89  	defer setUpNetlinkTest(t)()
    90  
    91  	state1 := getBaseState()
    92  	state2 := getBaseState()
    93  	state2.Src = net.ParseIP("127.1.0.1")
    94  	state2.Dst = net.ParseIP("127.1.0.2")
    95  	state2.Proto = XFRM_PROTO_AH
    96  	state2.Mode = XFRM_MODE_TUNNEL
    97  	state2.Spi = 20
    98  	state2.Mark = nil
    99  	state2.Crypt = nil
   100  
   101  	if err := XfrmStateAdd(state1); err != nil {
   102  		t.Fatal(err)
   103  	}
   104  	if err := XfrmStateAdd(state2); err != nil {
   105  		t.Fatal(err)
   106  	}
   107  
   108  	// flushing proto for which no state is present should return silently
   109  	if err := XfrmStateFlush(XFRM_PROTO_COMP); err != nil {
   110  		t.Fatal(err)
   111  	}
   112  
   113  	if err := XfrmStateFlush(XFRM_PROTO_AH); err != nil {
   114  		t.Fatal(err)
   115  	}
   116  
   117  	if _, err := XfrmStateGet(state2); err == nil {
   118  		t.Fatalf("Unexpected success")
   119  	}
   120  
   121  	if err := XfrmStateAdd(state2); err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	if err := XfrmStateFlush(0); err != nil {
   126  		t.Fatal(err)
   127  	}
   128  
   129  	states, err := XfrmStateList(FAMILY_ALL)
   130  	if err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	if len(states) != 0 {
   134  		t.Fatal("State not flushed properly")
   135  	}
   136  
   137  }
   138  
   139  func TestXfrmStateUpdateLimits(t *testing.T) {
   140  	defer setUpNetlinkTest(t)()
   141  
   142  	// Program state with limits
   143  	state := getBaseState()
   144  	state.Limits.TimeHard = 3600
   145  	state.Limits.TimeSoft = 60
   146  	state.Limits.PacketHard = 1000
   147  	state.Limits.PacketSoft = 50
   148  	state.Limits.ByteHard = 1000000
   149  	state.Limits.ByteSoft = 50000
   150  	state.Limits.TimeUseHard = 3000
   151  	state.Limits.TimeUseSoft = 1500
   152  	if err := XfrmStateAdd(state); err != nil {
   153  		t.Fatal(err)
   154  	}
   155  	// Verify limits
   156  	s, err := XfrmStateGet(state)
   157  	if err != nil {
   158  		t.Fatal(err)
   159  	}
   160  	if !compareLimits(state, s) {
   161  		t.Fatalf("Incorrect time hard/soft retrieved: %s", s.Print(true))
   162  	}
   163  
   164  	// Update limits
   165  	state.Limits.TimeHard = 1800
   166  	state.Limits.TimeSoft = 30
   167  	state.Limits.PacketHard = 500
   168  	state.Limits.PacketSoft = 25
   169  	state.Limits.ByteHard = 500000
   170  	state.Limits.ByteSoft = 25000
   171  	state.Limits.TimeUseHard = 2000
   172  	state.Limits.TimeUseSoft = 1000
   173  	if err := XfrmStateUpdate(state); err != nil {
   174  		t.Fatal(err)
   175  	}
   176  
   177  	// Verify new limits
   178  	s, err = XfrmStateGet(state)
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  	if s.Limits.TimeHard != 1800 || s.Limits.TimeSoft != 30 {
   183  		t.Fatalf("Incorrect time hard retrieved: (%d, %d)", s.Limits.TimeHard, s.Limits.TimeSoft)
   184  	}
   185  }
   186  
   187  func TestXfrmStateStats(t *testing.T) {
   188  	defer setUpNetlinkTest(t)()
   189  
   190  	// Program state and record time
   191  	state := getBaseState()
   192  	now := time.Now()
   193  	if err := XfrmStateAdd(state); err != nil {
   194  		t.Fatal(err)
   195  	}
   196  	// Retrieve state
   197  	s, err := XfrmStateGet(state)
   198  	if err != nil {
   199  		t.Fatal(err)
   200  	}
   201  	// Verify stats: We expect zero counters, same second add time and unset use time
   202  	if s.Statistics.Bytes != 0 || s.Statistics.Packets != 0 || s.Statistics.AddTime != uint64(now.Unix()) || s.Statistics.UseTime != 0 {
   203  		t.Fatalf("Unexpected statistics (addTime: %s) for state:\n%s", now.Format(time.UnixDate), s.Print(true))
   204  	}
   205  }
   206  
   207  func TestXfrmStateWithIfid(t *testing.T) {
   208  	minKernelRequired(t, 4, 19)
   209  	defer setUpNetlinkTest(t)()
   210  
   211  	state := getBaseState()
   212  	state.Ifid = 54321
   213  	if err := XfrmStateAdd(state); err != nil {
   214  		t.Fatal(err)
   215  	}
   216  	s, err := XfrmStateGet(state)
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	if !compareStates(state, s) {
   221  		t.Fatalf("unexpected state returned.\nExpected: %v.\nGot %v", state, s)
   222  	}
   223  	if err = XfrmStateDel(s); err != nil {
   224  		t.Fatal(err)
   225  	}
   226  }
   227  
   228  func TestXfrmStateWithSADir(t *testing.T) {
   229  	minKernelRequired(t, 4, 19)
   230  	defer setUpNetlinkTest(t)()
   231  
   232  	state := getBaseState()
   233  	state.SADir = XFRM_SA_DIR_IN
   234  	if err := XfrmStateAdd(state); err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	s, err := XfrmStateGet(state)
   238  	if err != nil {
   239  		t.Fatal(err)
   240  	}
   241  	if !compareStates(state, s) {
   242  		t.Fatalf("unexpected state returned.\nExpected: %v.\nGot %v", state, s)
   243  	}
   244  	if err = XfrmStateDel(s); err != nil {
   245  		t.Fatal(err)
   246  	}
   247  }
   248  
   249  func TestXfrmStateWithPcpunumWithoutSADir(t *testing.T) {
   250  	minKernelRequired(t, 4, 19)
   251  	defer setUpNetlinkTest(t)()
   252  
   253  	state := getBaseState()
   254  	pcpuNum := uint32(1)
   255  	state.Pcpunum = &pcpuNum
   256  	if err := XfrmStateAdd(state); err != nil {
   257  		t.Fatal(err)
   258  	}
   259  	s, err := XfrmStateGet(state)
   260  	if err != nil {
   261  		t.Fatal(err)
   262  	}
   263  	if !compareStates(state, s) {
   264  		t.Fatalf("unexpected state returned.\nExpected: %v.\nGot %v", state, s)
   265  	}
   266  	if err = XfrmStateDel(s); err != nil {
   267  		t.Fatal(err)
   268  	}
   269  }
   270  
   271  func TestXfrmStateWithPcpunumWithSADir(t *testing.T) {
   272  	minKernelRequired(t, 4, 19)
   273  	defer setUpNetlinkTest(t)()
   274  
   275  	state := getBaseState()
   276  	state.SADir = XFRM_SA_DIR_IN
   277  	pcpuNum := uint32(1)
   278  	state.Pcpunum = &pcpuNum
   279  	if err := XfrmStateAdd(state); err != nil {
   280  		t.Fatal(err)
   281  	}
   282  	s, err := XfrmStateGet(state)
   283  	if err != nil {
   284  		t.Fatal(err)
   285  	}
   286  	if !compareStates(state, s) {
   287  		t.Fatalf("unexpected state returned.\nExpected: %v.\nGot %v", state, s)
   288  	}
   289  	if err = XfrmStateDel(s); err != nil {
   290  		t.Fatal(err)
   291  	}
   292  }
   293  
   294  func TestXfrmStateWithOutputMark(t *testing.T) {
   295  	minKernelRequired(t, 4, 14)
   296  	defer setUpNetlinkTest(t)()
   297  
   298  	state := getBaseState()
   299  	state.OutputMark = &XfrmMark{
   300  		Value: 0x0000000a,
   301  	}
   302  	if err := XfrmStateAdd(state); err != nil {
   303  		t.Fatal(err)
   304  	}
   305  	s, err := XfrmStateGet(state)
   306  	if err != nil {
   307  		t.Fatal(err)
   308  	}
   309  	if !compareStates(state, s) {
   310  		t.Fatalf("unexpected state returned.\nExpected: %v.\nGot %v", state, s)
   311  	}
   312  	if err = XfrmStateDel(s); err != nil {
   313  		t.Fatal(err)
   314  	}
   315  }
   316  
   317  func TestXfrmStateWithOutputMarkAndMask(t *testing.T) {
   318  	minKernelRequired(t, 4, 19)
   319  	defer setUpNetlinkTest(t)()
   320  
   321  	state := getBaseState()
   322  	state.OutputMark = &XfrmMark{
   323  		Value: 0x0000000a,
   324  		Mask:  0x0000000f,
   325  	}
   326  	if err := XfrmStateAdd(state); err != nil {
   327  		t.Fatal(err)
   328  	}
   329  	s, err := XfrmStateGet(state)
   330  	if err != nil {
   331  		t.Fatal(err)
   332  	}
   333  	if !compareStates(state, s) {
   334  		t.Fatalf("unexpected state returned.\nExpected: %v.\nGot %v", state, s)
   335  	}
   336  	if err = XfrmStateDel(s); err != nil {
   337  		t.Fatal(err)
   338  	}
   339  }
   340  func genStateSelectorForV6Payload() *XfrmPolicy {
   341  	_, wildcardV6Net, _ := net.ParseCIDR("::/0")
   342  	return &XfrmPolicy{
   343  		Src: wildcardV6Net,
   344  		Dst: wildcardV6Net,
   345  	}
   346  }
   347  
   348  func genStateSelectorForV4Payload() *XfrmPolicy {
   349  	_, wildcardV4Net, _ := net.ParseCIDR("0.0.0.0/0")
   350  	return &XfrmPolicy{
   351  		Src: wildcardV4Net,
   352  		Dst: wildcardV4Net,
   353  	}
   354  }
   355  
   356  func getBaseState() *XfrmState {
   357  	return &XfrmState{
   358  		// Force 4 byte notation for the IPv4 addresses
   359  		Src:   net.ParseIP("127.0.0.1").To4(),
   360  		Dst:   net.ParseIP("127.0.0.2").To4(),
   361  		Proto: XFRM_PROTO_ESP,
   362  		Mode:  XFRM_MODE_TUNNEL,
   363  		Spi:   1,
   364  		Auth: &XfrmStateAlgo{
   365  			Name: "hmac(sha256)",
   366  			Key:  []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
   367  		},
   368  		Crypt: &XfrmStateAlgo{
   369  			Name: "cbc(aes)",
   370  			Key:  []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
   371  		},
   372  		Mark: &XfrmMark{
   373  			Value: 0x12340000,
   374  			Mask:  0xffff0000,
   375  		},
   376  	}
   377  }
   378  
   379  func getBaseStateV4oV6() *XfrmState {
   380  	return &XfrmState{
   381  		// Force 4 byte notation for the IPv4 addressesd
   382  		Src:   net.ParseIP("2001:dead::1").To16(),
   383  		Dst:   net.ParseIP("2001:beef::1").To16(),
   384  		Proto: XFRM_PROTO_ESP,
   385  		Mode:  XFRM_MODE_TUNNEL,
   386  		Spi:   1,
   387  		Auth: &XfrmStateAlgo{
   388  			Name: "hmac(sha256)",
   389  			Key:  []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
   390  		},
   391  		Crypt: &XfrmStateAlgo{
   392  			Name: "cbc(aes)",
   393  			Key:  []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
   394  		},
   395  		Mark: &XfrmMark{
   396  			Value: 0x12340000,
   397  			Mask:  0xffff0000,
   398  		},
   399  		Selector: genStateSelectorForV4Payload(),
   400  	}
   401  }
   402  
   403  func getBaseStateV6oV4() *XfrmState {
   404  	return &XfrmState{
   405  		// Force 4 byte notation for the IPv4 addressesd
   406  		Src:   net.ParseIP("192.168.1.1").To4(),
   407  		Dst:   net.ParseIP("192.168.2.2").To4(),
   408  		Proto: XFRM_PROTO_ESP,
   409  		Mode:  XFRM_MODE_TUNNEL,
   410  		Spi:   1,
   411  		Auth: &XfrmStateAlgo{
   412  			Name: "hmac(sha256)",
   413  			Key:  []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
   414  		},
   415  		Crypt: &XfrmStateAlgo{
   416  			Name: "cbc(aes)",
   417  			Key:  []byte("abcdefghijklmnopqrstuvwzyzABCDEF"),
   418  		},
   419  		Mark: &XfrmMark{
   420  			Value: 0x12340000,
   421  			Mask:  0xffff0000,
   422  		},
   423  		Selector: genStateSelectorForV6Payload(),
   424  	}
   425  }
   426  
   427  func getAeadState() *XfrmState {
   428  	// 128 key bits + 32 salt bits
   429  	k, _ := hex.DecodeString("d0562776bf0e75830ba3f7f8eb6c09b555aa1177")
   430  	return &XfrmState{
   431  		// Leave IPv4 addresses in Ipv4 in IPv6 notation
   432  		Src:   net.ParseIP("192.168.1.1"),
   433  		Dst:   net.ParseIP("192.168.2.2"),
   434  		Proto: XFRM_PROTO_ESP,
   435  		Mode:  XFRM_MODE_TUNNEL,
   436  		Spi:   2,
   437  		Aead: &XfrmStateAlgo{
   438  			Name:   "rfc4106(gcm(aes))",
   439  			Key:    k,
   440  			ICVLen: 64,
   441  		},
   442  	}
   443  }
   444  func compareSelector(a, b *XfrmPolicy) bool {
   445  	return a.Src.String() == b.Src.String() &&
   446  		a.Dst.String() == b.Dst.String() &&
   447  		a.Proto == b.Proto &&
   448  		a.DstPort == b.DstPort &&
   449  		a.SrcPort == b.SrcPort &&
   450  		a.Ifindex == b.Ifindex
   451  }
   452  
   453  func compareStates(a, b *XfrmState) bool {
   454  	if a == b {
   455  		return true
   456  	}
   457  	if a == nil || b == nil {
   458  		return false
   459  	}
   460  	if a.Selector != nil && b.Selector != nil {
   461  		if !compareSelector(a.Selector, b.Selector) {
   462  			return false
   463  		}
   464  	}
   465  
   466  	return a.Src.Equal(b.Src) && a.Dst.Equal(b.Dst) &&
   467  		a.Mode == b.Mode && a.Spi == b.Spi && a.Proto == b.Proto &&
   468  		a.Ifid == b.Ifid &&
   469  		compareAlgo(a.Auth, b.Auth) &&
   470  		compareAlgo(a.Crypt, b.Crypt) &&
   471  		compareAlgo(a.Aead, b.Aead) &&
   472  		compareMarks(a.Mark, b.Mark) &&
   473  		compareMarks(a.OutputMark, b.OutputMark)
   474  
   475  }
   476  
   477  func compareLimits(a, b *XfrmState) bool {
   478  	return a.Limits.TimeHard == b.Limits.TimeHard &&
   479  		a.Limits.TimeSoft == b.Limits.TimeSoft &&
   480  		a.Limits.PacketHard == b.Limits.PacketHard &&
   481  		a.Limits.PacketSoft == b.Limits.PacketSoft &&
   482  		a.Limits.ByteHard == b.Limits.ByteHard &&
   483  		a.Limits.ByteSoft == b.Limits.ByteSoft &&
   484  		a.Limits.TimeUseHard == b.Limits.TimeUseHard &&
   485  		a.Limits.TimeUseSoft == b.Limits.TimeUseSoft
   486  }
   487  
   488  func compareAlgo(a, b *XfrmStateAlgo) bool {
   489  	if a == b {
   490  		return true
   491  	}
   492  	if a == nil || b == nil {
   493  		return false
   494  	}
   495  	return a.Name == b.Name && bytes.Equal(a.Key, b.Key) &&
   496  		(a.TruncateLen == 0 || a.TruncateLen == b.TruncateLen) &&
   497  		(a.ICVLen == 0 || a.ICVLen == b.ICVLen)
   498  }
   499  
   500  func compareMarks(a, b *XfrmMark) bool {
   501  	if a == b {
   502  		return true
   503  	}
   504  	if a == nil || b == nil {
   505  		return false
   506  	}
   507  	return a.Value == b.Value && a.Mask == b.Mask
   508  }