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