xref: /linux/tools/bpf/bpftool/token.c (revision bce5749b02019f9b7e60fdff584098e57337c8b6)
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 
232d812311STao Chen static bool has_delegate_options(const char *mnt_ops)
242d812311STao Chen {
252d812311STao Chen 	return strstr(mnt_ops, "delegate_cmds") ||
262d812311STao Chen 	       strstr(mnt_ops, "delegate_maps") ||
272d812311STao Chen 	       strstr(mnt_ops, "delegate_progs") ||
282d812311STao Chen 	       strstr(mnt_ops, "delegate_attachs");
292d812311STao Chen }
302d812311STao Chen 
312d812311STao Chen static char *get_delegate_value(const char *opts, const char *key)
322d812311STao Chen {
332d812311STao Chen 	char *token, *rest, *ret = NULL;
342d812311STao Chen 	char *opts_copy = strdup(opts);
352d812311STao Chen 
362d812311STao Chen 	if (!opts_copy)
372d812311STao Chen 		return NULL;
382d812311STao Chen 
392d812311STao Chen 	for (token = strtok_r(opts_copy, ",", &rest); token;
402d812311STao Chen 			token = strtok_r(NULL, ",", &rest)) {
412d812311STao Chen 		if (strncmp(token, key, strlen(key)) == 0 &&
422d812311STao Chen 		    token[strlen(key)] == '=') {
432d812311STao Chen 			ret = token + strlen(key) + 1;
442d812311STao Chen 			break;
452d812311STao Chen 		}
462d812311STao Chen 	}
472d812311STao Chen 	free(opts_copy);
482d812311STao Chen 
492d812311STao Chen 	return ret;
502d812311STao Chen }
512d812311STao Chen 
522d812311STao Chen static void print_items_per_line(const char *input, int items_per_line)
532d812311STao Chen {
542d812311STao Chen 	char *str, *rest, *strs;
552d812311STao Chen 	int cnt = 0;
562d812311STao Chen 
572d812311STao Chen 	if (!input)
582d812311STao Chen 		return;
592d812311STao Chen 
602d812311STao Chen 	strs = strdup(input);
612d812311STao Chen 	if (!strs)
622d812311STao Chen 		return;
632d812311STao Chen 
642d812311STao Chen 	for (str = strtok_r(strs, ":", &rest); str;
652d812311STao Chen 			str = strtok_r(NULL, ":", &rest)) {
662d812311STao Chen 		if (cnt % items_per_line == 0)
672d812311STao Chen 			printf("\n\t  ");
682d812311STao Chen 
692d812311STao Chen 		printf("%-20s", str);
702d812311STao Chen 		cnt++;
712d812311STao Chen 	}
722d812311STao Chen 
732d812311STao Chen 	free(strs);
742d812311STao Chen }
752d812311STao Chen 
762d812311STao Chen #define ITEMS_PER_LINE 4
772d812311STao Chen static void show_token_info_plain(struct mntent *mntent)
782d812311STao Chen {
792d812311STao Chen 	char *value;
802d812311STao Chen 
812d812311STao Chen 	printf("token_info  %s", mntent->mnt_dir);
822d812311STao Chen 
832d812311STao Chen 	printf("\n\tallowed_cmds:");
842d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_cmds");
852d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
862d812311STao Chen 
872d812311STao Chen 	printf("\n\tallowed_maps:");
882d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_maps");
892d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
902d812311STao Chen 
912d812311STao Chen 	printf("\n\tallowed_progs:");
922d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_progs");
932d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
942d812311STao Chen 
952d812311STao Chen 	printf("\n\tallowed_attachs:");
962d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_attachs");
972d812311STao Chen 	print_items_per_line(value, ITEMS_PER_LINE);
982d812311STao Chen 	printf("\n");
992d812311STao Chen }
1002d812311STao Chen 
1012d812311STao Chen static void split_json_array_str(const char *input)
1022d812311STao Chen {
1032d812311STao Chen 	char *str, *rest, *strs;
1042d812311STao Chen 
1052d812311STao Chen 	if (!input) {
1062d812311STao Chen 		jsonw_start_array(json_wtr);
1072d812311STao Chen 		jsonw_end_array(json_wtr);
1082d812311STao Chen 		return;
1092d812311STao Chen 	}
1102d812311STao Chen 
1112d812311STao Chen 	strs = strdup(input);
1122d812311STao Chen 	if (!strs)
1132d812311STao Chen 		return;
1142d812311STao Chen 
1152d812311STao Chen 	jsonw_start_array(json_wtr);
1162d812311STao Chen 	for (str = strtok_r(strs, ":", &rest); str;
1172d812311STao Chen 			str = strtok_r(NULL, ":", &rest)) {
1182d812311STao Chen 		jsonw_string(json_wtr, str);
1192d812311STao Chen 	}
1202d812311STao Chen 	jsonw_end_array(json_wtr);
1212d812311STao Chen 
1222d812311STao Chen 	free(strs);
1232d812311STao Chen }
1242d812311STao Chen 
1252d812311STao Chen static void show_token_info_json(struct mntent *mntent)
1262d812311STao Chen {
1272d812311STao Chen 	char *value;
1282d812311STao Chen 
1292d812311STao Chen 	jsonw_start_object(json_wtr);
1302d812311STao Chen 
1312d812311STao Chen 	jsonw_string_field(json_wtr, "token_info", mntent->mnt_dir);
1322d812311STao Chen 
1332d812311STao Chen 	jsonw_name(json_wtr, "allowed_cmds");
1342d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_cmds");
1352d812311STao Chen 	split_json_array_str(value);
1362d812311STao Chen 
1372d812311STao Chen 	jsonw_name(json_wtr, "allowed_maps");
1382d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_maps");
1392d812311STao Chen 	split_json_array_str(value);
1402d812311STao Chen 
1412d812311STao Chen 	jsonw_name(json_wtr, "allowed_progs");
1422d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_progs");
1432d812311STao Chen 	split_json_array_str(value);
1442d812311STao Chen 
1452d812311STao Chen 	jsonw_name(json_wtr, "allowed_attachs");
1462d812311STao Chen 	value = get_delegate_value(mntent->mnt_opts, "delegate_attachs");
1472d812311STao Chen 	split_json_array_str(value);
1482d812311STao Chen 
1492d812311STao Chen 	jsonw_end_object(json_wtr);
1502d812311STao Chen }
1512d812311STao Chen 
1522d812311STao Chen static int __show_token_info(struct mntent *mntent)
1532d812311STao Chen {
1542d812311STao Chen 	if (json_output)
1552d812311STao Chen 		show_token_info_json(mntent);
1562d812311STao Chen 	else
1572d812311STao Chen 		show_token_info_plain(mntent);
1582d812311STao Chen 
1592d812311STao Chen 	return 0;
1602d812311STao Chen }
1612d812311STao Chen 
1622d812311STao Chen static int show_token_info(void)
1632d812311STao Chen {
1642d812311STao Chen 	FILE *fp;
1652d812311STao Chen 	struct mntent *ent;
1662d812311STao Chen 
1672d812311STao Chen 	fp = setmntent(MOUNTS_FILE, "r");
1682d812311STao Chen 	if (!fp) {
1692d812311STao Chen 		p_err("Failed to open: %s", MOUNTS_FILE);
1702d812311STao Chen 		return -1;
1712d812311STao Chen 	}
1722d812311STao Chen 
1732d812311STao Chen 	if (json_output)
1742d812311STao Chen 		jsonw_start_array(json_wtr);
1752d812311STao Chen 
1762d812311STao Chen 	while ((ent = getmntent(fp)) != NULL) {
1772d812311STao Chen 		if (strncmp(ent->mnt_type, "bpf", 3) == 0) {
1782d812311STao Chen 			if (has_delegate_options(ent->mnt_opts))
1792d812311STao Chen 				__show_token_info(ent);
1802d812311STao Chen 		}
1812d812311STao Chen 	}
1822d812311STao Chen 
1832d812311STao Chen 	if (json_output)
1842d812311STao Chen 		jsonw_end_array(json_wtr);
1852d812311STao Chen 
1862d812311STao Chen 	endmntent(fp);
1872d812311STao Chen 
1882d812311STao Chen 	return 0;
1892d812311STao Chen }
1902d812311STao Chen 
1912d812311STao Chen static int do_show(int argc, char **argv)
1922d812311STao Chen {
1932d812311STao Chen 	if (argc)
1942d812311STao Chen 		return BAD_ARG();
1952d812311STao Chen 
1962d812311STao Chen 	return show_token_info();
1972d812311STao Chen }
1982d812311STao Chen 
1992d812311STao Chen static int do_help(int argc, char **argv)
2002d812311STao Chen {
2012d812311STao Chen 	if (json_output) {
2022d812311STao Chen 		jsonw_null(json_wtr);
2032d812311STao Chen 		return 0;
2042d812311STao Chen 	}
2052d812311STao Chen 
2062d812311STao Chen 	fprintf(stderr,
2072d812311STao Chen 		"Usage: %1$s %2$s { show | list }\n"
2082d812311STao Chen 		"       %1$s %2$s help\n"
209*bce5749bSTao Chen 		"       " HELP_SPEC_OPTIONS " }\n"
2102d812311STao Chen 		"\n"
2112d812311STao Chen 		"",
2122d812311STao Chen 		bin_name, argv[-2]);
2132d812311STao Chen 	return 0;
2142d812311STao Chen }
2152d812311STao Chen 
2162d812311STao Chen static const struct cmd cmds[] = {
2172d812311STao Chen 	{ "show",	do_show },
2182d812311STao Chen 	{ "list",	do_show },
2192d812311STao Chen 	{ "help",	do_help },
2202d812311STao Chen 	{ 0 }
2212d812311STao Chen };
2222d812311STao Chen 
2232d812311STao Chen int do_token(int argc, char **argv)
2242d812311STao Chen {
2252d812311STao Chen 	return cmd_select(cmds, argc, argv, do_help);
2262d812311STao Chen }
227