1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 // Copyright (c) 2020 Cloudflare 3 4 #include <errno.h> 5 #include <stdbool.h> 6 #include <stddef.h> 7 #include <linux/bpf.h> 8 #include <linux/in.h> 9 #include <sys/socket.h> 10 11 #include <bpf/bpf_endian.h> 12 #include <bpf/bpf_helpers.h> 13 14 #define IP4(a, b, c, d) \ 15 bpf_htonl((((__u32)(a) & 0xffU) << 24) | \ 16 (((__u32)(b) & 0xffU) << 16) | \ 17 (((__u32)(c) & 0xffU) << 8) | \ 18 (((__u32)(d) & 0xffU) << 0)) 19 #define IP6(aaaa, bbbb, cccc, dddd) \ 20 { bpf_htonl(aaaa), bpf_htonl(bbbb), bpf_htonl(cccc), bpf_htonl(dddd) } 21 22 /* Macros for least-significant byte and word accesses. */ 23 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 24 #define LSE_INDEX(index, size) (index) 25 #else 26 #define LSE_INDEX(index, size) ((size) - (index) - 1) 27 #endif 28 #define LSB(value, index) \ 29 (((__u8 *)&(value))[LSE_INDEX((index), sizeof(value))]) 30 #define LSW(value, index) \ 31 (((__u16 *)&(value))[LSE_INDEX((index), sizeof(value) / 2)]) 32 33 #define MAX_SOCKS 32 34 35 struct { 36 __uint(type, BPF_MAP_TYPE_SOCKMAP); 37 __uint(max_entries, MAX_SOCKS); 38 __type(key, __u32); 39 __type(value, __u64); 40 } redir_map SEC(".maps"); 41 42 struct { 43 __uint(type, BPF_MAP_TYPE_ARRAY); 44 __uint(max_entries, 2); 45 __type(key, int); 46 __type(value, int); 47 } run_map SEC(".maps"); 48 49 enum { 50 PROG1 = 0, 51 PROG2, 52 }; 53 54 enum { 55 SERVER_A = 0, 56 SERVER_B, 57 }; 58 59 /* Addressable key/value constants for convenience */ 60 static const int KEY_PROG1 = PROG1; 61 static const int KEY_PROG2 = PROG2; 62 static const int PROG_DONE = 1; 63 64 static const __u32 KEY_SERVER_A = SERVER_A; 65 static const __u32 KEY_SERVER_B = SERVER_B; 66 67 static const __u16 DST_PORT = 7007; /* Host byte order */ 68 static const __u32 DST_IP4 = IP4(127, 0, 0, 1); 69 static const __u32 DST_IP6[] = IP6(0xfd000000, 0x0, 0x0, 0x00000001); 70 71 SEC("sk_lookup/lookup_pass") 72 int lookup_pass(struct bpf_sk_lookup *ctx) 73 { 74 return SK_PASS; 75 } 76 77 SEC("sk_lookup/lookup_drop") 78 int lookup_drop(struct bpf_sk_lookup *ctx) 79 { 80 return SK_DROP; 81 } 82 83 SEC("sk_reuseport/reuse_pass") 84 int reuseport_pass(struct sk_reuseport_md *ctx) 85 { 86 return SK_PASS; 87 } 88 89 SEC("sk_reuseport/reuse_drop") 90 int reuseport_drop(struct sk_reuseport_md *ctx) 91 { 92 return SK_DROP; 93 } 94 95 /* Redirect packets destined for port DST_PORT to socket at redir_map[0]. */ 96 SEC("sk_lookup/redir_port") 97 int redir_port(struct bpf_sk_lookup *ctx) 98 { 99 struct bpf_sock *sk; 100 int err; 101 102 if (ctx->local_port != DST_PORT) 103 return SK_PASS; 104 105 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 106 if (!sk) 107 return SK_PASS; 108 109 err = bpf_sk_assign(ctx, sk, 0); 110 bpf_sk_release(sk); 111 return err ? SK_DROP : SK_PASS; 112 } 113 114 /* Redirect packets destined for DST_IP4 address to socket at redir_map[0]. */ 115 SEC("sk_lookup/redir_ip4") 116 int redir_ip4(struct bpf_sk_lookup *ctx) 117 { 118 struct bpf_sock *sk; 119 int err; 120 121 if (ctx->family != AF_INET) 122 return SK_PASS; 123 if (ctx->local_port != DST_PORT) 124 return SK_PASS; 125 if (ctx->local_ip4 != DST_IP4) 126 return SK_PASS; 127 128 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 129 if (!sk) 130 return SK_PASS; 131 132 err = bpf_sk_assign(ctx, sk, 0); 133 bpf_sk_release(sk); 134 return err ? SK_DROP : SK_PASS; 135 } 136 137 /* Redirect packets destined for DST_IP6 address to socket at redir_map[0]. */ 138 SEC("sk_lookup/redir_ip6") 139 int redir_ip6(struct bpf_sk_lookup *ctx) 140 { 141 struct bpf_sock *sk; 142 int err; 143 144 if (ctx->family != AF_INET6) 145 return SK_PASS; 146 if (ctx->local_port != DST_PORT) 147 return SK_PASS; 148 if (ctx->local_ip6[0] != DST_IP6[0] || 149 ctx->local_ip6[1] != DST_IP6[1] || 150 ctx->local_ip6[2] != DST_IP6[2] || 151 ctx->local_ip6[3] != DST_IP6[3]) 152 return SK_PASS; 153 154 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 155 if (!sk) 156 return SK_PASS; 157 158 err = bpf_sk_assign(ctx, sk, 0); 159 bpf_sk_release(sk); 160 return err ? SK_DROP : SK_PASS; 161 } 162 163 SEC("sk_lookup/select_sock_a") 164 int select_sock_a(struct bpf_sk_lookup *ctx) 165 { 166 struct bpf_sock *sk; 167 int err; 168 169 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 170 if (!sk) 171 return SK_PASS; 172 173 err = bpf_sk_assign(ctx, sk, 0); 174 bpf_sk_release(sk); 175 return err ? SK_DROP : SK_PASS; 176 } 177 178 SEC("sk_lookup/select_sock_a_no_reuseport") 179 int select_sock_a_no_reuseport(struct bpf_sk_lookup *ctx) 180 { 181 struct bpf_sock *sk; 182 int err; 183 184 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 185 if (!sk) 186 return SK_DROP; 187 188 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_NO_REUSEPORT); 189 bpf_sk_release(sk); 190 return err ? SK_DROP : SK_PASS; 191 } 192 193 SEC("sk_reuseport/select_sock_b") 194 int select_sock_b(struct sk_reuseport_md *ctx) 195 { 196 __u32 key = KEY_SERVER_B; 197 int err; 198 199 err = bpf_sk_select_reuseport(ctx, &redir_map, &key, 0); 200 return err ? SK_DROP : SK_PASS; 201 } 202 203 /* Check that bpf_sk_assign() returns -EEXIST if socket already selected. */ 204 SEC("sk_lookup/sk_assign_eexist") 205 int sk_assign_eexist(struct bpf_sk_lookup *ctx) 206 { 207 struct bpf_sock *sk; 208 int err, ret; 209 210 ret = SK_DROP; 211 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B); 212 if (!sk) 213 goto out; 214 err = bpf_sk_assign(ctx, sk, 0); 215 if (err) 216 goto out; 217 bpf_sk_release(sk); 218 219 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 220 if (!sk) 221 goto out; 222 err = bpf_sk_assign(ctx, sk, 0); 223 if (err != -EEXIST) { 224 bpf_printk("sk_assign returned %d, expected %d\n", 225 err, -EEXIST); 226 goto out; 227 } 228 229 ret = SK_PASS; /* Success, redirect to KEY_SERVER_B */ 230 out: 231 if (sk) 232 bpf_sk_release(sk); 233 return ret; 234 } 235 236 /* Check that bpf_sk_assign(BPF_SK_LOOKUP_F_REPLACE) can override selection. */ 237 SEC("sk_lookup/sk_assign_replace_flag") 238 int sk_assign_replace_flag(struct bpf_sk_lookup *ctx) 239 { 240 struct bpf_sock *sk; 241 int err, ret; 242 243 ret = SK_DROP; 244 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 245 if (!sk) 246 goto out; 247 err = bpf_sk_assign(ctx, sk, 0); 248 if (err) 249 goto out; 250 bpf_sk_release(sk); 251 252 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B); 253 if (!sk) 254 goto out; 255 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_REPLACE); 256 if (err) { 257 bpf_printk("sk_assign returned %d, expected 0\n", err); 258 goto out; 259 } 260 261 ret = SK_PASS; /* Success, redirect to KEY_SERVER_B */ 262 out: 263 if (sk) 264 bpf_sk_release(sk); 265 return ret; 266 } 267 268 /* Check that bpf_sk_assign(sk=NULL) is accepted. */ 269 SEC("sk_lookup/sk_assign_null") 270 int sk_assign_null(struct bpf_sk_lookup *ctx) 271 { 272 struct bpf_sock *sk = NULL; 273 int err, ret; 274 275 ret = SK_DROP; 276 277 err = bpf_sk_assign(ctx, NULL, 0); 278 if (err) { 279 bpf_printk("sk_assign returned %d, expected 0\n", err); 280 goto out; 281 } 282 283 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B); 284 if (!sk) 285 goto out; 286 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_REPLACE); 287 if (err) { 288 bpf_printk("sk_assign returned %d, expected 0\n", err); 289 goto out; 290 } 291 292 if (ctx->sk != sk) 293 goto out; 294 err = bpf_sk_assign(ctx, NULL, 0); 295 if (err != -EEXIST) 296 goto out; 297 err = bpf_sk_assign(ctx, NULL, BPF_SK_LOOKUP_F_REPLACE); 298 if (err) 299 goto out; 300 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_REPLACE); 301 if (err) 302 goto out; 303 304 ret = SK_PASS; /* Success, redirect to KEY_SERVER_B */ 305 out: 306 if (sk) 307 bpf_sk_release(sk); 308 return ret; 309 } 310 311 /* Check that selected sk is accessible through context. */ 312 SEC("sk_lookup/access_ctx_sk") 313 int access_ctx_sk(struct bpf_sk_lookup *ctx) 314 { 315 struct bpf_sock *sk1 = NULL, *sk2 = NULL; 316 int err, ret; 317 318 ret = SK_DROP; 319 320 /* Try accessing unassigned (NULL) ctx->sk field */ 321 if (ctx->sk && ctx->sk->family != AF_INET) 322 goto out; 323 324 /* Assign a value to ctx->sk */ 325 sk1 = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 326 if (!sk1) 327 goto out; 328 err = bpf_sk_assign(ctx, sk1, 0); 329 if (err) 330 goto out; 331 if (ctx->sk != sk1) 332 goto out; 333 334 /* Access ctx->sk fields */ 335 if (ctx->sk->family != AF_INET || 336 ctx->sk->type != SOCK_STREAM || 337 ctx->sk->state != BPF_TCP_LISTEN) 338 goto out; 339 340 /* Reset selection */ 341 err = bpf_sk_assign(ctx, NULL, BPF_SK_LOOKUP_F_REPLACE); 342 if (err) 343 goto out; 344 if (ctx->sk) 345 goto out; 346 347 /* Assign another socket */ 348 sk2 = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B); 349 if (!sk2) 350 goto out; 351 err = bpf_sk_assign(ctx, sk2, BPF_SK_LOOKUP_F_REPLACE); 352 if (err) 353 goto out; 354 if (ctx->sk != sk2) 355 goto out; 356 357 /* Access reassigned ctx->sk fields */ 358 if (ctx->sk->family != AF_INET || 359 ctx->sk->type != SOCK_STREAM || 360 ctx->sk->state != BPF_TCP_LISTEN) 361 goto out; 362 363 ret = SK_PASS; /* Success, redirect to KEY_SERVER_B */ 364 out: 365 if (sk1) 366 bpf_sk_release(sk1); 367 if (sk2) 368 bpf_sk_release(sk2); 369 return ret; 370 } 371 372 /* Check narrow loads from ctx fields that support them. 373 * 374 * Narrow loads of size >= target field size from a non-zero offset 375 * are not covered because they give bogus results, that is the 376 * verifier ignores the offset. 377 */ 378 SEC("sk_lookup/ctx_narrow_access") 379 int ctx_narrow_access(struct bpf_sk_lookup *ctx) 380 { 381 struct bpf_sock *sk; 382 int err, family; 383 bool v4; 384 385 v4 = (ctx->family == AF_INET); 386 387 /* Narrow loads from family field */ 388 if (LSB(ctx->family, 0) != (v4 ? AF_INET : AF_INET6) || 389 LSB(ctx->family, 1) != 0 || LSB(ctx->family, 2) != 0 || LSB(ctx->family, 3) != 0) 390 return SK_DROP; 391 if (LSW(ctx->family, 0) != (v4 ? AF_INET : AF_INET6)) 392 return SK_DROP; 393 394 /* Narrow loads from protocol field */ 395 if (LSB(ctx->protocol, 0) != IPPROTO_TCP || 396 LSB(ctx->protocol, 1) != 0 || LSB(ctx->protocol, 2) != 0 || LSB(ctx->protocol, 3) != 0) 397 return SK_DROP; 398 if (LSW(ctx->protocol, 0) != IPPROTO_TCP) 399 return SK_DROP; 400 401 /* Narrow loads from remote_port field. Expect non-0 value. */ 402 if (LSB(ctx->remote_port, 0) == 0 && LSB(ctx->remote_port, 1) == 0 && 403 LSB(ctx->remote_port, 2) == 0 && LSB(ctx->remote_port, 3) == 0) 404 return SK_DROP; 405 if (LSW(ctx->remote_port, 0) == 0) 406 return SK_DROP; 407 408 /* Narrow loads from local_port field. Expect DST_PORT. */ 409 if (LSB(ctx->local_port, 0) != ((DST_PORT >> 0) & 0xff) || 410 LSB(ctx->local_port, 1) != ((DST_PORT >> 8) & 0xff) || 411 LSB(ctx->local_port, 2) != 0 || LSB(ctx->local_port, 3) != 0) 412 return SK_DROP; 413 if (LSW(ctx->local_port, 0) != DST_PORT) 414 return SK_DROP; 415 416 /* Narrow loads from IPv4 fields */ 417 if (v4) { 418 /* Expect non-0.0.0.0 in remote_ip4 */ 419 if (LSB(ctx->remote_ip4, 0) == 0 && LSB(ctx->remote_ip4, 1) == 0 && 420 LSB(ctx->remote_ip4, 2) == 0 && LSB(ctx->remote_ip4, 3) == 0) 421 return SK_DROP; 422 if (LSW(ctx->remote_ip4, 0) == 0 && LSW(ctx->remote_ip4, 1) == 0) 423 return SK_DROP; 424 425 /* Expect DST_IP4 in local_ip4 */ 426 if (LSB(ctx->local_ip4, 0) != ((DST_IP4 >> 0) & 0xff) || 427 LSB(ctx->local_ip4, 1) != ((DST_IP4 >> 8) & 0xff) || 428 LSB(ctx->local_ip4, 2) != ((DST_IP4 >> 16) & 0xff) || 429 LSB(ctx->local_ip4, 3) != ((DST_IP4 >> 24) & 0xff)) 430 return SK_DROP; 431 if (LSW(ctx->local_ip4, 0) != ((DST_IP4 >> 0) & 0xffff) || 432 LSW(ctx->local_ip4, 1) != ((DST_IP4 >> 16) & 0xffff)) 433 return SK_DROP; 434 } else { 435 /* Expect 0.0.0.0 IPs when family != AF_INET */ 436 if (LSB(ctx->remote_ip4, 0) != 0 || LSB(ctx->remote_ip4, 1) != 0 || 437 LSB(ctx->remote_ip4, 2) != 0 || LSB(ctx->remote_ip4, 3) != 0) 438 return SK_DROP; 439 if (LSW(ctx->remote_ip4, 0) != 0 || LSW(ctx->remote_ip4, 1) != 0) 440 return SK_DROP; 441 442 if (LSB(ctx->local_ip4, 0) != 0 || LSB(ctx->local_ip4, 1) != 0 || 443 LSB(ctx->local_ip4, 2) != 0 || LSB(ctx->local_ip4, 3) != 0) 444 return SK_DROP; 445 if (LSW(ctx->local_ip4, 0) != 0 || LSW(ctx->local_ip4, 1) != 0) 446 return SK_DROP; 447 } 448 449 /* Narrow loads from IPv6 fields */ 450 if (!v4) { 451 /* Expect non-:: IP in remote_ip6 */ 452 if (LSB(ctx->remote_ip6[0], 0) == 0 && LSB(ctx->remote_ip6[0], 1) == 0 && 453 LSB(ctx->remote_ip6[0], 2) == 0 && LSB(ctx->remote_ip6[0], 3) == 0 && 454 LSB(ctx->remote_ip6[1], 0) == 0 && LSB(ctx->remote_ip6[1], 1) == 0 && 455 LSB(ctx->remote_ip6[1], 2) == 0 && LSB(ctx->remote_ip6[1], 3) == 0 && 456 LSB(ctx->remote_ip6[2], 0) == 0 && LSB(ctx->remote_ip6[2], 1) == 0 && 457 LSB(ctx->remote_ip6[2], 2) == 0 && LSB(ctx->remote_ip6[2], 3) == 0 && 458 LSB(ctx->remote_ip6[3], 0) == 0 && LSB(ctx->remote_ip6[3], 1) == 0 && 459 LSB(ctx->remote_ip6[3], 2) == 0 && LSB(ctx->remote_ip6[3], 3) == 0) 460 return SK_DROP; 461 if (LSW(ctx->remote_ip6[0], 0) == 0 && LSW(ctx->remote_ip6[0], 1) == 0 && 462 LSW(ctx->remote_ip6[1], 0) == 0 && LSW(ctx->remote_ip6[1], 1) == 0 && 463 LSW(ctx->remote_ip6[2], 0) == 0 && LSW(ctx->remote_ip6[2], 1) == 0 && 464 LSW(ctx->remote_ip6[3], 0) == 0 && LSW(ctx->remote_ip6[3], 1) == 0) 465 return SK_DROP; 466 /* Expect DST_IP6 in local_ip6 */ 467 if (LSB(ctx->local_ip6[0], 0) != ((DST_IP6[0] >> 0) & 0xff) || 468 LSB(ctx->local_ip6[0], 1) != ((DST_IP6[0] >> 8) & 0xff) || 469 LSB(ctx->local_ip6[0], 2) != ((DST_IP6[0] >> 16) & 0xff) || 470 LSB(ctx->local_ip6[0], 3) != ((DST_IP6[0] >> 24) & 0xff) || 471 LSB(ctx->local_ip6[1], 0) != ((DST_IP6[1] >> 0) & 0xff) || 472 LSB(ctx->local_ip6[1], 1) != ((DST_IP6[1] >> 8) & 0xff) || 473 LSB(ctx->local_ip6[1], 2) != ((DST_IP6[1] >> 16) & 0xff) || 474 LSB(ctx->local_ip6[1], 3) != ((DST_IP6[1] >> 24) & 0xff) || 475 LSB(ctx->local_ip6[2], 0) != ((DST_IP6[2] >> 0) & 0xff) || 476 LSB(ctx->local_ip6[2], 1) != ((DST_IP6[2] >> 8) & 0xff) || 477 LSB(ctx->local_ip6[2], 2) != ((DST_IP6[2] >> 16) & 0xff) || 478 LSB(ctx->local_ip6[2], 3) != ((DST_IP6[2] >> 24) & 0xff) || 479 LSB(ctx->local_ip6[3], 0) != ((DST_IP6[3] >> 0) & 0xff) || 480 LSB(ctx->local_ip6[3], 1) != ((DST_IP6[3] >> 8) & 0xff) || 481 LSB(ctx->local_ip6[3], 2) != ((DST_IP6[3] >> 16) & 0xff) || 482 LSB(ctx->local_ip6[3], 3) != ((DST_IP6[3] >> 24) & 0xff)) 483 return SK_DROP; 484 if (LSW(ctx->local_ip6[0], 0) != ((DST_IP6[0] >> 0) & 0xffff) || 485 LSW(ctx->local_ip6[0], 1) != ((DST_IP6[0] >> 16) & 0xffff) || 486 LSW(ctx->local_ip6[1], 0) != ((DST_IP6[1] >> 0) & 0xffff) || 487 LSW(ctx->local_ip6[1], 1) != ((DST_IP6[1] >> 16) & 0xffff) || 488 LSW(ctx->local_ip6[2], 0) != ((DST_IP6[2] >> 0) & 0xffff) || 489 LSW(ctx->local_ip6[2], 1) != ((DST_IP6[2] >> 16) & 0xffff) || 490 LSW(ctx->local_ip6[3], 0) != ((DST_IP6[3] >> 0) & 0xffff) || 491 LSW(ctx->local_ip6[3], 1) != ((DST_IP6[3] >> 16) & 0xffff)) 492 return SK_DROP; 493 } else { 494 /* Expect :: IPs when family != AF_INET6 */ 495 if (LSB(ctx->remote_ip6[0], 0) != 0 || LSB(ctx->remote_ip6[0], 1) != 0 || 496 LSB(ctx->remote_ip6[0], 2) != 0 || LSB(ctx->remote_ip6[0], 3) != 0 || 497 LSB(ctx->remote_ip6[1], 0) != 0 || LSB(ctx->remote_ip6[1], 1) != 0 || 498 LSB(ctx->remote_ip6[1], 2) != 0 || LSB(ctx->remote_ip6[1], 3) != 0 || 499 LSB(ctx->remote_ip6[2], 0) != 0 || LSB(ctx->remote_ip6[2], 1) != 0 || 500 LSB(ctx->remote_ip6[2], 2) != 0 || LSB(ctx->remote_ip6[2], 3) != 0 || 501 LSB(ctx->remote_ip6[3], 0) != 0 || LSB(ctx->remote_ip6[3], 1) != 0 || 502 LSB(ctx->remote_ip6[3], 2) != 0 || LSB(ctx->remote_ip6[3], 3) != 0) 503 return SK_DROP; 504 if (LSW(ctx->remote_ip6[0], 0) != 0 || LSW(ctx->remote_ip6[0], 1) != 0 || 505 LSW(ctx->remote_ip6[1], 0) != 0 || LSW(ctx->remote_ip6[1], 1) != 0 || 506 LSW(ctx->remote_ip6[2], 0) != 0 || LSW(ctx->remote_ip6[2], 1) != 0 || 507 LSW(ctx->remote_ip6[3], 0) != 0 || LSW(ctx->remote_ip6[3], 1) != 0) 508 return SK_DROP; 509 510 if (LSB(ctx->local_ip6[0], 0) != 0 || LSB(ctx->local_ip6[0], 1) != 0 || 511 LSB(ctx->local_ip6[0], 2) != 0 || LSB(ctx->local_ip6[0], 3) != 0 || 512 LSB(ctx->local_ip6[1], 0) != 0 || LSB(ctx->local_ip6[1], 1) != 0 || 513 LSB(ctx->local_ip6[1], 2) != 0 || LSB(ctx->local_ip6[1], 3) != 0 || 514 LSB(ctx->local_ip6[2], 0) != 0 || LSB(ctx->local_ip6[2], 1) != 0 || 515 LSB(ctx->local_ip6[2], 2) != 0 || LSB(ctx->local_ip6[2], 3) != 0 || 516 LSB(ctx->local_ip6[3], 0) != 0 || LSB(ctx->local_ip6[3], 1) != 0 || 517 LSB(ctx->local_ip6[3], 2) != 0 || LSB(ctx->local_ip6[3], 3) != 0) 518 return SK_DROP; 519 if (LSW(ctx->remote_ip6[0], 0) != 0 || LSW(ctx->remote_ip6[0], 1) != 0 || 520 LSW(ctx->remote_ip6[1], 0) != 0 || LSW(ctx->remote_ip6[1], 1) != 0 || 521 LSW(ctx->remote_ip6[2], 0) != 0 || LSW(ctx->remote_ip6[2], 1) != 0 || 522 LSW(ctx->remote_ip6[3], 0) != 0 || LSW(ctx->remote_ip6[3], 1) != 0) 523 return SK_DROP; 524 } 525 526 /* Success, redirect to KEY_SERVER_B */ 527 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B); 528 if (sk) { 529 bpf_sk_assign(ctx, sk, 0); 530 bpf_sk_release(sk); 531 } 532 return SK_PASS; 533 } 534 535 /* Check that sk_assign rejects SERVER_A socket with -ESOCKNOSUPPORT */ 536 SEC("sk_lookup/sk_assign_esocknosupport") 537 int sk_assign_esocknosupport(struct bpf_sk_lookup *ctx) 538 { 539 struct bpf_sock *sk; 540 int err, ret; 541 542 ret = SK_DROP; 543 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 544 if (!sk) 545 goto out; 546 547 err = bpf_sk_assign(ctx, sk, 0); 548 if (err != -ESOCKTNOSUPPORT) { 549 bpf_printk("sk_assign returned %d, expected %d\n", 550 err, -ESOCKTNOSUPPORT); 551 goto out; 552 } 553 554 ret = SK_PASS; /* Success, pass to regular lookup */ 555 out: 556 if (sk) 557 bpf_sk_release(sk); 558 return ret; 559 } 560 561 SEC("sk_lookup/multi_prog_pass1") 562 int multi_prog_pass1(struct bpf_sk_lookup *ctx) 563 { 564 bpf_map_update_elem(&run_map, &KEY_PROG1, &PROG_DONE, BPF_ANY); 565 return SK_PASS; 566 } 567 568 SEC("sk_lookup/multi_prog_pass2") 569 int multi_prog_pass2(struct bpf_sk_lookup *ctx) 570 { 571 bpf_map_update_elem(&run_map, &KEY_PROG2, &PROG_DONE, BPF_ANY); 572 return SK_PASS; 573 } 574 575 SEC("sk_lookup/multi_prog_drop1") 576 int multi_prog_drop1(struct bpf_sk_lookup *ctx) 577 { 578 bpf_map_update_elem(&run_map, &KEY_PROG1, &PROG_DONE, BPF_ANY); 579 return SK_DROP; 580 } 581 582 SEC("sk_lookup/multi_prog_drop2") 583 int multi_prog_drop2(struct bpf_sk_lookup *ctx) 584 { 585 bpf_map_update_elem(&run_map, &KEY_PROG2, &PROG_DONE, BPF_ANY); 586 return SK_DROP; 587 } 588 589 static __always_inline int select_server_a(struct bpf_sk_lookup *ctx) 590 { 591 struct bpf_sock *sk; 592 int err; 593 594 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A); 595 if (!sk) 596 return SK_DROP; 597 598 err = bpf_sk_assign(ctx, sk, 0); 599 bpf_sk_release(sk); 600 if (err) 601 return SK_DROP; 602 603 return SK_PASS; 604 } 605 606 SEC("sk_lookup/multi_prog_redir1") 607 int multi_prog_redir1(struct bpf_sk_lookup *ctx) 608 { 609 int ret; 610 611 ret = select_server_a(ctx); 612 bpf_map_update_elem(&run_map, &KEY_PROG1, &PROG_DONE, BPF_ANY); 613 return SK_PASS; 614 } 615 616 SEC("sk_lookup/multi_prog_redir2") 617 int multi_prog_redir2(struct bpf_sk_lookup *ctx) 618 { 619 int ret; 620 621 ret = select_server_a(ctx); 622 bpf_map_update_elem(&run_map, &KEY_PROG2, &PROG_DONE, BPF_ANY); 623 return SK_PASS; 624 } 625 626 char _license[] SEC("license") = "Dual BSD/GPL"; 627 __u32 _version SEC("version") = 1; 628