18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (C) 2016-2020  B.A.T.M.A.N. contributors:
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Matthias Schiffer
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "netlink.h"
88c2ecf20Sopenharmony_ci#include "main.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/atomic.h>
118c2ecf20Sopenharmony_ci#include <linux/bitops.h>
128c2ecf20Sopenharmony_ci#include <linux/bug.h>
138c2ecf20Sopenharmony_ci#include <linux/byteorder/generic.h>
148c2ecf20Sopenharmony_ci#include <linux/cache.h>
158c2ecf20Sopenharmony_ci#include <linux/err.h>
168c2ecf20Sopenharmony_ci#include <linux/errno.h>
178c2ecf20Sopenharmony_ci#include <linux/export.h>
188c2ecf20Sopenharmony_ci#include <linux/genetlink.h>
198c2ecf20Sopenharmony_ci#include <linux/gfp.h>
208c2ecf20Sopenharmony_ci#include <linux/if_ether.h>
218c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
228c2ecf20Sopenharmony_ci#include <linux/init.h>
238c2ecf20Sopenharmony_ci#include <linux/kernel.h>
248c2ecf20Sopenharmony_ci#include <linux/limits.h>
258c2ecf20Sopenharmony_ci#include <linux/list.h>
268c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
278c2ecf20Sopenharmony_ci#include <linux/netlink.h>
288c2ecf20Sopenharmony_ci#include <linux/printk.h>
298c2ecf20Sopenharmony_ci#include <linux/rtnetlink.h>
308c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
318c2ecf20Sopenharmony_ci#include <linux/stddef.h>
328c2ecf20Sopenharmony_ci#include <linux/types.h>
338c2ecf20Sopenharmony_ci#include <net/genetlink.h>
348c2ecf20Sopenharmony_ci#include <net/net_namespace.h>
358c2ecf20Sopenharmony_ci#include <net/netlink.h>
368c2ecf20Sopenharmony_ci#include <net/sock.h>
378c2ecf20Sopenharmony_ci#include <uapi/linux/batadv_packet.h>
388c2ecf20Sopenharmony_ci#include <uapi/linux/batman_adv.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#include "bat_algo.h"
418c2ecf20Sopenharmony_ci#include "bridge_loop_avoidance.h"
428c2ecf20Sopenharmony_ci#include "distributed-arp-table.h"
438c2ecf20Sopenharmony_ci#include "gateway_client.h"
448c2ecf20Sopenharmony_ci#include "gateway_common.h"
458c2ecf20Sopenharmony_ci#include "hard-interface.h"
468c2ecf20Sopenharmony_ci#include "log.h"
478c2ecf20Sopenharmony_ci#include "multicast.h"
488c2ecf20Sopenharmony_ci#include "network-coding.h"
498c2ecf20Sopenharmony_ci#include "originator.h"
508c2ecf20Sopenharmony_ci#include "soft-interface.h"
518c2ecf20Sopenharmony_ci#include "tp_meter.h"
528c2ecf20Sopenharmony_ci#include "translation-table.h"
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistruct genl_family batadv_netlink_family;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* multicast groups */
578c2ecf20Sopenharmony_cienum batadv_netlink_multicast_groups {
588c2ecf20Sopenharmony_ci	BATADV_NL_MCGRP_CONFIG,
598c2ecf20Sopenharmony_ci	BATADV_NL_MCGRP_TPMETER,
608c2ecf20Sopenharmony_ci};
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/**
638c2ecf20Sopenharmony_ci * enum batadv_genl_ops_flags - flags for genl_ops's internal_flags
648c2ecf20Sopenharmony_ci */
658c2ecf20Sopenharmony_cienum batadv_genl_ops_flags {
668c2ecf20Sopenharmony_ci	/**
678c2ecf20Sopenharmony_ci	 * @BATADV_FLAG_NEED_MESH: request requires valid soft interface in
688c2ecf20Sopenharmony_ci	 *  attribute BATADV_ATTR_MESH_IFINDEX and expects a pointer to it to be
698c2ecf20Sopenharmony_ci	 *  saved in info->user_ptr[0]
708c2ecf20Sopenharmony_ci	 */
718c2ecf20Sopenharmony_ci	BATADV_FLAG_NEED_MESH = BIT(0),
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	/**
748c2ecf20Sopenharmony_ci	 * @BATADV_FLAG_NEED_HARDIF: request requires valid hard interface in
758c2ecf20Sopenharmony_ci	 *  attribute BATADV_ATTR_HARD_IFINDEX and expects a pointer to it to be
768c2ecf20Sopenharmony_ci	 *  saved in info->user_ptr[1]
778c2ecf20Sopenharmony_ci	 */
788c2ecf20Sopenharmony_ci	BATADV_FLAG_NEED_HARDIF = BIT(1),
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/**
818c2ecf20Sopenharmony_ci	 * @BATADV_FLAG_NEED_VLAN: request requires valid vlan in
828c2ecf20Sopenharmony_ci	 *  attribute BATADV_ATTR_VLANID and expects a pointer to it to be
838c2ecf20Sopenharmony_ci	 *  saved in info->user_ptr[1]
848c2ecf20Sopenharmony_ci	 */
858c2ecf20Sopenharmony_ci	BATADV_FLAG_NEED_VLAN = BIT(2),
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistatic const struct genl_multicast_group batadv_netlink_mcgrps[] = {
898c2ecf20Sopenharmony_ci	[BATADV_NL_MCGRP_CONFIG] = { .name = BATADV_NL_MCAST_GROUP_CONFIG },
908c2ecf20Sopenharmony_ci	[BATADV_NL_MCGRP_TPMETER] = { .name = BATADV_NL_MCAST_GROUP_TPMETER },
918c2ecf20Sopenharmony_ci};
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
948c2ecf20Sopenharmony_ci	[BATADV_ATTR_VERSION]			= { .type = NLA_STRING },
958c2ecf20Sopenharmony_ci	[BATADV_ATTR_ALGO_NAME]			= { .type = NLA_STRING },
968c2ecf20Sopenharmony_ci	[BATADV_ATTR_MESH_IFINDEX]		= { .type = NLA_U32 },
978c2ecf20Sopenharmony_ci	[BATADV_ATTR_MESH_IFNAME]		= { .type = NLA_STRING },
988c2ecf20Sopenharmony_ci	[BATADV_ATTR_MESH_ADDRESS]		= { .len = ETH_ALEN },
998c2ecf20Sopenharmony_ci	[BATADV_ATTR_HARD_IFINDEX]		= { .type = NLA_U32 },
1008c2ecf20Sopenharmony_ci	[BATADV_ATTR_HARD_IFNAME]		= { .type = NLA_STRING },
1018c2ecf20Sopenharmony_ci	[BATADV_ATTR_HARD_ADDRESS]		= { .len = ETH_ALEN },
1028c2ecf20Sopenharmony_ci	[BATADV_ATTR_ORIG_ADDRESS]		= { .len = ETH_ALEN },
1038c2ecf20Sopenharmony_ci	[BATADV_ATTR_TPMETER_RESULT]		= { .type = NLA_U8 },
1048c2ecf20Sopenharmony_ci	[BATADV_ATTR_TPMETER_TEST_TIME]		= { .type = NLA_U32 },
1058c2ecf20Sopenharmony_ci	[BATADV_ATTR_TPMETER_BYTES]		= { .type = NLA_U64 },
1068c2ecf20Sopenharmony_ci	[BATADV_ATTR_TPMETER_COOKIE]		= { .type = NLA_U32 },
1078c2ecf20Sopenharmony_ci	[BATADV_ATTR_ACTIVE]			= { .type = NLA_FLAG },
1088c2ecf20Sopenharmony_ci	[BATADV_ATTR_TT_ADDRESS]		= { .len = ETH_ALEN },
1098c2ecf20Sopenharmony_ci	[BATADV_ATTR_TT_TTVN]			= { .type = NLA_U8 },
1108c2ecf20Sopenharmony_ci	[BATADV_ATTR_TT_LAST_TTVN]		= { .type = NLA_U8 },
1118c2ecf20Sopenharmony_ci	[BATADV_ATTR_TT_CRC32]			= { .type = NLA_U32 },
1128c2ecf20Sopenharmony_ci	[BATADV_ATTR_TT_VID]			= { .type = NLA_U16 },
1138c2ecf20Sopenharmony_ci	[BATADV_ATTR_TT_FLAGS]			= { .type = NLA_U32 },
1148c2ecf20Sopenharmony_ci	[BATADV_ATTR_FLAG_BEST]			= { .type = NLA_FLAG },
1158c2ecf20Sopenharmony_ci	[BATADV_ATTR_LAST_SEEN_MSECS]		= { .type = NLA_U32 },
1168c2ecf20Sopenharmony_ci	[BATADV_ATTR_NEIGH_ADDRESS]		= { .len = ETH_ALEN },
1178c2ecf20Sopenharmony_ci	[BATADV_ATTR_TQ]			= { .type = NLA_U8 },
1188c2ecf20Sopenharmony_ci	[BATADV_ATTR_THROUGHPUT]		= { .type = NLA_U32 },
1198c2ecf20Sopenharmony_ci	[BATADV_ATTR_BANDWIDTH_UP]		= { .type = NLA_U32 },
1208c2ecf20Sopenharmony_ci	[BATADV_ATTR_BANDWIDTH_DOWN]		= { .type = NLA_U32 },
1218c2ecf20Sopenharmony_ci	[BATADV_ATTR_ROUTER]			= { .len = ETH_ALEN },
1228c2ecf20Sopenharmony_ci	[BATADV_ATTR_BLA_OWN]			= { .type = NLA_FLAG },
1238c2ecf20Sopenharmony_ci	[BATADV_ATTR_BLA_ADDRESS]		= { .len = ETH_ALEN },
1248c2ecf20Sopenharmony_ci	[BATADV_ATTR_BLA_VID]			= { .type = NLA_U16 },
1258c2ecf20Sopenharmony_ci	[BATADV_ATTR_BLA_BACKBONE]		= { .len = ETH_ALEN },
1268c2ecf20Sopenharmony_ci	[BATADV_ATTR_BLA_CRC]			= { .type = NLA_U16 },
1278c2ecf20Sopenharmony_ci	[BATADV_ATTR_DAT_CACHE_IP4ADDRESS]	= { .type = NLA_U32 },
1288c2ecf20Sopenharmony_ci	[BATADV_ATTR_DAT_CACHE_HWADDRESS]	= { .len = ETH_ALEN },
1298c2ecf20Sopenharmony_ci	[BATADV_ATTR_DAT_CACHE_VID]		= { .type = NLA_U16 },
1308c2ecf20Sopenharmony_ci	[BATADV_ATTR_MCAST_FLAGS]		= { .type = NLA_U32 },
1318c2ecf20Sopenharmony_ci	[BATADV_ATTR_MCAST_FLAGS_PRIV]		= { .type = NLA_U32 },
1328c2ecf20Sopenharmony_ci	[BATADV_ATTR_VLANID]			= { .type = NLA_U16 },
1338c2ecf20Sopenharmony_ci	[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]	= { .type = NLA_U8 },
1348c2ecf20Sopenharmony_ci	[BATADV_ATTR_AP_ISOLATION_ENABLED]	= { .type = NLA_U8 },
1358c2ecf20Sopenharmony_ci	[BATADV_ATTR_ISOLATION_MARK]		= { .type = NLA_U32 },
1368c2ecf20Sopenharmony_ci	[BATADV_ATTR_ISOLATION_MASK]		= { .type = NLA_U32 },
1378c2ecf20Sopenharmony_ci	[BATADV_ATTR_BONDING_ENABLED]		= { .type = NLA_U8 },
1388c2ecf20Sopenharmony_ci	[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]	= { .type = NLA_U8 },
1398c2ecf20Sopenharmony_ci	[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]	= { .type = NLA_U8 },
1408c2ecf20Sopenharmony_ci	[BATADV_ATTR_FRAGMENTATION_ENABLED]	= { .type = NLA_U8 },
1418c2ecf20Sopenharmony_ci	[BATADV_ATTR_GW_BANDWIDTH_DOWN]		= { .type = NLA_U32 },
1428c2ecf20Sopenharmony_ci	[BATADV_ATTR_GW_BANDWIDTH_UP]		= { .type = NLA_U32 },
1438c2ecf20Sopenharmony_ci	[BATADV_ATTR_GW_MODE]			= { .type = NLA_U8 },
1448c2ecf20Sopenharmony_ci	[BATADV_ATTR_GW_SEL_CLASS]		= { .type = NLA_U32 },
1458c2ecf20Sopenharmony_ci	[BATADV_ATTR_HOP_PENALTY]		= { .type = NLA_U8 },
1468c2ecf20Sopenharmony_ci	[BATADV_ATTR_LOG_LEVEL]			= { .type = NLA_U32 },
1478c2ecf20Sopenharmony_ci	[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]	= { .type = NLA_U8 },
1488c2ecf20Sopenharmony_ci	[BATADV_ATTR_MULTICAST_FANOUT]		= { .type = NLA_U32 },
1498c2ecf20Sopenharmony_ci	[BATADV_ATTR_NETWORK_CODING_ENABLED]	= { .type = NLA_U8 },
1508c2ecf20Sopenharmony_ci	[BATADV_ATTR_ORIG_INTERVAL]		= { .type = NLA_U32 },
1518c2ecf20Sopenharmony_ci	[BATADV_ATTR_ELP_INTERVAL]		= { .type = NLA_U32 },
1528c2ecf20Sopenharmony_ci	[BATADV_ATTR_THROUGHPUT_OVERRIDE]	= { .type = NLA_U32 },
1538c2ecf20Sopenharmony_ci};
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/**
1568c2ecf20Sopenharmony_ci * batadv_netlink_get_ifindex() - Extract an interface index from a message
1578c2ecf20Sopenharmony_ci * @nlh: Message header
1588c2ecf20Sopenharmony_ci * @attrtype: Attribute which holds an interface index
1598c2ecf20Sopenharmony_ci *
1608c2ecf20Sopenharmony_ci * Return: interface index, or 0.
1618c2ecf20Sopenharmony_ci */
1628c2ecf20Sopenharmony_ciint
1638c2ecf20Sopenharmony_cibatadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	return (attr && nla_len(attr) == sizeof(u32)) ? nla_get_u32(attr) : 0;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci/**
1718c2ecf20Sopenharmony_ci * batadv_netlink_mesh_fill_ap_isolation() - Add ap_isolation softif attribute
1728c2ecf20Sopenharmony_ci * @msg: Netlink message to dump into
1738c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
1748c2ecf20Sopenharmony_ci *
1758c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
1768c2ecf20Sopenharmony_ci */
1778c2ecf20Sopenharmony_cistatic int batadv_netlink_mesh_fill_ap_isolation(struct sk_buff *msg,
1788c2ecf20Sopenharmony_ci						 struct batadv_priv *bat_priv)
1798c2ecf20Sopenharmony_ci{
1808c2ecf20Sopenharmony_ci	struct batadv_softif_vlan *vlan;
1818c2ecf20Sopenharmony_ci	u8 ap_isolation;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS);
1848c2ecf20Sopenharmony_ci	if (!vlan)
1858c2ecf20Sopenharmony_ci		return 0;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	ap_isolation = atomic_read(&vlan->ap_isolation);
1888c2ecf20Sopenharmony_ci	batadv_softif_vlan_put(vlan);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	return nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED,
1918c2ecf20Sopenharmony_ci			  !!ap_isolation);
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci/**
1958c2ecf20Sopenharmony_ci * batadv_option_set_ap_isolation() - Set ap_isolation from genl msg
1968c2ecf20Sopenharmony_ci * @attr: parsed BATADV_ATTR_AP_ISOLATION_ENABLED attribute
1978c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
1988c2ecf20Sopenharmony_ci *
1998c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
2008c2ecf20Sopenharmony_ci */
2018c2ecf20Sopenharmony_cistatic int batadv_netlink_set_mesh_ap_isolation(struct nlattr *attr,
2028c2ecf20Sopenharmony_ci						struct batadv_priv *bat_priv)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	struct batadv_softif_vlan *vlan;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	vlan = batadv_softif_vlan_get(bat_priv, BATADV_NO_FLAGS);
2078c2ecf20Sopenharmony_ci	if (!vlan)
2088c2ecf20Sopenharmony_ci		return -ENOENT;
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr));
2118c2ecf20Sopenharmony_ci	batadv_softif_vlan_put(vlan);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	return 0;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci/**
2178c2ecf20Sopenharmony_ci * batadv_netlink_mesh_fill() - Fill message with mesh attributes
2188c2ecf20Sopenharmony_ci * @msg: Netlink message to dump into
2198c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
2208c2ecf20Sopenharmony_ci * @cmd: type of message to generate
2218c2ecf20Sopenharmony_ci * @portid: Port making netlink request
2228c2ecf20Sopenharmony_ci * @seq: sequence number for message
2238c2ecf20Sopenharmony_ci * @flags: Additional flags for message
2248c2ecf20Sopenharmony_ci *
2258c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
2268c2ecf20Sopenharmony_ci */
2278c2ecf20Sopenharmony_cistatic int batadv_netlink_mesh_fill(struct sk_buff *msg,
2288c2ecf20Sopenharmony_ci				    struct batadv_priv *bat_priv,
2298c2ecf20Sopenharmony_ci				    enum batadv_nl_commands cmd,
2308c2ecf20Sopenharmony_ci				    u32 portid, u32 seq, int flags)
2318c2ecf20Sopenharmony_ci{
2328c2ecf20Sopenharmony_ci	struct net_device *soft_iface = bat_priv->soft_iface;
2338c2ecf20Sopenharmony_ci	struct batadv_hard_iface *primary_if = NULL;
2348c2ecf20Sopenharmony_ci	struct net_device *hard_iface;
2358c2ecf20Sopenharmony_ci	void *hdr;
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
2388c2ecf20Sopenharmony_ci	if (!hdr)
2398c2ecf20Sopenharmony_ci		return -ENOBUFS;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	if (nla_put_string(msg, BATADV_ATTR_VERSION, BATADV_SOURCE_VERSION) ||
2428c2ecf20Sopenharmony_ci	    nla_put_string(msg, BATADV_ATTR_ALGO_NAME,
2438c2ecf20Sopenharmony_ci			   bat_priv->algo_ops->name) ||
2448c2ecf20Sopenharmony_ci	    nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, soft_iface->ifindex) ||
2458c2ecf20Sopenharmony_ci	    nla_put_string(msg, BATADV_ATTR_MESH_IFNAME, soft_iface->name) ||
2468c2ecf20Sopenharmony_ci	    nla_put(msg, BATADV_ATTR_MESH_ADDRESS, ETH_ALEN,
2478c2ecf20Sopenharmony_ci		    soft_iface->dev_addr) ||
2488c2ecf20Sopenharmony_ci	    nla_put_u8(msg, BATADV_ATTR_TT_TTVN,
2498c2ecf20Sopenharmony_ci		       (u8)atomic_read(&bat_priv->tt.vn)))
2508c2ecf20Sopenharmony_ci		goto nla_put_failure;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_BLA
2538c2ecf20Sopenharmony_ci	if (nla_put_u16(msg, BATADV_ATTR_BLA_CRC,
2548c2ecf20Sopenharmony_ci			ntohs(bat_priv->bla.claim_dest.group)))
2558c2ecf20Sopenharmony_ci		goto nla_put_failure;
2568c2ecf20Sopenharmony_ci#endif
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	if (batadv_mcast_mesh_info_put(msg, bat_priv))
2598c2ecf20Sopenharmony_ci		goto nla_put_failure;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	primary_if = batadv_primary_if_get_selected(bat_priv);
2628c2ecf20Sopenharmony_ci	if (primary_if && primary_if->if_status == BATADV_IF_ACTIVE) {
2638c2ecf20Sopenharmony_ci		hard_iface = primary_if->net_dev;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci		if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
2668c2ecf20Sopenharmony_ci				hard_iface->ifindex) ||
2678c2ecf20Sopenharmony_ci		    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
2688c2ecf20Sopenharmony_ci				   hard_iface->name) ||
2698c2ecf20Sopenharmony_ci		    nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
2708c2ecf20Sopenharmony_ci			    hard_iface->dev_addr))
2718c2ecf20Sopenharmony_ci			goto nla_put_failure;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_AGGREGATED_OGMS_ENABLED,
2758c2ecf20Sopenharmony_ci		       !!atomic_read(&bat_priv->aggregated_ogms)))
2768c2ecf20Sopenharmony_ci		goto nla_put_failure;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	if (batadv_netlink_mesh_fill_ap_isolation(msg, bat_priv))
2798c2ecf20Sopenharmony_ci		goto nla_put_failure;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MARK,
2828c2ecf20Sopenharmony_ci			bat_priv->isolation_mark))
2838c2ecf20Sopenharmony_ci		goto nla_put_failure;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_ISOLATION_MASK,
2868c2ecf20Sopenharmony_ci			bat_priv->isolation_mark_mask))
2878c2ecf20Sopenharmony_ci		goto nla_put_failure;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_BONDING_ENABLED,
2908c2ecf20Sopenharmony_ci		       !!atomic_read(&bat_priv->bonding)))
2918c2ecf20Sopenharmony_ci		goto nla_put_failure;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_BLA
2948c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED,
2958c2ecf20Sopenharmony_ci		       !!atomic_read(&bat_priv->bridge_loop_avoidance)))
2968c2ecf20Sopenharmony_ci		goto nla_put_failure;
2978c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_BLA */
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_DAT
3008c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED,
3018c2ecf20Sopenharmony_ci		       !!atomic_read(&bat_priv->distributed_arp_table)))
3028c2ecf20Sopenharmony_ci		goto nla_put_failure;
3038c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_DAT */
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION_ENABLED,
3068c2ecf20Sopenharmony_ci		       !!atomic_read(&bat_priv->fragmentation)))
3078c2ecf20Sopenharmony_ci		goto nla_put_failure;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_DOWN,
3108c2ecf20Sopenharmony_ci			atomic_read(&bat_priv->gw.bandwidth_down)))
3118c2ecf20Sopenharmony_ci		goto nla_put_failure;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_UP,
3148c2ecf20Sopenharmony_ci			atomic_read(&bat_priv->gw.bandwidth_up)))
3158c2ecf20Sopenharmony_ci		goto nla_put_failure;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_GW_MODE,
3188c2ecf20Sopenharmony_ci		       atomic_read(&bat_priv->gw.mode)))
3198c2ecf20Sopenharmony_ci		goto nla_put_failure;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	if (bat_priv->algo_ops->gw.get_best_gw_node &&
3228c2ecf20Sopenharmony_ci	    bat_priv->algo_ops->gw.is_eligible) {
3238c2ecf20Sopenharmony_ci		/* GW selection class is not available if the routing algorithm
3248c2ecf20Sopenharmony_ci		 * in use does not implement the GW API
3258c2ecf20Sopenharmony_ci		 */
3268c2ecf20Sopenharmony_ci		if (nla_put_u32(msg, BATADV_ATTR_GW_SEL_CLASS,
3278c2ecf20Sopenharmony_ci				atomic_read(&bat_priv->gw.sel_class)))
3288c2ecf20Sopenharmony_ci			goto nla_put_failure;
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
3328c2ecf20Sopenharmony_ci		       atomic_read(&bat_priv->hop_penalty)))
3338c2ecf20Sopenharmony_ci		goto nla_put_failure;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_DEBUG
3368c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_LOG_LEVEL,
3378c2ecf20Sopenharmony_ci			atomic_read(&bat_priv->log_level)))
3388c2ecf20Sopenharmony_ci		goto nla_put_failure;
3398c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_DEBUG */
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_MCAST
3428c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED,
3438c2ecf20Sopenharmony_ci		       !atomic_read(&bat_priv->multicast_mode)))
3448c2ecf20Sopenharmony_ci		goto nla_put_failure;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_MULTICAST_FANOUT,
3478c2ecf20Sopenharmony_ci			atomic_read(&bat_priv->multicast_fanout)))
3488c2ecf20Sopenharmony_ci		goto nla_put_failure;
3498c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_MCAST */
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_NC
3528c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_NETWORK_CODING_ENABLED,
3538c2ecf20Sopenharmony_ci		       !!atomic_read(&bat_priv->network_coding)))
3548c2ecf20Sopenharmony_ci		goto nla_put_failure;
3558c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_NC */
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_ORIG_INTERVAL,
3588c2ecf20Sopenharmony_ci			atomic_read(&bat_priv->orig_interval)))
3598c2ecf20Sopenharmony_ci		goto nla_put_failure;
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	if (primary_if)
3628c2ecf20Sopenharmony_ci		batadv_hardif_put(primary_if);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	genlmsg_end(msg, hdr);
3658c2ecf20Sopenharmony_ci	return 0;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cinla_put_failure:
3688c2ecf20Sopenharmony_ci	if (primary_if)
3698c2ecf20Sopenharmony_ci		batadv_hardif_put(primary_if);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	genlmsg_cancel(msg, hdr);
3728c2ecf20Sopenharmony_ci	return -EMSGSIZE;
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci/**
3768c2ecf20Sopenharmony_ci * batadv_netlink_notify_mesh() - send softif attributes to listener
3778c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
3788c2ecf20Sopenharmony_ci *
3798c2ecf20Sopenharmony_ci * Return: 0 on success, < 0 on error
3808c2ecf20Sopenharmony_ci */
3818c2ecf20Sopenharmony_ciint batadv_netlink_notify_mesh(struct batadv_priv *bat_priv)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	struct sk_buff *msg;
3848c2ecf20Sopenharmony_ci	int ret;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3878c2ecf20Sopenharmony_ci	if (!msg)
3888c2ecf20Sopenharmony_ci		return -ENOMEM;
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_SET_MESH,
3918c2ecf20Sopenharmony_ci				       0, 0, 0);
3928c2ecf20Sopenharmony_ci	if (ret < 0) {
3938c2ecf20Sopenharmony_ci		nlmsg_free(msg);
3948c2ecf20Sopenharmony_ci		return ret;
3958c2ecf20Sopenharmony_ci	}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	genlmsg_multicast_netns(&batadv_netlink_family,
3988c2ecf20Sopenharmony_ci				dev_net(bat_priv->soft_iface), msg, 0,
3998c2ecf20Sopenharmony_ci				BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci	return 0;
4028c2ecf20Sopenharmony_ci}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci/**
4058c2ecf20Sopenharmony_ci * batadv_netlink_get_mesh() - Get softif attributes
4068c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
4078c2ecf20Sopenharmony_ci * @info: receiver information
4088c2ecf20Sopenharmony_ci *
4098c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
4108c2ecf20Sopenharmony_ci */
4118c2ecf20Sopenharmony_cistatic int batadv_netlink_get_mesh(struct sk_buff *skb, struct genl_info *info)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
4148c2ecf20Sopenharmony_ci	struct sk_buff *msg;
4158c2ecf20Sopenharmony_ci	int ret;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4188c2ecf20Sopenharmony_ci	if (!msg)
4198c2ecf20Sopenharmony_ci		return -ENOMEM;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	ret = batadv_netlink_mesh_fill(msg, bat_priv, BATADV_CMD_GET_MESH,
4228c2ecf20Sopenharmony_ci				       info->snd_portid, info->snd_seq, 0);
4238c2ecf20Sopenharmony_ci	if (ret < 0) {
4248c2ecf20Sopenharmony_ci		nlmsg_free(msg);
4258c2ecf20Sopenharmony_ci		return ret;
4268c2ecf20Sopenharmony_ci	}
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	ret = genlmsg_reply(msg, info);
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	return ret;
4318c2ecf20Sopenharmony_ci}
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci/**
4348c2ecf20Sopenharmony_ci * batadv_netlink_set_mesh() - Set softif attributes
4358c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
4368c2ecf20Sopenharmony_ci * @info: receiver information
4378c2ecf20Sopenharmony_ci *
4388c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
4398c2ecf20Sopenharmony_ci */
4408c2ecf20Sopenharmony_cistatic int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
4438c2ecf20Sopenharmony_ci	struct nlattr *attr;
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]) {
4468c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED];
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->aggregated_ogms, !!nla_get_u8(attr));
4498c2ecf20Sopenharmony_ci	}
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
4528c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED];
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci		batadv_netlink_set_mesh_ap_isolation(attr, bat_priv);
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_ISOLATION_MARK]) {
4588c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_ISOLATION_MARK];
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci		bat_priv->isolation_mark = nla_get_u32(attr);
4618c2ecf20Sopenharmony_ci	}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_ISOLATION_MASK]) {
4648c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_ISOLATION_MASK];
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci		bat_priv->isolation_mark_mask = nla_get_u32(attr);
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_BONDING_ENABLED]) {
4708c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_BONDING_ENABLED];
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->bonding, !!nla_get_u8(attr));
4738c2ecf20Sopenharmony_ci	}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_BLA
4768c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]) {
4778c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED];
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->bridge_loop_avoidance,
4808c2ecf20Sopenharmony_ci			   !!nla_get_u8(attr));
4818c2ecf20Sopenharmony_ci		batadv_bla_status_update(bat_priv->soft_iface);
4828c2ecf20Sopenharmony_ci	}
4838c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_BLA */
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_DAT
4868c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]) {
4878c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED];
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->distributed_arp_table,
4908c2ecf20Sopenharmony_ci			   !!nla_get_u8(attr));
4918c2ecf20Sopenharmony_ci		batadv_dat_status_update(bat_priv->soft_iface);
4928c2ecf20Sopenharmony_ci	}
4938c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_DAT */
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED]) {
4968c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED];
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->fragmentation, !!nla_get_u8(attr));
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci		rtnl_lock();
5018c2ecf20Sopenharmony_ci		batadv_update_min_mtu(bat_priv->soft_iface);
5028c2ecf20Sopenharmony_ci		rtnl_unlock();
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) {
5068c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN];
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->gw.bandwidth_down, nla_get_u32(attr));
5098c2ecf20Sopenharmony_ci		batadv_gw_tvlv_container_update(bat_priv);
5108c2ecf20Sopenharmony_ci	}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) {
5138c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP];
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->gw.bandwidth_up, nla_get_u32(attr));
5168c2ecf20Sopenharmony_ci		batadv_gw_tvlv_container_update(bat_priv);
5178c2ecf20Sopenharmony_ci	}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_GW_MODE]) {
5208c2ecf20Sopenharmony_ci		u8 gw_mode;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_GW_MODE];
5238c2ecf20Sopenharmony_ci		gw_mode = nla_get_u8(attr);
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci		if (gw_mode <= BATADV_GW_MODE_SERVER) {
5268c2ecf20Sopenharmony_ci			/* Invoking batadv_gw_reselect() is not enough to really
5278c2ecf20Sopenharmony_ci			 * de-select the current GW. It will only instruct the
5288c2ecf20Sopenharmony_ci			 * gateway client code to perform a re-election the next
5298c2ecf20Sopenharmony_ci			 * time that this is needed.
5308c2ecf20Sopenharmony_ci			 *
5318c2ecf20Sopenharmony_ci			 * When gw client mode is being switched off the current
5328c2ecf20Sopenharmony_ci			 * GW must be de-selected explicitly otherwise no GW_ADD
5338c2ecf20Sopenharmony_ci			 * uevent is thrown on client mode re-activation. This
5348c2ecf20Sopenharmony_ci			 * is operation is performed in
5358c2ecf20Sopenharmony_ci			 * batadv_gw_check_client_stop().
5368c2ecf20Sopenharmony_ci			 */
5378c2ecf20Sopenharmony_ci			batadv_gw_reselect(bat_priv);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci			/* always call batadv_gw_check_client_stop() before
5408c2ecf20Sopenharmony_ci			 * changing the gateway state
5418c2ecf20Sopenharmony_ci			 */
5428c2ecf20Sopenharmony_ci			batadv_gw_check_client_stop(bat_priv);
5438c2ecf20Sopenharmony_ci			atomic_set(&bat_priv->gw.mode, gw_mode);
5448c2ecf20Sopenharmony_ci			batadv_gw_tvlv_container_update(bat_priv);
5458c2ecf20Sopenharmony_ci		}
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_GW_SEL_CLASS] &&
5498c2ecf20Sopenharmony_ci	    bat_priv->algo_ops->gw.get_best_gw_node &&
5508c2ecf20Sopenharmony_ci	    bat_priv->algo_ops->gw.is_eligible) {
5518c2ecf20Sopenharmony_ci		/* setting the GW selection class is allowed only if the routing
5528c2ecf20Sopenharmony_ci		 * algorithm in use implements the GW API
5538c2ecf20Sopenharmony_ci		 */
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci		u32 sel_class_max = 0xffffffffu;
5568c2ecf20Sopenharmony_ci		u32 sel_class;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_GW_SEL_CLASS];
5598c2ecf20Sopenharmony_ci		sel_class = nla_get_u32(attr);
5608c2ecf20Sopenharmony_ci
5618c2ecf20Sopenharmony_ci		if (!bat_priv->algo_ops->gw.store_sel_class)
5628c2ecf20Sopenharmony_ci			sel_class_max = BATADV_TQ_MAX_VALUE;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci		if (sel_class >= 1 && sel_class <= sel_class_max) {
5658c2ecf20Sopenharmony_ci			atomic_set(&bat_priv->gw.sel_class, sel_class);
5668c2ecf20Sopenharmony_ci			batadv_gw_reselect(bat_priv);
5678c2ecf20Sopenharmony_ci		}
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
5718c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr));
5748c2ecf20Sopenharmony_ci	}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_DEBUG
5778c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_LOG_LEVEL]) {
5788c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_LOG_LEVEL];
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->log_level,
5818c2ecf20Sopenharmony_ci			   nla_get_u32(attr) & BATADV_DBG_ALL);
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_DEBUG */
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_MCAST
5868c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]) {
5878c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED];
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->multicast_mode, !nla_get_u8(attr));
5908c2ecf20Sopenharmony_ci	}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_MULTICAST_FANOUT]) {
5938c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_MULTICAST_FANOUT];
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->multicast_fanout, nla_get_u32(attr));
5968c2ecf20Sopenharmony_ci	}
5978c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_MCAST */
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_NC
6008c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED]) {
6018c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED];
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->network_coding, !!nla_get_u8(attr));
6048c2ecf20Sopenharmony_ci		batadv_nc_status_update(bat_priv->soft_iface);
6058c2ecf20Sopenharmony_ci	}
6068c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_NC */
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_ORIG_INTERVAL]) {
6098c2ecf20Sopenharmony_ci		u32 orig_interval;
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_ORIG_INTERVAL];
6128c2ecf20Sopenharmony_ci		orig_interval = nla_get_u32(attr);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci		orig_interval = min_t(u32, orig_interval, INT_MAX);
6158c2ecf20Sopenharmony_ci		orig_interval = max_t(u32, orig_interval, 2 * BATADV_JITTER);
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci		atomic_set(&bat_priv->orig_interval, orig_interval);
6188c2ecf20Sopenharmony_ci	}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	batadv_netlink_notify_mesh(bat_priv);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	return 0;
6238c2ecf20Sopenharmony_ci}
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci/**
6268c2ecf20Sopenharmony_ci * batadv_netlink_tp_meter_put() - Fill information of started tp_meter session
6278c2ecf20Sopenharmony_ci * @msg: netlink message to be sent back
6288c2ecf20Sopenharmony_ci * @cookie: tp meter session cookie
6298c2ecf20Sopenharmony_ci *
6308c2ecf20Sopenharmony_ci *  Return: 0 on success, < 0 on error
6318c2ecf20Sopenharmony_ci */
6328c2ecf20Sopenharmony_cistatic int
6338c2ecf20Sopenharmony_cibatadv_netlink_tp_meter_put(struct sk_buff *msg, u32 cookie)
6348c2ecf20Sopenharmony_ci{
6358c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie))
6368c2ecf20Sopenharmony_ci		return -ENOBUFS;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	return 0;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci/**
6428c2ecf20Sopenharmony_ci * batadv_netlink_tpmeter_notify() - send tp_meter result via netlink to client
6438c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
6448c2ecf20Sopenharmony_ci * @dst: destination of tp_meter session
6458c2ecf20Sopenharmony_ci * @result: reason for tp meter session stop
6468c2ecf20Sopenharmony_ci * @test_time: total time of the tp_meter session
6478c2ecf20Sopenharmony_ci * @total_bytes: bytes acked to the receiver
6488c2ecf20Sopenharmony_ci * @cookie: cookie of tp_meter session
6498c2ecf20Sopenharmony_ci *
6508c2ecf20Sopenharmony_ci * Return: 0 on success, < 0 on error
6518c2ecf20Sopenharmony_ci */
6528c2ecf20Sopenharmony_ciint batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst,
6538c2ecf20Sopenharmony_ci				  u8 result, u32 test_time, u64 total_bytes,
6548c2ecf20Sopenharmony_ci				  u32 cookie)
6558c2ecf20Sopenharmony_ci{
6568c2ecf20Sopenharmony_ci	struct sk_buff *msg;
6578c2ecf20Sopenharmony_ci	void *hdr;
6588c2ecf20Sopenharmony_ci	int ret;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6618c2ecf20Sopenharmony_ci	if (!msg)
6628c2ecf20Sopenharmony_ci		return -ENOMEM;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	hdr = genlmsg_put(msg, 0, 0, &batadv_netlink_family, 0,
6658c2ecf20Sopenharmony_ci			  BATADV_CMD_TP_METER);
6668c2ecf20Sopenharmony_ci	if (!hdr) {
6678c2ecf20Sopenharmony_ci		ret = -ENOBUFS;
6688c2ecf20Sopenharmony_ci		goto err_genlmsg;
6698c2ecf20Sopenharmony_ci	}
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie))
6728c2ecf20Sopenharmony_ci		goto nla_put_failure;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_TPMETER_TEST_TIME, test_time))
6758c2ecf20Sopenharmony_ci		goto nla_put_failure;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	if (nla_put_u64_64bit(msg, BATADV_ATTR_TPMETER_BYTES, total_bytes,
6788c2ecf20Sopenharmony_ci			      BATADV_ATTR_PAD))
6798c2ecf20Sopenharmony_ci		goto nla_put_failure;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_TPMETER_RESULT, result))
6828c2ecf20Sopenharmony_ci		goto nla_put_failure;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, dst))
6858c2ecf20Sopenharmony_ci		goto nla_put_failure;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	genlmsg_end(msg, hdr);
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	genlmsg_multicast_netns(&batadv_netlink_family,
6908c2ecf20Sopenharmony_ci				dev_net(bat_priv->soft_iface), msg, 0,
6918c2ecf20Sopenharmony_ci				BATADV_NL_MCGRP_TPMETER, GFP_KERNEL);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	return 0;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_cinla_put_failure:
6968c2ecf20Sopenharmony_ci	genlmsg_cancel(msg, hdr);
6978c2ecf20Sopenharmony_ci	ret = -EMSGSIZE;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_cierr_genlmsg:
7008c2ecf20Sopenharmony_ci	nlmsg_free(msg);
7018c2ecf20Sopenharmony_ci	return ret;
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci/**
7058c2ecf20Sopenharmony_ci * batadv_netlink_tp_meter_start() - Start a new tp_meter session
7068c2ecf20Sopenharmony_ci * @skb: received netlink message
7078c2ecf20Sopenharmony_ci * @info: receiver information
7088c2ecf20Sopenharmony_ci *
7098c2ecf20Sopenharmony_ci * Return: 0 on success, < 0 on error
7108c2ecf20Sopenharmony_ci */
7118c2ecf20Sopenharmony_cistatic int
7128c2ecf20Sopenharmony_cibatadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info)
7138c2ecf20Sopenharmony_ci{
7148c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
7158c2ecf20Sopenharmony_ci	struct sk_buff *msg = NULL;
7168c2ecf20Sopenharmony_ci	u32 test_length;
7178c2ecf20Sopenharmony_ci	void *msg_head;
7188c2ecf20Sopenharmony_ci	u32 cookie;
7198c2ecf20Sopenharmony_ci	u8 *dst;
7208c2ecf20Sopenharmony_ci	int ret;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS])
7238c2ecf20Sopenharmony_ci		return -EINVAL;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	if (!info->attrs[BATADV_ATTR_TPMETER_TEST_TIME])
7268c2ecf20Sopenharmony_ci		return -EINVAL;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]);
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	test_length = nla_get_u32(info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]);
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7338c2ecf20Sopenharmony_ci	if (!msg) {
7348c2ecf20Sopenharmony_ci		ret = -ENOMEM;
7358c2ecf20Sopenharmony_ci		goto out;
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq,
7398c2ecf20Sopenharmony_ci			       &batadv_netlink_family, 0,
7408c2ecf20Sopenharmony_ci			       BATADV_CMD_TP_METER);
7418c2ecf20Sopenharmony_ci	if (!msg_head) {
7428c2ecf20Sopenharmony_ci		ret = -ENOBUFS;
7438c2ecf20Sopenharmony_ci		goto out;
7448c2ecf20Sopenharmony_ci	}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	batadv_tp_start(bat_priv, dst, test_length, &cookie);
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	ret = batadv_netlink_tp_meter_put(msg, cookie);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci out:
7518c2ecf20Sopenharmony_ci	if (ret) {
7528c2ecf20Sopenharmony_ci		if (msg)
7538c2ecf20Sopenharmony_ci			nlmsg_free(msg);
7548c2ecf20Sopenharmony_ci		return ret;
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	genlmsg_end(msg, msg_head);
7588c2ecf20Sopenharmony_ci	return genlmsg_reply(msg, info);
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci/**
7628c2ecf20Sopenharmony_ci * batadv_netlink_tp_meter_start() - Cancel a running tp_meter session
7638c2ecf20Sopenharmony_ci * @skb: received netlink message
7648c2ecf20Sopenharmony_ci * @info: receiver information
7658c2ecf20Sopenharmony_ci *
7668c2ecf20Sopenharmony_ci * Return: 0 on success, < 0 on error
7678c2ecf20Sopenharmony_ci */
7688c2ecf20Sopenharmony_cistatic int
7698c2ecf20Sopenharmony_cibatadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info)
7708c2ecf20Sopenharmony_ci{
7718c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
7728c2ecf20Sopenharmony_ci	u8 *dst;
7738c2ecf20Sopenharmony_ci	int ret = 0;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS])
7768c2ecf20Sopenharmony_ci		return -EINVAL;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	batadv_tp_stop(bat_priv, dst, BATADV_TP_REASON_CANCEL);
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	return ret;
7838c2ecf20Sopenharmony_ci}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci/**
7868c2ecf20Sopenharmony_ci * batadv_netlink_hardif_fill() - Fill message with hardif attributes
7878c2ecf20Sopenharmony_ci * @msg: Netlink message to dump into
7888c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
7898c2ecf20Sopenharmony_ci * @hard_iface: hard interface which was modified
7908c2ecf20Sopenharmony_ci * @cmd: type of message to generate
7918c2ecf20Sopenharmony_ci * @portid: Port making netlink request
7928c2ecf20Sopenharmony_ci * @seq: sequence number for message
7938c2ecf20Sopenharmony_ci * @flags: Additional flags for message
7948c2ecf20Sopenharmony_ci * @cb: Control block containing additional options
7958c2ecf20Sopenharmony_ci *
7968c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
7978c2ecf20Sopenharmony_ci */
7988c2ecf20Sopenharmony_cistatic int batadv_netlink_hardif_fill(struct sk_buff *msg,
7998c2ecf20Sopenharmony_ci				      struct batadv_priv *bat_priv,
8008c2ecf20Sopenharmony_ci				      struct batadv_hard_iface *hard_iface,
8018c2ecf20Sopenharmony_ci				      enum batadv_nl_commands cmd,
8028c2ecf20Sopenharmony_ci				      u32 portid, u32 seq, int flags,
8038c2ecf20Sopenharmony_ci				      struct netlink_callback *cb)
8048c2ecf20Sopenharmony_ci{
8058c2ecf20Sopenharmony_ci	struct net_device *net_dev = hard_iface->net_dev;
8068c2ecf20Sopenharmony_ci	void *hdr;
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
8098c2ecf20Sopenharmony_ci	if (!hdr)
8108c2ecf20Sopenharmony_ci		return -ENOBUFS;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	if (cb)
8138c2ecf20Sopenharmony_ci		genl_dump_check_consistent(cb, hdr);
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX,
8168c2ecf20Sopenharmony_ci			bat_priv->soft_iface->ifindex))
8178c2ecf20Sopenharmony_ci		goto nla_put_failure;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
8208c2ecf20Sopenharmony_ci			net_dev->ifindex) ||
8218c2ecf20Sopenharmony_ci	    nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
8228c2ecf20Sopenharmony_ci			   net_dev->name) ||
8238c2ecf20Sopenharmony_ci	    nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN,
8248c2ecf20Sopenharmony_ci		    net_dev->dev_addr))
8258c2ecf20Sopenharmony_ci		goto nla_put_failure;
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	if (hard_iface->if_status == BATADV_IF_ACTIVE) {
8288c2ecf20Sopenharmony_ci		if (nla_put_flag(msg, BATADV_ATTR_ACTIVE))
8298c2ecf20Sopenharmony_ci			goto nla_put_failure;
8308c2ecf20Sopenharmony_ci	}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
8338c2ecf20Sopenharmony_ci		       atomic_read(&hard_iface->hop_penalty)))
8348c2ecf20Sopenharmony_ci		goto nla_put_failure;
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_BATMAN_V
8378c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL,
8388c2ecf20Sopenharmony_ci			atomic_read(&hard_iface->bat_v.elp_interval)))
8398c2ecf20Sopenharmony_ci		goto nla_put_failure;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT_OVERRIDE,
8428c2ecf20Sopenharmony_ci			atomic_read(&hard_iface->bat_v.throughput_override)))
8438c2ecf20Sopenharmony_ci		goto nla_put_failure;
8448c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_BATMAN_V */
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	genlmsg_end(msg, hdr);
8478c2ecf20Sopenharmony_ci	return 0;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cinla_put_failure:
8508c2ecf20Sopenharmony_ci	genlmsg_cancel(msg, hdr);
8518c2ecf20Sopenharmony_ci	return -EMSGSIZE;
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci/**
8558c2ecf20Sopenharmony_ci * batadv_netlink_notify_hardif() - send hardif attributes to listener
8568c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
8578c2ecf20Sopenharmony_ci * @hard_iface: hard interface which was modified
8588c2ecf20Sopenharmony_ci *
8598c2ecf20Sopenharmony_ci * Return: 0 on success, < 0 on error
8608c2ecf20Sopenharmony_ci */
8618c2ecf20Sopenharmony_ciint batadv_netlink_notify_hardif(struct batadv_priv *bat_priv,
8628c2ecf20Sopenharmony_ci				 struct batadv_hard_iface *hard_iface)
8638c2ecf20Sopenharmony_ci{
8648c2ecf20Sopenharmony_ci	struct sk_buff *msg;
8658c2ecf20Sopenharmony_ci	int ret;
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8688c2ecf20Sopenharmony_ci	if (!msg)
8698c2ecf20Sopenharmony_ci		return -ENOMEM;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
8728c2ecf20Sopenharmony_ci					 BATADV_CMD_SET_HARDIF, 0, 0, 0, NULL);
8738c2ecf20Sopenharmony_ci	if (ret < 0) {
8748c2ecf20Sopenharmony_ci		nlmsg_free(msg);
8758c2ecf20Sopenharmony_ci		return ret;
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	genlmsg_multicast_netns(&batadv_netlink_family,
8798c2ecf20Sopenharmony_ci				dev_net(bat_priv->soft_iface), msg, 0,
8808c2ecf20Sopenharmony_ci				BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	return 0;
8838c2ecf20Sopenharmony_ci}
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci/**
8868c2ecf20Sopenharmony_ci * batadv_netlink_get_hardif() - Get hardif attributes
8878c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
8888c2ecf20Sopenharmony_ci * @info: receiver information
8898c2ecf20Sopenharmony_ci *
8908c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
8918c2ecf20Sopenharmony_ci */
8928c2ecf20Sopenharmony_cistatic int batadv_netlink_get_hardif(struct sk_buff *skb,
8938c2ecf20Sopenharmony_ci				     struct genl_info *info)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	struct batadv_hard_iface *hard_iface = info->user_ptr[1];
8968c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
8978c2ecf20Sopenharmony_ci	struct sk_buff *msg;
8988c2ecf20Sopenharmony_ci	int ret;
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
9018c2ecf20Sopenharmony_ci	if (!msg)
9028c2ecf20Sopenharmony_ci		return -ENOMEM;
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
9058c2ecf20Sopenharmony_ci					 BATADV_CMD_GET_HARDIF,
9068c2ecf20Sopenharmony_ci					 info->snd_portid, info->snd_seq, 0,
9078c2ecf20Sopenharmony_ci					 NULL);
9088c2ecf20Sopenharmony_ci	if (ret < 0) {
9098c2ecf20Sopenharmony_ci		nlmsg_free(msg);
9108c2ecf20Sopenharmony_ci		return ret;
9118c2ecf20Sopenharmony_ci	}
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	ret = genlmsg_reply(msg, info);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	return ret;
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci/**
9198c2ecf20Sopenharmony_ci * batadv_netlink_set_hardif() - Set hardif attributes
9208c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
9218c2ecf20Sopenharmony_ci * @info: receiver information
9228c2ecf20Sopenharmony_ci *
9238c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
9248c2ecf20Sopenharmony_ci */
9258c2ecf20Sopenharmony_cistatic int batadv_netlink_set_hardif(struct sk_buff *skb,
9268c2ecf20Sopenharmony_ci				     struct genl_info *info)
9278c2ecf20Sopenharmony_ci{
9288c2ecf20Sopenharmony_ci	struct batadv_hard_iface *hard_iface = info->user_ptr[1];
9298c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
9308c2ecf20Sopenharmony_ci	struct nlattr *attr;
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
9338c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci		atomic_set(&hard_iface->hop_penalty, nla_get_u8(attr));
9368c2ecf20Sopenharmony_ci	}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci#ifdef CONFIG_BATMAN_ADV_BATMAN_V
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
9418c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
9428c2ecf20Sopenharmony_ci
9438c2ecf20Sopenharmony_ci		atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr));
9448c2ecf20Sopenharmony_ci	}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) {
9478c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE];
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci		atomic_set(&hard_iface->bat_v.throughput_override,
9508c2ecf20Sopenharmony_ci			   nla_get_u32(attr));
9518c2ecf20Sopenharmony_ci	}
9528c2ecf20Sopenharmony_ci#endif /* CONFIG_BATMAN_ADV_BATMAN_V */
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	batadv_netlink_notify_hardif(bat_priv, hard_iface);
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	return 0;
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci/**
9608c2ecf20Sopenharmony_ci * batadv_netlink_dump_hardif() - Dump all hard interface into a messages
9618c2ecf20Sopenharmony_ci * @msg: Netlink message to dump into
9628c2ecf20Sopenharmony_ci * @cb: Parameters from query
9638c2ecf20Sopenharmony_ci *
9648c2ecf20Sopenharmony_ci * Return: error code, or length of reply message on success
9658c2ecf20Sopenharmony_ci */
9668c2ecf20Sopenharmony_cistatic int
9678c2ecf20Sopenharmony_cibatadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb)
9688c2ecf20Sopenharmony_ci{
9698c2ecf20Sopenharmony_ci	struct net *net = sock_net(cb->skb->sk);
9708c2ecf20Sopenharmony_ci	struct net_device *soft_iface;
9718c2ecf20Sopenharmony_ci	struct batadv_hard_iface *hard_iface;
9728c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv;
9738c2ecf20Sopenharmony_ci	int ifindex;
9748c2ecf20Sopenharmony_ci	int portid = NETLINK_CB(cb->skb).portid;
9758c2ecf20Sopenharmony_ci	int skip = cb->args[0];
9768c2ecf20Sopenharmony_ci	int i = 0;
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	ifindex = batadv_netlink_get_ifindex(cb->nlh,
9798c2ecf20Sopenharmony_ci					     BATADV_ATTR_MESH_IFINDEX);
9808c2ecf20Sopenharmony_ci	if (!ifindex)
9818c2ecf20Sopenharmony_ci		return -EINVAL;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	soft_iface = dev_get_by_index(net, ifindex);
9848c2ecf20Sopenharmony_ci	if (!soft_iface)
9858c2ecf20Sopenharmony_ci		return -ENODEV;
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	if (!batadv_softif_is_valid(soft_iface)) {
9888c2ecf20Sopenharmony_ci		dev_put(soft_iface);
9898c2ecf20Sopenharmony_ci		return -ENODEV;
9908c2ecf20Sopenharmony_ci	}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	bat_priv = netdev_priv(soft_iface);
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_ci	rtnl_lock();
9958c2ecf20Sopenharmony_ci	cb->seq = batadv_hardif_generation << 1 | 1;
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
9988c2ecf20Sopenharmony_ci		if (hard_iface->soft_iface != soft_iface)
9998c2ecf20Sopenharmony_ci			continue;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci		if (i++ < skip)
10028c2ecf20Sopenharmony_ci			continue;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		if (batadv_netlink_hardif_fill(msg, bat_priv, hard_iface,
10058c2ecf20Sopenharmony_ci					       BATADV_CMD_GET_HARDIF,
10068c2ecf20Sopenharmony_ci					       portid, cb->nlh->nlmsg_seq,
10078c2ecf20Sopenharmony_ci					       NLM_F_MULTI, cb)) {
10088c2ecf20Sopenharmony_ci			i--;
10098c2ecf20Sopenharmony_ci			break;
10108c2ecf20Sopenharmony_ci		}
10118c2ecf20Sopenharmony_ci	}
10128c2ecf20Sopenharmony_ci
10138c2ecf20Sopenharmony_ci	rtnl_unlock();
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	dev_put(soft_iface);
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_ci	cb->args[0] = i;
10188c2ecf20Sopenharmony_ci
10198c2ecf20Sopenharmony_ci	return msg->len;
10208c2ecf20Sopenharmony_ci}
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci/**
10238c2ecf20Sopenharmony_ci * batadv_netlink_vlan_fill() - Fill message with vlan attributes
10248c2ecf20Sopenharmony_ci * @msg: Netlink message to dump into
10258c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
10268c2ecf20Sopenharmony_ci * @vlan: vlan which was modified
10278c2ecf20Sopenharmony_ci * @cmd: type of message to generate
10288c2ecf20Sopenharmony_ci * @portid: Port making netlink request
10298c2ecf20Sopenharmony_ci * @seq: sequence number for message
10308c2ecf20Sopenharmony_ci * @flags: Additional flags for message
10318c2ecf20Sopenharmony_ci *
10328c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
10338c2ecf20Sopenharmony_ci */
10348c2ecf20Sopenharmony_cistatic int batadv_netlink_vlan_fill(struct sk_buff *msg,
10358c2ecf20Sopenharmony_ci				    struct batadv_priv *bat_priv,
10368c2ecf20Sopenharmony_ci				    struct batadv_softif_vlan *vlan,
10378c2ecf20Sopenharmony_ci				    enum batadv_nl_commands cmd,
10388c2ecf20Sopenharmony_ci				    u32 portid, u32 seq, int flags)
10398c2ecf20Sopenharmony_ci{
10408c2ecf20Sopenharmony_ci	void *hdr;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd);
10438c2ecf20Sopenharmony_ci	if (!hdr)
10448c2ecf20Sopenharmony_ci		return -ENOBUFS;
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX,
10478c2ecf20Sopenharmony_ci			bat_priv->soft_iface->ifindex))
10488c2ecf20Sopenharmony_ci		goto nla_put_failure;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK))
10518c2ecf20Sopenharmony_ci		goto nla_put_failure;
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ci	if (nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED,
10548c2ecf20Sopenharmony_ci		       !!atomic_read(&vlan->ap_isolation)))
10558c2ecf20Sopenharmony_ci		goto nla_put_failure;
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_ci	genlmsg_end(msg, hdr);
10588c2ecf20Sopenharmony_ci	return 0;
10598c2ecf20Sopenharmony_ci
10608c2ecf20Sopenharmony_cinla_put_failure:
10618c2ecf20Sopenharmony_ci	genlmsg_cancel(msg, hdr);
10628c2ecf20Sopenharmony_ci	return -EMSGSIZE;
10638c2ecf20Sopenharmony_ci}
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci/**
10668c2ecf20Sopenharmony_ci * batadv_netlink_notify_vlan() - send vlan attributes to listener
10678c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
10688c2ecf20Sopenharmony_ci * @vlan: vlan which was modified
10698c2ecf20Sopenharmony_ci *
10708c2ecf20Sopenharmony_ci * Return: 0 on success, < 0 on error
10718c2ecf20Sopenharmony_ci */
10728c2ecf20Sopenharmony_ciint batadv_netlink_notify_vlan(struct batadv_priv *bat_priv,
10738c2ecf20Sopenharmony_ci			       struct batadv_softif_vlan *vlan)
10748c2ecf20Sopenharmony_ci{
10758c2ecf20Sopenharmony_ci	struct sk_buff *msg;
10768c2ecf20Sopenharmony_ci	int ret;
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10798c2ecf20Sopenharmony_ci	if (!msg)
10808c2ecf20Sopenharmony_ci		return -ENOMEM;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan,
10838c2ecf20Sopenharmony_ci				       BATADV_CMD_SET_VLAN, 0, 0, 0);
10848c2ecf20Sopenharmony_ci	if (ret < 0) {
10858c2ecf20Sopenharmony_ci		nlmsg_free(msg);
10868c2ecf20Sopenharmony_ci		return ret;
10878c2ecf20Sopenharmony_ci	}
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	genlmsg_multicast_netns(&batadv_netlink_family,
10908c2ecf20Sopenharmony_ci				dev_net(bat_priv->soft_iface), msg, 0,
10918c2ecf20Sopenharmony_ci				BATADV_NL_MCGRP_CONFIG, GFP_KERNEL);
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	return 0;
10948c2ecf20Sopenharmony_ci}
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci/**
10978c2ecf20Sopenharmony_ci * batadv_netlink_get_vlan() - Get vlan attributes
10988c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
10998c2ecf20Sopenharmony_ci * @info: receiver information
11008c2ecf20Sopenharmony_ci *
11018c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
11028c2ecf20Sopenharmony_ci */
11038c2ecf20Sopenharmony_cistatic int batadv_netlink_get_vlan(struct sk_buff *skb, struct genl_info *info)
11048c2ecf20Sopenharmony_ci{
11058c2ecf20Sopenharmony_ci	struct batadv_softif_vlan *vlan = info->user_ptr[1];
11068c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
11078c2ecf20Sopenharmony_ci	struct sk_buff *msg;
11088c2ecf20Sopenharmony_ci	int ret;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11118c2ecf20Sopenharmony_ci	if (!msg)
11128c2ecf20Sopenharmony_ci		return -ENOMEM;
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, BATADV_CMD_GET_VLAN,
11158c2ecf20Sopenharmony_ci				       info->snd_portid, info->snd_seq, 0);
11168c2ecf20Sopenharmony_ci	if (ret < 0) {
11178c2ecf20Sopenharmony_ci		nlmsg_free(msg);
11188c2ecf20Sopenharmony_ci		return ret;
11198c2ecf20Sopenharmony_ci	}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	ret = genlmsg_reply(msg, info);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	return ret;
11248c2ecf20Sopenharmony_ci}
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci/**
11278c2ecf20Sopenharmony_ci * batadv_netlink_set_vlan() - Get vlan attributes
11288c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
11298c2ecf20Sopenharmony_ci * @info: receiver information
11308c2ecf20Sopenharmony_ci *
11318c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
11328c2ecf20Sopenharmony_ci */
11338c2ecf20Sopenharmony_cistatic int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info)
11348c2ecf20Sopenharmony_ci{
11358c2ecf20Sopenharmony_ci	struct batadv_softif_vlan *vlan = info->user_ptr[1];
11368c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = info->user_ptr[0];
11378c2ecf20Sopenharmony_ci	struct nlattr *attr;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
11408c2ecf20Sopenharmony_ci		attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED];
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci		atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr));
11438c2ecf20Sopenharmony_ci	}
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	batadv_netlink_notify_vlan(bat_priv, vlan);
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	return 0;
11488c2ecf20Sopenharmony_ci}
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci/**
11518c2ecf20Sopenharmony_ci * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes
11528c2ecf20Sopenharmony_ci * @net: the applicable net namespace
11538c2ecf20Sopenharmony_ci * @info: receiver information
11548c2ecf20Sopenharmony_ci *
11558c2ecf20Sopenharmony_ci * Return: Pointer to soft interface (with increased refcnt) on success, error
11568c2ecf20Sopenharmony_ci *  pointer on error
11578c2ecf20Sopenharmony_ci */
11588c2ecf20Sopenharmony_cistatic struct net_device *
11598c2ecf20Sopenharmony_cibatadv_get_softif_from_info(struct net *net, struct genl_info *info)
11608c2ecf20Sopenharmony_ci{
11618c2ecf20Sopenharmony_ci	struct net_device *soft_iface;
11628c2ecf20Sopenharmony_ci	int ifindex;
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci	if (!info->attrs[BATADV_ATTR_MESH_IFINDEX])
11658c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]);
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	soft_iface = dev_get_by_index(net, ifindex);
11708c2ecf20Sopenharmony_ci	if (!soft_iface)
11718c2ecf20Sopenharmony_ci		return ERR_PTR(-ENODEV);
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	if (!batadv_softif_is_valid(soft_iface))
11748c2ecf20Sopenharmony_ci		goto err_put_softif;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	return soft_iface;
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_cierr_put_softif:
11798c2ecf20Sopenharmony_ci	dev_put(soft_iface);
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	return ERR_PTR(-EINVAL);
11828c2ecf20Sopenharmony_ci}
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci/**
11858c2ecf20Sopenharmony_ci * batadv_get_hardif_from_info() - Retrieve hardif from genl attributes
11868c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
11878c2ecf20Sopenharmony_ci * @net: the applicable net namespace
11888c2ecf20Sopenharmony_ci * @info: receiver information
11898c2ecf20Sopenharmony_ci *
11908c2ecf20Sopenharmony_ci * Return: Pointer to hard interface (with increased refcnt) on success, error
11918c2ecf20Sopenharmony_ci *  pointer on error
11928c2ecf20Sopenharmony_ci */
11938c2ecf20Sopenharmony_cistatic struct batadv_hard_iface *
11948c2ecf20Sopenharmony_cibatadv_get_hardif_from_info(struct batadv_priv *bat_priv, struct net *net,
11958c2ecf20Sopenharmony_ci			    struct genl_info *info)
11968c2ecf20Sopenharmony_ci{
11978c2ecf20Sopenharmony_ci	struct batadv_hard_iface *hard_iface;
11988c2ecf20Sopenharmony_ci	struct net_device *hard_dev;
11998c2ecf20Sopenharmony_ci	unsigned int hardif_index;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	if (!info->attrs[BATADV_ATTR_HARD_IFINDEX])
12028c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ci	hardif_index = nla_get_u32(info->attrs[BATADV_ATTR_HARD_IFINDEX]);
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	hard_dev = dev_get_by_index(net, hardif_index);
12078c2ecf20Sopenharmony_ci	if (!hard_dev)
12088c2ecf20Sopenharmony_ci		return ERR_PTR(-ENODEV);
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	hard_iface = batadv_hardif_get_by_netdev(hard_dev);
12118c2ecf20Sopenharmony_ci	if (!hard_iface)
12128c2ecf20Sopenharmony_ci		goto err_put_harddev;
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	if (hard_iface->soft_iface != bat_priv->soft_iface)
12158c2ecf20Sopenharmony_ci		goto err_put_hardif;
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	/* hard_dev is referenced by hard_iface and not needed here */
12188c2ecf20Sopenharmony_ci	dev_put(hard_dev);
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	return hard_iface;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_cierr_put_hardif:
12238c2ecf20Sopenharmony_ci	batadv_hardif_put(hard_iface);
12248c2ecf20Sopenharmony_cierr_put_harddev:
12258c2ecf20Sopenharmony_ci	dev_put(hard_dev);
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	return ERR_PTR(-EINVAL);
12288c2ecf20Sopenharmony_ci}
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci/**
12318c2ecf20Sopenharmony_ci * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes
12328c2ecf20Sopenharmony_ci * @bat_priv: the bat priv with all the soft interface information
12338c2ecf20Sopenharmony_ci * @net: the applicable net namespace
12348c2ecf20Sopenharmony_ci * @info: receiver information
12358c2ecf20Sopenharmony_ci *
12368c2ecf20Sopenharmony_ci * Return: Pointer to vlan on success (with increased refcnt), error pointer
12378c2ecf20Sopenharmony_ci *  on error
12388c2ecf20Sopenharmony_ci */
12398c2ecf20Sopenharmony_cistatic struct batadv_softif_vlan *
12408c2ecf20Sopenharmony_cibatadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net,
12418c2ecf20Sopenharmony_ci			  struct genl_info *info)
12428c2ecf20Sopenharmony_ci{
12438c2ecf20Sopenharmony_ci	struct batadv_softif_vlan *vlan;
12448c2ecf20Sopenharmony_ci	u16 vid;
12458c2ecf20Sopenharmony_ci
12468c2ecf20Sopenharmony_ci	if (!info->attrs[BATADV_ATTR_VLANID])
12478c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]);
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG);
12528c2ecf20Sopenharmony_ci	if (!vlan)
12538c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOENT);
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	return vlan;
12568c2ecf20Sopenharmony_ci}
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci/**
12598c2ecf20Sopenharmony_ci * batadv_pre_doit() - Prepare batman-adv genl doit request
12608c2ecf20Sopenharmony_ci * @ops: requested netlink operation
12618c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
12628c2ecf20Sopenharmony_ci * @info: receiver information
12638c2ecf20Sopenharmony_ci *
12648c2ecf20Sopenharmony_ci * Return: 0 on success or negative error number in case of failure
12658c2ecf20Sopenharmony_ci */
12668c2ecf20Sopenharmony_cistatic int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
12678c2ecf20Sopenharmony_ci			   struct genl_info *info)
12688c2ecf20Sopenharmony_ci{
12698c2ecf20Sopenharmony_ci	struct net *net = genl_info_net(info);
12708c2ecf20Sopenharmony_ci	struct batadv_hard_iface *hard_iface;
12718c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv = NULL;
12728c2ecf20Sopenharmony_ci	struct batadv_softif_vlan *vlan;
12738c2ecf20Sopenharmony_ci	struct net_device *soft_iface;
12748c2ecf20Sopenharmony_ci	u8 user_ptr1_flags;
12758c2ecf20Sopenharmony_ci	u8 mesh_dep_flags;
12768c2ecf20Sopenharmony_ci	int ret;
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	user_ptr1_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
12798c2ecf20Sopenharmony_ci	if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1))
12808c2ecf20Sopenharmony_ci		return -EINVAL;
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	mesh_dep_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN;
12838c2ecf20Sopenharmony_ci	if (WARN_ON((ops->internal_flags & mesh_dep_flags) &&
12848c2ecf20Sopenharmony_ci		    (~ops->internal_flags & BATADV_FLAG_NEED_MESH)))
12858c2ecf20Sopenharmony_ci		return -EINVAL;
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	if (ops->internal_flags & BATADV_FLAG_NEED_MESH) {
12888c2ecf20Sopenharmony_ci		soft_iface = batadv_get_softif_from_info(net, info);
12898c2ecf20Sopenharmony_ci		if (IS_ERR(soft_iface))
12908c2ecf20Sopenharmony_ci			return PTR_ERR(soft_iface);
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci		bat_priv = netdev_priv(soft_iface);
12938c2ecf20Sopenharmony_ci		info->user_ptr[0] = bat_priv;
12948c2ecf20Sopenharmony_ci	}
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF) {
12978c2ecf20Sopenharmony_ci		hard_iface = batadv_get_hardif_from_info(bat_priv, net, info);
12988c2ecf20Sopenharmony_ci		if (IS_ERR(hard_iface)) {
12998c2ecf20Sopenharmony_ci			ret = PTR_ERR(hard_iface);
13008c2ecf20Sopenharmony_ci			goto err_put_softif;
13018c2ecf20Sopenharmony_ci		}
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci		info->user_ptr[1] = hard_iface;
13048c2ecf20Sopenharmony_ci	}
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	if (ops->internal_flags & BATADV_FLAG_NEED_VLAN) {
13078c2ecf20Sopenharmony_ci		vlan = batadv_get_vlan_from_info(bat_priv, net, info);
13088c2ecf20Sopenharmony_ci		if (IS_ERR(vlan)) {
13098c2ecf20Sopenharmony_ci			ret = PTR_ERR(vlan);
13108c2ecf20Sopenharmony_ci			goto err_put_softif;
13118c2ecf20Sopenharmony_ci		}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci		info->user_ptr[1] = vlan;
13148c2ecf20Sopenharmony_ci	}
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	return 0;
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_cierr_put_softif:
13198c2ecf20Sopenharmony_ci	if (bat_priv)
13208c2ecf20Sopenharmony_ci		dev_put(bat_priv->soft_iface);
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	return ret;
13238c2ecf20Sopenharmony_ci}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci/**
13268c2ecf20Sopenharmony_ci * batadv_post_doit() - End batman-adv genl doit request
13278c2ecf20Sopenharmony_ci * @ops: requested netlink operation
13288c2ecf20Sopenharmony_ci * @skb: Netlink message with request data
13298c2ecf20Sopenharmony_ci * @info: receiver information
13308c2ecf20Sopenharmony_ci */
13318c2ecf20Sopenharmony_cistatic void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
13328c2ecf20Sopenharmony_ci			     struct genl_info *info)
13338c2ecf20Sopenharmony_ci{
13348c2ecf20Sopenharmony_ci	struct batadv_hard_iface *hard_iface;
13358c2ecf20Sopenharmony_ci	struct batadv_softif_vlan *vlan;
13368c2ecf20Sopenharmony_ci	struct batadv_priv *bat_priv;
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF &&
13398c2ecf20Sopenharmony_ci	    info->user_ptr[1]) {
13408c2ecf20Sopenharmony_ci		hard_iface = info->user_ptr[1];
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci		batadv_hardif_put(hard_iface);
13438c2ecf20Sopenharmony_ci	}
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci	if (ops->internal_flags & BATADV_FLAG_NEED_VLAN && info->user_ptr[1]) {
13468c2ecf20Sopenharmony_ci		vlan = info->user_ptr[1];
13478c2ecf20Sopenharmony_ci		batadv_softif_vlan_put(vlan);
13488c2ecf20Sopenharmony_ci	}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) {
13518c2ecf20Sopenharmony_ci		bat_priv = info->user_ptr[0];
13528c2ecf20Sopenharmony_ci		dev_put(bat_priv->soft_iface);
13538c2ecf20Sopenharmony_ci	}
13548c2ecf20Sopenharmony_ci}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_cistatic const struct genl_small_ops batadv_netlink_ops[] = {
13578c2ecf20Sopenharmony_ci	{
13588c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_MESH,
13598c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13608c2ecf20Sopenharmony_ci		/* can be retrieved by unprivileged users */
13618c2ecf20Sopenharmony_ci		.doit = batadv_netlink_get_mesh,
13628c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH,
13638c2ecf20Sopenharmony_ci	},
13648c2ecf20Sopenharmony_ci	{
13658c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_TP_METER,
13668c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13678c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
13688c2ecf20Sopenharmony_ci		.doit = batadv_netlink_tp_meter_start,
13698c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH,
13708c2ecf20Sopenharmony_ci	},
13718c2ecf20Sopenharmony_ci	{
13728c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_TP_METER_CANCEL,
13738c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13748c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
13758c2ecf20Sopenharmony_ci		.doit = batadv_netlink_tp_meter_cancel,
13768c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH,
13778c2ecf20Sopenharmony_ci	},
13788c2ecf20Sopenharmony_ci	{
13798c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_ROUTING_ALGOS,
13808c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13818c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
13828c2ecf20Sopenharmony_ci		.dumpit = batadv_algo_dump,
13838c2ecf20Sopenharmony_ci	},
13848c2ecf20Sopenharmony_ci	{
13858c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_HARDIF,
13868c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13878c2ecf20Sopenharmony_ci		/* can be retrieved by unprivileged users */
13888c2ecf20Sopenharmony_ci		.dumpit = batadv_netlink_dump_hardif,
13898c2ecf20Sopenharmony_ci		.doit = batadv_netlink_get_hardif,
13908c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH |
13918c2ecf20Sopenharmony_ci				  BATADV_FLAG_NEED_HARDIF,
13928c2ecf20Sopenharmony_ci	},
13938c2ecf20Sopenharmony_ci	{
13948c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL,
13958c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
13968c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
13978c2ecf20Sopenharmony_ci		.dumpit = batadv_tt_local_dump,
13988c2ecf20Sopenharmony_ci	},
13998c2ecf20Sopenharmony_ci	{
14008c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL,
14018c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14028c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14038c2ecf20Sopenharmony_ci		.dumpit = batadv_tt_global_dump,
14048c2ecf20Sopenharmony_ci	},
14058c2ecf20Sopenharmony_ci	{
14068c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_ORIGINATORS,
14078c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14088c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14098c2ecf20Sopenharmony_ci		.dumpit = batadv_orig_dump,
14108c2ecf20Sopenharmony_ci	},
14118c2ecf20Sopenharmony_ci	{
14128c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_NEIGHBORS,
14138c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14148c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14158c2ecf20Sopenharmony_ci		.dumpit = batadv_hardif_neigh_dump,
14168c2ecf20Sopenharmony_ci	},
14178c2ecf20Sopenharmony_ci	{
14188c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_GATEWAYS,
14198c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14208c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14218c2ecf20Sopenharmony_ci		.dumpit = batadv_gw_dump,
14228c2ecf20Sopenharmony_ci	},
14238c2ecf20Sopenharmony_ci	{
14248c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_BLA_CLAIM,
14258c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14268c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14278c2ecf20Sopenharmony_ci		.dumpit = batadv_bla_claim_dump,
14288c2ecf20Sopenharmony_ci	},
14298c2ecf20Sopenharmony_ci	{
14308c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_BLA_BACKBONE,
14318c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14328c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14338c2ecf20Sopenharmony_ci		.dumpit = batadv_bla_backbone_dump,
14348c2ecf20Sopenharmony_ci	},
14358c2ecf20Sopenharmony_ci	{
14368c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_DAT_CACHE,
14378c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14388c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14398c2ecf20Sopenharmony_ci		.dumpit = batadv_dat_cache_dump,
14408c2ecf20Sopenharmony_ci	},
14418c2ecf20Sopenharmony_ci	{
14428c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_MCAST_FLAGS,
14438c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14448c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14458c2ecf20Sopenharmony_ci		.dumpit = batadv_mcast_flags_dump,
14468c2ecf20Sopenharmony_ci	},
14478c2ecf20Sopenharmony_ci	{
14488c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_SET_MESH,
14498c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14508c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14518c2ecf20Sopenharmony_ci		.doit = batadv_netlink_set_mesh,
14528c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH,
14538c2ecf20Sopenharmony_ci	},
14548c2ecf20Sopenharmony_ci	{
14558c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_SET_HARDIF,
14568c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14578c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14588c2ecf20Sopenharmony_ci		.doit = batadv_netlink_set_hardif,
14598c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH |
14608c2ecf20Sopenharmony_ci				  BATADV_FLAG_NEED_HARDIF,
14618c2ecf20Sopenharmony_ci	},
14628c2ecf20Sopenharmony_ci	{
14638c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_GET_VLAN,
14648c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14658c2ecf20Sopenharmony_ci		/* can be retrieved by unprivileged users */
14668c2ecf20Sopenharmony_ci		.doit = batadv_netlink_get_vlan,
14678c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH |
14688c2ecf20Sopenharmony_ci				  BATADV_FLAG_NEED_VLAN,
14698c2ecf20Sopenharmony_ci	},
14708c2ecf20Sopenharmony_ci	{
14718c2ecf20Sopenharmony_ci		.cmd = BATADV_CMD_SET_VLAN,
14728c2ecf20Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
14738c2ecf20Sopenharmony_ci		.flags = GENL_UNS_ADMIN_PERM,
14748c2ecf20Sopenharmony_ci		.doit = batadv_netlink_set_vlan,
14758c2ecf20Sopenharmony_ci		.internal_flags = BATADV_FLAG_NEED_MESH |
14768c2ecf20Sopenharmony_ci				  BATADV_FLAG_NEED_VLAN,
14778c2ecf20Sopenharmony_ci	},
14788c2ecf20Sopenharmony_ci};
14798c2ecf20Sopenharmony_ci
14808c2ecf20Sopenharmony_cistruct genl_family batadv_netlink_family __ro_after_init = {
14818c2ecf20Sopenharmony_ci	.hdrsize = 0,
14828c2ecf20Sopenharmony_ci	.name = BATADV_NL_NAME,
14838c2ecf20Sopenharmony_ci	.version = 1,
14848c2ecf20Sopenharmony_ci	.maxattr = BATADV_ATTR_MAX,
14858c2ecf20Sopenharmony_ci	.policy = batadv_netlink_policy,
14868c2ecf20Sopenharmony_ci	.netnsok = true,
14878c2ecf20Sopenharmony_ci	.pre_doit = batadv_pre_doit,
14888c2ecf20Sopenharmony_ci	.post_doit = batadv_post_doit,
14898c2ecf20Sopenharmony_ci	.module = THIS_MODULE,
14908c2ecf20Sopenharmony_ci	.small_ops = batadv_netlink_ops,
14918c2ecf20Sopenharmony_ci	.n_small_ops = ARRAY_SIZE(batadv_netlink_ops),
14928c2ecf20Sopenharmony_ci	.mcgrps = batadv_netlink_mcgrps,
14938c2ecf20Sopenharmony_ci	.n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps),
14948c2ecf20Sopenharmony_ci};
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci/**
14978c2ecf20Sopenharmony_ci * batadv_netlink_register() - register batadv genl netlink family
14988c2ecf20Sopenharmony_ci */
14998c2ecf20Sopenharmony_civoid __init batadv_netlink_register(void)
15008c2ecf20Sopenharmony_ci{
15018c2ecf20Sopenharmony_ci	int ret;
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci	ret = genl_register_family(&batadv_netlink_family);
15048c2ecf20Sopenharmony_ci	if (ret)
15058c2ecf20Sopenharmony_ci		pr_warn("unable to register netlink family");
15068c2ecf20Sopenharmony_ci}
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci/**
15098c2ecf20Sopenharmony_ci * batadv_netlink_unregister() - unregister batadv genl netlink family
15108c2ecf20Sopenharmony_ci */
15118c2ecf20Sopenharmony_civoid batadv_netlink_unregister(void)
15128c2ecf20Sopenharmony_ci{
15138c2ecf20Sopenharmony_ci	genl_unregister_family(&batadv_netlink_family);
15148c2ecf20Sopenharmony_ci}
1515