linux/net/batman-adv/hard-interface.c
<<
>>
Prefs
   1/* Copyright (C) 2007-2013 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 "distributed-arp-table.h"
  22#include "hard-interface.h"
  23#include "soft-interface.h"
  24#include "send.h"
  25#include "translation-table.h"
  26#include "routing.h"
  27#include "sysfs.h"
  28#include "originator.h"
  29#include "hash.h"
  30#include "bridge_loop_avoidance.h"
  31#include "gateway_client.h"
  32
  33#include <linux/if_arp.h>
  34#include <linux/if_ether.h>
  35
  36void batadv_hardif_free_rcu(struct rcu_head *rcu)
  37{
  38        struct batadv_hard_iface *hard_iface;
  39
  40        hard_iface = container_of(rcu, struct batadv_hard_iface, rcu);
  41        dev_put(hard_iface->net_dev);
  42        kfree(hard_iface);
  43}
  44
  45struct batadv_hard_iface *
  46batadv_hardif_get_by_netdev(const struct net_device *net_dev)
  47{
  48        struct batadv_hard_iface *hard_iface;
  49
  50        rcu_read_lock();
  51        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
  52                if (hard_iface->net_dev == net_dev &&
  53                    atomic_inc_not_zero(&hard_iface->refcount))
  54                        goto out;
  55        }
  56
  57        hard_iface = NULL;
  58
  59out:
  60        rcu_read_unlock();
  61        return hard_iface;
  62}
  63
  64/**
  65 * batadv_is_on_batman_iface - check if a device is a batman iface descendant
  66 * @net_dev: the device to check
  67 *
  68 * If the user creates any virtual device on top of a batman-adv interface, it
  69 * is important to prevent this new interface to be used to create a new mesh
  70 * network (this behaviour would lead to a batman-over-batman configuration).
  71 * This function recursively checks all the fathers of the device passed as
  72 * argument looking for a batman-adv soft interface.
  73 *
  74 * Returns true if the device is descendant of a batman-adv mesh interface (or
  75 * if it is a batman-adv interface itself), false otherwise
  76 */
  77static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
  78{
  79        struct net_device *parent_dev;
  80        bool ret;
  81
  82        /* check if this is a batman-adv mesh interface */
  83        if (batadv_softif_is_valid(net_dev))
  84                return true;
  85
  86        /* no more parents..stop recursion */
  87        if (net_dev->iflink == net_dev->ifindex)
  88                return false;
  89
  90        /* recurse over the parent device */
  91        parent_dev = dev_get_by_index(&init_net, net_dev->iflink);
  92        /* if we got a NULL parent_dev there is something broken.. */
  93        if (WARN(!parent_dev, "Cannot find parent device"))
  94                return false;
  95
  96        ret = batadv_is_on_batman_iface(parent_dev);
  97
  98        if (parent_dev)
  99                dev_put(parent_dev);
 100        return ret;
 101}
 102
 103static int batadv_is_valid_iface(const struct net_device *net_dev)
 104{
 105        if (net_dev->flags & IFF_LOOPBACK)
 106                return 0;
 107
 108        if (net_dev->type != ARPHRD_ETHER)
 109                return 0;
 110
 111        if (net_dev->addr_len != ETH_ALEN)
 112                return 0;
 113
 114        /* no batman over batman */
 115        if (batadv_is_on_batman_iface(net_dev))
 116                return 0;
 117
 118        return 1;
 119}
 120
 121/**
 122 * batadv_is_wifi_netdev - check if the given net_device struct is a wifi
 123 *  interface
 124 * @net_device: the device to check
 125 *
 126 * Returns true if the net device is a 802.11 wireless device, false otherwise.
 127 */
 128bool batadv_is_wifi_netdev(struct net_device *net_device)
 129{
 130        if (!net_device)
 131                return false;
 132
 133#ifdef CONFIG_WIRELESS_EXT
 134        /* pre-cfg80211 drivers have to implement WEXT, so it is possible to
 135         * check for wireless_handlers != NULL
 136         */
 137        if (net_device->wireless_handlers)
 138                return true;
 139#endif
 140
 141        /* cfg80211 drivers have to set ieee80211_ptr */
 142        if (net_device->ieee80211_ptr)
 143                return true;
 144
 145        return false;
 146}
 147
 148static struct batadv_hard_iface *
 149batadv_hardif_get_active(const struct net_device *soft_iface)
 150{
 151        struct batadv_hard_iface *hard_iface;
 152
 153        rcu_read_lock();
 154        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 155                if (hard_iface->soft_iface != soft_iface)
 156                        continue;
 157
 158                if (hard_iface->if_status == BATADV_IF_ACTIVE &&
 159                    atomic_inc_not_zero(&hard_iface->refcount))
 160                        goto out;
 161        }
 162
 163        hard_iface = NULL;
 164
 165out:
 166        rcu_read_unlock();
 167        return hard_iface;
 168}
 169
 170static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
 171                                          struct batadv_hard_iface *oldif)
 172{
 173        struct batadv_hard_iface *primary_if;
 174
 175        primary_if = batadv_primary_if_get_selected(bat_priv);
 176        if (!primary_if)
 177                goto out;
 178
 179        batadv_dat_init_own_addr(bat_priv, primary_if);
 180        batadv_bla_update_orig_address(bat_priv, primary_if, oldif);
 181out:
 182        if (primary_if)
 183                batadv_hardif_free_ref(primary_if);
 184}
 185
 186static void batadv_primary_if_select(struct batadv_priv *bat_priv,
 187                                     struct batadv_hard_iface *new_hard_iface)
 188{
 189        struct batadv_hard_iface *curr_hard_iface;
 190
 191        ASSERT_RTNL();
 192
 193        if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
 194                new_hard_iface = NULL;
 195
 196        curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1);
 197        rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
 198
 199        if (!new_hard_iface)
 200                goto out;
 201
 202        bat_priv->bat_algo_ops->bat_primary_iface_set(new_hard_iface);
 203        batadv_primary_if_update_addr(bat_priv, curr_hard_iface);
 204
 205out:
 206        if (curr_hard_iface)
 207                batadv_hardif_free_ref(curr_hard_iface);
 208}
 209
 210static bool
 211batadv_hardif_is_iface_up(const struct batadv_hard_iface *hard_iface)
 212{
 213        if (hard_iface->net_dev->flags & IFF_UP)
 214                return true;
 215
 216        return false;
 217}
 218
 219static void batadv_check_known_mac_addr(const struct net_device *net_dev)
 220{
 221        const struct batadv_hard_iface *hard_iface;
 222
 223        rcu_read_lock();
 224        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 225                if ((hard_iface->if_status != BATADV_IF_ACTIVE) &&
 226                    (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED))
 227                        continue;
 228
 229                if (hard_iface->net_dev == net_dev)
 230                        continue;
 231
 232                if (!batadv_compare_eth(hard_iface->net_dev->dev_addr,
 233                                        net_dev->dev_addr))
 234                        continue;
 235
 236                pr_warn("The newly added mac address (%pM) already exists on: %s\n",
 237                        net_dev->dev_addr, hard_iface->net_dev->name);
 238                pr_warn("It is strongly recommended to keep mac addresses unique to avoid problems!\n");
 239        }
 240        rcu_read_unlock();
 241}
 242
 243int batadv_hardif_min_mtu(struct net_device *soft_iface)
 244{
 245        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
 246        const struct batadv_hard_iface *hard_iface;
 247        int min_mtu = ETH_DATA_LEN;
 248
 249        rcu_read_lock();
 250        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
 251                if ((hard_iface->if_status != BATADV_IF_ACTIVE) &&
 252                    (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED))
 253                        continue;
 254
 255                if (hard_iface->soft_iface != soft_iface)
 256                        continue;
 257
 258                min_mtu = min_t(int, hard_iface->net_dev->mtu, min_mtu);
 259        }
 260        rcu_read_unlock();
 261
 262        atomic_set(&bat_priv->packet_size_max, min_mtu);
 263
 264        if (atomic_read(&bat_priv->fragmentation) == 0)
 265                goto out;
 266
 267        /* with fragmentation enabled the maximum size of internally generated
 268         * packets such as translation table exchanges or tvlv containers, etc
 269         * has to be calculated
 270         */
 271        min_mtu = min_t(int, min_mtu, BATADV_FRAG_MAX_FRAG_SIZE);
 272        min_mtu -= sizeof(struct batadv_frag_packet);
 273        min_mtu *= BATADV_FRAG_MAX_FRAGMENTS;
 274        atomic_set(&bat_priv->packet_size_max, min_mtu);
 275
 276        /* with fragmentation enabled we can fragment external packets easily */
 277        min_mtu = min_t(int, min_mtu, ETH_DATA_LEN);
 278
 279out:
 280        return min_mtu - batadv_max_header_len();
 281}
 282
 283/* adjusts the MTU if a new interface with a smaller MTU appeared. */
 284void batadv_update_min_mtu(struct net_device *soft_iface)
 285{
 286        soft_iface->mtu = batadv_hardif_min_mtu(soft_iface);
 287
 288        /* Check if the local translate table should be cleaned up to match a
 289         * new (and smaller) MTU.
 290         */
 291        batadv_tt_local_resize_to_mtu(soft_iface);
 292}
 293
 294static void
 295batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface)
 296{
 297        struct batadv_priv *bat_priv;
 298        struct batadv_hard_iface *primary_if = NULL;
 299
 300        if (hard_iface->if_status != BATADV_IF_INACTIVE)
 301                goto out;
 302
 303        bat_priv = netdev_priv(hard_iface->soft_iface);
 304
 305        bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface);
 306        hard_iface->if_status = BATADV_IF_TO_BE_ACTIVATED;
 307
 308        /* the first active interface becomes our primary interface or
 309         * the next active interface after the old primary interface was removed
 310         */
 311        primary_if = batadv_primary_if_get_selected(bat_priv);
 312        if (!primary_if)
 313                batadv_primary_if_select(bat_priv, hard_iface);
 314
 315        batadv_info(hard_iface->soft_iface, "Interface activated: %s\n",
 316                    hard_iface->net_dev->name);
 317
 318        batadv_update_min_mtu(hard_iface->soft_iface);
 319
 320out:
 321        if (primary_if)
 322                batadv_hardif_free_ref(primary_if);
 323}
 324
 325static void
 326batadv_hardif_deactivate_interface(struct batadv_hard_iface *hard_iface)
 327{
 328        if ((hard_iface->if_status != BATADV_IF_ACTIVE) &&
 329            (hard_iface->if_status != BATADV_IF_TO_BE_ACTIVATED))
 330                return;
 331
 332        hard_iface->if_status = BATADV_IF_INACTIVE;
 333
 334        batadv_info(hard_iface->soft_iface, "Interface deactivated: %s\n",
 335                    hard_iface->net_dev->name);
 336
 337        batadv_update_min_mtu(hard_iface->soft_iface);
 338}
 339
 340/**
 341 * batadv_master_del_slave - remove hard_iface from the current master interface
 342 * @slave: the interface enslaved in another master
 343 * @master: the master from which slave has to be removed
 344 *
 345 * Invoke ndo_del_slave on master passing slave as argument. In this way slave
 346 * is free'd and master can correctly change its internal state.
 347 * Return 0 on success, a negative value representing the error otherwise
 348 */
 349static int batadv_master_del_slave(struct batadv_hard_iface *slave,
 350                                   struct net_device *master)
 351{
 352        int ret;
 353
 354        if (!master)
 355                return 0;
 356
 357        ret = -EBUSY;
 358        if (master->netdev_ops->ndo_del_slave)
 359                ret = master->netdev_ops->ndo_del_slave(master, slave->net_dev);
 360
 361        return ret;
 362}
 363
 364int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 365                                   const char *iface_name)
 366{
 367        struct batadv_priv *bat_priv;
 368        struct net_device *soft_iface, *master;
 369        __be16 ethertype = htons(ETH_P_BATMAN);
 370        int max_header_len = batadv_max_header_len();
 371        int ret;
 372
 373        if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
 374                goto out;
 375
 376        if (!atomic_inc_not_zero(&hard_iface->refcount))
 377                goto out;
 378
 379        soft_iface = dev_get_by_name(&init_net, iface_name);
 380
 381        if (!soft_iface) {
 382                soft_iface = batadv_softif_create(iface_name);
 383
 384                if (!soft_iface) {
 385                        ret = -ENOMEM;
 386                        goto err;
 387                }
 388
 389                /* dev_get_by_name() increases the reference counter for us */
 390                dev_hold(soft_iface);
 391        }
 392
 393        if (!batadv_softif_is_valid(soft_iface)) {
 394                pr_err("Can't create batman mesh interface %s: already exists as regular interface\n",
 395                       soft_iface->name);
 396                ret = -EINVAL;
 397                goto err_dev;
 398        }
 399
 400        /* check if the interface is enslaved in another virtual one and
 401         * in that case unlink it first
 402         */
 403        master = netdev_master_upper_dev_get(hard_iface->net_dev);
 404        ret = batadv_master_del_slave(hard_iface, master);
 405        if (ret)
 406                goto err_dev;
 407
 408        hard_iface->soft_iface = soft_iface;
 409        bat_priv = netdev_priv(hard_iface->soft_iface);
 410
 411        ret = netdev_master_upper_dev_link(hard_iface->net_dev, soft_iface);
 412        if (ret)
 413                goto err_dev;
 414
 415        ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface);
 416        if (ret < 0)
 417                goto err_upper;
 418
 419        hard_iface->if_num = bat_priv->num_ifaces;
 420        bat_priv->num_ifaces++;
 421        hard_iface->if_status = BATADV_IF_INACTIVE;
 422        ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
 423        if (ret < 0) {
 424                bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
 425                bat_priv->num_ifaces--;
 426                hard_iface->if_status = BATADV_IF_NOT_IN_USE;
 427                goto err_upper;
 428        }
 429
 430        hard_iface->batman_adv_ptype.type = ethertype;
 431        hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv;
 432        hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;
 433        dev_add_pack(&hard_iface->batman_adv_ptype);
 434
 435        batadv_info(hard_iface->soft_iface, "Adding interface: %s\n",
 436                    hard_iface->net_dev->name);
 437
 438        if (atomic_read(&bat_priv->fragmentation) &&
 439            hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
 440                batadv_info(hard_iface->soft_iface,
 441                            "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 %i would solve the problem.\n",
 442                            hard_iface->net_dev->name, hard_iface->net_dev->mtu,
 443                            ETH_DATA_LEN + max_header_len);
 444
 445        if (!atomic_read(&bat_priv->fragmentation) &&
 446            hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
 447                batadv_info(hard_iface->soft_iface,
 448                            "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 %i.\n",
 449                            hard_iface->net_dev->name, hard_iface->net_dev->mtu,
 450                            ETH_DATA_LEN + max_header_len);
 451
 452        if (batadv_hardif_is_iface_up(hard_iface))
 453                batadv_hardif_activate_interface(hard_iface);
 454        else
 455                batadv_err(hard_iface->soft_iface,
 456                           "Not using interface %s (retrying later): interface not active\n",
 457                           hard_iface->net_dev->name);
 458
 459        /* begin scheduling originator messages on that interface */
 460        batadv_schedule_bat_ogm(hard_iface);
 461
 462out:
 463        return 0;
 464
 465err_upper:
 466        netdev_upper_dev_unlink(hard_iface->net_dev, soft_iface);
 467err_dev:
 468        hard_iface->soft_iface = NULL;
 469        dev_put(soft_iface);
 470err:
 471        batadv_hardif_free_ref(hard_iface);
 472        return ret;
 473}
 474
 475void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
 476                                     enum batadv_hard_if_cleanup autodel)
 477{
 478        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 479        struct batadv_hard_iface *primary_if = NULL;
 480
 481        if (hard_iface->if_status == BATADV_IF_ACTIVE)
 482                batadv_hardif_deactivate_interface(hard_iface);
 483
 484        if (hard_iface->if_status != BATADV_IF_INACTIVE)
 485                goto out;
 486
 487        batadv_info(hard_iface->soft_iface, "Removing interface: %s\n",
 488                    hard_iface->net_dev->name);
 489        dev_remove_pack(&hard_iface->batman_adv_ptype);
 490
 491        bat_priv->num_ifaces--;
 492        batadv_orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
 493
 494        primary_if = batadv_primary_if_get_selected(bat_priv);
 495        if (hard_iface == primary_if) {
 496                struct batadv_hard_iface *new_if;
 497
 498                new_if = batadv_hardif_get_active(hard_iface->soft_iface);
 499                batadv_primary_if_select(bat_priv, new_if);
 500
 501                if (new_if)
 502                        batadv_hardif_free_ref(new_if);
 503        }
 504
 505        bat_priv->bat_algo_ops->bat_iface_disable(hard_iface);
 506        hard_iface->if_status = BATADV_IF_NOT_IN_USE;
 507
 508        /* delete all references to this hard_iface */
 509        batadv_purge_orig_ref(bat_priv);
 510        batadv_purge_outstanding_packets(bat_priv, hard_iface);
 511        dev_put(hard_iface->soft_iface);
 512
 513        /* nobody uses this interface anymore */
 514        if (!bat_priv->num_ifaces) {
 515                batadv_gw_check_client_stop(bat_priv);
 516
 517                if (autodel == BATADV_IF_CLEANUP_AUTO)
 518                        batadv_softif_destroy_sysfs(hard_iface->soft_iface);
 519        }
 520
 521        netdev_upper_dev_unlink(hard_iface->net_dev, hard_iface->soft_iface);
 522        hard_iface->soft_iface = NULL;
 523        batadv_hardif_free_ref(hard_iface);
 524
 525out:
 526        if (primary_if)
 527                batadv_hardif_free_ref(primary_if);
 528}
 529
 530/**
 531 * batadv_hardif_remove_interface_finish - cleans up the remains of a hardif
 532 * @work: work queue item
 533 *
 534 * Free the parts of the hard interface which can not be removed under
 535 * rtnl lock (to prevent deadlock situations).
 536 */
 537static void batadv_hardif_remove_interface_finish(struct work_struct *work)
 538{
 539        struct batadv_hard_iface *hard_iface;
 540
 541        hard_iface = container_of(work, struct batadv_hard_iface,
 542                                  cleanup_work);
 543
 544        batadv_sysfs_del_hardif(&hard_iface->hardif_obj);
 545        batadv_hardif_free_ref(hard_iface);
 546}
 547
 548static struct batadv_hard_iface *
 549batadv_hardif_add_interface(struct net_device *net_dev)
 550{
 551        struct batadv_hard_iface *hard_iface;
 552        int ret;
 553
 554        ASSERT_RTNL();
 555
 556        ret = batadv_is_valid_iface(net_dev);
 557        if (ret != 1)
 558                goto out;
 559
 560        dev_hold(net_dev);
 561
 562        hard_iface = kzalloc(sizeof(*hard_iface), GFP_ATOMIC);
 563        if (!hard_iface)
 564                goto release_dev;
 565
 566        ret = batadv_sysfs_add_hardif(&hard_iface->hardif_obj, net_dev);
 567        if (ret)
 568                goto free_if;
 569
 570        hard_iface->if_num = -1;
 571        hard_iface->net_dev = net_dev;
 572        hard_iface->soft_iface = NULL;
 573        hard_iface->if_status = BATADV_IF_NOT_IN_USE;
 574        INIT_LIST_HEAD(&hard_iface->list);
 575        INIT_WORK(&hard_iface->cleanup_work,
 576                  batadv_hardif_remove_interface_finish);
 577
 578        hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
 579        if (batadv_is_wifi_netdev(net_dev))
 580                hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
 581
 582        /* extra reference for return */
 583        atomic_set(&hard_iface->refcount, 2);
 584
 585        batadv_check_known_mac_addr(hard_iface->net_dev);
 586        list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
 587
 588        return hard_iface;
 589
 590free_if:
 591        kfree(hard_iface);
 592release_dev:
 593        dev_put(net_dev);
 594out:
 595        return NULL;
 596}
 597
 598static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
 599{
 600        ASSERT_RTNL();
 601
 602        /* first deactivate interface */
 603        if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
 604                batadv_hardif_disable_interface(hard_iface,
 605                                                BATADV_IF_CLEANUP_AUTO);
 606
 607        if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
 608                return;
 609
 610        hard_iface->if_status = BATADV_IF_TO_BE_REMOVED;
 611        queue_work(batadv_event_workqueue, &hard_iface->cleanup_work);
 612}
 613
 614void batadv_hardif_remove_interfaces(void)
 615{
 616        struct batadv_hard_iface *hard_iface, *hard_iface_tmp;
 617
 618        rtnl_lock();
 619        list_for_each_entry_safe(hard_iface, hard_iface_tmp,
 620                                 &batadv_hardif_list, list) {
 621                list_del_rcu(&hard_iface->list);
 622                batadv_hardif_remove_interface(hard_iface);
 623        }
 624        rtnl_unlock();
 625}
 626
 627static int batadv_hard_if_event(struct notifier_block *this,
 628                                unsigned long event, void *ptr)
 629{
 630        struct net_device *net_dev = netdev_notifier_info_to_dev(ptr);
 631        struct batadv_hard_iface *hard_iface;
 632        struct batadv_hard_iface *primary_if = NULL;
 633        struct batadv_priv *bat_priv;
 634
 635        if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
 636                batadv_sysfs_add_meshif(net_dev);
 637                bat_priv = netdev_priv(net_dev);
 638                batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS);
 639                return NOTIFY_DONE;
 640        }
 641
 642        hard_iface = batadv_hardif_get_by_netdev(net_dev);
 643        if (!hard_iface && event == NETDEV_REGISTER)
 644                hard_iface = batadv_hardif_add_interface(net_dev);
 645
 646        if (!hard_iface)
 647                goto out;
 648
 649        switch (event) {
 650        case NETDEV_UP:
 651                batadv_hardif_activate_interface(hard_iface);
 652                break;
 653        case NETDEV_GOING_DOWN:
 654        case NETDEV_DOWN:
 655                batadv_hardif_deactivate_interface(hard_iface);
 656                break;
 657        case NETDEV_UNREGISTER:
 658                list_del_rcu(&hard_iface->list);
 659
 660                batadv_hardif_remove_interface(hard_iface);
 661                break;
 662        case NETDEV_CHANGEMTU:
 663                if (hard_iface->soft_iface)
 664                        batadv_update_min_mtu(hard_iface->soft_iface);
 665                break;
 666        case NETDEV_CHANGEADDR:
 667                if (hard_iface->if_status == BATADV_IF_NOT_IN_USE)
 668                        goto hardif_put;
 669
 670                batadv_check_known_mac_addr(hard_iface->net_dev);
 671
 672                bat_priv = netdev_priv(hard_iface->soft_iface);
 673                bat_priv->bat_algo_ops->bat_iface_update_mac(hard_iface);
 674
 675                primary_if = batadv_primary_if_get_selected(bat_priv);
 676                if (!primary_if)
 677                        goto hardif_put;
 678
 679                if (hard_iface == primary_if)
 680                        batadv_primary_if_update_addr(bat_priv, NULL);
 681                break;
 682        default:
 683                break;
 684        }
 685
 686hardif_put:
 687        batadv_hardif_free_ref(hard_iface);
 688out:
 689        if (primary_if)
 690                batadv_hardif_free_ref(primary_if);
 691        return NOTIFY_DONE;
 692}
 693
 694struct notifier_block batadv_hard_if_notifier = {
 695        .notifier_call = batadv_hard_if_event,
 696};
 697