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