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