xref: /linux/tools/bpf/bpftool/token.c (revision 2d812311c2b28cc9096e29862a957aeb32bfdb76)
1*2d812311STao Chen // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*2d812311STao Chen /* Copyright (C) 2025 Didi Technology Co., Tao Chen */
3*2d812311STao Chen 
4*2d812311STao Chen #ifndef _GNU_SOURCE
5*2d812311STao Chen #define _GNU_SOURCE
6*2d812311STao Chen #endif
7*2d812311STao Chen #include <errno.h>
8*2d812311STao Chen #include <fcntl.h>
9*2d812311STao Chen #include <stdbool.h>
10*2d812311STao Chen #include <stdio.h>
11*2d812311STao Chen #include <stdlib.h>
12*2d812311STao Chen #include <string.h>
13*2d812311STao Chen #include <unistd.h>
14*2d812311STao Chen #include <mntent.h>
15*2d812311STao Chen #include <sys/types.h>
16*2d812311STao Chen #include <sys/stat.h>
17*2d812311STao Chen 
18*2d812311STao Chen #include "json_writer.h"
19*2d812311STao Chen #include "main.h"
20*2d812311STao Chen 
21*2d812311STao Chen #define MOUNTS_FILE "/proc/mounts"
22*2d812311STao Chen 
23*2d812311STao Chen static bool has_delegate_options(const char *mnt_ops)
24*2d812311STao Chen {
25*2d812311STao Chen 	return strstr(mnt_ops, "delegate_cmds") ||
26*2d812311STao Chen 	       strstr(mnt_ops, "delegate_maps") ||
27*2d812311STao Chen 	       strstr(mnt_ops, "delegate_progs") ||
28*2d812311STao Chen 	       strstr(mnt_ops, "delegate_attachs");
29*2d812311STao Chen }
30*2d812311STao Chen 
31*2d812311STao Chen static char *get_delegate_value(const char *opts, const char *key)
32*2d812311STao Chen {
33*2d812311STao Chen 	char *token, *rest, *ret = NULL;
34*2d812311STao Chen 	char *opts_copy = strdup(opts);
35*2d812311STao Chen 
36*2d812311STao Chen 	if (!opts_copy)
37*2d812311STao Chen 		return NULL;
38*2d812311STao Chen 
39*2d812311STao Chen 	for (token = strtok_r(opts_copy, ",", &rest); token;
40*2d812311STao Chen 			token = strtok_r(NULL, ",", &rest)) {
41*2d812311STao Chen 		if (strncmp(token, key, strlen(key)) == 0 &&
42*2d812311STao Chen 		    token[strlen(key)] == '=') {
43*2d812311STao Chen 			ret = token + strlen(key) + 1;
44*2d812311STao Chen 			break;
45*2d812311STao Chen 		}
46*2d812311STao Chen 	}
47*2d812311STao Chen 	free(opts_copy);
48*2d812311STao Chen 
49*2d812311STao Chen 	return ret;
50*2d812311STao Chen }
51*2d812311STao Chen 
52*2d812311STao Chen static void print_items_per_line(const char *input, int items_per_line)
53*2d812311STao Chen {
54*2d812311STao Chen 	char *str, *rest, *strs;
55*2d812311STao Chen 	int cnt = 0;
56*2d812311STao Chen 
57*2d812311STao Chen 	if (!input)
58*2d812311STao Chen 		return;
59*2d812311STao Chen 
60*2d812311STao Chen 	strs = strdup(input);
61*2d812311STao Chen 	if (!strs)
62*2d812311STao Chen 		return;
63*2d812311STao Chen 
64*2d812311STao Chen 	for (str = strtok_r(strs, ":", &rest); str;
65*2d812311STao Chen 			str = strtok_r(NULL, ":", &rest)) {
66*2d812311STao Chen 		if (cnt % items_per_line == 0)
67*2d812311STao Chen 			printf("\n\t  ");
68*2d812311STao Chen 
69*2d812311STao Chen 		printf("%-20s", str);
70*2d812311STao Chen 		cnt++;
71*2d812311STao Chen 	}
72*2d812311STao Chen 
73*2d812311STao Chen 	free(strs);
74*2d812311STao Chen }
75*2d812311STao Chen 
76*2d812311STao Chen #define ITEMS_PER_LINE 4
77*2d812311STao Chen static void show_token_info_plain(struct mntent *mntent)
78*2d812311STao Chen {
79*2d812311STao Chen 	char *value;
80*2d812311STao Chen 
81*2d812311STao Chen 	printf("token_info  %s", mntent->mnt_dir);
82*2d812311STao Chen 
83*2d812311STao Chen 	printf("\n\tallowed_cmds:");
84*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_cmds");
85*2d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
86*2d812311STao Chen 
87*2d812311STao Chen 	printf("\n\tallowed_maps:");
88*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_maps");
89*2d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
90*2d812311STao Chen 
91*2d812311STao Chen 	printf("\n\tallowed_progs:");
92*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_progs");
93*2d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
94*2d812311STao Chen 
95*2d812311STao Chen 	printf("\n\tallowed_attachs:");
96*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_attachs");
97*2d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
98*2d812311STao Chen 	printf("\n");
99*2d812311STao Chen }
100*2d812311STao Chen 
101*2d812311STao Chen static void split_json_array_str(const char *input)
102*2d812311STao Chen {
103*2d812311STao Chen 	char *str, *rest, *strs;
104*2d812311STao Chen 
105*2d812311STao Chen 	if (!input) {
106*2d812311STao Chen 		jsonw_start_array(json_wtr);
107*2d812311STao Chen 		jsonw_end_array(json_wtr);
108*2d812311STao Chen 		return;
109*2d812311STao Chen 	}
110*2d812311STao Chen 
111*2d812311STao Chen 	strs = strdup(input);
112*2d812311STao Chen 	if (!strs)
113*2d812311STao Chen 		return;
114*2d812311STao Chen 
115*2d812311STao Chen 	jsonw_start_array(json_wtr);
116*2d812311STao Chen 	for (str = strtok_r(strs, ":", &rest); str;
117*2d812311STao Chen 			str = strtok_r(NULL, ":", &rest)) {
118*2d812311STao Chen 		jsonw_string(json_wtr, str);
119*2d812311STao Chen 	}
120*2d812311STao Chen 	jsonw_end_array(json_wtr);
121*2d812311STao Chen 
122*2d812311STao Chen 	free(strs);
123*2d812311STao Chen }
124*2d812311STao Chen 
125*2d812311STao Chen static void show_token_info_json(struct mntent *mntent)
126*2d812311STao Chen {
127*2d812311STao Chen 	char *value;
128*2d812311STao Chen 
129*2d812311STao Chen 	jsonw_start_object(json_wtr);
130*2d812311STao Chen 
131*2d812311STao Chen 	jsonw_string_field(json_wtr, "token_info", mntent->mnt_dir);
132*2d812311STao Chen 
133*2d812311STao Chen 	jsonw_name(json_wtr, "allowed_cmds");
134*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_cmds");
135*2d812311STao Chen 	split_json_array_str(value);
136*2d812311STao Chen 
137*2d812311STao Chen 	jsonw_name(json_wtr, "allowed_maps");
138*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_maps");
139*2d812311STao Chen 	split_json_array_str(value);
140*2d812311STao Chen 
141*2d812311STao Chen 	jsonw_name(json_wtr, "allowed_progs");
142*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_progs");
143*2d812311STao Chen 	split_json_array_str(value);
144*2d812311STao Chen 
145*2d812311STao Chen 	jsonw_name(json_wtr, "allowed_attachs");
146*2d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_attachs");
147*2d812311STao Chen 	split_json_array_str(value);
148*2d812311STao Chen 
149*2d812311STao Chen 	jsonw_end_object(json_wtr);
150*2d812311STao Chen }
151*2d812311STao Chen 
152*2d812311STao Chen static int __show_token_info(struct mntent *mntent)
153*2d812311STao Chen {
154*2d812311STao Chen 	if (json_output)
155*2d812311STao Chen 		show_token_info_json(mntent);
156*2d812311STao Chen 	else
157*2d812311STao Chen 		show_token_info_plain(mntent);
158*2d812311STao Chen 
159*2d812311STao Chen 	return 0;
160*2d812311STao Chen }
161*2d812311STao Chen 
162*2d812311STao Chen static int show_token_info(void)
163*2d812311STao Chen {
164*2d812311STao Chen 	FILE *fp;
165*2d812311STao Chen 	struct mntent *ent;
166*2d812311STao Chen 
167*2d812311STao Chen 	fp = setmntent(MOUNTS_FILE, "r");
168*2d812311STao Chen 	if (!fp) {
169*2d812311STao Chen 		p_err("Failed to open: %s", MOUNTS_FILE);
170*2d812311STao Chen 		return -1;
171*2d812311STao Chen 	}
172*2d812311STao Chen 
173*2d812311STao Chen 	if (json_output)
174*2d812311STao Chen 		jsonw_start_array(json_wtr);
175*2d812311STao Chen 
176*2d812311STao Chen 	while ((ent = getmntent(fp)) != NULL) {
177*2d812311STao Chen 		if (strncmp(ent->mnt_type, "bpf", 3) == 0) {
178*2d812311STao Chen 			if (has_delegate_options(ent->mnt_opts))
179*2d812311STao Chen 				__show_token_info(ent);
180*2d812311STao Chen 		}
181*2d812311STao Chen 	}
182*2d812311STao Chen 
183*2d812311STao Chen 	if (json_output)
184*2d812311STao Chen 		jsonw_end_array(json_wtr);
185*2d812311STao Chen 
186*2d812311STao Chen 	endmntent(fp);
187*2d812311STao Chen 
188*2d812311STao Chen 	return 0;
189*2d812311STao Chen }
190*2d812311STao Chen 
191*2d812311STao Chen static int do_show(int argc, char **argv)
192*2d812311STao Chen {
193*2d812311STao Chen 	if (argc)
194*2d812311STao Chen 		return BAD_ARG();
195*2d812311STao Chen 
196*2d812311STao Chen 	return show_token_info();
197*2d812311STao Chen }
198*2d812311STao Chen 
199*2d812311STao Chen static int do_help(int argc, char **argv)
200*2d812311STao Chen {
201*2d812311STao Chen 	if (json_output) {
202*2d812311STao Chen 		jsonw_null(json_wtr);
203*2d812311STao Chen 		return 0;
204*2d812311STao Chen 	}
205*2d812311STao Chen 
206*2d812311STao Chen 	fprintf(stderr,
207*2d812311STao Chen 		"Usage: %1$s %2$s { show | list }\n"
208*2d812311STao Chen 		"       %1$s %2$s help\n"
209*2d812311STao Chen 		"\n"
210*2d812311STao Chen 		"",
211*2d812311STao Chen 		bin_name, argv[-2]);
212*2d812311STao Chen 	return 0;
213*2d812311STao Chen }
214*2d812311STao Chen 
215*2d812311STao Chen static const struct cmd cmds[] = {
216*2d812311STao Chen 	{ "show",	do_show },
217*2d812311STao Chen 	{ "list",	do_show },
218*2d812311STao Chen 	{ "help",	do_help },
219*2d812311STao Chen 	{ 0 }
220*2d812311STao Chen };
221*2d812311STao Chen 
222*2d812311STao Chen int do_token(int argc, char **argv)
223*2d812311STao Chen {
224*2d812311STao Chen 	return cmd_select(cmds, argc, argv, do_help);
225*2d812311STao Chen }
226