hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/tools/bpf/bpftool/common.c
....@@ -1,40 +1,11 @@
1
-/*
2
- * Copyright (C) 2017-2018 Netronome Systems, Inc.
3
- *
4
- * This software is dual licensed under the GNU General License Version 2,
5
- * June 1991 as shown in the file COPYING in the top-level directory of this
6
- * source tree or the BSD 2-Clause License provided below. You have the
7
- * option to license this software under the complete terms of either license.
8
- *
9
- * The BSD 2-Clause License:
10
- *
11
- * Redistribution and use in source and binary forms, with or
12
- * without modification, are permitted provided that the following
13
- * conditions are met:
14
- *
15
- * 1. Redistributions of source code must retain the above
16
- * copyright notice, this list of conditions and the following
17
- * disclaimer.
18
- *
19
- * 2. Redistributions in binary form must reproduce the above
20
- * copyright notice, this list of conditions and the following
21
- * disclaimer in the documentation and/or other materials
22
- * provided with the distribution.
23
- *
24
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
- * SOFTWARE.
32
- */
1
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2
+/* Copyright (C) 2017-2018 Netronome Systems, Inc. */
333
4
+#define _GNU_SOURCE
345 #include <ctype.h>
356 #include <errno.h>
367 #include <fcntl.h>
37
-#include <fts.h>
8
+#include <ftw.h>
389 #include <libgen.h>
3910 #include <mntent.h>
4011 #include <stdbool.h>
....@@ -46,17 +17,56 @@
4617 #include <linux/magic.h>
4718 #include <net/if.h>
4819 #include <sys/mount.h>
20
+#include <sys/resource.h>
4921 #include <sys/stat.h>
50
-#include <sys/types.h>
5122 #include <sys/vfs.h>
5223
53
-#include <bpf.h>
24
+#include <bpf/bpf.h>
25
+#include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
5426
5527 #include "main.h"
5628
5729 #ifndef BPF_FS_MAGIC
5830 #define BPF_FS_MAGIC 0xcafe4a11
5931 #endif
32
+
33
+const char * const attach_type_name[__MAX_BPF_ATTACH_TYPE] = {
34
+ [BPF_CGROUP_INET_INGRESS] = "ingress",
35
+ [BPF_CGROUP_INET_EGRESS] = "egress",
36
+ [BPF_CGROUP_INET_SOCK_CREATE] = "sock_create",
37
+ [BPF_CGROUP_INET_SOCK_RELEASE] = "sock_release",
38
+ [BPF_CGROUP_SOCK_OPS] = "sock_ops",
39
+ [BPF_CGROUP_DEVICE] = "device",
40
+ [BPF_CGROUP_INET4_BIND] = "bind4",
41
+ [BPF_CGROUP_INET6_BIND] = "bind6",
42
+ [BPF_CGROUP_INET4_CONNECT] = "connect4",
43
+ [BPF_CGROUP_INET6_CONNECT] = "connect6",
44
+ [BPF_CGROUP_INET4_POST_BIND] = "post_bind4",
45
+ [BPF_CGROUP_INET6_POST_BIND] = "post_bind6",
46
+ [BPF_CGROUP_INET4_GETPEERNAME] = "getpeername4",
47
+ [BPF_CGROUP_INET6_GETPEERNAME] = "getpeername6",
48
+ [BPF_CGROUP_INET4_GETSOCKNAME] = "getsockname4",
49
+ [BPF_CGROUP_INET6_GETSOCKNAME] = "getsockname6",
50
+ [BPF_CGROUP_UDP4_SENDMSG] = "sendmsg4",
51
+ [BPF_CGROUP_UDP6_SENDMSG] = "sendmsg6",
52
+ [BPF_CGROUP_SYSCTL] = "sysctl",
53
+ [BPF_CGROUP_UDP4_RECVMSG] = "recvmsg4",
54
+ [BPF_CGROUP_UDP6_RECVMSG] = "recvmsg6",
55
+ [BPF_CGROUP_GETSOCKOPT] = "getsockopt",
56
+ [BPF_CGROUP_SETSOCKOPT] = "setsockopt",
57
+
58
+ [BPF_SK_SKB_STREAM_PARSER] = "sk_skb_stream_parser",
59
+ [BPF_SK_SKB_STREAM_VERDICT] = "sk_skb_stream_verdict",
60
+ [BPF_SK_MSG_VERDICT] = "sk_msg_verdict",
61
+ [BPF_LIRC_MODE2] = "lirc_mode2",
62
+ [BPF_FLOW_DISSECTOR] = "flow_dissector",
63
+ [BPF_TRACE_RAW_TP] = "raw_tp",
64
+ [BPF_TRACE_FENTRY] = "fentry",
65
+ [BPF_TRACE_FEXIT] = "fexit",
66
+ [BPF_MODIFY_RETURN] = "mod_ret",
67
+ [BPF_LSM_MAC] = "lsm_mac",
68
+ [BPF_SK_LOOKUP] = "sk_lookup",
69
+};
6070
6171 void p_err(const char *fmt, ...)
6272 {
....@@ -99,7 +109,15 @@
99109 return (unsigned long)st_fs.f_type == BPF_FS_MAGIC;
100110 }
101111
102
-static int mnt_bpffs(const char *target, char *buff, size_t bufflen)
112
+void set_max_rlimit(void)
113
+{
114
+ struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
115
+
116
+ setrlimit(RLIMIT_MEMLOCK, &rinf);
117
+}
118
+
119
+static int
120
+mnt_fs(const char *target, const char *type, char *buff, size_t bufflen)
103121 {
104122 bool bind_done = false;
105123
....@@ -121,33 +139,58 @@
121139 bind_done = true;
122140 }
123141
124
- if (mount("bpf", target, "bpf", 0, "mode=0700")) {
125
- snprintf(buff, bufflen, "mount -t bpf bpf %s failed: %s",
126
- target, strerror(errno));
142
+ if (mount(type, target, type, 0, "mode=0700")) {
143
+ snprintf(buff, bufflen, "mount -t %s %s %s failed: %s",
144
+ type, type, target, strerror(errno));
127145 return -1;
128146 }
129147
130148 return 0;
131149 }
132150
133
-int open_obj_pinned(char *path, bool quiet)
151
+int mount_tracefs(const char *target)
134152 {
135
- int fd;
153
+ char err_str[ERR_MAX_LEN];
154
+ int err;
136155
137
- fd = bpf_obj_get(path);
138
- if (fd < 0) {
139
- if (!quiet)
140
- p_err("bpf obj get (%s): %s", path,
141
- errno == EACCES && !is_bpffs(dirname(path)) ?
142
- "directory not in bpf file system (bpffs)" :
143
- strerror(errno));
144
- return -1;
156
+ err = mnt_fs(target, "tracefs", err_str, ERR_MAX_LEN);
157
+ if (err) {
158
+ err_str[ERR_MAX_LEN - 1] = '\0';
159
+ p_err("can't mount tracefs: %s", err_str);
145160 }
146161
162
+ return err;
163
+}
164
+
165
+int open_obj_pinned(const char *path, bool quiet)
166
+{
167
+ char *pname;
168
+ int fd = -1;
169
+
170
+ pname = strdup(path);
171
+ if (!pname) {
172
+ if (!quiet)
173
+ p_err("mem alloc failed");
174
+ goto out_ret;
175
+ }
176
+
177
+ fd = bpf_obj_get(pname);
178
+ if (fd < 0) {
179
+ if (!quiet)
180
+ p_err("bpf obj get (%s): %s", pname,
181
+ errno == EACCES && !is_bpffs(dirname(pname)) ?
182
+ "directory not in bpf file system (bpffs)" :
183
+ strerror(errno));
184
+ goto out_free;
185
+ }
186
+
187
+out_free:
188
+ free(pname);
189
+out_ret:
147190 return fd;
148191 }
149192
150
-int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
193
+int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
151194 {
152195 enum bpf_obj_type type;
153196 int fd;
....@@ -170,16 +213,12 @@
170213 return fd;
171214 }
172215
173
-int do_pin_fd(int fd, const char *name)
216
+int mount_bpffs_for_pin(const char *name)
174217 {
175218 char err_str[ERR_MAX_LEN];
176219 char *file;
177220 char *dir;
178221 int err = 0;
179
-
180
- err = bpf_obj_pin(fd, name);
181
- if (!err)
182
- goto out;
183222
184223 file = malloc(strlen(name) + 1);
185224 if (!file) {
....@@ -190,19 +229,18 @@
190229 strcpy(file, name);
191230 dir = dirname(file);
192231
193
- if (errno != EPERM || is_bpffs(dir)) {
194
- p_err("can't pin the object (%s): %s", name, strerror(errno));
232
+ if (is_bpffs(dir))
233
+ /* nothing to do if already mounted */
234
+ goto out_free;
235
+
236
+ if (block_mount) {
237
+ p_err("no BPF file system found, not mounting it due to --nomount option");
238
+ err = -1;
195239 goto out_free;
196240 }
197241
198
- /* Attempt to mount bpffs, then retry pinning. */
199
- err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
200
- if (!err) {
201
- err = bpf_obj_pin(fd, name);
202
- if (err)
203
- p_err("can't pin the object (%s): %s", name,
204
- strerror(errno));
205
- } else {
242
+ err = mnt_fs(dir, "bpf", err_str, ERR_MAX_LEN);
243
+ if (err) {
206244 err_str[ERR_MAX_LEN - 1] = '\0';
207245 p_err("can't mount BPF file system to pin the object (%s): %s",
208246 name, err_str);
....@@ -210,43 +248,35 @@
210248
211249 out_free:
212250 free(file);
213
-out:
214251 return err;
215252 }
216253
217
-int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
254
+int do_pin_fd(int fd, const char *name)
218255 {
219
- unsigned int id;
220
- char *endptr;
256
+ int err;
257
+
258
+ err = mount_bpffs_for_pin(name);
259
+ if (err)
260
+ return err;
261
+
262
+ err = bpf_obj_pin(fd, name);
263
+ if (err)
264
+ p_err("can't pin the object (%s): %s", name, strerror(errno));
265
+
266
+ return err;
267
+}
268
+
269
+int do_pin_any(int argc, char **argv, int (*get_fd)(int *, char ***))
270
+{
221271 int err;
222272 int fd;
223273
224
- if (argc < 3) {
225
- p_err("too few arguments, id ID and FILE path is required");
226
- return -1;
227
- } else if (argc > 3) {
228
- p_err("too many arguments");
229
- return -1;
230
- }
274
+ if (!REQ_ARGS(3))
275
+ return -EINVAL;
231276
232
- if (!is_prefix(*argv, "id")) {
233
- p_err("expected 'id' got %s", *argv);
234
- return -1;
235
- }
236
- NEXT_ARG();
237
-
238
- id = strtoul(*argv, &endptr, 0);
239
- if (*endptr) {
240
- p_err("can't parse %s as ID", *argv);
241
- return -1;
242
- }
243
- NEXT_ARG();
244
-
245
- fd = get_fd_by_id(id);
246
- if (fd < 0) {
247
- p_err("can't open object by id (%u): %s", id, strerror(errno));
248
- return -1;
249
- }
277
+ fd = get_fd(&argc, &argv);
278
+ if (fd < 0)
279
+ return fd;
250280
251281 err = do_pin_fd(fd, *argv);
252282
....@@ -274,7 +304,7 @@
274304 char buf[512];
275305 ssize_t n;
276306
277
- snprintf(path, sizeof(path), "/proc/%d/fd/%d", getpid(), fd);
307
+ snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
278308
279309 n = readlink(path, buf, sizeof(buf));
280310 if (n < 0) {
....@@ -290,6 +320,8 @@
290320 return BPF_OBJ_MAP;
291321 else if (strstr(buf, "bpf-prog"))
292322 return BPF_OBJ_PROG;
323
+ else if (strstr(buf, "bpf-link"))
324
+ return BPF_OBJ_LINK;
293325
294326 return BPF_OBJ_UNKNOWN;
295327 }
....@@ -302,13 +334,11 @@
302334 ssize_t n;
303335 FILE *fdi;
304336
305
- snprintf(path, sizeof(path), "/proc/%d/fdinfo/%d", getpid(), fd);
337
+ snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);
306338
307339 fdi = fopen(path, "r");
308
- if (!fdi) {
309
- p_err("can't open fdinfo: %s", strerror(errno));
340
+ if (!fdi)
310341 return NULL;
311
- }
312342
313343 while ((n = getline(&line, &line_n, fdi)) > 0) {
314344 char *value;
....@@ -321,7 +351,6 @@
321351
322352 value = strchr(line, '\t');
323353 if (!value || !value[1]) {
324
- p_err("malformed fdinfo!?");
325354 free(line);
326355 return NULL;
327356 }
....@@ -334,7 +363,6 @@
334363 return line;
335364 }
336365
337
- p_err("key '%s' not found in fdinfo", key);
338366 free(line);
339367 fclose(fdi);
340368 return NULL;
....@@ -360,71 +388,82 @@
360388 jsonw_end_array(json_wtr);
361389 }
362390
391
+/* extra params for nftw cb */
392
+static struct pinned_obj_table *build_fn_table;
393
+static enum bpf_obj_type build_fn_type;
394
+
395
+static int do_build_table_cb(const char *fpath, const struct stat *sb,
396
+ int typeflag, struct FTW *ftwbuf)
397
+{
398
+ struct bpf_prog_info pinned_info;
399
+ __u32 len = sizeof(pinned_info);
400
+ struct pinned_obj *obj_node;
401
+ enum bpf_obj_type objtype;
402
+ int fd, err = 0;
403
+
404
+ if (typeflag != FTW_F)
405
+ goto out_ret;
406
+
407
+ fd = open_obj_pinned(fpath, true);
408
+ if (fd < 0)
409
+ goto out_ret;
410
+
411
+ objtype = get_fd_type(fd);
412
+ if (objtype != build_fn_type)
413
+ goto out_close;
414
+
415
+ memset(&pinned_info, 0, sizeof(pinned_info));
416
+ if (bpf_obj_get_info_by_fd(fd, &pinned_info, &len))
417
+ goto out_close;
418
+
419
+ obj_node = calloc(1, sizeof(*obj_node));
420
+ if (!obj_node) {
421
+ err = -1;
422
+ goto out_close;
423
+ }
424
+
425
+ obj_node->id = pinned_info.id;
426
+ obj_node->path = strdup(fpath);
427
+ if (!obj_node->path) {
428
+ err = -1;
429
+ free(obj_node);
430
+ goto out_close;
431
+ }
432
+
433
+ hash_add(build_fn_table->table, &obj_node->hash, obj_node->id);
434
+out_close:
435
+ close(fd);
436
+out_ret:
437
+ return err;
438
+}
439
+
363440 int build_pinned_obj_table(struct pinned_obj_table *tab,
364441 enum bpf_obj_type type)
365442 {
366
- struct bpf_prog_info pinned_info = {};
367
- struct pinned_obj *obj_node = NULL;
368
- __u32 len = sizeof(pinned_info);
369443 struct mntent *mntent = NULL;
370
- enum bpf_obj_type objtype;
371444 FILE *mntfile = NULL;
372
- FTSENT *ftse = NULL;
373
- FTS *fts = NULL;
374
- int fd, err;
445
+ int flags = FTW_PHYS;
446
+ int nopenfd = 16;
447
+ int err = 0;
375448
376449 mntfile = setmntent("/proc/mounts", "r");
377450 if (!mntfile)
378451 return -1;
379452
453
+ build_fn_table = tab;
454
+ build_fn_type = type;
455
+
380456 while ((mntent = getmntent(mntfile))) {
381
- char *path[] = { mntent->mnt_dir, NULL };
457
+ char *path = mntent->mnt_dir;
382458
383459 if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
384460 continue;
385
-
386
- fts = fts_open(path, 0, NULL);
387
- if (!fts)
388
- continue;
389
-
390
- while ((ftse = fts_read(fts))) {
391
- if (!(ftse->fts_info & FTS_F))
392
- continue;
393
- fd = open_obj_pinned(ftse->fts_path, true);
394
- if (fd < 0)
395
- continue;
396
-
397
- objtype = get_fd_type(fd);
398
- if (objtype != type) {
399
- close(fd);
400
- continue;
401
- }
402
- memset(&pinned_info, 0, sizeof(pinned_info));
403
- err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len);
404
- if (err) {
405
- close(fd);
406
- continue;
407
- }
408
-
409
- obj_node = malloc(sizeof(*obj_node));
410
- if (!obj_node) {
411
- close(fd);
412
- fts_close(fts);
413
- fclose(mntfile);
414
- return -1;
415
- }
416
-
417
- memset(obj_node, 0, sizeof(*obj_node));
418
- obj_node->id = pinned_info.id;
419
- obj_node->path = strdup(ftse->fts_path);
420
- hash_add(tab->table, &obj_node->hash, obj_node->id);
421
-
422
- close(fd);
423
- }
424
- fts_close(fts);
461
+ err = nftw(path, do_build_table_cb, nopenfd, flags);
462
+ if (err)
463
+ break;
425464 }
426465 fclose(mntfile);
427
- return 0;
466
+ return err;
428467 }
429468
430469 void delete_pinned_obj_table(struct pinned_obj_table *tab)
....@@ -451,57 +490,13 @@
451490
452491 unsigned int get_possible_cpus(void)
453492 {
454
- static unsigned int result;
455
- char buf[128];
456
- long int n;
457
- char *ptr;
458
- int fd;
493
+ int cpus = libbpf_num_possible_cpus();
459494
460
- if (result)
461
- return result;
462
-
463
- fd = open("/sys/devices/system/cpu/possible", O_RDONLY);
464
- if (fd < 0) {
465
- p_err("can't open sysfs possible cpus");
495
+ if (cpus < 0) {
496
+ p_err("Can't get # of possible cpus: %s", strerror(-cpus));
466497 exit(-1);
467498 }
468
-
469
- n = read(fd, buf, sizeof(buf));
470
- if (n < 2) {
471
- p_err("can't read sysfs possible cpus");
472
- exit(-1);
473
- }
474
- close(fd);
475
-
476
- if (n == sizeof(buf)) {
477
- p_err("read sysfs possible cpus overflow");
478
- exit(-1);
479
- }
480
-
481
- ptr = buf;
482
- n = 0;
483
- while (*ptr && *ptr != '\n') {
484
- unsigned int a, b;
485
-
486
- if (sscanf(ptr, "%u-%u", &a, &b) == 2) {
487
- n += b - a + 1;
488
-
489
- ptr = strchr(ptr, '-') + 1;
490
- } else if (sscanf(ptr, "%u", &a) == 1) {
491
- n++;
492
- } else {
493
- assert(0);
494
- }
495
-
496
- while (isdigit(*ptr))
497
- ptr++;
498
- if (*ptr == ',')
499
- ptr++;
500
- }
501
-
502
- result = n;
503
-
504
- return result;
499
+ return cpus;
505500 }
506501
507502 static char *
....@@ -560,7 +555,9 @@
560555 return read_sysfs_hex_int(full_path);
561556 }
562557
563
-const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino)
558
+const char *
559
+ifindex_to_bfd_params(__u32 ifindex, __u64 ns_dev, __u64 ns_ino,
560
+ const char **opt)
564561 {
565562 char devname[IF_NAMESIZE];
566563 int vendor_id;
....@@ -585,6 +582,7 @@
585582 device_id != 0x6000 &&
586583 device_id != 0x6003)
587584 p_info("Unknown NFP device ID, assuming it is NFP-6xxx arch");
585
+ *opt = "ctx4";
588586 return "NFP-6xxx";
589587 default:
590588 p_err("Can't get bfd arch name for device vendor id 0x%04x",
....@@ -600,7 +598,7 @@
600598 if (!ifindex)
601599 return;
602600
603
- printf(" dev ");
601
+ printf(" offloaded_to ");
604602 if (ifindex_to_name_ns(ifindex, ns_dev, ns_inode, name))
605603 printf("%s", name);
606604 else
....@@ -624,3 +622,339 @@
624622 jsonw_string_field(json_wtr, "ifname", name);
625623 jsonw_end_object(json_wtr);
626624 }
625
+
626
+int parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what)
627
+{
628
+ char *endptr;
629
+
630
+ NEXT_ARGP();
631
+
632
+ if (*val) {
633
+ p_err("%s already specified", what);
634
+ return -1;
635
+ }
636
+
637
+ *val = strtoul(**argv, &endptr, 0);
638
+ if (*endptr) {
639
+ p_err("can't parse %s as %s", **argv, what);
640
+ return -1;
641
+ }
642
+ NEXT_ARGP();
643
+
644
+ return 0;
645
+}
646
+
647
+int __printf(2, 0)
648
+print_all_levels(__maybe_unused enum libbpf_print_level level,
649
+ const char *format, va_list args)
650
+{
651
+ return vfprintf(stderr, format, args);
652
+}
653
+
654
+static int prog_fd_by_nametag(void *nametag, int **fds, bool tag)
655
+{
656
+ unsigned int id = 0;
657
+ int fd, nb_fds = 0;
658
+ void *tmp;
659
+ int err;
660
+
661
+ while (true) {
662
+ struct bpf_prog_info info = {};
663
+ __u32 len = sizeof(info);
664
+
665
+ err = bpf_prog_get_next_id(id, &id);
666
+ if (err) {
667
+ if (errno != ENOENT) {
668
+ p_err("%s", strerror(errno));
669
+ goto err_close_fds;
670
+ }
671
+ return nb_fds;
672
+ }
673
+
674
+ fd = bpf_prog_get_fd_by_id(id);
675
+ if (fd < 0) {
676
+ p_err("can't get prog by id (%u): %s",
677
+ id, strerror(errno));
678
+ goto err_close_fds;
679
+ }
680
+
681
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
682
+ if (err) {
683
+ p_err("can't get prog info (%u): %s",
684
+ id, strerror(errno));
685
+ goto err_close_fd;
686
+ }
687
+
688
+ if ((tag && memcmp(nametag, info.tag, BPF_TAG_SIZE)) ||
689
+ (!tag && strncmp(nametag, info.name, BPF_OBJ_NAME_LEN))) {
690
+ close(fd);
691
+ continue;
692
+ }
693
+
694
+ if (nb_fds > 0) {
695
+ tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
696
+ if (!tmp) {
697
+ p_err("failed to realloc");
698
+ goto err_close_fd;
699
+ }
700
+ *fds = tmp;
701
+ }
702
+ (*fds)[nb_fds++] = fd;
703
+ }
704
+
705
+err_close_fd:
706
+ close(fd);
707
+err_close_fds:
708
+ while (--nb_fds >= 0)
709
+ close((*fds)[nb_fds]);
710
+ return -1;
711
+}
712
+
713
+int prog_parse_fds(int *argc, char ***argv, int **fds)
714
+{
715
+ if (is_prefix(**argv, "id")) {
716
+ unsigned int id;
717
+ char *endptr;
718
+
719
+ NEXT_ARGP();
720
+
721
+ id = strtoul(**argv, &endptr, 0);
722
+ if (*endptr) {
723
+ p_err("can't parse %s as ID", **argv);
724
+ return -1;
725
+ }
726
+ NEXT_ARGP();
727
+
728
+ (*fds)[0] = bpf_prog_get_fd_by_id(id);
729
+ if ((*fds)[0] < 0) {
730
+ p_err("get by id (%u): %s", id, strerror(errno));
731
+ return -1;
732
+ }
733
+ return 1;
734
+ } else if (is_prefix(**argv, "tag")) {
735
+ unsigned char tag[BPF_TAG_SIZE];
736
+
737
+ NEXT_ARGP();
738
+
739
+ if (sscanf(**argv, BPF_TAG_FMT, tag, tag + 1, tag + 2,
740
+ tag + 3, tag + 4, tag + 5, tag + 6, tag + 7)
741
+ != BPF_TAG_SIZE) {
742
+ p_err("can't parse tag");
743
+ return -1;
744
+ }
745
+ NEXT_ARGP();
746
+
747
+ return prog_fd_by_nametag(tag, fds, true);
748
+ } else if (is_prefix(**argv, "name")) {
749
+ char *name;
750
+
751
+ NEXT_ARGP();
752
+
753
+ name = **argv;
754
+ if (strlen(name) > BPF_OBJ_NAME_LEN - 1) {
755
+ p_err("can't parse name");
756
+ return -1;
757
+ }
758
+ NEXT_ARGP();
759
+
760
+ return prog_fd_by_nametag(name, fds, false);
761
+ } else if (is_prefix(**argv, "pinned")) {
762
+ char *path;
763
+
764
+ NEXT_ARGP();
765
+
766
+ path = **argv;
767
+ NEXT_ARGP();
768
+
769
+ (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_PROG);
770
+ if ((*fds)[0] < 0)
771
+ return -1;
772
+ return 1;
773
+ }
774
+
775
+ p_err("expected 'id', 'tag', 'name' or 'pinned', got: '%s'?", **argv);
776
+ return -1;
777
+}
778
+
779
+int prog_parse_fd(int *argc, char ***argv)
780
+{
781
+ int *fds = NULL;
782
+ int nb_fds, fd;
783
+
784
+ fds = malloc(sizeof(int));
785
+ if (!fds) {
786
+ p_err("mem alloc failed");
787
+ return -1;
788
+ }
789
+ nb_fds = prog_parse_fds(argc, argv, &fds);
790
+ if (nb_fds != 1) {
791
+ if (nb_fds > 1) {
792
+ p_err("several programs match this handle");
793
+ while (nb_fds--)
794
+ close(fds[nb_fds]);
795
+ }
796
+ fd = -1;
797
+ goto exit_free;
798
+ }
799
+
800
+ fd = fds[0];
801
+exit_free:
802
+ free(fds);
803
+ return fd;
804
+}
805
+
806
+static int map_fd_by_name(char *name, int **fds)
807
+{
808
+ unsigned int id = 0;
809
+ int fd, nb_fds = 0;
810
+ void *tmp;
811
+ int err;
812
+
813
+ while (true) {
814
+ struct bpf_map_info info = {};
815
+ __u32 len = sizeof(info);
816
+
817
+ err = bpf_map_get_next_id(id, &id);
818
+ if (err) {
819
+ if (errno != ENOENT) {
820
+ p_err("%s", strerror(errno));
821
+ goto err_close_fds;
822
+ }
823
+ return nb_fds;
824
+ }
825
+
826
+ fd = bpf_map_get_fd_by_id(id);
827
+ if (fd < 0) {
828
+ p_err("can't get map by id (%u): %s",
829
+ id, strerror(errno));
830
+ goto err_close_fds;
831
+ }
832
+
833
+ err = bpf_obj_get_info_by_fd(fd, &info, &len);
834
+ if (err) {
835
+ p_err("can't get map info (%u): %s",
836
+ id, strerror(errno));
837
+ goto err_close_fd;
838
+ }
839
+
840
+ if (strncmp(name, info.name, BPF_OBJ_NAME_LEN)) {
841
+ close(fd);
842
+ continue;
843
+ }
844
+
845
+ if (nb_fds > 0) {
846
+ tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
847
+ if (!tmp) {
848
+ p_err("failed to realloc");
849
+ goto err_close_fd;
850
+ }
851
+ *fds = tmp;
852
+ }
853
+ (*fds)[nb_fds++] = fd;
854
+ }
855
+
856
+err_close_fd:
857
+ close(fd);
858
+err_close_fds:
859
+ while (--nb_fds >= 0)
860
+ close((*fds)[nb_fds]);
861
+ return -1;
862
+}
863
+
864
+int map_parse_fds(int *argc, char ***argv, int **fds)
865
+{
866
+ if (is_prefix(**argv, "id")) {
867
+ unsigned int id;
868
+ char *endptr;
869
+
870
+ NEXT_ARGP();
871
+
872
+ id = strtoul(**argv, &endptr, 0);
873
+ if (*endptr) {
874
+ p_err("can't parse %s as ID", **argv);
875
+ return -1;
876
+ }
877
+ NEXT_ARGP();
878
+
879
+ (*fds)[0] = bpf_map_get_fd_by_id(id);
880
+ if ((*fds)[0] < 0) {
881
+ p_err("get map by id (%u): %s", id, strerror(errno));
882
+ return -1;
883
+ }
884
+ return 1;
885
+ } else if (is_prefix(**argv, "name")) {
886
+ char *name;
887
+
888
+ NEXT_ARGP();
889
+
890
+ name = **argv;
891
+ if (strlen(name) > BPF_OBJ_NAME_LEN - 1) {
892
+ p_err("can't parse name");
893
+ return -1;
894
+ }
895
+ NEXT_ARGP();
896
+
897
+ return map_fd_by_name(name, fds);
898
+ } else if (is_prefix(**argv, "pinned")) {
899
+ char *path;
900
+
901
+ NEXT_ARGP();
902
+
903
+ path = **argv;
904
+ NEXT_ARGP();
905
+
906
+ (*fds)[0] = open_obj_pinned_any(path, BPF_OBJ_MAP);
907
+ if ((*fds)[0] < 0)
908
+ return -1;
909
+ return 1;
910
+ }
911
+
912
+ p_err("expected 'id', 'name' or 'pinned', got: '%s'?", **argv);
913
+ return -1;
914
+}
915
+
916
+int map_parse_fd(int *argc, char ***argv)
917
+{
918
+ int *fds = NULL;
919
+ int nb_fds, fd;
920
+
921
+ fds = malloc(sizeof(int));
922
+ if (!fds) {
923
+ p_err("mem alloc failed");
924
+ return -1;
925
+ }
926
+ nb_fds = map_parse_fds(argc, argv, &fds);
927
+ if (nb_fds != 1) {
928
+ if (nb_fds > 1) {
929
+ p_err("several maps match this handle");
930
+ while (nb_fds--)
931
+ close(fds[nb_fds]);
932
+ }
933
+ fd = -1;
934
+ goto exit_free;
935
+ }
936
+
937
+ fd = fds[0];
938
+exit_free:
939
+ free(fds);
940
+ return fd;
941
+}
942
+
943
+int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
944
+{
945
+ int err;
946
+ int fd;
947
+
948
+ fd = map_parse_fd(argc, argv);
949
+ if (fd < 0)
950
+ return -1;
951
+
952
+ err = bpf_obj_get_info_by_fd(fd, info, info_len);
953
+ if (err) {
954
+ p_err("can't get map info: %s", strerror(errno));
955
+ close(fd);
956
+ return err;
957
+ }
958
+
959
+ return fd;
960
+}