1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) B.A.T.M.A.N. contributors:
*
* Antonio Quartulli <a@unstable.cc>
*
* License-Filename: LICENSES/preferred/GPL-2.0
*/
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "main.h"
#include "sys.h"
static struct isolation_mark_data {
uint32_t isolation_mark;
uint32_t isolation_mask;
} isolation_mark;
static int parse_isolation_mark(struct state *state, int argc, char *argv[])
{
struct settings_data *settings = state->cmd->arg;
struct isolation_mark_data *data = settings->data;
char *mask_ptr;
char buff[256];
uint32_t mark;
uint32_t mask;
char *endptr;
if (argc != 2) {
fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n");
return -EINVAL;
}
strncpy(buff, argv[1], sizeof(buff));
buff[sizeof(buff) - 1] = '\0';
/* parse the mask if it has been specified, otherwise assume the mask is
* the biggest possible
*/
mask = 0xFFFFFFFF;
mask_ptr = strchr(buff, '/');
if (mask_ptr) {
*mask_ptr = '\0';
mask_ptr++;
/* the mask must be entered in hex base as it is going to be a
* bitmask and not a prefix length
*/
mask = strtoul(mask_ptr, &endptr, 16);
if (!endptr || *endptr != '\0')
goto inval_format;
}
/* the mark can be entered in any base */
mark = strtoul(buff, &endptr, 0);
if (!endptr || *endptr != '\0')
goto inval_format;
data->isolation_mask = mask;
/* erase bits not covered by the mask */
data->isolation_mark = mark & mask;
return 0;
inval_format:
fprintf(stderr, "Error - incorrect number of arguments (expected 1)\n");
fprintf(stderr, "The following formats for mark(/mask) are allowed:\n");
fprintf(stderr, " * 0x12345678\n");
fprintf(stderr, " * 0x12345678/0xabcdef09\n");
return -EINVAL;
}
static int print_isolation_mark(struct nl_msg *msg, void *arg)
{
struct nlattr *attrs[BATADV_ATTR_MAX + 1];
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct genlmsghdr *ghdr;
int *result = arg;
if (!genlmsg_valid_hdr(nlh, 0))
return NL_OK;
ghdr = nlmsg_data(nlh);
if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0),
genlmsg_len(ghdr), batadv_netlink_policy)) {
return NL_OK;
}
if (!attrs[BATADV_ATTR_ISOLATION_MARK] ||
!attrs[BATADV_ATTR_ISOLATION_MASK])
return NL_OK;
printf("0x%08x/0x%08x\n",
nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MARK]),
nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MASK]));
*result = 0;
return NL_STOP;
}
static int get_isolation_mark(struct state *state)
{
return sys_simple_nlquery(state, BATADV_CMD_GET_MESH,
NULL, print_isolation_mark);
}
static int set_attrs_isolation_mark(struct nl_msg *msg, void *arg)
{
struct state *state = arg;
struct settings_data *settings = state->cmd->arg;
struct isolation_mark_data *data = settings->data;
nla_put_u32(msg, BATADV_ATTR_ISOLATION_MARK, data->isolation_mark);
nla_put_u32(msg, BATADV_ATTR_ISOLATION_MASK, data->isolation_mask);
return 0;
}
static int set_isolation_mark(struct state *state)
{
return sys_simple_nlquery(state, BATADV_CMD_SET_MESH,
set_attrs_isolation_mark, NULL);
}
static struct settings_data batctl_settings_isolation_mark = {
.data = &isolation_mark,
.parse = parse_isolation_mark,
.netlink_get = get_isolation_mark,
.netlink_set = set_isolation_mark,
};
COMMAND_NAMED(SUBCOMMAND_MIF, isolation_mark, "mark", handle_sys_setting,
COMMAND_FLAG_MESH_IFACE | COMMAND_FLAG_NETLINK,
&batctl_settings_isolation_mark,
"[mark] \tdisplay or modify isolation_mark setting");
|