1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2016-2017 B.A.T.M.A.N. contributors: 3 * 4 * Matthias Schiffer 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of version 2 of the GNU General Public 8 * License as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "netlink.h" 20 #include "main.h" 21 22 #include <linux/atomic.h> 23 #include <linux/byteorder/generic.h> 24 #include <linux/cache.h> 25 #include <linux/errno.h> 26 #include <linux/export.h> 27 #include <linux/genetlink.h> 28 #include <linux/gfp.h> 29 #include <linux/if_ether.h> 30 #include <linux/init.h> 31 #include <linux/kernel.h> 32 #include <linux/netdevice.h> 33 #include <linux/netlink.h> 34 #include <linux/printk.h> 35 #include <linux/rculist.h> 36 #include <linux/rcupdate.h> 37 #include <linux/skbuff.h> 38 #include <linux/stddef.h> 39 #include <linux/types.h> 40 #include <net/genetlink.h> 41 #include <net/netlink.h> 42 #include <net/sock.h> 43 #include <uapi/linux/batadv_packet.h> 44 #include <uapi/linux/batman_adv.h> 45 46 #include "bat_algo.h" 47 #include "bridge_loop_avoidance.h" 48 #include "gateway_client.h" 49 #include "hard-interface.h" 50 #include "originator.h" 51 #include "soft-interface.h" 52 #include "tp_meter.h" 53 #include "translation-table.h" 54 55 struct genl_family batadv_netlink_family; 56 57 /* multicast groups */ 58 enum batadv_netlink_multicast_groups { 59 BATADV_NL_MCGRP_TPMETER, 60 }; 61 62 static const struct genl_multicast_group batadv_netlink_mcgrps[] = { 63 [BATADV_NL_MCGRP_TPMETER] = { .name = BATADV_NL_MCAST_GROUP_TPMETER }, 64 }; 65 66 static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = { 67 [BATADV_ATTR_VERSION] = { .type = NLA_STRING }, 68 [BATADV_ATTR_ALGO_NAME] = { .type = NLA_STRING }, 69 [BATADV_ATTR_MESH_IFINDEX] = { .type = NLA_U32 }, 70 [BATADV_ATTR_MESH_IFNAME] = { .type = NLA_STRING }, 71 [BATADV_ATTR_MESH_ADDRESS] = { .len = ETH_ALEN }, 72 [BATADV_ATTR_HARD_IFINDEX] = { .type = NLA_U32 }, 73 [BATADV_ATTR_HARD_IFNAME] = { .type = NLA_STRING }, 74 [BATADV_ATTR_HARD_ADDRESS] = { .len = ETH_ALEN }, 75 [BATADV_ATTR_ORIG_ADDRESS] = { .len = ETH_ALEN }, 76 [BATADV_ATTR_TPMETER_RESULT] = { .type = NLA_U8 }, 77 [BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NLA_U32 }, 78 [BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 }, 79 [BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 }, 80 [BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG }, 81 [BATADV_ATTR_TT_ADDRESS] = { .len = ETH_ALEN }, 82 [BATADV_ATTR_TT_TTVN] = { .type = NLA_U8 }, 83 [BATADV_ATTR_TT_LAST_TTVN] = { .type = NLA_U8 }, 84 [BATADV_ATTR_TT_CRC32] = { .type = NLA_U32 }, 85 [BATADV_ATTR_TT_VID] = { .type = NLA_U16 }, 86 [BATADV_ATTR_TT_FLAGS] = { .type = NLA_U32 }, 87 [BATADV_ATTR_FLAG_BEST] = { .type = NLA_FLAG }, 88 [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 }, 89 [BATADV_ATTR_NEIGH_ADDRESS] = { .len = ETH_ALEN }, 90 [BATADV_ATTR_TQ] = { .type = NLA_U8 }, 91 [BATADV_ATTR_THROUGHPUT] = { .type = NLA_U32 }, 92 [BATADV_ATTR_BANDWIDTH_UP] = { .type = NLA_U32 }, 93 [BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NLA_U32 }, 94 [BATADV_ATTR_ROUTER] = { .len = ETH_ALEN }, 95 [BATADV_ATTR_BLA_OWN] = { .type = NLA_FLAG }, 96 [BATADV_ATTR_BLA_ADDRESS] = { .len = ETH_ALEN }, 97 [BATADV_ATTR_BLA_VID] = { .type = NLA_U16 }, 98 [BATADV_ATTR_BLA_BACKBONE] = { .len = ETH_ALEN }, 99 [BATADV_ATTR_BLA_CRC] = { .type = NLA_U16 }, 100 }; 101 102 /** 103 * batadv_netlink_get_ifindex() - Extract an interface index from a message 104 * @nlh: Message header 105 * @attrtype: Attribute which holds an interface index 106 * 107 * Return: interface index, or 0. 108 */ 109 int 110 batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) 111 { 112 struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype); 113 114 return attr ? nla_get_u32(attr) : 0; 115 } 116 117 /** 118 * batadv_netlink_mesh_info_put() - fill in generic information about mesh 119 * interface 120 * @msg: netlink message to be sent back 121 * @soft_iface: interface for which the data should be taken 122 * 123 * Return: 0 on success, < 0 on error 124 */ 125 static int 126 batadv_netlink_mesh_info_put(struct sk_buff *msg, struct net_device *soft_iface) 127 { 128 struct batadv_priv *bat_priv = netdev_priv(soft_iface); 129 struct batadv_hard_iface *primary_if = NULL; 130 struct net_device *hard_iface; 131 int ret = -ENOBUFS; 132 133 if (nla_put_string(msg, BATADV_ATTR_VERSION, BATADV_SOURCE_VERSION) || 134 nla_put_string(msg, BATADV_ATTR_ALGO_NAME, 135 bat_priv->algo_ops->name) || 136 nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, soft_iface->ifindex) || 137 nla_put_string(msg, BATADV_ATTR_MESH_IFNAME, soft_iface->name) || 138 nla_put(msg, BATADV_ATTR_MESH_ADDRESS, ETH_ALEN, 139 soft_iface->dev_addr) || 140 nla_put_u8(msg, BATADV_ATTR_TT_TTVN, 141 (u8)atomic_read(&bat_priv->tt.vn))) 142 goto out; 143 144 #ifdef CONFIG_BATMAN_ADV_BLA 145 if (nla_put_u16(msg, BATADV_ATTR_BLA_CRC, 146 ntohs(bat_priv->bla.claim_dest.group))) 147 goto out; 148 #endif 149 150 primary_if = batadv_primary_if_get_selected(bat_priv); 151 if (primary_if && primary_if->if_status == BATADV_IF_ACTIVE) { 152 hard_iface = primary_if->net_dev; 153 154 if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, 155 hard_iface->ifindex) || 156 nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, 157 hard_iface->name) || 158 nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN, 159 hard_iface->dev_addr)) 160 goto out; 161 } 162 163 ret = 0; 164 165 out: 166 if (primary_if) 167 batadv_hardif_put(primary_if); 168 169 return ret; 170 } 171 172 /** 173 * batadv_netlink_get_mesh_info() - handle incoming BATADV_CMD_GET_MESH_INFO 174 * netlink request 175 * @skb: received netlink message 176 * @info: receiver information 177 * 178 * Return: 0 on success, < 0 on error 179 */ 180 static int 181 batadv_netlink_get_mesh_info(struct sk_buff *skb, struct genl_info *info) 182 { 183 struct net *net = genl_info_net(info); 184 struct net_device *soft_iface; 185 struct sk_buff *msg = NULL; 186 void *msg_head; 187 int ifindex; 188 int ret; 189 190 if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) 191 return -EINVAL; 192 193 ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); 194 if (!ifindex) 195 return -EINVAL; 196 197 soft_iface = dev_get_by_index(net, ifindex); 198 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { 199 ret = -ENODEV; 200 goto out; 201 } 202 203 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 204 if (!msg) { 205 ret = -ENOMEM; 206 goto out; 207 } 208 209 msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq, 210 &batadv_netlink_family, 0, 211 BATADV_CMD_GET_MESH_INFO); 212 if (!msg_head) { 213 ret = -ENOBUFS; 214 goto out; 215 } 216 217 ret = batadv_netlink_mesh_info_put(msg, soft_iface); 218 219 out: 220 if (soft_iface) 221 dev_put(soft_iface); 222 223 if (ret) { 224 if (msg) 225 nlmsg_free(msg); 226 return ret; 227 } 228 229 genlmsg_end(msg, msg_head); 230 return genlmsg_reply(msg, info); 231 } 232 233 /** 234 * batadv_netlink_tp_meter_put() - Fill information of started tp_meter session 235 * @msg: netlink message to be sent back 236 * @cookie: tp meter session cookie 237 * 238 * Return: 0 on success, < 0 on error 239 */ 240 static int 241 batadv_netlink_tp_meter_put(struct sk_buff *msg, u32 cookie) 242 { 243 if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie)) 244 return -ENOBUFS; 245 246 return 0; 247 } 248 249 /** 250 * batadv_netlink_tpmeter_notify() - send tp_meter result via netlink to client 251 * @bat_priv: the bat priv with all the soft interface information 252 * @dst: destination of tp_meter session 253 * @result: reason for tp meter session stop 254 * @test_time: total time ot the tp_meter session 255 * @total_bytes: bytes acked to the receiver 256 * @cookie: cookie of tp_meter session 257 * 258 * Return: 0 on success, < 0 on error 259 */ 260 int batadv_netlink_tpmeter_notify(struct batadv_priv *bat_priv, const u8 *dst, 261 u8 result, u32 test_time, u64 total_bytes, 262 u32 cookie) 263 { 264 struct sk_buff *msg; 265 void *hdr; 266 int ret; 267 268 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 269 if (!msg) 270 return -ENOMEM; 271 272 hdr = genlmsg_put(msg, 0, 0, &batadv_netlink_family, 0, 273 BATADV_CMD_TP_METER); 274 if (!hdr) { 275 ret = -ENOBUFS; 276 goto err_genlmsg; 277 } 278 279 if (nla_put_u32(msg, BATADV_ATTR_TPMETER_COOKIE, cookie)) 280 goto nla_put_failure; 281 282 if (nla_put_u32(msg, BATADV_ATTR_TPMETER_TEST_TIME, test_time)) 283 goto nla_put_failure; 284 285 if (nla_put_u64_64bit(msg, BATADV_ATTR_TPMETER_BYTES, total_bytes, 286 BATADV_ATTR_PAD)) 287 goto nla_put_failure; 288 289 if (nla_put_u8(msg, BATADV_ATTR_TPMETER_RESULT, result)) 290 goto nla_put_failure; 291 292 if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, dst)) 293 goto nla_put_failure; 294 295 genlmsg_end(msg, hdr); 296 297 genlmsg_multicast_netns(&batadv_netlink_family, 298 dev_net(bat_priv->soft_iface), msg, 0, 299 BATADV_NL_MCGRP_TPMETER, GFP_KERNEL); 300 301 return 0; 302 303 nla_put_failure: 304 genlmsg_cancel(msg, hdr); 305 ret = -EMSGSIZE; 306 307 err_genlmsg: 308 nlmsg_free(msg); 309 return ret; 310 } 311 312 /** 313 * batadv_netlink_tp_meter_start() - Start a new tp_meter session 314 * @skb: received netlink message 315 * @info: receiver information 316 * 317 * Return: 0 on success, < 0 on error 318 */ 319 static int 320 batadv_netlink_tp_meter_start(struct sk_buff *skb, struct genl_info *info) 321 { 322 struct net *net = genl_info_net(info); 323 struct net_device *soft_iface; 324 struct batadv_priv *bat_priv; 325 struct sk_buff *msg = NULL; 326 u32 test_length; 327 void *msg_head; 328 int ifindex; 329 u32 cookie; 330 u8 *dst; 331 int ret; 332 333 if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) 334 return -EINVAL; 335 336 if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) 337 return -EINVAL; 338 339 if (!info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]) 340 return -EINVAL; 341 342 ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); 343 if (!ifindex) 344 return -EINVAL; 345 346 dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); 347 348 test_length = nla_get_u32(info->attrs[BATADV_ATTR_TPMETER_TEST_TIME]); 349 350 soft_iface = dev_get_by_index(net, ifindex); 351 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { 352 ret = -ENODEV; 353 goto out; 354 } 355 356 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 357 if (!msg) { 358 ret = -ENOMEM; 359 goto out; 360 } 361 362 msg_head = genlmsg_put(msg, info->snd_portid, info->snd_seq, 363 &batadv_netlink_family, 0, 364 BATADV_CMD_TP_METER); 365 if (!msg_head) { 366 ret = -ENOBUFS; 367 goto out; 368 } 369 370 bat_priv = netdev_priv(soft_iface); 371 batadv_tp_start(bat_priv, dst, test_length, &cookie); 372 373 ret = batadv_netlink_tp_meter_put(msg, cookie); 374 375 out: 376 if (soft_iface) 377 dev_put(soft_iface); 378 379 if (ret) { 380 if (msg) 381 nlmsg_free(msg); 382 return ret; 383 } 384 385 genlmsg_end(msg, msg_head); 386 return genlmsg_reply(msg, info); 387 } 388 389 /** 390 * batadv_netlink_tp_meter_start() - Cancel a running tp_meter session 391 * @skb: received netlink message 392 * @info: receiver information 393 * 394 * Return: 0 on success, < 0 on error 395 */ 396 static int 397 batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info) 398 { 399 struct net *net = genl_info_net(info); 400 struct net_device *soft_iface; 401 struct batadv_priv *bat_priv; 402 int ifindex; 403 u8 *dst; 404 int ret = 0; 405 406 if (!info->attrs[BATADV_ATTR_MESH_IFINDEX]) 407 return -EINVAL; 408 409 if (!info->attrs[BATADV_ATTR_ORIG_ADDRESS]) 410 return -EINVAL; 411 412 ifindex = nla_get_u32(info->attrs[BATADV_ATTR_MESH_IFINDEX]); 413 if (!ifindex) 414 return -EINVAL; 415 416 dst = nla_data(info->attrs[BATADV_ATTR_ORIG_ADDRESS]); 417 418 soft_iface = dev_get_by_index(net, ifindex); 419 if (!soft_iface || !batadv_softif_is_valid(soft_iface)) { 420 ret = -ENODEV; 421 goto out; 422 } 423 424 bat_priv = netdev_priv(soft_iface); 425 batadv_tp_stop(bat_priv, dst, BATADV_TP_REASON_CANCEL); 426 427 out: 428 if (soft_iface) 429 dev_put(soft_iface); 430 431 return ret; 432 } 433 434 /** 435 * batadv_netlink_dump_hardif_entry() - Dump one hard interface into a message 436 * @msg: Netlink message to dump into 437 * @portid: Port making netlink request 438 * @seq: Sequence number of netlink message 439 * @hard_iface: Hard interface to dump 440 * 441 * Return: error code, or 0 on success 442 */ 443 static int 444 batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, u32 seq, 445 struct batadv_hard_iface *hard_iface) 446 { 447 struct net_device *net_dev = hard_iface->net_dev; 448 void *hdr; 449 450 hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI, 451 BATADV_CMD_GET_HARDIFS); 452 if (!hdr) 453 return -EMSGSIZE; 454 455 if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, 456 net_dev->ifindex) || 457 nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, 458 net_dev->name) || 459 nla_put(msg, BATADV_ATTR_HARD_ADDRESS, ETH_ALEN, 460 net_dev->dev_addr)) 461 goto nla_put_failure; 462 463 if (hard_iface->if_status == BATADV_IF_ACTIVE) { 464 if (nla_put_flag(msg, BATADV_ATTR_ACTIVE)) 465 goto nla_put_failure; 466 } 467 468 genlmsg_end(msg, hdr); 469 return 0; 470 471 nla_put_failure: 472 genlmsg_cancel(msg, hdr); 473 return -EMSGSIZE; 474 } 475 476 /** 477 * batadv_netlink_dump_hardifs() - Dump all hard interface into a messages 478 * @msg: Netlink message to dump into 479 * @cb: Parameters from query 480 * 481 * Return: error code, or length of reply message on success 482 */ 483 static int 484 batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) 485 { 486 struct net *net = sock_net(cb->skb->sk); 487 struct net_device *soft_iface; 488 struct batadv_hard_iface *hard_iface; 489 int ifindex; 490 int portid = NETLINK_CB(cb->skb).portid; 491 int seq = cb->nlh->nlmsg_seq; 492 int skip = cb->args[0]; 493 int i = 0; 494 495 ifindex = batadv_netlink_get_ifindex(cb->nlh, 496 BATADV_ATTR_MESH_IFINDEX); 497 if (!ifindex) 498 return -EINVAL; 499 500 soft_iface = dev_get_by_index(net, ifindex); 501 if (!soft_iface) 502 return -ENODEV; 503 504 if (!batadv_softif_is_valid(soft_iface)) { 505 dev_put(soft_iface); 506 return -ENODEV; 507 } 508 509 rcu_read_lock(); 510 511 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 512 if (hard_iface->soft_iface != soft_iface) 513 continue; 514 515 if (i++ < skip) 516 continue; 517 518 if (batadv_netlink_dump_hardif_entry(msg, portid, seq, 519 hard_iface)) { 520 i--; 521 break; 522 } 523 } 524 525 rcu_read_unlock(); 526 527 dev_put(soft_iface); 528 529 cb->args[0] = i; 530 531 return msg->len; 532 } 533 534 static const struct genl_ops batadv_netlink_ops[] = { 535 { 536 .cmd = BATADV_CMD_GET_MESH_INFO, 537 .flags = GENL_ADMIN_PERM, 538 .policy = batadv_netlink_policy, 539 .doit = batadv_netlink_get_mesh_info, 540 }, 541 { 542 .cmd = BATADV_CMD_TP_METER, 543 .flags = GENL_ADMIN_PERM, 544 .policy = batadv_netlink_policy, 545 .doit = batadv_netlink_tp_meter_start, 546 }, 547 { 548 .cmd = BATADV_CMD_TP_METER_CANCEL, 549 .flags = GENL_ADMIN_PERM, 550 .policy = batadv_netlink_policy, 551 .doit = batadv_netlink_tp_meter_cancel, 552 }, 553 { 554 .cmd = BATADV_CMD_GET_ROUTING_ALGOS, 555 .flags = GENL_ADMIN_PERM, 556 .policy = batadv_netlink_policy, 557 .dumpit = batadv_algo_dump, 558 }, 559 { 560 .cmd = BATADV_CMD_GET_HARDIFS, 561 .flags = GENL_ADMIN_PERM, 562 .policy = batadv_netlink_policy, 563 .dumpit = batadv_netlink_dump_hardifs, 564 }, 565 { 566 .cmd = BATADV_CMD_GET_TRANSTABLE_LOCAL, 567 .flags = GENL_ADMIN_PERM, 568 .policy = batadv_netlink_policy, 569 .dumpit = batadv_tt_local_dump, 570 }, 571 { 572 .cmd = BATADV_CMD_GET_TRANSTABLE_GLOBAL, 573 .flags = GENL_ADMIN_PERM, 574 .policy = batadv_netlink_policy, 575 .dumpit = batadv_tt_global_dump, 576 }, 577 { 578 .cmd = BATADV_CMD_GET_ORIGINATORS, 579 .flags = GENL_ADMIN_PERM, 580 .policy = batadv_netlink_policy, 581 .dumpit = batadv_orig_dump, 582 }, 583 { 584 .cmd = BATADV_CMD_GET_NEIGHBORS, 585 .flags = GENL_ADMIN_PERM, 586 .policy = batadv_netlink_policy, 587 .dumpit = batadv_hardif_neigh_dump, 588 }, 589 { 590 .cmd = BATADV_CMD_GET_GATEWAYS, 591 .flags = GENL_ADMIN_PERM, 592 .policy = batadv_netlink_policy, 593 .dumpit = batadv_gw_dump, 594 }, 595 { 596 .cmd = BATADV_CMD_GET_BLA_CLAIM, 597 .flags = GENL_ADMIN_PERM, 598 .policy = batadv_netlink_policy, 599 .dumpit = batadv_bla_claim_dump, 600 }, 601 { 602 .cmd = BATADV_CMD_GET_BLA_BACKBONE, 603 .flags = GENL_ADMIN_PERM, 604 .policy = batadv_netlink_policy, 605 .dumpit = batadv_bla_backbone_dump, 606 }, 607 608 }; 609 610 struct genl_family batadv_netlink_family __ro_after_init = { 611 .hdrsize = 0, 612 .name = BATADV_NL_NAME, 613 .version = 1, 614 .maxattr = BATADV_ATTR_MAX, 615 .netnsok = true, 616 .module = THIS_MODULE, 617 .ops = batadv_netlink_ops, 618 .n_ops = ARRAY_SIZE(batadv_netlink_ops), 619 .mcgrps = batadv_netlink_mcgrps, 620 .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps), 621 }; 622 623 /** 624 * batadv_netlink_register() - register batadv genl netlink family 625 */ 626 void __init batadv_netlink_register(void) 627 { 628 int ret; 629 630 ret = genl_register_family(&batadv_netlink_family); 631 if (ret) 632 pr_warn("unable to register netlink family"); 633 } 634 635 /** 636 * batadv_netlink_unregister() - unregister batadv genl netlink family 637 */ 638 void batadv_netlink_unregister(void) 639 { 640 genl_unregister_family(&batadv_netlink_family); 641 } 642