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