210 lines · 3.9 KB · C
RawDownload
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/* Copyright (C) 2025 Didi Technology Co., Tao Chen */ #ifndef _GNU_SOURCE#define _GNU_SOURCE#endif#include <errno.h>#include <fcntl.h>#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <mntent.h>#include <sys/types.h>#include <sys/stat.h> #include "json_writer.h"#include "main.h" #define MOUNTS_FILE "/proc/mounts" static struct {	const char *header;	const char *key;} sets[] = {	{"allowed_cmds", "delegate_cmds"},	{"allowed_maps", "delegate_maps"},	{"allowed_progs", "delegate_progs"},	{"allowed_attachs", "delegate_attachs"},}; static bool has_delegate_options(const char *mnt_ops){	return strstr(mnt_ops, "delegate_cmds") ||	       strstr(mnt_ops, "delegate_maps") ||	       strstr(mnt_ops, "delegate_progs") ||	       strstr(mnt_ops, "delegate_attachs");} static char *get_delegate_value(char *opts, const char *key){	char *token, *rest, *ret = NULL; 	if (!opts)		return NULL; 	for (token = strtok_r(opts, ",", &rest); token;			token = strtok_r(NULL, ",", &rest)) {		if (strncmp(token, key, strlen(key)) == 0 &&		    token[strlen(key)] == '=') {			ret = token + strlen(key) + 1;			break;		}	} 	return ret;} static void print_items_per_line(char *input, int items_per_line){	char *str, *rest;	int cnt = 0; 	if (!input)		return; 	for (str = strtok_r(input, ":", &rest); str;			str = strtok_r(NULL, ":", &rest)) {		if (cnt % items_per_line == 0)			printf("\n\t  "); 		printf("%-20s", str);		cnt++;	}} #define ITEMS_PER_LINE 4static void show_token_info_plain(struct mntent *mntent){	size_t i; 	printf("token_info  %s", mntent->mnt_dir); 	for (i = 0; i < ARRAY_SIZE(sets); i++) {		char *opts, *value; 		printf("\n\t%s:", sets[i].header);		opts = strdup(mntent->mnt_opts);		value = get_delegate_value(opts, sets[i].key);		print_items_per_line(value, ITEMS_PER_LINE);		free(opts);	} 	printf("\n");} static void split_json_array_str(char *input){	char *str, *rest; 	if (!input) {		jsonw_start_array(json_wtr);		jsonw_end_array(json_wtr);		return;	} 	jsonw_start_array(json_wtr);	for (str = strtok_r(input, ":", &rest); str;			str = strtok_r(NULL, ":", &rest)) {		jsonw_string(json_wtr, str);	}	jsonw_end_array(json_wtr);} static void show_token_info_json(struct mntent *mntent){	size_t i; 	jsonw_start_object(json_wtr);	jsonw_string_field(json_wtr, "token_info", mntent->mnt_dir); 	for (i = 0; i < ARRAY_SIZE(sets); i++) {		char *opts, *value; 		jsonw_name(json_wtr, sets[i].header);		opts = strdup(mntent->mnt_opts);		value = get_delegate_value(opts, sets[i].key);		split_json_array_str(value);		free(opts);	} 	jsonw_end_object(json_wtr);} static int __show_token_info(struct mntent *mntent){	if (json_output)		show_token_info_json(mntent);	else		show_token_info_plain(mntent); 	return 0;} static int show_token_info(void){	FILE *fp;	struct mntent *ent; 	fp = setmntent(MOUNTS_FILE, "r");	if (!fp) {		p_err("Failed to open: %s", MOUNTS_FILE);		return -1;	} 	if (json_output)		jsonw_start_array(json_wtr); 	while ((ent = getmntent(fp)) != NULL) {		if (strncmp(ent->mnt_type, "bpf", 3) == 0) {			if (has_delegate_options(ent->mnt_opts))				__show_token_info(ent);		}	} 	if (json_output)		jsonw_end_array(json_wtr); 	endmntent(fp); 	return 0;} static int do_show(int argc, char **argv){	if (argc)		return BAD_ARG(); 	return show_token_info();} static int do_help(int argc, char **argv){	if (json_output) {		jsonw_null(json_wtr);		return 0;	} 	fprintf(stderr,		"Usage: %1$s %2$s { show | list }\n"		"       %1$s %2$s help\n"		"       " HELP_SPEC_OPTIONS " }\n"		"\n"		"",		bin_name, argv[-2]);	return 0;} static const struct cmd cmds[] = {	{ "show",	do_show },	{ "list",	do_show },	{ "help",	do_help },	{ 0 }}; int do_token(int argc, char **argv){	return cmd_select(cmds, argc, argv, do_help);}