Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 // Copyright (c) 2020 Cloudflare
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 /* Macros for least-significant byte and word accesses. */
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 /* Addressable key/value constants for convenience */
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; /* Host byte order */
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 /* Redirect packets destined for port DST_PORT to socket at redir_map[0]. */
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 /* Redirect packets destined for DST_IP4 address to socket at redir_map[0]. */
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 /* Redirect packets destined for DST_IP6 address to socket at redir_map[0]. */
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 /* Check that bpf_sk_assign() returns -EEXIST if socket already selected. */
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; /* Success, redirect to KEY_SERVER_B */
0242 out:
0243     if (sk)
0244         bpf_sk_release(sk);
0245     return ret;
0246 }
0247 
0248 /* Check that bpf_sk_assign(BPF_SK_LOOKUP_F_REPLACE) can override selection. */
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; /* Success, redirect to KEY_SERVER_B */
0274 out:
0275     if (sk)
0276         bpf_sk_release(sk);
0277     return ret;
0278 }
0279 
0280 /* Check that bpf_sk_assign(sk=NULL) is accepted. */
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; /* Success, redirect to KEY_SERVER_B */
0317 out:
0318     if (sk)
0319         bpf_sk_release(sk);
0320     return ret;
0321 }
0322 
0323 /* Check that selected sk is accessible through context. */
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     /* Try accessing unassigned (NULL) ctx->sk field */
0333     if (ctx->sk && ctx->sk->family != AF_INET)
0334         goto out;
0335 
0336     /* Assign a value to ctx->sk */
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     /* Access ctx->sk fields */
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     /* Reset selection */
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     /* Assign another socket */
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     /* Access reassigned ctx->sk fields */
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; /* Success, redirect to KEY_SERVER_B */
0376 out:
0377     if (sk1)
0378         bpf_sk_release(sk1);
0379     if (sk2)
0380         bpf_sk_release(sk2);
0381     return ret;
0382 }
0383 
0384 /* Check narrow loads from ctx fields that support them.
0385  *
0386  * Narrow loads of size >= target field size from a non-zero offset
0387  * are not covered because they give bogus results, that is the
0388  * verifier ignores the offset.
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     /* Narrow loads from family field */
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     /* Narrow loads from protocol field */
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     /* Narrow loads from remote_port field. Expect SRC_PORT. */
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      * NOTE: 4-byte load from bpf_sk_lookup at remote_port offset
0423      * is quirky. It gets rewritten by the access converter to a
0424      * 2-byte load for backward compatibility. Treating the load
0425      * result as a be16 value makes the code portable across
0426      * little- and big-endian platforms.
0427      */
0428     val_u32 = *(__u32 *)&ctx->remote_port;
0429     if (val_u32 != SRC_PORT)
0430         return SK_DROP;
0431 
0432     /* Narrow loads from local_port field. Expect DST_PORT. */
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     /* Narrow loads from IPv4 fields */
0441     if (v4) {
0442         /* Expect SRC_IP4 in remote_ip4 */
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         /* Expect DST_IP4 in local_ip4 */
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         /* Expect 0.0.0.0 IPs when family != AF_INET */
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     /* Narrow loads from IPv6 fields */
0477     if (!v4) {
0478         /* Expect SRC_IP6 in remote_ip6 */
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         /* Expect DST_IP6 in local_ip6 */
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         /* Expect :: IPs when family != AF_INET6 */
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     /* Success, redirect to KEY_SERVER_B */
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 /* Check that sk_assign rejects SERVER_A socket with -ESOCKNOSUPPORT */
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; /* Success, pass to regular lookup */
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";