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