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