brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 3844f9b Raw
214 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2018 Facebook3// Copyright (c) 2019 Cloudflare4 5#include <limits.h>6#include <string.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/socket.h>14 15#include <bpf/bpf.h>16#include <bpf/libbpf.h>17 18#include "cgroup_helpers.h"19#include "network_helpers.h"20 21static int get_map_fd_by_prog_id(int prog_id, bool *xdp)22{23	struct bpf_prog_info info = {};24	__u32 info_len = sizeof(info);25	__u32 map_ids[1];26	int prog_fd = -1;27	int map_fd = -1;28 29	prog_fd = bpf_prog_get_fd_by_id(prog_id);30	if (prog_fd < 0) {31		log_err("Failed to get fd by prog id %d", prog_id);32		goto err;33	}34 35	info.nr_map_ids = 1;36	info.map_ids = (__u64)(unsigned long)map_ids;37 38	if (bpf_prog_get_info_by_fd(prog_fd, &info, &info_len)) {39		log_err("Failed to get info by prog fd %d", prog_fd);40		goto err;41	}42 43	if (!info.nr_map_ids) {44		log_err("No maps found for prog fd %d", prog_fd);45		goto err;46	}47 48	*xdp = info.type == BPF_PROG_TYPE_XDP;49 50	map_fd = bpf_map_get_fd_by_id(map_ids[0]);51	if (map_fd < 0)52		log_err("Failed to get fd by map id %d", map_ids[0]);53err:54	if (prog_fd >= 0)55		close(prog_fd);56	return map_fd;57}58 59static int run_test(int server_fd, int results_fd, bool xdp)60{61	int client = -1, srv_client = -1;62	int ret = 0;63	__u32 key = 0;64	__u32 key_gen = 1;65	__u32 key_mss = 2;66	__u32 value = 0;67	__u32 value_gen = 0;68	__u32 value_mss = 0;69 70	if (bpf_map_update_elem(results_fd, &key, &value, 0) < 0) {71		log_err("Can't clear results");72		goto err;73	}74 75	if (bpf_map_update_elem(results_fd, &key_gen, &value_gen, 0) < 0) {76		log_err("Can't clear results");77		goto err;78	}79 80	if (bpf_map_update_elem(results_fd, &key_mss, &value_mss, 0) < 0) {81		log_err("Can't clear results");82		goto err;83	}84 85	client = connect_to_fd(server_fd, 0);86	if (client == -1)87		goto err;88 89	srv_client = accept(server_fd, NULL, 0);90	if (srv_client == -1) {91		log_err("Can't accept connection");92		goto err;93	}94 95	if (bpf_map_lookup_elem(results_fd, &key, &value) < 0) {96		log_err("Can't lookup result");97		goto err;98	}99 100	if (value == 0) {101		log_err("Didn't match syncookie: %u", value);102		goto err;103	}104 105	if (bpf_map_lookup_elem(results_fd, &key_gen, &value_gen) < 0) {106		log_err("Can't lookup result");107		goto err;108	}109 110	if (xdp && value_gen == 0) {111		// SYN packets do not get passed through generic XDP, skip the112		// rest of the test.113		printf("Skipping XDP cookie check\n");114		goto out;115	}116 117	if (bpf_map_lookup_elem(results_fd, &key_mss, &value_mss) < 0) {118		log_err("Can't lookup result");119		goto err;120	}121 122	if (value != value_gen) {123		log_err("BPF generated cookie does not match kernel one");124		goto err;125	}126 127	if (value_mss < 536 || value_mss > USHRT_MAX) {128		log_err("Unexpected MSS retrieved");129		goto err;130	}131 132	goto out;133 134err:135	ret = 1;136out:137	close(client);138	close(srv_client);139	return ret;140}141 142static int v6only_true(int fd, void *opts)143{144	int mode = true;145 146	return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode));147}148 149static int v6only_false(int fd, void *opts)150{151	int mode = false;152 153	return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode));154}155 156int main(int argc, char **argv)157{158	struct network_helper_opts opts = { 0 };159	int server = -1;160	int server_v6 = -1;161	int server_dual = -1;162	int results = -1;163	int err = 0;164	bool xdp;165 166	if (argc < 2) {167		fprintf(stderr, "Usage: %s prog_id\n", argv[0]);168		exit(1);169	}170 171	/* Use libbpf 1.0 API mode */172	libbpf_set_strict_mode(LIBBPF_STRICT_ALL);173 174	results = get_map_fd_by_prog_id(atoi(argv[1]), &xdp);175	if (results < 0) {176		log_err("Can't get map");177		goto err;178	}179 180	server = start_server_str(AF_INET, SOCK_STREAM, "127.0.0.1", 0, NULL);181	if (server == -1)182		goto err;183 184	opts.post_socket_cb = v6only_true;185	server_v6 = start_server_str(AF_INET6, SOCK_STREAM, "::1", 0, &opts);186	if (server_v6 == -1)187		goto err;188 189	opts.post_socket_cb = v6only_false;190	server_dual = start_server_str(AF_INET6, SOCK_STREAM, "::0", 0, &opts);191	if (server_dual == -1)192		goto err;193 194	if (run_test(server, results, xdp))195		goto err;196 197	if (run_test(server_v6, results, xdp))198		goto err;199 200	if (run_test(server_dual, results, xdp))201		goto err;202 203	printf("ok\n");204	goto out;205err:206	err = 1;207out:208	close(server);209	close(server_v6);210	close(server_dual);211	close(results);212	return err;213}214