// SPDX-License-Identifier: GPL-2.0+ #include #include #include "dcb.h" #include "utils.h" static void dcb_apptrust_help_set(void) { fprintf(stderr, "Usage: dcb apptrust set dev STRING\n" " [ order [ ethtype | stream-port | dgram-port | port | dscp | pcp ] ]\n" "\n"); } static void dcb_apptrust_help_show(void) { fprintf(stderr, "Usage: dcb apptrust show dev STRING\n" " [ order ]\n" "\n"); } static void dcb_apptrust_help(void) { fprintf(stderr, "Usage: dcb apptrust help\n" "\n"); dcb_apptrust_help_show(); dcb_apptrust_help_set(); } static const char *const selector_names[] = { [IEEE_8021QAZ_APP_SEL_ETHERTYPE] = "ethtype", [IEEE_8021QAZ_APP_SEL_STREAM] = "stream-port", [IEEE_8021QAZ_APP_SEL_DGRAM] = "dgram-port", [IEEE_8021QAZ_APP_SEL_ANY] = "port", [IEEE_8021QAZ_APP_SEL_DSCP] = "dscp", [DCB_APP_SEL_PCP] = "pcp", }; struct dcb_apptrust_table { __u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1]; int nselectors; }; static bool dcb_apptrust_contains(const struct dcb_apptrust_table *table, __u8 selector) { int i; for (i = 0; i < table->nselectors; i++) if (table->selectors[i] == selector) return true; return false; } static void dcb_apptrust_print_order(const struct dcb_apptrust_table *table) { const char *str; __u8 selector; int i; open_json_array(PRINT_JSON, "order"); print_string(PRINT_FP, NULL, "order: ", NULL); for (i = 0; i < table->nselectors; i++) { selector = table->selectors[i]; str = selector_names[selector]; print_string(PRINT_ANY, NULL, "%s ", str); } print_nl(); close_json_array(PRINT_JSON, "order"); } static void dcb_apptrust_print(const struct dcb_apptrust_table *table) { dcb_apptrust_print_order(table); print_nl(); } static int dcb_apptrust_get_cb(const struct nlattr *attr, void *data) { struct dcb_apptrust_table *table = data; uint16_t type; __u8 selector; type = mnl_attr_get_type(attr); if (!dcb_app_attr_type_validate(type)) { fprintf(stderr, "Unknown attribute in DCB_ATTR_IEEE_APP_TRUST_TABLE: %d\n", type); return MNL_CB_OK; } if (mnl_attr_get_payload_len(attr) < 1) { fprintf(stderr, "DCB_ATTR_IEEE_APP_TRUST payload expected to have size %zd, not %d\n", sizeof(struct dcb_app), mnl_attr_get_payload_len(attr)); return MNL_CB_OK; } selector = mnl_attr_get_u8(attr); /* Check that selector is encapsulated in the right attribute */ if (!dcb_app_selector_validate(type, selector)) { fprintf(stderr, "Wrong type for selector: %s\n", selector_names[selector]); return MNL_CB_OK; } table->selectors[table->nselectors++] = selector; return MNL_CB_OK; } static int dcb_apptrust_get(struct dcb *dcb, const char *dev, struct dcb_apptrust_table *table) { uint16_t payload_len; void *payload; int ret; ret = dcb_get_attribute_va(dcb, dev, DCB_ATTR_DCB_APP_TRUST_TABLE, &payload, &payload_len); if (ret != 0) return ret; ret = mnl_attr_parse_payload(payload, payload_len, dcb_apptrust_get_cb, table); if (ret != MNL_CB_OK) return -EINVAL; return 0; } static int dcb_apptrust_set_cb(struct dcb *dcb, struct nlmsghdr *nlh, void *data) { const struct dcb_apptrust_table *table = data; enum ieee_attrs_app type; struct nlattr *nest; int i; nest = mnl_attr_nest_start(nlh, DCB_ATTR_DCB_APP_TRUST_TABLE); for (i = 0; i < table->nselectors; i++) { type = dcb_app_attr_type_get(table->selectors[i]); mnl_attr_put_u8(nlh, type, table->selectors[i]); } mnl_attr_nest_end(nlh, nest); return 0; } static int dcb_apptrust_set(struct dcb *dcb, const char *dev, const struct dcb_apptrust_table *table) { return dcb_set_attribute_va(dcb, DCB_CMD_IEEE_SET, dev, &dcb_apptrust_set_cb, (void *)table); } static __u8 dcb_apptrust_parse_selector(const char *selector, int *err) { int i; for (i = 0; i < ARRAY_SIZE(selector_names); i++) { if (selector_names[i] && strcmp(selector, selector_names[i]) == 0) { *err = 0; return i; } } *err = -EINVAL; return 0; } static int dcb_apptrust_parse_selector_list(int *argcp, char ***argvp, struct dcb_apptrust_table *table) { int argc = *argcp, err; char **argv = *argvp; __u8 selector; /* No trusted selectors ? */ if (argc == 0) goto out; while (argc > 0) { selector = dcb_apptrust_parse_selector(*argv, &err); if (err < 0) goto out; if (table->nselectors > IEEE_8021QAZ_APP_SEL_MAX) return -ERANGE; if (dcb_apptrust_contains(table, selector)) { fprintf(stderr, "Duplicate selector: %s\n", selector_names[selector]); return -EINVAL; } table->selectors[table->nselectors++] = selector; NEXT_ARG_FWD(); } out: *argcp = argc; *argvp = argv; return 0; } static int dcb_cmd_apptrust_set(struct dcb *dcb, const char *dev, int argc, char **argv) { struct dcb_apptrust_table table = { 0 }; int ret; if (!argc) { dcb_apptrust_help_set(); return 0; } do { if (strcmp(*argv, "help") == 0) { dcb_apptrust_help_set(); return 0; } else if (strcmp(*argv, "order") == 0) { NEXT_ARG_FWD(); ret = dcb_apptrust_parse_selector_list(&argc, &argv, &table); if (ret < 0) { fprintf(stderr, "Invalid list of selectors\n"); return -EINVAL; } } else { fprintf(stderr, "What is \"%s\"?\n", *argv); dcb_apptrust_help_set(); return -EINVAL; } } while (argc > 0); return dcb_apptrust_set(dcb, dev, &table); } static int dcb_cmd_apptrust_show(struct dcb *dcb, const char *dev, int argc, char **argv) { struct dcb_apptrust_table table = { 0 }; int ret; ret = dcb_apptrust_get(dcb, dev, &table); if (ret) return ret; open_json_object(NULL); if (!argc) { dcb_apptrust_print(&table); goto out; } do { if (strcmp(*argv, "help") == 0) { dcb_apptrust_help_show(); return 0; } else if (strcmp(*argv, "order") == 0) { dcb_apptrust_print_order(&table); } else { fprintf(stderr, "What is \"%s\"?\n", *argv); dcb_apptrust_help_show(); return -EINVAL; } NEXT_ARG_FWD(); } while (argc > 0); out: close_json_object(); return 0; } int dcb_cmd_apptrust(struct dcb *dcb, int argc, char **argv) { if (!argc || strcmp(*argv, "help") == 0) { dcb_apptrust_help(); return 0; } else if (strcmp(*argv, "show") == 0) { NEXT_ARG_FWD(); return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_apptrust_show, dcb_apptrust_help_show); } else if (strcmp(*argv, "set") == 0) { NEXT_ARG_FWD(); return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_apptrust_set, dcb_apptrust_help_set); } else { fprintf(stderr, "What is \"%s\"?\n", *argv); dcb_apptrust_help(); return -EINVAL; } }