Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2018 Facebook
0003 
0004 #define _GNU_SOURCE
0005 
0006 #include <stdio.h>
0007 #include <stdlib.h>
0008 #include <unistd.h>
0009 
0010 #include <arpa/inet.h>
0011 #include <netinet/in.h>
0012 #include <sys/types.h>
0013 #include <sys/select.h>
0014 #include <sys/socket.h>
0015 
0016 #include <linux/filter.h>
0017 
0018 #include <bpf/bpf.h>
0019 #include <bpf/libbpf.h>
0020 
0021 #include "cgroup_helpers.h"
0022 #include "bpf_util.h"
0023 
0024 #ifndef ENOTSUPP
0025 # define ENOTSUPP 524
0026 #endif
0027 
0028 #define CG_PATH "/foo"
0029 #define CONNECT4_PROG_PATH  "./connect4_prog.o"
0030 #define CONNECT6_PROG_PATH  "./connect6_prog.o"
0031 #define SENDMSG4_PROG_PATH  "./sendmsg4_prog.o"
0032 #define SENDMSG6_PROG_PATH  "./sendmsg6_prog.o"
0033 #define RECVMSG4_PROG_PATH  "./recvmsg4_prog.o"
0034 #define RECVMSG6_PROG_PATH  "./recvmsg6_prog.o"
0035 #define BIND4_PROG_PATH     "./bind4_prog.o"
0036 #define BIND6_PROG_PATH     "./bind6_prog.o"
0037 
0038 #define SERV4_IP        "192.168.1.254"
0039 #define SERV4_REWRITE_IP    "127.0.0.1"
0040 #define SRC4_IP         "172.16.0.1"
0041 #define SRC4_REWRITE_IP     "127.0.0.4"
0042 #define SERV4_PORT      4040
0043 #define SERV4_REWRITE_PORT  4444
0044 
0045 #define SERV6_IP        "face:b00c:1234:5678::abcd"
0046 #define SERV6_REWRITE_IP    "::1"
0047 #define SERV6_V4MAPPED_IP   "::ffff:192.168.0.4"
0048 #define SRC6_IP         "::1"
0049 #define SRC6_REWRITE_IP     "::6"
0050 #define WILDCARD6_IP        "::"
0051 #define SERV6_PORT      6060
0052 #define SERV6_REWRITE_PORT  6666
0053 
0054 #define INET_NTOP_BUF   40
0055 
0056 struct sock_addr_test;
0057 
0058 typedef int (*load_fn)(const struct sock_addr_test *test);
0059 typedef int (*info_fn)(int, struct sockaddr *, socklen_t *);
0060 
0061 char bpf_log_buf[BPF_LOG_BUF_SIZE];
0062 
0063 struct sock_addr_test {
0064     const char *descr;
0065     /* BPF prog properties */
0066     load_fn loadfn;
0067     enum bpf_attach_type expected_attach_type;
0068     enum bpf_attach_type attach_type;
0069     /* Socket properties */
0070     int domain;
0071     int type;
0072     /* IP:port pairs for BPF prog to override */
0073     const char *requested_ip;
0074     unsigned short requested_port;
0075     const char *expected_ip;
0076     unsigned short expected_port;
0077     const char *expected_src_ip;
0078     /* Expected test result */
0079     enum {
0080         LOAD_REJECT,
0081         ATTACH_REJECT,
0082         ATTACH_OKAY,
0083         SYSCALL_EPERM,
0084         SYSCALL_ENOTSUPP,
0085         SUCCESS,
0086     } expected_result;
0087 };
0088 
0089 static int bind4_prog_load(const struct sock_addr_test *test);
0090 static int bind6_prog_load(const struct sock_addr_test *test);
0091 static int connect4_prog_load(const struct sock_addr_test *test);
0092 static int connect6_prog_load(const struct sock_addr_test *test);
0093 static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
0094 static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
0095 static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
0096 static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
0097 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
0098 static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test);
0099 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
0100 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
0101 static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test);
0102 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
0103 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
0104 static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
0105 
0106 static struct sock_addr_test tests[] = {
0107     /* bind */
0108     {
0109         "bind4: load prog with wrong expected attach type",
0110         bind4_prog_load,
0111         BPF_CGROUP_INET6_BIND,
0112         BPF_CGROUP_INET4_BIND,
0113         AF_INET,
0114         SOCK_STREAM,
0115         NULL,
0116         0,
0117         NULL,
0118         0,
0119         NULL,
0120         LOAD_REJECT,
0121     },
0122     {
0123         "bind4: attach prog with wrong attach type",
0124         bind4_prog_load,
0125         BPF_CGROUP_INET4_BIND,
0126         BPF_CGROUP_INET6_BIND,
0127         AF_INET,
0128         SOCK_STREAM,
0129         NULL,
0130         0,
0131         NULL,
0132         0,
0133         NULL,
0134         ATTACH_REJECT,
0135     },
0136     {
0137         "bind4: rewrite IP & TCP port in",
0138         bind4_prog_load,
0139         BPF_CGROUP_INET4_BIND,
0140         BPF_CGROUP_INET4_BIND,
0141         AF_INET,
0142         SOCK_STREAM,
0143         SERV4_IP,
0144         SERV4_PORT,
0145         SERV4_REWRITE_IP,
0146         SERV4_REWRITE_PORT,
0147         NULL,
0148         SUCCESS,
0149     },
0150     {
0151         "bind4: rewrite IP & UDP port in",
0152         bind4_prog_load,
0153         BPF_CGROUP_INET4_BIND,
0154         BPF_CGROUP_INET4_BIND,
0155         AF_INET,
0156         SOCK_DGRAM,
0157         SERV4_IP,
0158         SERV4_PORT,
0159         SERV4_REWRITE_IP,
0160         SERV4_REWRITE_PORT,
0161         NULL,
0162         SUCCESS,
0163     },
0164     {
0165         "bind6: load prog with wrong expected attach type",
0166         bind6_prog_load,
0167         BPF_CGROUP_INET4_BIND,
0168         BPF_CGROUP_INET6_BIND,
0169         AF_INET6,
0170         SOCK_STREAM,
0171         NULL,
0172         0,
0173         NULL,
0174         0,
0175         NULL,
0176         LOAD_REJECT,
0177     },
0178     {
0179         "bind6: attach prog with wrong attach type",
0180         bind6_prog_load,
0181         BPF_CGROUP_INET6_BIND,
0182         BPF_CGROUP_INET4_BIND,
0183         AF_INET,
0184         SOCK_STREAM,
0185         NULL,
0186         0,
0187         NULL,
0188         0,
0189         NULL,
0190         ATTACH_REJECT,
0191     },
0192     {
0193         "bind6: rewrite IP & TCP port in",
0194         bind6_prog_load,
0195         BPF_CGROUP_INET6_BIND,
0196         BPF_CGROUP_INET6_BIND,
0197         AF_INET6,
0198         SOCK_STREAM,
0199         SERV6_IP,
0200         SERV6_PORT,
0201         SERV6_REWRITE_IP,
0202         SERV6_REWRITE_PORT,
0203         NULL,
0204         SUCCESS,
0205     },
0206     {
0207         "bind6: rewrite IP & UDP port in",
0208         bind6_prog_load,
0209         BPF_CGROUP_INET6_BIND,
0210         BPF_CGROUP_INET6_BIND,
0211         AF_INET6,
0212         SOCK_DGRAM,
0213         SERV6_IP,
0214         SERV6_PORT,
0215         SERV6_REWRITE_IP,
0216         SERV6_REWRITE_PORT,
0217         NULL,
0218         SUCCESS,
0219     },
0220 
0221     /* connect */
0222     {
0223         "connect4: load prog with wrong expected attach type",
0224         connect4_prog_load,
0225         BPF_CGROUP_INET6_CONNECT,
0226         BPF_CGROUP_INET4_CONNECT,
0227         AF_INET,
0228         SOCK_STREAM,
0229         NULL,
0230         0,
0231         NULL,
0232         0,
0233         NULL,
0234         LOAD_REJECT,
0235     },
0236     {
0237         "connect4: attach prog with wrong attach type",
0238         connect4_prog_load,
0239         BPF_CGROUP_INET4_CONNECT,
0240         BPF_CGROUP_INET6_CONNECT,
0241         AF_INET,
0242         SOCK_STREAM,
0243         NULL,
0244         0,
0245         NULL,
0246         0,
0247         NULL,
0248         ATTACH_REJECT,
0249     },
0250     {
0251         "connect4: rewrite IP & TCP port",
0252         connect4_prog_load,
0253         BPF_CGROUP_INET4_CONNECT,
0254         BPF_CGROUP_INET4_CONNECT,
0255         AF_INET,
0256         SOCK_STREAM,
0257         SERV4_IP,
0258         SERV4_PORT,
0259         SERV4_REWRITE_IP,
0260         SERV4_REWRITE_PORT,
0261         SRC4_REWRITE_IP,
0262         SUCCESS,
0263     },
0264     {
0265         "connect4: rewrite IP & UDP port",
0266         connect4_prog_load,
0267         BPF_CGROUP_INET4_CONNECT,
0268         BPF_CGROUP_INET4_CONNECT,
0269         AF_INET,
0270         SOCK_DGRAM,
0271         SERV4_IP,
0272         SERV4_PORT,
0273         SERV4_REWRITE_IP,
0274         SERV4_REWRITE_PORT,
0275         SRC4_REWRITE_IP,
0276         SUCCESS,
0277     },
0278     {
0279         "connect6: load prog with wrong expected attach type",
0280         connect6_prog_load,
0281         BPF_CGROUP_INET4_CONNECT,
0282         BPF_CGROUP_INET6_CONNECT,
0283         AF_INET6,
0284         SOCK_STREAM,
0285         NULL,
0286         0,
0287         NULL,
0288         0,
0289         NULL,
0290         LOAD_REJECT,
0291     },
0292     {
0293         "connect6: attach prog with wrong attach type",
0294         connect6_prog_load,
0295         BPF_CGROUP_INET6_CONNECT,
0296         BPF_CGROUP_INET4_CONNECT,
0297         AF_INET,
0298         SOCK_STREAM,
0299         NULL,
0300         0,
0301         NULL,
0302         0,
0303         NULL,
0304         ATTACH_REJECT,
0305     },
0306     {
0307         "connect6: rewrite IP & TCP port",
0308         connect6_prog_load,
0309         BPF_CGROUP_INET6_CONNECT,
0310         BPF_CGROUP_INET6_CONNECT,
0311         AF_INET6,
0312         SOCK_STREAM,
0313         SERV6_IP,
0314         SERV6_PORT,
0315         SERV6_REWRITE_IP,
0316         SERV6_REWRITE_PORT,
0317         SRC6_REWRITE_IP,
0318         SUCCESS,
0319     },
0320     {
0321         "connect6: rewrite IP & UDP port",
0322         connect6_prog_load,
0323         BPF_CGROUP_INET6_CONNECT,
0324         BPF_CGROUP_INET6_CONNECT,
0325         AF_INET6,
0326         SOCK_DGRAM,
0327         SERV6_IP,
0328         SERV6_PORT,
0329         SERV6_REWRITE_IP,
0330         SERV6_REWRITE_PORT,
0331         SRC6_REWRITE_IP,
0332         SUCCESS,
0333     },
0334 
0335     /* sendmsg */
0336     {
0337         "sendmsg4: load prog with wrong expected attach type",
0338         sendmsg4_rw_asm_prog_load,
0339         BPF_CGROUP_UDP6_SENDMSG,
0340         BPF_CGROUP_UDP4_SENDMSG,
0341         AF_INET,
0342         SOCK_DGRAM,
0343         NULL,
0344         0,
0345         NULL,
0346         0,
0347         NULL,
0348         LOAD_REJECT,
0349     },
0350     {
0351         "sendmsg4: attach prog with wrong attach type",
0352         sendmsg4_rw_asm_prog_load,
0353         BPF_CGROUP_UDP4_SENDMSG,
0354         BPF_CGROUP_UDP6_SENDMSG,
0355         AF_INET,
0356         SOCK_DGRAM,
0357         NULL,
0358         0,
0359         NULL,
0360         0,
0361         NULL,
0362         ATTACH_REJECT,
0363     },
0364     {
0365         "sendmsg4: rewrite IP & port (asm)",
0366         sendmsg4_rw_asm_prog_load,
0367         BPF_CGROUP_UDP4_SENDMSG,
0368         BPF_CGROUP_UDP4_SENDMSG,
0369         AF_INET,
0370         SOCK_DGRAM,
0371         SERV4_IP,
0372         SERV4_PORT,
0373         SERV4_REWRITE_IP,
0374         SERV4_REWRITE_PORT,
0375         SRC4_REWRITE_IP,
0376         SUCCESS,
0377     },
0378     {
0379         "sendmsg4: rewrite IP & port (C)",
0380         sendmsg4_rw_c_prog_load,
0381         BPF_CGROUP_UDP4_SENDMSG,
0382         BPF_CGROUP_UDP4_SENDMSG,
0383         AF_INET,
0384         SOCK_DGRAM,
0385         SERV4_IP,
0386         SERV4_PORT,
0387         SERV4_REWRITE_IP,
0388         SERV4_REWRITE_PORT,
0389         SRC4_REWRITE_IP,
0390         SUCCESS,
0391     },
0392     {
0393         "sendmsg4: deny call",
0394         sendmsg_deny_prog_load,
0395         BPF_CGROUP_UDP4_SENDMSG,
0396         BPF_CGROUP_UDP4_SENDMSG,
0397         AF_INET,
0398         SOCK_DGRAM,
0399         SERV4_IP,
0400         SERV4_PORT,
0401         SERV4_REWRITE_IP,
0402         SERV4_REWRITE_PORT,
0403         SRC4_REWRITE_IP,
0404         SYSCALL_EPERM,
0405     },
0406     {
0407         "sendmsg6: load prog with wrong expected attach type",
0408         sendmsg6_rw_asm_prog_load,
0409         BPF_CGROUP_UDP4_SENDMSG,
0410         BPF_CGROUP_UDP6_SENDMSG,
0411         AF_INET6,
0412         SOCK_DGRAM,
0413         NULL,
0414         0,
0415         NULL,
0416         0,
0417         NULL,
0418         LOAD_REJECT,
0419     },
0420     {
0421         "sendmsg6: attach prog with wrong attach type",
0422         sendmsg6_rw_asm_prog_load,
0423         BPF_CGROUP_UDP6_SENDMSG,
0424         BPF_CGROUP_UDP4_SENDMSG,
0425         AF_INET6,
0426         SOCK_DGRAM,
0427         NULL,
0428         0,
0429         NULL,
0430         0,
0431         NULL,
0432         ATTACH_REJECT,
0433     },
0434     {
0435         "sendmsg6: rewrite IP & port (asm)",
0436         sendmsg6_rw_asm_prog_load,
0437         BPF_CGROUP_UDP6_SENDMSG,
0438         BPF_CGROUP_UDP6_SENDMSG,
0439         AF_INET6,
0440         SOCK_DGRAM,
0441         SERV6_IP,
0442         SERV6_PORT,
0443         SERV6_REWRITE_IP,
0444         SERV6_REWRITE_PORT,
0445         SRC6_REWRITE_IP,
0446         SUCCESS,
0447     },
0448     {
0449         "sendmsg6: rewrite IP & port (C)",
0450         sendmsg6_rw_c_prog_load,
0451         BPF_CGROUP_UDP6_SENDMSG,
0452         BPF_CGROUP_UDP6_SENDMSG,
0453         AF_INET6,
0454         SOCK_DGRAM,
0455         SERV6_IP,
0456         SERV6_PORT,
0457         SERV6_REWRITE_IP,
0458         SERV6_REWRITE_PORT,
0459         SRC6_REWRITE_IP,
0460         SUCCESS,
0461     },
0462     {
0463         "sendmsg6: IPv4-mapped IPv6",
0464         sendmsg6_rw_v4mapped_prog_load,
0465         BPF_CGROUP_UDP6_SENDMSG,
0466         BPF_CGROUP_UDP6_SENDMSG,
0467         AF_INET6,
0468         SOCK_DGRAM,
0469         SERV6_IP,
0470         SERV6_PORT,
0471         SERV6_REWRITE_IP,
0472         SERV6_REWRITE_PORT,
0473         SRC6_REWRITE_IP,
0474         SYSCALL_ENOTSUPP,
0475     },
0476     {
0477         "sendmsg6: set dst IP = [::] (BSD'ism)",
0478         sendmsg6_rw_wildcard_prog_load,
0479         BPF_CGROUP_UDP6_SENDMSG,
0480         BPF_CGROUP_UDP6_SENDMSG,
0481         AF_INET6,
0482         SOCK_DGRAM,
0483         SERV6_IP,
0484         SERV6_PORT,
0485         SERV6_REWRITE_IP,
0486         SERV6_REWRITE_PORT,
0487         SRC6_REWRITE_IP,
0488         SUCCESS,
0489     },
0490     {
0491         "sendmsg6: preserve dst IP = [::] (BSD'ism)",
0492         sendmsg_allow_prog_load,
0493         BPF_CGROUP_UDP6_SENDMSG,
0494         BPF_CGROUP_UDP6_SENDMSG,
0495         AF_INET6,
0496         SOCK_DGRAM,
0497         WILDCARD6_IP,
0498         SERV6_PORT,
0499         SERV6_REWRITE_IP,
0500         SERV6_PORT,
0501         SRC6_IP,
0502         SUCCESS,
0503     },
0504     {
0505         "sendmsg6: deny call",
0506         sendmsg_deny_prog_load,
0507         BPF_CGROUP_UDP6_SENDMSG,
0508         BPF_CGROUP_UDP6_SENDMSG,
0509         AF_INET6,
0510         SOCK_DGRAM,
0511         SERV6_IP,
0512         SERV6_PORT,
0513         SERV6_REWRITE_IP,
0514         SERV6_REWRITE_PORT,
0515         SRC6_REWRITE_IP,
0516         SYSCALL_EPERM,
0517     },
0518 
0519     /* recvmsg */
0520     {
0521         "recvmsg4: return code ok",
0522         recvmsg_allow_prog_load,
0523         BPF_CGROUP_UDP4_RECVMSG,
0524         BPF_CGROUP_UDP4_RECVMSG,
0525         AF_INET,
0526         SOCK_DGRAM,
0527         NULL,
0528         0,
0529         NULL,
0530         0,
0531         NULL,
0532         ATTACH_OKAY,
0533     },
0534     {
0535         "recvmsg4: return code !ok",
0536         recvmsg_deny_prog_load,
0537         BPF_CGROUP_UDP4_RECVMSG,
0538         BPF_CGROUP_UDP4_RECVMSG,
0539         AF_INET,
0540         SOCK_DGRAM,
0541         NULL,
0542         0,
0543         NULL,
0544         0,
0545         NULL,
0546         LOAD_REJECT,
0547     },
0548     {
0549         "recvmsg6: return code ok",
0550         recvmsg_allow_prog_load,
0551         BPF_CGROUP_UDP6_RECVMSG,
0552         BPF_CGROUP_UDP6_RECVMSG,
0553         AF_INET6,
0554         SOCK_DGRAM,
0555         NULL,
0556         0,
0557         NULL,
0558         0,
0559         NULL,
0560         ATTACH_OKAY,
0561     },
0562     {
0563         "recvmsg6: return code !ok",
0564         recvmsg_deny_prog_load,
0565         BPF_CGROUP_UDP6_RECVMSG,
0566         BPF_CGROUP_UDP6_RECVMSG,
0567         AF_INET6,
0568         SOCK_DGRAM,
0569         NULL,
0570         0,
0571         NULL,
0572         0,
0573         NULL,
0574         LOAD_REJECT,
0575     },
0576     {
0577         "recvmsg4: rewrite IP & port (C)",
0578         recvmsg4_rw_c_prog_load,
0579         BPF_CGROUP_UDP4_RECVMSG,
0580         BPF_CGROUP_UDP4_RECVMSG,
0581         AF_INET,
0582         SOCK_DGRAM,
0583         SERV4_REWRITE_IP,
0584         SERV4_REWRITE_PORT,
0585         SERV4_REWRITE_IP,
0586         SERV4_REWRITE_PORT,
0587         SERV4_IP,
0588         SUCCESS,
0589     },
0590     {
0591         "recvmsg6: rewrite IP & port (C)",
0592         recvmsg6_rw_c_prog_load,
0593         BPF_CGROUP_UDP6_RECVMSG,
0594         BPF_CGROUP_UDP6_RECVMSG,
0595         AF_INET6,
0596         SOCK_DGRAM,
0597         SERV6_REWRITE_IP,
0598         SERV6_REWRITE_PORT,
0599         SERV6_REWRITE_IP,
0600         SERV6_REWRITE_PORT,
0601         SERV6_IP,
0602         SUCCESS,
0603     },
0604 };
0605 
0606 static int mk_sockaddr(int domain, const char *ip, unsigned short port,
0607                struct sockaddr *addr, socklen_t addr_len)
0608 {
0609     struct sockaddr_in6 *addr6;
0610     struct sockaddr_in *addr4;
0611 
0612     if (domain != AF_INET && domain != AF_INET6) {
0613         log_err("Unsupported address family");
0614         return -1;
0615     }
0616 
0617     memset(addr, 0, addr_len);
0618 
0619     if (domain == AF_INET) {
0620         if (addr_len < sizeof(struct sockaddr_in))
0621             return -1;
0622         addr4 = (struct sockaddr_in *)addr;
0623         addr4->sin_family = domain;
0624         addr4->sin_port = htons(port);
0625         if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1) {
0626             log_err("Invalid IPv4: %s", ip);
0627             return -1;
0628         }
0629     } else if (domain == AF_INET6) {
0630         if (addr_len < sizeof(struct sockaddr_in6))
0631             return -1;
0632         addr6 = (struct sockaddr_in6 *)addr;
0633         addr6->sin6_family = domain;
0634         addr6->sin6_port = htons(port);
0635         if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1) {
0636             log_err("Invalid IPv6: %s", ip);
0637             return -1;
0638         }
0639     }
0640 
0641     return 0;
0642 }
0643 
0644 static int load_insns(const struct sock_addr_test *test,
0645               const struct bpf_insn *insns, size_t insns_cnt)
0646 {
0647     LIBBPF_OPTS(bpf_prog_load_opts, opts);
0648     int ret;
0649 
0650     opts.expected_attach_type = test->expected_attach_type;
0651     opts.log_buf = bpf_log_buf;
0652     opts.log_size = BPF_LOG_BUF_SIZE;
0653 
0654     ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, NULL, "GPL", insns, insns_cnt, &opts);
0655     if (ret < 0 && test->expected_result != LOAD_REJECT) {
0656         log_err(">>> Loading program error.\n"
0657             ">>> Verifier output:\n%s\n-------\n", bpf_log_buf);
0658     }
0659 
0660     return ret;
0661 }
0662 
0663 static int load_path(const struct sock_addr_test *test, const char *path)
0664 {
0665     struct bpf_object *obj;
0666     struct bpf_program *prog;
0667     int err;
0668 
0669     obj = bpf_object__open_file(path, NULL);
0670     err = libbpf_get_error(obj);
0671     if (err) {
0672         log_err(">>> Opening BPF object (%s) error.\n", path);
0673         return -1;
0674     }
0675 
0676     prog = bpf_object__next_program(obj, NULL);
0677     if (!prog)
0678         goto err_out;
0679 
0680     bpf_program__set_type(prog, BPF_PROG_TYPE_CGROUP_SOCK_ADDR);
0681     bpf_program__set_expected_attach_type(prog, test->expected_attach_type);
0682     bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32);
0683 
0684     err = bpf_object__load(obj);
0685     if (err) {
0686         if (test->expected_result != LOAD_REJECT)
0687             log_err(">>> Loading program (%s) error.\n", path);
0688         goto err_out;
0689     }
0690 
0691     return bpf_program__fd(prog);
0692 err_out:
0693     bpf_object__close(obj);
0694     return -1;
0695 }
0696 
0697 static int bind4_prog_load(const struct sock_addr_test *test)
0698 {
0699     return load_path(test, BIND4_PROG_PATH);
0700 }
0701 
0702 static int bind6_prog_load(const struct sock_addr_test *test)
0703 {
0704     return load_path(test, BIND6_PROG_PATH);
0705 }
0706 
0707 static int connect4_prog_load(const struct sock_addr_test *test)
0708 {
0709     return load_path(test, CONNECT4_PROG_PATH);
0710 }
0711 
0712 static int connect6_prog_load(const struct sock_addr_test *test)
0713 {
0714     return load_path(test, CONNECT6_PROG_PATH);
0715 }
0716 
0717 static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
0718                    int32_t rc)
0719 {
0720     struct bpf_insn insns[] = {
0721         /* return rc */
0722         BPF_MOV64_IMM(BPF_REG_0, rc),
0723         BPF_EXIT_INSN(),
0724     };
0725     return load_insns(test, insns, ARRAY_SIZE(insns));
0726 }
0727 
0728 static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
0729 {
0730     return xmsg_ret_only_prog_load(test, /*rc*/ 1);
0731 }
0732 
0733 static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
0734 {
0735     return xmsg_ret_only_prog_load(test, /*rc*/ 0);
0736 }
0737 
0738 static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
0739 {
0740     return xmsg_ret_only_prog_load(test, /*rc*/ 1);
0741 }
0742 
0743 static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
0744 {
0745     return xmsg_ret_only_prog_load(test, /*rc*/ 0);
0746 }
0747 
0748 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
0749 {
0750     struct sockaddr_in dst4_rw_addr;
0751     struct in_addr src4_rw_ip;
0752 
0753     if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) {
0754         log_err("Invalid IPv4: %s", SRC4_REWRITE_IP);
0755         return -1;
0756     }
0757 
0758     if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT,
0759             (struct sockaddr *)&dst4_rw_addr,
0760             sizeof(dst4_rw_addr)) == -1)
0761         return -1;
0762 
0763     struct bpf_insn insns[] = {
0764         BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
0765 
0766         /* if (sk.family == AF_INET && */
0767         BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
0768                 offsetof(struct bpf_sock_addr, family)),
0769         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 8),
0770 
0771         /*     sk.type == SOCK_DGRAM)  { */
0772         BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
0773                 offsetof(struct bpf_sock_addr, type)),
0774         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 6),
0775 
0776         /*      msg_src_ip4 = src4_rw_ip */
0777         BPF_MOV32_IMM(BPF_REG_7, src4_rw_ip.s_addr),
0778         BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
0779                 offsetof(struct bpf_sock_addr, msg_src_ip4)),
0780 
0781         /*      user_ip4 = dst4_rw_addr.sin_addr */
0782         BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_addr.s_addr),
0783         BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
0784                 offsetof(struct bpf_sock_addr, user_ip4)),
0785 
0786         /*      user_port = dst4_rw_addr.sin_port */
0787         BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_port),
0788         BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
0789                 offsetof(struct bpf_sock_addr, user_port)),
0790         /* } */
0791 
0792         /* return 1 */
0793         BPF_MOV64_IMM(BPF_REG_0, 1),
0794         BPF_EXIT_INSN(),
0795     };
0796 
0797     return load_insns(test, insns, ARRAY_SIZE(insns));
0798 }
0799 
0800 static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test)
0801 {
0802     return load_path(test, RECVMSG4_PROG_PATH);
0803 }
0804 
0805 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
0806 {
0807     return load_path(test, SENDMSG4_PROG_PATH);
0808 }
0809 
0810 static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test,
0811                      const char *rw_dst_ip)
0812 {
0813     struct sockaddr_in6 dst6_rw_addr;
0814     struct in6_addr src6_rw_ip;
0815 
0816     if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) {
0817         log_err("Invalid IPv6: %s", SRC6_REWRITE_IP);
0818         return -1;
0819     }
0820 
0821     if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT,
0822             (struct sockaddr *)&dst6_rw_addr,
0823             sizeof(dst6_rw_addr)) == -1)
0824         return -1;
0825 
0826     struct bpf_insn insns[] = {
0827         BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
0828 
0829         /* if (sk.family == AF_INET6) { */
0830         BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
0831                 offsetof(struct bpf_sock_addr, family)),
0832         BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18),
0833 
0834 #define STORE_IPV6_WORD_N(DST, SRC, N)                         \
0835         BPF_MOV32_IMM(BPF_REG_7, SRC[N]),                  \
0836         BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,               \
0837                 offsetof(struct bpf_sock_addr, DST[N]))
0838 
0839 #define STORE_IPV6(DST, SRC)                               \
0840         STORE_IPV6_WORD_N(DST, SRC, 0),                    \
0841         STORE_IPV6_WORD_N(DST, SRC, 1),                    \
0842         STORE_IPV6_WORD_N(DST, SRC, 2),                    \
0843         STORE_IPV6_WORD_N(DST, SRC, 3)
0844 
0845         STORE_IPV6(msg_src_ip6, src6_rw_ip.s6_addr32),
0846         STORE_IPV6(user_ip6, dst6_rw_addr.sin6_addr.s6_addr32),
0847 
0848         /*      user_port = dst6_rw_addr.sin6_port */
0849         BPF_MOV32_IMM(BPF_REG_7, dst6_rw_addr.sin6_port),
0850         BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
0851                 offsetof(struct bpf_sock_addr, user_port)),
0852 
0853         /* } */
0854 
0855         /* return 1 */
0856         BPF_MOV64_IMM(BPF_REG_0, 1),
0857         BPF_EXIT_INSN(),
0858     };
0859 
0860     return load_insns(test, insns, ARRAY_SIZE(insns));
0861 }
0862 
0863 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
0864 {
0865     return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
0866 }
0867 
0868 static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test)
0869 {
0870     return load_path(test, RECVMSG6_PROG_PATH);
0871 }
0872 
0873 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
0874 {
0875     return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
0876 }
0877 
0878 static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
0879 {
0880     return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
0881 }
0882 
0883 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
0884 {
0885     return load_path(test, SENDMSG6_PROG_PATH);
0886 }
0887 
0888 static int cmp_addr(const struct sockaddr_storage *addr1,
0889             const struct sockaddr_storage *addr2, int cmp_port)
0890 {
0891     const struct sockaddr_in *four1, *four2;
0892     const struct sockaddr_in6 *six1, *six2;
0893 
0894     if (addr1->ss_family != addr2->ss_family)
0895         return -1;
0896 
0897     if (addr1->ss_family == AF_INET) {
0898         four1 = (const struct sockaddr_in *)addr1;
0899         four2 = (const struct sockaddr_in *)addr2;
0900         return !((four1->sin_port == four2->sin_port || !cmp_port) &&
0901              four1->sin_addr.s_addr == four2->sin_addr.s_addr);
0902     } else if (addr1->ss_family == AF_INET6) {
0903         six1 = (const struct sockaddr_in6 *)addr1;
0904         six2 = (const struct sockaddr_in6 *)addr2;
0905         return !((six1->sin6_port == six2->sin6_port || !cmp_port) &&
0906              !memcmp(&six1->sin6_addr, &six2->sin6_addr,
0907                  sizeof(struct in6_addr)));
0908     }
0909 
0910     return -1;
0911 }
0912 
0913 static int cmp_sock_addr(info_fn fn, int sock1,
0914              const struct sockaddr_storage *addr2, int cmp_port)
0915 {
0916     struct sockaddr_storage addr1;
0917     socklen_t len1 = sizeof(addr1);
0918 
0919     memset(&addr1, 0, len1);
0920     if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0)
0921         return -1;
0922 
0923     return cmp_addr(&addr1, addr2, cmp_port);
0924 }
0925 
0926 static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2)
0927 {
0928     return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0);
0929 }
0930 
0931 static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2)
0932 {
0933     return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1);
0934 }
0935 
0936 static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2)
0937 {
0938     return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1);
0939 }
0940 
0941 static int start_server(int type, const struct sockaddr_storage *addr,
0942             socklen_t addr_len)
0943 {
0944     int fd;
0945 
0946     fd = socket(addr->ss_family, type, 0);
0947     if (fd == -1) {
0948         log_err("Failed to create server socket");
0949         goto out;
0950     }
0951 
0952     if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) {
0953         log_err("Failed to bind server socket");
0954         goto close_out;
0955     }
0956 
0957     if (type == SOCK_STREAM) {
0958         if (listen(fd, 128) == -1) {
0959             log_err("Failed to listen on server socket");
0960             goto close_out;
0961         }
0962     }
0963 
0964     goto out;
0965 close_out:
0966     close(fd);
0967     fd = -1;
0968 out:
0969     return fd;
0970 }
0971 
0972 static int connect_to_server(int type, const struct sockaddr_storage *addr,
0973                  socklen_t addr_len)
0974 {
0975     int domain;
0976     int fd = -1;
0977 
0978     domain = addr->ss_family;
0979 
0980     if (domain != AF_INET && domain != AF_INET6) {
0981         log_err("Unsupported address family");
0982         goto err;
0983     }
0984 
0985     fd = socket(domain, type, 0);
0986     if (fd == -1) {
0987         log_err("Failed to create client socket");
0988         goto err;
0989     }
0990 
0991     if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) {
0992         log_err("Fail to connect to server");
0993         goto err;
0994     }
0995 
0996     goto out;
0997 err:
0998     close(fd);
0999     fd = -1;
1000 out:
1001     return fd;
1002 }
1003 
1004 int init_pktinfo(int domain, struct cmsghdr *cmsg)
1005 {
1006     struct in6_pktinfo *pktinfo6;
1007     struct in_pktinfo *pktinfo4;
1008 
1009     if (domain == AF_INET) {
1010         cmsg->cmsg_level = SOL_IP;
1011         cmsg->cmsg_type = IP_PKTINFO;
1012         cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1013         pktinfo4 = (struct in_pktinfo *)CMSG_DATA(cmsg);
1014         memset(pktinfo4, 0, sizeof(struct in_pktinfo));
1015         if (inet_pton(domain, SRC4_IP,
1016                   (void *)&pktinfo4->ipi_spec_dst) != 1)
1017             return -1;
1018     } else if (domain == AF_INET6) {
1019         cmsg->cmsg_level = SOL_IPV6;
1020         cmsg->cmsg_type = IPV6_PKTINFO;
1021         cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1022         pktinfo6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1023         memset(pktinfo6, 0, sizeof(struct in6_pktinfo));
1024         if (inet_pton(domain, SRC6_IP,
1025                   (void *)&pktinfo6->ipi6_addr) != 1)
1026             return -1;
1027     } else {
1028         return -1;
1029     }
1030 
1031     return 0;
1032 }
1033 
1034 static int sendmsg_to_server(int type, const struct sockaddr_storage *addr,
1035                  socklen_t addr_len, int set_cmsg, int flags,
1036                  int *syscall_err)
1037 {
1038     union {
1039         char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1040         struct cmsghdr align;
1041     } control6;
1042     union {
1043         char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
1044         struct cmsghdr align;
1045     } control4;
1046     struct msghdr hdr;
1047     struct iovec iov;
1048     char data = 'a';
1049     int domain;
1050     int fd = -1;
1051 
1052     domain = addr->ss_family;
1053 
1054     if (domain != AF_INET && domain != AF_INET6) {
1055         log_err("Unsupported address family");
1056         goto err;
1057     }
1058 
1059     fd = socket(domain, type, 0);
1060     if (fd == -1) {
1061         log_err("Failed to create client socket");
1062         goto err;
1063     }
1064 
1065     memset(&iov, 0, sizeof(iov));
1066     iov.iov_base = &data;
1067     iov.iov_len = sizeof(data);
1068 
1069     memset(&hdr, 0, sizeof(hdr));
1070     hdr.msg_name = (void *)addr;
1071     hdr.msg_namelen = addr_len;
1072     hdr.msg_iov = &iov;
1073     hdr.msg_iovlen = 1;
1074 
1075     if (set_cmsg) {
1076         if (domain == AF_INET) {
1077             hdr.msg_control = &control4;
1078             hdr.msg_controllen = sizeof(control4.buf);
1079         } else if (domain == AF_INET6) {
1080             hdr.msg_control = &control6;
1081             hdr.msg_controllen = sizeof(control6.buf);
1082         }
1083         if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) {
1084             log_err("Fail to init pktinfo");
1085             goto err;
1086         }
1087     }
1088 
1089     if (sendmsg(fd, &hdr, flags) != sizeof(data)) {
1090         log_err("Fail to send message to server");
1091         *syscall_err = errno;
1092         goto err;
1093     }
1094 
1095     goto out;
1096 err:
1097     close(fd);
1098     fd = -1;
1099 out:
1100     return fd;
1101 }
1102 
1103 static int fastconnect_to_server(const struct sockaddr_storage *addr,
1104                  socklen_t addr_len)
1105 {
1106     int sendmsg_err;
1107 
1108     return sendmsg_to_server(SOCK_STREAM, addr, addr_len, /*set_cmsg*/0,
1109                  MSG_FASTOPEN, &sendmsg_err);
1110 }
1111 
1112 static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr)
1113 {
1114     struct timeval tv;
1115     struct msghdr hdr;
1116     struct iovec iov;
1117     char data[64];
1118     fd_set rfds;
1119 
1120     FD_ZERO(&rfds);
1121     FD_SET(sockfd, &rfds);
1122 
1123     tv.tv_sec = 2;
1124     tv.tv_usec = 0;
1125 
1126     if (select(sockfd + 1, &rfds, NULL, NULL, &tv) <= 0 ||
1127         !FD_ISSET(sockfd, &rfds))
1128         return -1;
1129 
1130     memset(&iov, 0, sizeof(iov));
1131     iov.iov_base = data;
1132     iov.iov_len = sizeof(data);
1133 
1134     memset(&hdr, 0, sizeof(hdr));
1135     hdr.msg_name = src_addr;
1136     hdr.msg_namelen = sizeof(struct sockaddr_storage);
1137     hdr.msg_iov = &iov;
1138     hdr.msg_iovlen = 1;
1139 
1140     return recvmsg(sockfd, &hdr, 0);
1141 }
1142 
1143 static int init_addrs(const struct sock_addr_test *test,
1144               struct sockaddr_storage *requested_addr,
1145               struct sockaddr_storage *expected_addr,
1146               struct sockaddr_storage *expected_src_addr)
1147 {
1148     socklen_t addr_len = sizeof(struct sockaddr_storage);
1149 
1150     if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port,
1151             (struct sockaddr *)expected_addr, addr_len) == -1)
1152         goto err;
1153 
1154     if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port,
1155             (struct sockaddr *)requested_addr, addr_len) == -1)
1156         goto err;
1157 
1158     if (test->expected_src_ip &&
1159         mk_sockaddr(test->domain, test->expected_src_ip, 0,
1160             (struct sockaddr *)expected_src_addr, addr_len) == -1)
1161         goto err;
1162 
1163     return 0;
1164 err:
1165     return -1;
1166 }
1167 
1168 static int run_bind_test_case(const struct sock_addr_test *test)
1169 {
1170     socklen_t addr_len = sizeof(struct sockaddr_storage);
1171     struct sockaddr_storage requested_addr;
1172     struct sockaddr_storage expected_addr;
1173     int clientfd = -1;
1174     int servfd = -1;
1175     int err = 0;
1176 
1177     if (init_addrs(test, &requested_addr, &expected_addr, NULL))
1178         goto err;
1179 
1180     servfd = start_server(test->type, &requested_addr, addr_len);
1181     if (servfd == -1)
1182         goto err;
1183 
1184     if (cmp_local_addr(servfd, &expected_addr))
1185         goto err;
1186 
1187     /* Try to connect to server just in case */
1188     clientfd = connect_to_server(test->type, &expected_addr, addr_len);
1189     if (clientfd == -1)
1190         goto err;
1191 
1192     goto out;
1193 err:
1194     err = -1;
1195 out:
1196     close(clientfd);
1197     close(servfd);
1198     return err;
1199 }
1200 
1201 static int run_connect_test_case(const struct sock_addr_test *test)
1202 {
1203     socklen_t addr_len = sizeof(struct sockaddr_storage);
1204     struct sockaddr_storage expected_src_addr;
1205     struct sockaddr_storage requested_addr;
1206     struct sockaddr_storage expected_addr;
1207     int clientfd = -1;
1208     int servfd = -1;
1209     int err = 0;
1210 
1211     if (init_addrs(test, &requested_addr, &expected_addr,
1212                &expected_src_addr))
1213         goto err;
1214 
1215     /* Prepare server to connect to */
1216     servfd = start_server(test->type, &expected_addr, addr_len);
1217     if (servfd == -1)
1218         goto err;
1219 
1220     clientfd = connect_to_server(test->type, &requested_addr, addr_len);
1221     if (clientfd == -1)
1222         goto err;
1223 
1224     /* Make sure src and dst addrs were overridden properly */
1225     if (cmp_peer_addr(clientfd, &expected_addr))
1226         goto err;
1227 
1228     if (cmp_local_ip(clientfd, &expected_src_addr))
1229         goto err;
1230 
1231     if (test->type == SOCK_STREAM) {
1232         /* Test TCP Fast Open scenario */
1233         clientfd = fastconnect_to_server(&requested_addr, addr_len);
1234         if (clientfd == -1)
1235             goto err;
1236 
1237         /* Make sure src and dst addrs were overridden properly */
1238         if (cmp_peer_addr(clientfd, &expected_addr))
1239             goto err;
1240 
1241         if (cmp_local_ip(clientfd, &expected_src_addr))
1242             goto err;
1243     }
1244 
1245     goto out;
1246 err:
1247     err = -1;
1248 out:
1249     close(clientfd);
1250     close(servfd);
1251     return err;
1252 }
1253 
1254 static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
1255 {
1256     socklen_t addr_len = sizeof(struct sockaddr_storage);
1257     struct sockaddr_storage expected_addr;
1258     struct sockaddr_storage server_addr;
1259     struct sockaddr_storage sendmsg_addr;
1260     struct sockaddr_storage recvmsg_addr;
1261     int clientfd = -1;
1262     int servfd = -1;
1263     int set_cmsg;
1264     int err = 0;
1265 
1266     if (test->type != SOCK_DGRAM)
1267         goto err;
1268 
1269     if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
1270         goto err;
1271 
1272     /* Prepare server to sendmsg to */
1273     servfd = start_server(test->type, &server_addr, addr_len);
1274     if (servfd == -1)
1275         goto err;
1276 
1277     for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
1278         if (clientfd >= 0)
1279             close(clientfd);
1280 
1281         clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
1282                          addr_len, set_cmsg, /*flags*/0,
1283                          &err);
1284         if (err)
1285             goto out;
1286         else if (clientfd == -1)
1287             goto err;
1288 
1289         /* Try to receive message on server instead of using
1290          * getpeername(2) on client socket, to check that client's
1291          * destination address was rewritten properly, since
1292          * getpeername(2) doesn't work with unconnected datagram
1293          * sockets.
1294          *
1295          * Get source address from recvmsg(2) as well to make sure
1296          * source was rewritten properly: getsockname(2) can't be used
1297          * since socket is unconnected and source defined for one
1298          * specific packet may differ from the one used by default and
1299          * returned by getsockname(2).
1300          */
1301         if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
1302             goto err;
1303 
1304         if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
1305             goto err;
1306     }
1307 
1308     goto out;
1309 err:
1310     err = -1;
1311 out:
1312     close(clientfd);
1313     close(servfd);
1314     return err;
1315 }
1316 
1317 static int run_test_case(int cgfd, const struct sock_addr_test *test)
1318 {
1319     int progfd = -1;
1320     int err = 0;
1321 
1322     printf("Test case: %s .. ", test->descr);
1323 
1324     progfd = test->loadfn(test);
1325     if (test->expected_result == LOAD_REJECT && progfd < 0)
1326         goto out;
1327     else if (test->expected_result == LOAD_REJECT || progfd < 0)
1328         goto err;
1329 
1330     err = bpf_prog_attach(progfd, cgfd, test->attach_type,
1331                   BPF_F_ALLOW_OVERRIDE);
1332     if (test->expected_result == ATTACH_REJECT && err) {
1333         err = 0; /* error was expected, reset it */
1334         goto out;
1335     } else if (test->expected_result == ATTACH_REJECT || err) {
1336         goto err;
1337     } else if (test->expected_result == ATTACH_OKAY) {
1338         err = 0;
1339         goto out;
1340     }
1341 
1342     switch (test->attach_type) {
1343     case BPF_CGROUP_INET4_BIND:
1344     case BPF_CGROUP_INET6_BIND:
1345         err = run_bind_test_case(test);
1346         break;
1347     case BPF_CGROUP_INET4_CONNECT:
1348     case BPF_CGROUP_INET6_CONNECT:
1349         err = run_connect_test_case(test);
1350         break;
1351     case BPF_CGROUP_UDP4_SENDMSG:
1352     case BPF_CGROUP_UDP6_SENDMSG:
1353         err = run_xmsg_test_case(test, 1);
1354         break;
1355     case BPF_CGROUP_UDP4_RECVMSG:
1356     case BPF_CGROUP_UDP6_RECVMSG:
1357         err = run_xmsg_test_case(test, 0);
1358         break;
1359     default:
1360         goto err;
1361     }
1362 
1363     if (test->expected_result == SYSCALL_EPERM && err == EPERM) {
1364         err = 0; /* error was expected, reset it */
1365         goto out;
1366     }
1367 
1368     if (test->expected_result == SYSCALL_ENOTSUPP && err == ENOTSUPP) {
1369         err = 0; /* error was expected, reset it */
1370         goto out;
1371     }
1372 
1373     if (err || test->expected_result != SUCCESS)
1374         goto err;
1375 
1376     goto out;
1377 err:
1378     err = -1;
1379 out:
1380     /* Detaching w/o checking return code: best effort attempt. */
1381     if (progfd != -1)
1382         bpf_prog_detach(cgfd, test->attach_type);
1383     close(progfd);
1384     printf("[%s]\n", err ? "FAIL" : "PASS");
1385     return err;
1386 }
1387 
1388 static int run_tests(int cgfd)
1389 {
1390     int passes = 0;
1391     int fails = 0;
1392     int i;
1393 
1394     for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1395         if (run_test_case(cgfd, &tests[i]))
1396             ++fails;
1397         else
1398             ++passes;
1399     }
1400     printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1401     return fails ? -1 : 0;
1402 }
1403 
1404 int main(int argc, char **argv)
1405 {
1406     int cgfd = -1;
1407     int err = 0;
1408 
1409     if (argc < 2) {
1410         fprintf(stderr,
1411             "%s has to be run via %s.sh. Skip direct run.\n",
1412             argv[0], argv[0]);
1413         exit(err);
1414     }
1415 
1416     cgfd = cgroup_setup_and_join(CG_PATH);
1417     if (cgfd < 0)
1418         goto err;
1419 
1420     /* Use libbpf 1.0 API mode */
1421     libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1422 
1423     if (run_tests(cgfd))
1424         goto err;
1425 
1426     goto out;
1427 err:
1428     err = -1;
1429 out:
1430     close(cgfd);
1431     cleanup_cgroup_environment();
1432     return err;
1433 }