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 }