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