18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (c) 2018 Facebook 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#define _GNU_SOURCE 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <stdio.h> 78c2ecf20Sopenharmony_ci#include <stdlib.h> 88c2ecf20Sopenharmony_ci#include <unistd.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <arpa/inet.h> 118c2ecf20Sopenharmony_ci#include <netinet/in.h> 128c2ecf20Sopenharmony_ci#include <sys/types.h> 138c2ecf20Sopenharmony_ci#include <sys/select.h> 148c2ecf20Sopenharmony_ci#include <sys/socket.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/filter.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 198c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "cgroup_helpers.h" 228c2ecf20Sopenharmony_ci#include "bpf_rlimit.h" 238c2ecf20Sopenharmony_ci#include "bpf_util.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#ifndef ENOTSUPP 268c2ecf20Sopenharmony_ci# define ENOTSUPP 524 278c2ecf20Sopenharmony_ci#endif 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define CG_PATH "/foo" 308c2ecf20Sopenharmony_ci#define CONNECT4_PROG_PATH "./connect4_prog.o" 318c2ecf20Sopenharmony_ci#define CONNECT6_PROG_PATH "./connect6_prog.o" 328c2ecf20Sopenharmony_ci#define SENDMSG4_PROG_PATH "./sendmsg4_prog.o" 338c2ecf20Sopenharmony_ci#define SENDMSG6_PROG_PATH "./sendmsg6_prog.o" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define SERV4_IP "192.168.1.254" 368c2ecf20Sopenharmony_ci#define SERV4_REWRITE_IP "127.0.0.1" 378c2ecf20Sopenharmony_ci#define SRC4_IP "172.16.0.1" 388c2ecf20Sopenharmony_ci#define SRC4_REWRITE_IP "127.0.0.4" 398c2ecf20Sopenharmony_ci#define SERV4_PORT 4040 408c2ecf20Sopenharmony_ci#define SERV4_REWRITE_PORT 4444 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define SERV6_IP "face:b00c:1234:5678::abcd" 438c2ecf20Sopenharmony_ci#define SERV6_REWRITE_IP "::1" 448c2ecf20Sopenharmony_ci#define SERV6_V4MAPPED_IP "::ffff:192.168.0.4" 458c2ecf20Sopenharmony_ci#define SRC6_IP "::1" 468c2ecf20Sopenharmony_ci#define SRC6_REWRITE_IP "::6" 478c2ecf20Sopenharmony_ci#define WILDCARD6_IP "::" 488c2ecf20Sopenharmony_ci#define SERV6_PORT 6060 498c2ecf20Sopenharmony_ci#define SERV6_REWRITE_PORT 6666 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define INET_NTOP_BUF 40 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistruct sock_addr_test; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_citypedef int (*load_fn)(const struct sock_addr_test *test); 568c2ecf20Sopenharmony_citypedef int (*info_fn)(int, struct sockaddr *, socklen_t *); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cichar bpf_log_buf[BPF_LOG_BUF_SIZE]; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct sock_addr_test { 618c2ecf20Sopenharmony_ci const char *descr; 628c2ecf20Sopenharmony_ci /* BPF prog properties */ 638c2ecf20Sopenharmony_ci load_fn loadfn; 648c2ecf20Sopenharmony_ci enum bpf_attach_type expected_attach_type; 658c2ecf20Sopenharmony_ci enum bpf_attach_type attach_type; 668c2ecf20Sopenharmony_ci /* Socket properties */ 678c2ecf20Sopenharmony_ci int domain; 688c2ecf20Sopenharmony_ci int type; 698c2ecf20Sopenharmony_ci /* IP:port pairs for BPF prog to override */ 708c2ecf20Sopenharmony_ci const char *requested_ip; 718c2ecf20Sopenharmony_ci unsigned short requested_port; 728c2ecf20Sopenharmony_ci const char *expected_ip; 738c2ecf20Sopenharmony_ci unsigned short expected_port; 748c2ecf20Sopenharmony_ci const char *expected_src_ip; 758c2ecf20Sopenharmony_ci /* Expected test result */ 768c2ecf20Sopenharmony_ci enum { 778c2ecf20Sopenharmony_ci LOAD_REJECT, 788c2ecf20Sopenharmony_ci ATTACH_REJECT, 798c2ecf20Sopenharmony_ci ATTACH_OKAY, 808c2ecf20Sopenharmony_ci SYSCALL_EPERM, 818c2ecf20Sopenharmony_ci SYSCALL_ENOTSUPP, 828c2ecf20Sopenharmony_ci SUCCESS, 838c2ecf20Sopenharmony_ci } expected_result; 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic int bind4_prog_load(const struct sock_addr_test *test); 878c2ecf20Sopenharmony_cistatic int bind6_prog_load(const struct sock_addr_test *test); 888c2ecf20Sopenharmony_cistatic int connect4_prog_load(const struct sock_addr_test *test); 898c2ecf20Sopenharmony_cistatic int connect6_prog_load(const struct sock_addr_test *test); 908c2ecf20Sopenharmony_cistatic int sendmsg_allow_prog_load(const struct sock_addr_test *test); 918c2ecf20Sopenharmony_cistatic int sendmsg_deny_prog_load(const struct sock_addr_test *test); 928c2ecf20Sopenharmony_cistatic int recvmsg_allow_prog_load(const struct sock_addr_test *test); 938c2ecf20Sopenharmony_cistatic int recvmsg_deny_prog_load(const struct sock_addr_test *test); 948c2ecf20Sopenharmony_cistatic int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test); 958c2ecf20Sopenharmony_cistatic int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test); 968c2ecf20Sopenharmony_cistatic int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test); 978c2ecf20Sopenharmony_cistatic int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test); 988c2ecf20Sopenharmony_cistatic int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test); 998c2ecf20Sopenharmony_cistatic int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test); 1008c2ecf20Sopenharmony_cistatic int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test); 1018c2ecf20Sopenharmony_cistatic int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic struct sock_addr_test tests[] = { 1048c2ecf20Sopenharmony_ci /* bind */ 1058c2ecf20Sopenharmony_ci { 1068c2ecf20Sopenharmony_ci "bind4: load prog with wrong expected attach type", 1078c2ecf20Sopenharmony_ci bind4_prog_load, 1088c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 1098c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1108c2ecf20Sopenharmony_ci AF_INET, 1118c2ecf20Sopenharmony_ci SOCK_STREAM, 1128c2ecf20Sopenharmony_ci NULL, 1138c2ecf20Sopenharmony_ci 0, 1148c2ecf20Sopenharmony_ci NULL, 1158c2ecf20Sopenharmony_ci 0, 1168c2ecf20Sopenharmony_ci NULL, 1178c2ecf20Sopenharmony_ci LOAD_REJECT, 1188c2ecf20Sopenharmony_ci }, 1198c2ecf20Sopenharmony_ci { 1208c2ecf20Sopenharmony_ci "bind4: attach prog with wrong attach type", 1218c2ecf20Sopenharmony_ci bind4_prog_load, 1228c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1238c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 1248c2ecf20Sopenharmony_ci AF_INET, 1258c2ecf20Sopenharmony_ci SOCK_STREAM, 1268c2ecf20Sopenharmony_ci NULL, 1278c2ecf20Sopenharmony_ci 0, 1288c2ecf20Sopenharmony_ci NULL, 1298c2ecf20Sopenharmony_ci 0, 1308c2ecf20Sopenharmony_ci NULL, 1318c2ecf20Sopenharmony_ci ATTACH_REJECT, 1328c2ecf20Sopenharmony_ci }, 1338c2ecf20Sopenharmony_ci { 1348c2ecf20Sopenharmony_ci "bind4: rewrite IP & TCP port in", 1358c2ecf20Sopenharmony_ci bind4_prog_load, 1368c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1378c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1388c2ecf20Sopenharmony_ci AF_INET, 1398c2ecf20Sopenharmony_ci SOCK_STREAM, 1408c2ecf20Sopenharmony_ci SERV4_IP, 1418c2ecf20Sopenharmony_ci SERV4_PORT, 1428c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 1438c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 1448c2ecf20Sopenharmony_ci NULL, 1458c2ecf20Sopenharmony_ci SUCCESS, 1468c2ecf20Sopenharmony_ci }, 1478c2ecf20Sopenharmony_ci { 1488c2ecf20Sopenharmony_ci "bind4: rewrite IP & UDP port in", 1498c2ecf20Sopenharmony_ci bind4_prog_load, 1508c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1518c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1528c2ecf20Sopenharmony_ci AF_INET, 1538c2ecf20Sopenharmony_ci SOCK_DGRAM, 1548c2ecf20Sopenharmony_ci SERV4_IP, 1558c2ecf20Sopenharmony_ci SERV4_PORT, 1568c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 1578c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 1588c2ecf20Sopenharmony_ci NULL, 1598c2ecf20Sopenharmony_ci SUCCESS, 1608c2ecf20Sopenharmony_ci }, 1618c2ecf20Sopenharmony_ci { 1628c2ecf20Sopenharmony_ci "bind6: load prog with wrong expected attach type", 1638c2ecf20Sopenharmony_ci bind6_prog_load, 1648c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1658c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 1668c2ecf20Sopenharmony_ci AF_INET6, 1678c2ecf20Sopenharmony_ci SOCK_STREAM, 1688c2ecf20Sopenharmony_ci NULL, 1698c2ecf20Sopenharmony_ci 0, 1708c2ecf20Sopenharmony_ci NULL, 1718c2ecf20Sopenharmony_ci 0, 1728c2ecf20Sopenharmony_ci NULL, 1738c2ecf20Sopenharmony_ci LOAD_REJECT, 1748c2ecf20Sopenharmony_ci }, 1758c2ecf20Sopenharmony_ci { 1768c2ecf20Sopenharmony_ci "bind6: attach prog with wrong attach type", 1778c2ecf20Sopenharmony_ci bind6_prog_load, 1788c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 1798c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_BIND, 1808c2ecf20Sopenharmony_ci AF_INET, 1818c2ecf20Sopenharmony_ci SOCK_STREAM, 1828c2ecf20Sopenharmony_ci NULL, 1838c2ecf20Sopenharmony_ci 0, 1848c2ecf20Sopenharmony_ci NULL, 1858c2ecf20Sopenharmony_ci 0, 1868c2ecf20Sopenharmony_ci NULL, 1878c2ecf20Sopenharmony_ci ATTACH_REJECT, 1888c2ecf20Sopenharmony_ci }, 1898c2ecf20Sopenharmony_ci { 1908c2ecf20Sopenharmony_ci "bind6: rewrite IP & TCP port in", 1918c2ecf20Sopenharmony_ci bind6_prog_load, 1928c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 1938c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 1948c2ecf20Sopenharmony_ci AF_INET6, 1958c2ecf20Sopenharmony_ci SOCK_STREAM, 1968c2ecf20Sopenharmony_ci SERV6_IP, 1978c2ecf20Sopenharmony_ci SERV6_PORT, 1988c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 1998c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 2008c2ecf20Sopenharmony_ci NULL, 2018c2ecf20Sopenharmony_ci SUCCESS, 2028c2ecf20Sopenharmony_ci }, 2038c2ecf20Sopenharmony_ci { 2048c2ecf20Sopenharmony_ci "bind6: rewrite IP & UDP port in", 2058c2ecf20Sopenharmony_ci bind6_prog_load, 2068c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 2078c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_BIND, 2088c2ecf20Sopenharmony_ci AF_INET6, 2098c2ecf20Sopenharmony_ci SOCK_DGRAM, 2108c2ecf20Sopenharmony_ci SERV6_IP, 2118c2ecf20Sopenharmony_ci SERV6_PORT, 2128c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 2138c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 2148c2ecf20Sopenharmony_ci NULL, 2158c2ecf20Sopenharmony_ci SUCCESS, 2168c2ecf20Sopenharmony_ci }, 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* connect */ 2198c2ecf20Sopenharmony_ci { 2208c2ecf20Sopenharmony_ci "connect4: load prog with wrong expected attach type", 2218c2ecf20Sopenharmony_ci connect4_prog_load, 2228c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 2238c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2248c2ecf20Sopenharmony_ci AF_INET, 2258c2ecf20Sopenharmony_ci SOCK_STREAM, 2268c2ecf20Sopenharmony_ci NULL, 2278c2ecf20Sopenharmony_ci 0, 2288c2ecf20Sopenharmony_ci NULL, 2298c2ecf20Sopenharmony_ci 0, 2308c2ecf20Sopenharmony_ci NULL, 2318c2ecf20Sopenharmony_ci LOAD_REJECT, 2328c2ecf20Sopenharmony_ci }, 2338c2ecf20Sopenharmony_ci { 2348c2ecf20Sopenharmony_ci "connect4: attach prog with wrong attach type", 2358c2ecf20Sopenharmony_ci connect4_prog_load, 2368c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2378c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 2388c2ecf20Sopenharmony_ci AF_INET, 2398c2ecf20Sopenharmony_ci SOCK_STREAM, 2408c2ecf20Sopenharmony_ci NULL, 2418c2ecf20Sopenharmony_ci 0, 2428c2ecf20Sopenharmony_ci NULL, 2438c2ecf20Sopenharmony_ci 0, 2448c2ecf20Sopenharmony_ci NULL, 2458c2ecf20Sopenharmony_ci ATTACH_REJECT, 2468c2ecf20Sopenharmony_ci }, 2478c2ecf20Sopenharmony_ci { 2488c2ecf20Sopenharmony_ci "connect4: rewrite IP & TCP port", 2498c2ecf20Sopenharmony_ci connect4_prog_load, 2508c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2518c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2528c2ecf20Sopenharmony_ci AF_INET, 2538c2ecf20Sopenharmony_ci SOCK_STREAM, 2548c2ecf20Sopenharmony_ci SERV4_IP, 2558c2ecf20Sopenharmony_ci SERV4_PORT, 2568c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 2578c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 2588c2ecf20Sopenharmony_ci SRC4_REWRITE_IP, 2598c2ecf20Sopenharmony_ci SUCCESS, 2608c2ecf20Sopenharmony_ci }, 2618c2ecf20Sopenharmony_ci { 2628c2ecf20Sopenharmony_ci "connect4: rewrite IP & UDP port", 2638c2ecf20Sopenharmony_ci connect4_prog_load, 2648c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2658c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2668c2ecf20Sopenharmony_ci AF_INET, 2678c2ecf20Sopenharmony_ci SOCK_DGRAM, 2688c2ecf20Sopenharmony_ci SERV4_IP, 2698c2ecf20Sopenharmony_ci SERV4_PORT, 2708c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 2718c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 2728c2ecf20Sopenharmony_ci SRC4_REWRITE_IP, 2738c2ecf20Sopenharmony_ci SUCCESS, 2748c2ecf20Sopenharmony_ci }, 2758c2ecf20Sopenharmony_ci { 2768c2ecf20Sopenharmony_ci "connect6: load prog with wrong expected attach type", 2778c2ecf20Sopenharmony_ci connect6_prog_load, 2788c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2798c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 2808c2ecf20Sopenharmony_ci AF_INET6, 2818c2ecf20Sopenharmony_ci SOCK_STREAM, 2828c2ecf20Sopenharmony_ci NULL, 2838c2ecf20Sopenharmony_ci 0, 2848c2ecf20Sopenharmony_ci NULL, 2858c2ecf20Sopenharmony_ci 0, 2868c2ecf20Sopenharmony_ci NULL, 2878c2ecf20Sopenharmony_ci LOAD_REJECT, 2888c2ecf20Sopenharmony_ci }, 2898c2ecf20Sopenharmony_ci { 2908c2ecf20Sopenharmony_ci "connect6: attach prog with wrong attach type", 2918c2ecf20Sopenharmony_ci connect6_prog_load, 2928c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 2938c2ecf20Sopenharmony_ci BPF_CGROUP_INET4_CONNECT, 2948c2ecf20Sopenharmony_ci AF_INET, 2958c2ecf20Sopenharmony_ci SOCK_STREAM, 2968c2ecf20Sopenharmony_ci NULL, 2978c2ecf20Sopenharmony_ci 0, 2988c2ecf20Sopenharmony_ci NULL, 2998c2ecf20Sopenharmony_ci 0, 3008c2ecf20Sopenharmony_ci NULL, 3018c2ecf20Sopenharmony_ci ATTACH_REJECT, 3028c2ecf20Sopenharmony_ci }, 3038c2ecf20Sopenharmony_ci { 3048c2ecf20Sopenharmony_ci "connect6: rewrite IP & TCP port", 3058c2ecf20Sopenharmony_ci connect6_prog_load, 3068c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 3078c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 3088c2ecf20Sopenharmony_ci AF_INET6, 3098c2ecf20Sopenharmony_ci SOCK_STREAM, 3108c2ecf20Sopenharmony_ci SERV6_IP, 3118c2ecf20Sopenharmony_ci SERV6_PORT, 3128c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 3138c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 3148c2ecf20Sopenharmony_ci SRC6_REWRITE_IP, 3158c2ecf20Sopenharmony_ci SUCCESS, 3168c2ecf20Sopenharmony_ci }, 3178c2ecf20Sopenharmony_ci { 3188c2ecf20Sopenharmony_ci "connect6: rewrite IP & UDP port", 3198c2ecf20Sopenharmony_ci connect6_prog_load, 3208c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 3218c2ecf20Sopenharmony_ci BPF_CGROUP_INET6_CONNECT, 3228c2ecf20Sopenharmony_ci AF_INET6, 3238c2ecf20Sopenharmony_ci SOCK_DGRAM, 3248c2ecf20Sopenharmony_ci SERV6_IP, 3258c2ecf20Sopenharmony_ci SERV6_PORT, 3268c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 3278c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 3288c2ecf20Sopenharmony_ci SRC6_REWRITE_IP, 3298c2ecf20Sopenharmony_ci SUCCESS, 3308c2ecf20Sopenharmony_ci }, 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci /* sendmsg */ 3338c2ecf20Sopenharmony_ci { 3348c2ecf20Sopenharmony_ci "sendmsg4: load prog with wrong expected attach type", 3358c2ecf20Sopenharmony_ci sendmsg4_rw_asm_prog_load, 3368c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 3378c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3388c2ecf20Sopenharmony_ci AF_INET, 3398c2ecf20Sopenharmony_ci SOCK_DGRAM, 3408c2ecf20Sopenharmony_ci NULL, 3418c2ecf20Sopenharmony_ci 0, 3428c2ecf20Sopenharmony_ci NULL, 3438c2ecf20Sopenharmony_ci 0, 3448c2ecf20Sopenharmony_ci NULL, 3458c2ecf20Sopenharmony_ci LOAD_REJECT, 3468c2ecf20Sopenharmony_ci }, 3478c2ecf20Sopenharmony_ci { 3488c2ecf20Sopenharmony_ci "sendmsg4: attach prog with wrong attach type", 3498c2ecf20Sopenharmony_ci sendmsg4_rw_asm_prog_load, 3508c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3518c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 3528c2ecf20Sopenharmony_ci AF_INET, 3538c2ecf20Sopenharmony_ci SOCK_DGRAM, 3548c2ecf20Sopenharmony_ci NULL, 3558c2ecf20Sopenharmony_ci 0, 3568c2ecf20Sopenharmony_ci NULL, 3578c2ecf20Sopenharmony_ci 0, 3588c2ecf20Sopenharmony_ci NULL, 3598c2ecf20Sopenharmony_ci ATTACH_REJECT, 3608c2ecf20Sopenharmony_ci }, 3618c2ecf20Sopenharmony_ci { 3628c2ecf20Sopenharmony_ci "sendmsg4: rewrite IP & port (asm)", 3638c2ecf20Sopenharmony_ci sendmsg4_rw_asm_prog_load, 3648c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3658c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3668c2ecf20Sopenharmony_ci AF_INET, 3678c2ecf20Sopenharmony_ci SOCK_DGRAM, 3688c2ecf20Sopenharmony_ci SERV4_IP, 3698c2ecf20Sopenharmony_ci SERV4_PORT, 3708c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 3718c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 3728c2ecf20Sopenharmony_ci SRC4_REWRITE_IP, 3738c2ecf20Sopenharmony_ci SUCCESS, 3748c2ecf20Sopenharmony_ci }, 3758c2ecf20Sopenharmony_ci { 3768c2ecf20Sopenharmony_ci "sendmsg4: rewrite IP & port (C)", 3778c2ecf20Sopenharmony_ci sendmsg4_rw_c_prog_load, 3788c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3798c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3808c2ecf20Sopenharmony_ci AF_INET, 3818c2ecf20Sopenharmony_ci SOCK_DGRAM, 3828c2ecf20Sopenharmony_ci SERV4_IP, 3838c2ecf20Sopenharmony_ci SERV4_PORT, 3848c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 3858c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 3868c2ecf20Sopenharmony_ci SRC4_REWRITE_IP, 3878c2ecf20Sopenharmony_ci SUCCESS, 3888c2ecf20Sopenharmony_ci }, 3898c2ecf20Sopenharmony_ci { 3908c2ecf20Sopenharmony_ci "sendmsg4: deny call", 3918c2ecf20Sopenharmony_ci sendmsg_deny_prog_load, 3928c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3938c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 3948c2ecf20Sopenharmony_ci AF_INET, 3958c2ecf20Sopenharmony_ci SOCK_DGRAM, 3968c2ecf20Sopenharmony_ci SERV4_IP, 3978c2ecf20Sopenharmony_ci SERV4_PORT, 3988c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 3998c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 4008c2ecf20Sopenharmony_ci SRC4_REWRITE_IP, 4018c2ecf20Sopenharmony_ci SYSCALL_EPERM, 4028c2ecf20Sopenharmony_ci }, 4038c2ecf20Sopenharmony_ci { 4048c2ecf20Sopenharmony_ci "sendmsg6: load prog with wrong expected attach type", 4058c2ecf20Sopenharmony_ci sendmsg6_rw_asm_prog_load, 4068c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 4078c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4088c2ecf20Sopenharmony_ci AF_INET6, 4098c2ecf20Sopenharmony_ci SOCK_DGRAM, 4108c2ecf20Sopenharmony_ci NULL, 4118c2ecf20Sopenharmony_ci 0, 4128c2ecf20Sopenharmony_ci NULL, 4138c2ecf20Sopenharmony_ci 0, 4148c2ecf20Sopenharmony_ci NULL, 4158c2ecf20Sopenharmony_ci LOAD_REJECT, 4168c2ecf20Sopenharmony_ci }, 4178c2ecf20Sopenharmony_ci { 4188c2ecf20Sopenharmony_ci "sendmsg6: attach prog with wrong attach type", 4198c2ecf20Sopenharmony_ci sendmsg6_rw_asm_prog_load, 4208c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4218c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_SENDMSG, 4228c2ecf20Sopenharmony_ci AF_INET6, 4238c2ecf20Sopenharmony_ci SOCK_DGRAM, 4248c2ecf20Sopenharmony_ci NULL, 4258c2ecf20Sopenharmony_ci 0, 4268c2ecf20Sopenharmony_ci NULL, 4278c2ecf20Sopenharmony_ci 0, 4288c2ecf20Sopenharmony_ci NULL, 4298c2ecf20Sopenharmony_ci ATTACH_REJECT, 4308c2ecf20Sopenharmony_ci }, 4318c2ecf20Sopenharmony_ci { 4328c2ecf20Sopenharmony_ci "sendmsg6: rewrite IP & port (asm)", 4338c2ecf20Sopenharmony_ci sendmsg6_rw_asm_prog_load, 4348c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4358c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4368c2ecf20Sopenharmony_ci AF_INET6, 4378c2ecf20Sopenharmony_ci SOCK_DGRAM, 4388c2ecf20Sopenharmony_ci SERV6_IP, 4398c2ecf20Sopenharmony_ci SERV6_PORT, 4408c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 4418c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 4428c2ecf20Sopenharmony_ci SRC6_REWRITE_IP, 4438c2ecf20Sopenharmony_ci SUCCESS, 4448c2ecf20Sopenharmony_ci }, 4458c2ecf20Sopenharmony_ci { 4468c2ecf20Sopenharmony_ci "sendmsg6: rewrite IP & port (C)", 4478c2ecf20Sopenharmony_ci sendmsg6_rw_c_prog_load, 4488c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4498c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4508c2ecf20Sopenharmony_ci AF_INET6, 4518c2ecf20Sopenharmony_ci SOCK_DGRAM, 4528c2ecf20Sopenharmony_ci SERV6_IP, 4538c2ecf20Sopenharmony_ci SERV6_PORT, 4548c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 4558c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 4568c2ecf20Sopenharmony_ci SRC6_REWRITE_IP, 4578c2ecf20Sopenharmony_ci SUCCESS, 4588c2ecf20Sopenharmony_ci }, 4598c2ecf20Sopenharmony_ci { 4608c2ecf20Sopenharmony_ci "sendmsg6: IPv4-mapped IPv6", 4618c2ecf20Sopenharmony_ci sendmsg6_rw_v4mapped_prog_load, 4628c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4638c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4648c2ecf20Sopenharmony_ci AF_INET6, 4658c2ecf20Sopenharmony_ci SOCK_DGRAM, 4668c2ecf20Sopenharmony_ci SERV6_IP, 4678c2ecf20Sopenharmony_ci SERV6_PORT, 4688c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 4698c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 4708c2ecf20Sopenharmony_ci SRC6_REWRITE_IP, 4718c2ecf20Sopenharmony_ci SYSCALL_ENOTSUPP, 4728c2ecf20Sopenharmony_ci }, 4738c2ecf20Sopenharmony_ci { 4748c2ecf20Sopenharmony_ci "sendmsg6: set dst IP = [::] (BSD'ism)", 4758c2ecf20Sopenharmony_ci sendmsg6_rw_wildcard_prog_load, 4768c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4778c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4788c2ecf20Sopenharmony_ci AF_INET6, 4798c2ecf20Sopenharmony_ci SOCK_DGRAM, 4808c2ecf20Sopenharmony_ci SERV6_IP, 4818c2ecf20Sopenharmony_ci SERV6_PORT, 4828c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 4838c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 4848c2ecf20Sopenharmony_ci SRC6_REWRITE_IP, 4858c2ecf20Sopenharmony_ci SUCCESS, 4868c2ecf20Sopenharmony_ci }, 4878c2ecf20Sopenharmony_ci { 4888c2ecf20Sopenharmony_ci "sendmsg6: preserve dst IP = [::] (BSD'ism)", 4898c2ecf20Sopenharmony_ci sendmsg_allow_prog_load, 4908c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4918c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 4928c2ecf20Sopenharmony_ci AF_INET6, 4938c2ecf20Sopenharmony_ci SOCK_DGRAM, 4948c2ecf20Sopenharmony_ci WILDCARD6_IP, 4958c2ecf20Sopenharmony_ci SERV6_PORT, 4968c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 4978c2ecf20Sopenharmony_ci SERV6_PORT, 4988c2ecf20Sopenharmony_ci SRC6_IP, 4998c2ecf20Sopenharmony_ci SUCCESS, 5008c2ecf20Sopenharmony_ci }, 5018c2ecf20Sopenharmony_ci { 5028c2ecf20Sopenharmony_ci "sendmsg6: deny call", 5038c2ecf20Sopenharmony_ci sendmsg_deny_prog_load, 5048c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 5058c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_SENDMSG, 5068c2ecf20Sopenharmony_ci AF_INET6, 5078c2ecf20Sopenharmony_ci SOCK_DGRAM, 5088c2ecf20Sopenharmony_ci SERV6_IP, 5098c2ecf20Sopenharmony_ci SERV6_PORT, 5108c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 5118c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 5128c2ecf20Sopenharmony_ci SRC6_REWRITE_IP, 5138c2ecf20Sopenharmony_ci SYSCALL_EPERM, 5148c2ecf20Sopenharmony_ci }, 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci /* recvmsg */ 5178c2ecf20Sopenharmony_ci { 5188c2ecf20Sopenharmony_ci "recvmsg4: return code ok", 5198c2ecf20Sopenharmony_ci recvmsg_allow_prog_load, 5208c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_RECVMSG, 5218c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_RECVMSG, 5228c2ecf20Sopenharmony_ci AF_INET, 5238c2ecf20Sopenharmony_ci SOCK_DGRAM, 5248c2ecf20Sopenharmony_ci NULL, 5258c2ecf20Sopenharmony_ci 0, 5268c2ecf20Sopenharmony_ci NULL, 5278c2ecf20Sopenharmony_ci 0, 5288c2ecf20Sopenharmony_ci NULL, 5298c2ecf20Sopenharmony_ci ATTACH_OKAY, 5308c2ecf20Sopenharmony_ci }, 5318c2ecf20Sopenharmony_ci { 5328c2ecf20Sopenharmony_ci "recvmsg4: return code !ok", 5338c2ecf20Sopenharmony_ci recvmsg_deny_prog_load, 5348c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_RECVMSG, 5358c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_RECVMSG, 5368c2ecf20Sopenharmony_ci AF_INET, 5378c2ecf20Sopenharmony_ci SOCK_DGRAM, 5388c2ecf20Sopenharmony_ci NULL, 5398c2ecf20Sopenharmony_ci 0, 5408c2ecf20Sopenharmony_ci NULL, 5418c2ecf20Sopenharmony_ci 0, 5428c2ecf20Sopenharmony_ci NULL, 5438c2ecf20Sopenharmony_ci LOAD_REJECT, 5448c2ecf20Sopenharmony_ci }, 5458c2ecf20Sopenharmony_ci { 5468c2ecf20Sopenharmony_ci "recvmsg6: return code ok", 5478c2ecf20Sopenharmony_ci recvmsg_allow_prog_load, 5488c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_RECVMSG, 5498c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_RECVMSG, 5508c2ecf20Sopenharmony_ci AF_INET6, 5518c2ecf20Sopenharmony_ci SOCK_DGRAM, 5528c2ecf20Sopenharmony_ci NULL, 5538c2ecf20Sopenharmony_ci 0, 5548c2ecf20Sopenharmony_ci NULL, 5558c2ecf20Sopenharmony_ci 0, 5568c2ecf20Sopenharmony_ci NULL, 5578c2ecf20Sopenharmony_ci ATTACH_OKAY, 5588c2ecf20Sopenharmony_ci }, 5598c2ecf20Sopenharmony_ci { 5608c2ecf20Sopenharmony_ci "recvmsg6: return code !ok", 5618c2ecf20Sopenharmony_ci recvmsg_deny_prog_load, 5628c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_RECVMSG, 5638c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_RECVMSG, 5648c2ecf20Sopenharmony_ci AF_INET6, 5658c2ecf20Sopenharmony_ci SOCK_DGRAM, 5668c2ecf20Sopenharmony_ci NULL, 5678c2ecf20Sopenharmony_ci 0, 5688c2ecf20Sopenharmony_ci NULL, 5698c2ecf20Sopenharmony_ci 0, 5708c2ecf20Sopenharmony_ci NULL, 5718c2ecf20Sopenharmony_ci LOAD_REJECT, 5728c2ecf20Sopenharmony_ci }, 5738c2ecf20Sopenharmony_ci { 5748c2ecf20Sopenharmony_ci "recvmsg4: rewrite IP & port (asm)", 5758c2ecf20Sopenharmony_ci recvmsg4_rw_asm_prog_load, 5768c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_RECVMSG, 5778c2ecf20Sopenharmony_ci BPF_CGROUP_UDP4_RECVMSG, 5788c2ecf20Sopenharmony_ci AF_INET, 5798c2ecf20Sopenharmony_ci SOCK_DGRAM, 5808c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 5818c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 5828c2ecf20Sopenharmony_ci SERV4_REWRITE_IP, 5838c2ecf20Sopenharmony_ci SERV4_REWRITE_PORT, 5848c2ecf20Sopenharmony_ci SERV4_IP, 5858c2ecf20Sopenharmony_ci SUCCESS, 5868c2ecf20Sopenharmony_ci }, 5878c2ecf20Sopenharmony_ci { 5888c2ecf20Sopenharmony_ci "recvmsg6: rewrite IP & port (asm)", 5898c2ecf20Sopenharmony_ci recvmsg6_rw_asm_prog_load, 5908c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_RECVMSG, 5918c2ecf20Sopenharmony_ci BPF_CGROUP_UDP6_RECVMSG, 5928c2ecf20Sopenharmony_ci AF_INET6, 5938c2ecf20Sopenharmony_ci SOCK_DGRAM, 5948c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 5958c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 5968c2ecf20Sopenharmony_ci SERV6_REWRITE_IP, 5978c2ecf20Sopenharmony_ci SERV6_REWRITE_PORT, 5988c2ecf20Sopenharmony_ci SERV6_IP, 5998c2ecf20Sopenharmony_ci SUCCESS, 6008c2ecf20Sopenharmony_ci }, 6018c2ecf20Sopenharmony_ci}; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_cistatic int mk_sockaddr(int domain, const char *ip, unsigned short port, 6048c2ecf20Sopenharmony_ci struct sockaddr *addr, socklen_t addr_len) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci struct sockaddr_in6 *addr6; 6078c2ecf20Sopenharmony_ci struct sockaddr_in *addr4; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (domain != AF_INET && domain != AF_INET6) { 6108c2ecf20Sopenharmony_ci log_err("Unsupported address family"); 6118c2ecf20Sopenharmony_ci return -1; 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci memset(addr, 0, addr_len); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (domain == AF_INET) { 6178c2ecf20Sopenharmony_ci if (addr_len < sizeof(struct sockaddr_in)) 6188c2ecf20Sopenharmony_ci return -1; 6198c2ecf20Sopenharmony_ci addr4 = (struct sockaddr_in *)addr; 6208c2ecf20Sopenharmony_ci addr4->sin_family = domain; 6218c2ecf20Sopenharmony_ci addr4->sin_port = htons(port); 6228c2ecf20Sopenharmony_ci if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1) { 6238c2ecf20Sopenharmony_ci log_err("Invalid IPv4: %s", ip); 6248c2ecf20Sopenharmony_ci return -1; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci } else if (domain == AF_INET6) { 6278c2ecf20Sopenharmony_ci if (addr_len < sizeof(struct sockaddr_in6)) 6288c2ecf20Sopenharmony_ci return -1; 6298c2ecf20Sopenharmony_ci addr6 = (struct sockaddr_in6 *)addr; 6308c2ecf20Sopenharmony_ci addr6->sin6_family = domain; 6318c2ecf20Sopenharmony_ci addr6->sin6_port = htons(port); 6328c2ecf20Sopenharmony_ci if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1) { 6338c2ecf20Sopenharmony_ci log_err("Invalid IPv6: %s", ip); 6348c2ecf20Sopenharmony_ci return -1; 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci return 0; 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_cistatic int load_insns(const struct sock_addr_test *test, 6428c2ecf20Sopenharmony_ci const struct bpf_insn *insns, size_t insns_cnt) 6438c2ecf20Sopenharmony_ci{ 6448c2ecf20Sopenharmony_ci struct bpf_load_program_attr load_attr; 6458c2ecf20Sopenharmony_ci int ret; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); 6488c2ecf20Sopenharmony_ci load_attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; 6498c2ecf20Sopenharmony_ci load_attr.expected_attach_type = test->expected_attach_type; 6508c2ecf20Sopenharmony_ci load_attr.insns = insns; 6518c2ecf20Sopenharmony_ci load_attr.insns_cnt = insns_cnt; 6528c2ecf20Sopenharmony_ci load_attr.license = "GPL"; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci ret = bpf_load_program_xattr(&load_attr, bpf_log_buf, BPF_LOG_BUF_SIZE); 6558c2ecf20Sopenharmony_ci if (ret < 0 && test->expected_result != LOAD_REJECT) { 6568c2ecf20Sopenharmony_ci log_err(">>> Loading program error.\n" 6578c2ecf20Sopenharmony_ci ">>> Verifier output:\n%s\n-------\n", bpf_log_buf); 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci return ret; 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci/* [1] These testing programs try to read different context fields, including 6648c2ecf20Sopenharmony_ci * narrow loads of different sizes from user_ip4 and user_ip6, and write to 6658c2ecf20Sopenharmony_ci * those allowed to be overridden. 6668c2ecf20Sopenharmony_ci * 6678c2ecf20Sopenharmony_ci * [2] BPF_LD_IMM64 & BPF_JMP_REG are used below whenever there is a need to 6688c2ecf20Sopenharmony_ci * compare a register with unsigned 32bit integer. BPF_JMP_IMM can't be used 6698c2ecf20Sopenharmony_ci * in such cases since it accepts only _signed_ 32bit integer as IMM 6708c2ecf20Sopenharmony_ci * argument. Also note that BPF_LD_IMM64 contains 2 instructions what matters 6718c2ecf20Sopenharmony_ci * to count jumps properly. 6728c2ecf20Sopenharmony_ci */ 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_cistatic int bind4_prog_load(const struct sock_addr_test *test) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci union { 6778c2ecf20Sopenharmony_ci uint8_t u4_addr8[4]; 6788c2ecf20Sopenharmony_ci uint16_t u4_addr16[2]; 6798c2ecf20Sopenharmony_ci uint32_t u4_addr32; 6808c2ecf20Sopenharmony_ci } ip4, port; 6818c2ecf20Sopenharmony_ci struct sockaddr_in addr4_rw; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci if (inet_pton(AF_INET, SERV4_IP, (void *)&ip4) != 1) { 6848c2ecf20Sopenharmony_ci log_err("Invalid IPv4: %s", SERV4_IP); 6858c2ecf20Sopenharmony_ci return -1; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci port.u4_addr32 = htons(SERV4_PORT); 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, 6918c2ecf20Sopenharmony_ci (struct sockaddr *)&addr4_rw, sizeof(addr4_rw)) == -1) 6928c2ecf20Sopenharmony_ci return -1; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci /* See [1]. */ 6958c2ecf20Sopenharmony_ci struct bpf_insn insns[] = { 6968c2ecf20Sopenharmony_ci BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci /* if (sk.family == AF_INET && */ 6998c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 7008c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, family)), 7018c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 32), 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* (sk.type == SOCK_DGRAM || sk.type == SOCK_STREAM) && */ 7048c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 7058c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, type)), 7068c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 1), 7078c2ecf20Sopenharmony_ci BPF_JMP_A(1), 7088c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_STREAM, 28), 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci /* 1st_byte_of_user_ip4 == expected && */ 7118c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 7128c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4)), 7138c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[0], 26), 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci /* 2nd_byte_of_user_ip4 == expected && */ 7168c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 7178c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4) + 1), 7188c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[1], 24), 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci /* 3rd_byte_of_user_ip4 == expected && */ 7218c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 7228c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4) + 2), 7238c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[2], 22), 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci /* 4th_byte_of_user_ip4 == expected && */ 7268c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 7278c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4) + 3), 7288c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr8[3], 20), 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci /* 1st_half_of_user_ip4 == expected && */ 7318c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 7328c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4)), 7338c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr16[0], 18), 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci /* 2nd_half_of_user_ip4 == expected && */ 7368c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 7378c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4) + 2), 7388c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip4.u4_addr16[1], 16), 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* whole_user_ip4 == expected && */ 7418c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 7428c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4)), 7438c2ecf20Sopenharmony_ci BPF_LD_IMM64(BPF_REG_8, ip4.u4_addr32), /* See [2]. */ 7448c2ecf20Sopenharmony_ci BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 12), 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* 1st_byte_of_user_port == expected && */ 7478c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 7488c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 7498c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, port.u4_addr8[0], 10), 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* 1st_half_of_user_port == expected && */ 7528c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 7538c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 7548c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, port.u4_addr16[0], 8), 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* user_port == expected) { */ 7578c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 7588c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 7598c2ecf20Sopenharmony_ci BPF_LD_IMM64(BPF_REG_8, port.u4_addr32), /* See [2]. */ 7608c2ecf20Sopenharmony_ci BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 4), 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci /* user_ip4 = addr4_rw.sin_addr */ 7638c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, addr4_rw.sin_addr.s_addr), 7648c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 7658c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4)), 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci /* user_port = addr4_rw.sin_port */ 7688c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, addr4_rw.sin_port), 7698c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 7708c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 7718c2ecf20Sopenharmony_ci /* } */ 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci /* return 1 */ 7748c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 7758c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 7768c2ecf20Sopenharmony_ci }; 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic int bind6_prog_load(const struct sock_addr_test *test) 7828c2ecf20Sopenharmony_ci{ 7838c2ecf20Sopenharmony_ci struct sockaddr_in6 addr6_rw; 7848c2ecf20Sopenharmony_ci struct in6_addr ip6; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci if (inet_pton(AF_INET6, SERV6_IP, (void *)&ip6) != 1) { 7878c2ecf20Sopenharmony_ci log_err("Invalid IPv6: %s", SERV6_IP); 7888c2ecf20Sopenharmony_ci return -1; 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci if (mk_sockaddr(AF_INET6, SERV6_REWRITE_IP, SERV6_REWRITE_PORT, 7928c2ecf20Sopenharmony_ci (struct sockaddr *)&addr6_rw, sizeof(addr6_rw)) == -1) 7938c2ecf20Sopenharmony_ci return -1; 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci /* See [1]. */ 7968c2ecf20Sopenharmony_ci struct bpf_insn insns[] = { 7978c2ecf20Sopenharmony_ci BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* if (sk.family == AF_INET6 && */ 8008c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 8018c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, family)), 8028c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18), 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* 5th_byte_of_user_ip6 == expected && */ 8058c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_B, BPF_REG_7, BPF_REG_6, 8068c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip6[1])), 8078c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip6.s6_addr[4], 16), 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci /* 3rd_half_of_user_ip6 == expected && */ 8108c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_H, BPF_REG_7, BPF_REG_6, 8118c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip6[1])), 8128c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, ip6.s6_addr16[2], 14), 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci /* last_word_of_user_ip6 == expected) { */ 8158c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 8168c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip6[3])), 8178c2ecf20Sopenharmony_ci BPF_LD_IMM64(BPF_REG_8, ip6.s6_addr32[3]), /* See [2]. */ 8188c2ecf20Sopenharmony_ci BPF_JMP_REG(BPF_JNE, BPF_REG_7, BPF_REG_8, 10), 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci#define STORE_IPV6_WORD(N) \ 8228c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, addr6_rw.sin6_addr.s6_addr32[N]), \ 8238c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, \ 8248c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip6[N])) 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci /* user_ip6 = addr6_rw.sin6_addr */ 8278c2ecf20Sopenharmony_ci STORE_IPV6_WORD(0), 8288c2ecf20Sopenharmony_ci STORE_IPV6_WORD(1), 8298c2ecf20Sopenharmony_ci STORE_IPV6_WORD(2), 8308c2ecf20Sopenharmony_ci STORE_IPV6_WORD(3), 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci /* user_port = addr6_rw.sin6_port */ 8338c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, addr6_rw.sin6_port), 8348c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 8358c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci /* } */ 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci /* return 1 */ 8408c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 8418c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 8428c2ecf20Sopenharmony_ci }; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_cistatic int load_path(const struct sock_addr_test *test, const char *path) 8488c2ecf20Sopenharmony_ci{ 8498c2ecf20Sopenharmony_ci struct bpf_prog_load_attr attr; 8508c2ecf20Sopenharmony_ci struct bpf_object *obj; 8518c2ecf20Sopenharmony_ci int prog_fd; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci memset(&attr, 0, sizeof(struct bpf_prog_load_attr)); 8548c2ecf20Sopenharmony_ci attr.file = path; 8558c2ecf20Sopenharmony_ci attr.prog_type = BPF_PROG_TYPE_CGROUP_SOCK_ADDR; 8568c2ecf20Sopenharmony_ci attr.expected_attach_type = test->expected_attach_type; 8578c2ecf20Sopenharmony_ci attr.prog_flags = BPF_F_TEST_RND_HI32; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (bpf_prog_load_xattr(&attr, &obj, &prog_fd)) { 8608c2ecf20Sopenharmony_ci if (test->expected_result != LOAD_REJECT) 8618c2ecf20Sopenharmony_ci log_err(">>> Loading program (%s) error.\n", path); 8628c2ecf20Sopenharmony_ci return -1; 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci return prog_fd; 8668c2ecf20Sopenharmony_ci} 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_cistatic int connect4_prog_load(const struct sock_addr_test *test) 8698c2ecf20Sopenharmony_ci{ 8708c2ecf20Sopenharmony_ci return load_path(test, CONNECT4_PROG_PATH); 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic int connect6_prog_load(const struct sock_addr_test *test) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci return load_path(test, CONNECT6_PROG_PATH); 8768c2ecf20Sopenharmony_ci} 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_cistatic int xmsg_ret_only_prog_load(const struct sock_addr_test *test, 8798c2ecf20Sopenharmony_ci int32_t rc) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci struct bpf_insn insns[] = { 8828c2ecf20Sopenharmony_ci /* return rc */ 8838c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, rc), 8848c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 8858c2ecf20Sopenharmony_ci }; 8868c2ecf20Sopenharmony_ci return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 8878c2ecf20Sopenharmony_ci} 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_cistatic int sendmsg_allow_prog_load(const struct sock_addr_test *test) 8908c2ecf20Sopenharmony_ci{ 8918c2ecf20Sopenharmony_ci return xmsg_ret_only_prog_load(test, /*rc*/ 1); 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_cistatic int sendmsg_deny_prog_load(const struct sock_addr_test *test) 8958c2ecf20Sopenharmony_ci{ 8968c2ecf20Sopenharmony_ci return xmsg_ret_only_prog_load(test, /*rc*/ 0); 8978c2ecf20Sopenharmony_ci} 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_cistatic int recvmsg_allow_prog_load(const struct sock_addr_test *test) 9008c2ecf20Sopenharmony_ci{ 9018c2ecf20Sopenharmony_ci return xmsg_ret_only_prog_load(test, /*rc*/ 1); 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_cistatic int recvmsg_deny_prog_load(const struct sock_addr_test *test) 9058c2ecf20Sopenharmony_ci{ 9068c2ecf20Sopenharmony_ci return xmsg_ret_only_prog_load(test, /*rc*/ 0); 9078c2ecf20Sopenharmony_ci} 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_cistatic int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci struct sockaddr_in dst4_rw_addr; 9128c2ecf20Sopenharmony_ci struct in_addr src4_rw_ip; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) { 9158c2ecf20Sopenharmony_ci log_err("Invalid IPv4: %s", SRC4_REWRITE_IP); 9168c2ecf20Sopenharmony_ci return -1; 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT, 9208c2ecf20Sopenharmony_ci (struct sockaddr *)&dst4_rw_addr, 9218c2ecf20Sopenharmony_ci sizeof(dst4_rw_addr)) == -1) 9228c2ecf20Sopenharmony_ci return -1; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci struct bpf_insn insns[] = { 9258c2ecf20Sopenharmony_ci BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci /* if (sk.family == AF_INET && */ 9288c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 9298c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, family)), 9308c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 8), 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci /* sk.type == SOCK_DGRAM) { */ 9338c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 9348c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, type)), 9358c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 6), 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci /* msg_src_ip4 = src4_rw_ip */ 9388c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, src4_rw_ip.s_addr), 9398c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 9408c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, msg_src_ip4)), 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci /* user_ip4 = dst4_rw_addr.sin_addr */ 9438c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_addr.s_addr), 9448c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 9458c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4)), 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci /* user_port = dst4_rw_addr.sin_port */ 9488c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_port), 9498c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 9508c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 9518c2ecf20Sopenharmony_ci /* } */ 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* return 1 */ 9548c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 9558c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 9568c2ecf20Sopenharmony_ci }; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 9598c2ecf20Sopenharmony_ci} 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_cistatic int recvmsg4_rw_asm_prog_load(const struct sock_addr_test *test) 9628c2ecf20Sopenharmony_ci{ 9638c2ecf20Sopenharmony_ci struct sockaddr_in src4_rw_addr; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci if (mk_sockaddr(AF_INET, SERV4_IP, SERV4_PORT, 9668c2ecf20Sopenharmony_ci (struct sockaddr *)&src4_rw_addr, 9678c2ecf20Sopenharmony_ci sizeof(src4_rw_addr)) == -1) 9688c2ecf20Sopenharmony_ci return -1; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci struct bpf_insn insns[] = { 9718c2ecf20Sopenharmony_ci BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci /* if (sk.family == AF_INET && */ 9748c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 9758c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, family)), 9768c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 6), 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci /* sk.type == SOCK_DGRAM) { */ 9798c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 9808c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, type)), 9818c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 4), 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci /* user_ip4 = src4_rw_addr.sin_addr */ 9848c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_addr.s_addr), 9858c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 9868c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_ip4)), 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci /* user_port = src4_rw_addr.sin_port */ 9898c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, src4_rw_addr.sin_port), 9908c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 9918c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 9928c2ecf20Sopenharmony_ci /* } */ 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* return 1 */ 9958c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 9968c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 9978c2ecf20Sopenharmony_ci }; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 10008c2ecf20Sopenharmony_ci} 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_cistatic int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test) 10038c2ecf20Sopenharmony_ci{ 10048c2ecf20Sopenharmony_ci return load_path(test, SENDMSG4_PROG_PATH); 10058c2ecf20Sopenharmony_ci} 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_cistatic int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test, 10088c2ecf20Sopenharmony_ci const char *rw_dst_ip) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci struct sockaddr_in6 dst6_rw_addr; 10118c2ecf20Sopenharmony_ci struct in6_addr src6_rw_ip; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) { 10148c2ecf20Sopenharmony_ci log_err("Invalid IPv6: %s", SRC6_REWRITE_IP); 10158c2ecf20Sopenharmony_ci return -1; 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT, 10198c2ecf20Sopenharmony_ci (struct sockaddr *)&dst6_rw_addr, 10208c2ecf20Sopenharmony_ci sizeof(dst6_rw_addr)) == -1) 10218c2ecf20Sopenharmony_ci return -1; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci struct bpf_insn insns[] = { 10248c2ecf20Sopenharmony_ci BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci /* if (sk.family == AF_INET6) { */ 10278c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 10288c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, family)), 10298c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18), 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci#define STORE_IPV6_WORD_N(DST, SRC, N) \ 10328c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, SRC[N]), \ 10338c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, \ 10348c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, DST[N])) 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci#define STORE_IPV6(DST, SRC) \ 10378c2ecf20Sopenharmony_ci STORE_IPV6_WORD_N(DST, SRC, 0), \ 10388c2ecf20Sopenharmony_ci STORE_IPV6_WORD_N(DST, SRC, 1), \ 10398c2ecf20Sopenharmony_ci STORE_IPV6_WORD_N(DST, SRC, 2), \ 10408c2ecf20Sopenharmony_ci STORE_IPV6_WORD_N(DST, SRC, 3) 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci STORE_IPV6(msg_src_ip6, src6_rw_ip.s6_addr32), 10438c2ecf20Sopenharmony_ci STORE_IPV6(user_ip6, dst6_rw_addr.sin6_addr.s6_addr32), 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* user_port = dst6_rw_addr.sin6_port */ 10468c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, dst6_rw_addr.sin6_port), 10478c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 10488c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /* } */ 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci /* return 1 */ 10538c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 10548c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 10558c2ecf20Sopenharmony_ci }; 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 10588c2ecf20Sopenharmony_ci} 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_cistatic int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test) 10618c2ecf20Sopenharmony_ci{ 10628c2ecf20Sopenharmony_ci return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP); 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_cistatic int recvmsg6_rw_asm_prog_load(const struct sock_addr_test *test) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci struct sockaddr_in6 src6_rw_addr; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci if (mk_sockaddr(AF_INET6, SERV6_IP, SERV6_PORT, 10708c2ecf20Sopenharmony_ci (struct sockaddr *)&src6_rw_addr, 10718c2ecf20Sopenharmony_ci sizeof(src6_rw_addr)) == -1) 10728c2ecf20Sopenharmony_ci return -1; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci struct bpf_insn insns[] = { 10758c2ecf20Sopenharmony_ci BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci /* if (sk.family == AF_INET6) { */ 10788c2ecf20Sopenharmony_ci BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6, 10798c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, family)), 10808c2ecf20Sopenharmony_ci BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 10), 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci STORE_IPV6(user_ip6, src6_rw_addr.sin6_addr.s6_addr32), 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci /* user_port = dst6_rw_addr.sin6_port */ 10858c2ecf20Sopenharmony_ci BPF_MOV32_IMM(BPF_REG_7, src6_rw_addr.sin6_port), 10868c2ecf20Sopenharmony_ci BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7, 10878c2ecf20Sopenharmony_ci offsetof(struct bpf_sock_addr, user_port)), 10888c2ecf20Sopenharmony_ci /* } */ 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci /* return 1 */ 10918c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 1), 10928c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 10938c2ecf20Sopenharmony_ci }; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn)); 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_cistatic int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test) 10998c2ecf20Sopenharmony_ci{ 11008c2ecf20Sopenharmony_ci return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP); 11018c2ecf20Sopenharmony_ci} 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_cistatic int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test) 11048c2ecf20Sopenharmony_ci{ 11058c2ecf20Sopenharmony_ci return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP); 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_cistatic int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci return load_path(test, SENDMSG6_PROG_PATH); 11118c2ecf20Sopenharmony_ci} 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_cistatic int cmp_addr(const struct sockaddr_storage *addr1, 11148c2ecf20Sopenharmony_ci const struct sockaddr_storage *addr2, int cmp_port) 11158c2ecf20Sopenharmony_ci{ 11168c2ecf20Sopenharmony_ci const struct sockaddr_in *four1, *four2; 11178c2ecf20Sopenharmony_ci const struct sockaddr_in6 *six1, *six2; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci if (addr1->ss_family != addr2->ss_family) 11208c2ecf20Sopenharmony_ci return -1; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci if (addr1->ss_family == AF_INET) { 11238c2ecf20Sopenharmony_ci four1 = (const struct sockaddr_in *)addr1; 11248c2ecf20Sopenharmony_ci four2 = (const struct sockaddr_in *)addr2; 11258c2ecf20Sopenharmony_ci return !((four1->sin_port == four2->sin_port || !cmp_port) && 11268c2ecf20Sopenharmony_ci four1->sin_addr.s_addr == four2->sin_addr.s_addr); 11278c2ecf20Sopenharmony_ci } else if (addr1->ss_family == AF_INET6) { 11288c2ecf20Sopenharmony_ci six1 = (const struct sockaddr_in6 *)addr1; 11298c2ecf20Sopenharmony_ci six2 = (const struct sockaddr_in6 *)addr2; 11308c2ecf20Sopenharmony_ci return !((six1->sin6_port == six2->sin6_port || !cmp_port) && 11318c2ecf20Sopenharmony_ci !memcmp(&six1->sin6_addr, &six2->sin6_addr, 11328c2ecf20Sopenharmony_ci sizeof(struct in6_addr))); 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci return -1; 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_cistatic int cmp_sock_addr(info_fn fn, int sock1, 11398c2ecf20Sopenharmony_ci const struct sockaddr_storage *addr2, int cmp_port) 11408c2ecf20Sopenharmony_ci{ 11418c2ecf20Sopenharmony_ci struct sockaddr_storage addr1; 11428c2ecf20Sopenharmony_ci socklen_t len1 = sizeof(addr1); 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci memset(&addr1, 0, len1); 11458c2ecf20Sopenharmony_ci if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0) 11468c2ecf20Sopenharmony_ci return -1; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci return cmp_addr(&addr1, addr2, cmp_port); 11498c2ecf20Sopenharmony_ci} 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_cistatic int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2) 11528c2ecf20Sopenharmony_ci{ 11538c2ecf20Sopenharmony_ci return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0); 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_cistatic int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2) 11578c2ecf20Sopenharmony_ci{ 11588c2ecf20Sopenharmony_ci return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1); 11598c2ecf20Sopenharmony_ci} 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_cistatic int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1); 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic int start_server(int type, const struct sockaddr_storage *addr, 11678c2ecf20Sopenharmony_ci socklen_t addr_len) 11688c2ecf20Sopenharmony_ci{ 11698c2ecf20Sopenharmony_ci int fd; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci fd = socket(addr->ss_family, type, 0); 11728c2ecf20Sopenharmony_ci if (fd == -1) { 11738c2ecf20Sopenharmony_ci log_err("Failed to create server socket"); 11748c2ecf20Sopenharmony_ci goto out; 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) { 11788c2ecf20Sopenharmony_ci log_err("Failed to bind server socket"); 11798c2ecf20Sopenharmony_ci goto close_out; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (type == SOCK_STREAM) { 11838c2ecf20Sopenharmony_ci if (listen(fd, 128) == -1) { 11848c2ecf20Sopenharmony_ci log_err("Failed to listen on server socket"); 11858c2ecf20Sopenharmony_ci goto close_out; 11868c2ecf20Sopenharmony_ci } 11878c2ecf20Sopenharmony_ci } 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci goto out; 11908c2ecf20Sopenharmony_ciclose_out: 11918c2ecf20Sopenharmony_ci close(fd); 11928c2ecf20Sopenharmony_ci fd = -1; 11938c2ecf20Sopenharmony_ciout: 11948c2ecf20Sopenharmony_ci return fd; 11958c2ecf20Sopenharmony_ci} 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_cistatic int connect_to_server(int type, const struct sockaddr_storage *addr, 11988c2ecf20Sopenharmony_ci socklen_t addr_len) 11998c2ecf20Sopenharmony_ci{ 12008c2ecf20Sopenharmony_ci int domain; 12018c2ecf20Sopenharmony_ci int fd = -1; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci domain = addr->ss_family; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci if (domain != AF_INET && domain != AF_INET6) { 12068c2ecf20Sopenharmony_ci log_err("Unsupported address family"); 12078c2ecf20Sopenharmony_ci goto err; 12088c2ecf20Sopenharmony_ci } 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci fd = socket(domain, type, 0); 12118c2ecf20Sopenharmony_ci if (fd == -1) { 12128c2ecf20Sopenharmony_ci log_err("Failed to create client socket"); 12138c2ecf20Sopenharmony_ci goto err; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) { 12178c2ecf20Sopenharmony_ci log_err("Fail to connect to server"); 12188c2ecf20Sopenharmony_ci goto err; 12198c2ecf20Sopenharmony_ci } 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci goto out; 12228c2ecf20Sopenharmony_cierr: 12238c2ecf20Sopenharmony_ci close(fd); 12248c2ecf20Sopenharmony_ci fd = -1; 12258c2ecf20Sopenharmony_ciout: 12268c2ecf20Sopenharmony_ci return fd; 12278c2ecf20Sopenharmony_ci} 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ciint init_pktinfo(int domain, struct cmsghdr *cmsg) 12308c2ecf20Sopenharmony_ci{ 12318c2ecf20Sopenharmony_ci struct in6_pktinfo *pktinfo6; 12328c2ecf20Sopenharmony_ci struct in_pktinfo *pktinfo4; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci if (domain == AF_INET) { 12358c2ecf20Sopenharmony_ci cmsg->cmsg_level = SOL_IP; 12368c2ecf20Sopenharmony_ci cmsg->cmsg_type = IP_PKTINFO; 12378c2ecf20Sopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 12388c2ecf20Sopenharmony_ci pktinfo4 = (struct in_pktinfo *)CMSG_DATA(cmsg); 12398c2ecf20Sopenharmony_ci memset(pktinfo4, 0, sizeof(struct in_pktinfo)); 12408c2ecf20Sopenharmony_ci if (inet_pton(domain, SRC4_IP, 12418c2ecf20Sopenharmony_ci (void *)&pktinfo4->ipi_spec_dst) != 1) 12428c2ecf20Sopenharmony_ci return -1; 12438c2ecf20Sopenharmony_ci } else if (domain == AF_INET6) { 12448c2ecf20Sopenharmony_ci cmsg->cmsg_level = SOL_IPV6; 12458c2ecf20Sopenharmony_ci cmsg->cmsg_type = IPV6_PKTINFO; 12468c2ecf20Sopenharmony_ci cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 12478c2ecf20Sopenharmony_ci pktinfo6 = (struct in6_pktinfo *)CMSG_DATA(cmsg); 12488c2ecf20Sopenharmony_ci memset(pktinfo6, 0, sizeof(struct in6_pktinfo)); 12498c2ecf20Sopenharmony_ci if (inet_pton(domain, SRC6_IP, 12508c2ecf20Sopenharmony_ci (void *)&pktinfo6->ipi6_addr) != 1) 12518c2ecf20Sopenharmony_ci return -1; 12528c2ecf20Sopenharmony_ci } else { 12538c2ecf20Sopenharmony_ci return -1; 12548c2ecf20Sopenharmony_ci } 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci return 0; 12578c2ecf20Sopenharmony_ci} 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_cistatic int sendmsg_to_server(int type, const struct sockaddr_storage *addr, 12608c2ecf20Sopenharmony_ci socklen_t addr_len, int set_cmsg, int flags, 12618c2ecf20Sopenharmony_ci int *syscall_err) 12628c2ecf20Sopenharmony_ci{ 12638c2ecf20Sopenharmony_ci union { 12648c2ecf20Sopenharmony_ci char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 12658c2ecf20Sopenharmony_ci struct cmsghdr align; 12668c2ecf20Sopenharmony_ci } control6; 12678c2ecf20Sopenharmony_ci union { 12688c2ecf20Sopenharmony_ci char buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; 12698c2ecf20Sopenharmony_ci struct cmsghdr align; 12708c2ecf20Sopenharmony_ci } control4; 12718c2ecf20Sopenharmony_ci struct msghdr hdr; 12728c2ecf20Sopenharmony_ci struct iovec iov; 12738c2ecf20Sopenharmony_ci char data = 'a'; 12748c2ecf20Sopenharmony_ci int domain; 12758c2ecf20Sopenharmony_ci int fd = -1; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci domain = addr->ss_family; 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci if (domain != AF_INET && domain != AF_INET6) { 12808c2ecf20Sopenharmony_ci log_err("Unsupported address family"); 12818c2ecf20Sopenharmony_ci goto err; 12828c2ecf20Sopenharmony_ci } 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci fd = socket(domain, type, 0); 12858c2ecf20Sopenharmony_ci if (fd == -1) { 12868c2ecf20Sopenharmony_ci log_err("Failed to create client socket"); 12878c2ecf20Sopenharmony_ci goto err; 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci memset(&iov, 0, sizeof(iov)); 12918c2ecf20Sopenharmony_ci iov.iov_base = &data; 12928c2ecf20Sopenharmony_ci iov.iov_len = sizeof(data); 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci memset(&hdr, 0, sizeof(hdr)); 12958c2ecf20Sopenharmony_ci hdr.msg_name = (void *)addr; 12968c2ecf20Sopenharmony_ci hdr.msg_namelen = addr_len; 12978c2ecf20Sopenharmony_ci hdr.msg_iov = &iov; 12988c2ecf20Sopenharmony_ci hdr.msg_iovlen = 1; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci if (set_cmsg) { 13018c2ecf20Sopenharmony_ci if (domain == AF_INET) { 13028c2ecf20Sopenharmony_ci hdr.msg_control = &control4; 13038c2ecf20Sopenharmony_ci hdr.msg_controllen = sizeof(control4.buf); 13048c2ecf20Sopenharmony_ci } else if (domain == AF_INET6) { 13058c2ecf20Sopenharmony_ci hdr.msg_control = &control6; 13068c2ecf20Sopenharmony_ci hdr.msg_controllen = sizeof(control6.buf); 13078c2ecf20Sopenharmony_ci } 13088c2ecf20Sopenharmony_ci if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) { 13098c2ecf20Sopenharmony_ci log_err("Fail to init pktinfo"); 13108c2ecf20Sopenharmony_ci goto err; 13118c2ecf20Sopenharmony_ci } 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci if (sendmsg(fd, &hdr, flags) != sizeof(data)) { 13158c2ecf20Sopenharmony_ci log_err("Fail to send message to server"); 13168c2ecf20Sopenharmony_ci *syscall_err = errno; 13178c2ecf20Sopenharmony_ci goto err; 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci goto out; 13218c2ecf20Sopenharmony_cierr: 13228c2ecf20Sopenharmony_ci close(fd); 13238c2ecf20Sopenharmony_ci fd = -1; 13248c2ecf20Sopenharmony_ciout: 13258c2ecf20Sopenharmony_ci return fd; 13268c2ecf20Sopenharmony_ci} 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_cistatic int fastconnect_to_server(const struct sockaddr_storage *addr, 13298c2ecf20Sopenharmony_ci socklen_t addr_len) 13308c2ecf20Sopenharmony_ci{ 13318c2ecf20Sopenharmony_ci int sendmsg_err; 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci return sendmsg_to_server(SOCK_STREAM, addr, addr_len, /*set_cmsg*/0, 13348c2ecf20Sopenharmony_ci MSG_FASTOPEN, &sendmsg_err); 13358c2ecf20Sopenharmony_ci} 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_cistatic int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr) 13388c2ecf20Sopenharmony_ci{ 13398c2ecf20Sopenharmony_ci struct timeval tv; 13408c2ecf20Sopenharmony_ci struct msghdr hdr; 13418c2ecf20Sopenharmony_ci struct iovec iov; 13428c2ecf20Sopenharmony_ci char data[64]; 13438c2ecf20Sopenharmony_ci fd_set rfds; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci FD_ZERO(&rfds); 13468c2ecf20Sopenharmony_ci FD_SET(sockfd, &rfds); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci tv.tv_sec = 2; 13498c2ecf20Sopenharmony_ci tv.tv_usec = 0; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci if (select(sockfd + 1, &rfds, NULL, NULL, &tv) <= 0 || 13528c2ecf20Sopenharmony_ci !FD_ISSET(sockfd, &rfds)) 13538c2ecf20Sopenharmony_ci return -1; 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_ci memset(&iov, 0, sizeof(iov)); 13568c2ecf20Sopenharmony_ci iov.iov_base = data; 13578c2ecf20Sopenharmony_ci iov.iov_len = sizeof(data); 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci memset(&hdr, 0, sizeof(hdr)); 13608c2ecf20Sopenharmony_ci hdr.msg_name = src_addr; 13618c2ecf20Sopenharmony_ci hdr.msg_namelen = sizeof(struct sockaddr_storage); 13628c2ecf20Sopenharmony_ci hdr.msg_iov = &iov; 13638c2ecf20Sopenharmony_ci hdr.msg_iovlen = 1; 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci return recvmsg(sockfd, &hdr, 0); 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_cistatic int init_addrs(const struct sock_addr_test *test, 13698c2ecf20Sopenharmony_ci struct sockaddr_storage *requested_addr, 13708c2ecf20Sopenharmony_ci struct sockaddr_storage *expected_addr, 13718c2ecf20Sopenharmony_ci struct sockaddr_storage *expected_src_addr) 13728c2ecf20Sopenharmony_ci{ 13738c2ecf20Sopenharmony_ci socklen_t addr_len = sizeof(struct sockaddr_storage); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port, 13768c2ecf20Sopenharmony_ci (struct sockaddr *)expected_addr, addr_len) == -1) 13778c2ecf20Sopenharmony_ci goto err; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port, 13808c2ecf20Sopenharmony_ci (struct sockaddr *)requested_addr, addr_len) == -1) 13818c2ecf20Sopenharmony_ci goto err; 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci if (test->expected_src_ip && 13848c2ecf20Sopenharmony_ci mk_sockaddr(test->domain, test->expected_src_ip, 0, 13858c2ecf20Sopenharmony_ci (struct sockaddr *)expected_src_addr, addr_len) == -1) 13868c2ecf20Sopenharmony_ci goto err; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci return 0; 13898c2ecf20Sopenharmony_cierr: 13908c2ecf20Sopenharmony_ci return -1; 13918c2ecf20Sopenharmony_ci} 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_cistatic int run_bind_test_case(const struct sock_addr_test *test) 13948c2ecf20Sopenharmony_ci{ 13958c2ecf20Sopenharmony_ci socklen_t addr_len = sizeof(struct sockaddr_storage); 13968c2ecf20Sopenharmony_ci struct sockaddr_storage requested_addr; 13978c2ecf20Sopenharmony_ci struct sockaddr_storage expected_addr; 13988c2ecf20Sopenharmony_ci int clientfd = -1; 13998c2ecf20Sopenharmony_ci int servfd = -1; 14008c2ecf20Sopenharmony_ci int err = 0; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci if (init_addrs(test, &requested_addr, &expected_addr, NULL)) 14038c2ecf20Sopenharmony_ci goto err; 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci servfd = start_server(test->type, &requested_addr, addr_len); 14068c2ecf20Sopenharmony_ci if (servfd == -1) 14078c2ecf20Sopenharmony_ci goto err; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci if (cmp_local_addr(servfd, &expected_addr)) 14108c2ecf20Sopenharmony_ci goto err; 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci /* Try to connect to server just in case */ 14138c2ecf20Sopenharmony_ci clientfd = connect_to_server(test->type, &expected_addr, addr_len); 14148c2ecf20Sopenharmony_ci if (clientfd == -1) 14158c2ecf20Sopenharmony_ci goto err; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci goto out; 14188c2ecf20Sopenharmony_cierr: 14198c2ecf20Sopenharmony_ci err = -1; 14208c2ecf20Sopenharmony_ciout: 14218c2ecf20Sopenharmony_ci close(clientfd); 14228c2ecf20Sopenharmony_ci close(servfd); 14238c2ecf20Sopenharmony_ci return err; 14248c2ecf20Sopenharmony_ci} 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_cistatic int run_connect_test_case(const struct sock_addr_test *test) 14278c2ecf20Sopenharmony_ci{ 14288c2ecf20Sopenharmony_ci socklen_t addr_len = sizeof(struct sockaddr_storage); 14298c2ecf20Sopenharmony_ci struct sockaddr_storage expected_src_addr; 14308c2ecf20Sopenharmony_ci struct sockaddr_storage requested_addr; 14318c2ecf20Sopenharmony_ci struct sockaddr_storage expected_addr; 14328c2ecf20Sopenharmony_ci int clientfd = -1; 14338c2ecf20Sopenharmony_ci int servfd = -1; 14348c2ecf20Sopenharmony_ci int err = 0; 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci if (init_addrs(test, &requested_addr, &expected_addr, 14378c2ecf20Sopenharmony_ci &expected_src_addr)) 14388c2ecf20Sopenharmony_ci goto err; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci /* Prepare server to connect to */ 14418c2ecf20Sopenharmony_ci servfd = start_server(test->type, &expected_addr, addr_len); 14428c2ecf20Sopenharmony_ci if (servfd == -1) 14438c2ecf20Sopenharmony_ci goto err; 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci clientfd = connect_to_server(test->type, &requested_addr, addr_len); 14468c2ecf20Sopenharmony_ci if (clientfd == -1) 14478c2ecf20Sopenharmony_ci goto err; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci /* Make sure src and dst addrs were overridden properly */ 14508c2ecf20Sopenharmony_ci if (cmp_peer_addr(clientfd, &expected_addr)) 14518c2ecf20Sopenharmony_ci goto err; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci if (cmp_local_ip(clientfd, &expected_src_addr)) 14548c2ecf20Sopenharmony_ci goto err; 14558c2ecf20Sopenharmony_ci 14568c2ecf20Sopenharmony_ci if (test->type == SOCK_STREAM) { 14578c2ecf20Sopenharmony_ci /* Test TCP Fast Open scenario */ 14588c2ecf20Sopenharmony_ci clientfd = fastconnect_to_server(&requested_addr, addr_len); 14598c2ecf20Sopenharmony_ci if (clientfd == -1) 14608c2ecf20Sopenharmony_ci goto err; 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci /* Make sure src and dst addrs were overridden properly */ 14638c2ecf20Sopenharmony_ci if (cmp_peer_addr(clientfd, &expected_addr)) 14648c2ecf20Sopenharmony_ci goto err; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci if (cmp_local_ip(clientfd, &expected_src_addr)) 14678c2ecf20Sopenharmony_ci goto err; 14688c2ecf20Sopenharmony_ci } 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci goto out; 14718c2ecf20Sopenharmony_cierr: 14728c2ecf20Sopenharmony_ci err = -1; 14738c2ecf20Sopenharmony_ciout: 14748c2ecf20Sopenharmony_ci close(clientfd); 14758c2ecf20Sopenharmony_ci close(servfd); 14768c2ecf20Sopenharmony_ci return err; 14778c2ecf20Sopenharmony_ci} 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_cistatic int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg) 14808c2ecf20Sopenharmony_ci{ 14818c2ecf20Sopenharmony_ci socklen_t addr_len = sizeof(struct sockaddr_storage); 14828c2ecf20Sopenharmony_ci struct sockaddr_storage expected_addr; 14838c2ecf20Sopenharmony_ci struct sockaddr_storage server_addr; 14848c2ecf20Sopenharmony_ci struct sockaddr_storage sendmsg_addr; 14858c2ecf20Sopenharmony_ci struct sockaddr_storage recvmsg_addr; 14868c2ecf20Sopenharmony_ci int clientfd = -1; 14878c2ecf20Sopenharmony_ci int servfd = -1; 14888c2ecf20Sopenharmony_ci int set_cmsg; 14898c2ecf20Sopenharmony_ci int err = 0; 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci if (test->type != SOCK_DGRAM) 14928c2ecf20Sopenharmony_ci goto err; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr)) 14958c2ecf20Sopenharmony_ci goto err; 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci /* Prepare server to sendmsg to */ 14988c2ecf20Sopenharmony_ci servfd = start_server(test->type, &server_addr, addr_len); 14998c2ecf20Sopenharmony_ci if (servfd == -1) 15008c2ecf20Sopenharmony_ci goto err; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) { 15038c2ecf20Sopenharmony_ci if (clientfd >= 0) 15048c2ecf20Sopenharmony_ci close(clientfd); 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci clientfd = sendmsg_to_server(test->type, &sendmsg_addr, 15078c2ecf20Sopenharmony_ci addr_len, set_cmsg, /*flags*/0, 15088c2ecf20Sopenharmony_ci &err); 15098c2ecf20Sopenharmony_ci if (err) 15108c2ecf20Sopenharmony_ci goto out; 15118c2ecf20Sopenharmony_ci else if (clientfd == -1) 15128c2ecf20Sopenharmony_ci goto err; 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci /* Try to receive message on server instead of using 15158c2ecf20Sopenharmony_ci * getpeername(2) on client socket, to check that client's 15168c2ecf20Sopenharmony_ci * destination address was rewritten properly, since 15178c2ecf20Sopenharmony_ci * getpeername(2) doesn't work with unconnected datagram 15188c2ecf20Sopenharmony_ci * sockets. 15198c2ecf20Sopenharmony_ci * 15208c2ecf20Sopenharmony_ci * Get source address from recvmsg(2) as well to make sure 15218c2ecf20Sopenharmony_ci * source was rewritten properly: getsockname(2) can't be used 15228c2ecf20Sopenharmony_ci * since socket is unconnected and source defined for one 15238c2ecf20Sopenharmony_ci * specific packet may differ from the one used by default and 15248c2ecf20Sopenharmony_ci * returned by getsockname(2). 15258c2ecf20Sopenharmony_ci */ 15268c2ecf20Sopenharmony_ci if (recvmsg_from_client(servfd, &recvmsg_addr) == -1) 15278c2ecf20Sopenharmony_ci goto err; 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0)) 15308c2ecf20Sopenharmony_ci goto err; 15318c2ecf20Sopenharmony_ci } 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci goto out; 15348c2ecf20Sopenharmony_cierr: 15358c2ecf20Sopenharmony_ci err = -1; 15368c2ecf20Sopenharmony_ciout: 15378c2ecf20Sopenharmony_ci close(clientfd); 15388c2ecf20Sopenharmony_ci close(servfd); 15398c2ecf20Sopenharmony_ci return err; 15408c2ecf20Sopenharmony_ci} 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_cistatic int run_test_case(int cgfd, const struct sock_addr_test *test) 15438c2ecf20Sopenharmony_ci{ 15448c2ecf20Sopenharmony_ci int progfd = -1; 15458c2ecf20Sopenharmony_ci int err = 0; 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci printf("Test case: %s .. ", test->descr); 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci progfd = test->loadfn(test); 15508c2ecf20Sopenharmony_ci if (test->expected_result == LOAD_REJECT && progfd < 0) 15518c2ecf20Sopenharmony_ci goto out; 15528c2ecf20Sopenharmony_ci else if (test->expected_result == LOAD_REJECT || progfd < 0) 15538c2ecf20Sopenharmony_ci goto err; 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci err = bpf_prog_attach(progfd, cgfd, test->attach_type, 15568c2ecf20Sopenharmony_ci BPF_F_ALLOW_OVERRIDE); 15578c2ecf20Sopenharmony_ci if (test->expected_result == ATTACH_REJECT && err) { 15588c2ecf20Sopenharmony_ci err = 0; /* error was expected, reset it */ 15598c2ecf20Sopenharmony_ci goto out; 15608c2ecf20Sopenharmony_ci } else if (test->expected_result == ATTACH_REJECT || err) { 15618c2ecf20Sopenharmony_ci goto err; 15628c2ecf20Sopenharmony_ci } else if (test->expected_result == ATTACH_OKAY) { 15638c2ecf20Sopenharmony_ci err = 0; 15648c2ecf20Sopenharmony_ci goto out; 15658c2ecf20Sopenharmony_ci } 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci switch (test->attach_type) { 15688c2ecf20Sopenharmony_ci case BPF_CGROUP_INET4_BIND: 15698c2ecf20Sopenharmony_ci case BPF_CGROUP_INET6_BIND: 15708c2ecf20Sopenharmony_ci err = run_bind_test_case(test); 15718c2ecf20Sopenharmony_ci break; 15728c2ecf20Sopenharmony_ci case BPF_CGROUP_INET4_CONNECT: 15738c2ecf20Sopenharmony_ci case BPF_CGROUP_INET6_CONNECT: 15748c2ecf20Sopenharmony_ci err = run_connect_test_case(test); 15758c2ecf20Sopenharmony_ci break; 15768c2ecf20Sopenharmony_ci case BPF_CGROUP_UDP4_SENDMSG: 15778c2ecf20Sopenharmony_ci case BPF_CGROUP_UDP6_SENDMSG: 15788c2ecf20Sopenharmony_ci err = run_xmsg_test_case(test, 1); 15798c2ecf20Sopenharmony_ci break; 15808c2ecf20Sopenharmony_ci case BPF_CGROUP_UDP4_RECVMSG: 15818c2ecf20Sopenharmony_ci case BPF_CGROUP_UDP6_RECVMSG: 15828c2ecf20Sopenharmony_ci err = run_xmsg_test_case(test, 0); 15838c2ecf20Sopenharmony_ci break; 15848c2ecf20Sopenharmony_ci default: 15858c2ecf20Sopenharmony_ci goto err; 15868c2ecf20Sopenharmony_ci } 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci if (test->expected_result == SYSCALL_EPERM && err == EPERM) { 15898c2ecf20Sopenharmony_ci err = 0; /* error was expected, reset it */ 15908c2ecf20Sopenharmony_ci goto out; 15918c2ecf20Sopenharmony_ci } 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci if (test->expected_result == SYSCALL_ENOTSUPP && err == ENOTSUPP) { 15948c2ecf20Sopenharmony_ci err = 0; /* error was expected, reset it */ 15958c2ecf20Sopenharmony_ci goto out; 15968c2ecf20Sopenharmony_ci } 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci if (err || test->expected_result != SUCCESS) 15998c2ecf20Sopenharmony_ci goto err; 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci goto out; 16028c2ecf20Sopenharmony_cierr: 16038c2ecf20Sopenharmony_ci err = -1; 16048c2ecf20Sopenharmony_ciout: 16058c2ecf20Sopenharmony_ci /* Detaching w/o checking return code: best effort attempt. */ 16068c2ecf20Sopenharmony_ci if (progfd != -1) 16078c2ecf20Sopenharmony_ci bpf_prog_detach(cgfd, test->attach_type); 16088c2ecf20Sopenharmony_ci close(progfd); 16098c2ecf20Sopenharmony_ci printf("[%s]\n", err ? "FAIL" : "PASS"); 16108c2ecf20Sopenharmony_ci return err; 16118c2ecf20Sopenharmony_ci} 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_cistatic int run_tests(int cgfd) 16148c2ecf20Sopenharmony_ci{ 16158c2ecf20Sopenharmony_ci int passes = 0; 16168c2ecf20Sopenharmony_ci int fails = 0; 16178c2ecf20Sopenharmony_ci int i; 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tests); ++i) { 16208c2ecf20Sopenharmony_ci if (run_test_case(cgfd, &tests[i])) 16218c2ecf20Sopenharmony_ci ++fails; 16228c2ecf20Sopenharmony_ci else 16238c2ecf20Sopenharmony_ci ++passes; 16248c2ecf20Sopenharmony_ci } 16258c2ecf20Sopenharmony_ci printf("Summary: %d PASSED, %d FAILED\n", passes, fails); 16268c2ecf20Sopenharmony_ci return fails ? -1 : 0; 16278c2ecf20Sopenharmony_ci} 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ciint main(int argc, char **argv) 16308c2ecf20Sopenharmony_ci{ 16318c2ecf20Sopenharmony_ci int cgfd = -1; 16328c2ecf20Sopenharmony_ci int err = 0; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci if (argc < 2) { 16358c2ecf20Sopenharmony_ci fprintf(stderr, 16368c2ecf20Sopenharmony_ci "%s has to be run via %s.sh. Skip direct run.\n", 16378c2ecf20Sopenharmony_ci argv[0], argv[0]); 16388c2ecf20Sopenharmony_ci exit(err); 16398c2ecf20Sopenharmony_ci } 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci cgfd = cgroup_setup_and_join(CG_PATH); 16428c2ecf20Sopenharmony_ci if (cgfd < 0) 16438c2ecf20Sopenharmony_ci goto err; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci if (run_tests(cgfd)) 16468c2ecf20Sopenharmony_ci goto err; 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci goto out; 16498c2ecf20Sopenharmony_cierr: 16508c2ecf20Sopenharmony_ci err = -1; 16518c2ecf20Sopenharmony_ciout: 16528c2ecf20Sopenharmony_ci close(cgfd); 16538c2ecf20Sopenharmony_ci cleanup_cgroup_environment(); 16548c2ecf20Sopenharmony_ci return err; 16558c2ecf20Sopenharmony_ci} 1656