File Index
Files and directories
Sign in
FILE

netlink.c

File preview with syntax highlighting.

linux-6.19.14/net/batman-adv/netlink.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) B.A.T.M.A.N. contributors:
   3 *
   4 * Matthias Schiffer
   5 */
   6
   7#include "netlink.h"
   8#include "main.h"
   9
  10#include <linux/array_size.h>
  11#include <linux/atomic.h>
  12#include <linux/bitops.h>
  13#include <linux/bug.h>
  14#include <linux/byteorder/generic.h>
  15#include <linux/cache.h>
  16#include <linux/err.h>
  17#include <linux/errno.h>
  18#include <linux/gfp.h>
  19#include <linux/if_ether.h>
  20#include <linux/if_vlan.h>
  21#include <linux/init.h>
  22#include <linux/limits.h>
  23#include <linux/minmax.h>
  24#include <linux/netdevice.h>
  25#include <linux/netlink.h>
  26#include <linux/printk.h>
  27#include <linux/rtnetlink.h>
  28#include <linux/skbuff.h>
  29#include <linux/stddef.h>
  30#include <linux/types.h>
  31#include <net/genetlink.h>
  32#include <net/net_namespace.h>
  33#include <net/netlink.h>
  34#include <net/sock.h>
  35#include <uapi/linux/batadv_packet.h>
  36#include <uapi/linux/batman_adv.h>
  37
  38#include "bat_algo.h"
  39#include "bridge_loop_avoidance.h"
  40#include "distributed-arp-table.h"
  41#include "gateway_client.h"
  42#include "gateway_common.h"
  43#include "hard-interface.h"
  44#include "log.h"
  45#include "mesh-interface.h"
  46#include "multicast.h"
  47#include "originator.h"
  48#include "tp_meter.h"
  49#include "translation-table.h"
  50
  51struct genl_family batadv_netlink_family;
  52
  53/* multicast groups */
  54enum batadv_netlink_multicast_groups {
  55	BATADV_NL_MCGRP_CONFIG,
  56	BATADV_NL_MCGRP_TPMETER,
  57};
  58
  59/**
  60 * enum batadv_genl_ops_flags - flags for genl_ops's internal_flags
  61 */
  62enum batadv_genl_ops_flags {
  63	/**
  64	 * @BATADV_FLAG_NEED_MESH: request requires valid mesh interface in
  65	 *  attribute BATADV_ATTR_MESH_IFINDEX and expects a pointer to it to be
  66	 *  saved in info->user_ptr[0]
  67	 */
  68	BATADV_FLAG_NEED_MESH = BIT(0),
  69
  70	/**
  71	 * @BATADV_FLAG_NEED_HARDIF: request requires valid hard interface in
  72	 *  attribute BATADV_ATTR_HARD_IFINDEX and expects a pointer to it to be
  73	 *  saved in info->user_ptr[1]
  74	 */
  75	BATADV_FLAG_NEED_HARDIF = BIT(1),
  76
  77	/**
  78	 * @BATADV_FLAG_NEED_VLAN: request requires valid vlan in
  79	 *  attribute BATADV_ATTR_VLANID and expects a pointer to it to be
  80	 *  saved in info->user_ptr[1]
  81	 */
  82	BATADV_FLAG_NEED_VLAN = BIT(2),
  83};
  84
  85static const struct genl_multicast_group batadv_netlink_mcgrps[] = {
  86	[BATADV_NL_MCGRP_CONFIG] = { .name = BATADV_NL_MCAST_GROUP_CONFIG },
  87	[BATADV_NL_MCGRP_TPMETER] = { .name = BATADV_NL_MCAST_GROUP_TPMETER },
  88};
  89
  90static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
  91	[BATADV_ATTR_VERSION]			= { .type = NLA_STRING },
  92	[BATADV_ATTR_ALGO_NAME]			= { .type = NLA_STRING },
  93	[BATADV_ATTR_MESH_IFINDEX]		= { .type = NLA_U32 },
  94	[BATADV_ATTR_MESH_IFNAME]		= { .type = NLA_STRING },
  95	[BATADV_ATTR_MESH_ADDRESS]		= { .len = ETH_ALEN },
  96	[BATADV_ATTR_HARD_IFINDEX]		= { .type = NLA_U32 },
  97	[BATADV_ATTR_HARD_IFNAME]		= { .type = NLA_STRING },
  98	[BATADV_ATTR_HARD_ADDRESS]		= { .len = ETH_ALEN },
  99	[BATADV_ATTR_ORIG_ADDRESS]		= { .len = ETH_ALEN },
 100	[BATADV_ATTR_TPMETER_RESULT]		= { .type = NLA_U8 },
 101	[BATADV_ATTR_TPMETER_TEST_TIME]		= { .type = NLA_U32 },
 102	[BATADV_ATTR_TPMETER_BYTES]		= { .type = NLA_U64 },
 103	[BATADV_ATTR_TPMETER_COOKIE]		= { .type = NLA_U32 },
 104	[BATADV_ATTR_ACTIVE]			= { .type = NLA_FLAG },
 105	[BATADV_ATTR_TT_ADDRESS]		= { .len = ETH_ALEN },
 106	[BATADV_ATTR_TT_TTVN]			= { .type = NLA_U8 },
 107	[BATADV_ATTR_TT_LAST_TTVN]		= { .type = NLA_U8 },
 108	[BATADV_ATTR_TT_CRC32]			= { .type = NLA_U32 },
 109	[BATADV_ATTR_TT_VID]			= { .type = NLA_U16 },
 110	[BATADV_ATTR_TT_FLAGS]			= { .type = NLA_U32 },
 111	[BATADV_ATTR_FLAG_BEST]			= { .type = NLA_FLAG },
 112	[BATADV_ATTR_LAST_SEEN_MSECS]		= { .type = NLA_U32 },
 113	[BATADV_ATTR_NEIGH_ADDRESS]		= { .len = ETH_ALEN },
 114	[BATADV_ATTR_TQ]			= { .type = NLA_U8 },
 115	[BATADV_ATTR_THROUGHPUT]		= { .type = NLA_U32 },
 116	[BATADV_ATTR_BANDWIDTH_UP]		= { .type = NLA_U32 },
 117	[BATADV_ATTR_BANDWIDTH_DOWN]		= { .type = NLA_U32 },
 118	[BATADV_ATTR_ROUTER]			= { .len = ETH_ALEN },
 119	[BATADV_ATTR_BLA_OWN]			= { .type = NLA_FLAG },
 120	[BATADV_ATTR_BLA_ADDRESS]		= { .len = ETH_ALEN },
 121	[BATADV_ATTR_BLA_VID]			= { .type = NLA_U16 },
 122	[BATADV_ATTR_BLA_BACKBONE]		= { .len = ETH_ALEN },
 123	[BATADV_ATTR_BLA_CRC]			= { .type = NLA_U16 },
 124	[BATADV_ATTR_DAT_CACHE_IP4ADDRESS]	= { .type = NLA_U32 },
 125	[BATADV_ATTR_DAT_CACHE_HWADDRESS]	= { .len = ETH_ALEN },
 126	[BATADV_ATTR_DAT_CACHE_VID]		= { .type = NLA_U16 },
 127	[BATADV_ATTR_MCAST_FLAGS]		= { .type = NLA_U32 },
 128	[BATADV_ATTR_MCAST_FLAGS_PRIV]		= { .type = NLA_U32 },
 129	[BATADV_ATTR_VLANID]			= { .type = NLA_U16 },
 130	[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]	= { .type = NLA_U8 },
 131	[BATADV_ATTR_AP_ISOLATION_ENABLED]	= { .type = NLA_U8 },
 132	[BATADV_ATTR_ISOLATION_MARK]		= { .type = NLA_U32 },
 133	[BATADV_ATTR_ISOLATION_MASK]		= { .type = NLA_U32 },
 134	[BATADV_ATTR_BONDING_ENABLED]		= { .type = NLA_U8 },
 135	[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]	= { .type = NLA_U8 },
 136	[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]	= { .type = NLA_U8 },
 137	[BATADV_ATTR_FRAGMENTATION_ENABLED]	= { .type = NLA_U8 },
 138	[BATADV_ATTR_GW_BANDWIDTH_DOWN]		= { .type = NLA_U32 },
 139	[BATADV_ATTR_GW_BANDWIDTH_UP]		= { .type = NLA_U32 },
 140	[BATADV_ATTR_GW_MODE]			= { .type = NLA_U8 },
 141	[BATADV_ATTR_GW_SEL_CLASS]		= { .type = NLA_U32 },
 142	[BATADV_ATTR_HOP_PENALTY]		= { .type = NLA_U8 },
 143	[BATADV_ATTR_LOG_LEVEL]			= { .type = NLA_U32 },
 144	[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]	= { .type = NLA_U8 },
 145	[BATADV_ATTR_MULTICAST_FANOUT]		= { .type = NLA_U32 },
 146	[BATADV_ATTR_ORIG_INTERVAL]		= { .type = NLA_U32 },
 147	[BATADV_ATTR_ELP_INTERVAL]		= { .type = NLA_U32 },
 148	[BATADV_ATTR_THROUGHPUT_OVERRIDE]	= { .type = NLA_U32 },
 149};
 150
 151/**
 152 * batadv_netlink_get_ifindex() - Extract an interface index from a message
 153 * @nlh: Message header
 154 * @attrtype: Attribute which holds an interface index
 155 *
 156 * Return: interface index, or 0.
 157 */
 158static int batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype)
 159{
 160	struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
 161
 162	return (attr && nla_len(attr) == sizeof(u32)) ? nla_get_u32(attr) : 0;
 163}
 164
 165/**
 166 * batadv_netlink_mesh_fill_ap_isolation() - Add ap_isolation meshif attribute
 167 * @msg: Netlink message to dump into
 168 * @bat_priv: the bat priv with all the mesh interface information
 169 *
 170 * Return: 0 on success or negative error number in case of failure
 171 */
 172static int batadv_netlink_mesh_fill_ap_isolation(struct sk_buff *msg,
 173						 struct batadv_priv *bat_priv)
 174{
 175	struct batadv_meshif_vlan *vlan;
 176	u8 ap_isolation;
 177
 178	vlan = batadv_meshif_vlan_get(bat_priv, BATADV_NO_FLAGS);
 179	if (!vlan)
 180		return 0;
 181
 182	ap_isolation = atomic_read(&vlan->ap_isolation);
 183	batadv_meshif_vlan_put(vlan);
 184
 185	return nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED,
 186			  !!ap_isolation);
 187}
 188
 189/**
 190 * batadv_netlink_set_mesh_ap_isolation() - Set ap_isolation from genl msg
 191 * @attr: parsed BATADV_ATTR_AP_ISOLATION_ENABLED attribute
 192 * @bat_priv: the bat priv with all the mesh interface information
 193 *
 194 * Return: 0 on success or negative error number in case of failure
 195 */
 196static int batadv_netlink_set_mesh_ap_isolation(struct nlattr *attr,
 197						struct batadv_priv *bat_priv)
 198{
 199	struct batadv_meshif_vlan *vlan;
 200
 201	vlan = batadv_meshif_vlan_get(bat_priv, BATADV_NO_FLAGS);
 202	if (!vlan)
 203		return -ENOENT;
 204
 205	atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr));
 206	batadv_meshif_vlan_put(vlan);
 207
 208	return 0;
 209}
 210
 211/**
 212 * batadv_netlink_mesh_fill() - Fill message with mesh attributes
 213 * @msg: Netlink message to dump into
 214 * @bat_priv: the bat priv with all the mesh interface information
 215 * @cmd: type of message to generate
 216 * @portid: Port making netlink request
 217 * @seq: sequence number for message
 218 * @flags: Additional flags for message
 219 *
 220 * Return: 0 on success or negative error number in case of failure
 221 */
 222static int batadv_netlink_mesh_fill(struct sk_buff *msg,
 223				    struct batadv_priv *bat_priv,
 224				    enum batadv_nl_commands cmd,
 225				    u32 portid, u32 seq, int flags)
 226{
 227	struct net_device *mesh_iface = bat_priv->mesh_iface;
 228	struct batadv_hard_iface *primary_if = NULL;
 229	struct net_device *hard_iface;
 230	void *hdr;
 231
 232	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
 233	if (!hdr)
 234		return -ENOBUFS;
 235
 236	if (nla_put_string(msg, BATADV_ATTR_VERSION, BATADV_SOURCE_VERSION) ||
 237	    nla_put_string(msg, BATADV_ATTR_ALGO_NAME,
 238			   bat_priv->algo_ops->name) ||
 239	    nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, mesh_iface->ifindex) ||
 240	    nla_put_string(msg, BATADV_ATTR_MESH_IFNAME, mesh_iface->name) ||
 241	    nla_put(msg, BATADV_ATTR_MESH_ADDRESS, ETH_ALEN,
 242		    mesh_iface->dev_addr) ||
 243	    nla_put_u8(msg, BATADV_ATTR_TT_TTVN,
 244		       (u8)atomic_read(&bat_priv->tt.vn)))
 245		goto nla_put_failure;
 246
 247#ifdef CONFIG_BATMAN_ADV_BLA
 248	if (nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
 249			ntohs(bat_priv->bla.claim_dest.group)))
 250		goto nla_put_failure;
 251#endif
 252
 253	if (batadv_mcast_mesh_info_put(msg, bat_priv))
 254		goto nla_put_failure;
 255
 256	primary_if = batadv_primary_if_get_selected(bat_priv);
 257	if (primary_if && primary_if->if_status == BATADV_IF_ACTIVE) {
 258		hard_iface = primary_if->net_dev;
 259
 260		if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
 261				hard_iface->ifindex) ||
 262		    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
 263				   hard_iface->name) ||
 264		    nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
 265			    hard_iface->dev_addr))
 266			goto nla_put_failure;
 267	}
 268
 269	if (nla_put_u8(msg, BATADV_ATTR_AGGREGATED_OGMS_ENABLED,
 270		       !!atomic_read(&bat_priv->aggregated_ogms)))
 271		goto nla_put_failure;
 272
 273	if (batadv_netlink_mesh_fill_ap_isolation(msg, bat_priv))
 274		goto nla_put_failure;
 275
 276	if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MARK,
 277			bat_priv->isolation_mark))
 278		goto nla_put_failure;
 279
 280	if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MASK,
 281			bat_priv->isolation_mark_mask))
 282		goto nla_put_failure;
 283
 284	if (nla_put_u8(msg, BATADV_ATTR_BONDING_ENABLED,
 285		       !!atomic_read(&bat_priv->bonding)))
 286		goto nla_put_failure;
 287
 288#ifdef CONFIG_BATMAN_ADV_BLA
 289	if (nla_put_u8(msg, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED,
 290		       !!atomic_read(&bat_priv->bridge_loop_avoidance)))
 291		goto nla_put_failure;
 292#endif /* CONFIG_BATMAN_ADV_BLA */
 293
 294#ifdef CONFIG_BATMAN_ADV_DAT
 295	if (nla_put_u8(msg, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED,
 296		       !!atomic_read(&bat_priv->distributed_arp_table)))
 297		goto nla_put_failure;
 298#endif /* CONFIG_BATMAN_ADV_DAT */
 299
 300	if (nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION_ENABLED,
 301		       !!atomic_read(&bat_priv->fragmentation)))
 302		goto nla_put_failure;
 303
 304	if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_DOWN,
 305			atomic_read(&bat_priv->gw.bandwidth_down)))
 306		goto nla_put_failure;
 307
 308	if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_UP,
 309			atomic_read(&bat_priv->gw.bandwidth_up)))
 310		goto nla_put_failure;
 311
 312	if (nla_put_u8(msg, BATADV_ATTR_GW_MODE,
 313		       atomic_read(&bat_priv->gw.mode)))
 314		goto nla_put_failure;
 315
 316	if (bat_priv->algo_ops->gw.get_best_gw_node &&
 317	    bat_priv->algo_ops->gw.is_eligible) {
 318		/* GW selection class is not available if the routing algorithm
 319		 * in use does not implement the GW API
 320		 */
 321		if (nla_put_u32(msg, BATADV_ATTR_GW_SEL_CLASS,
 322				atomic_read(&bat_priv->gw.sel_class)))
 323			goto nla_put_failure;
 324	}
 325
 326	if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
 327		       atomic_read(&bat_priv->hop_penalty)))
 328		goto nla_put_failure;
 329
 330#ifdef CONFIG_BATMAN_ADV_DEBUG
 331	if (nla_put_u32(msg, BATADV_ATTR_LOG_LEVEL,
 332			atomic_read(&bat_priv->log_level)))
 333		goto nla_put_failure;
 334#endif /* CONFIG_BATMAN_ADV_DEBUG */
 335
 336#ifdef CONFIG_BATMAN_ADV_MCAST
 337	if (nla_put_u8(msg, BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED,
 338		       !atomic_read(&bat_priv->multicast_mode)))
 339		goto nla_put_failure;
 340
 341	if (nla_put_u32(msg, BATADV_ATTR_MULTICAST_FANOUT,
 342			atomic_read(&bat_priv->multicast_fanout)))
 343		goto nla_put_failure;
 344#endif /* CONFIG_BATMAN_ADV_MCAST */
 345
 346	if (nla_put_u32(msg, BATADV_ATTR_ORIG_INTERVAL,
 347			atomic_read(&bat_priv->orig_interval)))
 348		goto nla_put_failure;
 349
 350	batadv_hardif_put(primary_if);
 351
 352	genlmsg_end(msg, hdr);
 353	return 0;
 354
 355nla_put_failure:
 356	batadv_hardif_put(primary_if);
 357
 358	genlmsg_cancel(msg, hdr);
 359	return -EMSGSIZE;
 360}
 361
 362/**
 363 * batadv_netlink_notify_mesh() - send meshif attributes to listener
 364 * @bat_priv: the bat priv with all the mesh interface information
 365 *
 366 * Return: 0 on success, < 0 on error
 367 */
 368static int batadv_netlink_notify_mesh(struct batadv_priv *bat_priv)
 369{
 370	struct sk_buff *msg;
 371	int ret;
 372
 373	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 374	if (!msg)
 375		return -ENOMEM;
 376
 377	ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_SET_MESH,
 378				       0, 0, 0);
 379	if (ret < 0) {
 380		nlmsg_free(msg);
 381		return ret;
 382	}
 383
 384	genlmsg_multicast_netns(&batadv_netlink_family,
 385				dev_net(bat_priv->mesh_iface), msg, 0,
 386				BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
 387
 388	return 0;
 389}
 390
 391/**
 392 * batadv_netlink_get_mesh() - Get meshif attributes
 393 * @skb: Netlink message with request data
 394 * @info: receiver information
 395 *
 396 * Return: 0 on success or negative error number in case of failure
 397 */
 398static int batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info)
 399{
 400	struct batadv_priv *bat_priv = info->user_ptr[0];
 401	struct sk_buff *msg;
 402	int ret;
 403
 404	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 405	if (!msg)
 406		return -ENOMEM;
 407
 408	ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_GET_MESH,
 409				       info->snd_portid, info->snd_seq, 0);
 410	if (ret < 0) {
 411		nlmsg_free(msg);
 412		return ret;
 413	}
 414
 415	ret = genlmsg_reply(msg, info);
 416
 417	return ret;
 418}
 419
 420/**
 421 * batadv_netlink_set_mesh() - Set meshif attributes
 422 * @skb: Netlink message with request data
 423 * @info: receiver information
 424 *
 425 * Return: 0 on success or negative error number in case of failure
 426 */
 427static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
 428{
 429	struct batadv_priv *bat_priv = info->user_ptr[0];
 430	struct nlattr *attr;
 431
 432	if (info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]) {
 433		attr = info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED];
 434
 435		atomic_set(&bat_priv->aggregated_ogms, !!nla_get_u8(attr));
 436	}
 437
 438	if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
 439		attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED];
 440
 441		batadv_netlink_set_mesh_ap_isolation(attr, bat_priv);
 442	}
 443
 444	if (info->attrs[BATADV_ATTR_ISOLATION_MARK]) {
 445		attr = info->attrs[BATADV_ATTR_ISOLATION_MARK];
 446
 447		bat_priv->isolation_mark = nla_get_u32(attr);
 448	}
 449
 450	if (info->attrs[BATADV_ATTR_ISOLATION_MASK]) {
 451		attr = info->attrs[BATADV_ATTR_ISOLATION_MASK];
 452
 453		bat_priv->isolation_mark_mask = nla_get_u32(attr);
 454	}
 455
 456	if (info->attrs[BATADV_ATTR_BONDING_ENABLED]) {
 457		attr = info->attrs[BATADV_ATTR_BONDING_ENABLED];
 458
 459		atomic_set(&bat_priv->bonding, !!nla_get_u8(attr));
 460	}
 461
 462#ifdef CONFIG_BATMAN_ADV_BLA
 463	if (info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]) {
 464		attr = info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED];
 465
 466		atomic_set(&bat_priv->bridge_loop_avoidance,
 467			   !!nla_get_u8(attr));
 468		batadv_bla_status_update(bat_priv->mesh_iface);
 469	}
 470#endif /* CONFIG_BATMAN_ADV_BLA */
 471
 472#ifdef CONFIG_BATMAN_ADV_DAT
 473	if (info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]) {
 474		attr = info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED];
 475
 476		atomic_set(&bat_priv->distributed_arp_table,
 477			   !!nla_get_u8(attr));
 478		batadv_dat_status_update(bat_priv->mesh_iface);
 479	}
 480#endif /* CONFIG_BATMAN_ADV_DAT */
 481
 482	if (info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED]) {
 483		attr = info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED];
 484
 485		atomic_set(&bat_priv->fragmentation, !!nla_get_u8(attr));
 486
 487		rtnl_lock();
 488		batadv_update_min_mtu(bat_priv->mesh_iface);
 489		rtnl_unlock();
 490	}
 491
 492	if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) {
 493		attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN];
 494
 495		atomic_set(&bat_priv->gw.bandwidth_down, nla_get_u32(attr));
 496		batadv_gw_tvlv_container_update(bat_priv);
 497	}
 498
 499	if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) {
 500		attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP];
 501
 502		atomic_set(&bat_priv->gw.bandwidth_up, nla_get_u32(attr));
 503		batadv_gw_tvlv_container_update(bat_priv);
 504	}
 505
 506	if (info->attrs[BATADV_ATTR_GW_MODE]) {
 507		u8 gw_mode;
 508
 509		attr = info->attrs[BATADV_ATTR_GW_MODE];
 510		gw_mode = nla_get_u8(attr);
 511
 512		if (gw_mode <= BATADV_GW_MODE_SERVER) {
 513			/* Invoking batadv_gw_reselect() is not enough to really
 514			 * de-select the current GW. It will only instruct the
 515			 * gateway client code to perform a re-election the next
 516			 * time that this is needed.
 517			 *
 518			 * When gw client mode is being switched off the current
 519			 * GW must be de-selected explicitly otherwise no GW_ADD
 520			 * uevent is thrown on client mode re-activation. This
 521			 * is operation is performed in
 522			 * batadv_gw_check_client_stop().
 523			 */
 524			batadv_gw_reselect(bat_priv);
 525
 526			/* always call batadv_gw_check_client_stop() before
 527			 * changing the gateway state
 528			 */
 529			batadv_gw_check_client_stop(bat_priv);
 530			atomic_set(&bat_priv->gw.mode, gw_mode);
 531			batadv_gw_tvlv_container_update(bat_priv);
 532		}
 533	}
 534
 535	if (info->attrs[BATADV_ATTR_GW_SEL_CLASS] &&
 536	    bat_priv->algo_ops->gw.get_best_gw_node &&
 537	    bat_priv->algo_ops->gw.is_eligible) {
 538		/* setting the GW selection class is allowed only if the routing
 539		 * algorithm in use implements the GW API
 540		 */
 541
 542		u32 sel_class_max = bat_priv->algo_ops->gw.sel_class_max;
 543		u32 sel_class;
 544
 545		attr = info->attrs[BATADV_ATTR_GW_SEL_CLASS];
 546		sel_class = nla_get_u32(attr);
 547
 548		if (sel_class >= 1 && sel_class <= sel_class_max) {
 549			atomic_set(&bat_priv->gw.sel_class, sel_class);
 550			batadv_gw_reselect(bat_priv);
 551		}
 552	}
 553
 554	if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
 555		attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
 556
 557		atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr));
 558	}
 559
 560#ifdef CONFIG_BATMAN_ADV_DEBUG
 561	if (info->attrs[BATADV_ATTR_LOG_LEVEL]) {
 562		attr = info->attrs[BATADV_ATTR_LOG_LEVEL];
 563
 564		atomic_set(&bat_priv->log_level,
 565			   nla_get_u32(attr) & BATADV_DBG_ALL);
 566	}
 567#endif /* CONFIG_BATMAN_ADV_DEBUG */
 568
 569#ifdef CONFIG_BATMAN_ADV_MCAST
 570	if (info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]) {
 571		attr = info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED];
 572
 573		atomic_set(&bat_priv->multicast_mode, !nla_get_u8(attr));
 574	}
 575
 576	if (info->attrs[BATADV_ATTR_MULTICAST_FANOUT]) {
 577		attr = info->attrs[BATADV_ATTR_MULTICAST_FANOUT];
 578
 579		atomic_set(&bat_priv->multicast_fanout, nla_get_u32(attr));
 580	}
 581#endif /* CONFIG_BATMAN_ADV_MCAST */
 582
 583	if (info->attrs[BATADV_ATTR_ORIG_INTERVAL]) {
 584		u32 orig_interval;
 585
 586		attr = info->attrs[BATADV_ATTR_ORIG_INTERVAL];
 587		orig_interval = nla_get_u32(attr);
 588
 589		orig_interval = min_t(u32, orig_interval, INT_MAX);
 590		orig_interval = max_t(u32, orig_interval, 2 * BATADV_JITTER);
 591
 592		atomic_set(&bat_priv->orig_interval, orig_interval);
 593	}
 594
 595	batadv_netlink_notify_mesh(bat_priv);
 596
 597	return 0;
 598}
 599
 600/**
 601 * batadv_netlink_tp_meter_put() - Fill information of started tp_meter session
 602 * @msg: netlink message to be sent back
 603 * @cookie: tp meter session cookie
 604 *
 605 *  Return: 0 on success, < 0 on error
 606 */
 607static int
 608batadv_netlink_tp_meter_put(struct sk_buff *msg, u32 cookie)
 609{
 610	if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie))
 611		return -ENOBUFS;
 612
 613	return 0;
 614}
 615
 616/**
 617 * batadv_netlink_tpmeter_notify() - send tp_meter result via netlink to client
 618 * @bat_priv: the bat priv with all the mesh interface information
 619 * @dst: destination of tp_meter session
 620 * @result: reason for tp meter session stop
 621 * @test_time: total time of the tp_meter session
 622 * @total_bytes: bytes acked to the receiver
 623 * @cookie: cookie of tp_meter session
 624 *
 625 * Return: 0 on success, < 0 on error
 626 */
 627int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst,
 628				  u8 result, u32 test_time, u64 total_bytes,
 629				  u32 cookie)
 630{
 631	struct sk_buff *msg;
 632	void *hdr;
 633	int ret;
 634
 635	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 636	if (!msg)
 637		return -ENOMEM;
 638
 639	hdr = genlmsg_put(msg, 0, 0, &batadv_netlink_family, 0,
 640			  BATADV_CMD_TP_METER);
 641	if (!hdr) {
 642		ret = -ENOBUFS;
 643		goto err_genlmsg;
 644	}
 645
 646	if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie))
 647		goto nla_put_failure;
 648
 649	if (nla_put_u32(msg, BATADV_ATTR_TPMETER_TEST_TIME, test_time))
 650		goto nla_put_failure;
 651
 652	if (nla_put_u64_64bit(msg, BATADV_ATTR_TPMETER_BYTES, total_bytes,
 653			      BATADV_ATTR_PAD))
 654		goto nla_put_failure;
 655
 656	if (nla_put_u8(msg, BATADV_ATTR_TPMETER_RESULT, result))
 657		goto nla_put_failure;
 658
 659	if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, dst))
 660		goto nla_put_failure;
 661
 662	genlmsg_end(msg, hdr);
 663
 664	genlmsg_multicast_netns(&batadv_netlink_family,
 665				dev_net(bat_priv->mesh_iface), msg, 0,
 666				BATADV_NL_MCGRP_TPMETER, GFP_KERNEL);
 667
 668	return 0;
 669
 670nla_put_failure:
 671	genlmsg_cancel(msg, hdr);
 672	ret = -EMSGSIZE;
 673
 674err_genlmsg:
 675	nlmsg_free(msg);
 676	return ret;
 677}
 678
 679/**
 680 * batadv_netlink_tp_meter_start() - Start a new tp_meter session
 681 * @skb: received netlink message
 682 * @info: receiver information
 683 *
 684 * Return: 0 on success, < 0 on error
 685 */
 686static int
 687batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info)
 688{
 689	struct batadv_priv *bat_priv = info->user_ptr[0];
 690	struct sk_buff *msg = NULL;
 691	u32 test_length;
 692	void *msg_head;
 693	u32 cookie;
 694	u8 *dst;
 695	int ret;
 696
 697	if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS])
 698		return -EINVAL;
 699
 700	if (!info->attrs[BATADV_ATTR_TPMETER_TEST_TIME])
 701		return -EINVAL;
 702
 703	dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]);
 704
 705	test_length = nla_get_u32(info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]);
 706
 707	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 708	if (!msg) {
 709		ret = -ENOMEM;
 710		goto out;
 711	}
 712
 713	msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq,
 714			       &batadv_netlink_family, 0,
 715			       BATADV_CMD_TP_METER);
 716	if (!msg_head) {
 717		ret = -ENOBUFS;
 718		goto out;
 719	}
 720
 721	batadv_tp_start(bat_priv, dst, test_length, &cookie);
 722
 723	ret = batadv_netlink_tp_meter_put(msg, cookie);
 724
 725 out:
 726	if (ret) {
 727		if (msg)
 728			nlmsg_free(msg);
 729		return ret;
 730	}
 731
 732	genlmsg_end(msg, msg_head);
 733	return genlmsg_reply(msg, info);
 734}
 735
 736/**
 737 * batadv_netlink_tp_meter_cancel() - Cancel a running tp_meter session
 738 * @skb: received netlink message
 739 * @info: receiver information
 740 *
 741 * Return: 0 on success, < 0 on error
 742 */
 743static int
 744batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info)
 745{
 746	struct batadv_priv *bat_priv = info->user_ptr[0];
 747	u8 *dst;
 748	int ret = 0;
 749
 750	if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS])
 751		return -EINVAL;
 752
 753	dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]);
 754
 755	batadv_tp_stop(bat_priv, dst, BATADV_TP_REASON_CANCEL);
 756
 757	return ret;
 758}
 759
 760/**
 761 * batadv_netlink_hardif_fill() - Fill message with hardif attributes
 762 * @msg: Netlink message to dump into
 763 * @bat_priv: the bat priv with all the mesh interface information
 764 * @hard_iface: hard interface which was modified
 765 * @cmd: type of message to generate
 766 * @portid: Port making netlink request
 767 * @seq: sequence number for message
 768 * @flags: Additional flags for message
 769 * @cb: Control block containing additional options
 770 *
 771 * Return: 0 on success or negative error number in case of failure
 772 */
 773static int batadv_netlink_hardif_fill(struct sk_buff *msg,
 774				      struct batadv_priv *bat_priv,
 775				      struct batadv_hard_iface *hard_iface,
 776				      enum batadv_nl_commands cmd,
 777				      u32 portid, u32 seq, int flags,
 778				      struct netlink_callback *cb)
 779{
 780	struct net_device *net_dev = hard_iface->net_dev;
 781	void *hdr;
 782
 783	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
 784	if (!hdr)
 785		return -ENOBUFS;
 786
 787	if (cb)
 788		genl_dump_check_consistent(cb, hdr);
 789
 790	if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX,
 791			bat_priv->mesh_iface->ifindex))
 792		goto nla_put_failure;
 793
 794	if (nla_put_string(msg, BATADV_ATTR_MESH_IFNAME,
 795			   bat_priv->mesh_iface->name))
 796		goto nla_put_failure;
 797
 798	if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
 799			net_dev->ifindex) ||
 800	    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
 801			   net_dev->name) ||
 802	    nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
 803		    net_dev->dev_addr))
 804		goto nla_put_failure;
 805
 806	if (hard_iface->if_status == BATADV_IF_ACTIVE) {
 807		if (nla_put_flag(msg, BATADV_ATTR_ACTIVE))
 808			goto nla_put_failure;
 809	}
 810
 811	if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
 812		       atomic_read(&hard_iface->hop_penalty)))
 813		goto nla_put_failure;
 814
 815#ifdef CONFIG_BATMAN_ADV_BATMAN_V
 816	if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL,
 817			atomic_read(&hard_iface->bat_v.elp_interval)))
 818		goto nla_put_failure;
 819
 820	if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT_OVERRIDE,
 821			atomic_read(&hard_iface->bat_v.throughput_override)))
 822		goto nla_put_failure;
 823#endif /* CONFIG_BATMAN_ADV_BATMAN_V */
 824
 825	genlmsg_end(msg, hdr);
 826	return 0;
 827
 828nla_put_failure:
 829	genlmsg_cancel(msg, hdr);
 830	return -EMSGSIZE;
 831}
 832
 833/**
 834 * batadv_netlink_notify_hardif() - send hardif attributes to listener
 835 * @bat_priv: the bat priv with all the mesh interface information
 836 * @hard_iface: hard interface which was modified
 837 *
 838 * Return: 0 on success, < 0 on error
 839 */
 840static int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv,
 841					struct batadv_hard_iface *hard_iface)
 842{
 843	struct sk_buff *msg;
 844	int ret;
 845
 846	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 847	if (!msg)
 848		return -ENOMEM;
 849
 850	ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
 851					 BATADV_CMD_SET_HARDIF, 0, 0, 0, NULL);
 852	if (ret < 0) {
 853		nlmsg_free(msg);
 854		return ret;
 855	}
 856
 857	genlmsg_multicast_netns(&batadv_netlink_family,
 858				dev_net(bat_priv->mesh_iface), msg, 0,
 859				BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
 860
 861	return 0;
 862}
 863
 864/**
 865 * batadv_netlink_cmd_get_hardif() - Get hardif attributes
 866 * @skb: Netlink message with request data
 867 * @info: receiver information
 868 *
 869 * Return: 0 on success or negative error number in case of failure
 870 */
 871static int batadv_netlink_cmd_get_hardif(struct sk_buff *skb,
 872					 struct genl_info *info)
 873{
 874	struct batadv_hard_iface *hard_iface = info->user_ptr[1];
 875	struct batadv_priv *bat_priv = info->user_ptr[0];
 876	struct sk_buff *msg;
 877	int ret;
 878
 879	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 880	if (!msg)
 881		return -ENOMEM;
 882
 883	ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
 884					 BATADV_CMD_GET_HARDIF,
 885					 info->snd_portid, info->snd_seq, 0,
 886					 NULL);
 887	if (ret < 0) {
 888		nlmsg_free(msg);
 889		return ret;
 890	}
 891
 892	ret = genlmsg_reply(msg, info);
 893
 894	return ret;
 895}
 896
 897/**
 898 * batadv_netlink_set_hardif() - Set hardif attributes
 899 * @skb: Netlink message with request data
 900 * @info: receiver information
 901 *
 902 * Return: 0 on success or negative error number in case of failure
 903 */
 904static int batadv_netlink_set_hardif(struct sk_buff *skb,
 905				     struct genl_info *info)
 906{
 907	struct batadv_hard_iface *hard_iface = info->user_ptr[1];
 908	struct batadv_priv *bat_priv = info->user_ptr[0];
 909	struct nlattr *attr;
 910
 911	if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
 912		attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
 913
 914		atomic_set(&hard_iface->hop_penalty, nla_get_u8(attr));
 915	}
 916
 917#ifdef CONFIG_BATMAN_ADV_BATMAN_V
 918
 919	if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
 920		attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
 921
 922		atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr));
 923	}
 924
 925	if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) {
 926		attr = info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE];
 927
 928		atomic_set(&hard_iface->bat_v.throughput_override,
 929			   nla_get_u32(attr));
 930	}
 931#endif /* CONFIG_BATMAN_ADV_BATMAN_V */
 932
 933	batadv_netlink_notify_hardif(bat_priv, hard_iface);
 934
 935	return 0;
 936}
 937
 938/**
 939 * batadv_netlink_dump_hardif() - Dump all hard interface into a messages
 940 * @msg: Netlink message to dump into
 941 * @cb: Parameters from query
 942 *
 943 * Return: error code, or length of reply message on success
 944 */
 945static int
 946batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
 947{
 948	struct net_device *mesh_iface;
 949	struct batadv_hard_iface *hard_iface;
 950	struct batadv_priv *bat_priv;
 951	int portid = NETLINK_CB(cb->skb).portid;
 952	int skip = cb->args[0];
 953	struct list_head *iter;
 954	int i = 0;
 955
 956	mesh_iface = batadv_netlink_get_meshif(cb);
 957	if (IS_ERR(mesh_iface))
 958		return PTR_ERR(mesh_iface);
 959
 960	bat_priv = netdev_priv(mesh_iface);
 961
 962	rtnl_lock();
 963	cb->seq = batadv_hardif_generation << 1 | 1;
 964
 965	netdev_for_each_lower_private(mesh_iface, hard_iface, iter) {
 966		if (i++ < skip)
 967			continue;
 968
 969		if (batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
 970					       BATADV_CMD_GET_HARDIF,
 971					       portid, cb->nlh->nlmsg_seq,
 972					       NLM_F_MULTI, cb)) {
 973			i--;
 974			break;
 975		}
 976	}
 977
 978	rtnl_unlock();
 979
 980	dev_put(mesh_iface);
 981
 982	cb->args[0] = i;
 983
 984	return msg->len;
 985}
 986
 987/**
 988 * batadv_netlink_vlan_fill() - Fill message with vlan attributes
 989 * @msg: Netlink message to dump into
 990 * @bat_priv: the bat priv with all the mesh interface information
 991 * @vlan: vlan which was modified
 992 * @cmd: type of message to generate
 993 * @portid: Port making netlink request
 994 * @seq: sequence number for message
 995 * @flags: Additional flags for message
 996 *
 997 * Return: 0 on success or negative error number in case of failure
 998 */
 999static int batadv_netlink_vlan_fill(struct sk_buff *msg,
1000				    struct batadv_priv *bat_priv,
1001				    struct batadv_meshif_vlan *vlan,
1002				    enum batadv_nl_commands cmd,
1003				    u32 portid, u32 seq, int flags)
1004{
1005	void *hdr;
1006
1007	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
1008	if (!hdr)
1009		return -ENOBUFS;
1010
1011	if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX,
1012			bat_priv->mesh_iface->ifindex))
1013		goto nla_put_failure;
1014
1015	if (nla_put_string(msg, BATADV_ATTR_MESH_IFNAME,
1016			   bat_priv->mesh_iface->name))
1017		goto nla_put_failure;
1018
1019	if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK))
1020		goto nla_put_failure;
1021
1022	if (nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED,
1023		       !!atomic_read(&vlan->ap_isolation)))
1024		goto nla_put_failure;
1025
1026	genlmsg_end(msg, hdr);
1027	return 0;
1028
1029nla_put_failure:
1030	genlmsg_cancel(msg, hdr);
1031	return -EMSGSIZE;
1032}
1033
1034/**
1035 * batadv_netlink_notify_vlan() - send vlan attributes to listener
1036 * @bat_priv: the bat priv with all the mesh interface information
1037 * @vlan: vlan which was modified
1038 *
1039 * Return: 0 on success, < 0 on error
1040 */
1041static int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv,
1042				      struct batadv_meshif_vlan *vlan)
1043{
1044	struct sk_buff *msg;
1045	int ret;
1046
1047	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1048	if (!msg)
1049		return -ENOMEM;
1050
1051	ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan,
1052				       BATADV_CMD_SET_VLAN, 0, 0, 0);
1053	if (ret < 0) {
1054		nlmsg_free(msg);
1055		return ret;
1056	}
1057
1058	genlmsg_multicast_netns(&batadv_netlink_family,
1059				dev_net(bat_priv->mesh_iface), msg, 0,
1060				BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
1061
1062	return 0;
1063}
1064
1065/**
1066 * batadv_netlink_get_vlan() - Get vlan attributes
1067 * @skb: Netlink message with request data
1068 * @info: receiver information
1069 *
1070 * Return: 0 on success or negative error number in case of failure
1071 */
1072static int batadv_netlink_get_vlan(struct sk_buff *skb, struct genl_info *info)
1073{
1074	struct batadv_meshif_vlan *vlan = info->user_ptr[1];
1075	struct batadv_priv *bat_priv = info->user_ptr[0];
1076	struct sk_buff *msg;
1077	int ret;
1078
1079	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1080	if (!msg)
1081		return -ENOMEM;
1082
1083	ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, BATADV_CMD_GET_VLAN,
1084				       info->snd_portid, info->snd_seq, 0);
1085	if (ret < 0) {
1086		nlmsg_free(msg);
1087		return ret;
1088	}
1089
1090	ret = genlmsg_reply(msg, info);
1091
1092	return ret;
1093}
1094
1095/**
1096 * batadv_netlink_set_vlan() - Get vlan attributes
1097 * @skb: Netlink message with request data
1098 * @info: receiver information
1099 *
1100 * Return: 0 on success or negative error number in case of failure
1101 */
1102static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info)
1103{
1104	struct batadv_meshif_vlan *vlan = info->user_ptr[1];
1105	struct batadv_priv *bat_priv = info->user_ptr[0];
1106	struct nlattr *attr;
1107
1108	if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
1109		attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED];
1110
1111		atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr));
1112	}
1113
1114	batadv_netlink_notify_vlan(bat_priv, vlan);
1115
1116	return 0;
1117}
1118
1119/**
1120 * batadv_netlink_get_meshif_from_ifindex() - Get mesh-iface from ifindex
1121 * @net: the applicable net namespace
1122 * @ifindex: index of the mesh interface
1123 *
1124 * Return: Pointer to mesh interface (with increased refcnt) on success, error
1125 *  pointer on error
1126 */
1127static struct net_device *
1128batadv_netlink_get_meshif_from_ifindex(struct net *net, int ifindex)
1129{
1130	struct net_device *mesh_iface;
1131
1132	mesh_iface = dev_get_by_index(net, ifindex);
1133	if (!mesh_iface)
1134		return ERR_PTR(-ENODEV);
1135
1136	if (!batadv_meshif_is_valid(mesh_iface))
1137		goto err_put_meshif;
1138
1139	return mesh_iface;
1140
1141err_put_meshif:
1142	dev_put(mesh_iface);
1143
1144	return ERR_PTR(-EINVAL);
1145}
1146
1147/**
1148 * batadv_netlink_get_meshif_from_info() - Get mesh-iface from genl attributes
1149 * @net: the applicable net namespace
1150 * @info: receiver information
1151 *
1152 * Return: Pointer to mesh interface (with increased refcnt) on success, error
1153 *  pointer on error
1154 */
1155static struct net_device *
1156batadv_netlink_get_meshif_from_info(struct net *net, struct genl_info *info)
1157{
1158	int ifindex;
1159
1160	if (!info->attrs[BATADV_ATTR_MESH_IFINDEX])
1161		return ERR_PTR(-EINVAL);
1162
1163	ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]);
1164
1165	return batadv_netlink_get_meshif_from_ifindex(net, ifindex);
1166}
1167
1168/**
1169 * batadv_netlink_get_meshif() - Retrieve mesh interface from netlink callback
1170 * @cb: callback structure containing arguments
1171 *
1172 * Return: Pointer to mesh interface (with increased refcnt) on success, error
1173 *  pointer on error
1174 */
1175struct net_device *batadv_netlink_get_meshif(struct netlink_callback *cb)
1176{
1177	int ifindex = batadv_netlink_get_ifindex(cb->nlh,
1178						 BATADV_ATTR_MESH_IFINDEX);
1179	if (!ifindex)
1180		return ERR_PTR(-ENONET);
1181
1182	return batadv_netlink_get_meshif_from_ifindex(sock_net(cb->skb->sk),
1183						      ifindex);
1184}
1185
1186/**
1187 * batadv_netlink_get_hardif_from_ifindex() - Get hard-iface from ifindex
1188 * @bat_priv: the bat priv with all the mesh interface information
1189 * @net: the applicable net namespace
1190 * @ifindex: index of the hard interface
1191 *
1192 * Return: Pointer to hard interface (with increased refcnt) on success, error
1193 *  pointer on error
1194 */
1195static struct batadv_hard_iface *
1196batadv_netlink_get_hardif_from_ifindex(struct batadv_priv *bat_priv,
1197				       struct net *net, int ifindex)
1198{
1199	struct batadv_hard_iface *hard_iface;
1200	struct net_device *hard_dev;
1201
1202	hard_dev = dev_get_by_index(net, ifindex);
1203	if (!hard_dev)
1204		return ERR_PTR(-ENODEV);
1205
1206	hard_iface = batadv_hardif_get_by_netdev(hard_dev);
1207	if (!hard_iface)
1208		goto err_put_harddev;
1209
1210	if (hard_iface->mesh_iface != bat_priv->mesh_iface)
1211		goto err_put_hardif;
1212
1213	/* hard_dev is referenced by hard_iface and not needed here */
1214	dev_put(hard_dev);
1215
1216	return hard_iface;
1217
1218err_put_hardif:
1219	batadv_hardif_put(hard_iface);
1220err_put_harddev:
1221	dev_put(hard_dev);
1222
1223	return ERR_PTR(-EINVAL);
1224}
1225
1226/**
1227 * batadv_netlink_get_hardif_from_info() - Get hard-iface from genl attributes
1228 * @bat_priv: the bat priv with all the mesh interface information
1229 * @net: the applicable net namespace
1230 * @info: receiver information
1231 *
1232 * Return: Pointer to hard interface (with increased refcnt) on success, error
1233 *  pointer on error
1234 */
1235static struct batadv_hard_iface *
1236batadv_netlink_get_hardif_from_info(struct batadv_priv *bat_priv,
1237				    struct net *net, struct genl_info *info)
1238{
1239	int ifindex;
1240
1241	if (!info->attrs[BATADV_ATTR_HARD_IFINDEX])
1242		return ERR_PTR(-EINVAL);
1243
1244	ifindex = nla_get_u32(info->attrs[BATADV_ATTR_HARD_IFINDEX]);
1245
1246	return batadv_netlink_get_hardif_from_ifindex(bat_priv, net, ifindex);
1247}
1248
1249/**
1250 * batadv_netlink_get_hardif() - Retrieve hard interface from netlink callback
1251 * @bat_priv: the bat priv with all the mesh interface information
1252 * @cb: callback structure containing arguments
1253 *
1254 * Return: Pointer to hard interface (with increased refcnt) on success, error
1255 *  pointer on error
1256 */
1257struct batadv_hard_iface *
1258batadv_netlink_get_hardif(struct batadv_priv *bat_priv,
1259			  struct netlink_callback *cb)
1260{
1261	int ifindex = batadv_netlink_get_ifindex(cb->nlh,
1262						 BATADV_ATTR_HARD_IFINDEX);
1263	if (!ifindex)
1264		return ERR_PTR(-ENONET);
1265
1266	return batadv_netlink_get_hardif_from_ifindex(bat_priv,
1267						      sock_net(cb->skb->sk),
1268						      ifindex);
1269}
1270
1271/**
1272 * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes
1273 * @bat_priv: the bat priv with all the mesh interface information
1274 * @net: the applicable net namespace
1275 * @info: receiver information
1276 *
1277 * Return: Pointer to vlan on success (with increased refcnt), error pointer
1278 *  on error
1279 */
1280static struct batadv_meshif_vlan *
1281batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net,
1282			  struct genl_info *info)
1283{
1284	struct batadv_meshif_vlan *vlan;
1285	u16 vid;
1286
1287	if (!info->attrs[BATADV_ATTR_VLANID])
1288		return ERR_PTR(-EINVAL);
1289
1290	vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]);
1291
1292	vlan = batadv_meshif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG);
1293	if (!vlan)
1294		return ERR_PTR(-ENOENT);
1295
1296	return vlan;
1297}
1298
1299/**
1300 * batadv_pre_doit() - Prepare batman-adv genl doit request
1301 * @ops: requested netlink operation
1302 * @skb: Netlink message with request data
1303 * @info: receiver information
1304 *
1305 * Return: 0 on success or negative error number in case of failure
1306 */
1307static int batadv_pre_doit(const struct genl_split_ops *ops,
1308			   struct sk_buff *skb,
1309			   struct genl_info *info)
1310{
1311	struct net *net = genl_info_net(info);
1312	struct batadv_hard_iface *hard_iface;
1313	struct batadv_priv *bat_priv = NULL;
1314	struct batadv_meshif_vlan *vlan;
1315	struct net_device *mesh_iface;
1316	u8 user_ptr1_flags;
1317	u8 mesh_dep_flags;
1318	int ret;
1319
1320	user_ptr1_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
1321	if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1))
1322		return -EINVAL;
1323
1324	mesh_dep_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
1325	if (WARN_ON((ops->internal_flags & mesh_dep_flags) &&
1326		    (~ops->internal_flags & BATADV_FLAG_NEED_MESH)))
1327		return -EINVAL;
1328
1329	if (ops->internal_flags & BATADV_FLAG_NEED_MESH) {
1330		mesh_iface = batadv_netlink_get_meshif_from_info(net, info);
1331		if (IS_ERR(mesh_iface))
1332			return PTR_ERR(mesh_iface);
1333
1334		bat_priv = netdev_priv(mesh_iface);
1335		info->user_ptr[0] = bat_priv;
1336	}
1337
1338	if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF) {
1339		hard_iface = batadv_netlink_get_hardif_from_info(bat_priv, net,
1340								 info);
1341		if (IS_ERR(hard_iface)) {
1342			ret = PTR_ERR(hard_iface);
1343			goto err_put_meshif;
1344		}
1345
1346		info->user_ptr[1] = hard_iface;
1347	}
1348
1349	if (ops->internal_flags & BATADV_FLAG_NEED_VLAN) {
1350		vlan = batadv_get_vlan_from_info(bat_priv, net, info);
1351		if (IS_ERR(vlan)) {
1352			ret = PTR_ERR(vlan);
1353			goto err_put_meshif;
1354		}
1355
1356		info->user_ptr[1] = vlan;
1357	}
1358
1359	return 0;
1360
1361err_put_meshif:
1362	if (bat_priv)
1363		dev_put(bat_priv->mesh_iface);
1364
1365	return ret;
1366}
1367
1368/**
1369 * batadv_post_doit() - End batman-adv genl doit request
1370 * @ops: requested netlink operation
1371 * @skb: Netlink message with request data
1372 * @info: receiver information
1373 */
1374static void batadv_post_doit(const struct genl_split_ops *ops,
1375			     struct sk_buff *skb,
1376			     struct genl_info *info)
1377{
1378	struct batadv_hard_iface *hard_iface;
1379	struct batadv_meshif_vlan *vlan;
1380	struct batadv_priv *bat_priv;
1381
1382	if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF &&
1383	    info->user_ptr[1]) {
1384		hard_iface = info->user_ptr[1];
1385
1386		batadv_hardif_put(hard_iface);
1387	}
1388
1389	if (ops->internal_flags & BATADV_FLAG_NEED_VLAN && info->user_ptr[1]) {
1390		vlan = info->user_ptr[1];
1391		batadv_meshif_vlan_put(vlan);
1392	}
1393
1394	if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) {
1395		bat_priv = info->user_ptr[0];
1396		dev_put(bat_priv->mesh_iface);
1397	}
1398}
1399
1400static const struct genl_small_ops batadv_netlink_ops[] = {
1401	{
1402		.cmd = BATADV_CMD_GET_MESH,
1403		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1404		/* can be retrieved by unprivileged users */
1405		.doit = batadv_netlink_get_mesh,
1406		.internal_flags = BATADV_FLAG_NEED_MESH,
1407	},
1408	{
1409		.cmd = BATADV_CMD_TP_METER,
1410		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1411		.flags = GENL_UNS_ADMIN_PERM,
1412		.doit = batadv_netlink_tp_meter_start,
1413		.internal_flags = BATADV_FLAG_NEED_MESH,
1414	},
1415	{
1416		.cmd = BATADV_CMD_TP_METER_CANCEL,
1417		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1418		.flags = GENL_UNS_ADMIN_PERM,
1419		.doit = batadv_netlink_tp_meter_cancel,
1420		.internal_flags = BATADV_FLAG_NEED_MESH,
1421	},
1422	{
1423		.cmd = BATADV_CMD_GET_ROUTING_ALGOS,
1424		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1425		.flags = GENL_UNS_ADMIN_PERM,
1426		.dumpit = batadv_algo_dump,
1427	},
1428	{
1429		.cmd = BATADV_CMD_GET_HARDIF,
1430		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1431		/* can be retrieved by unprivileged users */
1432		.dumpit = batadv_netlink_dump_hardif,
1433		.doit = batadv_netlink_cmd_get_hardif,
1434		.internal_flags = BATADV_FLAG_NEED_MESH |
1435				  BATADV_FLAG_NEED_HARDIF,
1436	},
1437	{
1438		.cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL,
1439		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1440		.flags = GENL_UNS_ADMIN_PERM,
1441		.dumpit = batadv_tt_local_dump,
1442	},
1443	{
1444		.cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL,
1445		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1446		.flags = GENL_UNS_ADMIN_PERM,
1447		.dumpit = batadv_tt_global_dump,
1448	},
1449	{
1450		.cmd = BATADV_CMD_GET_ORIGINATORS,
1451		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1452		.flags = GENL_UNS_ADMIN_PERM,
1453		.dumpit = batadv_orig_dump,
1454	},
1455	{
1456		.cmd = BATADV_CMD_GET_NEIGHBORS,
1457		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1458		.flags = GENL_UNS_ADMIN_PERM,
1459		.dumpit = batadv_hardif_neigh_dump,
1460	},
1461	{
1462		.cmd = BATADV_CMD_GET_GATEWAYS,
1463		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1464		.flags = GENL_UNS_ADMIN_PERM,
1465		.dumpit = batadv_gw_dump,
1466	},
1467	{
1468		.cmd = BATADV_CMD_GET_BLA_CLAIM,
1469		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1470		.flags = GENL_UNS_ADMIN_PERM,
1471		.dumpit = batadv_bla_claim_dump,
1472	},
1473	{
1474		.cmd = BATADV_CMD_GET_BLA_BACKBONE,
1475		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1476		.flags = GENL_UNS_ADMIN_PERM,
1477		.dumpit = batadv_bla_backbone_dump,
1478	},
1479	{
1480		.cmd = BATADV_CMD_GET_DAT_CACHE,
1481		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1482		.flags = GENL_UNS_ADMIN_PERM,
1483		.dumpit = batadv_dat_cache_dump,
1484	},
1485	{
1486		.cmd = BATADV_CMD_GET_MCAST_FLAGS,
1487		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1488		.flags = GENL_UNS_ADMIN_PERM,
1489		.dumpit = batadv_mcast_flags_dump,
1490	},
1491	{
1492		.cmd = BATADV_CMD_SET_MESH,
1493		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1494		.flags = GENL_UNS_ADMIN_PERM,
1495		.doit = batadv_netlink_set_mesh,
1496		.internal_flags = BATADV_FLAG_NEED_MESH,
1497	},
1498	{
1499		.cmd = BATADV_CMD_SET_HARDIF,
1500		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1501		.flags = GENL_UNS_ADMIN_PERM,
1502		.doit = batadv_netlink_set_hardif,
1503		.internal_flags = BATADV_FLAG_NEED_MESH |
1504				  BATADV_FLAG_NEED_HARDIF,
1505	},
1506	{
1507		.cmd = BATADV_CMD_GET_VLAN,
1508		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1509		/* can be retrieved by unprivileged users */
1510		.doit = batadv_netlink_get_vlan,
1511		.internal_flags = BATADV_FLAG_NEED_MESH |
1512				  BATADV_FLAG_NEED_VLAN,
1513	},
1514	{
1515		.cmd = BATADV_CMD_SET_VLAN,
1516		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1517		.flags = GENL_UNS_ADMIN_PERM,
1518		.doit = batadv_netlink_set_vlan,
1519		.internal_flags = BATADV_FLAG_NEED_MESH |
1520				  BATADV_FLAG_NEED_VLAN,
1521	},
1522};
1523
1524struct genl_family batadv_netlink_family __ro_after_init = {
1525	.hdrsize = 0,
1526	.name = BATADV_NL_NAME,
1527	.version = 1,
1528	.maxattr = BATADV_ATTR_MAX,
1529	.policy = batadv_netlink_policy,
1530	.netnsok = true,
1531	.pre_doit = batadv_pre_doit,
1532	.post_doit = batadv_post_doit,
1533	.module = THIS_MODULE,
1534	.small_ops = batadv_netlink_ops,
1535	.n_small_ops = ARRAY_SIZE(batadv_netlink_ops),
1536	.resv_start_op = BATADV_CMD_SET_VLAN + 1,
1537	.mcgrps = batadv_netlink_mcgrps,
1538	.n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps),
1539};
1540
1541/**
1542 * batadv_netlink_register() - register batadv genl netlink family
1543 */
1544void __init batadv_netlink_register(void)
1545{
1546	int ret;
1547
1548	ret = genl_register_family(&batadv_netlink_family);
1549	if (ret)
1550		pr_warn("unable to register netlink family\n");
1551}
1552
1553/**
1554 * batadv_netlink_unregister() - unregister batadv genl netlink family
1555 */
1556void batadv_netlink_unregister(void)
1557{
1558	genl_unregister_family(&batadv_netlink_family);
1559}
~/ Read-only file preview.