// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
// Copyright (c) 2020 Cloudflare
/*
* Test BPF attach point for INET socket lookup (BPF_SK_LOOKUP).
*
* Tests exercise:
* - attaching/detaching/querying programs to BPF_SK_LOOKUP hook,
* - redirecting socket lookup to a socket selected by BPF program,
* - failing a socket lookup on BPF program's request,
* - error scenarios for selecting a socket from BPF program,
* - accessing BPF program context,
* - attaching and running multiple BPF programs.
*
* Tests run in a dedicated network namespace.
*/
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
#include "test_progs.h"
#include "bpf_rlimit.h"
#include "bpf_util.h"
#include "cgroup_helpers.h"
#include "network_helpers.h"
#include "testing_helpers.h"
#include "test_sk_lookup.skel.h"
/* External (address, port) pairs the client sends packets to. */
#define EXT_IP4 "127.0.0.1"
#define EXT_IP6 "fd00::1"
#define EXT_PORT 7007
/* Internal (address, port) pairs the server listens/receives at. */
#define INT_IP4 "127.0.0.2"
#define INT_IP4_V6 "::ffff:127.0.0.2"
#define INT_IP6 "fd00::2"
#define INT_PORT 8008
#define IO_TIMEOUT_SEC 3
enum server {
SERVER_A = 0,
SERVER_B = 1,
MAX_SERVERS,
};
enum {
PROG1 = 0,
PROG2,
};
struct inet_addr {
const char *ip;
unsigned short port;
};
struct test {
const char *desc;
struct bpf_program *lookup_prog;
struct bpf_program *reuseport_prog;
struct bpf_map *sock_map;
int sotype;
struct inet_addr connect_to;
struct inet_addr listen_at;
enum server accept_on;
bool reuseport_has_conns; /* Add a connected socket to reuseport group */
};
static __u32 duration; /* for CHECK macro */
static bool is_ipv6(const char *ip)
{
return !!strchr(ip, ':');
}
static int attach_reuseport(int sock_fd, struct bpf_program *reuseport_prog)
{
int err, prog_fd;
prog_fd = bpf_program__fd(reuseport_prog);
if (prog_fd < 0) {
errno = -prog_fd;
return -1;
}
err = setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF,
&prog_fd, sizeof(prog_fd));
if (err)
return -1;
return 0;
}
static socklen_t inetaddr_len(const struct