Linux Audio

Check our new training course

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