16256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/*
26256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * eBPF user space agent part
36256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann *
46256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * Simple, _self-contained_ user space agent for the eBPF kernel
56256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * ebpf_prog.c program, which gets all map fds passed from tc via unix
66256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * domain socket in one transaction and can thus keep referencing
76256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * them from user space in order to read out (or possibly modify)
86256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * map data. Here, just as a minimal example to display counters.
96256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann *
106256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * The agent only uses the bpf(2) syscall API to read or possibly
116256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * write to eBPF maps, it doesn't need to be aware of the low-level
126256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * bytecode parts and/or ELF parsing bits.
136256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann *
146256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * ! For more details, see header comment in bpf_prog.c !
156256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann *
166256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * gcc bpf_agent.c -o bpf_agent -Wall -O2
176256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann *
186256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * For example, a more complex user space agent could run on each
196256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * host, reading and writing into eBPF maps used by tc classifier
206256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * and actions. It would thus allow for implementing a distributed
216256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * tc architecture, for example, which would push down central
226256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann * policies into eBPF maps, and thus altering run-time behaviour.
236256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann *
246256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann *   -- Happy eBPF hacking! ;)
256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann */
266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
274bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann#define _GNU_SOURCE
284bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <stdio.h>
306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <stdlib.h>
316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <string.h>
326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <errno.h>
336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <unistd.h>
346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <stdint.h>
356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <assert.h>
364bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <sys/un.h>
386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <sys/types.h>
396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <sys/stat.h>
406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include <sys/socket.h>
416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* Just some misc macros as min(), offsetof(), etc. */
436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "../../include/utils.h"
446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* Common code from fd passing. */
456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "../../include/bpf_scm.h"
466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* Common, shared definitions with ebpf_prog.c */
476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_shared.h"
486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann/* Mini syscall wrapper */
496256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann#include "bpf_sys.h"
506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
516256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_dump_drops(int fd)
526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
536256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int cpu, max;
546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
556256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	max = sysconf(_SC_NPROCESSORS_ONLN);
566256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
576256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	printf(" `- number of drops:");
586256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (cpu = 0; cpu < max; cpu++) {
596256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		long drops;
606256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
616256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		assert(bpf_lookup_elem(fd, &cpu, &drops) == 0);
626256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("\tcpu%d: %5ld", cpu, drops);
636256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
646256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	printf("\n");
656256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
666256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
676256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_dump_queue(int fd)
686256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
696256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	/* Just for the same of the example. */
706256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int max_queue = 4, i;
716256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
726256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	printf("  | nic queues:");
736256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < max_queue; i++) {
746256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		struct count_queue cq;
756256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		int ret;
766256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
776256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		memset(&cq, 0, sizeof(cq));
786256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		ret = bpf_lookup_elem(fd, &i, &cq);
796256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		assert(ret == 0 || (ret < 0 && errno == ENOENT));
806256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
816256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("\tq%d:[pkts: %ld, mis: %ld]",
826256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		       i, cq.total, cq.mismatch);
836256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
846256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	printf("\n");
856256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
866256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
876256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_dump_proto(int fd)
886256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
896256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	uint8_t protos[] = { IPPROTO_TCP, IPPROTO_UDP, IPPROTO_ICMP };
906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	char *names[] = { "tcp", "udp", "icmp" };
916256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int i;
926256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
936256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	printf("  ` protos:");
946256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < ARRAY_SIZE(protos); i++) {
956256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		struct count_tuple ct;
966256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		int ret;
976256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
986256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		memset(&ct, 0, sizeof(ct));
996256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		ret = bpf_lookup_elem(fd, &protos[i], &ct);
1006256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		assert(ret == 0 || (ret < 0 && errno == ENOENT));
1016256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1026256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("\t%s:[pkts: %ld, bytes: %ld]",
1036256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		       names[i], ct.packets, ct.bytes);
1046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
1056256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	printf("\n");
1066256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
1076256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1084bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannstatic void bpf_dump_map_data(int *tfd)
1094bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{
1104bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	int i;
1114bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
1124bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	for (i = 0; i < 30; i++) {
1134bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		const int period = 5;
1144bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
1154bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		printf("data, period: %dsec\n", period);
1164bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
1174bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		bpf_dump_drops(tfd[BPF_MAP_ID_DROPS]);
1184bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		bpf_dump_queue(tfd[BPF_MAP_ID_QUEUE]);
1194bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		bpf_dump_proto(tfd[BPF_MAP_ID_PROTO]);
1204bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
1214bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		sleep(period);
1224bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	}
1234bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann}
1244bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
1256256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic void bpf_info_loop(int *fds, struct bpf_map_aux *aux)
1266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
1276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int i, tfd[BPF_MAP_ID_MAX];
1286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	printf("ver: %d\nobj: %s\ndev: %lu\nino: %lu\nmaps: %u\n",
1306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	       aux->uds_ver, aux->obj_name, aux->obj_st.st_dev,
1316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	       aux->obj_st.st_ino, aux->num_ent);
1326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < aux->num_ent; i++) {
1346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("map%d:\n", i);
1356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf(" `- fd: %u\n", fds[i]);
1366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("  | serial: %u\n", aux->ent[i].id);
1376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("  | type: %u\n", aux->ent[i].type);
1386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("  | max elem: %u\n", aux->ent[i].max_elem);
1396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("  | size key: %u\n", aux->ent[i].size_key);
1406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		printf("  ` size val: %u\n", aux->ent[i].size_value);
1416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		tfd[aux->ent[i].id] = fds[i];
1436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
1446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1454bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	bpf_dump_map_data(tfd);
1464bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann}
1476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1484bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmannstatic void bpf_map_get_from_env(int *tfd)
1494bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann{
1504bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	char key[64], *val;
1514bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	int i;
1526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1534bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	for (i = 0; i < BPF_MAP_ID_MAX; i++) {
1544bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		memset(key, 0, sizeof(key));
1554bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		snprintf(key, sizeof(key), "BPF_MAP%d", i);
1566256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
157611f70b28719f09ca7bb998047915fa2aca52a2dNicolas Dichtel		val = getenv(key);
1584bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		assert(val != NULL);
1594bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
1604bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		tfd[i] = atoi(val);
1616256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
1626256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
1636256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1646256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannstatic int bpf_map_set_recv(int fd, int *fds,  struct bpf_map_aux *aux,
1656256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			    unsigned int entries)
1666256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
1676256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct bpf_map_set_msg msg;
1686256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int *cmsg_buf, min_fd, i;
1696256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	char *amsg_buf, *mmsg_buf;
1706256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1716256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	cmsg_buf = bpf_map_set_init(&msg, NULL, 0);
1726256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	amsg_buf = (char *)msg.aux.ent;
1736256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	mmsg_buf = (char *)&msg.aux;
1746256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1756256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < entries; i += min_fd) {
1766256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		struct cmsghdr *cmsg;
1776256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		int ret;
1786256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1796256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		min_fd = min(BPF_SCM_MAX_FDS * 1U, entries - i);
1806256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1816256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		bpf_map_set_init_single(&msg, min_fd);
1826256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1836256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		ret = recvmsg(fd, &msg.hdr, 0);
1846256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (ret <= 0)
1856256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			return ret ? : -1;
1866256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1876256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		cmsg = CMSG_FIRSTHDR(&msg.hdr);
1886256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS)
1896256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			return -EINVAL;
1906256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (msg.hdr.msg_flags & MSG_CTRUNC)
1916256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			return -EIO;
1926256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1936256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		min_fd = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(fd);
1946256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (min_fd > entries || min_fd <= 0)
1956256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			return -1;
1966256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
1976256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		memcpy(&fds[i], cmsg_buf, sizeof(fds[0]) * min_fd);
1986256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		memcpy(&aux->ent[i], amsg_buf, sizeof(aux->ent[0]) * min_fd);
1996256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		memcpy(aux, mmsg_buf, offsetof(struct bpf_map_aux, ent));
2006256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2016256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		if (i + min_fd == aux->num_ent)
2026256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			break;
2036256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
2046256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2056256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	return 0;
2066256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
2076256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2086256f8c9e45f01187b297a576e148534a393c990Daniel Borkmannint main(int argc, char **argv)
2096256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann{
2106256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int fds[BPF_SCM_MAX_FDS];
2116256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct bpf_map_aux aux;
2126256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	struct sockaddr_un addr;
2136256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	int fd, ret, i;
2146256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2154bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	/* When arguments are being passed, we take it as a path
2164bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	 * to a Unix domain socket, otherwise we grab the fds
2174bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	 * from the environment to demonstrate both possibilities.
2184bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	 */
2194bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann	if (argc == 1) {
2204bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		int tfd[BPF_MAP_ID_MAX];
2214bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
2224bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		bpf_map_get_from_env(tfd);
2234bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		bpf_dump_map_data(tfd);
2244bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
2254bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann		return 0;
2266256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
2276256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2286256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	fd = socket(AF_UNIX, SOCK_DGRAM, 0);
2296256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (fd < 0) {
2306256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		fprintf(stderr, "Cannot open socket: %s\n",
2316256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			strerror(errno));
2326256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		exit(1);
2336256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
2346256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2356256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(&addr, 0, sizeof(addr));
2366256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	addr.sun_family = AF_UNIX;
2376256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	strncpy(addr.sun_path, argv[argc - 1], sizeof(addr.sun_path));
2386256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2396256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
2406256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (ret < 0) {
2416256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		fprintf(stderr, "Cannot bind to socket: %s\n",
2426256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann			strerror(errno));
2436256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		exit(1);
2446256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	}
2456256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2466256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(fds, 0, sizeof(fds));
2476256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	memset(&aux, 0, sizeof(aux));
2486256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2496256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	ret = bpf_map_set_recv(fd, fds, &aux, BPF_SCM_MAX_FDS);
2506256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	if (ret >= 0)
2516256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		bpf_info_loop(fds, &aux);
2526256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann
2536256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	for (i = 0; i < aux.num_ent; i++)
2546256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann		close(fds[i]);
2554bd624467bc6f8f6e8b4c676f3dd8ae7593fbe70Daniel Borkmann
2566256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	close(fd);
2576256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann	return 0;
2586256f8c9e45f01187b297a576e148534a393c990Daniel Borkmann}
259