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