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 }