github.com/cilium/cilium@v1.16.2/bpf/tests/ipsec_from_network_generic.h (about)

     1  /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
     2  /* Copyright Authors of Cilium */
     3  
     4  #define NODE_ID 2333
     5  #define ENCRYPT_KEY 3
     6  #define ENABLE_IPV4
     7  #define ENABLE_IPV6
     8  #define ENABLE_IPSEC
     9  #define TUNNEL_MODE
    10  #define ENCAP_IFINDEX 4
    11  #define DEST_IFINDEX 5
    12  #define DEST_LXC_ID 200
    13  
    14  #include "common.h"
    15  #include <bpf/ctx/skb.h>
    16  #include "pktgen.h"
    17  #define ROUTER_IP
    18  #define SECLABEL
    19  #define SECLABEL_IPV4
    20  #define SECLABEL_IPV6
    21  #undef ROUTER_IP
    22  #undef SECLABEL
    23  #undef SECLABEL_IPV4
    24  #undef SECLABEL_IPV6
    25  
    26  #define ctx_redirect mock_ctx_redirect
    27  int mock_ctx_redirect(const struct __sk_buff *ctx __maybe_unused, int ifindex, __u32 flags)
    28  {
    29  	if (ifindex != 1)
    30  		return -1;
    31  	if (flags != 0)
    32  		return -2;
    33  	return CTX_ACT_REDIRECT;
    34  }
    35  
    36  #define skb_change_type mock_skb_change_type
    37  int mock_skb_change_type(__maybe_unused struct __sk_buff *skb, __u32 type)
    38  {
    39  	if (type != PACKET_HOST)
    40  		return -1;
    41  	return 0;
    42  }
    43  
    44  static volatile const __u8 *DEST_EP_MAC = mac_three;
    45  static volatile const __u8 *DEST_NODE_MAC = mac_four;
    46  
    47  #include "bpf_network.c"
    48  
    49  #include "lib/endpoint.h"
    50  #include "lib/node.h"
    51  
    52  #define FROM_NETWORK 0
    53  #define ESP_SEQUENCE 69865
    54  
    55  struct {
    56  	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    57  	__uint(key_size, sizeof(__u32));
    58  	__uint(max_entries, 1);
    59  	__array(values, int());
    60  } entry_call_map __section(".maps") = {
    61  	.values = {
    62  		[FROM_NETWORK] = &cil_from_network,
    63  	},
    64  };
    65  
    66  PKTGEN("tc", "ipv4_not_decrypted_ipsec_from_network")
    67  int ipv4_not_decrypted_ipsec_from_network_pktgen(struct __ctx_buff *ctx)
    68  {
    69  	struct pktgen builder;
    70  	struct ethhdr *l2;
    71  	struct iphdr *l3;
    72  	struct ip_esp_hdr *l4;
    73  	void *data;
    74  
    75  	pktgen__init(&builder, ctx);
    76  
    77  	l2 = pktgen__push_ethhdr(&builder);
    78  	if (!l2)
    79  		return TEST_ERROR;
    80  	ethhdr__set_macs(l2, (__u8 *)mac_one, (__u8 *)mac_two);
    81  
    82  	l3 = pktgen__push_default_iphdr(&builder);
    83  	if (!l3)
    84  		return TEST_ERROR;
    85  	l3->saddr = v4_pod_one;
    86  	l3->daddr = v4_pod_two;
    87  
    88  	l4 = pktgen__push_default_esphdr(&builder);
    89  	if (!l4)
    90  		return TEST_ERROR;
    91  	l4->spi = ENCRYPT_KEY;
    92  	l4->seq_no = ESP_SEQUENCE;
    93  
    94  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
    95  	if (!data)
    96  		return TEST_ERROR;
    97  
    98  	pktgen__finish(&builder);
    99  	return 0;
   100  }
   101  
   102  SETUP("tc", "ipv4_not_decrypted_ipsec_from_network")
   103  int ipv4_not_decrypted_ipsec_from_network_setup(struct __ctx_buff *ctx)
   104  {
   105  	/* We need to populate the node ID map because we'll lookup into it on
   106  	 * ingress to find the node ID to use to match against XFRM IN states.
   107  	 */
   108  	node_v4_add_entry(v4_pod_one, NODE_ID, 0);
   109  
   110  	tail_call_static(ctx, entry_call_map, FROM_NETWORK);
   111  	return TEST_ERROR;
   112  }
   113  
   114  CHECK("tc", "ipv4_not_decrypted_ipsec_from_network")
   115  int ipv4_not_decrypted_ipsec_from_network_check(__maybe_unused const struct __ctx_buff *ctx)
   116  {
   117  	void *data;
   118  	void *data_end;
   119  	__u32 *status_code;
   120  	struct ethhdr *l2;
   121  	struct iphdr *l3;
   122  	struct ip_esp_hdr *l4;
   123  	__u8 *payload;
   124  
   125  	test_init();
   126  
   127  	data = (void *)(long)ctx->data;
   128  	data_end = (void *)(long)ctx->data_end;
   129  
   130  	if (data + sizeof(*status_code) > data_end)
   131  		test_fatal("status code out of bounds");
   132  
   133  	status_code = data;
   134  	assert(*status_code == CTX_ACT_OK);
   135  	assert(ctx->mark == (MARK_MAGIC_DECRYPT | NODE_ID << 16));
   136  
   137  	l2 = data + sizeof(*status_code);
   138  
   139  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   140  		test_fatal("l2 out of bounds");
   141  
   142  	if (l2->h_proto != bpf_htons(ETH_P_IP))
   143  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   144  
   145  	if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0)
   146  		test_fatal("not_decrypted: src mac hasn't been set to source ep's mac");
   147  
   148  	if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0)
   149  		test_fatal("dest mac hasn't been set to dest ep's mac");
   150  
   151  	l3 = (void *)l2 + sizeof(struct ethhdr);
   152  
   153  	if ((void *)l3 + sizeof(struct iphdr) > data_end)
   154  		test_fatal("l3 out of bounds");
   155  
   156  	if (l3->saddr != v4_pod_one)
   157  		test_fatal("src IP was changed");
   158  
   159  	if (l3->daddr != v4_pod_two)
   160  		test_fatal("dest IP was changed");
   161  
   162  	if (l3->check != bpf_htons(0xf948))
   163  		test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check));
   164  
   165  	l4 = (void *)l3 + sizeof(struct iphdr);
   166  
   167  	if ((void *)l4 + sizeof(struct ip_esp_hdr) > data_end)
   168  		test_fatal("l4 out of bounds");
   169  
   170  	if (l4->spi != ENCRYPT_KEY)
   171  		test_fatal("ESP spi was changed");
   172  
   173  	if (l4->seq_no != ESP_SEQUENCE)
   174  		test_fatal("ESP seq was changed");
   175  
   176  	payload = (void *)l4 + sizeof(struct ip_esp_hdr);
   177  	if ((void *)payload + sizeof(default_data) > data_end)
   178  		test_fatal("paylaod out of bounds\n");
   179  
   180  	if (memcmp(payload, default_data, sizeof(default_data)) != 0)
   181  		test_fatal("tcp payload was changed");
   182  
   183  	test_finish();
   184  }
   185  
   186  PKTGEN("tc", "ipv6_not_decrypted_ipsec_from_network")
   187  int ipv6_not_decrypted_ipsec_from_network_pktgen(struct __ctx_buff *ctx)
   188  {
   189  	struct pktgen builder;
   190  	struct ethhdr *l2;
   191  	struct ipv6hdr *l3;
   192  	struct ip_esp_hdr *l4;
   193  	void *data;
   194  
   195  	pktgen__init(&builder, ctx);
   196  
   197  	l2 = pktgen__push_ethhdr(&builder);
   198  	if (!l2)
   199  		return TEST_ERROR;
   200  	ethhdr__set_macs(l2, (__u8 *)mac_one, (__u8 *)mac_two);
   201  
   202  	l3 = pktgen__push_default_ipv6hdr(&builder);
   203  	if (!l3)
   204  		return TEST_ERROR;
   205  	ipv6hdr__set_addrs(l3, (__u8 *)v6_pod_one, (__u8 *)v6_pod_two);
   206  
   207  	l4 = pktgen__push_default_esphdr(&builder);
   208  	if (!l4)
   209  		return TEST_ERROR;
   210  	l4->spi = ENCRYPT_KEY;
   211  	l4->seq_no = ESP_SEQUENCE;
   212  
   213  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
   214  	if (!data)
   215  		return TEST_ERROR;
   216  
   217  	pktgen__finish(&builder);
   218  	return 0;
   219  }
   220  
   221  SETUP("tc", "ipv6_not_decrypted_ipsec_from_network")
   222  int ipv6_not_decrypted_ipsec_from_network_setup(struct __ctx_buff *ctx)
   223  {
   224  	/* To be able to use memcpy, we need to ensure that the memcpy'ed field is
   225  	 * 8B aligned on the stack. Given the existing node_ip struct, the only way
   226  	 * to achieve that is to align a parent tmp struct.
   227  	 * We can't simply use __bpf_memcpy_builtin because that causes a
   228  	 * relocation error in the lib.
   229  	 */
   230  	struct tmp {
   231  		__u32 _;
   232  		struct node_key k;
   233  	} node_ip __align_stack_8 = {};
   234  	struct node_value node_value = {
   235  		.id = NODE_ID,
   236  		.spi = 0
   237  	};
   238  
   239  	/* We need to populate the node ID map because we'll lookup into it on
   240  	 * ingress to find the node ID to use to match against XFRM IN states.
   241  	 */
   242  	node_ip.k.family = ENDPOINT_KEY_IPV6;
   243  	memcpy((__u8 *)&node_ip.k.ip6, (__u8 *)v6_pod_one, 16);
   244  	map_update_elem(&NODE_MAP_V2, &node_ip.k, &node_value, BPF_ANY);
   245  
   246  	tail_call_static(ctx, entry_call_map, FROM_NETWORK);
   247  	return TEST_ERROR;
   248  }
   249  
   250  CHECK("tc", "ipv6_not_decrypted_ipsec_from_network")
   251  int ipv6_not_decrypted_ipsec_from_network_check(__maybe_unused const struct __ctx_buff *ctx)
   252  {
   253  	void *data;
   254  	void *data_end;
   255  	__u32 *status_code;
   256  	struct ethhdr *l2;
   257  	struct ipv6hdr *l3;
   258  	struct ip_esp_hdr *l4;
   259  	__u8 *payload;
   260  
   261  	test_init();
   262  
   263  	data = (void *)(long)ctx->data;
   264  	data_end = (void *)(long)ctx->data_end;
   265  
   266  	if (data + sizeof(*status_code) > data_end)
   267  		test_fatal("status code out of bounds");
   268  
   269  	status_code = data;
   270  	assert(*status_code == CTX_ACT_OK);
   271  	assert(ctx->mark == (MARK_MAGIC_DECRYPT | NODE_ID << 16));
   272  
   273  	l2 = data + sizeof(*status_code);
   274  
   275  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   276  		test_fatal("l2 out of bounds");
   277  
   278  	if (l2->h_proto != bpf_htons(ETH_P_IPV6))
   279  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   280  
   281  	if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0)
   282  		test_fatal("not_decrypted: src mac hasn't been set to source ep's mac");
   283  
   284  	if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0)
   285  		test_fatal("dest mac hasn't been set to dest ep's mac");
   286  
   287  	l3 = (void *)l2 + sizeof(struct ethhdr);
   288  
   289  	if ((void *)l3 + sizeof(struct ipv6hdr) > data_end)
   290  		test_fatal("l3 out of bounds");
   291  
   292  	if (memcmp((__u8 *)&l3->saddr, (__u8 *)v6_pod_one, 16) != 0)
   293  		test_fatal("src IP was changed");
   294  
   295  	if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_two, 16) != 0)
   296  		test_fatal("dest IP was changed");
   297  
   298  	l4 = (void *)l3 + sizeof(struct ipv6hdr);
   299  
   300  	if ((void *)l4 + sizeof(struct ip_esp_hdr) > data_end)
   301  		test_fatal("l4 out of bounds");
   302  
   303  	if (l4->spi != ENCRYPT_KEY)
   304  		test_fatal("ESP spi was changed");
   305  
   306  	if (l4->seq_no != ESP_SEQUENCE)
   307  		test_fatal("ESP seq was changed");
   308  
   309  	payload = (void *)l4 + sizeof(struct ip_esp_hdr);
   310  	if ((void *)payload + sizeof(default_data) > data_end)
   311  		test_fatal("paylaod out of bounds\n");
   312  
   313  	if (memcmp(payload, default_data, sizeof(default_data)) != 0)
   314  		test_fatal("tcp payload was changed");
   315  
   316  	test_finish();
   317  }
   318  
   319  PKTGEN("tc", "ipv4_decrypted_ipsec_from_network")
   320  int ipv4_decrypted_ipsec_from_network_pktgen(struct __ctx_buff *ctx)
   321  {
   322  	struct pktgen builder;
   323  	struct tcphdr *l4;
   324  	void *data;
   325  
   326  	pktgen__init(&builder, ctx);
   327  
   328  	l4 = pktgen__push_ipv4_tcp_packet(&builder,
   329  					  (__u8 *)mac_one, (__u8 *)mac_two,
   330  					  v4_pod_one, v4_pod_two,
   331  					  tcp_src_one, tcp_svc_one);
   332  	if (!l4)
   333  		return TEST_ERROR;
   334  
   335  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
   336  	if (!data)
   337  		return TEST_ERROR;
   338  
   339  	pktgen__finish(&builder);
   340  	return 0;
   341  }
   342  
   343  SETUP("tc", "ipv4_decrypted_ipsec_from_network")
   344  int ipv4_decrypted_ipsec_from_network_setup(struct __ctx_buff *ctx)
   345  {
   346  	endpoint_v4_add_entry(v4_pod_two, DEST_IFINDEX, DEST_LXC_ID, 0, 0,
   347  			      (__u8 *)DEST_EP_MAC, (__u8 *)DEST_NODE_MAC);
   348  
   349  	ctx->mark = MARK_MAGIC_DECRYPT;
   350  	tail_call_static(ctx, entry_call_map, FROM_NETWORK);
   351  	return TEST_ERROR;
   352  }
   353  
   354  CHECK("tc", "ipv4_decrypted_ipsec_from_network")
   355  int ipv4_decrypted_ipsec_from_network_check(__maybe_unused const struct __ctx_buff *ctx)
   356  {
   357  	void *data;
   358  	void *data_end;
   359  	__u32 *status_code;
   360  	struct ethhdr *l2;
   361  	struct iphdr *l3;
   362  	struct tcphdr *l4;
   363  	__u8 *payload;
   364  
   365  	test_init();
   366  
   367  	data = (void *)(long)ctx->data;
   368  	data_end = (void *)(long)ctx->data_end;
   369  
   370  	if (data + sizeof(*status_code) > data_end)
   371  		test_fatal("status code out of bounds");
   372  
   373  	status_code = data;
   374  	assert(*status_code == EXPECTED_STATUS_CODE_FOR_DECRYPTED);
   375  	assert(ctx->mark == 0);
   376  
   377  	l2 = data + sizeof(*status_code);
   378  
   379  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   380  		test_fatal("l2 out of bounds");
   381  
   382  	if (l2->h_proto != bpf_htons(ETH_P_IP))
   383  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   384  
   385  	if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0)
   386  		test_fatal("decrypted: src mac hasn't been set to source ep's mac");
   387  
   388  	if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0)
   389  		test_fatal("dest mac hasn't been set to dest ep's mac");
   390  
   391  	l3 = (void *)l2 + sizeof(struct ethhdr);
   392  
   393  	if ((void *)l3 + sizeof(struct iphdr) > data_end)
   394  		test_fatal("l3 out of bounds");
   395  
   396  	if (l3->saddr != v4_pod_one)
   397  		test_fatal("src IP was changed");
   398  
   399  	if (l3->daddr != v4_pod_two)
   400  		test_fatal("dest IP was changed");
   401  
   402  	if (l3->check != bpf_htons(0xf968))
   403  		test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check));
   404  
   405  	l4 = (void *)l3 + sizeof(struct iphdr);
   406  
   407  	if ((void *)l4 + sizeof(struct tcphdr) > data_end)
   408  		test_fatal("l4 out of bounds");
   409  
   410  	if (l4->source != tcp_src_one)
   411  		test_fatal("src TCP port was changed");
   412  
   413  	if (l4->dest != tcp_svc_one)
   414  		test_fatal("dst TCP port was changed");
   415  
   416  	payload = (void *)l4 + sizeof(struct tcphdr);
   417  	if ((void *)payload + sizeof(default_data) > data_end)
   418  		test_fatal("paylaod out of bounds\n");
   419  
   420  	if (memcmp(payload, default_data, sizeof(default_data)) != 0)
   421  		test_fatal("tcp payload was changed");
   422  
   423  	test_finish();
   424  }
   425  
   426  PKTGEN("tc", "ipv6_decrypted_ipsec_from_network")
   427  int ipv6_decrypted_ipsec_from_network_pktgen(struct __ctx_buff *ctx)
   428  {
   429  	struct pktgen builder;
   430  	struct tcphdr *l4;
   431  	void *data;
   432  
   433  	pktgen__init(&builder, ctx);
   434  
   435  	l4 = pktgen__push_ipv6_tcp_packet(&builder,
   436  					  (__u8 *)mac_one, (__u8 *)mac_two,
   437  					  (__u8 *)v6_pod_one, (__u8 *)v6_pod_two,
   438  					  tcp_src_one, tcp_svc_one);
   439  	if (!l4)
   440  		return TEST_ERROR;
   441  
   442  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
   443  	if (!data)
   444  		return TEST_ERROR;
   445  
   446  	pktgen__finish(&builder);
   447  	return 0;
   448  }
   449  
   450  SETUP("tc", "ipv6_decrypted_ipsec_from_network")
   451  int ipv6_decrypted_ipsec_from_network_setup(struct __ctx_buff *ctx)
   452  {
   453  	endpoint_v6_add_entry((union v6addr *)v6_pod_two, DEST_IFINDEX, DEST_LXC_ID,
   454  			      0, 0, (__u8 *)DEST_EP_MAC, (__u8 *)DEST_NODE_MAC);
   455  
   456  	ctx->mark = MARK_MAGIC_DECRYPT;
   457  	tail_call_static(ctx, entry_call_map, FROM_NETWORK);
   458  	return TEST_ERROR;
   459  }
   460  
   461  CHECK("tc", "ipv6_decrypted_ipsec_from_network")
   462  int ipv6_decrypted_ipsec_from_network_check(__maybe_unused const struct __ctx_buff *ctx)
   463  {
   464  	void *data;
   465  	void *data_end;
   466  	__u32 *status_code;
   467  	struct ethhdr *l2;
   468  	struct ipv6hdr *l3;
   469  	struct tcphdr *l4;
   470  	__u8 *payload;
   471  
   472  	test_init();
   473  
   474  	data = (void *)(long)ctx->data;
   475  	data_end = (void *)(long)ctx->data_end;
   476  
   477  	if (data + sizeof(*status_code) > data_end)
   478  		test_fatal("status code out of bounds");
   479  
   480  	status_code = data;
   481  	assert(*status_code == EXPECTED_STATUS_CODE_FOR_DECRYPTED);
   482  	assert(ctx->mark == 0);
   483  
   484  	l2 = data + sizeof(*status_code);
   485  
   486  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   487  		test_fatal("l2 out of bounds");
   488  
   489  	if (l2->h_proto != bpf_htons(ETH_P_IPV6))
   490  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   491  
   492  	if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0)
   493  		test_fatal("decrypted: src mac hasn't been set to source ep's mac");
   494  
   495  	if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0)
   496  		test_fatal("dest mac hasn't been set to dest ep's mac");
   497  
   498  	l3 = (void *)l2 + sizeof(struct ethhdr);
   499  
   500  	if ((void *)l3 + sizeof(struct ipv6hdr) > data_end)
   501  		test_fatal("l3 out of bounds");
   502  
   503  	if (memcmp((__u8 *)&l3->saddr, (__u8 *)v6_pod_one, 16) != 0)
   504  		test_fatal("src IP was changed");
   505  
   506  	if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_two, 16) != 0)
   507  		test_fatal("dest IP was changed");
   508  
   509  	l4 = (void *)l3 + sizeof(struct ipv6hdr);
   510  
   511  	if ((void *)l4 + sizeof(struct tcphdr) > data_end)
   512  		test_fatal("l4 out of bounds");
   513  
   514  	if (l4->source != tcp_src_one)
   515  		test_fatal("src TCP port was changed");
   516  
   517  	if (l4->dest != tcp_svc_one)
   518  		test_fatal("dst TCP port was changed");
   519  
   520  	payload = (void *)l4 + sizeof(struct tcphdr);
   521  	if ((void *)payload + sizeof(default_data) > data_end)
   522  		test_fatal("paylaod out of bounds\n");
   523  
   524  	if (memcmp(payload, default_data, sizeof(default_data)) != 0)
   525  		test_fatal("tcp payload was changed");
   526  
   527  	test_finish();
   528  }