xref: /linux/tools/bpf/bpftool/token.c (revision 4f38da1f027ea2c9f01bb71daa7a299c191b6940)
12d812311STao Chen // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
22d812311STao Chen /* Copyright (C) 2025 Didi Technology Co., Tao Chen */
32d812311STao Chen 
42d812311STao Chen #ifndef _GNU_SOURCE
52d812311STao Chen #define _GNU_SOURCE
62d812311STao Chen #endif
72d812311STao Chen #include <errno.h>
82d812311STao Chen #include <fcntl.h>
92d812311STao Chen #include <stdbool.h>
102d812311STao Chen #include <stdio.h>
112d812311STao Chen #include <stdlib.h>
122d812311STao Chen #include <string.h>
132d812311STao Chen #include <unistd.h>
142d812311STao Chen #include <mntent.h>
152d812311STao Chen #include <sys/types.h>
162d812311STao Chen #include <sys/stat.h>
172d812311STao Chen 
182d812311STao Chen #include "json_writer.h"
192d812311STao Chen #include "main.h"
202d812311STao Chen 
212d812311STao Chen #define MOUNTS_FILE "/proc/mounts"
222d812311STao Chen 
23*57cb2695STao Chen static struct {
24*57cb2695STao Chen 	const char *header;
25*57cb2695STao Chen 	const char *key;
26*57cb2695STao Chen } sets[] = {
27*57cb2695STao Chen 	{"allowed_cmds", "delegate_cmds"},
28*57cb2695STao Chen 	{"allowed_maps", "delegate_maps"},
29*57cb2695STao Chen 	{"allowed_progs", "delegate_progs"},
30*57cb2695STao Chen 	{"allowed_attachs", "delegate_attachs"},
31*57cb2695STao Chen };
32*57cb2695STao Chen 
332d812311STao Chen static bool has_delegate_options(const char *mnt_ops)
342d812311STao Chen {
352d812311STao Chen 	return strstr(mnt_ops, "delegate_cmds") ||
362d812311STao Chen 	       strstr(mnt_ops, "delegate_maps") ||
372d812311STao Chen 	       strstr(mnt_ops, "delegate_progs") ||
382d812311STao Chen 	       strstr(mnt_ops, "delegate_attachs");
392d812311STao Chen }
402d812311STao Chen 
41*57cb2695STao Chen static char *get_delegate_value(char *opts, const char *key)
422d812311STao Chen {
432d812311STao Chen 	char *token, *rest, *ret = NULL;
442d812311STao Chen 
45*57cb2695STao Chen 	if (!opts)
462d812311STao Chen 		return NULL;
472d812311STao Chen 
48*57cb2695STao Chen 	for (token = strtok_r(opts, ",", &rest); token;
492d812311STao Chen 			token = strtok_r(NULL, ",", &rest)) {
502d812311STao Chen 		if (strncmp(token, key, strlen(key)) == 0 &&
512d812311STao Chen 		    token[strlen(key)] == '=') {
522d812311STao Chen 			ret = token + strlen(key) + 1;
532d812311STao Chen 			break;
542d812311STao Chen 		}
552d812311STao Chen 	}
562d812311STao Chen 
572d812311STao Chen 	return ret;
582d812311STao Chen }
592d812311STao Chen 
60*57cb2695STao Chen static void print_items_per_line(char *input, int items_per_line)
612d812311STao Chen {
62*57cb2695STao Chen 	char *str, *rest;
632d812311STao Chen 	int cnt = 0;
642d812311STao Chen 
652d812311STao Chen 	if (!input)
662d812311STao Chen 		return;
672d812311STao Chen 
68*57cb2695STao Chen 	for (str = strtok_r(input, ":", &rest); str;
692d812311STao Chen 			str = strtok_r(NULL, ":", &rest)) {
702d812311STao Chen 		if (cnt % items_per_line == 0)
712d812311STao Chen 			printf("\n\t  ");
722d812311STao Chen 
732d812311STao Chen 		printf("%-20s", str);
742d812311STao Chen 		cnt++;
752d812311STao Chen 	}
762d812311STao Chen }
772d812311STao Chen 
782d812311STao Chen #define ITEMS_PER_LINE 4
792d812311STao Chen static void show_token_info_plain(struct mntent *mntent)
802d812311STao Chen {
81*57cb2695STao Chen 	size_t i;
822d812311STao Chen 
832d812311STao Chen 	printf("token_info  %s", mntent->mnt_dir);
842d812311STao Chen 
85*57cb2695STao Chen 	for (i = 0; i < ARRAY_SIZE(sets); i++) {
86*57cb2695STao Chen 		char *opts, *value;
872d812311STao Chen 
88*57cb2695STao Chen 		printf("\n\t%s:", sets[i].header);
89*57cb2695STao Chen 		opts = strdup(mntent->mnt_opts);
90*57cb2695STao Chen 		value = get_delegate_value(opts, sets[i].key);
912d812311STao Chen 		print_items_per_line(value, ITEMS_PER_LINE);
92*57cb2695STao Chen 		free(opts);
93*57cb2695STao Chen 	}
942d812311STao Chen 
952d812311STao Chen 	printf("\n");
962d812311STao Chen }
972d812311STao Chen 
98*57cb2695STao Chen static void split_json_array_str(char *input)
992d812311STao Chen {
100*57cb2695STao Chen 	char *str, *rest;
1012d812311STao Chen 
1022d812311STao Chen 	if (!input) {
1032d812311STao Chen 		jsonw_start_array(json_wtr);
1042d812311STao Chen 		jsonw_end_array(json_wtr);
1052d812311STao Chen 		return;
1062d812311STao Chen 	}
1072d812311STao Chen 
1082d812311STao Chen 	jsonw_start_array(json_wtr);
109*57cb2695STao Chen 	for (str = strtok_r(input, ":", &rest); str;
1102d812311STao Chen 			str = strtok_r(NULL, ":", &rest)) {
1112d812311STao Chen 		jsonw_string(json_wtr, str);
1122d812311STao Chen 	}
1132d812311STao Chen 	jsonw_end_array(json_wtr);
1142d812311STao Chen }
1152d812311STao Chen 
1162d812311STao Chen static void show_token_info_json(struct mntent *mntent)
1172d812311STao Chen {
118*57cb2695STao Chen 	size_t i;
1192d812311STao Chen 
1202d812311STao Chen 	jsonw_start_object(json_wtr);
1212d812311STao Chen 	jsonw_string_field(json_wtr, "token_info", mntent->mnt_dir);
1222d812311STao Chen 
123*57cb2695STao Chen 	for (i = 0; i < ARRAY_SIZE(sets); i++) {
124*57cb2695STao Chen 		char *opts, *value;
1252d812311STao Chen 
126*57cb2695STao Chen 		jsonw_name(json_wtr, sets[i].header);
127*57cb2695STao Chen 		opts = strdup(mntent->mnt_opts);
128*57cb2695STao Chen 		value = get_delegate_value(opts, sets[i].key);
1292d812311STao Chen 		split_json_array_str(value);
130*57cb2695STao Chen 		free(opts);
131*57cb2695STao Chen 	}
1322d812311STao Chen 
1332d812311STao Chen 	jsonw_end_object(json_wtr);
1342d812311STao Chen }
1352d812311STao Chen 
1362d812311STao Chen static int __show_token_info(struct mntent *mntent)
1372d812311STao Chen {
1382d812311STao Chen 	if (json_output)
1392d812311STao Chen 		show_token_info_json(mntent);
1402d812311STao Chen 	else
1412d812311STao Chen 		show_token_info_plain(mntent);
1422d812311STao Chen 
1432d812311STao Chen 	return 0;
1442d812311STao Chen }
1452d812311STao Chen 
1462d812311STao Chen static int show_token_info(void)
1472d812311STao Chen {
1482d812311STao Chen 	FILE *fp;
1492d812311STao Chen 	struct mntent *ent;
1502d812311STao Chen 
1512d812311STao Chen 	fp = setmntent(MOUNTS_FILE, "r");
1522d812311STao Chen 	if (!fp) {
1532d812311STao Chen 		p_err("Failed to open: %s", MOUNTS_FILE);
1542d812311STao Chen 		return -1;
1552d812311STao Chen 	}
1562d812311STao Chen 
1572d812311STao Chen 	if (json_output)
1582d812311STao Chen 		jsonw_start_array(json_wtr);
1592d812311STao Chen 
1602d812311STao Chen 	while ((ent = getmntent(fp)) != NULL) {
1612d812311STao Chen 		if (strncmp(ent->mnt_type, "bpf", 3) == 0) {
1622d812311STao Chen 			if (has_delegate_options(ent->mnt_opts))
1632d812311STao Chen 				__show_token_info(ent);
1642d812311STao Chen 		}
1652d812311STao Chen 	}
1662d812311STao Chen 
1672d812311STao Chen 	if (json_output)
1682d812311STao Chen 		jsonw_end_array(json_wtr);
1692d812311STao Chen 
1702d812311STao Chen 	endmntent(fp);
1712d812311STao Chen 
1722d812311STao Chen 	return 0;
1732d812311STao Chen }
1742d812311STao Chen 
1752d812311STao Chen static int do_show(int argc, char **argv)
1762d812311STao Chen {
1772d812311STao Chen 	if (argc)
1782d812311STao Chen 		return BAD_ARG();
1792d812311STao Chen 
1802d812311STao Chen 	return show_token_info();
1812d812311STao Chen }
1822d812311STao Chen 
1832d812311STao Chen static int do_help(int argc, char **argv)
1842d812311STao Chen {
1852d812311STao Chen 	if (json_output) {
1862d812311STao Chen 		jsonw_null(json_wtr);
1872d812311STao Chen 		return 0;
1882d812311STao Chen 	}
1892d812311STao Chen 
1902d812311STao Chen 	fprintf(stderr,
1912d812311STao Chen 		"Usage: %1$s %2$s { show | list }\n"
1922d812311STao Chen 		"       %1$s %2$s help\n"
193bce5749bSTao Chen 		"       " HELP_SPEC_OPTIONS " }\n"
1942d812311STao Chen 		"\n"
1952d812311STao Chen 		"",
1962d812311STao Chen 		bin_name, argv[-2]);
1972d812311STao Chen 	return 0;
1982d812311STao Chen }
1992d812311STao Chen 
2002d812311STao Chen static const struct cmd cmds[] = {
2012d812311STao Chen 	{ "show",	do_show },
2022d812311STao Chen 	{ "list",	do_show },
2032d812311STao Chen 	{ "help",	do_help },
2042d812311STao Chen 	{ 0 }
2052d812311STao Chen };
2062d812311STao Chen 
2072d812311STao Chen int do_token(int argc, char **argv)
2082d812311STao Chen {
2092d812311STao Chen 	return cmd_select(cmds, argc, argv, do_help);
2102d812311STao Chen }
211