@@ -27,6 +27,7 @@
#define BATADV_NL_NAME "batadv"
+#define BATADV_NL_MCAST_GROUP_CONFIG "config"
#define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter"
/**
@@ -138,6 +139,20 @@ enum batadv_mcast_flags_priv {
BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING = (1 << 4),
};
+/**
+ * enum batadv_gw_modes - gateway mode of node
+ */
+enum batadv_gw_modes {
+ /** @BATADV_GW_MODE_OFF: gw mode disabled */
+ BATADV_GW_MODE_OFF,
+
+ /** @BATADV_GW_MODE_CLIENT: send DHCP requests to gw servers */
+ BATADV_GW_MODE_CLIENT,
+
+ /** @BATADV_GW_MODE_CLIENT: announce itself as gatway server */
+ BATADV_GW_MODE_SERVER,
+};
+
/**
* enum batadv_nl_attrs - batman-adv netlink attributes
*/
@@ -344,6 +359,136 @@ enum batadv_nl_attrs {
*/
BATADV_ATTR_MCAST_FLAGS_PRIV,
+ /**
+ * @BATADV_ATTR_VLANID: VLAN id on top of soft interface
+ */
+ BATADV_ATTR_VLANID,
+
+ /**
+ * @BATADV_ATTR_AGGREGATED_OGMS: whether the batman protocol messages
+ * of the mesh mesh interface shall be aggregated or not.
+ */
+ BATADV_ATTR_AGGREGATED_OGMS,
+
+ /**
+ * @BATADV_ATTR_AP_ISOLATION: whether the data traffic going from a
+ * wireless client to another wireless client will be silently dropped.
+ */
+ BATADV_ATTR_AP_ISOLATION,
+
+ /**
+ * @BATADV_ATTR_ISOLATION_MARK: the isolation mark which is used to
+ * classify clients as "isolated" by the Extended Isolation feature.
+ */
+ BATADV_ATTR_ISOLATION_MARK,
+
+ /**
+ * @BATADV_ATTR_ISOLATION_MASK: the isolation (bit)mask which is used to
+ * classify clients as "isolated" by the Extended Isolation feature.
+ */
+ BATADV_ATTR_ISOLATION_MASK,
+
+ /**
+ * @BATADV_ATTR_BONDING: whether the data traffic going through the
+ * mesh will be sent using multiple interfaces at the same time.
+ */
+ BATADV_ATTR_BONDING,
+
+ /**
+ * @BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE: whether the bridge loop avoidance
+ * feature is enabled. This feature detects and avoids loops between
+ * the mesh and devices bridged with the soft interface
+ */
+ BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE,
+
+ /**
+ * @BATADV_ATTR_DISTRIBUTED_ARP_TABLE: whether the distributed arp table
+ * feature is enabled. This feature uses a distributed hash table to
+ * answer ARP requests without flooding the request through the whole
+ * mesh.
+ */
+ BATADV_ATTR_DISTRIBUTED_ARP_TABLE,
+
+ /**
+ * @BATADV_ATTR_FRAGMENTATION: whether the data traffic going through
+ * the mesh will be fragmented or silently discarded if the packet size
+ * exceeds the outgoing interface MTU.
+ */
+ BATADV_ATTR_FRAGMENTATION,
+
+ /**
+ * @BATADV_ATTR_GW_BANDWIDTH_DOWN: defines the download bandwidth which
+ * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set
+ * to 'server'.
+ */
+ BATADV_ATTR_GW_BANDWIDTH_DOWN,
+
+ /**
+ * @BATADV_ATTR_GW_BANDWIDTH_UP: defines the upload bandwidth which
+ * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set
+ * to 'server'.
+ */
+ BATADV_ATTR_GW_BANDWIDTH_UP,
+
+ /**
+ * @BATADV_ATTR_GW_MODE: defines the state of the gateway features.
+ * Possible values are specified in enum batadv_gw_modes
+ */
+ BATADV_ATTR_GW_MODE,
+
+ /**
+ * @BATADV_ATTR_GW_SEL_CLASS: defines the selection criteria this node
+ * will use to choose a gateway if gw_mode was set to 'client'.
+ */
+ BATADV_ATTR_GW_SEL_CLASS,
+
+ /**
+ * @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied
+ * to an originator message's tq-field on every hop.
+ */
+ BATADV_ATTR_HOP_PENALTY,
+
+ /**
+ * @BATADV_ATTR_LOG_LEVEL: bitmask with to define which debug messages
+ * should be send to the debug log/trace ring buffer
+ */
+ BATADV_ATTR_LOG_LEVEL,
+
+ /**
+ * @BATADV_ATTR_MULTICAST_MODE: whether multicast optimizations are
+ * enabled or disabled. If set to zero then all nodes in the mesh are
+ * going to use classic flooding for any multicast packet with no
+ * optimizations.
+ */
+ BATADV_ATTR_MULTICAST_MODE,
+
+ /**
+ * @BATADV_ATTR_NETWORK_CODING: whether Network Coding (using some magic
+ * to send fewer wifi packets but still the same content) is enabled or
+ * not.
+ */
+ BATADV_ATTR_NETWORK_CODING,
+
+ /**
+ * @BATADV_ATTR_ORIG_INTERVAL: defines the interval in milliseconds in
+ * which batman sends its protocol messages.
+ */
+ BATADV_ATTR_ORIG_INTERVAL,
+
+ /**
+ * @BATADV_ATTR_ELP_INTERVAL: defines the interval in milliseconds in
+ * which batman emits probing packets for neighbor sensing (ELP).
+ */
+ BATADV_ATTR_ELP_INTERVAL,
+
+ /**
+ * @BATADV_ATTR_THROUGHPUT_OVERRIDE: defines the throughput value to be
+ * used by B.A.T.M.A.N. V when estimating the link throughput using
+ * this interface. If the value is set to 0 then batman-adv will try to
+ * estimate the throughput by itself.
+ */
+ BATADV_ATTR_THROUGHPUT_OVERRIDE,
+
/* add attributes above here, update the policy in netlink.c */
/**
@@ -372,10 +517,14 @@ enum batadv_nl_commands {
BATADV_CMD_UNSPEC,
/**
- * @BATADV_CMD_GET_MESH_INFO: Query basic information about batman-adv
- * device
+ * @BATADV_CMD_GET_MESH: Get attributes from softif/mesh
+ */
+ BATADV_CMD_GET_MESH,
+
+ /**
+ * @BATADV_CMD_GET_MESH_INFO: Alias for @BATADV_CMD_GET_MESH
*/
- BATADV_CMD_GET_MESH_INFO,
+ BATADV_CMD_GET_MESH_INFO = BATADV_CMD_GET_MESH,
/**
* @BATADV_CMD_TP_METER: Start a tp meter session
@@ -393,9 +542,15 @@ enum batadv_nl_commands {
BATADV_CMD_GET_ROUTING_ALGOS,
/**
- * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces
+ * @BATADV_CMD_GET_HARDIF: Get attributes from a hardif of the
+ * current softif
*/
- BATADV_CMD_GET_HARDIFS,
+ BATADV_CMD_GET_HARDIF,
+
+ /**
+ * @BATADV_CMD_GET_HARDIFS: Alias for @BATADV_CMD_GET_HARDIF
+ */
+ BATADV_CMD_GET_HARDIFS = BATADV_CMD_GET_HARDIF,
/**
* @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations
@@ -443,6 +598,29 @@ enum batadv_nl_commands {
*/
BATADV_CMD_GET_MCAST_FLAGS,
+ /**
+ * @BATADV_CMD_SET_MESH: Set attributes for softif/mesh
+ */
+ BATADV_CMD_SET_MESH,
+
+ /**
+ * @BATADV_CMD_SET_HARDIF: Set attributes for hardif of the
+ * current softif
+ */
+ BATADV_CMD_SET_HARDIF,
+
+ /**
+ * @BATADV_CMD_GET_VLAN: Get attributes from a VLAN of the
+ * current softif
+ */
+ BATADV_CMD_GET_VLAN,
+
+ /**
+ * @BATADV_CMD_SET_VLAN: Set attributes for VLAN of the
+ * current softif
+ */
+ BATADV_CMD_SET_VLAN,
+
/* add new commands above here */
/**
@@ -22,6 +22,7 @@
#include <errno.h>
#include <getopt.h>
+#include <net/if.h>
#include <netinet/if_ether.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
@@ -51,6 +52,14 @@ struct event_args {
struct timeval tv;
};
+static const char *u8_to_boolstr(struct nlattr *attrs)
+{
+ if (nla_get_u8(attrs))
+ return "true";
+ else
+ return "false";
+}
+
static void event_usage(void)
{
fprintf(stderr, "Usage: batctl [options] event [parameters]\n");
@@ -87,6 +96,25 @@ static int event_prepare(struct state *state)
skip_tp_meter:
+ mcid = nl_get_multicast_id(state->sock, BATADV_NL_NAME,
+ BATADV_NL_MCAST_GROUP_CONFIG);
+ if (mcid < 0) {
+ fprintf(stderr, "Failed to resolve batadv config multicast group: %d\n",
+ mcid);
+ /* ignore error for now */
+ goto skip_config;
+ }
+
+ ret = nl_socket_add_membership(state->sock, mcid);
+ if (ret) {
+ fprintf(stderr, "Failed to join batadv config multicast group: %d\n",
+ ret);
+ /* ignore error for now */
+ goto skip_config;
+ }
+
+skip_config:
+
return 0;
}
@@ -145,6 +173,203 @@ static void event_parse_tp_meter(struct nlattr **attrs)
printf("tp_meter 0x%08x: %s\n", cookie, result_str);
}
+static void event_parse_set_mesh(struct nlattr **attrs)
+{
+ static const int mesh_mandatory[] = {
+ BATADV_ATTR_MESH_IFINDEX,
+ BATADV_ATTR_ALGO_NAME,
+ };
+ char meshif_buf[IF_NAMESIZE];
+ char *meshif_name;
+ uint32_t mesh_ifindex;
+
+ /* ignore entry when attributes are missing */
+ if (missing_mandatory_attrs(attrs, mesh_mandatory,
+ ARRAY_SIZE(mesh_mandatory)))
+ return;
+
+ mesh_ifindex = nla_get_u32(attrs[BATADV_ATTR_MESH_IFINDEX]);
+ meshif_name = if_indextoname(mesh_ifindex, meshif_buf);
+ if (!meshif_name)
+ return;
+
+ printf("%s: set mesh:\n", meshif_name);
+
+ if (attrs[BATADV_ATTR_AGGREGATED_OGMS])
+ printf("* aggregated_ogms %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_AGGREGATED_OGMS]));
+
+ if (attrs[BATADV_ATTR_AP_ISOLATION])
+ printf("* ap_isolation %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_AP_ISOLATION]));
+
+ if (attrs[BATADV_ATTR_ISOLATION_MARK])
+ printf("* isolation_mark 0x%08x\n",
+ nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MARK]));
+
+ if (attrs[BATADV_ATTR_ISOLATION_MASK])
+ printf("* isolation_mask 0x%08x\n",
+ nla_get_u32(attrs[BATADV_ATTR_ISOLATION_MASK]));
+
+ if (attrs[BATADV_ATTR_BONDING])
+ printf("* bonding %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_BONDING]));
+
+ if (attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE])
+ printf("* bridge_loop_avoidance %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE]));
+
+ if (attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE])
+ printf("* distributed_arp_table %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE]));
+
+ if (attrs[BATADV_ATTR_FRAGMENTATION])
+ printf("* fragmentation %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_FRAGMENTATION]));
+
+ if (attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) {
+ uint32_t val;
+
+ val = nla_get_u32(attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]);
+ printf("* gw_bandwidth_down %u.%01u MBit/s\n", val / 10,
+ val % 10);
+ }
+
+ if (attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) {
+ uint32_t val;
+
+ val = nla_get_u32(attrs[BATADV_ATTR_GW_BANDWIDTH_UP]);
+ printf("* gw_bandwidth_up %u.%01u MBit/s\n", val / 10,
+ val % 10);
+ }
+
+ if (attrs[BATADV_ATTR_GW_MODE]) {
+ uint8_t val = nla_get_u8(attrs[BATADV_ATTR_GW_MODE]);
+ const char *valstr;
+
+ switch (val) {
+ case BATADV_GW_MODE_OFF:
+ valstr = "off";
+ break;
+ case BATADV_GW_MODE_CLIENT:
+ valstr = "client";
+ break;
+ case BATADV_GW_MODE_SERVER:
+ valstr = "server";
+ break;
+ default:
+ valstr = "unknown";
+ break;
+ }
+
+ printf("* gw_mode %s\n", valstr);
+ }
+
+ if (attrs[BATADV_ATTR_GW_SEL_CLASS]) {
+ uint32_t val = nla_get_u32(attrs[BATADV_ATTR_GW_SEL_CLASS]);
+ const char *algo = nla_data(attrs[BATADV_ATTR_ALGO_NAME]);
+
+ if (strcmp(algo, "BATMAN_V") == 0)
+ printf("* gw_sel_class %u.%01u MBit/s\n", val / 10,
+ val % 10);
+ else
+ printf("* gw_sel_class %u\n", val);
+ }
+
+ if (attrs[BATADV_ATTR_HOP_PENALTY])
+ printf("* hop_penalty %u\n",
+ nla_get_u8(attrs[BATADV_ATTR_HOP_PENALTY]));
+
+ if (attrs[BATADV_ATTR_LOG_LEVEL])
+ printf("* log_level 0x%08x\n",
+ nla_get_u32(attrs[BATADV_ATTR_LOG_LEVEL]));
+
+ if (attrs[BATADV_ATTR_MULTICAST_MODE])
+ printf("* multicast_mode %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_MULTICAST_MODE]));
+
+ if (attrs[BATADV_ATTR_NETWORK_CODING])
+ printf("* network_coding %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_NETWORK_CODING]));
+
+ if (attrs[BATADV_ATTR_ORIG_INTERVAL])
+ printf("* orig_interval %u ms\n",
+ nla_get_u32(attrs[BATADV_ATTR_ORIG_INTERVAL]));
+}
+
+static void event_parse_set_hardif(struct nlattr **attrs)
+{
+ static const int hardif_mandatory[] = {
+ BATADV_ATTR_MESH_IFINDEX,
+ BATADV_ATTR_HARD_IFINDEX,
+ };
+ char meshif_buf[IF_NAMESIZE];
+ char hardif_buf[IF_NAMESIZE];
+ char *meshif_name;
+ char *hardif_name;
+ uint32_t hardif_ifindex;
+ uint32_t mesh_ifindex;
+
+ /* ignore entry when attributes are missing */
+ if (missing_mandatory_attrs(attrs, hardif_mandatory,
+ ARRAY_SIZE(hardif_mandatory)))
+ return;
+
+ mesh_ifindex = nla_get_u32(attrs[BATADV_ATTR_MESH_IFINDEX]);
+ meshif_name = if_indextoname(mesh_ifindex, meshif_buf);
+ if (!meshif_name)
+ return;
+
+ hardif_ifindex = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]);
+ hardif_name = if_indextoname(hardif_ifindex, hardif_buf);
+ if (!hardif_name)
+ return;
+
+ printf("%s (%s): set hardif:\n", meshif_name, hardif_name);
+
+ if (attrs[BATADV_ATTR_ELP_INTERVAL])
+ printf("* elp_interval %u ms\n",
+ nla_get_u32(attrs[BATADV_ATTR_ELP_INTERVAL]));
+
+ if (attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) {
+ uint32_t val;
+
+ val = nla_get_u32(attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]);
+ printf("* throughput_override %u.%01u MBit/s\n", val / 10,
+ val % 10);
+ }
+}
+
+static void event_parse_set_vlan(struct nlattr **attrs)
+{
+ static const int vlan_mandatory[] = {
+ BATADV_ATTR_MESH_IFINDEX,
+ BATADV_ATTR_VLANID,
+ };
+ char meshif_buf[IF_NAMESIZE];
+ char *meshif_name;
+ uint32_t mesh_ifindex;
+ uint16_t vid;
+
+ /* ignore entry when attributes are missing */
+ if (missing_mandatory_attrs(attrs, vlan_mandatory,
+ ARRAY_SIZE(vlan_mandatory)))
+ return;
+
+ mesh_ifindex = nla_get_u32(attrs[BATADV_ATTR_MESH_IFINDEX]);
+ meshif_name = if_indextoname(mesh_ifindex, meshif_buf);
+ if (!meshif_name)
+ return;
+
+ vid = nla_get_u16(attrs[BATADV_ATTR_VLANID]);
+
+ printf("%s (vid %u): set vlan:\n", meshif_name, vid);
+
+ if (attrs[BATADV_ATTR_AP_ISOLATION])
+ printf("* ap_isolation %s\n",
+ u8_to_boolstr(attrs[BATADV_ATTR_AP_ISOLATION]));
+}
+
static unsigned long long get_timestamp(struct event_args *event_args)
{
unsigned long long prevtime = 0;
@@ -190,6 +415,15 @@ static int event_parse(struct nl_msg *msg, void *arg)
case BATADV_CMD_TP_METER:
event_parse_tp_meter(attrs);
break;
+ case BATADV_CMD_SET_MESH:
+ event_parse_set_mesh(attrs);
+ break;
+ case BATADV_CMD_SET_HARDIF:
+ event_parse_set_hardif(attrs);
+ break;
+ case BATADV_CMD_SET_VLAN:
+ event_parse_set_vlan(attrs);
+ break;
default:
printf("Received unknown event %u\n", ghdr->cmd);
break;
@@ -107,6 +107,26 @@ struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_DAT_CACHE_VID] = { .type = NLA_U16 },
[BATADV_ATTR_MCAST_FLAGS] = { .type = NLA_U32 },
[BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NLA_U32 },
+ [BATADV_ATTR_VLANID] = { .type = NLA_U16 },
+ [BATADV_ATTR_AGGREGATED_OGMS] = { .type = NLA_U8 },
+ [BATADV_ATTR_AP_ISOLATION] = { .type = NLA_U8 },
+ [BATADV_ATTR_ISOLATION_MARK] = { .type = NLA_U32 },
+ [BATADV_ATTR_ISOLATION_MASK] = { .type = NLA_U32 },
+ [BATADV_ATTR_BONDING] = { .type = NLA_U8 },
+ [BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE] = { .type = NLA_U8 },
+ [BATADV_ATTR_DISTRIBUTED_ARP_TABLE] = { .type = NLA_U8 },
+ [BATADV_ATTR_FRAGMENTATION] = { .type = NLA_U8 },
+ [BATADV_ATTR_GW_BANDWIDTH_DOWN] = { .type = NLA_U32 },
+ [BATADV_ATTR_GW_BANDWIDTH_UP] = { .type = NLA_U32 },
+ [BATADV_ATTR_GW_MODE] = { .type = NLA_U8 },
+ [BATADV_ATTR_GW_SEL_CLASS] = { .type = NLA_U32 },
+ [BATADV_ATTR_HOP_PENALTY] = { .type = NLA_U8 },
+ [BATADV_ATTR_LOG_LEVEL] = { .type = NLA_U32 },
+ [BATADV_ATTR_MULTICAST_MODE] = { .type = NLA_U8 },
+ [BATADV_ATTR_NETWORK_CODING] = { .type = NLA_U8 },
+ [BATADV_ATTR_ORIG_INTERVAL] = { .type = NLA_U32 },
+ [BATADV_ATTR_ELP_INTERVAL] = { .type = NLA_U32 },
+ [BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NLA_U32 },
};
int netlink_create(struct state *state)