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

     1  /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
     2  /* Copyright Authors of Cilium */
     3  
     4  #include "common.h"
     5  #include <bpf/ctx/skb.h>
     6  #include "pktgen.h"
     7  #define ROUTER_IP
     8  #undef ROUTER_IP
     9  
    10  #define NODE_ID 2333
    11  #define ENCRYPT_KEY 3
    12  #define ENABLE_IPV4
    13  #define ENABLE_IPV6
    14  #define ENABLE_IPSEC
    15  #define SECCTX_FROM_IPCACHE 1
    16  
    17  #define ENCAP_IFINDEX 4
    18  #define skb_set_tunnel_key mock_skb_set_tunnel_key
    19  #define ctx_redirect mock_ctx_redirect
    20  
    21  int mock_skb_set_tunnel_key(__maybe_unused struct __sk_buff *skb,
    22  			    const struct bpf_tunnel_key *from,
    23  			    __maybe_unused __u32 size,
    24  			    __maybe_unused __u32 flags)
    25  {
    26  	/* 0xfffff is the default SECLABEL */
    27  	if (from->tunnel_id != 0xfffff)
    28  		return -1;
    29  	if (from->local_ipv4 != 0)
    30  		return -2;
    31  	if (from->remote_ipv4 != bpf_htonl(v4_node_two))
    32  		return -3;
    33  	return 0;
    34  }
    35  
    36  int mock_ctx_redirect(const struct __sk_buff *ctx __maybe_unused, int ifindex, __u32 flags)
    37  {
    38  	if (ifindex != ENCAP_IFINDEX)
    39  		return -1;
    40  	if (flags != 0)
    41  		return -2;
    42  	return CTX_ACT_REDIRECT;
    43  }
    44  
    45  #include "bpf_host.c"
    46  
    47  #include "lib/ipcache.h"
    48  
    49  #define FROM_HOST 0
    50  #define ESP_SEQUENCE 69865
    51  
    52  struct {
    53  	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    54  	__uint(key_size, sizeof(__u32));
    55  	__uint(max_entries, 1);
    56  	__array(values, int());
    57  } entry_call_map __section(".maps") = {
    58  	.values = {
    59  		[FROM_HOST] = &cil_from_host,
    60  	},
    61  };
    62  
    63  PKTGEN("tc", "ipv4_ipsec_from_host")
    64  int ipv4_ipsec_from_host_pktgen(struct __ctx_buff *ctx)
    65  {
    66  	struct pktgen builder;
    67  	struct ethhdr *l2;
    68  	struct iphdr *l3;
    69  	struct ip_esp_hdr *l4;
    70  	void *data;
    71  
    72  	pktgen__init(&builder, ctx);
    73  
    74  	l2 = pktgen__push_ethhdr(&builder);
    75  	if (!l2)
    76  		return TEST_ERROR;
    77  	ethhdr__set_macs(l2, (__u8 *)mac_one, (__u8 *)mac_two);
    78  
    79  	l3 = pktgen__push_default_iphdr(&builder);
    80  	if (!l3)
    81  		return TEST_ERROR;
    82  	l3->saddr = v4_pod_one;
    83  	l3->daddr = v4_pod_two;
    84  
    85  	l4 = pktgen__push_default_esphdr(&builder);
    86  	if (!l4)
    87  		return TEST_ERROR;
    88  	l4->spi = ENCRYPT_KEY;
    89  	l4->seq_no = ESP_SEQUENCE;
    90  
    91  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
    92  	if (!data)
    93  		return TEST_ERROR;
    94  
    95  	pktgen__finish(&builder);
    96  	return 0;
    97  }
    98  
    99  SETUP("tc", "ipv4_ipsec_from_host")
   100  int ipv4_ipsec_from_host_setup(struct __ctx_buff *ctx)
   101  {
   102  	/* This is the ipcache entry for the CiliumInternalIP of the remote node.
   103  	 * It allows us to lookup the tunnel endpoint from the outer destination IP
   104  	 * address of the ESP packet. The CiliumInternalIPs are used for that outer
   105  	 * header.
   106  	 */
   107  	ipcache_v4_add_entry(v4_pod_two, 0, 233, v4_node_two, 0);
   108  
   109  	set_encrypt_key_mark(ctx, ENCRYPT_KEY, NODE_ID);
   110  	set_identity_meta(ctx, SECLABEL_IPV4);
   111  	tail_call_static(ctx, entry_call_map, FROM_HOST);
   112  	return TEST_ERROR;
   113  }
   114  
   115  CHECK("tc", "ipv4_ipsec_from_host")
   116  int ipv4_ipsec_from_host_check(__maybe_unused const struct __ctx_buff *ctx)
   117  {
   118  	void *data;
   119  	void *data_end;
   120  	__u32 *status_code;
   121  	struct ethhdr *l2;
   122  	struct iphdr *l3;
   123  	struct ip_esp_hdr *l4;
   124  	__u8 *payload;
   125  
   126  	test_init();
   127  
   128  	data = (void *)(long)ctx->data;
   129  	data_end = (void *)(long)ctx->data_end;
   130  
   131  	if (data + sizeof(*status_code) > data_end)
   132  		test_fatal("status code out of bounds");
   133  
   134  	status_code = data;
   135  	assert(*status_code == EXPECTED_STATUS_CODE);
   136  
   137  	assert(ctx->mark == 0);
   138  
   139  #ifdef CHECK_CB_ENCRYPT_IDENTITY
   140  	assert(ctx_load_meta(ctx, CB_ENCRYPT_IDENTITY) == 0);
   141  #endif
   142  
   143  	l2 = data + sizeof(*status_code);
   144  
   145  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   146  		test_fatal("l2 out of bounds");
   147  
   148  	if (l2->h_proto != bpf_htons(ETH_P_IP))
   149  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   150  
   151  	if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0)
   152  		test_fatal("src mac hasn't been set to source ep's mac");
   153  
   154  	if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0)
   155  		test_fatal("dest mac hasn't been set to dest ep's mac");
   156  
   157  	l3 = (void *)l2 + sizeof(struct ethhdr);
   158  
   159  	if ((void *)l3 + sizeof(struct iphdr) > data_end)
   160  		test_fatal("l3 out of bounds");
   161  
   162  	if (l3->saddr != v4_pod_one)
   163  		test_fatal("src IP was changed");
   164  
   165  	if (l3->daddr != v4_pod_two)
   166  		test_fatal("dest IP was changed");
   167  
   168  	if (l3->check != bpf_htons(0xf948))
   169  		test_fatal("L3 checksum is invalid: %d", bpf_htons(l3->check));
   170  
   171  	l4 = (void *)l3 + sizeof(struct iphdr);
   172  
   173  	if ((void *)l4 + sizeof(struct ip_esp_hdr) > data_end)
   174  		test_fatal("l4 out of bounds");
   175  
   176  	if (l4->spi != ENCRYPT_KEY)
   177  		test_fatal("ESP spi was changed");
   178  
   179  	if (l4->seq_no != ESP_SEQUENCE)
   180  		test_fatal("ESP seq was changed");
   181  
   182  	payload = (void *)l4 + sizeof(struct ip_esp_hdr);
   183  	if ((void *)payload + sizeof(default_data) > data_end)
   184  		test_fatal("paylaod out of bounds\n");
   185  
   186  	if (memcmp(payload, default_data, sizeof(default_data)) != 0)
   187  		test_fatal("tcp payload was changed");
   188  
   189  	test_finish();
   190  }
   191  
   192  PKTGEN("tc", "ipv6_ipsec_from_host")
   193  int ipv6_ipsec_from_host_pktgen(struct __ctx_buff *ctx)
   194  {
   195  	struct pktgen builder;
   196  	struct ethhdr *l2;
   197  	struct ipv6hdr *l3;
   198  	struct ip_esp_hdr *l4;
   199  	void *data;
   200  
   201  	pktgen__init(&builder, ctx);
   202  
   203  	l2 = pktgen__push_ethhdr(&builder);
   204  	if (!l2)
   205  		return TEST_ERROR;
   206  	ethhdr__set_macs(l2, (__u8 *)mac_one, (__u8 *)mac_two);
   207  
   208  	l3 = pktgen__push_default_ipv6hdr(&builder);
   209  	if (!l3)
   210  		return TEST_ERROR;
   211  	ipv6hdr__set_addrs(l3, (__u8 *)v6_pod_one, (__u8 *)v6_pod_two);
   212  
   213  	l4 = pktgen__push_default_esphdr(&builder);
   214  	if (!l4)
   215  		return TEST_ERROR;
   216  	l4->spi = ENCRYPT_KEY;
   217  	l4->seq_no = ESP_SEQUENCE;
   218  
   219  	data = pktgen__push_data(&builder, default_data, sizeof(default_data));
   220  	if (!data)
   221  		return TEST_ERROR;
   222  
   223  	pktgen__finish(&builder);
   224  	return 0;
   225  }
   226  
   227  SETUP("tc", "ipv6_ipsec_from_host")
   228  int ipv6_ipsec_from_host_setup(struct __ctx_buff *ctx)
   229  {
   230  	/* See comment for IPv4 counterpart. */
   231  	ipcache_v6_add_entry((union v6addr *)v6_pod_two, 0, 233, v4_node_two, 0);
   232  
   233  	set_encrypt_key_mark(ctx, ENCRYPT_KEY, NODE_ID);
   234  	set_identity_meta(ctx, SECLABEL_IPV6);
   235  	tail_call_static(ctx, entry_call_map, FROM_HOST);
   236  	return TEST_ERROR;
   237  }
   238  
   239  CHECK("tc", "ipv6_ipsec_from_host")
   240  int ipv6_ipsec_from_host_check(__maybe_unused const struct __ctx_buff *ctx)
   241  {
   242  	void *data;
   243  	void *data_end;
   244  	__u32 *status_code;
   245  	struct ethhdr *l2;
   246  	struct ipv6hdr *l3;
   247  	struct ip_esp_hdr *l4;
   248  	__u8 *payload;
   249  
   250  	test_init();
   251  
   252  	data = (void *)(long)ctx->data;
   253  	data_end = (void *)(long)ctx->data_end;
   254  
   255  	if (data + sizeof(*status_code) > data_end)
   256  		test_fatal("status code out of bounds");
   257  
   258  	status_code = data;
   259  	assert(*status_code == EXPECTED_STATUS_CODE);
   260  
   261  #ifdef CHECK_CB_ENCRYPT_IDENTITY
   262  	assert(ctx_load_meta(ctx, CB_ENCRYPT_IDENTITY) == 0);
   263  #endif
   264  
   265  	assert(ctx->mark == 0);
   266  
   267  	l2 = data + sizeof(*status_code);
   268  
   269  	if ((void *)l2 + sizeof(struct ethhdr) > data_end)
   270  		test_fatal("l2 out of bounds");
   271  
   272  	if (l2->h_proto != bpf_htons(ETH_P_IPV6))
   273  		test_fatal("l2 proto hasn't been set to ETH_P_IP");
   274  
   275  	if (memcmp(l2->h_source, (__u8 *)mac_one, ETH_ALEN) != 0)
   276  		test_fatal("src mac hasn't been set to source ep's mac");
   277  
   278  	if (memcmp(l2->h_dest, (__u8 *)mac_two, ETH_ALEN) != 0)
   279  		test_fatal("dest mac hasn't been set to dest ep's mac");
   280  
   281  	l3 = (void *)l2 + sizeof(struct ethhdr);
   282  
   283  	if ((void *)l3 + sizeof(struct ipv6hdr) > data_end)
   284  		test_fatal("l3 out of bounds");
   285  
   286  	if (memcmp((__u8 *)&l3->saddr, (__u8 *)v6_pod_one, 16) != 0)
   287  		test_fatal("src IP was changed");
   288  
   289  	if (memcmp((__u8 *)&l3->daddr, (__u8 *)v6_pod_two, 16) != 0)
   290  		test_fatal("dest IP was changed");
   291  
   292  	l4 = (void *)l3 + sizeof(struct ipv6hdr);
   293  
   294  	if ((void *)l4 + sizeof(struct ip_esp_hdr) > data_end)
   295  		test_fatal("l4 out of bounds");
   296  
   297  	if (l4->spi != ENCRYPT_KEY)
   298  		test_fatal("ESP spi was changed");
   299  
   300  	if (l4->seq_no != ESP_SEQUENCE)
   301  		test_fatal("ESP seq was changed");
   302  
   303  	payload = (void *)l4 + sizeof(struct ip_esp_hdr);
   304  	if ((void *)payload + sizeof(default_data) > data_end)
   305  		test_fatal("paylaod out of bounds\n");
   306  
   307  	if (memcmp(payload, default_data, sizeof(default_data)) != 0)
   308  		test_fatal("tcp payload was changed");
   309  
   310  	test_finish();
   311  }