0001
0002
0003
0004 #include <errno.h>
0005 #include <stdbool.h>
0006 #include <stddef.h>
0007 #include <linux/bpf.h>
0008 #include <linux/in.h>
0009 #include <sys/socket.h>
0010
0011 #include <bpf/bpf_endian.h>
0012 #include <bpf/bpf_helpers.h>
0013
0014 #define IP4(a, b, c, d) \
0015 bpf_htonl((((__u32)(a) & 0xffU) << 24) | \
0016 (((__u32)(b) & 0xffU) << 16) | \
0017 (((__u32)(c) & 0xffU) << 8) | \
0018 (((__u32)(d) & 0xffU) << 0))
0019 #define IP6(aaaa, bbbb, cccc, dddd) \
0020 { bpf_htonl(aaaa), bpf_htonl(bbbb), bpf_htonl(cccc), bpf_htonl(dddd) }
0021
0022
0023 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
0024 #define LSE_INDEX(index, size) (index)
0025 #else
0026 #define LSE_INDEX(index, size) ((size) - (index) - 1)
0027 #endif
0028 #define LSB(value, index) \
0029 (((__u8 *)&(value))[LSE_INDEX((index), sizeof(value))])
0030 #define LSW(value, index) \
0031 (((__u16 *)&(value))[LSE_INDEX((index), sizeof(value) / 2)])
0032
0033 #define MAX_SOCKS 32
0034
0035 struct {
0036 __uint(type, BPF_MAP_TYPE_SOCKMAP);
0037 __uint(max_entries, MAX_SOCKS);
0038 __type(key, __u32);
0039 __type(value, __u64);
0040 } redir_map SEC(".maps");
0041
0042 struct {
0043 __uint(type, BPF_MAP_TYPE_ARRAY);
0044 __uint(max_entries, 2);
0045 __type(key, int);
0046 __type(value, int);
0047 } run_map SEC(".maps");
0048
0049 enum {
0050 PROG1 = 0,
0051 PROG2,
0052 };
0053
0054 enum {
0055 SERVER_A = 0,
0056 SERVER_B,
0057 };
0058
0059
0060 static const int KEY_PROG1 = PROG1;
0061 static const int KEY_PROG2 = PROG2;
0062 static const int PROG_DONE = 1;
0063
0064 static const __u32 KEY_SERVER_A = SERVER_A;
0065 static const __u32 KEY_SERVER_B = SERVER_B;
0066
0067 static const __u16 SRC_PORT = bpf_htons(8008);
0068 static const __u32 SRC_IP4 = IP4(127, 0, 0, 2);
0069 static const __u32 SRC_IP6[] = IP6(0xfd000000, 0x0, 0x0, 0x00000002);
0070
0071 static const __u16 DST_PORT = 7007;
0072 static const __u32 DST_IP4 = IP4(127, 0, 0, 1);
0073 static const __u32 DST_IP6[] = IP6(0xfd000000, 0x0, 0x0, 0x00000001);
0074
0075 SEC("sk_lookup")
0076 int lookup_pass(struct bpf_sk_lookup *ctx)
0077 {
0078 return SK_PASS;
0079 }
0080
0081 SEC("sk_lookup")
0082 int lookup_drop(struct bpf_sk_lookup *ctx)
0083 {
0084 return SK_DROP;
0085 }
0086
0087 SEC("sk_lookup")
0088 int check_ifindex(struct bpf_sk_lookup *ctx)
0089 {
0090 if (ctx->ingress_ifindex == 1)
0091 return SK_DROP;
0092 return SK_PASS;
0093 }
0094
0095 SEC("sk_reuseport")
0096 int reuseport_pass(struct sk_reuseport_md *ctx)
0097 {
0098 return SK_PASS;
0099 }
0100
0101 SEC("sk_reuseport")
0102 int reuseport_drop(struct sk_reuseport_md *ctx)
0103 {
0104 return SK_DROP;
0105 }
0106
0107
0108 SEC("sk_lookup")
0109 int redir_port(struct bpf_sk_lookup *ctx)
0110 {
0111 struct bpf_sock *sk;
0112 int err;
0113
0114 if (ctx->local_port != DST_PORT)
0115 return SK_PASS;
0116
0117 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0118 if (!sk)
0119 return SK_PASS;
0120
0121 err = bpf_sk_assign(ctx, sk, 0);
0122 bpf_sk_release(sk);
0123 return err ? SK_DROP : SK_PASS;
0124 }
0125
0126
0127 SEC("sk_lookup")
0128 int redir_ip4(struct bpf_sk_lookup *ctx)
0129 {
0130 struct bpf_sock *sk;
0131 int err;
0132
0133 if (ctx->family != AF_INET)
0134 return SK_PASS;
0135 if (ctx->local_port != DST_PORT)
0136 return SK_PASS;
0137 if (ctx->local_ip4 != DST_IP4)
0138 return SK_PASS;
0139
0140 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0141 if (!sk)
0142 return SK_PASS;
0143
0144 err = bpf_sk_assign(ctx, sk, 0);
0145 bpf_sk_release(sk);
0146 return err ? SK_DROP : SK_PASS;
0147 }
0148
0149
0150 SEC("sk_lookup")
0151 int redir_ip6(struct bpf_sk_lookup *ctx)
0152 {
0153 struct bpf_sock *sk;
0154 int err;
0155
0156 if (ctx->family != AF_INET6)
0157 return SK_PASS;
0158 if (ctx->local_port != DST_PORT)
0159 return SK_PASS;
0160 if (ctx->local_ip6[0] != DST_IP6[0] ||
0161 ctx->local_ip6[1] != DST_IP6[1] ||
0162 ctx->local_ip6[2] != DST_IP6[2] ||
0163 ctx->local_ip6[3] != DST_IP6[3])
0164 return SK_PASS;
0165
0166 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0167 if (!sk)
0168 return SK_PASS;
0169
0170 err = bpf_sk_assign(ctx, sk, 0);
0171 bpf_sk_release(sk);
0172 return err ? SK_DROP : SK_PASS;
0173 }
0174
0175 SEC("sk_lookup")
0176 int select_sock_a(struct bpf_sk_lookup *ctx)
0177 {
0178 struct bpf_sock *sk;
0179 int err;
0180
0181 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0182 if (!sk)
0183 return SK_PASS;
0184
0185 err = bpf_sk_assign(ctx, sk, 0);
0186 bpf_sk_release(sk);
0187 return err ? SK_DROP : SK_PASS;
0188 }
0189
0190 SEC("sk_lookup")
0191 int select_sock_a_no_reuseport(struct bpf_sk_lookup *ctx)
0192 {
0193 struct bpf_sock *sk;
0194 int err;
0195
0196 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0197 if (!sk)
0198 return SK_DROP;
0199
0200 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_NO_REUSEPORT);
0201 bpf_sk_release(sk);
0202 return err ? SK_DROP : SK_PASS;
0203 }
0204
0205 SEC("sk_reuseport")
0206 int select_sock_b(struct sk_reuseport_md *ctx)
0207 {
0208 __u32 key = KEY_SERVER_B;
0209 int err;
0210
0211 err = bpf_sk_select_reuseport(ctx, &redir_map, &key, 0);
0212 return err ? SK_DROP : SK_PASS;
0213 }
0214
0215
0216 SEC("sk_lookup")
0217 int sk_assign_eexist(struct bpf_sk_lookup *ctx)
0218 {
0219 struct bpf_sock *sk;
0220 int err, ret;
0221
0222 ret = SK_DROP;
0223 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B);
0224 if (!sk)
0225 goto out;
0226 err = bpf_sk_assign(ctx, sk, 0);
0227 if (err)
0228 goto out;
0229 bpf_sk_release(sk);
0230
0231 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0232 if (!sk)
0233 goto out;
0234 err = bpf_sk_assign(ctx, sk, 0);
0235 if (err != -EEXIST) {
0236 bpf_printk("sk_assign returned %d, expected %d\n",
0237 err, -EEXIST);
0238 goto out;
0239 }
0240
0241 ret = SK_PASS;
0242 out:
0243 if (sk)
0244 bpf_sk_release(sk);
0245 return ret;
0246 }
0247
0248
0249 SEC("sk_lookup")
0250 int sk_assign_replace_flag(struct bpf_sk_lookup *ctx)
0251 {
0252 struct bpf_sock *sk;
0253 int err, ret;
0254
0255 ret = SK_DROP;
0256 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0257 if (!sk)
0258 goto out;
0259 err = bpf_sk_assign(ctx, sk, 0);
0260 if (err)
0261 goto out;
0262 bpf_sk_release(sk);
0263
0264 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B);
0265 if (!sk)
0266 goto out;
0267 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_REPLACE);
0268 if (err) {
0269 bpf_printk("sk_assign returned %d, expected 0\n", err);
0270 goto out;
0271 }
0272
0273 ret = SK_PASS;
0274 out:
0275 if (sk)
0276 bpf_sk_release(sk);
0277 return ret;
0278 }
0279
0280
0281 SEC("sk_lookup")
0282 int sk_assign_null(struct bpf_sk_lookup *ctx)
0283 {
0284 struct bpf_sock *sk = NULL;
0285 int err, ret;
0286
0287 ret = SK_DROP;
0288
0289 err = bpf_sk_assign(ctx, NULL, 0);
0290 if (err) {
0291 bpf_printk("sk_assign returned %d, expected 0\n", err);
0292 goto out;
0293 }
0294
0295 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B);
0296 if (!sk)
0297 goto out;
0298 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_REPLACE);
0299 if (err) {
0300 bpf_printk("sk_assign returned %d, expected 0\n", err);
0301 goto out;
0302 }
0303
0304 if (ctx->sk != sk)
0305 goto out;
0306 err = bpf_sk_assign(ctx, NULL, 0);
0307 if (err != -EEXIST)
0308 goto out;
0309 err = bpf_sk_assign(ctx, NULL, BPF_SK_LOOKUP_F_REPLACE);
0310 if (err)
0311 goto out;
0312 err = bpf_sk_assign(ctx, sk, BPF_SK_LOOKUP_F_REPLACE);
0313 if (err)
0314 goto out;
0315
0316 ret = SK_PASS;
0317 out:
0318 if (sk)
0319 bpf_sk_release(sk);
0320 return ret;
0321 }
0322
0323
0324 SEC("sk_lookup")
0325 int access_ctx_sk(struct bpf_sk_lookup *ctx)
0326 {
0327 struct bpf_sock *sk1 = NULL, *sk2 = NULL;
0328 int err, ret;
0329
0330 ret = SK_DROP;
0331
0332
0333 if (ctx->sk && ctx->sk->family != AF_INET)
0334 goto out;
0335
0336
0337 sk1 = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0338 if (!sk1)
0339 goto out;
0340 err = bpf_sk_assign(ctx, sk1, 0);
0341 if (err)
0342 goto out;
0343 if (ctx->sk != sk1)
0344 goto out;
0345
0346
0347 if (ctx->sk->family != AF_INET ||
0348 ctx->sk->type != SOCK_STREAM ||
0349 ctx->sk->state != BPF_TCP_LISTEN)
0350 goto out;
0351
0352
0353 err = bpf_sk_assign(ctx, NULL, BPF_SK_LOOKUP_F_REPLACE);
0354 if (err)
0355 goto out;
0356 if (ctx->sk)
0357 goto out;
0358
0359
0360 sk2 = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B);
0361 if (!sk2)
0362 goto out;
0363 err = bpf_sk_assign(ctx, sk2, BPF_SK_LOOKUP_F_REPLACE);
0364 if (err)
0365 goto out;
0366 if (ctx->sk != sk2)
0367 goto out;
0368
0369
0370 if (ctx->sk->family != AF_INET ||
0371 ctx->sk->type != SOCK_STREAM ||
0372 ctx->sk->state != BPF_TCP_LISTEN)
0373 goto out;
0374
0375 ret = SK_PASS;
0376 out:
0377 if (sk1)
0378 bpf_sk_release(sk1);
0379 if (sk2)
0380 bpf_sk_release(sk2);
0381 return ret;
0382 }
0383
0384
0385
0386
0387
0388
0389
0390 SEC("sk_lookup")
0391 int ctx_narrow_access(struct bpf_sk_lookup *ctx)
0392 {
0393 struct bpf_sock *sk;
0394 int err, family;
0395 __u32 val_u32;
0396 bool v4;
0397
0398 v4 = (ctx->family == AF_INET);
0399
0400
0401 if (LSB(ctx->family, 0) != (v4 ? AF_INET : AF_INET6) ||
0402 LSB(ctx->family, 1) != 0 || LSB(ctx->family, 2) != 0 || LSB(ctx->family, 3) != 0)
0403 return SK_DROP;
0404 if (LSW(ctx->family, 0) != (v4 ? AF_INET : AF_INET6))
0405 return SK_DROP;
0406
0407
0408 if (LSB(ctx->protocol, 0) != IPPROTO_TCP ||
0409 LSB(ctx->protocol, 1) != 0 || LSB(ctx->protocol, 2) != 0 || LSB(ctx->protocol, 3) != 0)
0410 return SK_DROP;
0411 if (LSW(ctx->protocol, 0) != IPPROTO_TCP)
0412 return SK_DROP;
0413
0414
0415 if (LSB(ctx->remote_port, 0) != ((SRC_PORT >> 0) & 0xff) ||
0416 LSB(ctx->remote_port, 1) != ((SRC_PORT >> 8) & 0xff))
0417 return SK_DROP;
0418 if (LSW(ctx->remote_port, 0) != SRC_PORT)
0419 return SK_DROP;
0420
0421
0422
0423
0424
0425
0426
0427
0428 val_u32 = *(__u32 *)&ctx->remote_port;
0429 if (val_u32 != SRC_PORT)
0430 return SK_DROP;
0431
0432
0433 if (LSB(ctx->local_port, 0) != ((DST_PORT >> 0) & 0xff) ||
0434 LSB(ctx->local_port, 1) != ((DST_PORT >> 8) & 0xff) ||
0435 LSB(ctx->local_port, 2) != 0 || LSB(ctx->local_port, 3) != 0)
0436 return SK_DROP;
0437 if (LSW(ctx->local_port, 0) != DST_PORT)
0438 return SK_DROP;
0439
0440
0441 if (v4) {
0442
0443 if (LSB(ctx->remote_ip4, 0) != ((SRC_IP4 >> 0) & 0xff) ||
0444 LSB(ctx->remote_ip4, 1) != ((SRC_IP4 >> 8) & 0xff) ||
0445 LSB(ctx->remote_ip4, 2) != ((SRC_IP4 >> 16) & 0xff) ||
0446 LSB(ctx->remote_ip4, 3) != ((SRC_IP4 >> 24) & 0xff))
0447 return SK_DROP;
0448 if (LSW(ctx->remote_ip4, 0) != ((SRC_IP4 >> 0) & 0xffff) ||
0449 LSW(ctx->remote_ip4, 1) != ((SRC_IP4 >> 16) & 0xffff))
0450 return SK_DROP;
0451
0452
0453 if (LSB(ctx->local_ip4, 0) != ((DST_IP4 >> 0) & 0xff) ||
0454 LSB(ctx->local_ip4, 1) != ((DST_IP4 >> 8) & 0xff) ||
0455 LSB(ctx->local_ip4, 2) != ((DST_IP4 >> 16) & 0xff) ||
0456 LSB(ctx->local_ip4, 3) != ((DST_IP4 >> 24) & 0xff))
0457 return SK_DROP;
0458 if (LSW(ctx->local_ip4, 0) != ((DST_IP4 >> 0) & 0xffff) ||
0459 LSW(ctx->local_ip4, 1) != ((DST_IP4 >> 16) & 0xffff))
0460 return SK_DROP;
0461 } else {
0462
0463 if (LSB(ctx->remote_ip4, 0) != 0 || LSB(ctx->remote_ip4, 1) != 0 ||
0464 LSB(ctx->remote_ip4, 2) != 0 || LSB(ctx->remote_ip4, 3) != 0)
0465 return SK_DROP;
0466 if (LSW(ctx->remote_ip4, 0) != 0 || LSW(ctx->remote_ip4, 1) != 0)
0467 return SK_DROP;
0468
0469 if (LSB(ctx->local_ip4, 0) != 0 || LSB(ctx->local_ip4, 1) != 0 ||
0470 LSB(ctx->local_ip4, 2) != 0 || LSB(ctx->local_ip4, 3) != 0)
0471 return SK_DROP;
0472 if (LSW(ctx->local_ip4, 0) != 0 || LSW(ctx->local_ip4, 1) != 0)
0473 return SK_DROP;
0474 }
0475
0476
0477 if (!v4) {
0478
0479 if (LSB(ctx->remote_ip6[0], 0) != ((SRC_IP6[0] >> 0) & 0xff) ||
0480 LSB(ctx->remote_ip6[0], 1) != ((SRC_IP6[0] >> 8) & 0xff) ||
0481 LSB(ctx->remote_ip6[0], 2) != ((SRC_IP6[0] >> 16) & 0xff) ||
0482 LSB(ctx->remote_ip6[0], 3) != ((SRC_IP6[0] >> 24) & 0xff) ||
0483 LSB(ctx->remote_ip6[1], 0) != ((SRC_IP6[1] >> 0) & 0xff) ||
0484 LSB(ctx->remote_ip6[1], 1) != ((SRC_IP6[1] >> 8) & 0xff) ||
0485 LSB(ctx->remote_ip6[1], 2) != ((SRC_IP6[1] >> 16) & 0xff) ||
0486 LSB(ctx->remote_ip6[1], 3) != ((SRC_IP6[1] >> 24) & 0xff) ||
0487 LSB(ctx->remote_ip6[2], 0) != ((SRC_IP6[2] >> 0) & 0xff) ||
0488 LSB(ctx->remote_ip6[2], 1) != ((SRC_IP6[2] >> 8) & 0xff) ||
0489 LSB(ctx->remote_ip6[2], 2) != ((SRC_IP6[2] >> 16) & 0xff) ||
0490 LSB(ctx->remote_ip6[2], 3) != ((SRC_IP6[2] >> 24) & 0xff) ||
0491 LSB(ctx->remote_ip6[3], 0) != ((SRC_IP6[3] >> 0) & 0xff) ||
0492 LSB(ctx->remote_ip6[3], 1) != ((SRC_IP6[3] >> 8) & 0xff) ||
0493 LSB(ctx->remote_ip6[3], 2) != ((SRC_IP6[3] >> 16) & 0xff) ||
0494 LSB(ctx->remote_ip6[3], 3) != ((SRC_IP6[3] >> 24) & 0xff))
0495 return SK_DROP;
0496 if (LSW(ctx->remote_ip6[0], 0) != ((SRC_IP6[0] >> 0) & 0xffff) ||
0497 LSW(ctx->remote_ip6[0], 1) != ((SRC_IP6[0] >> 16) & 0xffff) ||
0498 LSW(ctx->remote_ip6[1], 0) != ((SRC_IP6[1] >> 0) & 0xffff) ||
0499 LSW(ctx->remote_ip6[1], 1) != ((SRC_IP6[1] >> 16) & 0xffff) ||
0500 LSW(ctx->remote_ip6[2], 0) != ((SRC_IP6[2] >> 0) & 0xffff) ||
0501 LSW(ctx->remote_ip6[2], 1) != ((SRC_IP6[2] >> 16) & 0xffff) ||
0502 LSW(ctx->remote_ip6[3], 0) != ((SRC_IP6[3] >> 0) & 0xffff) ||
0503 LSW(ctx->remote_ip6[3], 1) != ((SRC_IP6[3] >> 16) & 0xffff))
0504 return SK_DROP;
0505
0506 if (LSB(ctx->local_ip6[0], 0) != ((DST_IP6[0] >> 0) & 0xff) ||
0507 LSB(ctx->local_ip6[0], 1) != ((DST_IP6[0] >> 8) & 0xff) ||
0508 LSB(ctx->local_ip6[0], 2) != ((DST_IP6[0] >> 16) & 0xff) ||
0509 LSB(ctx->local_ip6[0], 3) != ((DST_IP6[0] >> 24) & 0xff) ||
0510 LSB(ctx->local_ip6[1], 0) != ((DST_IP6[1] >> 0) & 0xff) ||
0511 LSB(ctx->local_ip6[1], 1) != ((DST_IP6[1] >> 8) & 0xff) ||
0512 LSB(ctx->local_ip6[1], 2) != ((DST_IP6[1] >> 16) & 0xff) ||
0513 LSB(ctx->local_ip6[1], 3) != ((DST_IP6[1] >> 24) & 0xff) ||
0514 LSB(ctx->local_ip6[2], 0) != ((DST_IP6[2] >> 0) & 0xff) ||
0515 LSB(ctx->local_ip6[2], 1) != ((DST_IP6[2] >> 8) & 0xff) ||
0516 LSB(ctx->local_ip6[2], 2) != ((DST_IP6[2] >> 16) & 0xff) ||
0517 LSB(ctx->local_ip6[2], 3) != ((DST_IP6[2] >> 24) & 0xff) ||
0518 LSB(ctx->local_ip6[3], 0) != ((DST_IP6[3] >> 0) & 0xff) ||
0519 LSB(ctx->local_ip6[3], 1) != ((DST_IP6[3] >> 8) & 0xff) ||
0520 LSB(ctx->local_ip6[3], 2) != ((DST_IP6[3] >> 16) & 0xff) ||
0521 LSB(ctx->local_ip6[3], 3) != ((DST_IP6[3] >> 24) & 0xff))
0522 return SK_DROP;
0523 if (LSW(ctx->local_ip6[0], 0) != ((DST_IP6[0] >> 0) & 0xffff) ||
0524 LSW(ctx->local_ip6[0], 1) != ((DST_IP6[0] >> 16) & 0xffff) ||
0525 LSW(ctx->local_ip6[1], 0) != ((DST_IP6[1] >> 0) & 0xffff) ||
0526 LSW(ctx->local_ip6[1], 1) != ((DST_IP6[1] >> 16) & 0xffff) ||
0527 LSW(ctx->local_ip6[2], 0) != ((DST_IP6[2] >> 0) & 0xffff) ||
0528 LSW(ctx->local_ip6[2], 1) != ((DST_IP6[2] >> 16) & 0xffff) ||
0529 LSW(ctx->local_ip6[3], 0) != ((DST_IP6[3] >> 0) & 0xffff) ||
0530 LSW(ctx->local_ip6[3], 1) != ((DST_IP6[3] >> 16) & 0xffff))
0531 return SK_DROP;
0532 } else {
0533
0534 if (LSB(ctx->remote_ip6[0], 0) != 0 || LSB(ctx->remote_ip6[0], 1) != 0 ||
0535 LSB(ctx->remote_ip6[0], 2) != 0 || LSB(ctx->remote_ip6[0], 3) != 0 ||
0536 LSB(ctx->remote_ip6[1], 0) != 0 || LSB(ctx->remote_ip6[1], 1) != 0 ||
0537 LSB(ctx->remote_ip6[1], 2) != 0 || LSB(ctx->remote_ip6[1], 3) != 0 ||
0538 LSB(ctx->remote_ip6[2], 0) != 0 || LSB(ctx->remote_ip6[2], 1) != 0 ||
0539 LSB(ctx->remote_ip6[2], 2) != 0 || LSB(ctx->remote_ip6[2], 3) != 0 ||
0540 LSB(ctx->remote_ip6[3], 0) != 0 || LSB(ctx->remote_ip6[3], 1) != 0 ||
0541 LSB(ctx->remote_ip6[3], 2) != 0 || LSB(ctx->remote_ip6[3], 3) != 0)
0542 return SK_DROP;
0543 if (LSW(ctx->remote_ip6[0], 0) != 0 || LSW(ctx->remote_ip6[0], 1) != 0 ||
0544 LSW(ctx->remote_ip6[1], 0) != 0 || LSW(ctx->remote_ip6[1], 1) != 0 ||
0545 LSW(ctx->remote_ip6[2], 0) != 0 || LSW(ctx->remote_ip6[2], 1) != 0 ||
0546 LSW(ctx->remote_ip6[3], 0) != 0 || LSW(ctx->remote_ip6[3], 1) != 0)
0547 return SK_DROP;
0548
0549 if (LSB(ctx->local_ip6[0], 0) != 0 || LSB(ctx->local_ip6[0], 1) != 0 ||
0550 LSB(ctx->local_ip6[0], 2) != 0 || LSB(ctx->local_ip6[0], 3) != 0 ||
0551 LSB(ctx->local_ip6[1], 0) != 0 || LSB(ctx->local_ip6[1], 1) != 0 ||
0552 LSB(ctx->local_ip6[1], 2) != 0 || LSB(ctx->local_ip6[1], 3) != 0 ||
0553 LSB(ctx->local_ip6[2], 0) != 0 || LSB(ctx->local_ip6[2], 1) != 0 ||
0554 LSB(ctx->local_ip6[2], 2) != 0 || LSB(ctx->local_ip6[2], 3) != 0 ||
0555 LSB(ctx->local_ip6[3], 0) != 0 || LSB(ctx->local_ip6[3], 1) != 0 ||
0556 LSB(ctx->local_ip6[3], 2) != 0 || LSB(ctx->local_ip6[3], 3) != 0)
0557 return SK_DROP;
0558 if (LSW(ctx->remote_ip6[0], 0) != 0 || LSW(ctx->remote_ip6[0], 1) != 0 ||
0559 LSW(ctx->remote_ip6[1], 0) != 0 || LSW(ctx->remote_ip6[1], 1) != 0 ||
0560 LSW(ctx->remote_ip6[2], 0) != 0 || LSW(ctx->remote_ip6[2], 1) != 0 ||
0561 LSW(ctx->remote_ip6[3], 0) != 0 || LSW(ctx->remote_ip6[3], 1) != 0)
0562 return SK_DROP;
0563 }
0564
0565
0566 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_B);
0567 if (sk) {
0568 bpf_sk_assign(ctx, sk, 0);
0569 bpf_sk_release(sk);
0570 }
0571 return SK_PASS;
0572 }
0573
0574
0575 SEC("sk_lookup")
0576 int sk_assign_esocknosupport(struct bpf_sk_lookup *ctx)
0577 {
0578 struct bpf_sock *sk;
0579 int err, ret;
0580
0581 ret = SK_DROP;
0582 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0583 if (!sk)
0584 goto out;
0585
0586 err = bpf_sk_assign(ctx, sk, 0);
0587 if (err != -ESOCKTNOSUPPORT) {
0588 bpf_printk("sk_assign returned %d, expected %d\n",
0589 err, -ESOCKTNOSUPPORT);
0590 goto out;
0591 }
0592
0593 ret = SK_PASS;
0594 out:
0595 if (sk)
0596 bpf_sk_release(sk);
0597 return ret;
0598 }
0599
0600 SEC("sk_lookup")
0601 int multi_prog_pass1(struct bpf_sk_lookup *ctx)
0602 {
0603 bpf_map_update_elem(&run_map, &KEY_PROG1, &PROG_DONE, BPF_ANY);
0604 return SK_PASS;
0605 }
0606
0607 SEC("sk_lookup")
0608 int multi_prog_pass2(struct bpf_sk_lookup *ctx)
0609 {
0610 bpf_map_update_elem(&run_map, &KEY_PROG2, &PROG_DONE, BPF_ANY);
0611 return SK_PASS;
0612 }
0613
0614 SEC("sk_lookup")
0615 int multi_prog_drop1(struct bpf_sk_lookup *ctx)
0616 {
0617 bpf_map_update_elem(&run_map, &KEY_PROG1, &PROG_DONE, BPF_ANY);
0618 return SK_DROP;
0619 }
0620
0621 SEC("sk_lookup")
0622 int multi_prog_drop2(struct bpf_sk_lookup *ctx)
0623 {
0624 bpf_map_update_elem(&run_map, &KEY_PROG2, &PROG_DONE, BPF_ANY);
0625 return SK_DROP;
0626 }
0627
0628 static __always_inline int select_server_a(struct bpf_sk_lookup *ctx)
0629 {
0630 struct bpf_sock *sk;
0631 int err;
0632
0633 sk = bpf_map_lookup_elem(&redir_map, &KEY_SERVER_A);
0634 if (!sk)
0635 return SK_DROP;
0636
0637 err = bpf_sk_assign(ctx, sk, 0);
0638 bpf_sk_release(sk);
0639 if (err)
0640 return SK_DROP;
0641
0642 return SK_PASS;
0643 }
0644
0645 SEC("sk_lookup")
0646 int multi_prog_redir1(struct bpf_sk_lookup *ctx)
0647 {
0648 int ret;
0649
0650 ret = select_server_a(ctx);
0651 bpf_map_update_elem(&run_map, &KEY_PROG1, &PROG_DONE, BPF_ANY);
0652 return SK_PASS;
0653 }
0654
0655 SEC("sk_lookup")
0656 int multi_prog_redir2(struct bpf_sk_lookup *ctx)
0657 {
0658 int ret;
0659
0660 ret = select_server_a(ctx);
0661 bpf_map_update_elem(&run_map, &KEY_PROG2, &PROG_DONE, BPF_ANY);
0662 return SK_PASS;
0663 }
0664
0665 char _license[] SEC("license") = "Dual BSD/GPL";