linux/tools/testing/selftests/bpf/test_sock_addr.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (c) 2018 Facebook
   3
   4#define _GNU_SOURCE
   5
   6#include <stdio.h>
   7#include <stdlib.h>
   8#include <unistd.h>
   9
  10#include <arpa/inet.h>
  11#include <netinet/in.h>
  12#include <sys/types.h>
  13#include <sys/select.h>
  14#include <sys/socket.h>
  15
  16#include <linux/filter.h>
  17
  18#include <bpf/bpf.h>
  19#include <bpf/libbpf.h>
  20
  21#include "cgroup_helpers.h"
  22#include "bpf_rlimit.h"
  23#include "bpf_util.h"
  24
  25#ifndef ENOTSUPP
  26# define ENOTSUPP 524
  27#endif
  28
  29#define CG_PATH "/foo"
  30#define CONNECT4_PROG_PATH      "./connect4_prog.o"
  31#define CONNECT6_PROG_PATH      "./connect6_prog.o"
  32#define SENDMSG4_PROG_PATH      "./sendmsg4_prog.o"
  33#define SENDMSG6_PROG_PATH      "./sendmsg6_prog.o"
  34#define RECVMSG4_PROG_PATH      "./recvmsg4_prog.o"
  35#define RECVMSG6_PROG_PATH      "./recvmsg6_prog.o"
  36#define BIND4_PROG_PATH         "./bind4_prog.o"
  37#define BIND6_PROG_PATH         "./bind6_prog.o"
  38
  39#define SERV4_IP                "192.168.1.254"
  40#define SERV4_REWRITE_IP        "127.0.0.1"
  41#define SRC4_IP                 "172.16.0.1"
  42#define SRC4_REWRITE_IP         "127.0.0.4"
  43#define SERV4_PORT              4040
  44#define SERV4_REWRITE_PORT      4444
  45
  46#define SERV6_IP                "face:b00c:1234:5678::abcd"
  47#define SERV6_REWRITE_IP        "::1"
  48#define SERV6_V4MAPPED_IP       "::ffff:192.168.0.4"
  49#define SRC6_IP                 "::1"
  50#define SRC6_REWRITE_IP         "::6"
  51#define WILDCARD6_IP            "::"
  52#define SERV6_PORT              6060
  53#define SERV6_REWRITE_PORT      6666
  54
  55#define INET_NTOP_BUF   40
  56
  57struct sock_addr_test;
  58
  59typedef int (*load_fn)(const struct sock_addr_test *test);
  60typedef int (*info_fn)(int, struct sockaddr *, socklen_t *);
  61
  62char bpf_log_buf[BPF_LOG_BUF_SIZE];
  63
  64struct sock_addr_test {
  65        const char *descr;
  66        /* BPF prog properties */
  67        load_fn loadfn;
  68        enum bpf_attach_type expected_attach_type;
  69        enum bpf_attach_type attach_type;
  70        /* Socket properties */
  71        int domain;
  72        int type;
  73        /* IP:port pairs for BPF prog to override */
  74        const char *requested_ip;
  75        unsigned short requested_port;
  76        const char *expected_ip;
  77        unsigned short expected_port;
  78        const char *expected_src_ip;
  79        /* Expected test result */
  80        enum {
  81                LOAD_REJECT,
  82                ATTACH_REJECT,
  83                ATTACH_OKAY,
  84                SYSCALL_EPERM,
  85                SYSCALL_ENOTSUPP,
  86                SUCCESS,
  87        } expected_result;
  88};
  89
  90static int bind4_prog_load(const struct sock_addr_test *test);
  91static int bind6_prog_load(const struct sock_addr_test *test);
  92static int connect4_prog_load(const struct sock_addr_test *test);
  93static int connect6_prog_load(const struct sock_addr_test *test);
  94static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
  95static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
  96static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
  97static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
  98static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
  99static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test);
 100static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
 101static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
 102static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 103static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 104static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
 105static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
 106
 107static struct sock_addr_test tests[] = {
 108        /* bind */
 109        {
 110                "bind4: load prog with wrong expected attach type",
 111                bind4_prog_load,
 112                BPF_CGROUP_INET6_BIND,
 113                BPF_CGROUP_INET4_BIND,
 114                AF_INET,
 115                SOCK_STREAM,
 116                NULL,
 117                0,
 118                NULL,
 119                0,
 120                NULL,
 121                LOAD_REJECT,
 122        },
 123        {
 124                "bind4: attach prog with wrong attach type",
 125                bind4_prog_load,
 126                BPF_CGROUP_INET4_BIND,
 127                BPF_CGROUP_INET6_BIND,
 128                AF_INET,
 129                SOCK_STREAM,
 130                NULL,
 131                0,
 132                NULL,
 133                0,
 134                NULL,
 135                ATTACH_REJECT,
 136        },
 137        {
 138                "bind4: rewrite IP & TCP port in",
 139                bind4_prog_load,
 140                BPF_CGROUP_INET4_BIND,
 141                BPF_CGROUP_INET4_BIND,
 142                AF_INET,
 143                SOCK_STREAM,
 144                SERV4_IP,
 145                SERV4_PORT,
 146                SERV4_REWRITE_IP,
 147                SERV4_REWRITE_PORT,
 148                NULL,
 149                SUCCESS,
 150        },
 151        {
 152                "bind4: rewrite IP & UDP port in",
 153                bind4_prog_load,
 154                BPF_CGROUP_INET4_BIND,
 155                BPF_CGROUP_INET4_BIND,
 156                AF_INET,
 157                SOCK_DGRAM,
 158                SERV4_IP,
 159                SERV4_PORT,
 160                SERV4_REWRITE_IP,
 161                SERV4_REWRITE_PORT,
 162                NULL,
 163                SUCCESS,
 164        },
 165        {
 166                "bind6: load prog with wrong expected attach type",
 167                bind6_prog_load,
 168                BPF_CGROUP_INET4_BIND,
 169                BPF_CGROUP_INET6_BIND,
 170                AF_INET6,
 171                SOCK_STREAM,
 172                NULL,
 173                0,
 174                NULL,
 175                0,
 176                NULL,
 177                LOAD_REJECT,
 178        },
 179        {
 180                "bind6: attach prog with wrong attach type",
 181                bind6_prog_load,
 182                BPF_CGROUP_INET6_BIND,
 183                BPF_CGROUP_INET4_BIND,
 184                AF_INET,
 185                SOCK_STREAM,
 186                NULL,
 187                0,
 188                NULL,
 189                0,
 190                NULL,
 191                ATTACH_REJECT,
 192        },
 193        {
 194                "bind6: rewrite IP & TCP port in",
 195                bind6_prog_load,
 196                BPF_CGROUP_INET6_BIND,
 197                BPF_CGROUP_INET6_BIND,
 198                AF_INET6,
 199                SOCK_STREAM,
 200                SERV6_IP,
 201                SERV6_PORT,
 202                SERV6_REWRITE_IP,
 203                SERV6_REWRITE_PORT,
 204                NULL,
 205                SUCCESS,
 206        },
 207        {
 208                "bind6: rewrite IP & UDP port in",
 209                bind6_prog_load,
 210                BPF_CGROUP_INET6_BIND,
 211                BPF_CGROUP_INET6_BIND,
 212                AF_INET6,
 213                SOCK_DGRAM,
 214                SERV6_IP,
 215                SERV6_PORT,
 216                SERV6_REWRITE_IP,
 217                SERV6_REWRITE_PORT,
 218                NULL,
 219                SUCCESS,
 220        },
 221
 222        /* connect */
 223        {
 224                "connect4: load prog with wrong expected attach type",
 225                connect4_prog_load,
 226                BPF_CGROUP_INET6_CONNECT,
 227                BPF_CGROUP_INET4_CONNECT,
 228                AF_INET,
 229                SOCK_STREAM,
 230                NULL,
 231                0,
 232                NULL,
 233                0,
 234                NULL,
 235                LOAD_REJECT,
 236        },
 237        {
 238                "connect4: attach prog with wrong attach type",
 239                connect4_prog_load,
 240                BPF_CGROUP_INET4_CONNECT,
 241                BPF_CGROUP_INET6_CONNECT,
 242                AF_INET,
 243                SOCK_STREAM,
 244                NULL,
 245                0,
 246                NULL,
 247                0,
 248                NULL,
 249                ATTACH_REJECT,
 250        },
 251        {
 252                "connect4: rewrite IP & TCP port",
 253                connect4_prog_load,
 254                BPF_CGROUP_INET4_CONNECT,
 255                BPF_CGROUP_INET4_CONNECT,
 256                AF_INET,
 257                SOCK_STREAM,
 258                SERV4_IP,
 259                SERV4_PORT,
 260                SERV4_REWRITE_IP,
 261                SERV4_REWRITE_PORT,
 262                SRC4_REWRITE_IP,
 263                SUCCESS,
 264        },
 265        {
 266                "connect4: rewrite IP & UDP port",
 267                connect4_prog_load,
 268                BPF_CGROUP_INET4_CONNECT,
 269                BPF_CGROUP_INET4_CONNECT,
 270                AF_INET,
 271                SOCK_DGRAM,
 272                SERV4_IP,
 273                SERV4_PORT,
 274                SERV4_REWRITE_IP,
 275                SERV4_REWRITE_PORT,
 276                SRC4_REWRITE_IP,
 277                SUCCESS,
 278        },
 279        {
 280                "connect6: load prog with wrong expected attach type",
 281                connect6_prog_load,
 282                BPF_CGROUP_INET4_CONNECT,
 283                BPF_CGROUP_INET6_CONNECT,
 284                AF_INET6,
 285                SOCK_STREAM,
 286                NULL,
 287                0,
 288                NULL,
 289                0,
 290                NULL,
 291                LOAD_REJECT,
 292        },
 293        {
 294                "connect6: attach prog with wrong attach type",
 295                connect6_prog_load,
 296                BPF_CGROUP_INET6_CONNECT,
 297                BPF_CGROUP_INET4_CONNECT,
 298                AF_INET,
 299                SOCK_STREAM,
 300                NULL,
 301                0,
 302                NULL,
 303                0,
 304                NULL,
 305                ATTACH_REJECT,
 306        },
 307        {
 308                "connect6: rewrite IP & TCP port",
 309                connect6_prog_load,
 310                BPF_CGROUP_INET6_CONNECT,
 311                BPF_CGROUP_INET6_CONNECT,
 312                AF_INET6,
 313                SOCK_STREAM,
 314                SERV6_IP,
 315                SERV6_PORT,
 316                SERV6_REWRITE_IP,
 317                SERV6_REWRITE_PORT,
 318                SRC6_REWRITE_IP,
 319                SUCCESS,
 320        },
 321        {
 322                "connect6: rewrite IP & UDP port",
 323                connect6_prog_load,
 324                BPF_CGROUP_INET6_CONNECT,
 325                BPF_CGROUP_INET6_CONNECT,
 326                AF_INET6,
 327                SOCK_DGRAM,
 328                SERV6_IP,
 329                SERV6_PORT,
 330                SERV6_REWRITE_IP,
 331                SERV6_REWRITE_PORT,
 332                SRC6_REWRITE_IP,
 333                SUCCESS,
 334        },
 335
 336        /* sendmsg */
 337        {
 338                "sendmsg4: load prog with wrong expected attach type",
 339                sendmsg4_rw_asm_prog_load,
 340                BPF_CGROUP_UDP6_SENDMSG,
 341                BPF_CGROUP_UDP4_SENDMSG,
 342                AF_INET,
 343                SOCK_DGRAM,
 344                NULL,
 345                0,
 346                NULL,
 347                0,
 348                NULL,
 349                LOAD_REJECT,
 350        },
 351        {
 352                "sendmsg4: attach prog with wrong attach type",
 353                sendmsg4_rw_asm_prog_load,
 354                BPF_CGROUP_UDP4_SENDMSG,
 355                BPF_CGROUP_UDP6_SENDMSG,
 356                AF_INET,
 357                SOCK_DGRAM,
 358                NULL,
 359                0,
 360                NULL,
 361                0,
 362                NULL,
 363                ATTACH_REJECT,
 364        },
 365        {
 366                "sendmsg4: rewrite IP & port (asm)",
 367                sendmsg4_rw_asm_prog_load,
 368                BPF_CGROUP_UDP4_SENDMSG,
 369                BPF_CGROUP_UDP4_SENDMSG,
 370                AF_INET,
 371                SOCK_DGRAM,
 372                SERV4_IP,
 373                SERV4_PORT,
 374                SERV4_REWRITE_IP,
 375                SERV4_REWRITE_PORT,
 376                SRC4_REWRITE_IP,
 377                SUCCESS,
 378        },
 379        {
 380                "sendmsg4: rewrite IP & port (C)",
 381                sendmsg4_rw_c_prog_load,
 382                BPF_CGROUP_UDP4_SENDMSG,
 383                BPF_CGROUP_UDP4_SENDMSG,
 384                AF_INET,
 385                SOCK_DGRAM,
 386                SERV4_IP,
 387                SERV4_PORT,
 388                SERV4_REWRITE_IP,
 389                SERV4_REWRITE_PORT,
 390                SRC4_REWRITE_IP,
 391                SUCCESS,
 392        },
 393        {
 394                "sendmsg4: deny call",
 395                sendmsg_deny_prog_load,
 396                BPF_CGROUP_UDP4_SENDMSG,
 397                BPF_CGROUP_UDP4_SENDMSG,
 398                AF_INET,
 399                SOCK_DGRAM,
 400                SERV4_IP,
 401                SERV4_PORT,
 402                SERV4_REWRITE_IP,
 403                SERV4_REWRITE_PORT,
 404                SRC4_REWRITE_IP,
 405                SYSCALL_EPERM,
 406        },
 407        {
 408                "sendmsg6: load prog with wrong expected attach type",
 409                sendmsg6_rw_asm_prog_load,
 410                BPF_CGROUP_UDP4_SENDMSG,
 411                BPF_CGROUP_UDP6_SENDMSG,
 412                AF_INET6,
 413                SOCK_DGRAM,
 414                NULL,
 415                0,
 416                NULL,
 417                0,
 418                NULL,
 419                LOAD_REJECT,
 420        },
 421        {
 422                "sendmsg6: attach prog with wrong attach type",
 423                sendmsg6_rw_asm_prog_load,
 424                BPF_CGROUP_UDP6_SENDMSG,
 425                BPF_CGROUP_UDP4_SENDMSG,
 426                AF_INET6,
 427                SOCK_DGRAM,
 428                NULL,
 429                0,
 430                NULL,
 431                0,
 432                NULL,
 433                ATTACH_REJECT,
 434        },
 435        {
 436                "sendmsg6: rewrite IP & port (asm)",
 437                sendmsg6_rw_asm_prog_load,
 438                BPF_CGROUP_UDP6_SENDMSG,
 439                BPF_CGROUP_UDP6_SENDMSG,
 440                AF_INET6,
 441                SOCK_DGRAM,
 442                SERV6_IP,
 443                SERV6_PORT,
 444                SERV6_REWRITE_IP,
 445                SERV6_REWRITE_PORT,
 446                SRC6_REWRITE_IP,
 447                SUCCESS,
 448        },
 449        {
 450                "sendmsg6: rewrite IP & port (C)",
 451                sendmsg6_rw_c_prog_load,
 452                BPF_CGROUP_UDP6_SENDMSG,
 453                BPF_CGROUP_UDP6_SENDMSG,
 454                AF_INET6,
 455                SOCK_DGRAM,
 456                SERV6_IP,
 457                SERV6_PORT,
 458                SERV6_REWRITE_IP,
 459                SERV6_REWRITE_PORT,
 460                SRC6_REWRITE_IP,
 461                SUCCESS,
 462        },
 463        {
 464                "sendmsg6: IPv4-mapped IPv6",
 465                sendmsg6_rw_v4mapped_prog_load,
 466                BPF_CGROUP_UDP6_SENDMSG,
 467                BPF_CGROUP_UDP6_SENDMSG,
 468                AF_INET6,
 469                SOCK_DGRAM,
 470                SERV6_IP,
 471                SERV6_PORT,
 472                SERV6_REWRITE_IP,
 473                SERV6_REWRITE_PORT,
 474                SRC6_REWRITE_IP,
 475                SYSCALL_ENOTSUPP,
 476        },
 477        {
 478                "sendmsg6: set dst IP = [::] (BSD'ism)",
 479                sendmsg6_rw_wildcard_prog_load,
 480                BPF_CGROUP_UDP6_SENDMSG,
 481                BPF_CGROUP_UDP6_SENDMSG,
 482                AF_INET6,
 483                SOCK_DGRAM,
 484                SERV6_IP,
 485                SERV6_PORT,
 486                SERV6_REWRITE_IP,
 487                SERV6_REWRITE_PORT,
 488                SRC6_REWRITE_IP,
 489                SUCCESS,
 490        },
 491        {
 492                "sendmsg6: preserve dst IP = [::] (BSD'ism)",
 493                sendmsg_allow_prog_load,
 494                BPF_CGROUP_UDP6_SENDMSG,
 495                BPF_CGROUP_UDP6_SENDMSG,
 496                AF_INET6,
 497                SOCK_DGRAM,
 498                WILDCARD6_IP,
 499                SERV6_PORT,
 500                SERV6_REWRITE_IP,
 501                SERV6_PORT,
 502                SRC6_IP,
 503                SUCCESS,
 504        },
 505        {
 506                "sendmsg6: deny call",
 507                sendmsg_deny_prog_load,
 508                BPF_CGROUP_UDP6_SENDMSG,
 509                BPF_CGROUP_UDP6_SENDMSG,
 510                AF_INET6,
 511                SOCK_DGRAM,
 512                SERV6_IP,
 513                SERV6_PORT,
 514                SERV6_REWRITE_IP,
 515                SERV6_REWRITE_PORT,
 516                SRC6_REWRITE_IP,
 517                SYSCALL_EPERM,
 518        },
 519
 520        /* recvmsg */
 521        {
 522                "recvmsg4: return code ok",
 523                recvmsg_allow_prog_load,
 524                BPF_CGROUP_UDP4_RECVMSG,
 525                BPF_CGROUP_UDP4_RECVMSG,
 526                AF_INET,
 527                SOCK_DGRAM,
 528                NULL,
 529                0,
 530                NULL,
 531                0,
 532                NULL,
 533                ATTACH_OKAY,
 534        },
 535        {
 536                "recvmsg4: return code !ok",
 537                recvmsg_deny_prog_load,
 538                BPF_CGROUP_UDP4_RECVMSG,
 539                BPF_CGROUP_UDP4_RECVMSG,
 540                AF_INET,
 541                SOCK_DGRAM,
 542                NULL,
 543                0,
 544                NULL,
 545                0,
 546                NULL,
 547                LOAD_REJECT,
 548        },
 549        {
 550                "recvmsg6: return code ok",
 551                recvmsg_allow_prog_load,
 552                BPF_CGROUP_UDP6_RECVMSG,
 553                BPF_CGROUP_UDP6_RECVMSG,
 554                AF_INET6,
 555                SOCK_DGRAM,
 556                NULL,
 557                0,
 558                NULL,
 559                0,
 560                NULL,
 561                ATTACH_OKAY,
 562        },
 563        {
 564                "recvmsg6: return code !ok",
 565                recvmsg_deny_prog_load,
 566                BPF_CGROUP_UDP6_RECVMSG,
 567                BPF_CGROUP_UDP6_RECVMSG,
 568                AF_INET6,
 569                SOCK_DGRAM,
 570                NULL,
 571                0,
 572                NULL,
 573                0,
 574                NULL,
 575                LOAD_REJECT,
 576        },
 577        {
 578                "recvmsg4: rewrite IP & port (C)",
 579                recvmsg4_rw_c_prog_load,
 580                BPF_CGROUP_UDP4_RECVMSG,
 581                BPF_CGROUP_UDP4_RECVMSG,
 582                AF_INET,
 583                SOCK_DGRAM,
 584                SERV4_REWRITE_IP,
 585                SERV4_REWRITE_PORT,
 586                SERV4_REWRITE_IP,
 587                SERV4_REWRITE_PORT,
 588                SERV4_IP,
 589                SUCCESS,
 590        },
 591        {
 592                "recvmsg6: rewrite IP & port (C)",
 593                recvmsg6_rw_c_prog_load,
 594                BPF_CGROUP_UDP6_RECVMSG,
 595                BPF_CGROUP_UDP6_RECVMSG,
 596                AF_INET6,
 597                SOCK_DGRAM,
 598                SERV6_REWRITE_IP,
 599                SERV6_REWRITE_PORT,
 600                SERV6_REWRITE_IP,
 601                SERV6_REWRITE_PORT,
 602                SERV6_IP,
 603                SUCCESS,
 604        },
 605};
 606
 607static int mk_sockaddr(int domain, const char *ip, unsigned short port,
 608                       struct sockaddr *addr, socklen_t addr_len)
 609{
 610        struct sockaddr_in6 *addr6;
 611        struct sockaddr_in *addr4;
 612
 613        if (domain != AF_INET && domain != AF_INET6) {
 614                log_err("Unsupported address family");
 615                return -1;
 616        }
 617
 618        memset(addr, 0, addr_len);
 619
 620        if (domain == AF_INET) {
 621                if (addr_len < sizeof(struct sockaddr_in))
 622                        return -1;
 623                addr4 = (struct sockaddr_in *)addr;
 624                addr4->sin_family = domain;
 625                addr4->sin_port = htons(port);
 626                if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1) {
 627                        log_err("Invalid IPv4: %s", ip);
 628                        return -1;
 629                }
 630        } else if (domain == AF_INET6) {
 631                if (addr_len < sizeof(struct sockaddr_in6))
 632                        return -1;
 633                addr6 = (struct sockaddr_in6 *)addr;
 634                addr6->sin6_family = domain;
 635                addr6->sin6_port = htons(port);
 636                if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1) {
 637                        log_err("Invalid IPv6: %s", ip);
 638                        return -1;
 639                }
 640        }
 641
 642        return 0;
 643}
 644
 645static int load_insns(const struct sock_addr_test *test,
 646                      const struct bpf_insn *insns, size_t insns_cnt)
 647{
 648        struct bpf_load_program_attr load_attr;
 649        int ret;
 650
 651        memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
 652        load_attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
 653        load_attr.expected_attach_type = test->expected_attach_type;
 654        load_attr.insns = insns;
 655        load_attr.insns_cnt = insns_cnt;
 656        load_attr.license = "GPL";
 657
 658        ret = bpf_load_program_xattr(&load_attr, bpf_log_buf, BPF_LOG_BUF_SIZE);
 659        if (ret < 0 && test->expected_result != LOAD_REJECT) {
 660                log_err(">>> Loading program error.\n"
 661                        ">>> Verifier output:\n%s\n-------\n", bpf_log_buf);
 662        }
 663
 664        return ret;
 665}
 666
 667static int load_path(const struct sock_addr_test *test, const char *path)
 668{
 669        struct bpf_prog_load_attr attr;
 670        struct bpf_object *obj;
 671        int prog_fd;
 672
 673        memset(&attr, 0, sizeof(struct bpf_prog_load_attr));
 674        attr.file = path;
 675        attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR;
 676        attr.expected_attach_type = test->expected_attach_type;
 677        attr.prog_flags = BPF_F_TEST_RND_HI32;
 678
 679        if (bpf_prog_load_xattr(&attr, &obj, &prog_fd)) {
 680                if (test->expected_result != LOAD_REJECT)
 681                        log_err(">>> Loading program (%s) error.\n", path);
 682                return -1;
 683        }
 684
 685        return prog_fd;
 686}
 687
 688static int bind4_prog_load(const struct sock_addr_test *test)
 689{
 690        return load_path(test, BIND4_PROG_PATH);
 691}
 692
 693static int bind6_prog_load(const struct sock_addr_test *test)
 694{
 695        return load_path(test, BIND6_PROG_PATH);
 696}
 697
 698static int connect4_prog_load(const struct sock_addr_test *test)
 699{
 700        return load_path(test, CONNECT4_PROG_PATH);
 701}
 702
 703static int connect6_prog_load(const struct sock_addr_test *test)
 704{
 705        return load_path(test, CONNECT6_PROG_PATH);
 706}
 707
 708static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
 709                                   int32_t rc)
 710{
 711        struct bpf_insn insns[] = {
 712                /* return rc */
 713                BPF_MOV64_IMM(BPF_REG_0, rc),
 714                BPF_EXIT_INSN(),
 715        };
 716        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 717}
 718
 719static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
 720{
 721        return xmsg_ret_only_prog_load(test, /*rc*/ 1);
 722}
 723
 724static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
 725{
 726        return xmsg_ret_only_prog_load(test, /*rc*/ 0);
 727}
 728
 729static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
 730{
 731        return xmsg_ret_only_prog_load(test, /*rc*/ 1);
 732}
 733
 734static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
 735{
 736        return xmsg_ret_only_prog_load(test, /*rc*/ 0);
 737}
 738
 739static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
 740{
 741        struct sockaddr_in dst4_rw_addr;
 742        struct in_addr src4_rw_ip;
 743
 744        if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) {
 745                log_err("Invalid IPv4: %s", SRC4_REWRITE_IP);
 746                return -1;
 747        }
 748
 749        if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT,
 750                        (struct sockaddr *)&dst4_rw_addr,
 751                        sizeof(dst4_rw_addr)) == -1)
 752                return -1;
 753
 754        struct bpf_insn insns[] = {
 755                BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
 756
 757                /* if (sk.family == AF_INET && */
 758                BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
 759                            offsetof(struct bpf_sock_addr, family)),
 760                BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 8),
 761
 762                /*     sk.type == SOCK_DGRAM)  { */
 763                BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
 764                            offsetof(struct bpf_sock_addr, type)),
 765                BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 6),
 766
 767                /*      msg_src_ip4 = src4_rw_ip */
 768                BPF_MOV32_IMM(BPF_REG_7, src4_rw_ip.s_addr),
 769                BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
 770                            offsetof(struct bpf_sock_addr, msg_src_ip4)),
 771
 772                /*      user_ip4 = dst4_rw_addr.sin_addr */
 773                BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_addr.s_addr),
 774                BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
 775                            offsetof(struct bpf_sock_addr, user_ip4)),
 776
 777                /*      user_port = dst4_rw_addr.sin_port */
 778                BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_port),
 779                BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
 780                            offsetof(struct bpf_sock_addr, user_port)),
 781                /* } */
 782
 783                /* return 1 */
 784                BPF_MOV64_IMM(BPF_REG_0, 1),
 785                BPF_EXIT_INSN(),
 786        };
 787
 788        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 789}
 790
 791static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test)
 792{
 793        return load_path(test, RECVMSG4_PROG_PATH);
 794}
 795
 796static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
 797{
 798        return load_path(test, SENDMSG4_PROG_PATH);
 799}
 800
 801static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test,
 802                                         const char *rw_dst_ip)
 803{
 804        struct sockaddr_in6 dst6_rw_addr;
 805        struct in6_addr src6_rw_ip;
 806
 807        if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) {
 808                log_err("Invalid IPv6: %s", SRC6_REWRITE_IP);
 809                return -1;
 810        }
 811
 812        if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT,
 813                        (struct sockaddr *)&dst6_rw_addr,
 814                        sizeof(dst6_rw_addr)) == -1)
 815                return -1;
 816
 817        struct bpf_insn insns[] = {
 818                BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
 819
 820                /* if (sk.family == AF_INET6) { */
 821                BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
 822                            offsetof(struct bpf_sock_addr, family)),
 823                BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18),
 824
 825#define STORE_IPV6_WORD_N(DST, SRC, N)                                         \
 826                BPF_MOV32_IMM(BPF_REG_7, SRC[N]),                              \
 827                BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,                       \
 828                            offsetof(struct bpf_sock_addr, DST[N]))
 829
 830#define STORE_IPV6(DST, SRC)                                                   \
 831                STORE_IPV6_WORD_N(DST, SRC, 0),                                \
 832                STORE_IPV6_WORD_N(DST, SRC, 1),                                \
 833                STORE_IPV6_WORD_N(DST, SRC, 2),                                \
 834                STORE_IPV6_WORD_N(DST, SRC, 3)
 835
 836                STORE_IPV6(msg_src_ip6, src6_rw_ip.s6_addr32),
 837                STORE_IPV6(user_ip6, dst6_rw_addr.sin6_addr.s6_addr32),
 838
 839                /*      user_port = dst6_rw_addr.sin6_port */
 840                BPF_MOV32_IMM(BPF_REG_7, dst6_rw_addr.sin6_port),
 841                BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
 842                            offsetof(struct bpf_sock_addr, user_port)),
 843
 844                /* } */
 845
 846                /* return 1 */
 847                BPF_MOV64_IMM(BPF_REG_0, 1),
 848                BPF_EXIT_INSN(),
 849        };
 850
 851        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 852}
 853
 854static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
 855{
 856        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
 857}
 858
 859static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test)
 860{
 861        return load_path(test, RECVMSG6_PROG_PATH);
 862}
 863
 864static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
 865{
 866        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
 867}
 868
 869static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
 870{
 871        return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
 872}
 873
 874static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
 875{
 876        return load_path(test, SENDMSG6_PROG_PATH);
 877}
 878
 879static int cmp_addr(const struct sockaddr_storage *addr1,
 880                    const struct sockaddr_storage *addr2, int cmp_port)
 881{
 882        const struct sockaddr_in *four1, *four2;
 883        const struct sockaddr_in6 *six1, *six2;
 884
 885        if (addr1->ss_family != addr2->ss_family)
 886                return -1;
 887
 888        if (addr1->ss_family == AF_INET) {
 889                four1 = (const struct sockaddr_in *)addr1;
 890                four2 = (const struct sockaddr_in *)addr2;
 891                return !((four1->sin_port == four2->sin_port || !cmp_port) &&
 892                         four1->sin_addr.s_addr == four2->sin_addr.s_addr);
 893        } else if (addr1->ss_family == AF_INET6) {
 894                six1 = (const struct sockaddr_in6 *)addr1;
 895                six2 = (const struct sockaddr_in6 *)addr2;
 896                return !((six1->sin6_port == six2->sin6_port || !cmp_port) &&
 897                         !memcmp(&six1->sin6_addr, &six2->sin6_addr,
 898                                 sizeof(struct in6_addr)));
 899        }
 900
 901        return -1;
 902}
 903
 904static int cmp_sock_addr(info_fn fn, int sock1,
 905                         const struct sockaddr_storage *addr2, int cmp_port)
 906{
 907        struct sockaddr_storage addr1;
 908        socklen_t len1 = sizeof(addr1);
 909
 910        memset(&addr1, 0, len1);
 911        if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0)
 912                return -1;
 913
 914        return cmp_addr(&addr1, addr2, cmp_port);
 915}
 916
 917static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2)
 918{
 919        return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0);
 920}
 921
 922static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2)
 923{
 924        return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1);
 925}
 926
 927static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2)
 928{
 929        return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1);
 930}
 931
 932static int start_server(int type, const struct sockaddr_storage *addr,
 933                        socklen_t addr_len)
 934{
 935        int fd;
 936
 937        fd = socket(addr->ss_family, type, 0);
 938        if (fd == -1) {
 939                log_err("Failed to create server socket");
 940                goto out;
 941        }
 942
 943        if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) {
 944                log_err("Failed to bind server socket");
 945                goto close_out;
 946        }
 947
 948        if (type == SOCK_STREAM) {
 949                if (listen(fd, 128) == -1) {
 950                        log_err("Failed to listen on server socket");
 951                        goto close_out;
 952                }
 953        }
 954
 955        goto out;
 956close_out:
 957        close(fd);
 958        fd = -1;
 959out:
 960        return fd;
 961}
 962
 963static int connect_to_server(int type, const struct sockaddr_storage *addr,
 964                             socklen_t addr_len)
 965{
 966        int domain;
 967        int fd = -1;
 968
 969        domain = addr->ss_family;
 970
 971        if (domain != AF_INET && domain != AF_INET6) {
 972                log_err("Unsupported address family");
 973                goto err;
 974        }
 975
 976        fd = socket(domain, type, 0);
 977        if (fd == -1) {
 978                log_err("Failed to create client socket");
 979                goto err;
 980        }
 981
 982        if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) {
 983                log_err("Fail to connect to server");
 984                goto err;
 985        }
 986
 987        goto out;
 988err:
 989        close(fd);
 990        fd = -1;
 991out:
 992        return fd;
 993}
 994
 995int init_pktinfo(int domain, struct cmsghdr *cmsg)
 996{
 997        struct in6_pktinfo *pktinfo6;
 998        struct in_pktinfo *pktinfo4;
 999
1000        if (domain == AF_INET) {
1001                cmsg->cmsg_level = SOL_IP;
1002                cmsg->cmsg_type = IP_PKTINFO;
1003                cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1004                pktinfo4 = (struct in_pktinfo *)CMSG_DATA(cmsg);
1005                memset(pktinfo4, 0, sizeof(struct in_pktinfo));
1006                if (inet_pton(domain, SRC4_IP,
1007                              (void *)&pktinfo4->ipi_spec_dst) != 1)
1008                        return -1;
1009        } else if (domain == AF_INET6) {
1010                cmsg->cmsg_level = SOL_IPV6;
1011                cmsg->cmsg_type = IPV6_PKTINFO;
1012                cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1013                pktinfo6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1014                memset(pktinfo6, 0, sizeof(struct in6_pktinfo));
1015                if (inet_pton(domain, SRC6_IP,
1016                              (void *)&pktinfo6->ipi6_addr) != 1)
1017                        return -1;
1018        } else {
1019                return -1;
1020        }
1021
1022        return 0;
1023}
1024
1025static int sendmsg_to_server(int type, const struct sockaddr_storage *addr,
1026                             socklen_t addr_len, int set_cmsg, int flags,
1027                             int *syscall_err)
1028{
1029        union {
1030                char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1031                struct cmsghdr align;
1032        } control6;
1033        union {
1034                char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
1035                struct cmsghdr align;
1036        } control4;
1037        struct msghdr hdr;
1038        struct iovec iov;
1039        char data = 'a';
1040        int domain;
1041        int fd = -1;
1042
1043        domain = addr->ss_family;
1044
1045        if (domain != AF_INET && domain != AF_INET6) {
1046                log_err("Unsupported address family");
1047                goto err;
1048        }
1049
1050        fd = socket(domain, type, 0);
1051        if (fd == -1) {
1052                log_err("Failed to create client socket");
1053                goto err;
1054        }
1055
1056        memset(&iov, 0, sizeof(iov));
1057        iov.iov_base = &data;
1058        iov.iov_len = sizeof(data);
1059
1060        memset(&hdr, 0, sizeof(hdr));
1061        hdr.msg_name = (void *)addr;
1062        hdr.msg_namelen = addr_len;
1063        hdr.msg_iov = &iov;
1064        hdr.msg_iovlen = 1;
1065
1066        if (set_cmsg) {
1067                if (domain == AF_INET) {
1068                        hdr.msg_control = &control4;
1069                        hdr.msg_controllen = sizeof(control4.buf);
1070                } else if (domain == AF_INET6) {
1071                        hdr.msg_control = &control6;
1072                        hdr.msg_controllen = sizeof(control6.buf);
1073                }
1074                if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) {
1075                        log_err("Fail to init pktinfo");
1076                        goto err;
1077                }
1078        }
1079
1080        if (sendmsg(fd, &hdr, flags) != sizeof(data)) {
1081                log_err("Fail to send message to server");
1082                *syscall_err = errno;
1083                goto err;
1084        }
1085
1086        goto out;
1087err:
1088        close(fd);
1089        fd = -1;
1090out:
1091        return fd;
1092}
1093
1094static int fastconnect_to_server(const struct sockaddr_storage *addr,
1095                                 socklen_t addr_len)
1096{
1097        int sendmsg_err;
1098
1099        return sendmsg_to_server(SOCK_STREAM, addr, addr_len, /*set_cmsg*/0,
1100                                 MSG_FASTOPEN, &sendmsg_err);
1101}
1102
1103static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr)
1104{
1105        struct timeval tv;
1106        struct msghdr hdr;
1107        struct iovec iov;
1108        char data[64];
1109        fd_set rfds;
1110
1111        FD_ZERO(&rfds);
1112        FD_SET(sockfd, &rfds);
1113
1114        tv.tv_sec = 2;
1115        tv.tv_usec = 0;
1116
1117        if (select(sockfd + 1, &rfds, NULL, NULL, &tv) <= 0 ||
1118            !FD_ISSET(sockfd, &rfds))
1119                return -1;
1120
1121        memset(&iov, 0, sizeof(iov));
1122        iov.iov_base = data;
1123        iov.iov_len = sizeof(data);
1124
1125        memset(&hdr, 0, sizeof(hdr));
1126        hdr.msg_name = src_addr;
1127        hdr.msg_namelen = sizeof(struct sockaddr_storage);
1128        hdr.msg_iov = &iov;
1129        hdr.msg_iovlen = 1;
1130
1131        return recvmsg(sockfd, &hdr, 0);
1132}
1133
1134static int init_addrs(const struct sock_addr_test *test,
1135                      struct sockaddr_storage *requested_addr,
1136                      struct sockaddr_storage *expected_addr,
1137                      struct sockaddr_storage *expected_src_addr)
1138{
1139        socklen_t addr_len = sizeof(struct sockaddr_storage);
1140
1141        if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port,
1142                        (struct sockaddr *)expected_addr, addr_len) == -1)
1143                goto err;
1144
1145        if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port,
1146                        (struct sockaddr *)requested_addr, addr_len) == -1)
1147                goto err;
1148
1149        if (test->expected_src_ip &&
1150            mk_sockaddr(test->domain, test->expected_src_ip, 0,
1151                        (struct sockaddr *)expected_src_addr, addr_len) == -1)
1152                goto err;
1153
1154        return 0;
1155err:
1156        return -1;
1157}
1158
1159static int run_bind_test_case(const struct sock_addr_test *test)
1160{
1161        socklen_t addr_len = sizeof(struct sockaddr_storage);
1162        struct sockaddr_storage requested_addr;
1163        struct sockaddr_storage expected_addr;
1164        int clientfd = -1;
1165        int servfd = -1;
1166        int err = 0;
1167
1168        if (init_addrs(test, &requested_addr, &expected_addr, NULL))
1169                goto err;
1170
1171        servfd = start_server(test->type, &requested_addr, addr_len);
1172        if (servfd == -1)
1173                goto err;
1174
1175        if (cmp_local_addr(servfd, &expected_addr))
1176                goto err;
1177
1178        /* Try to connect to server just in case */
1179        clientfd = connect_to_server(test->type, &expected_addr, addr_len);
1180        if (clientfd == -1)
1181                goto err;
1182
1183        goto out;
1184err:
1185        err = -1;
1186out:
1187        close(clientfd);
1188        close(servfd);
1189        return err;
1190}
1191
1192static int run_connect_test_case(const struct sock_addr_test *test)
1193{
1194        socklen_t addr_len = sizeof(struct sockaddr_storage);
1195        struct sockaddr_storage expected_src_addr;
1196        struct sockaddr_storage requested_addr;
1197        struct sockaddr_storage expected_addr;
1198        int clientfd = -1;
1199        int servfd = -1;
1200        int err = 0;
1201
1202        if (init_addrs(test, &requested_addr, &expected_addr,
1203                       &expected_src_addr))
1204                goto err;
1205
1206        /* Prepare server to connect to */
1207        servfd = start_server(test->type, &expected_addr, addr_len);
1208        if (servfd == -1)
1209                goto err;
1210
1211        clientfd = connect_to_server(test->type, &requested_addr, addr_len);
1212        if (clientfd == -1)
1213                goto err;
1214
1215        /* Make sure src and dst addrs were overridden properly */
1216        if (cmp_peer_addr(clientfd, &expected_addr))
1217                goto err;
1218
1219        if (cmp_local_ip(clientfd, &expected_src_addr))
1220                goto err;
1221
1222        if (test->type == SOCK_STREAM) {
1223                /* Test TCP Fast Open scenario */
1224                clientfd = fastconnect_to_server(&requested_addr, addr_len);
1225                if (clientfd == -1)
1226                        goto err;
1227
1228                /* Make sure src and dst addrs were overridden properly */
1229                if (cmp_peer_addr(clientfd, &expected_addr))
1230                        goto err;
1231
1232                if (cmp_local_ip(clientfd, &expected_src_addr))
1233                        goto err;
1234        }
1235
1236        goto out;
1237err:
1238        err = -1;
1239out:
1240        close(clientfd);
1241        close(servfd);
1242        return err;
1243}
1244
1245static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
1246{
1247        socklen_t addr_len = sizeof(struct sockaddr_storage);
1248        struct sockaddr_storage expected_addr;
1249        struct sockaddr_storage server_addr;
1250        struct sockaddr_storage sendmsg_addr;
1251        struct sockaddr_storage recvmsg_addr;
1252        int clientfd = -1;
1253        int servfd = -1;
1254        int set_cmsg;
1255        int err = 0;
1256
1257        if (test->type != SOCK_DGRAM)
1258                goto err;
1259
1260        if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
1261                goto err;
1262
1263        /* Prepare server to sendmsg to */
1264        servfd = start_server(test->type, &server_addr, addr_len);
1265        if (servfd == -1)
1266                goto err;
1267
1268        for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
1269                if (clientfd >= 0)
1270                        close(clientfd);
1271
1272                clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
1273                                             addr_len, set_cmsg, /*flags*/0,
1274                                             &err);
1275                if (err)
1276                        goto out;
1277                else if (clientfd == -1)
1278                        goto err;
1279
1280                /* Try to receive message on server instead of using
1281                 * getpeername(2) on client socket, to check that client's
1282                 * destination address was rewritten properly, since
1283                 * getpeername(2) doesn't work with unconnected datagram
1284                 * sockets.
1285                 *
1286                 * Get source address from recvmsg(2) as well to make sure
1287                 * source was rewritten properly: getsockname(2) can't be used
1288                 * since socket is unconnected and source defined for one
1289                 * specific packet may differ from the one used by default and
1290                 * returned by getsockname(2).
1291                 */
1292                if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
1293                        goto err;
1294
1295                if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
1296                        goto err;
1297        }
1298
1299        goto out;
1300err:
1301        err = -1;
1302out:
1303        close(clientfd);
1304        close(servfd);
1305        return err;
1306}
1307
1308static int run_test_case(int cgfd, const struct sock_addr_test *test)
1309{
1310        int progfd = -1;
1311        int err = 0;
1312
1313        printf("Test case: %s .. ", test->descr);
1314
1315        progfd = test->loadfn(test);
1316        if (test->expected_result == LOAD_REJECT && progfd < 0)
1317                goto out;
1318        else if (test->expected_result == LOAD_REJECT || progfd < 0)
1319                goto err;
1320
1321        err = bpf_prog_attach(progfd, cgfd, test->attach_type,
1322                              BPF_F_ALLOW_OVERRIDE);
1323        if (test->expected_result == ATTACH_REJECT && err) {
1324                err = 0; /* error was expected, reset it */
1325                goto out;
1326        } else if (test->expected_result == ATTACH_REJECT || err) {
1327                goto err;
1328        } else if (test->expected_result == ATTACH_OKAY) {
1329                err = 0;
1330                goto out;
1331        }
1332
1333        switch (test->attach_type) {
1334        case BPF_CGROUP_INET4_BIND:
1335        case BPF_CGROUP_INET6_BIND:
1336                err = run_bind_test_case(test);
1337                break;
1338        case BPF_CGROUP_INET4_CONNECT:
1339        case BPF_CGROUP_INET6_CONNECT:
1340                err = run_connect_test_case(test);
1341                break;
1342        case BPF_CGROUP_UDP4_SENDMSG:
1343        case BPF_CGROUP_UDP6_SENDMSG:
1344                err = run_xmsg_test_case(test, 1);
1345                break;
1346        case BPF_CGROUP_UDP4_RECVMSG:
1347        case BPF_CGROUP_UDP6_RECVMSG:
1348                err = run_xmsg_test_case(test, 0);
1349                break;
1350        default:
1351                goto err;
1352        }
1353
1354        if (test->expected_result == SYSCALL_EPERM && err == EPERM) {
1355                err = 0; /* error was expected, reset it */
1356                goto out;
1357        }
1358
1359        if (test->expected_result == SYSCALL_ENOTSUPP && err == ENOTSUPP) {
1360                err = 0; /* error was expected, reset it */
1361                goto out;
1362        }
1363
1364        if (err || test->expected_result != SUCCESS)
1365                goto err;
1366
1367        goto out;
1368err:
1369        err = -1;
1370out:
1371        /* Detaching w/o checking return code: best effort attempt. */
1372        if (progfd != -1)
1373                bpf_prog_detach(cgfd, test->attach_type);
1374        close(progfd);
1375        printf("[%s]\n", err ? "FAIL" : "PASS");
1376        return err;
1377}
1378
1379static int run_tests(int cgfd)
1380{
1381        int passes = 0;
1382        int fails = 0;
1383        int i;
1384
1385        for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1386                if (run_test_case(cgfd, &tests[i]))
1387                        ++fails;
1388                else
1389                        ++passes;
1390        }
1391        printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1392        return fails ? -1 : 0;
1393}
1394
1395int main(int argc, char **argv)
1396{
1397        int cgfd = -1;
1398        int err = 0;
1399
1400        if (argc < 2) {
1401                fprintf(stderr,
1402                        "%s has to be run via %s.sh. Skip direct run.\n",
1403                        argv[0], argv[0]);
1404                exit(err);
1405        }
1406
1407        cgfd = cgroup_setup_and_join(CG_PATH);
1408        if (cgfd < 0)
1409                goto err;
1410
1411        if (run_tests(cgfd))
1412                goto err;
1413
1414        goto out;
1415err:
1416        err = -1;
1417out:
1418        close(cgfd);
1419        cleanup_cgroup_environment();
1420        return err;
1421}
1422