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 54 struct genl_family batadv_netlink_family; 55 56 /* multicast groups */ 57 enum 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 */ 65 enum 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 88 static 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 93 static 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 */ 162 int 163 batadv_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 */ 177 static 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 */ 201 static 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 */ 227 static 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 367 nla_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 */ 381 int 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 */ 411 static 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 */ 440 static 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 batadv_update_min_mtu(bat_priv->soft_iface); 500 } 501 502 if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) { 503 attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]; 504 505 atomic_set(&bat_priv->gw.bandwidth_down, nla_get_u32(attr)); 506 batadv_gw_tvlv_container_update(bat_priv); 507 } 508 509 if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) { 510 attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]; 511 512 atomic_set(&bat_priv->gw.bandwidth_up, nla_get_u32(attr)); 513 batadv_gw_tvlv_container_update(bat_priv); 514 } 515 516 if (info->attrs[BATADV_ATTR_GW_MODE]) { 517 u8 gw_mode; 518 519 attr = info->attrs[BATADV_ATTR_GW_MODE]; 520 gw_mode = nla_get_u8(attr); 521 522 if (gw_mode <= BATADV_GW_MODE_SERVER) { 523 /* Invoking batadv_gw_reselect() is not enough to really 524 * de-select the current GW. It will only instruct the 525 * gateway client code to perform a re-election the next 526 * time that this is needed. 527 * 528 * When gw client mode is being switched off the current 529 * GW must be de-selected explicitly otherwise no GW_ADD 530 * uevent is thrown on client mode re-activation. This 531 * is operation is performed in 532 * batadv_gw_check_client_stop(). 533 */ 534 batadv_gw_reselect(bat_priv); 535 536 /* always call batadv_gw_check_client_stop() before 537 * changing the gateway state 538 */ 539 batadv_gw_check_client_stop(bat_priv); 540 atomic_set(&bat_priv->gw.mode, gw_mode); 541 batadv_gw_tvlv_container_update(bat_priv); 542 } 543 } 544 545 if (info->attrs[BATADV_ATTR_GW_SEL_CLASS] && 546 bat_priv->algo_ops->gw.get_best_gw_node && 547 bat_priv->algo_ops->gw.is_eligible) { 548 /* setting the GW selection class is allowed only if the routing 549 * algorithm in use implements the GW API 550 */ 551 552 u32 sel_class_max = 0xffffffffu; 553 u32 sel_class; 554 555 attr = info->attrs[BATADV_ATTR_GW_SEL_CLASS]; 556 sel_class = nla_get_u32(attr); 557 558 if (!bat_priv->algo_ops->gw.store_sel_class) 559 sel_class_max = BATADV_TQ_MAX_VALUE; 560 561 if (sel_class >= 1 && sel_class <= sel_class_max) { 562 atomic_set(&bat_priv->gw.sel_class, sel_class); 563 batadv_gw_reselect(bat_priv); 564 } 565 } 566 567 if (info->attrs[BATADV_ATTR_HOP_PENALTY]) { 568 attr = info->attrs[BATADV_ATTR_HOP_PENALTY]; 569 570 atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr)); 571 } 572 573 #ifdef CONFIG_BATMAN_ADV_DEBUG 574 if (info->attrs[BATADV_ATTR_LOG_LEVEL]) { 575 attr = info->attrs[BATADV_ATTR_LOG_LEVEL]; 576 577 atomic_set(&bat_priv->log_level, 578 nla_get_u32(attr) & BATADV_DBG_ALL); 579 } 580 #endif /* CONFIG_BATMAN_ADV_DEBUG */ 581 582 #ifdef CONFIG_BATMAN_ADV_MCAST 583 if (info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]) { 584 attr = info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]; 585 586 atomic_set(&bat_priv->multicast_mode, !nla_get_u8(attr)); 587 } 588 589 if (info->attrs[BATADV_ATTR_MULTICAST_FANOUT]) { 590 attr = info->attrs[BATADV_ATTR_MULTICAST_FANOUT]; 591 592 atomic_set(&bat_priv->multicast_fanout, nla_get_u32(attr)); 593 } 594 #endif /* CONFIG_BATMAN_ADV_MCAST */ 595 596 #ifdef CONFIG_BATMAN_ADV_NC 597 if (info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED]) { 598 attr = info->attrs[BATADV_ATTR_NETWORK_CODING_ENABLED]; 599 600 atomic_set(&bat_priv->network_coding, !!nla_get_u8(attr)); 601 batadv_nc_status_update(bat_priv->soft_iface); 602 } 603 #endif /* CONFIG_BATMAN_ADV_NC */ 604 605 if (info->attrs[BATADV_ATTR_ORIG_INTERVAL]) { 606 u32 orig_interval; 607 608 attr = info->attrs[BATADV_ATTR_ORIG_INTERVAL]; 609 orig_interval = nla_get_u32(attr); 610 611 orig_interval = min_t(u32, orig_interval, INT_MAX); 612 orig_interval = max_t(u32, orig_interval, 2 * BATADV_JITTER); 613 614 atomic_set(&bat_priv->orig_interval, orig_interval); 615 } 616 617 batadv_netlink_notify_mesh(bat_priv); 618 619 return 0; 620 } 621 622 /** 623 * batadv_netlink_tp_meter_put() - Fill information of started tp_meter session 624 * @msg: netlink message to be sent back 625 * @cookie: tp meter session cookie 626 * 627 * Return: 0 on success, < 0 on error 628 */ 629 static int 630 batadv_netlink_tp_meter_put(struct sk_buff *msg, u32 cookie) 631 { 632 if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie)) 633 return -ENOBUFS; 634 635 return 0; 636 } 637 638 /** 639 * batadv_netlink_tpmeter_notify() - send tp_meter result via netlink to client 640 * @bat_priv: the bat priv with all the soft interface information 641 * @dst: destination of tp_meter session 642 * @result: reason for tp meter session stop 643 * @test_time: total time ot the tp_meter session 644 * @total_bytes: bytes acked to the receiver 645 * @cookie: cookie of tp_meter session 646 * 647 * Return: 0 on success, < 0 on error 648 */ 649 int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst, 650 u8 result, u32 test_time, u64 total_bytes, 651 u32 cookie) 652 { 653 struct sk_buff *msg; 654 void *hdr; 655 int ret; 656 657 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 658 if (!msg) 659 return -ENOMEM; 660 661 hdr = genlmsg_put(msg, 0, 0, &batadv_netlink_family, 0, 662 BATADV_CMD_TP_METER); 663 if (!hdr) { 664 ret = -ENOBUFS; 665 goto err_genlmsg; 666 } 667 668 if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie)) 669 goto nla_put_failure; 670 671 if (nla_put_u32(msg, BATADV_ATTR_TPMETER_TEST_TIME, test_time)) 672 goto nla_put_failure; 673 674 if (nla_put_u64_64bit(msg, BATADV_ATTR_TPMETER_BYTES, total_bytes, 675 BATADV_ATTR_PAD)) 676 goto nla_put_failure; 677 678 if (nla_put_u8(msg, BATADV_ATTR_TPMETER_RESULT, result)) 679 goto nla_put_failure; 680 681 if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, dst)) 682 goto nla_put_failure; 683 684 genlmsg_end(msg, hdr); 685 686 genlmsg_multicast_netns(&batadv_netlink_family, 687 dev_net(bat_priv->soft_iface), msg, 0, 688 BATADV_NL_MCGRP_TPMETER, GFP_KERNEL); 689 690 return 0; 691 692 nla_put_failure: 693 genlmsg_cancel(msg, hdr); 694 ret = -EMSGSIZE; 695 696 err_genlmsg: 697 nlmsg_free(msg); 698 return ret; 699 } 700 701 /** 702 * batadv_netlink_tp_meter_start() - Start a new tp_meter session 703 * @skb: received netlink message 704 * @info: receiver information 705 * 706 * Return: 0 on success, < 0 on error 707 */ 708 static int 709 batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) 710 { 711 struct batadv_priv *bat_priv = info->user_ptr[0]; 712 struct sk_buff *msg = NULL; 713 u32 test_length; 714 void *msg_head; 715 u32 cookie; 716 u8 *dst; 717 int ret; 718 719 if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) 720 return -EINVAL; 721 722 if (!info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]) 723 return -EINVAL; 724 725 dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); 726 727 test_length = nla_get_u32(info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]); 728 729 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 730 if (!msg) { 731 ret = -ENOMEM; 732 goto out; 733 } 734 735 msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq, 736 &batadv_netlink_family, 0, 737 BATADV_CMD_TP_METER); 738 if (!msg_head) { 739 ret = -ENOBUFS; 740 goto out; 741 } 742 743 batadv_tp_start(bat_priv, dst, test_length, &cookie); 744 745 ret = batadv_netlink_tp_meter_put(msg, cookie); 746 747 out: 748 if (ret) { 749 if (msg) 750 nlmsg_free(msg); 751 return ret; 752 } 753 754 genlmsg_end(msg, msg_head); 755 return genlmsg_reply(msg, info); 756 } 757 758 /** 759 * batadv_netlink_tp_meter_start() - Cancel a running tp_meter session 760 * @skb: received netlink message 761 * @info: receiver information 762 * 763 * Return: 0 on success, < 0 on error 764 */ 765 static int 766 batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info) 767 { 768 struct batadv_priv *bat_priv = info->user_ptr[0]; 769 u8 *dst; 770 int ret = 0; 771 772 if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) 773 return -EINVAL; 774 775 dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); 776 777 batadv_tp_stop(bat_priv, dst, BATADV_TP_REASON_CANCEL); 778 779 return ret; 780 } 781 782 /** 783 * batadv_netlink_hardif_fill() - Fill message with hardif attributes 784 * @msg: Netlink message to dump into 785 * @bat_priv: the bat priv with all the soft interface information 786 * @hard_iface: hard interface which was modified 787 * @cmd: type of message to generate 788 * @portid: Port making netlink request 789 * @seq: sequence number for message 790 * @flags: Additional flags for message 791 * @cb: Control block containing additional options 792 * 793 * Return: 0 on success or negative error number in case of failure 794 */ 795 static int batadv_netlink_hardif_fill(struct sk_buff *msg, 796 struct batadv_priv *bat_priv, 797 struct batadv_hard_iface *hard_iface, 798 enum batadv_nl_commands cmd, 799 u32 portid, u32 seq, int flags, 800 struct netlink_callback *cb) 801 { 802 struct net_device *net_dev = hard_iface->net_dev; 803 void *hdr; 804 805 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); 806 if (!hdr) 807 return -ENOBUFS; 808 809 if (cb) 810 genl_dump_check_consistent(cb, hdr); 811 812 if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, 813 bat_priv->soft_iface->ifindex)) 814 goto nla_put_failure; 815 816 if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, 817 net_dev->ifindex) || 818 nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, 819 net_dev->name) || 820 nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN, 821 net_dev->dev_addr)) 822 goto nla_put_failure; 823 824 if (hard_iface->if_status == BATADV_IF_ACTIVE) { 825 if (nla_put_flag(msg, BATADV_ATTR_ACTIVE)) 826 goto nla_put_failure; 827 } 828 829 #ifdef CONFIG_BATMAN_ADV_BATMAN_V 830 if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL, 831 atomic_read(&hard_iface->bat_v.elp_interval))) 832 goto nla_put_failure; 833 834 if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT_OVERRIDE, 835 atomic_read(&hard_iface->bat_v.throughput_override))) 836 goto nla_put_failure; 837 #endif /* CONFIG_BATMAN_ADV_BATMAN_V */ 838 839 genlmsg_end(msg, hdr); 840 return 0; 841 842 nla_put_failure: 843 genlmsg_cancel(msg, hdr); 844 return -EMSGSIZE; 845 } 846 847 /** 848 * batadv_netlink_notify_hardif() - send hardif attributes to listener 849 * @bat_priv: the bat priv with all the soft interface information 850 * @hard_iface: hard interface which was modified 851 * 852 * Return: 0 on success, < 0 on error 853 */ 854 int batadv_netlink_notify_hardif(struct batadv_priv *bat_priv, 855 struct batadv_hard_iface *hard_iface) 856 { 857 struct sk_buff *msg; 858 int ret; 859 860 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 861 if (!msg) 862 return -ENOMEM; 863 864 ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface, 865 BATADV_CMD_SET_HARDIF, 0, 0, 0, NULL); 866 if (ret < 0) { 867 nlmsg_free(msg); 868 return ret; 869 } 870 871 genlmsg_multicast_netns(&batadv_netlink_family, 872 dev_net(bat_priv->soft_iface), msg, 0, 873 BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); 874 875 return 0; 876 } 877 878 /** 879 * batadv_netlink_get_hardif() - Get hardif attributes 880 * @skb: Netlink message with request data 881 * @info: receiver information 882 * 883 * Return: 0 on success or negative error number in case of failure 884 */ 885 static int batadv_netlink_get_hardif(struct sk_buff *skb, 886 struct genl_info *info) 887 { 888 struct batadv_hard_iface *hard_iface = info->user_ptr[1]; 889 struct batadv_priv *bat_priv = info->user_ptr[0]; 890 struct sk_buff *msg; 891 int ret; 892 893 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 894 if (!msg) 895 return -ENOMEM; 896 897 ret = batadv_netlink_hardif_fill(msg, bat_priv, hard_iface, 898 BATADV_CMD_GET_HARDIF, 899 info->snd_portid, info->snd_seq, 0, 900 NULL); 901 if (ret < 0) { 902 nlmsg_free(msg); 903 return ret; 904 } 905 906 ret = genlmsg_reply(msg, info); 907 908 return ret; 909 } 910 911 /** 912 * batadv_netlink_set_hardif() - Set hardif attributes 913 * @skb: Netlink message with request data 914 * @info: receiver information 915 * 916 * Return: 0 on success or negative error number in case of failure 917 */ 918 static int batadv_netlink_set_hardif(struct sk_buff *skb, 919 struct genl_info *info) 920 { 921 struct batadv_hard_iface *hard_iface = info->user_ptr[1]; 922 struct batadv_priv *bat_priv = info->user_ptr[0]; 923 924 #ifdef CONFIG_BATMAN_ADV_BATMAN_V 925 struct nlattr *attr; 926 927 if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) { 928 attr = info->attrs[BATADV_ATTR_ELP_INTERVAL]; 929 930 atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr)); 931 } 932 933 if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) { 934 attr = info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]; 935 936 atomic_set(&hard_iface->bat_v.throughput_override, 937 nla_get_u32(attr)); 938 } 939 #endif /* CONFIG_BATMAN_ADV_BATMAN_V */ 940 941 batadv_netlink_notify_hardif(bat_priv, hard_iface); 942 943 return 0; 944 } 945 946 /** 947 * batadv_netlink_dump_hardif() - Dump all hard interface into a messages 948 * @msg: Netlink message to dump into 949 * @cb: Parameters from query 950 * 951 * Return: error code, or length of reply message on success 952 */ 953 static int 954 batadv_netlink_dump_hardif(struct sk_buff *msg, struct netlink_callback *cb) 955 { 956 struct net *net = sock_net(cb->skb->sk); 957 struct net_device *soft_iface; 958 struct batadv_hard_iface *hard_iface; 959 struct batadv_priv *bat_priv; 960 int ifindex; 961 int portid = NETLINK_CB(cb->skb).portid; 962 int skip = cb->args[0]; 963 int i = 0; 964 965 ifindex = batadv_netlink_get_ifindex(cb->nlh, 966 BATADV_ATTR_MESH_IFINDEX); 967 if (!ifindex) 968 return -EINVAL; 969 970 soft_iface = dev_get_by_index(net, ifindex); 971 if (!soft_iface) 972 return -ENODEV; 973 974 if (!batadv_softif_is_valid(soft_iface)) { 975 dev_put(soft_iface); 976 return -ENODEV; 977 } 978 979 bat_priv = netdev_priv(soft_iface); 980 981 rtnl_lock(); 982 cb->seq = batadv_hardif_generation << 1 | 1; 983 984 list_for_each_entry(hard_iface, &batadv_hardif_list, list) { 985 if (hard_iface->soft_iface != soft_iface) 986 continue; 987 988 if (i++ < skip) 989 continue; 990 991 if (batadv_netlink_hardif_fill(msg, bat_priv, hard_iface, 992 BATADV_CMD_GET_HARDIF, 993 portid, cb->nlh->nlmsg_seq, 994 NLM_F_MULTI, cb)) { 995 i--; 996 break; 997 } 998 } 999 1000 rtnl_unlock(); 1001 1002 dev_put(soft_iface); 1003 1004 cb->args[0] = i; 1005 1006 return msg->len; 1007 } 1008 1009 /** 1010 * batadv_netlink_vlan_fill() - Fill message with vlan attributes 1011 * @msg: Netlink message to dump into 1012 * @bat_priv: the bat priv with all the soft interface information 1013 * @vlan: vlan which was modified 1014 * @cmd: type of message to generate 1015 * @portid: Port making netlink request 1016 * @seq: sequence number for message 1017 * @flags: Additional flags for message 1018 * 1019 * Return: 0 on success or negative error number in case of failure 1020 */ 1021 static int batadv_netlink_vlan_fill(struct sk_buff *msg, 1022 struct batadv_priv *bat_priv, 1023 struct batadv_softif_vlan *vlan, 1024 enum batadv_nl_commands cmd, 1025 u32 portid, u32 seq, int flags) 1026 { 1027 void *hdr; 1028 1029 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, flags, cmd); 1030 if (!hdr) 1031 return -ENOBUFS; 1032 1033 if (nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, 1034 bat_priv->soft_iface->ifindex)) 1035 goto nla_put_failure; 1036 1037 if (nla_put_u32(msg, BATADV_ATTR_VLANID, vlan->vid & VLAN_VID_MASK)) 1038 goto nla_put_failure; 1039 1040 if (nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED, 1041 !!atomic_read(&vlan->ap_isolation))) 1042 goto nla_put_failure; 1043 1044 genlmsg_end(msg, hdr); 1045 return 0; 1046 1047 nla_put_failure: 1048 genlmsg_cancel(msg, hdr); 1049 return -EMSGSIZE; 1050 } 1051 1052 /** 1053 * batadv_netlink_notify_vlan() - send vlan attributes to listener 1054 * @bat_priv: the bat priv with all the soft interface information 1055 * @vlan: vlan which was modified 1056 * 1057 * Return: 0 on success, < 0 on error 1058 */ 1059 int batadv_netlink_notify_vlan(struct batadv_priv *bat_priv, 1060 struct batadv_softif_vlan *vlan) 1061 { 1062 struct sk_buff *msg; 1063 int ret; 1064 1065 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1066 if (!msg) 1067 return -ENOMEM; 1068 1069 ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, 1070 BATADV_CMD_SET_VLAN, 0, 0, 0); 1071 if (ret < 0) { 1072 nlmsg_free(msg); 1073 return ret; 1074 } 1075 1076 genlmsg_multicast_netns(&batadv_netlink_family, 1077 dev_net(bat_priv->soft_iface), msg, 0, 1078 BATADV_NL_MCGRP_CONFIG, GFP_KERNEL); 1079 1080 return 0; 1081 } 1082 1083 /** 1084 * batadv_netlink_get_vlan() - Get vlan attributes 1085 * @skb: Netlink message with request data 1086 * @info: receiver information 1087 * 1088 * Return: 0 on success or negative error number in case of failure 1089 */ 1090 static int batadv_netlink_get_vlan(struct sk_buff *skb, struct genl_info *info) 1091 { 1092 struct batadv_softif_vlan *vlan = info->user_ptr[1]; 1093 struct batadv_priv *bat_priv = info->user_ptr[0]; 1094 struct sk_buff *msg; 1095 int ret; 1096 1097 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1098 if (!msg) 1099 return -ENOMEM; 1100 1101 ret = batadv_netlink_vlan_fill(msg, bat_priv, vlan, BATADV_CMD_GET_VLAN, 1102 info->snd_portid, info->snd_seq, 0); 1103 if (ret < 0) { 1104 nlmsg_free(msg); 1105 return ret; 1106 } 1107 1108 ret = genlmsg_reply(msg, info); 1109 1110 return ret; 1111 } 1112 1113 /** 1114 * batadv_netlink_set_vlan() - Get vlan attributes 1115 * @skb: Netlink message with request data 1116 * @info: receiver information 1117 * 1118 * Return: 0 on success or negative error number in case of failure 1119 */ 1120 static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info) 1121 { 1122 struct batadv_softif_vlan *vlan = info->user_ptr[1]; 1123 struct batadv_priv *bat_priv = info->user_ptr[0]; 1124 struct nlattr *attr; 1125 1126 if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) { 1127 attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]; 1128 1129 atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr)); 1130 } 1131 1132 batadv_netlink_notify_vlan(bat_priv, vlan); 1133 1134 return 0; 1135 } 1136 1137 /** 1138 * batadv_get_softif_from_info() - Retrieve soft interface from genl attributes 1139 * @net: the applicable net namespace 1140 * @info: receiver information 1141 * 1142 * Return: Pointer to soft interface (with increased refcnt) on success, error 1143 * pointer on error 1144 */ 1145 static struct net_device * 1146 batadv_get_softif_from_info(struct net *net, struct genl_info *info) 1147 { 1148 struct net_device *soft_iface; 1149 int ifindex; 1150 1151 if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) 1152 return ERR_PTR(-EINVAL); 1153 1154 ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); 1155 1156 soft_iface = dev_get_by_index(net, ifindex); 1157 if (!soft_iface) 1158 return ERR_PTR(-ENODEV); 1159 1160 if (!batadv_softif_is_valid(soft_iface)) 1161 goto err_put_softif; 1162 1163 return soft_iface; 1164 1165 err_put_softif: 1166 dev_put(soft_iface); 1167 1168 return ERR_PTR(-EINVAL); 1169 } 1170 1171 /** 1172 * batadv_get_hardif_from_info() - Retrieve hardif from genl attributes 1173 * @bat_priv: the bat priv with all the soft interface information 1174 * @net: the applicable net namespace 1175 * @info: receiver information 1176 * 1177 * Return: Pointer to hard interface (with increased refcnt) on success, error 1178 * pointer on error 1179 */ 1180 static struct batadv_hard_iface * 1181 batadv_get_hardif_from_info(struct batadv_priv *bat_priv, struct net *net, 1182 struct genl_info *info) 1183 { 1184 struct batadv_hard_iface *hard_iface; 1185 struct net_device *hard_dev; 1186 unsigned int hardif_index; 1187 1188 if (!info->attrs[BATADV_ATTR_HARD_IFINDEX]) 1189 return ERR_PTR(-EINVAL); 1190 1191 hardif_index = nla_get_u32(info->attrs[BATADV_ATTR_HARD_IFINDEX]); 1192 1193 hard_dev = dev_get_by_index(net, hardif_index); 1194 if (!hard_dev) 1195 return ERR_PTR(-ENODEV); 1196 1197 hard_iface = batadv_hardif_get_by_netdev(hard_dev); 1198 if (!hard_iface) 1199 goto err_put_harddev; 1200 1201 if (hard_iface->soft_iface != bat_priv->soft_iface) 1202 goto err_put_hardif; 1203 1204 /* hard_dev is referenced by hard_iface and not needed here */ 1205 dev_put(hard_dev); 1206 1207 return hard_iface; 1208 1209 err_put_hardif: 1210 batadv_hardif_put(hard_iface); 1211 err_put_harddev: 1212 dev_put(hard_dev); 1213 1214 return ERR_PTR(-EINVAL); 1215 } 1216 1217 /** 1218 * batadv_get_vlan_from_info() - Retrieve vlan from genl attributes 1219 * @bat_priv: the bat priv with all the soft interface information 1220 * @net: the applicable net namespace 1221 * @info: receiver information 1222 * 1223 * Return: Pointer to vlan on success (with increased refcnt), error pointer 1224 * on error 1225 */ 1226 static struct batadv_softif_vlan * 1227 batadv_get_vlan_from_info(struct batadv_priv *bat_priv, struct net *net, 1228 struct genl_info *info) 1229 { 1230 struct batadv_softif_vlan *vlan; 1231 u16 vid; 1232 1233 if (!info->attrs[BATADV_ATTR_VLANID]) 1234 return ERR_PTR(-EINVAL); 1235 1236 vid = nla_get_u16(info->attrs[BATADV_ATTR_VLANID]); 1237 1238 vlan = batadv_softif_vlan_get(bat_priv, vid | BATADV_VLAN_HAS_TAG); 1239 if (!vlan) 1240 return ERR_PTR(-ENOENT); 1241 1242 return vlan; 1243 } 1244 1245 /** 1246 * batadv_pre_doit() - Prepare batman-adv genl doit request 1247 * @ops: requested netlink operation 1248 * @skb: Netlink message with request data 1249 * @info: receiver information 1250 * 1251 * Return: 0 on success or negative error number in case of failure 1252 */ 1253 static int batadv_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 1254 struct genl_info *info) 1255 { 1256 struct net *net = genl_info_net(info); 1257 struct batadv_hard_iface *hard_iface; 1258 struct batadv_priv *bat_priv = NULL; 1259 struct batadv_softif_vlan *vlan; 1260 struct net_device *soft_iface; 1261 u8 user_ptr1_flags; 1262 u8 mesh_dep_flags; 1263 int ret; 1264 1265 user_ptr1_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN; 1266 if (WARN_ON(hweight8(ops->internal_flags & user_ptr1_flags) > 1)) 1267 return -EINVAL; 1268 1269 mesh_dep_flags = BATADV_FLAG_NEED_HARDIF | BATADV_FLAG_NEED_VLAN; 1270 if (WARN_ON((ops->internal_flags & mesh_dep_flags) && 1271 (~ops->internal_flags & BATADV_FLAG_NEED_MESH))) 1272 return -EINVAL; 1273 1274 if (ops->internal_flags & BATADV_FLAG_NEED_MESH) { 1275 soft_iface = batadv_get_softif_from_info(net, info); 1276 if (IS_ERR(soft_iface)) 1277 return PTR_ERR(soft_iface); 1278 1279 bat_priv = netdev_priv(soft_iface); 1280 info->user_ptr[0] = bat_priv; 1281 } 1282 1283 if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF) { 1284 hard_iface = batadv_get_hardif_from_info(bat_priv, net, info); 1285 if (IS_ERR(hard_iface)) { 1286 ret = PTR_ERR(hard_iface); 1287 goto err_put_softif; 1288 } 1289 1290 info->user_ptr[1] = hard_iface; 1291 } 1292 1293 if (ops->internal_flags & BATADV_FLAG_NEED_VLAN) { 1294 vlan = batadv_get_vlan_from_info(bat_priv, net, info); 1295 if (IS_ERR(vlan)) { 1296 ret = PTR_ERR(vlan); 1297 goto err_put_softif; 1298 } 1299 1300 info->user_ptr[1] = vlan; 1301 } 1302 1303 return 0; 1304 1305 err_put_softif: 1306 if (bat_priv) 1307 dev_put(bat_priv->soft_iface); 1308 1309 return ret; 1310 } 1311 1312 /** 1313 * batadv_post_doit() - End batman-adv genl doit request 1314 * @ops: requested netlink operation 1315 * @skb: Netlink message with request data 1316 * @info: receiver information 1317 */ 1318 static void batadv_post_doit(const struct genl_ops *ops, struct sk_buff *skb, 1319 struct genl_info *info) 1320 { 1321 struct batadv_hard_iface *hard_iface; 1322 struct batadv_softif_vlan *vlan; 1323 struct batadv_priv *bat_priv; 1324 1325 if (ops->internal_flags & BATADV_FLAG_NEED_HARDIF && 1326 info->user_ptr[1]) { 1327 hard_iface = info->user_ptr[1]; 1328 1329 batadv_hardif_put(hard_iface); 1330 } 1331 1332 if (ops->internal_flags & BATADV_FLAG_NEED_VLAN && info->user_ptr[1]) { 1333 vlan = info->user_ptr[1]; 1334 batadv_softif_vlan_put(vlan); 1335 } 1336 1337 if (ops->internal_flags & BATADV_FLAG_NEED_MESH && info->user_ptr[0]) { 1338 bat_priv = info->user_ptr[0]; 1339 dev_put(bat_priv->soft_iface); 1340 } 1341 } 1342 1343 static const struct genl_ops batadv_netlink_ops[] = { 1344 { 1345 .cmd = BATADV_CMD_GET_MESH, 1346 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1347 /* can be retrieved by unprivileged users */ 1348 .doit = batadv_netlink_get_mesh, 1349 .internal_flags = BATADV_FLAG_NEED_MESH, 1350 }, 1351 { 1352 .cmd = BATADV_CMD_TP_METER, 1353 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1354 .flags = GENL_ADMIN_PERM, 1355 .doit = batadv_netlink_tp_meter_start, 1356 .internal_flags = BATADV_FLAG_NEED_MESH, 1357 }, 1358 { 1359 .cmd = BATADV_CMD_TP_METER_CANCEL, 1360 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1361 .flags = GENL_ADMIN_PERM, 1362 .doit = batadv_netlink_tp_meter_cancel, 1363 .internal_flags = BATADV_FLAG_NEED_MESH, 1364 }, 1365 { 1366 .cmd = BATADV_CMD_GET_ROUTING_ALGOS, 1367 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1368 .flags = GENL_ADMIN_PERM, 1369 .dumpit = batadv_algo_dump, 1370 }, 1371 { 1372 .cmd = BATADV_CMD_GET_HARDIF, 1373 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1374 /* can be retrieved by unprivileged users */ 1375 .dumpit = batadv_netlink_dump_hardif, 1376 .doit = batadv_netlink_get_hardif, 1377 .internal_flags = BATADV_FLAG_NEED_MESH | 1378 BATADV_FLAG_NEED_HARDIF, 1379 }, 1380 { 1381 .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL, 1382 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1383 .flags = GENL_ADMIN_PERM, 1384 .dumpit = batadv_tt_local_dump, 1385 }, 1386 { 1387 .cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL, 1388 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1389 .flags = GENL_ADMIN_PERM, 1390 .dumpit = batadv_tt_global_dump, 1391 }, 1392 { 1393 .cmd = BATADV_CMD_GET_ORIGINATORS, 1394 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1395 .flags = GENL_ADMIN_PERM, 1396 .dumpit = batadv_orig_dump, 1397 }, 1398 { 1399 .cmd = BATADV_CMD_GET_NEIGHBORS, 1400 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1401 .flags = GENL_ADMIN_PERM, 1402 .dumpit = batadv_hardif_neigh_dump, 1403 }, 1404 { 1405 .cmd = BATADV_CMD_GET_GATEWAYS, 1406 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1407 .flags = GENL_ADMIN_PERM, 1408 .dumpit = batadv_gw_dump, 1409 }, 1410 { 1411 .cmd = BATADV_CMD_GET_BLA_CLAIM, 1412 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1413 .flags = GENL_ADMIN_PERM, 1414 .dumpit = batadv_bla_claim_dump, 1415 }, 1416 { 1417 .cmd = BATADV_CMD_GET_BLA_BACKBONE, 1418 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1419 .flags = GENL_ADMIN_PERM, 1420 .dumpit = batadv_bla_backbone_dump, 1421 }, 1422 { 1423 .cmd = BATADV_CMD_GET_DAT_CACHE, 1424 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1425 .flags = GENL_ADMIN_PERM, 1426 .dumpit = batadv_dat_cache_dump, 1427 }, 1428 { 1429 .cmd = BATADV_CMD_GET_MCAST_FLAGS, 1430 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1431 .flags = GENL_ADMIN_PERM, 1432 .dumpit = batadv_mcast_flags_dump, 1433 }, 1434 { 1435 .cmd = BATADV_CMD_SET_MESH, 1436 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1437 .flags = GENL_ADMIN_PERM, 1438 .doit = batadv_netlink_set_mesh, 1439 .internal_flags = BATADV_FLAG_NEED_MESH, 1440 }, 1441 { 1442 .cmd = BATADV_CMD_SET_HARDIF, 1443 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1444 .flags = GENL_ADMIN_PERM, 1445 .doit = batadv_netlink_set_hardif, 1446 .internal_flags = BATADV_FLAG_NEED_MESH | 1447 BATADV_FLAG_NEED_HARDIF, 1448 }, 1449 { 1450 .cmd = BATADV_CMD_GET_VLAN, 1451 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1452 /* can be retrieved by unprivileged users */ 1453 .doit = batadv_netlink_get_vlan, 1454 .internal_flags = BATADV_FLAG_NEED_MESH | 1455 BATADV_FLAG_NEED_VLAN, 1456 }, 1457 { 1458 .cmd = BATADV_CMD_SET_VLAN, 1459 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 1460 .flags = GENL_ADMIN_PERM, 1461 .doit = batadv_netlink_set_vlan, 1462 .internal_flags = BATADV_FLAG_NEED_MESH | 1463 BATADV_FLAG_NEED_VLAN, 1464 }, 1465 }; 1466 1467 struct genl_family batadv_netlink_family __ro_after_init = { 1468 .hdrsize = 0, 1469 .name = BATADV_NL_NAME, 1470 .version = 1, 1471 .maxattr = BATADV_ATTR_MAX, 1472 .policy = batadv_netlink_policy, 1473 .netnsok = true, 1474 .pre_doit = batadv_pre_doit, 1475 .post_doit = batadv_post_doit, 1476 .module = THIS_MODULE, 1477 .ops = batadv_netlink_ops, 1478 .n_ops = ARRAY_SIZE(batadv_netlink_ops), 1479 .mcgrps = batadv_netlink_mcgrps, 1480 .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps), 1481 }; 1482 1483 /** 1484 * batadv_netlink_register() - register batadv genl netlink family 1485 */ 1486 void __init batadv_netlink_register(void) 1487 { 1488 int ret; 1489 1490 ret = genl_register_family(&batadv_netlink_family); 1491 if (ret) 1492 pr_warn("unable to register netlink family"); 1493 } 1494 1495 /** 1496 * batadv_netlink_unregister() - unregister batadv genl netlink family 1497 */ 1498 void batadv_netlink_unregister(void) 1499 { 1500 genl_unregister_family(&batadv_netlink_family); 1501 } 1502