1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3*858ea5e5SAndroid Build Coastguard Worker
4*858ea5e5SAndroid Build Coastguard Worker #ifndef _GNU_SOURCE
5*858ea5e5SAndroid Build Coastguard Worker #define _GNU_SOURCE
6*858ea5e5SAndroid Build Coastguard Worker #endif
7*858ea5e5SAndroid Build Coastguard Worker #include <ctype.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <errno.h>
9*858ea5e5SAndroid Build Coastguard Worker #include <fcntl.h>
10*858ea5e5SAndroid Build Coastguard Worker #include <ftw.h>
11*858ea5e5SAndroid Build Coastguard Worker #include <libgen.h>
12*858ea5e5SAndroid Build Coastguard Worker #include <mntent.h>
13*858ea5e5SAndroid Build Coastguard Worker #include <stdbool.h>
14*858ea5e5SAndroid Build Coastguard Worker #include <stdio.h>
15*858ea5e5SAndroid Build Coastguard Worker #include <stdlib.h>
16*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
17*858ea5e5SAndroid Build Coastguard Worker #include <unistd.h>
18*858ea5e5SAndroid Build Coastguard Worker #include <net/if.h>
19*858ea5e5SAndroid Build Coastguard Worker #include <sys/mount.h>
20*858ea5e5SAndroid Build Coastguard Worker #include <sys/resource.h>
21*858ea5e5SAndroid Build Coastguard Worker #include <sys/stat.h>
22*858ea5e5SAndroid Build Coastguard Worker #include <sys/vfs.h>
23*858ea5e5SAndroid Build Coastguard Worker
24*858ea5e5SAndroid Build Coastguard Worker #include <linux/filter.h>
25*858ea5e5SAndroid Build Coastguard Worker #include <linux/limits.h>
26*858ea5e5SAndroid Build Coastguard Worker #include <linux/magic.h>
27*858ea5e5SAndroid Build Coastguard Worker #include <linux/unistd.h>
28*858ea5e5SAndroid Build Coastguard Worker
29*858ea5e5SAndroid Build Coastguard Worker #include <bpf/bpf.h>
30*858ea5e5SAndroid Build Coastguard Worker #include <bpf/hashmap.h>
31*858ea5e5SAndroid Build Coastguard Worker #include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
32*858ea5e5SAndroid Build Coastguard Worker #include <bpf/btf.h>
33*858ea5e5SAndroid Build Coastguard Worker
34*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
35*858ea5e5SAndroid Build Coastguard Worker
36*858ea5e5SAndroid Build Coastguard Worker #ifndef BPF_FS_MAGIC
37*858ea5e5SAndroid Build Coastguard Worker #define BPF_FS_MAGIC 0xcafe4a11
38*858ea5e5SAndroid Build Coastguard Worker #endif
39*858ea5e5SAndroid Build Coastguard Worker
p_err(const char * fmt,...)40*858ea5e5SAndroid Build Coastguard Worker void p_err(const char *fmt, ...)
41*858ea5e5SAndroid Build Coastguard Worker {
42*858ea5e5SAndroid Build Coastguard Worker va_list ap;
43*858ea5e5SAndroid Build Coastguard Worker
44*858ea5e5SAndroid Build Coastguard Worker va_start(ap, fmt);
45*858ea5e5SAndroid Build Coastguard Worker if (json_output) {
46*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
47*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "error");
48*858ea5e5SAndroid Build Coastguard Worker jsonw_vprintf_enquote(json_wtr, fmt, ap);
49*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
50*858ea5e5SAndroid Build Coastguard Worker } else {
51*858ea5e5SAndroid Build Coastguard Worker fprintf(stderr, "Error: ");
52*858ea5e5SAndroid Build Coastguard Worker vfprintf(stderr, fmt, ap);
53*858ea5e5SAndroid Build Coastguard Worker fprintf(stderr, "\n");
54*858ea5e5SAndroid Build Coastguard Worker }
55*858ea5e5SAndroid Build Coastguard Worker va_end(ap);
56*858ea5e5SAndroid Build Coastguard Worker }
57*858ea5e5SAndroid Build Coastguard Worker
p_info(const char * fmt,...)58*858ea5e5SAndroid Build Coastguard Worker void p_info(const char *fmt, ...)
59*858ea5e5SAndroid Build Coastguard Worker {
60*858ea5e5SAndroid Build Coastguard Worker va_list ap;
61*858ea5e5SAndroid Build Coastguard Worker
62*858ea5e5SAndroid Build Coastguard Worker if (json_output)
63*858ea5e5SAndroid Build Coastguard Worker return;
64*858ea5e5SAndroid Build Coastguard Worker
65*858ea5e5SAndroid Build Coastguard Worker va_start(ap, fmt);
66*858ea5e5SAndroid Build Coastguard Worker vfprintf(stderr, fmt, ap);
67*858ea5e5SAndroid Build Coastguard Worker fprintf(stderr, "\n");
68*858ea5e5SAndroid Build Coastguard Worker va_end(ap);
69*858ea5e5SAndroid Build Coastguard Worker }
70*858ea5e5SAndroid Build Coastguard Worker
is_bpffs(const char * path)71*858ea5e5SAndroid Build Coastguard Worker static bool is_bpffs(const char *path)
72*858ea5e5SAndroid Build Coastguard Worker {
73*858ea5e5SAndroid Build Coastguard Worker struct statfs st_fs;
74*858ea5e5SAndroid Build Coastguard Worker
75*858ea5e5SAndroid Build Coastguard Worker if (statfs(path, &st_fs) < 0)
76*858ea5e5SAndroid Build Coastguard Worker return false;
77*858ea5e5SAndroid Build Coastguard Worker
78*858ea5e5SAndroid Build Coastguard Worker return (unsigned long)st_fs.f_type == BPF_FS_MAGIC;
79*858ea5e5SAndroid Build Coastguard Worker }
80*858ea5e5SAndroid Build Coastguard Worker
81*858ea5e5SAndroid Build Coastguard Worker /* Probe whether kernel switched from memlock-based (RLIMIT_MEMLOCK) to
82*858ea5e5SAndroid Build Coastguard Worker * memcg-based memory accounting for BPF maps and programs. This was done in
83*858ea5e5SAndroid Build Coastguard Worker * commit 97306be45fbe ("Merge branch 'switch to memcg-based memory
84*858ea5e5SAndroid Build Coastguard Worker * accounting'"), in Linux 5.11.
85*858ea5e5SAndroid Build Coastguard Worker *
86*858ea5e5SAndroid Build Coastguard Worker * Libbpf also offers to probe for memcg-based accounting vs rlimit, but does
87*858ea5e5SAndroid Build Coastguard Worker * so by checking for the availability of a given BPF helper and this has
88*858ea5e5SAndroid Build Coastguard Worker * failed on some kernels with backports in the past, see commit 6b4384ff1088
89*858ea5e5SAndroid Build Coastguard Worker * ("Revert "bpftool: Use libbpf 1.0 API mode instead of RLIMIT_MEMLOCK"").
90*858ea5e5SAndroid Build Coastguard Worker * Instead, we can probe by lowering the process-based rlimit to 0, trying to
91*858ea5e5SAndroid Build Coastguard Worker * load a BPF object, and resetting the rlimit. If the load succeeds then
92*858ea5e5SAndroid Build Coastguard Worker * memcg-based accounting is supported.
93*858ea5e5SAndroid Build Coastguard Worker *
94*858ea5e5SAndroid Build Coastguard Worker * This would be too dangerous to do in the library, because multithreaded
95*858ea5e5SAndroid Build Coastguard Worker * applications might attempt to load items while the rlimit is at 0. Given
96*858ea5e5SAndroid Build Coastguard Worker * that bpftool is single-threaded, this is fine to do here.
97*858ea5e5SAndroid Build Coastguard Worker */
known_to_need_rlimit(void)98*858ea5e5SAndroid Build Coastguard Worker static bool known_to_need_rlimit(void)
99*858ea5e5SAndroid Build Coastguard Worker {
100*858ea5e5SAndroid Build Coastguard Worker struct rlimit rlim_init, rlim_cur_zero = {};
101*858ea5e5SAndroid Build Coastguard Worker struct bpf_insn insns[] = {
102*858ea5e5SAndroid Build Coastguard Worker BPF_MOV64_IMM(BPF_REG_0, 0),
103*858ea5e5SAndroid Build Coastguard Worker BPF_EXIT_INSN(),
104*858ea5e5SAndroid Build Coastguard Worker };
105*858ea5e5SAndroid Build Coastguard Worker size_t insn_cnt = ARRAY_SIZE(insns);
106*858ea5e5SAndroid Build Coastguard Worker union bpf_attr attr;
107*858ea5e5SAndroid Build Coastguard Worker int prog_fd, err;
108*858ea5e5SAndroid Build Coastguard Worker
109*858ea5e5SAndroid Build Coastguard Worker memset(&attr, 0, sizeof(attr));
110*858ea5e5SAndroid Build Coastguard Worker attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
111*858ea5e5SAndroid Build Coastguard Worker attr.insns = ptr_to_u64(insns);
112*858ea5e5SAndroid Build Coastguard Worker attr.insn_cnt = insn_cnt;
113*858ea5e5SAndroid Build Coastguard Worker attr.license = ptr_to_u64("GPL");
114*858ea5e5SAndroid Build Coastguard Worker
115*858ea5e5SAndroid Build Coastguard Worker if (getrlimit(RLIMIT_MEMLOCK, &rlim_init))
116*858ea5e5SAndroid Build Coastguard Worker return false;
117*858ea5e5SAndroid Build Coastguard Worker
118*858ea5e5SAndroid Build Coastguard Worker /* Drop the soft limit to zero. We maintain the hard limit to its
119*858ea5e5SAndroid Build Coastguard Worker * current value, because lowering it would be a permanent operation
120*858ea5e5SAndroid Build Coastguard Worker * for unprivileged users.
121*858ea5e5SAndroid Build Coastguard Worker */
122*858ea5e5SAndroid Build Coastguard Worker rlim_cur_zero.rlim_max = rlim_init.rlim_max;
123*858ea5e5SAndroid Build Coastguard Worker if (setrlimit(RLIMIT_MEMLOCK, &rlim_cur_zero))
124*858ea5e5SAndroid Build Coastguard Worker return false;
125*858ea5e5SAndroid Build Coastguard Worker
126*858ea5e5SAndroid Build Coastguard Worker /* Do not use bpf_prog_load() from libbpf here, because it calls
127*858ea5e5SAndroid Build Coastguard Worker * bump_rlimit_memlock(), interfering with the current probe.
128*858ea5e5SAndroid Build Coastguard Worker */
129*858ea5e5SAndroid Build Coastguard Worker prog_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
130*858ea5e5SAndroid Build Coastguard Worker err = errno;
131*858ea5e5SAndroid Build Coastguard Worker
132*858ea5e5SAndroid Build Coastguard Worker /* reset soft rlimit to its initial value */
133*858ea5e5SAndroid Build Coastguard Worker setrlimit(RLIMIT_MEMLOCK, &rlim_init);
134*858ea5e5SAndroid Build Coastguard Worker
135*858ea5e5SAndroid Build Coastguard Worker if (prog_fd < 0)
136*858ea5e5SAndroid Build Coastguard Worker return err == EPERM;
137*858ea5e5SAndroid Build Coastguard Worker
138*858ea5e5SAndroid Build Coastguard Worker close(prog_fd);
139*858ea5e5SAndroid Build Coastguard Worker return false;
140*858ea5e5SAndroid Build Coastguard Worker }
141*858ea5e5SAndroid Build Coastguard Worker
set_max_rlimit(void)142*858ea5e5SAndroid Build Coastguard Worker void set_max_rlimit(void)
143*858ea5e5SAndroid Build Coastguard Worker {
144*858ea5e5SAndroid Build Coastguard Worker struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
145*858ea5e5SAndroid Build Coastguard Worker
146*858ea5e5SAndroid Build Coastguard Worker if (known_to_need_rlimit())
147*858ea5e5SAndroid Build Coastguard Worker setrlimit(RLIMIT_MEMLOCK, &rinf);
148*858ea5e5SAndroid Build Coastguard Worker }
149*858ea5e5SAndroid Build Coastguard Worker
150*858ea5e5SAndroid Build Coastguard Worker static int
mnt_fs(const char * target,const char * type,char * buff,size_t bufflen)151*858ea5e5SAndroid Build Coastguard Worker mnt_fs(const char *target, const char *type, char *buff, size_t bufflen)
152*858ea5e5SAndroid Build Coastguard Worker {
153*858ea5e5SAndroid Build Coastguard Worker bool bind_done = false;
154*858ea5e5SAndroid Build Coastguard Worker
155*858ea5e5SAndroid Build Coastguard Worker while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) {
156*858ea5e5SAndroid Build Coastguard Worker if (errno != EINVAL || bind_done) {
157*858ea5e5SAndroid Build Coastguard Worker snprintf(buff, bufflen,
158*858ea5e5SAndroid Build Coastguard Worker "mount --make-private %s failed: %s",
159*858ea5e5SAndroid Build Coastguard Worker target, strerror(errno));
160*858ea5e5SAndroid Build Coastguard Worker return -1;
161*858ea5e5SAndroid Build Coastguard Worker }
162*858ea5e5SAndroid Build Coastguard Worker
163*858ea5e5SAndroid Build Coastguard Worker if (mount(target, target, "none", MS_BIND, NULL)) {
164*858ea5e5SAndroid Build Coastguard Worker snprintf(buff, bufflen,
165*858ea5e5SAndroid Build Coastguard Worker "mount --bind %s %s failed: %s",
166*858ea5e5SAndroid Build Coastguard Worker target, target, strerror(errno));
167*858ea5e5SAndroid Build Coastguard Worker return -1;
168*858ea5e5SAndroid Build Coastguard Worker }
169*858ea5e5SAndroid Build Coastguard Worker
170*858ea5e5SAndroid Build Coastguard Worker bind_done = true;
171*858ea5e5SAndroid Build Coastguard Worker }
172*858ea5e5SAndroid Build Coastguard Worker
173*858ea5e5SAndroid Build Coastguard Worker if (mount(type, target, type, 0, "mode=0700")) {
174*858ea5e5SAndroid Build Coastguard Worker snprintf(buff, bufflen, "mount -t %s %s %s failed: %s",
175*858ea5e5SAndroid Build Coastguard Worker type, type, target, strerror(errno));
176*858ea5e5SAndroid Build Coastguard Worker return -1;
177*858ea5e5SAndroid Build Coastguard Worker }
178*858ea5e5SAndroid Build Coastguard Worker
179*858ea5e5SAndroid Build Coastguard Worker return 0;
180*858ea5e5SAndroid Build Coastguard Worker }
181*858ea5e5SAndroid Build Coastguard Worker
mount_tracefs(const char * target)182*858ea5e5SAndroid Build Coastguard Worker int mount_tracefs(const char *target)
183*858ea5e5SAndroid Build Coastguard Worker {
184*858ea5e5SAndroid Build Coastguard Worker char err_str[ERR_MAX_LEN];
185*858ea5e5SAndroid Build Coastguard Worker int err;
186*858ea5e5SAndroid Build Coastguard Worker
187*858ea5e5SAndroid Build Coastguard Worker err = mnt_fs(target, "tracefs", err_str, ERR_MAX_LEN);
188*858ea5e5SAndroid Build Coastguard Worker if (err) {
189*858ea5e5SAndroid Build Coastguard Worker err_str[ERR_MAX_LEN - 1] = '\0';
190*858ea5e5SAndroid Build Coastguard Worker p_err("can't mount tracefs: %s", err_str);
191*858ea5e5SAndroid Build Coastguard Worker }
192*858ea5e5SAndroid Build Coastguard Worker
193*858ea5e5SAndroid Build Coastguard Worker return err;
194*858ea5e5SAndroid Build Coastguard Worker }
195*858ea5e5SAndroid Build Coastguard Worker
open_obj_pinned(const char * path,bool quiet)196*858ea5e5SAndroid Build Coastguard Worker int open_obj_pinned(const char *path, bool quiet)
197*858ea5e5SAndroid Build Coastguard Worker {
198*858ea5e5SAndroid Build Coastguard Worker char *pname;
199*858ea5e5SAndroid Build Coastguard Worker int fd = -1;
200*858ea5e5SAndroid Build Coastguard Worker
201*858ea5e5SAndroid Build Coastguard Worker pname = strdup(path);
202*858ea5e5SAndroid Build Coastguard Worker if (!pname) {
203*858ea5e5SAndroid Build Coastguard Worker if (!quiet)
204*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
205*858ea5e5SAndroid Build Coastguard Worker goto out_ret;
206*858ea5e5SAndroid Build Coastguard Worker }
207*858ea5e5SAndroid Build Coastguard Worker
208*858ea5e5SAndroid Build Coastguard Worker fd = bpf_obj_get(pname);
209*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
210*858ea5e5SAndroid Build Coastguard Worker if (!quiet)
211*858ea5e5SAndroid Build Coastguard Worker p_err("bpf obj get (%s): %s", pname,
212*858ea5e5SAndroid Build Coastguard Worker errno == EACCES && !is_bpffs(dirname(pname)) ?
213*858ea5e5SAndroid Build Coastguard Worker "directory not in bpf file system (bpffs)" :
214*858ea5e5SAndroid Build Coastguard Worker strerror(errno));
215*858ea5e5SAndroid Build Coastguard Worker goto out_free;
216*858ea5e5SAndroid Build Coastguard Worker }
217*858ea5e5SAndroid Build Coastguard Worker
218*858ea5e5SAndroid Build Coastguard Worker out_free:
219*858ea5e5SAndroid Build Coastguard Worker free(pname);
220*858ea5e5SAndroid Build Coastguard Worker out_ret:
221*858ea5e5SAndroid Build Coastguard Worker return fd;
222*858ea5e5SAndroid Build Coastguard Worker }
223*858ea5e5SAndroid Build Coastguard Worker
open_obj_pinned_any(const char * path,enum bpf_obj_type exp_type)224*858ea5e5SAndroid Build Coastguard Worker int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
225*858ea5e5SAndroid Build Coastguard Worker {
226*858ea5e5SAndroid Build Coastguard Worker enum bpf_obj_type type;
227*858ea5e5SAndroid Build Coastguard Worker int fd;
228*858ea5e5SAndroid Build Coastguard Worker
229*858ea5e5SAndroid Build Coastguard Worker fd = open_obj_pinned(path, false);
230*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
231*858ea5e5SAndroid Build Coastguard Worker return -1;
232*858ea5e5SAndroid Build Coastguard Worker
233*858ea5e5SAndroid Build Coastguard Worker type = get_fd_type(fd);
234*858ea5e5SAndroid Build Coastguard Worker if (type < 0) {
235*858ea5e5SAndroid Build Coastguard Worker close(fd);
236*858ea5e5SAndroid Build Coastguard Worker return type;
237*858ea5e5SAndroid Build Coastguard Worker }
238*858ea5e5SAndroid Build Coastguard Worker if (type != exp_type) {
239*858ea5e5SAndroid Build Coastguard Worker p_err("incorrect object type: %s", get_fd_type_name(type));
240*858ea5e5SAndroid Build Coastguard Worker close(fd);
241*858ea5e5SAndroid Build Coastguard Worker return -1;
242*858ea5e5SAndroid Build Coastguard Worker }
243*858ea5e5SAndroid Build Coastguard Worker
244*858ea5e5SAndroid Build Coastguard Worker return fd;
245*858ea5e5SAndroid Build Coastguard Worker }
246*858ea5e5SAndroid Build Coastguard Worker
mount_bpffs_for_pin(const char * name,bool is_dir)247*858ea5e5SAndroid Build Coastguard Worker int mount_bpffs_for_pin(const char *name, bool is_dir)
248*858ea5e5SAndroid Build Coastguard Worker {
249*858ea5e5SAndroid Build Coastguard Worker char err_str[ERR_MAX_LEN];
250*858ea5e5SAndroid Build Coastguard Worker char *file;
251*858ea5e5SAndroid Build Coastguard Worker char *dir;
252*858ea5e5SAndroid Build Coastguard Worker int err = 0;
253*858ea5e5SAndroid Build Coastguard Worker
254*858ea5e5SAndroid Build Coastguard Worker if (is_dir && is_bpffs(name))
255*858ea5e5SAndroid Build Coastguard Worker return err;
256*858ea5e5SAndroid Build Coastguard Worker
257*858ea5e5SAndroid Build Coastguard Worker file = malloc(strlen(name) + 1);
258*858ea5e5SAndroid Build Coastguard Worker if (!file) {
259*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
260*858ea5e5SAndroid Build Coastguard Worker return -1;
261*858ea5e5SAndroid Build Coastguard Worker }
262*858ea5e5SAndroid Build Coastguard Worker
263*858ea5e5SAndroid Build Coastguard Worker strcpy(file, name);
264*858ea5e5SAndroid Build Coastguard Worker dir = dirname(file);
265*858ea5e5SAndroid Build Coastguard Worker
266*858ea5e5SAndroid Build Coastguard Worker if (is_bpffs(dir))
267*858ea5e5SAndroid Build Coastguard Worker /* nothing to do if already mounted */
268*858ea5e5SAndroid Build Coastguard Worker goto out_free;
269*858ea5e5SAndroid Build Coastguard Worker
270*858ea5e5SAndroid Build Coastguard Worker if (block_mount) {
271*858ea5e5SAndroid Build Coastguard Worker p_err("no BPF file system found, not mounting it due to --nomount option");
272*858ea5e5SAndroid Build Coastguard Worker err = -1;
273*858ea5e5SAndroid Build Coastguard Worker goto out_free;
274*858ea5e5SAndroid Build Coastguard Worker }
275*858ea5e5SAndroid Build Coastguard Worker
276*858ea5e5SAndroid Build Coastguard Worker err = mnt_fs(dir, "bpf", err_str, ERR_MAX_LEN);
277*858ea5e5SAndroid Build Coastguard Worker if (err) {
278*858ea5e5SAndroid Build Coastguard Worker err_str[ERR_MAX_LEN - 1] = '\0';
279*858ea5e5SAndroid Build Coastguard Worker p_err("can't mount BPF file system to pin the object (%s): %s",
280*858ea5e5SAndroid Build Coastguard Worker name, err_str);
281*858ea5e5SAndroid Build Coastguard Worker }
282*858ea5e5SAndroid Build Coastguard Worker
283*858ea5e5SAndroid Build Coastguard Worker out_free:
284*858ea5e5SAndroid Build Coastguard Worker free(file);
285*858ea5e5SAndroid Build Coastguard Worker return err;
286*858ea5e5SAndroid Build Coastguard Worker }
287*858ea5e5SAndroid Build Coastguard Worker
do_pin_fd(int fd,const char * name)288*858ea5e5SAndroid Build Coastguard Worker int do_pin_fd(int fd, const char *name)
289*858ea5e5SAndroid Build Coastguard Worker {
290*858ea5e5SAndroid Build Coastguard Worker int err;
291*858ea5e5SAndroid Build Coastguard Worker
292*858ea5e5SAndroid Build Coastguard Worker err = mount_bpffs_for_pin(name, false);
293*858ea5e5SAndroid Build Coastguard Worker if (err)
294*858ea5e5SAndroid Build Coastguard Worker return err;
295*858ea5e5SAndroid Build Coastguard Worker
296*858ea5e5SAndroid Build Coastguard Worker err = bpf_obj_pin(fd, name);
297*858ea5e5SAndroid Build Coastguard Worker if (err)
298*858ea5e5SAndroid Build Coastguard Worker p_err("can't pin the object (%s): %s", name, strerror(errno));
299*858ea5e5SAndroid Build Coastguard Worker
300*858ea5e5SAndroid Build Coastguard Worker return err;
301*858ea5e5SAndroid Build Coastguard Worker }
302*858ea5e5SAndroid Build Coastguard Worker
do_pin_any(int argc,char ** argv,int (* get_fd)(int *,char ***))303*858ea5e5SAndroid Build Coastguard Worker int do_pin_any(int argc, char **argv, int (*get_fd)(int *, char ***))
304*858ea5e5SAndroid Build Coastguard Worker {
305*858ea5e5SAndroid Build Coastguard Worker int err;
306*858ea5e5SAndroid Build Coastguard Worker int fd;
307*858ea5e5SAndroid Build Coastguard Worker
308*858ea5e5SAndroid Build Coastguard Worker if (!REQ_ARGS(3))
309*858ea5e5SAndroid Build Coastguard Worker return -EINVAL;
310*858ea5e5SAndroid Build Coastguard Worker
311*858ea5e5SAndroid Build Coastguard Worker fd = get_fd(&argc, &argv);
312*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
313*858ea5e5SAndroid Build Coastguard Worker return fd;
314*858ea5e5SAndroid Build Coastguard Worker
315*858ea5e5SAndroid Build Coastguard Worker err = do_pin_fd(fd, *argv);
316*858ea5e5SAndroid Build Coastguard Worker
317*858ea5e5SAndroid Build Coastguard Worker close(fd);
318*858ea5e5SAndroid Build Coastguard Worker return err;
319*858ea5e5SAndroid Build Coastguard Worker }
320*858ea5e5SAndroid Build Coastguard Worker
get_fd_type_name(enum bpf_obj_type type)321*858ea5e5SAndroid Build Coastguard Worker const char *get_fd_type_name(enum bpf_obj_type type)
322*858ea5e5SAndroid Build Coastguard Worker {
323*858ea5e5SAndroid Build Coastguard Worker static const char * const names[] = {
324*858ea5e5SAndroid Build Coastguard Worker [BPF_OBJ_UNKNOWN] = "unknown",
325*858ea5e5SAndroid Build Coastguard Worker [BPF_OBJ_PROG] = "prog",
326*858ea5e5SAndroid Build Coastguard Worker [BPF_OBJ_MAP] = "map",
327*858ea5e5SAndroid Build Coastguard Worker [BPF_OBJ_LINK] = "link",
328*858ea5e5SAndroid Build Coastguard Worker };
329*858ea5e5SAndroid Build Coastguard Worker
330*858ea5e5SAndroid Build Coastguard Worker if (type < 0 || type >= ARRAY_SIZE(names) || !names[type])
331*858ea5e5SAndroid Build Coastguard Worker return names[BPF_OBJ_UNKNOWN];
332*858ea5e5SAndroid Build Coastguard Worker
333*858ea5e5SAndroid Build Coastguard Worker return names[type];
334*858ea5e5SAndroid Build Coastguard Worker }
335*858ea5e5SAndroid Build Coastguard Worker
get_prog_full_name(const struct bpf_prog_info * prog_info,int prog_fd,char * name_buff,size_t buff_len)336*858ea5e5SAndroid Build Coastguard Worker void get_prog_full_name(const struct bpf_prog_info *prog_info, int prog_fd,
337*858ea5e5SAndroid Build Coastguard Worker char *name_buff, size_t buff_len)
338*858ea5e5SAndroid Build Coastguard Worker {
339*858ea5e5SAndroid Build Coastguard Worker const char *prog_name = prog_info->name;
340*858ea5e5SAndroid Build Coastguard Worker const struct btf_type *func_type;
341*858ea5e5SAndroid Build Coastguard Worker const struct bpf_func_info finfo = {};
342*858ea5e5SAndroid Build Coastguard Worker struct bpf_prog_info info = {};
343*858ea5e5SAndroid Build Coastguard Worker __u32 info_len = sizeof(info);
344*858ea5e5SAndroid Build Coastguard Worker struct btf *prog_btf = NULL;
345*858ea5e5SAndroid Build Coastguard Worker
346*858ea5e5SAndroid Build Coastguard Worker if (buff_len <= BPF_OBJ_NAME_LEN ||
347*858ea5e5SAndroid Build Coastguard Worker strlen(prog_info->name) < BPF_OBJ_NAME_LEN - 1)
348*858ea5e5SAndroid Build Coastguard Worker goto copy_name;
349*858ea5e5SAndroid Build Coastguard Worker
350*858ea5e5SAndroid Build Coastguard Worker if (!prog_info->btf_id || prog_info->nr_func_info == 0)
351*858ea5e5SAndroid Build Coastguard Worker goto copy_name;
352*858ea5e5SAndroid Build Coastguard Worker
353*858ea5e5SAndroid Build Coastguard Worker info.nr_func_info = 1;
354*858ea5e5SAndroid Build Coastguard Worker info.func_info_rec_size = prog_info->func_info_rec_size;
355*858ea5e5SAndroid Build Coastguard Worker if (info.func_info_rec_size > sizeof(finfo))
356*858ea5e5SAndroid Build Coastguard Worker info.func_info_rec_size = sizeof(finfo);
357*858ea5e5SAndroid Build Coastguard Worker info.func_info = ptr_to_u64(&finfo);
358*858ea5e5SAndroid Build Coastguard Worker
359*858ea5e5SAndroid Build Coastguard Worker if (bpf_prog_get_info_by_fd(prog_fd, &info, &info_len))
360*858ea5e5SAndroid Build Coastguard Worker goto copy_name;
361*858ea5e5SAndroid Build Coastguard Worker
362*858ea5e5SAndroid Build Coastguard Worker prog_btf = btf__load_from_kernel_by_id(info.btf_id);
363*858ea5e5SAndroid Build Coastguard Worker if (!prog_btf)
364*858ea5e5SAndroid Build Coastguard Worker goto copy_name;
365*858ea5e5SAndroid Build Coastguard Worker
366*858ea5e5SAndroid Build Coastguard Worker func_type = btf__type_by_id(prog_btf, finfo.type_id);
367*858ea5e5SAndroid Build Coastguard Worker if (!func_type || !btf_is_func(func_type))
368*858ea5e5SAndroid Build Coastguard Worker goto copy_name;
369*858ea5e5SAndroid Build Coastguard Worker
370*858ea5e5SAndroid Build Coastguard Worker prog_name = btf__name_by_offset(prog_btf, func_type->name_off);
371*858ea5e5SAndroid Build Coastguard Worker
372*858ea5e5SAndroid Build Coastguard Worker copy_name:
373*858ea5e5SAndroid Build Coastguard Worker snprintf(name_buff, buff_len, "%s", prog_name);
374*858ea5e5SAndroid Build Coastguard Worker
375*858ea5e5SAndroid Build Coastguard Worker if (prog_btf)
376*858ea5e5SAndroid Build Coastguard Worker btf__free(prog_btf);
377*858ea5e5SAndroid Build Coastguard Worker }
378*858ea5e5SAndroid Build Coastguard Worker
get_fd_type(int fd)379*858ea5e5SAndroid Build Coastguard Worker int get_fd_type(int fd)
380*858ea5e5SAndroid Build Coastguard Worker {
381*858ea5e5SAndroid Build Coastguard Worker char path[PATH_MAX];
382*858ea5e5SAndroid Build Coastguard Worker char buf[512];
383*858ea5e5SAndroid Build Coastguard Worker ssize_t n;
384*858ea5e5SAndroid Build Coastguard Worker
385*858ea5e5SAndroid Build Coastguard Worker snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
386*858ea5e5SAndroid Build Coastguard Worker
387*858ea5e5SAndroid Build Coastguard Worker n = readlink(path, buf, sizeof(buf));
388*858ea5e5SAndroid Build Coastguard Worker if (n < 0) {
389*858ea5e5SAndroid Build Coastguard Worker p_err("can't read link type: %s", strerror(errno));
390*858ea5e5SAndroid Build Coastguard Worker return -1;
391*858ea5e5SAndroid Build Coastguard Worker }
392*858ea5e5SAndroid Build Coastguard Worker if (n == sizeof(path)) {
393*858ea5e5SAndroid Build Coastguard Worker p_err("can't read link type: path too long!");
394*858ea5e5SAndroid Build Coastguard Worker return -1;
395*858ea5e5SAndroid Build Coastguard Worker }
396*858ea5e5SAndroid Build Coastguard Worker
397*858ea5e5SAndroid Build Coastguard Worker if (strstr(buf, "bpf-map"))
398*858ea5e5SAndroid Build Coastguard Worker return BPF_OBJ_MAP;
399*858ea5e5SAndroid Build Coastguard Worker else if (strstr(buf, "bpf-prog"))
400*858ea5e5SAndroid Build Coastguard Worker return BPF_OBJ_PROG;
401*858ea5e5SAndroid Build Coastguard Worker else if (strstr(buf, "bpf-link"))
402*858ea5e5SAndroid Build Coastguard Worker return BPF_OBJ_LINK;
403*858ea5e5SAndroid Build Coastguard Worker
404*858ea5e5SAndroid Build Coastguard Worker return BPF_OBJ_UNKNOWN;
405*858ea5e5SAndroid Build Coastguard Worker }
406*858ea5e5SAndroid Build Coastguard Worker
get_fdinfo(int fd,const char * key)407*858ea5e5SAndroid Build Coastguard Worker char *get_fdinfo(int fd, const char *key)
408*858ea5e5SAndroid Build Coastguard Worker {
409*858ea5e5SAndroid Build Coastguard Worker char path[PATH_MAX];
410*858ea5e5SAndroid Build Coastguard Worker char *line = NULL;
411*858ea5e5SAndroid Build Coastguard Worker size_t line_n = 0;
412*858ea5e5SAndroid Build Coastguard Worker ssize_t n;
413*858ea5e5SAndroid Build Coastguard Worker FILE *fdi;
414*858ea5e5SAndroid Build Coastguard Worker
415*858ea5e5SAndroid Build Coastguard Worker snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);
416*858ea5e5SAndroid Build Coastguard Worker
417*858ea5e5SAndroid Build Coastguard Worker fdi = fopen(path, "r");
418*858ea5e5SAndroid Build Coastguard Worker if (!fdi)
419*858ea5e5SAndroid Build Coastguard Worker return NULL;
420*858ea5e5SAndroid Build Coastguard Worker
421*858ea5e5SAndroid Build Coastguard Worker while ((n = getline(&line, &line_n, fdi)) > 0) {
422*858ea5e5SAndroid Build Coastguard Worker char *value;
423*858ea5e5SAndroid Build Coastguard Worker int len;
424*858ea5e5SAndroid Build Coastguard Worker
425*858ea5e5SAndroid Build Coastguard Worker if (!strstr(line, key))
426*858ea5e5SAndroid Build Coastguard Worker continue;
427*858ea5e5SAndroid Build Coastguard Worker
428*858ea5e5SAndroid Build Coastguard Worker fclose(fdi);
429*858ea5e5SAndroid Build Coastguard Worker
430*858ea5e5SAndroid Build Coastguard Worker value = strchr(line, '\t');
431*858ea5e5SAndroid Build Coastguard Worker if (!value || !value[1]) {
432*858ea5e5SAndroid Build Coastguard Worker free(line);
433*858ea5e5SAndroid Build Coastguard Worker return NULL;
434*858ea5e5SAndroid Build Coastguard Worker }
435*858ea5e5SAndroid Build Coastguard Worker value++;
436*858ea5e5SAndroid Build Coastguard Worker
437*858ea5e5SAndroid Build Coastguard Worker len = strlen(value);
438*858ea5e5SAndroid Build Coastguard Worker memmove(line, value, len);
439*858ea5e5SAndroid Build Coastguard Worker line[len - 1] = '\0';
440*858ea5e5SAndroid Build Coastguard Worker
441*858ea5e5SAndroid Build Coastguard Worker return line;
442*858ea5e5SAndroid Build Coastguard Worker }
443*858ea5e5SAndroid Build Coastguard Worker
444*858ea5e5SAndroid Build Coastguard Worker free(line);
445*858ea5e5SAndroid Build Coastguard Worker fclose(fdi);
446*858ea5e5SAndroid Build Coastguard Worker return NULL;
447*858ea5e5SAndroid Build Coastguard Worker }
448*858ea5e5SAndroid Build Coastguard Worker
print_data_json(uint8_t * data,size_t len)449*858ea5e5SAndroid Build Coastguard Worker void print_data_json(uint8_t *data, size_t len)
450*858ea5e5SAndroid Build Coastguard Worker {
451*858ea5e5SAndroid Build Coastguard Worker unsigned int i;
452*858ea5e5SAndroid Build Coastguard Worker
453*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
454*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < len; i++)
455*858ea5e5SAndroid Build Coastguard Worker jsonw_printf(json_wtr, "%d", data[i]);
456*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
457*858ea5e5SAndroid Build Coastguard Worker }
458*858ea5e5SAndroid Build Coastguard Worker
print_hex_data_json(uint8_t * data,size_t len)459*858ea5e5SAndroid Build Coastguard Worker void print_hex_data_json(uint8_t *data, size_t len)
460*858ea5e5SAndroid Build Coastguard Worker {
461*858ea5e5SAndroid Build Coastguard Worker unsigned int i;
462*858ea5e5SAndroid Build Coastguard Worker
463*858ea5e5SAndroid Build Coastguard Worker jsonw_start_array(json_wtr);
464*858ea5e5SAndroid Build Coastguard Worker for (i = 0; i < len; i++)
465*858ea5e5SAndroid Build Coastguard Worker jsonw_printf(json_wtr, "\"0x%02hhx\"", data[i]);
466*858ea5e5SAndroid Build Coastguard Worker jsonw_end_array(json_wtr);
467*858ea5e5SAndroid Build Coastguard Worker }
468*858ea5e5SAndroid Build Coastguard Worker
469*858ea5e5SAndroid Build Coastguard Worker /* extra params for nftw cb */
470*858ea5e5SAndroid Build Coastguard Worker static struct hashmap *build_fn_table;
471*858ea5e5SAndroid Build Coastguard Worker static enum bpf_obj_type build_fn_type;
472*858ea5e5SAndroid Build Coastguard Worker
do_build_table_cb(const char * fpath,const struct stat * sb,int typeflag,struct FTW * ftwbuf)473*858ea5e5SAndroid Build Coastguard Worker static int do_build_table_cb(const char *fpath, const struct stat *sb,
474*858ea5e5SAndroid Build Coastguard Worker int typeflag, struct FTW *ftwbuf)
475*858ea5e5SAndroid Build Coastguard Worker {
476*858ea5e5SAndroid Build Coastguard Worker struct bpf_prog_info pinned_info;
477*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(pinned_info);
478*858ea5e5SAndroid Build Coastguard Worker enum bpf_obj_type objtype;
479*858ea5e5SAndroid Build Coastguard Worker int fd, err = 0;
480*858ea5e5SAndroid Build Coastguard Worker char *path;
481*858ea5e5SAndroid Build Coastguard Worker
482*858ea5e5SAndroid Build Coastguard Worker if (typeflag != FTW_F)
483*858ea5e5SAndroid Build Coastguard Worker goto out_ret;
484*858ea5e5SAndroid Build Coastguard Worker
485*858ea5e5SAndroid Build Coastguard Worker fd = open_obj_pinned(fpath, true);
486*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
487*858ea5e5SAndroid Build Coastguard Worker goto out_ret;
488*858ea5e5SAndroid Build Coastguard Worker
489*858ea5e5SAndroid Build Coastguard Worker objtype = get_fd_type(fd);
490*858ea5e5SAndroid Build Coastguard Worker if (objtype != build_fn_type)
491*858ea5e5SAndroid Build Coastguard Worker goto out_close;
492*858ea5e5SAndroid Build Coastguard Worker
493*858ea5e5SAndroid Build Coastguard Worker memset(&pinned_info, 0, sizeof(pinned_info));
494*858ea5e5SAndroid Build Coastguard Worker if (bpf_prog_get_info_by_fd(fd, &pinned_info, &len))
495*858ea5e5SAndroid Build Coastguard Worker goto out_close;
496*858ea5e5SAndroid Build Coastguard Worker
497*858ea5e5SAndroid Build Coastguard Worker path = strdup(fpath);
498*858ea5e5SAndroid Build Coastguard Worker if (!path) {
499*858ea5e5SAndroid Build Coastguard Worker err = -1;
500*858ea5e5SAndroid Build Coastguard Worker goto out_close;
501*858ea5e5SAndroid Build Coastguard Worker }
502*858ea5e5SAndroid Build Coastguard Worker
503*858ea5e5SAndroid Build Coastguard Worker err = hashmap__append(build_fn_table, pinned_info.id, path);
504*858ea5e5SAndroid Build Coastguard Worker if (err) {
505*858ea5e5SAndroid Build Coastguard Worker p_err("failed to append entry to hashmap for ID %u, path '%s': %s",
506*858ea5e5SAndroid Build Coastguard Worker pinned_info.id, path, strerror(errno));
507*858ea5e5SAndroid Build Coastguard Worker free(path);
508*858ea5e5SAndroid Build Coastguard Worker goto out_close;
509*858ea5e5SAndroid Build Coastguard Worker }
510*858ea5e5SAndroid Build Coastguard Worker
511*858ea5e5SAndroid Build Coastguard Worker out_close:
512*858ea5e5SAndroid Build Coastguard Worker close(fd);
513*858ea5e5SAndroid Build Coastguard Worker out_ret:
514*858ea5e5SAndroid Build Coastguard Worker return err;
515*858ea5e5SAndroid Build Coastguard Worker }
516*858ea5e5SAndroid Build Coastguard Worker
build_pinned_obj_table(struct hashmap * tab,enum bpf_obj_type type)517*858ea5e5SAndroid Build Coastguard Worker int build_pinned_obj_table(struct hashmap *tab,
518*858ea5e5SAndroid Build Coastguard Worker enum bpf_obj_type type)
519*858ea5e5SAndroid Build Coastguard Worker {
520*858ea5e5SAndroid Build Coastguard Worker struct mntent *mntent = NULL;
521*858ea5e5SAndroid Build Coastguard Worker FILE *mntfile = NULL;
522*858ea5e5SAndroid Build Coastguard Worker int flags = FTW_PHYS;
523*858ea5e5SAndroid Build Coastguard Worker int nopenfd = 16;
524*858ea5e5SAndroid Build Coastguard Worker int err = 0;
525*858ea5e5SAndroid Build Coastguard Worker
526*858ea5e5SAndroid Build Coastguard Worker mntfile = setmntent("/proc/mounts", "r");
527*858ea5e5SAndroid Build Coastguard Worker if (!mntfile)
528*858ea5e5SAndroid Build Coastguard Worker return -1;
529*858ea5e5SAndroid Build Coastguard Worker
530*858ea5e5SAndroid Build Coastguard Worker build_fn_table = tab;
531*858ea5e5SAndroid Build Coastguard Worker build_fn_type = type;
532*858ea5e5SAndroid Build Coastguard Worker
533*858ea5e5SAndroid Build Coastguard Worker while ((mntent = getmntent(mntfile))) {
534*858ea5e5SAndroid Build Coastguard Worker char *path = mntent->mnt_dir;
535*858ea5e5SAndroid Build Coastguard Worker
536*858ea5e5SAndroid Build Coastguard Worker if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
537*858ea5e5SAndroid Build Coastguard Worker continue;
538*858ea5e5SAndroid Build Coastguard Worker err = nftw(path, do_build_table_cb, nopenfd, flags);
539*858ea5e5SAndroid Build Coastguard Worker if (err)
540*858ea5e5SAndroid Build Coastguard Worker break;
541*858ea5e5SAndroid Build Coastguard Worker }
542*858ea5e5SAndroid Build Coastguard Worker fclose(mntfile);
543*858ea5e5SAndroid Build Coastguard Worker return err;
544*858ea5e5SAndroid Build Coastguard Worker }
545*858ea5e5SAndroid Build Coastguard Worker
delete_pinned_obj_table(struct hashmap * map)546*858ea5e5SAndroid Build Coastguard Worker void delete_pinned_obj_table(struct hashmap *map)
547*858ea5e5SAndroid Build Coastguard Worker {
548*858ea5e5SAndroid Build Coastguard Worker struct hashmap_entry *entry;
549*858ea5e5SAndroid Build Coastguard Worker size_t bkt;
550*858ea5e5SAndroid Build Coastguard Worker
551*858ea5e5SAndroid Build Coastguard Worker if (!map)
552*858ea5e5SAndroid Build Coastguard Worker return;
553*858ea5e5SAndroid Build Coastguard Worker
554*858ea5e5SAndroid Build Coastguard Worker hashmap__for_each_entry(map, entry, bkt)
555*858ea5e5SAndroid Build Coastguard Worker free(entry->pvalue);
556*858ea5e5SAndroid Build Coastguard Worker
557*858ea5e5SAndroid Build Coastguard Worker hashmap__free(map);
558*858ea5e5SAndroid Build Coastguard Worker }
559*858ea5e5SAndroid Build Coastguard Worker
get_page_size(void)560*858ea5e5SAndroid Build Coastguard Worker unsigned int get_page_size(void)
561*858ea5e5SAndroid Build Coastguard Worker {
562*858ea5e5SAndroid Build Coastguard Worker static int result;
563*858ea5e5SAndroid Build Coastguard Worker
564*858ea5e5SAndroid Build Coastguard Worker if (!result)
565*858ea5e5SAndroid Build Coastguard Worker result = getpagesize();
566*858ea5e5SAndroid Build Coastguard Worker return result;
567*858ea5e5SAndroid Build Coastguard Worker }
568*858ea5e5SAndroid Build Coastguard Worker
get_possible_cpus(void)569*858ea5e5SAndroid Build Coastguard Worker unsigned int get_possible_cpus(void)
570*858ea5e5SAndroid Build Coastguard Worker {
571*858ea5e5SAndroid Build Coastguard Worker int cpus = libbpf_num_possible_cpus();
572*858ea5e5SAndroid Build Coastguard Worker
573*858ea5e5SAndroid Build Coastguard Worker if (cpus < 0) {
574*858ea5e5SAndroid Build Coastguard Worker p_err("Can't get # of possible cpus: %s", strerror(-cpus));
575*858ea5e5SAndroid Build Coastguard Worker exit(-1);
576*858ea5e5SAndroid Build Coastguard Worker }
577*858ea5e5SAndroid Build Coastguard Worker return cpus;
578*858ea5e5SAndroid Build Coastguard Worker }
579*858ea5e5SAndroid Build Coastguard Worker
580*858ea5e5SAndroid Build Coastguard Worker static char *
ifindex_to_name_ns(__u32 ifindex,__u32 ns_dev,__u32 ns_ino,char * buf)581*858ea5e5SAndroid Build Coastguard Worker ifindex_to_name_ns(__u32 ifindex, __u32 ns_dev, __u32 ns_ino, char *buf)
582*858ea5e5SAndroid Build Coastguard Worker {
583*858ea5e5SAndroid Build Coastguard Worker struct stat st;
584*858ea5e5SAndroid Build Coastguard Worker int err;
585*858ea5e5SAndroid Build Coastguard Worker
586*858ea5e5SAndroid Build Coastguard Worker err = stat("/proc/self/ns/net", &st);
587*858ea5e5SAndroid Build Coastguard Worker if (err) {
588*858ea5e5SAndroid Build Coastguard Worker p_err("Can't stat /proc/self: %s", strerror(errno));
589*858ea5e5SAndroid Build Coastguard Worker return NULL;
590*858ea5e5SAndroid Build Coastguard Worker }
591*858ea5e5SAndroid Build Coastguard Worker
592*858ea5e5SAndroid Build Coastguard Worker if (st.st_dev != ns_dev || st.st_ino != ns_ino)
593*858ea5e5SAndroid Build Coastguard Worker return NULL;
594*858ea5e5SAndroid Build Coastguard Worker
595*858ea5e5SAndroid Build Coastguard Worker return if_indextoname(ifindex, buf);
596*858ea5e5SAndroid Build Coastguard Worker }
597*858ea5e5SAndroid Build Coastguard Worker
read_sysfs_hex_int(char * path)598*858ea5e5SAndroid Build Coastguard Worker static int read_sysfs_hex_int(char *path)
599*858ea5e5SAndroid Build Coastguard Worker {
600*858ea5e5SAndroid Build Coastguard Worker char vendor_id_buf[8];
601*858ea5e5SAndroid Build Coastguard Worker int len;
602*858ea5e5SAndroid Build Coastguard Worker int fd;
603*858ea5e5SAndroid Build Coastguard Worker
604*858ea5e5SAndroid Build Coastguard Worker fd = open(path, O_RDONLY);
605*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
606*858ea5e5SAndroid Build Coastguard Worker p_err("Can't open %s: %s", path, strerror(errno));
607*858ea5e5SAndroid Build Coastguard Worker return -1;
608*858ea5e5SAndroid Build Coastguard Worker }
609*858ea5e5SAndroid Build Coastguard Worker
610*858ea5e5SAndroid Build Coastguard Worker len = read(fd, vendor_id_buf, sizeof(vendor_id_buf));
611*858ea5e5SAndroid Build Coastguard Worker close(fd);
612*858ea5e5SAndroid Build Coastguard Worker if (len < 0) {
613*858ea5e5SAndroid Build Coastguard Worker p_err("Can't read %s: %s", path, strerror(errno));
614*858ea5e5SAndroid Build Coastguard Worker return -1;
615*858ea5e5SAndroid Build Coastguard Worker }
616*858ea5e5SAndroid Build Coastguard Worker if (len >= (int)sizeof(vendor_id_buf)) {
617*858ea5e5SAndroid Build Coastguard Worker p_err("Value in %s too long", path);
618*858ea5e5SAndroid Build Coastguard Worker return -1;
619*858ea5e5SAndroid Build Coastguard Worker }
620*858ea5e5SAndroid Build Coastguard Worker
621*858ea5e5SAndroid Build Coastguard Worker vendor_id_buf[len] = 0;
622*858ea5e5SAndroid Build Coastguard Worker
623*858ea5e5SAndroid Build Coastguard Worker return strtol(vendor_id_buf, NULL, 0);
624*858ea5e5SAndroid Build Coastguard Worker }
625*858ea5e5SAndroid Build Coastguard Worker
read_sysfs_netdev_hex_int(char * devname,const char * entry_name)626*858ea5e5SAndroid Build Coastguard Worker static int read_sysfs_netdev_hex_int(char *devname, const char *entry_name)
627*858ea5e5SAndroid Build Coastguard Worker {
628*858ea5e5SAndroid Build Coastguard Worker char full_path[64];
629*858ea5e5SAndroid Build Coastguard Worker
630*858ea5e5SAndroid Build Coastguard Worker snprintf(full_path, sizeof(full_path), "/sys/class/net/%s/device/%s",
631*858ea5e5SAndroid Build Coastguard Worker devname, entry_name);
632*858ea5e5SAndroid Build Coastguard Worker
633*858ea5e5SAndroid Build Coastguard Worker return read_sysfs_hex_int(full_path);
634*858ea5e5SAndroid Build Coastguard Worker }
635*858ea5e5SAndroid Build Coastguard Worker
636*858ea5e5SAndroid Build Coastguard Worker const char *
ifindex_to_arch(__u32 ifindex,__u64 ns_dev,__u64 ns_ino,const char ** opt)637*858ea5e5SAndroid Build Coastguard Worker ifindex_to_arch(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, const char **opt)
638*858ea5e5SAndroid Build Coastguard Worker {
639*858ea5e5SAndroid Build Coastguard Worker __maybe_unused int device_id;
640*858ea5e5SAndroid Build Coastguard Worker char devname[IF_NAMESIZE];
641*858ea5e5SAndroid Build Coastguard Worker int vendor_id;
642*858ea5e5SAndroid Build Coastguard Worker
643*858ea5e5SAndroid Build Coastguard Worker if (!ifindex_to_name_ns(ifindex, ns_dev, ns_ino, devname)) {
644*858ea5e5SAndroid Build Coastguard Worker p_err("Can't get net device name for ifindex %d: %s", ifindex,
645*858ea5e5SAndroid Build Coastguard Worker strerror(errno));
646*858ea5e5SAndroid Build Coastguard Worker return NULL;
647*858ea5e5SAndroid Build Coastguard Worker }
648*858ea5e5SAndroid Build Coastguard Worker
649*858ea5e5SAndroid Build Coastguard Worker vendor_id = read_sysfs_netdev_hex_int(devname, "vendor");
650*858ea5e5SAndroid Build Coastguard Worker if (vendor_id < 0) {
651*858ea5e5SAndroid Build Coastguard Worker p_err("Can't get device vendor id for %s", devname);
652*858ea5e5SAndroid Build Coastguard Worker return NULL;
653*858ea5e5SAndroid Build Coastguard Worker }
654*858ea5e5SAndroid Build Coastguard Worker
655*858ea5e5SAndroid Build Coastguard Worker switch (vendor_id) {
656*858ea5e5SAndroid Build Coastguard Worker #ifdef HAVE_LIBBFD_SUPPORT
657*858ea5e5SAndroid Build Coastguard Worker case 0x19ee:
658*858ea5e5SAndroid Build Coastguard Worker device_id = read_sysfs_netdev_hex_int(devname, "device");
659*858ea5e5SAndroid Build Coastguard Worker if (device_id != 0x4000 &&
660*858ea5e5SAndroid Build Coastguard Worker device_id != 0x6000 &&
661*858ea5e5SAndroid Build Coastguard Worker device_id != 0x6003)
662*858ea5e5SAndroid Build Coastguard Worker p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
663*858ea5e5SAndroid Build Coastguard Worker *opt = "ctx4";
664*858ea5e5SAndroid Build Coastguard Worker return "NFP-6xxx";
665*858ea5e5SAndroid Build Coastguard Worker #endif /* HAVE_LIBBFD_SUPPORT */
666*858ea5e5SAndroid Build Coastguard Worker /* No NFP support in LLVM, we have no valid triple to return. */
667*858ea5e5SAndroid Build Coastguard Worker default:
668*858ea5e5SAndroid Build Coastguard Worker p_err("Can't get arch name for device vendor id 0x%04x",
669*858ea5e5SAndroid Build Coastguard Worker vendor_id);
670*858ea5e5SAndroid Build Coastguard Worker return NULL;
671*858ea5e5SAndroid Build Coastguard Worker }
672*858ea5e5SAndroid Build Coastguard Worker }
673*858ea5e5SAndroid Build Coastguard Worker
print_dev_plain(__u32 ifindex,__u64 ns_dev,__u64 ns_inode)674*858ea5e5SAndroid Build Coastguard Worker void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
675*858ea5e5SAndroid Build Coastguard Worker {
676*858ea5e5SAndroid Build Coastguard Worker char name[IF_NAMESIZE];
677*858ea5e5SAndroid Build Coastguard Worker
678*858ea5e5SAndroid Build Coastguard Worker if (!ifindex)
679*858ea5e5SAndroid Build Coastguard Worker return;
680*858ea5e5SAndroid Build Coastguard Worker
681*858ea5e5SAndroid Build Coastguard Worker printf(" offloaded_to ");
682*858ea5e5SAndroid Build Coastguard Worker if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
683*858ea5e5SAndroid Build Coastguard Worker printf("%s", name);
684*858ea5e5SAndroid Build Coastguard Worker else
685*858ea5e5SAndroid Build Coastguard Worker printf("ifindex %u ns_dev %llu ns_ino %llu",
686*858ea5e5SAndroid Build Coastguard Worker ifindex, ns_dev, ns_inode);
687*858ea5e5SAndroid Build Coastguard Worker }
688*858ea5e5SAndroid Build Coastguard Worker
print_dev_json(__u32 ifindex,__u64 ns_dev,__u64 ns_inode)689*858ea5e5SAndroid Build Coastguard Worker void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode)
690*858ea5e5SAndroid Build Coastguard Worker {
691*858ea5e5SAndroid Build Coastguard Worker char name[IF_NAMESIZE];
692*858ea5e5SAndroid Build Coastguard Worker
693*858ea5e5SAndroid Build Coastguard Worker if (!ifindex)
694*858ea5e5SAndroid Build Coastguard Worker return;
695*858ea5e5SAndroid Build Coastguard Worker
696*858ea5e5SAndroid Build Coastguard Worker jsonw_name(json_wtr, "dev");
697*858ea5e5SAndroid Build Coastguard Worker jsonw_start_object(json_wtr);
698*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "ifindex", ifindex);
699*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "ns_dev", ns_dev);
700*858ea5e5SAndroid Build Coastguard Worker jsonw_uint_field(json_wtr, "ns_inode", ns_inode);
701*858ea5e5SAndroid Build Coastguard Worker if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
702*858ea5e5SAndroid Build Coastguard Worker jsonw_string_field(json_wtr, "ifname", name);
703*858ea5e5SAndroid Build Coastguard Worker jsonw_end_object(json_wtr);
704*858ea5e5SAndroid Build Coastguard Worker }
705*858ea5e5SAndroid Build Coastguard Worker
parse_u32_arg(int * argc,char *** argv,__u32 * val,const char * what)706*858ea5e5SAndroid Build Coastguard Worker int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what)
707*858ea5e5SAndroid Build Coastguard Worker {
708*858ea5e5SAndroid Build Coastguard Worker char *endptr;
709*858ea5e5SAndroid Build Coastguard Worker
710*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
711*858ea5e5SAndroid Build Coastguard Worker
712*858ea5e5SAndroid Build Coastguard Worker if (*val) {
713*858ea5e5SAndroid Build Coastguard Worker p_err("%s already specified", what);
714*858ea5e5SAndroid Build Coastguard Worker return -1;
715*858ea5e5SAndroid Build Coastguard Worker }
716*858ea5e5SAndroid Build Coastguard Worker
717*858ea5e5SAndroid Build Coastguard Worker *val = strtoul(**argv, &endptr, 0);
718*858ea5e5SAndroid Build Coastguard Worker if (*endptr) {
719*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse %s as %s", **argv, what);
720*858ea5e5SAndroid Build Coastguard Worker return -1;
721*858ea5e5SAndroid Build Coastguard Worker }
722*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
723*858ea5e5SAndroid Build Coastguard Worker
724*858ea5e5SAndroid Build Coastguard Worker return 0;
725*858ea5e5SAndroid Build Coastguard Worker }
726*858ea5e5SAndroid Build Coastguard Worker
727*858ea5e5SAndroid Build Coastguard Worker int __printf(2, 0)
print_all_levels(__maybe_unused enum libbpf_print_level level,const char * format,va_list args)728*858ea5e5SAndroid Build Coastguard Worker print_all_levels(__maybe_unused enum libbpf_print_level level,
729*858ea5e5SAndroid Build Coastguard Worker const char *format, va_list args)
730*858ea5e5SAndroid Build Coastguard Worker {
731*858ea5e5SAndroid Build Coastguard Worker return vfprintf(stderr, format, args);
732*858ea5e5SAndroid Build Coastguard Worker }
733*858ea5e5SAndroid Build Coastguard Worker
prog_fd_by_nametag(void * nametag,int ** fds,bool tag)734*858ea5e5SAndroid Build Coastguard Worker static int prog_fd_by_nametag(void *nametag, int **fds, bool tag)
735*858ea5e5SAndroid Build Coastguard Worker {
736*858ea5e5SAndroid Build Coastguard Worker char prog_name[MAX_PROG_FULL_NAME];
737*858ea5e5SAndroid Build Coastguard Worker unsigned int id = 0;
738*858ea5e5SAndroid Build Coastguard Worker int fd, nb_fds = 0;
739*858ea5e5SAndroid Build Coastguard Worker void *tmp;
740*858ea5e5SAndroid Build Coastguard Worker int err;
741*858ea5e5SAndroid Build Coastguard Worker
742*858ea5e5SAndroid Build Coastguard Worker while (true) {
743*858ea5e5SAndroid Build Coastguard Worker struct bpf_prog_info info = {};
744*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
745*858ea5e5SAndroid Build Coastguard Worker
746*858ea5e5SAndroid Build Coastguard Worker err = bpf_prog_get_next_id(id, &id);
747*858ea5e5SAndroid Build Coastguard Worker if (err) {
748*858ea5e5SAndroid Build Coastguard Worker if (errno != ENOENT) {
749*858ea5e5SAndroid Build Coastguard Worker p_err("%s", strerror(errno));
750*858ea5e5SAndroid Build Coastguard Worker goto err_close_fds;
751*858ea5e5SAndroid Build Coastguard Worker }
752*858ea5e5SAndroid Build Coastguard Worker return nb_fds;
753*858ea5e5SAndroid Build Coastguard Worker }
754*858ea5e5SAndroid Build Coastguard Worker
755*858ea5e5SAndroid Build Coastguard Worker fd = bpf_prog_get_fd_by_id(id);
756*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
757*858ea5e5SAndroid Build Coastguard Worker p_err("can't get prog by id (%u): %s",
758*858ea5e5SAndroid Build Coastguard Worker id, strerror(errno));
759*858ea5e5SAndroid Build Coastguard Worker goto err_close_fds;
760*858ea5e5SAndroid Build Coastguard Worker }
761*858ea5e5SAndroid Build Coastguard Worker
762*858ea5e5SAndroid Build Coastguard Worker err = bpf_prog_get_info_by_fd(fd, &info, &len);
763*858ea5e5SAndroid Build Coastguard Worker if (err) {
764*858ea5e5SAndroid Build Coastguard Worker p_err("can't get prog info (%u): %s",
765*858ea5e5SAndroid Build Coastguard Worker id, strerror(errno));
766*858ea5e5SAndroid Build Coastguard Worker goto err_close_fd;
767*858ea5e5SAndroid Build Coastguard Worker }
768*858ea5e5SAndroid Build Coastguard Worker
769*858ea5e5SAndroid Build Coastguard Worker if (tag && memcmp(nametag, info.tag, BPF_TAG_SIZE)) {
770*858ea5e5SAndroid Build Coastguard Worker close(fd);
771*858ea5e5SAndroid Build Coastguard Worker continue;
772*858ea5e5SAndroid Build Coastguard Worker }
773*858ea5e5SAndroid Build Coastguard Worker
774*858ea5e5SAndroid Build Coastguard Worker if (!tag) {
775*858ea5e5SAndroid Build Coastguard Worker get_prog_full_name(&info, fd, prog_name,
776*858ea5e5SAndroid Build Coastguard Worker sizeof(prog_name));
777*858ea5e5SAndroid Build Coastguard Worker if (strncmp(nametag, prog_name, sizeof(prog_name))) {
778*858ea5e5SAndroid Build Coastguard Worker close(fd);
779*858ea5e5SAndroid Build Coastguard Worker continue;
780*858ea5e5SAndroid Build Coastguard Worker }
781*858ea5e5SAndroid Build Coastguard Worker }
782*858ea5e5SAndroid Build Coastguard Worker
783*858ea5e5SAndroid Build Coastguard Worker if (nb_fds > 0) {
784*858ea5e5SAndroid Build Coastguard Worker tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
785*858ea5e5SAndroid Build Coastguard Worker if (!tmp) {
786*858ea5e5SAndroid Build Coastguard Worker p_err("failed to realloc");
787*858ea5e5SAndroid Build Coastguard Worker goto err_close_fd;
788*858ea5e5SAndroid Build Coastguard Worker }
789*858ea5e5SAndroid Build Coastguard Worker *fds = tmp;
790*858ea5e5SAndroid Build Coastguard Worker }
791*858ea5e5SAndroid Build Coastguard Worker (*fds)[nb_fds++] = fd;
792*858ea5e5SAndroid Build Coastguard Worker }
793*858ea5e5SAndroid Build Coastguard Worker
794*858ea5e5SAndroid Build Coastguard Worker err_close_fd:
795*858ea5e5SAndroid Build Coastguard Worker close(fd);
796*858ea5e5SAndroid Build Coastguard Worker err_close_fds:
797*858ea5e5SAndroid Build Coastguard Worker while (--nb_fds >= 0)
798*858ea5e5SAndroid Build Coastguard Worker close((*fds)[nb_fds]);
799*858ea5e5SAndroid Build Coastguard Worker return -1;
800*858ea5e5SAndroid Build Coastguard Worker }
801*858ea5e5SAndroid Build Coastguard Worker
prog_parse_fds(int * argc,char *** argv,int ** fds)802*858ea5e5SAndroid Build Coastguard Worker int prog_parse_fds(int *argc, char ***argv, int **fds)
803*858ea5e5SAndroid Build Coastguard Worker {
804*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(**argv, "id")) {
805*858ea5e5SAndroid Build Coastguard Worker unsigned int id;
806*858ea5e5SAndroid Build Coastguard Worker char *endptr;
807*858ea5e5SAndroid Build Coastguard Worker
808*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
809*858ea5e5SAndroid Build Coastguard Worker
810*858ea5e5SAndroid Build Coastguard Worker id = strtoul(**argv, &endptr, 0);
811*858ea5e5SAndroid Build Coastguard Worker if (*endptr) {
812*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse %s as ID", **argv);
813*858ea5e5SAndroid Build Coastguard Worker return -1;
814*858ea5e5SAndroid Build Coastguard Worker }
815*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
816*858ea5e5SAndroid Build Coastguard Worker
817*858ea5e5SAndroid Build Coastguard Worker (*fds)[0] = bpf_prog_get_fd_by_id(id);
818*858ea5e5SAndroid Build Coastguard Worker if ((*fds)[0] < 0) {
819*858ea5e5SAndroid Build Coastguard Worker p_err("get by id (%u): %s", id, strerror(errno));
820*858ea5e5SAndroid Build Coastguard Worker return -1;
821*858ea5e5SAndroid Build Coastguard Worker }
822*858ea5e5SAndroid Build Coastguard Worker return 1;
823*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(**argv, "tag")) {
824*858ea5e5SAndroid Build Coastguard Worker unsigned char tag[BPF_TAG_SIZE];
825*858ea5e5SAndroid Build Coastguard Worker
826*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
827*858ea5e5SAndroid Build Coastguard Worker
828*858ea5e5SAndroid Build Coastguard Worker if (sscanf(**argv, BPF_TAG_FMT, tag, tag + 1, tag + 2,
829*858ea5e5SAndroid Build Coastguard Worker tag + 3, tag + 4, tag + 5, tag + 6, tag + 7)
830*858ea5e5SAndroid Build Coastguard Worker != BPF_TAG_SIZE) {
831*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse tag");
832*858ea5e5SAndroid Build Coastguard Worker return -1;
833*858ea5e5SAndroid Build Coastguard Worker }
834*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
835*858ea5e5SAndroid Build Coastguard Worker
836*858ea5e5SAndroid Build Coastguard Worker return prog_fd_by_nametag(tag, fds, true);
837*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(**argv, "name")) {
838*858ea5e5SAndroid Build Coastguard Worker char *name;
839*858ea5e5SAndroid Build Coastguard Worker
840*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
841*858ea5e5SAndroid Build Coastguard Worker
842*858ea5e5SAndroid Build Coastguard Worker name = **argv;
843*858ea5e5SAndroid Build Coastguard Worker if (strlen(name) > MAX_PROG_FULL_NAME - 1) {
844*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse name");
845*858ea5e5SAndroid Build Coastguard Worker return -1;
846*858ea5e5SAndroid Build Coastguard Worker }
847*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
848*858ea5e5SAndroid Build Coastguard Worker
849*858ea5e5SAndroid Build Coastguard Worker return prog_fd_by_nametag(name, fds, false);
850*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(**argv, "pinned")) {
851*858ea5e5SAndroid Build Coastguard Worker char *path;
852*858ea5e5SAndroid Build Coastguard Worker
853*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
854*858ea5e5SAndroid Build Coastguard Worker
855*858ea5e5SAndroid Build Coastguard Worker path = **argv;
856*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
857*858ea5e5SAndroid Build Coastguard Worker
858*858ea5e5SAndroid Build Coastguard Worker (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_PROG);
859*858ea5e5SAndroid Build Coastguard Worker if ((*fds)[0] < 0)
860*858ea5e5SAndroid Build Coastguard Worker return -1;
861*858ea5e5SAndroid Build Coastguard Worker return 1;
862*858ea5e5SAndroid Build Coastguard Worker }
863*858ea5e5SAndroid Build Coastguard Worker
864*858ea5e5SAndroid Build Coastguard Worker p_err("expected 'id', 'tag', 'name' or 'pinned', got: '%s'?", **argv);
865*858ea5e5SAndroid Build Coastguard Worker return -1;
866*858ea5e5SAndroid Build Coastguard Worker }
867*858ea5e5SAndroid Build Coastguard Worker
prog_parse_fd(int * argc,char *** argv)868*858ea5e5SAndroid Build Coastguard Worker int prog_parse_fd(int *argc, char ***argv)
869*858ea5e5SAndroid Build Coastguard Worker {
870*858ea5e5SAndroid Build Coastguard Worker int *fds = NULL;
871*858ea5e5SAndroid Build Coastguard Worker int nb_fds, fd;
872*858ea5e5SAndroid Build Coastguard Worker
873*858ea5e5SAndroid Build Coastguard Worker fds = malloc(sizeof(int));
874*858ea5e5SAndroid Build Coastguard Worker if (!fds) {
875*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
876*858ea5e5SAndroid Build Coastguard Worker return -1;
877*858ea5e5SAndroid Build Coastguard Worker }
878*858ea5e5SAndroid Build Coastguard Worker nb_fds = prog_parse_fds(argc, argv, &fds);
879*858ea5e5SAndroid Build Coastguard Worker if (nb_fds != 1) {
880*858ea5e5SAndroid Build Coastguard Worker if (nb_fds > 1) {
881*858ea5e5SAndroid Build Coastguard Worker p_err("several programs match this handle");
882*858ea5e5SAndroid Build Coastguard Worker while (nb_fds--)
883*858ea5e5SAndroid Build Coastguard Worker close(fds[nb_fds]);
884*858ea5e5SAndroid Build Coastguard Worker }
885*858ea5e5SAndroid Build Coastguard Worker fd = -1;
886*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
887*858ea5e5SAndroid Build Coastguard Worker }
888*858ea5e5SAndroid Build Coastguard Worker
889*858ea5e5SAndroid Build Coastguard Worker fd = fds[0];
890*858ea5e5SAndroid Build Coastguard Worker exit_free:
891*858ea5e5SAndroid Build Coastguard Worker free(fds);
892*858ea5e5SAndroid Build Coastguard Worker return fd;
893*858ea5e5SAndroid Build Coastguard Worker }
894*858ea5e5SAndroid Build Coastguard Worker
map_fd_by_name(char * name,int ** fds)895*858ea5e5SAndroid Build Coastguard Worker static int map_fd_by_name(char *name, int **fds)
896*858ea5e5SAndroid Build Coastguard Worker {
897*858ea5e5SAndroid Build Coastguard Worker unsigned int id = 0;
898*858ea5e5SAndroid Build Coastguard Worker int fd, nb_fds = 0;
899*858ea5e5SAndroid Build Coastguard Worker void *tmp;
900*858ea5e5SAndroid Build Coastguard Worker int err;
901*858ea5e5SAndroid Build Coastguard Worker
902*858ea5e5SAndroid Build Coastguard Worker while (true) {
903*858ea5e5SAndroid Build Coastguard Worker struct bpf_map_info info = {};
904*858ea5e5SAndroid Build Coastguard Worker __u32 len = sizeof(info);
905*858ea5e5SAndroid Build Coastguard Worker
906*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_next_id(id, &id);
907*858ea5e5SAndroid Build Coastguard Worker if (err) {
908*858ea5e5SAndroid Build Coastguard Worker if (errno != ENOENT) {
909*858ea5e5SAndroid Build Coastguard Worker p_err("%s", strerror(errno));
910*858ea5e5SAndroid Build Coastguard Worker goto err_close_fds;
911*858ea5e5SAndroid Build Coastguard Worker }
912*858ea5e5SAndroid Build Coastguard Worker return nb_fds;
913*858ea5e5SAndroid Build Coastguard Worker }
914*858ea5e5SAndroid Build Coastguard Worker
915*858ea5e5SAndroid Build Coastguard Worker fd = bpf_map_get_fd_by_id(id);
916*858ea5e5SAndroid Build Coastguard Worker if (fd < 0) {
917*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map by id (%u): %s",
918*858ea5e5SAndroid Build Coastguard Worker id, strerror(errno));
919*858ea5e5SAndroid Build Coastguard Worker goto err_close_fds;
920*858ea5e5SAndroid Build Coastguard Worker }
921*858ea5e5SAndroid Build Coastguard Worker
922*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_info_by_fd(fd, &info, &len);
923*858ea5e5SAndroid Build Coastguard Worker if (err) {
924*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map info (%u): %s",
925*858ea5e5SAndroid Build Coastguard Worker id, strerror(errno));
926*858ea5e5SAndroid Build Coastguard Worker goto err_close_fd;
927*858ea5e5SAndroid Build Coastguard Worker }
928*858ea5e5SAndroid Build Coastguard Worker
929*858ea5e5SAndroid Build Coastguard Worker if (strncmp(name, info.name, BPF_OBJ_NAME_LEN)) {
930*858ea5e5SAndroid Build Coastguard Worker close(fd);
931*858ea5e5SAndroid Build Coastguard Worker continue;
932*858ea5e5SAndroid Build Coastguard Worker }
933*858ea5e5SAndroid Build Coastguard Worker
934*858ea5e5SAndroid Build Coastguard Worker if (nb_fds > 0) {
935*858ea5e5SAndroid Build Coastguard Worker tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
936*858ea5e5SAndroid Build Coastguard Worker if (!tmp) {
937*858ea5e5SAndroid Build Coastguard Worker p_err("failed to realloc");
938*858ea5e5SAndroid Build Coastguard Worker goto err_close_fd;
939*858ea5e5SAndroid Build Coastguard Worker }
940*858ea5e5SAndroid Build Coastguard Worker *fds = tmp;
941*858ea5e5SAndroid Build Coastguard Worker }
942*858ea5e5SAndroid Build Coastguard Worker (*fds)[nb_fds++] = fd;
943*858ea5e5SAndroid Build Coastguard Worker }
944*858ea5e5SAndroid Build Coastguard Worker
945*858ea5e5SAndroid Build Coastguard Worker err_close_fd:
946*858ea5e5SAndroid Build Coastguard Worker close(fd);
947*858ea5e5SAndroid Build Coastguard Worker err_close_fds:
948*858ea5e5SAndroid Build Coastguard Worker while (--nb_fds >= 0)
949*858ea5e5SAndroid Build Coastguard Worker close((*fds)[nb_fds]);
950*858ea5e5SAndroid Build Coastguard Worker return -1;
951*858ea5e5SAndroid Build Coastguard Worker }
952*858ea5e5SAndroid Build Coastguard Worker
map_parse_fds(int * argc,char *** argv,int ** fds)953*858ea5e5SAndroid Build Coastguard Worker int map_parse_fds(int *argc, char ***argv, int **fds)
954*858ea5e5SAndroid Build Coastguard Worker {
955*858ea5e5SAndroid Build Coastguard Worker if (is_prefix(**argv, "id")) {
956*858ea5e5SAndroid Build Coastguard Worker unsigned int id;
957*858ea5e5SAndroid Build Coastguard Worker char *endptr;
958*858ea5e5SAndroid Build Coastguard Worker
959*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
960*858ea5e5SAndroid Build Coastguard Worker
961*858ea5e5SAndroid Build Coastguard Worker id = strtoul(**argv, &endptr, 0);
962*858ea5e5SAndroid Build Coastguard Worker if (*endptr) {
963*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse %s as ID", **argv);
964*858ea5e5SAndroid Build Coastguard Worker return -1;
965*858ea5e5SAndroid Build Coastguard Worker }
966*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
967*858ea5e5SAndroid Build Coastguard Worker
968*858ea5e5SAndroid Build Coastguard Worker (*fds)[0] = bpf_map_get_fd_by_id(id);
969*858ea5e5SAndroid Build Coastguard Worker if ((*fds)[0] < 0) {
970*858ea5e5SAndroid Build Coastguard Worker p_err("get map by id (%u): %s", id, strerror(errno));
971*858ea5e5SAndroid Build Coastguard Worker return -1;
972*858ea5e5SAndroid Build Coastguard Worker }
973*858ea5e5SAndroid Build Coastguard Worker return 1;
974*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(**argv, "name")) {
975*858ea5e5SAndroid Build Coastguard Worker char *name;
976*858ea5e5SAndroid Build Coastguard Worker
977*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
978*858ea5e5SAndroid Build Coastguard Worker
979*858ea5e5SAndroid Build Coastguard Worker name = **argv;
980*858ea5e5SAndroid Build Coastguard Worker if (strlen(name) > BPF_OBJ_NAME_LEN - 1) {
981*858ea5e5SAndroid Build Coastguard Worker p_err("can't parse name");
982*858ea5e5SAndroid Build Coastguard Worker return -1;
983*858ea5e5SAndroid Build Coastguard Worker }
984*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
985*858ea5e5SAndroid Build Coastguard Worker
986*858ea5e5SAndroid Build Coastguard Worker return map_fd_by_name(name, fds);
987*858ea5e5SAndroid Build Coastguard Worker } else if (is_prefix(**argv, "pinned")) {
988*858ea5e5SAndroid Build Coastguard Worker char *path;
989*858ea5e5SAndroid Build Coastguard Worker
990*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
991*858ea5e5SAndroid Build Coastguard Worker
992*858ea5e5SAndroid Build Coastguard Worker path = **argv;
993*858ea5e5SAndroid Build Coastguard Worker NEXT_ARGP();
994*858ea5e5SAndroid Build Coastguard Worker
995*858ea5e5SAndroid Build Coastguard Worker (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_MAP);
996*858ea5e5SAndroid Build Coastguard Worker if ((*fds)[0] < 0)
997*858ea5e5SAndroid Build Coastguard Worker return -1;
998*858ea5e5SAndroid Build Coastguard Worker return 1;
999*858ea5e5SAndroid Build Coastguard Worker }
1000*858ea5e5SAndroid Build Coastguard Worker
1001*858ea5e5SAndroid Build Coastguard Worker p_err("expected 'id', 'name' or 'pinned', got: '%s'?", **argv);
1002*858ea5e5SAndroid Build Coastguard Worker return -1;
1003*858ea5e5SAndroid Build Coastguard Worker }
1004*858ea5e5SAndroid Build Coastguard Worker
map_parse_fd(int * argc,char *** argv)1005*858ea5e5SAndroid Build Coastguard Worker int map_parse_fd(int *argc, char ***argv)
1006*858ea5e5SAndroid Build Coastguard Worker {
1007*858ea5e5SAndroid Build Coastguard Worker int *fds = NULL;
1008*858ea5e5SAndroid Build Coastguard Worker int nb_fds, fd;
1009*858ea5e5SAndroid Build Coastguard Worker
1010*858ea5e5SAndroid Build Coastguard Worker fds = malloc(sizeof(int));
1011*858ea5e5SAndroid Build Coastguard Worker if (!fds) {
1012*858ea5e5SAndroid Build Coastguard Worker p_err("mem alloc failed");
1013*858ea5e5SAndroid Build Coastguard Worker return -1;
1014*858ea5e5SAndroid Build Coastguard Worker }
1015*858ea5e5SAndroid Build Coastguard Worker nb_fds = map_parse_fds(argc, argv, &fds);
1016*858ea5e5SAndroid Build Coastguard Worker if (nb_fds != 1) {
1017*858ea5e5SAndroid Build Coastguard Worker if (nb_fds > 1) {
1018*858ea5e5SAndroid Build Coastguard Worker p_err("several maps match this handle");
1019*858ea5e5SAndroid Build Coastguard Worker while (nb_fds--)
1020*858ea5e5SAndroid Build Coastguard Worker close(fds[nb_fds]);
1021*858ea5e5SAndroid Build Coastguard Worker }
1022*858ea5e5SAndroid Build Coastguard Worker fd = -1;
1023*858ea5e5SAndroid Build Coastguard Worker goto exit_free;
1024*858ea5e5SAndroid Build Coastguard Worker }
1025*858ea5e5SAndroid Build Coastguard Worker
1026*858ea5e5SAndroid Build Coastguard Worker fd = fds[0];
1027*858ea5e5SAndroid Build Coastguard Worker exit_free:
1028*858ea5e5SAndroid Build Coastguard Worker free(fds);
1029*858ea5e5SAndroid Build Coastguard Worker return fd;
1030*858ea5e5SAndroid Build Coastguard Worker }
1031*858ea5e5SAndroid Build Coastguard Worker
map_parse_fd_and_info(int * argc,char *** argv,struct bpf_map_info * info,__u32 * info_len)1032*858ea5e5SAndroid Build Coastguard Worker int map_parse_fd_and_info(int *argc, char ***argv, struct bpf_map_info *info,
1033*858ea5e5SAndroid Build Coastguard Worker __u32 *info_len)
1034*858ea5e5SAndroid Build Coastguard Worker {
1035*858ea5e5SAndroid Build Coastguard Worker int err;
1036*858ea5e5SAndroid Build Coastguard Worker int fd;
1037*858ea5e5SAndroid Build Coastguard Worker
1038*858ea5e5SAndroid Build Coastguard Worker fd = map_parse_fd(argc, argv);
1039*858ea5e5SAndroid Build Coastguard Worker if (fd < 0)
1040*858ea5e5SAndroid Build Coastguard Worker return -1;
1041*858ea5e5SAndroid Build Coastguard Worker
1042*858ea5e5SAndroid Build Coastguard Worker err = bpf_map_get_info_by_fd(fd, info, info_len);
1043*858ea5e5SAndroid Build Coastguard Worker if (err) {
1044*858ea5e5SAndroid Build Coastguard Worker p_err("can't get map info: %s", strerror(errno));
1045*858ea5e5SAndroid Build Coastguard Worker close(fd);
1046*858ea5e5SAndroid Build Coastguard Worker return err;
1047*858ea5e5SAndroid Build Coastguard Worker }
1048*858ea5e5SAndroid Build Coastguard Worker
1049*858ea5e5SAndroid Build Coastguard Worker return fd;
1050*858ea5e5SAndroid Build Coastguard Worker }
1051*858ea5e5SAndroid Build Coastguard Worker
hash_fn_for_key_as_id(long key,void * ctx)1052*858ea5e5SAndroid Build Coastguard Worker size_t hash_fn_for_key_as_id(long key, void *ctx)
1053*858ea5e5SAndroid Build Coastguard Worker {
1054*858ea5e5SAndroid Build Coastguard Worker return key;
1055*858ea5e5SAndroid Build Coastguard Worker }
1056*858ea5e5SAndroid Build Coastguard Worker
equal_fn_for_key_as_id(long k1,long k2,void * ctx)1057*858ea5e5SAndroid Build Coastguard Worker bool equal_fn_for_key_as_id(long k1, long k2, void *ctx)
1058*858ea5e5SAndroid Build Coastguard Worker {
1059*858ea5e5SAndroid Build Coastguard Worker return k1 == k2;
1060*858ea5e5SAndroid Build Coastguard Worker }
1061*858ea5e5SAndroid Build Coastguard Worker
bpf_attach_type_input_str(enum bpf_attach_type t)1062*858ea5e5SAndroid Build Coastguard Worker const char *bpf_attach_type_input_str(enum bpf_attach_type t)
1063*858ea5e5SAndroid Build Coastguard Worker {
1064*858ea5e5SAndroid Build Coastguard Worker switch (t) {
1065*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET_INGRESS: return "ingress";
1066*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET_EGRESS: return "egress";
1067*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET_SOCK_CREATE: return "sock_create";
1068*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET_SOCK_RELEASE: return "sock_release";
1069*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_SOCK_OPS: return "sock_ops";
1070*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_DEVICE: return "device";
1071*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET4_BIND: return "bind4";
1072*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET6_BIND: return "bind6";
1073*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET4_CONNECT: return "connect4";
1074*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET6_CONNECT: return "connect6";
1075*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET4_POST_BIND: return "post_bind4";
1076*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET6_POST_BIND: return "post_bind6";
1077*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET4_GETPEERNAME: return "getpeername4";
1078*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET6_GETPEERNAME: return "getpeername6";
1079*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET4_GETSOCKNAME: return "getsockname4";
1080*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_INET6_GETSOCKNAME: return "getsockname6";
1081*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_UDP4_SENDMSG: return "sendmsg4";
1082*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_UDP6_SENDMSG: return "sendmsg6";
1083*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_SYSCTL: return "sysctl";
1084*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_UDP4_RECVMSG: return "recvmsg4";
1085*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_UDP6_RECVMSG: return "recvmsg6";
1086*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_GETSOCKOPT: return "getsockopt";
1087*858ea5e5SAndroid Build Coastguard Worker case BPF_CGROUP_SETSOCKOPT: return "setsockopt";
1088*858ea5e5SAndroid Build Coastguard Worker case BPF_TRACE_RAW_TP: return "raw_tp";
1089*858ea5e5SAndroid Build Coastguard Worker case BPF_TRACE_FENTRY: return "fentry";
1090*858ea5e5SAndroid Build Coastguard Worker case BPF_TRACE_FEXIT: return "fexit";
1091*858ea5e5SAndroid Build Coastguard Worker case BPF_MODIFY_RETURN: return "mod_ret";
1092*858ea5e5SAndroid Build Coastguard Worker case BPF_SK_REUSEPORT_SELECT: return "sk_skb_reuseport_select";
1093*858ea5e5SAndroid Build Coastguard Worker case BPF_SK_REUSEPORT_SELECT_OR_MIGRATE: return "sk_skb_reuseport_select_or_migrate";
1094*858ea5e5SAndroid Build Coastguard Worker default: return libbpf_bpf_attach_type_str(t);
1095*858ea5e5SAndroid Build Coastguard Worker }
1096*858ea5e5SAndroid Build Coastguard Worker }
1097*858ea5e5SAndroid Build Coastguard Worker
pathname_concat(char * buf,int buf_sz,const char * path,const char * name)1098*858ea5e5SAndroid Build Coastguard Worker int pathname_concat(char *buf, int buf_sz, const char *path,
1099*858ea5e5SAndroid Build Coastguard Worker const char *name)
1100*858ea5e5SAndroid Build Coastguard Worker {
1101*858ea5e5SAndroid Build Coastguard Worker int len;
1102*858ea5e5SAndroid Build Coastguard Worker
1103*858ea5e5SAndroid Build Coastguard Worker len = snprintf(buf, buf_sz, "%s/%s", path, name);
1104*858ea5e5SAndroid Build Coastguard Worker if (len < 0)
1105*858ea5e5SAndroid Build Coastguard Worker return -EINVAL;
1106*858ea5e5SAndroid Build Coastguard Worker if (len >= buf_sz)
1107*858ea5e5SAndroid Build Coastguard Worker return -ENAMETOOLONG;
1108*858ea5e5SAndroid Build Coastguard Worker
1109*858ea5e5SAndroid Build Coastguard Worker return 0;
1110*858ea5e5SAndroid Build Coastguard Worker }
1111