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