File: isolation_mark.c

package info (click to toggle)
batctl 2025.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 840 kB
  • sloc: ansic: 12,083; makefile: 155; sh: 21
file content (139 lines) | stat: -rw-r--r-- 3,563 bytes parent folder | download | duplicates (4)
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");