at v3.7 589 lines 16 kB view raw
1/* Copyright (C) 2007-2012 B.A.T.M.A.N. contributors: 2 * 3 * Marek Lindner, Simon Wunderlich 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, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 * 02110-1301, USA 18 */ 19 20#include "main.h" 21#include "hard-interface.h" 22#include "soft-interface.h" 23#include "send.h" 24#include "translation-table.h" 25#include "routing.h" 26#include "sysfs.h" 27#include "originator.h" 28#include "hash.h" 29#include "bridge_loop_avoidance.h" 30 31#include <linux/if_arp.h> 32 33void batadv_hardif_free_rcu(struct rcu_head *rcu) 34{ 35 struct batadv_hard_iface *hard_iface; 36 37 hard_iface = container_of(rcu, struct batadv_hard_iface, rcu); 38 dev_put(hard_iface->net_dev); 39 kfree(hard_iface); 40} 41 42struct batadv_hard_iface * 43batadv_hardif_get_by_netdev(const struct net_device *net_dev) 44{ 45 struct batadv_hard_iface *hard_iface; 46 47 rcu_read_lock(); 48 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 49 if (hard_iface->net_dev == net_dev && 50 atomic_inc_not_zero(&hard_iface->refcount)) 51 goto out; 52 } 53 54 hard_iface = NULL; 55 56out: 57 rcu_read_unlock(); 58 return hard_iface; 59} 60 61static int batadv_is_valid_iface(const struct net_device *net_dev) 62{ 63 if (net_dev->flags & IFF_LOOPBACK) 64 return 0; 65 66 if (net_dev->type != ARPHRD_ETHER) 67 return 0; 68 69 if (net_dev->addr_len != ETH_ALEN) 70 return 0; 71 72 /* no batman over batman */ 73 if (batadv_softif_is_valid(net_dev)) 74 return 0; 75 76 return 1; 77} 78 79static struct batadv_hard_iface * 80batadv_hardif_get_active(const struct net_device *soft_iface) 81{ 82 struct batadv_hard_iface *hard_iface; 83 84 rcu_read_lock(); 85 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 86 if (hard_iface->soft_iface != soft_iface) 87 continue; 88 89 if (hard_iface->if_status == BATADV_IF_ACTIVE && 90 atomic_inc_not_zero(&hard_iface->refcount)) 91 goto out; 92 } 93 94 hard_iface = NULL; 95 96out: 97 rcu_read_unlock(); 98 return hard_iface; 99} 100 101static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv, 102 struct batadv_hard_iface *oldif) 103{ 104 struct batadv_vis_packet *vis_packet; 105 struct batadv_hard_iface *primary_if; 106 struct sk_buff *skb; 107 108 primary_if = batadv_primary_if_get_selected(bat_priv); 109 if (!primary_if) 110 goto out; 111 112 skb = bat_priv->vis.my_info->skb_packet; 113 vis_packet = (struct batadv_vis_packet *)skb->data; 114 memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); 115 memcpy(vis_packet->sender_orig, 116 primary_if->net_dev->dev_addr, ETH_ALEN); 117 118 batadv_bla_update_orig_address(bat_priv, primary_if, oldif); 119out: 120 if (primary_if) 121 batadv_hardif_free_ref(primary_if); 122} 123 124static void batadv_primary_if_select(struct batadv_priv *bat_priv, 125 struct batadv_hard_iface *new_hard_iface) 126{ 127 struct batadv_hard_iface *curr_hard_iface; 128 129 ASSERT_RTNL(); 130 131 if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) 132 new_hard_iface = NULL; 133 134 curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1); 135 rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); 136 137 if (!new_hard_iface) 138 goto out; 139 140 bat_priv->bat_algo_ops->bat_primary_iface_set(new_hard_iface); 141 batadv_primary_if_update_addr(bat_priv, curr_hard_iface); 142 143out: 144 if (curr_hard_iface) 145 batadv_hardif_free_ref(curr_hard_iface); 146} 147 148static bool 149batadv_hardif_is_iface_up(const struct batadv_hard_iface *hard_iface) 150{ 151 if (hard_iface->net_dev->flags & IFF_UP) 152 return true; 153 154 return false; 155} 156 157static void batadv_check_known_mac_addr(const struct net_device *net_dev) 158{ 159 const struct batadv_hard_iface *hard_iface; 160 161 rcu_read_lock(); 162 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 163 if ((hard_iface->if_status != BATADV_IF_ACTIVE) && 164 (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED)) 165 continue; 166 167 if (hard_iface->net_dev == net_dev) 168 continue; 169 170 if (!batadv_compare_eth(hard_iface->net_dev->dev_addr, 171 net_dev->dev_addr)) 172 continue; 173 174 pr_warn("The newly added mac address (%pM) already exists on: %s\n", 175 net_dev->dev_addr, hard_iface->net_dev->name); 176 pr_warn("It is strongly recommended to keep mac addresses unique to avoid problems!\n"); 177 } 178 rcu_read_unlock(); 179} 180 181int batadv_hardif_min_mtu(struct net_device *soft_iface) 182{ 183 const struct batadv_priv *bat_priv = netdev_priv(soft_iface); 184 const struct batadv_hard_iface *hard_iface; 185 /* allow big frames if all devices are capable to do so 186 * (have MTU > 1500 + BAT_HEADER_LEN) 187 */ 188 int min_mtu = ETH_DATA_LEN; 189 190 if (atomic_read(&bat_priv->fragmentation)) 191 goto out; 192 193 rcu_read_lock(); 194 list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { 195 if ((hard_iface->if_status != BATADV_IF_ACTIVE) && 196 (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED)) 197 continue; 198 199 if (hard_iface->soft_iface != soft_iface) 200 continue; 201 202 min_mtu = min_t(int, 203 hard_iface->net_dev->mtu - BATADV_HEADER_LEN, 204 min_mtu); 205 } 206 rcu_read_unlock(); 207out: 208 return min_mtu; 209} 210 211/* adjusts the MTU if a new interface with a smaller MTU appeared. */ 212void batadv_update_min_mtu(struct net_device *soft_iface) 213{ 214 int min_mtu; 215 216 min_mtu = batadv_hardif_min_mtu(soft_iface); 217 if (soft_iface->mtu != min_mtu) 218 soft_iface->mtu = min_mtu; 219} 220 221static void 222batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface) 223{ 224 struct batadv_priv *bat_priv; 225 struct batadv_hard_iface *primary_if = NULL; 226 227 if (hard_iface->if_status != BATADV_IF_INACTIVE) 228 goto out; 229 230 bat_priv = netdev_priv(hard_iface->soft_iface); 231 232 bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface); 233 hard_iface->if_status = BATADV_IF_TO_BE_ACTIVATED; 234 235 /* the first active interface becomes our primary interface or 236 * the next active interface after the old primary interface was removed 237 */ 238 primary_if = batadv_primary_if_get_selected(bat_priv); 239 if (!primary_if) 240 batadv_primary_if_select(bat_priv, hard_iface); 241 242 batadv_info(hard_iface->soft_iface, "Interface activated: %s\n", 243 hard_iface->net_dev->name); 244 245 batadv_update_min_mtu(hard_iface->soft_iface); 246 247out: 248 if (primary_if) 249 batadv_hardif_free_ref(primary_if); 250} 251 252static void 253batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface) 254{ 255 if ((hard_iface->if_status != BATADV_IF_ACTIVE) && 256 (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED)) 257 return; 258 259 hard_iface->if_status = BATADV_IF_INACTIVE; 260 261 batadv_info(hard_iface->soft_iface, "Interface deactivated: %s\n", 262 hard_iface->net_dev->name); 263 264 batadv_update_min_mtu(hard_iface->soft_iface); 265} 266 267int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, 268 const char *iface_name) 269{ 270 struct batadv_priv *bat_priv; 271 struct net_device *soft_iface; 272 __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN); 273 int ret; 274 275 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 276 goto out; 277 278 if (!atomic_inc_not_zero(&hard_iface->refcount)) 279 goto out; 280 281 /* hard-interface is part of a bridge */ 282 if (hard_iface->net_dev->priv_flags & IFF_BRIDGE_PORT) 283 pr_err("You are about to enable batman-adv on '%s' which already is part of a bridge. Unless you know exactly what you are doing this is probably wrong and won't work the way you think it would.\n", 284 hard_iface->net_dev->name); 285 286 soft_iface = dev_get_by_name(&init_net, iface_name); 287 288 if (!soft_iface) { 289 soft_iface = batadv_softif_create(iface_name); 290 291 if (!soft_iface) { 292 ret = -ENOMEM; 293 goto err; 294 } 295 296 /* dev_get_by_name() increases the reference counter for us */ 297 dev_hold(soft_iface); 298 } 299 300 if (!batadv_softif_is_valid(soft_iface)) { 301 pr_err("Can't create batman mesh interface %s: already exists as regular interface\n", 302 soft_iface->name); 303 ret = -EINVAL; 304 goto err_dev; 305 } 306 307 hard_iface->soft_iface = soft_iface; 308 bat_priv = netdev_priv(hard_iface->soft_iface); 309 310 ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface); 311 if (ret < 0) 312 goto err_dev; 313 314 hard_iface->if_num = bat_priv->num_ifaces; 315 bat_priv->num_ifaces++; 316 hard_iface->if_status = BATADV_IF_INACTIVE; 317 ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces); 318 if (ret < 0) { 319 bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); 320 bat_priv->num_ifaces--; 321 hard_iface->if_status = BATADV_IF_NOT_IN_USE; 322 goto err_dev; 323 } 324 325 hard_iface->batman_adv_ptype.type = ethertype; 326 hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv; 327 hard_iface->batman_adv_ptype.dev = hard_iface->net_dev; 328 dev_add_pack(&hard_iface->batman_adv_ptype); 329 330 atomic_set(&hard_iface->frag_seqno, 1); 331 batadv_info(hard_iface->soft_iface, "Adding interface: %s\n", 332 hard_iface->net_dev->name); 333 334 if (atomic_read(&bat_priv->fragmentation) && 335 hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN) 336 batadv_info(hard_iface->soft_iface, 337 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %zi would solve the problem.\n", 338 hard_iface->net_dev->name, hard_iface->net_dev->mtu, 339 ETH_DATA_LEN + BATADV_HEADER_LEN); 340 341 if (!atomic_read(&bat_priv->fragmentation) && 342 hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN) 343 batadv_info(hard_iface->soft_iface, 344 "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %zi.\n", 345 hard_iface->net_dev->name, hard_iface->net_dev->mtu, 346 ETH_DATA_LEN + BATADV_HEADER_LEN); 347 348 if (batadv_hardif_is_iface_up(hard_iface)) 349 batadv_hardif_activate_interface(hard_iface); 350 else 351 batadv_err(hard_iface->soft_iface, 352 "Not using interface %s (retrying later): interface not active\n", 353 hard_iface->net_dev->name); 354 355 /* begin scheduling originator messages on that interface */ 356 batadv_schedule_bat_ogm(hard_iface); 357 358out: 359 return 0; 360 361err_dev: 362 dev_put(soft_iface); 363err: 364 batadv_hardif_free_ref(hard_iface); 365 return ret; 366} 367 368void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface) 369{ 370 struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); 371 struct batadv_hard_iface *primary_if = NULL; 372 373 if (hard_iface->if_status == BATADV_IF_ACTIVE) 374 batadv_hardif_deactivate_interface(hard_iface); 375 376 if (hard_iface->if_status != BATADV_IF_INACTIVE) 377 goto out; 378 379 batadv_info(hard_iface->soft_iface, "Removing interface: %s\n", 380 hard_iface->net_dev->name); 381 dev_remove_pack(&hard_iface->batman_adv_ptype); 382 383 bat_priv->num_ifaces--; 384 batadv_orig_hash_del_if(hard_iface, bat_priv->num_ifaces); 385 386 primary_if = batadv_primary_if_get_selected(bat_priv); 387 if (hard_iface == primary_if) { 388 struct batadv_hard_iface *new_if; 389 390 new_if = batadv_hardif_get_active(hard_iface->soft_iface); 391 batadv_primary_if_select(bat_priv, new_if); 392 393 if (new_if) 394 batadv_hardif_free_ref(new_if); 395 } 396 397 bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); 398 hard_iface->if_status = BATADV_IF_NOT_IN_USE; 399 400 /* delete all references to this hard_iface */ 401 batadv_purge_orig_ref(bat_priv); 402 batadv_purge_outstanding_packets(bat_priv, hard_iface); 403 dev_put(hard_iface->soft_iface); 404 405 /* nobody uses this interface anymore */ 406 if (!bat_priv->num_ifaces) 407 batadv_softif_destroy(hard_iface->soft_iface); 408 409 hard_iface->soft_iface = NULL; 410 batadv_hardif_free_ref(hard_iface); 411 412out: 413 if (primary_if) 414 batadv_hardif_free_ref(primary_if); 415} 416 417static struct batadv_hard_iface * 418batadv_hardif_add_interface(struct net_device *net_dev) 419{ 420 struct batadv_hard_iface *hard_iface; 421 int ret; 422 423 ASSERT_RTNL(); 424 425 ret = batadv_is_valid_iface(net_dev); 426 if (ret != 1) 427 goto out; 428 429 dev_hold(net_dev); 430 431 hard_iface = kmalloc(sizeof(*hard_iface), GFP_ATOMIC); 432 if (!hard_iface) 433 goto release_dev; 434 435 ret = batadv_sysfs_add_hardif(&hard_iface->hardif_obj, net_dev); 436 if (ret) 437 goto free_if; 438 439 hard_iface->if_num = -1; 440 hard_iface->net_dev = net_dev; 441 hard_iface->soft_iface = NULL; 442 hard_iface->if_status = BATADV_IF_NOT_IN_USE; 443 INIT_LIST_HEAD(&hard_iface->list); 444 /* extra reference for return */ 445 atomic_set(&hard_iface->refcount, 2); 446 447 batadv_check_known_mac_addr(hard_iface->net_dev); 448 list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); 449 450 /* This can't be called via a bat_priv callback because 451 * we have no bat_priv yet. 452 */ 453 atomic_set(&hard_iface->seqno, 1); 454 hard_iface->packet_buff = NULL; 455 456 return hard_iface; 457 458free_if: 459 kfree(hard_iface); 460release_dev: 461 dev_put(net_dev); 462out: 463 return NULL; 464} 465 466static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface) 467{ 468 ASSERT_RTNL(); 469 470 /* first deactivate interface */ 471 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 472 batadv_hardif_disable_interface(hard_iface); 473 474 if (hard_iface->if_status != BATADV_IF_NOT_IN_USE) 475 return; 476 477 hard_iface->if_status = BATADV_IF_TO_BE_REMOVED; 478 batadv_sysfs_del_hardif(&hard_iface->hardif_obj); 479 batadv_hardif_free_ref(hard_iface); 480} 481 482void batadv_hardif_remove_interfaces(void) 483{ 484 struct batadv_hard_iface *hard_iface, *hard_iface_tmp; 485 486 rtnl_lock(); 487 list_for_each_entry_safe(hard_iface, hard_iface_tmp, 488 &batadv_hardif_list, list) { 489 list_del_rcu(&hard_iface->list); 490 batadv_hardif_remove_interface(hard_iface); 491 } 492 rtnl_unlock(); 493} 494 495static int batadv_hard_if_event(struct notifier_block *this, 496 unsigned long event, void *ptr) 497{ 498 struct net_device *net_dev = ptr; 499 struct batadv_hard_iface *hard_iface; 500 struct batadv_hard_iface *primary_if = NULL; 501 struct batadv_priv *bat_priv; 502 503 hard_iface = batadv_hardif_get_by_netdev(net_dev); 504 if (!hard_iface && event == NETDEV_REGISTER) 505 hard_iface = batadv_hardif_add_interface(net_dev); 506 507 if (!hard_iface) 508 goto out; 509 510 switch (event) { 511 case NETDEV_UP: 512 batadv_hardif_activate_interface(hard_iface); 513 break; 514 case NETDEV_GOING_DOWN: 515 case NETDEV_DOWN: 516 batadv_hardif_deactivate_interface(hard_iface); 517 break; 518 case NETDEV_UNREGISTER: 519 list_del_rcu(&hard_iface->list); 520 521 batadv_hardif_remove_interface(hard_iface); 522 break; 523 case NETDEV_CHANGEMTU: 524 if (hard_iface->soft_iface) 525 batadv_update_min_mtu(hard_iface->soft_iface); 526 break; 527 case NETDEV_CHANGEADDR: 528 if (hard_iface->if_status == BATADV_IF_NOT_IN_USE) 529 goto hardif_put; 530 531 batadv_check_known_mac_addr(hard_iface->net_dev); 532 533 bat_priv = netdev_priv(hard_iface->soft_iface); 534 bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface); 535 536 primary_if = batadv_primary_if_get_selected(bat_priv); 537 if (!primary_if) 538 goto hardif_put; 539 540 if (hard_iface == primary_if) 541 batadv_primary_if_update_addr(bat_priv, NULL); 542 break; 543 default: 544 break; 545 } 546 547hardif_put: 548 batadv_hardif_free_ref(hard_iface); 549out: 550 if (primary_if) 551 batadv_hardif_free_ref(primary_if); 552 return NOTIFY_DONE; 553} 554 555/* This function returns true if the interface represented by ifindex is a 556 * 802.11 wireless device 557 */ 558bool batadv_is_wifi_iface(int ifindex) 559{ 560 struct net_device *net_device = NULL; 561 bool ret = false; 562 563 if (ifindex == BATADV_NULL_IFINDEX) 564 goto out; 565 566 net_device = dev_get_by_index(&init_net, ifindex); 567 if (!net_device) 568 goto out; 569 570#ifdef CONFIG_WIRELESS_EXT 571 /* pre-cfg80211 drivers have to implement WEXT, so it is possible to 572 * check for wireless_handlers != NULL 573 */ 574 if (net_device->wireless_handlers) 575 ret = true; 576 else 577#endif 578 /* cfg80211 drivers have to set ieee80211_ptr */ 579 if (net_device->ieee80211_ptr) 580 ret = true; 581out: 582 if (net_device) 583 dev_put(net_device); 584 return ret; 585} 586 587struct notifier_block batadv_hard_if_notifier = { 588 .notifier_call = batadv_hard_if_event, 589};