blob: ed1cba76929b0026ba1be13adf16baa527059f6f [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0+
#include <errno.h>
#include <linux/dcbnl.h>
#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;
}
}