cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

netlink.c (42224B)


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