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