]>
git.proxmox.com Git - mirror_iproute2.git/blob - tc/e_bpf.c
2 * e_bpf.c BPF exec proxy
4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Daniel Borkmann <daniel@iogearbox.net>
23 #define BPF_DEFAULT_CMD "/bin/sh"
25 static char *argv_default
[] = { BPF_DEFAULT_CMD
, NULL
};
27 static void explain(void)
29 fprintf(stderr
, "Usage: ... bpf [ import UDS_FILE ] [ run CMD ]\n");
30 fprintf(stderr
, " ... bpf [ debug ]\n");
31 fprintf(stderr
, " ... bpf [ graft MAP_FILE ] [ key KEY ]\n");
32 fprintf(stderr
, " `... [ object-file OBJ_FILE ] [ type TYPE ] [ section NAME ] [ verbose ]\n");
33 fprintf(stderr
, " `... [ object-pinned PROG_FILE ]\n");
34 fprintf(stderr
, "\n");
35 fprintf(stderr
, "Where UDS_FILE provides the name of a unix domain socket file\n");
36 fprintf(stderr
, "to import eBPF maps and the optional CMD denotes the command\n");
37 fprintf(stderr
, "to be executed (default: \'%s\').\n", BPF_DEFAULT_CMD
);
38 fprintf(stderr
, "Where MAP_FILE points to a pinned map, OBJ_FILE to an object file\n");
39 fprintf(stderr
, "and PROG_FILE to a pinned program. TYPE can be {cls, act}, where\n");
40 fprintf(stderr
, "\'cls\' is default. KEY is optional and can be inferred from the\n");
41 fprintf(stderr
, "section name, otherwise it needs to be provided.\n");
44 static int bpf_num_env_entries(void)
49 for (num
= 0, envp
= environ
; *envp
!= NULL
; envp
++)
54 static int parse_bpf(struct exec_util
*eu
, int argc
, char **argv
)
56 char **argv_run
= argv_default
, **envp_run
, *tmp
;
57 int ret
, i
, env_old
, env_num
, env_map
;
58 const char *bpf_uds_name
= NULL
;
59 int fds
[BPF_SCM_MAX_FDS
] = {};
60 struct bpf_map_aux aux
= {};
66 if (matches(*argv
, "run") == 0) {
70 } else if (matches(*argv
, "import") == 0) {
73 } else if (matches(*argv
, "debug") == 0 ||
74 matches(*argv
, "dbg") == 0) {
77 "No trace pipe, tracefs not mounted?\n");
79 } else if (matches(*argv
, "graft") == 0) {
80 const char *bpf_map_path
;
87 if (matches(*argv
, "key") == 0) {
89 if (get_unsigned(&key
, *argv
, 0)) {
90 fprintf(stderr
, "Illegal \"key\"\n");
96 return bpf_graft_map(bpf_map_path
, has_key
?
97 &key
: NULL
, argc
, argv
);
107 fprintf(stderr
, "bpf: No import parameter provided!\n");
112 if (argv_run
!= argv_default
&& argc
== 0) {
113 fprintf(stderr
, "bpf: No run command provided!\n");
118 ret
= bpf_recv_map_fds(bpf_uds_name
, fds
, &aux
, ARRAY_SIZE(fds
));
120 fprintf(stderr
, "bpf: Could not receive fds!\n");
124 if (aux
.num_ent
== 0) {
129 env_old
= bpf_num_env_entries();
130 env_num
= env_old
+ aux
.num_ent
+ 2;
131 env_map
= env_old
+ 1;
133 envp_run
= malloc(sizeof(*envp_run
) * env_num
);
135 fprintf(stderr
, "bpf: No memory left to allocate env!\n");
139 for (i
= 0; i
< env_old
; i
++)
140 envp_run
[i
] = environ
[i
];
142 ret
= asprintf(&tmp
, "BPF_NUM_MAPS=%u", aux
.num_ent
);
146 envp_run
[env_old
] = tmp
;
148 for (i
= env_map
; i
< env_num
- 1; i
++) {
149 ret
= asprintf(&tmp
, "BPF_MAP%u=%u",
150 aux
.ent
[i
- env_map
].id
,
158 envp_run
[env_num
- 1] = NULL
;
160 return execvpe(argv_run
[0], argv_run
, envp_run
);
163 for (--i
; i
>= env_old
; i
--)
168 for (i
= 0; i
< aux
.num_ent
; i
++)
173 struct exec_util bpf_exec_util
= {
175 .parse_eopt
= parse_bpf
,