Commit | Line | Data |
---|---|---|
c6c8fea2 | 1 | /* |
64afe353 | 2 | * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors: |
c6c8fea2 SE |
3 | * |
4 | * Marek Lindner, Simon Wunderlich | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of version 2 of the GNU General Public | |
8 | * License as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
18 | * 02110-1301, USA | |
19 | * | |
20 | */ | |
21 | ||
22 | #include "main.h" | |
23 | #include "hard-interface.h" | |
24 | #include "soft-interface.h" | |
25 | #include "send.h" | |
26 | #include "translation-table.h" | |
27 | #include "routing.h" | |
28 | #include "bat_sysfs.h" | |
29 | #include "originator.h" | |
30 | #include "hash.h" | |
31 | ||
32 | #include <linux/if_arp.h> | |
33 | ||
34 | /* protect update critical side of if_list - but not the content */ | |
35 | static DEFINE_SPINLOCK(if_list_lock); | |
36 | ||
fb86d764 SE |
37 | |
38 | static int batman_skb_recv(struct sk_buff *skb, | |
39 | struct net_device *dev, | |
40 | struct packet_type *ptype, | |
41 | struct net_device *orig_dev); | |
42 | ||
c6c8fea2 SE |
43 | static void hardif_free_rcu(struct rcu_head *rcu) |
44 | { | |
45 | struct batman_if *batman_if; | |
46 | ||
47 | batman_if = container_of(rcu, struct batman_if, rcu); | |
48 | dev_put(batman_if->net_dev); | |
49 | kref_put(&batman_if->refcount, hardif_free_ref); | |
50 | } | |
51 | ||
52 | struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev) | |
53 | { | |
54 | struct batman_if *batman_if; | |
55 | ||
56 | rcu_read_lock(); | |
57 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
58 | if (batman_if->net_dev == net_dev) | |
59 | goto out; | |
60 | } | |
61 | ||
62 | batman_if = NULL; | |
63 | ||
64 | out: | |
65 | if (batman_if) | |
66 | kref_get(&batman_if->refcount); | |
67 | ||
68 | rcu_read_unlock(); | |
69 | return batman_if; | |
70 | } | |
71 | ||
72 | static int is_valid_iface(struct net_device *net_dev) | |
73 | { | |
74 | if (net_dev->flags & IFF_LOOPBACK) | |
75 | return 0; | |
76 | ||
77 | if (net_dev->type != ARPHRD_ETHER) | |
78 | return 0; | |
79 | ||
80 | if (net_dev->addr_len != ETH_ALEN) | |
81 | return 0; | |
82 | ||
83 | /* no batman over batman */ | |
84 | #ifdef HAVE_NET_DEVICE_OPS | |
85 | if (net_dev->netdev_ops->ndo_start_xmit == interface_tx) | |
86 | return 0; | |
87 | #else | |
88 | if (net_dev->hard_start_xmit == interface_tx) | |
89 | return 0; | |
90 | #endif | |
91 | ||
92 | /* Device is being bridged */ | |
93 | /* if (net_dev->priv_flags & IFF_BRIDGE_PORT) | |
94 | return 0; */ | |
95 | ||
96 | return 1; | |
97 | } | |
98 | ||
99 | static struct batman_if *get_active_batman_if(struct net_device *soft_iface) | |
100 | { | |
101 | struct batman_if *batman_if; | |
102 | ||
103 | rcu_read_lock(); | |
104 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
105 | if (batman_if->soft_iface != soft_iface) | |
106 | continue; | |
107 | ||
108 | if (batman_if->if_status == IF_ACTIVE) | |
109 | goto out; | |
110 | } | |
111 | ||
112 | batman_if = NULL; | |
113 | ||
114 | out: | |
115 | if (batman_if) | |
116 | kref_get(&batman_if->refcount); | |
117 | ||
118 | rcu_read_unlock(); | |
119 | return batman_if; | |
120 | } | |
121 | ||
122 | static void update_primary_addr(struct bat_priv *bat_priv) | |
123 | { | |
124 | struct vis_packet *vis_packet; | |
125 | ||
126 | vis_packet = (struct vis_packet *) | |
127 | bat_priv->my_vis_info->skb_packet->data; | |
128 | memcpy(vis_packet->vis_orig, | |
129 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | |
130 | memcpy(vis_packet->sender_orig, | |
131 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | |
132 | } | |
133 | ||
134 | static void set_primary_if(struct bat_priv *bat_priv, | |
135 | struct batman_if *batman_if) | |
136 | { | |
137 | struct batman_packet *batman_packet; | |
138 | struct batman_if *old_if; | |
139 | ||
140 | if (batman_if) | |
141 | kref_get(&batman_if->refcount); | |
142 | ||
143 | old_if = bat_priv->primary_if; | |
144 | bat_priv->primary_if = batman_if; | |
145 | ||
146 | if (old_if) | |
147 | kref_put(&old_if->refcount, hardif_free_ref); | |
148 | ||
149 | if (!bat_priv->primary_if) | |
150 | return; | |
151 | ||
152 | batman_packet = (struct batman_packet *)(batman_if->packet_buff); | |
153 | batman_packet->flags = PRIMARIES_FIRST_HOP; | |
154 | batman_packet->ttl = TTL; | |
155 | ||
156 | update_primary_addr(bat_priv); | |
157 | ||
158 | /*** | |
159 | * hacky trick to make sure that we send the HNA information via | |
160 | * our new primary interface | |
161 | */ | |
162 | atomic_set(&bat_priv->hna_local_changed, 1); | |
163 | } | |
164 | ||
165 | static bool hardif_is_iface_up(struct batman_if *batman_if) | |
166 | { | |
167 | if (batman_if->net_dev->flags & IFF_UP) | |
168 | return true; | |
169 | ||
170 | return false; | |
171 | } | |
172 | ||
173 | static void update_mac_addresses(struct batman_if *batman_if) | |
174 | { | |
175 | memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, | |
176 | batman_if->net_dev->dev_addr, ETH_ALEN); | |
177 | memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender, | |
178 | batman_if->net_dev->dev_addr, ETH_ALEN); | |
179 | } | |
180 | ||
181 | static void check_known_mac_addr(struct net_device *net_dev) | |
182 | { | |
183 | struct batman_if *batman_if; | |
184 | ||
185 | rcu_read_lock(); | |
186 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
187 | if ((batman_if->if_status != IF_ACTIVE) && | |
188 | (batman_if->if_status != IF_TO_BE_ACTIVATED)) | |
189 | continue; | |
190 | ||
191 | if (batman_if->net_dev == net_dev) | |
192 | continue; | |
193 | ||
194 | if (!compare_orig(batman_if->net_dev->dev_addr, | |
195 | net_dev->dev_addr)) | |
196 | continue; | |
197 | ||
198 | pr_warning("The newly added mac address (%pM) already exists " | |
199 | "on: %s\n", net_dev->dev_addr, | |
200 | batman_if->net_dev->name); | |
201 | pr_warning("It is strongly recommended to keep mac addresses " | |
202 | "unique to avoid problems!\n"); | |
203 | } | |
204 | rcu_read_unlock(); | |
205 | } | |
206 | ||
207 | int hardif_min_mtu(struct net_device *soft_iface) | |
208 | { | |
209 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | |
210 | struct batman_if *batman_if; | |
211 | /* allow big frames if all devices are capable to do so | |
212 | * (have MTU > 1500 + BAT_HEADER_LEN) */ | |
213 | int min_mtu = ETH_DATA_LEN; | |
214 | ||
215 | if (atomic_read(&bat_priv->fragmentation)) | |
216 | goto out; | |
217 | ||
218 | rcu_read_lock(); | |
219 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
220 | if ((batman_if->if_status != IF_ACTIVE) && | |
221 | (batman_if->if_status != IF_TO_BE_ACTIVATED)) | |
222 | continue; | |
223 | ||
224 | if (batman_if->soft_iface != soft_iface) | |
225 | continue; | |
226 | ||
227 | min_mtu = min_t(int, batman_if->net_dev->mtu - BAT_HEADER_LEN, | |
228 | min_mtu); | |
229 | } | |
230 | rcu_read_unlock(); | |
231 | out: | |
232 | return min_mtu; | |
233 | } | |
234 | ||
235 | /* adjusts the MTU if a new interface with a smaller MTU appeared. */ | |
236 | void update_min_mtu(struct net_device *soft_iface) | |
237 | { | |
238 | int min_mtu; | |
239 | ||
240 | min_mtu = hardif_min_mtu(soft_iface); | |
241 | if (soft_iface->mtu != min_mtu) | |
242 | soft_iface->mtu = min_mtu; | |
243 | } | |
244 | ||
245 | static void hardif_activate_interface(struct batman_if *batman_if) | |
246 | { | |
247 | struct bat_priv *bat_priv; | |
248 | ||
249 | if (batman_if->if_status != IF_INACTIVE) | |
250 | return; | |
251 | ||
252 | bat_priv = netdev_priv(batman_if->soft_iface); | |
253 | ||
254 | update_mac_addresses(batman_if); | |
255 | batman_if->if_status = IF_TO_BE_ACTIVATED; | |
256 | ||
257 | /** | |
258 | * the first active interface becomes our primary interface or | |
259 | * the next active interface after the old primay interface was removed | |
260 | */ | |
261 | if (!bat_priv->primary_if) | |
262 | set_primary_if(bat_priv, batman_if); | |
263 | ||
264 | bat_info(batman_if->soft_iface, "Interface activated: %s\n", | |
265 | batman_if->net_dev->name); | |
266 | ||
267 | update_min_mtu(batman_if->soft_iface); | |
268 | return; | |
269 | } | |
270 | ||
271 | static void hardif_deactivate_interface(struct batman_if *batman_if) | |
272 | { | |
273 | if ((batman_if->if_status != IF_ACTIVE) && | |
a4c135c5 | 274 | (batman_if->if_status != IF_TO_BE_ACTIVATED)) |
c6c8fea2 SE |
275 | return; |
276 | ||
277 | batman_if->if_status = IF_INACTIVE; | |
278 | ||
279 | bat_info(batman_if->soft_iface, "Interface deactivated: %s\n", | |
280 | batman_if->net_dev->name); | |
281 | ||
282 | update_min_mtu(batman_if->soft_iface); | |
283 | } | |
284 | ||
285 | int hardif_enable_interface(struct batman_if *batman_if, char *iface_name) | |
286 | { | |
287 | struct bat_priv *bat_priv; | |
288 | struct batman_packet *batman_packet; | |
289 | ||
290 | if (batman_if->if_status != IF_NOT_IN_USE) | |
291 | goto out; | |
292 | ||
293 | batman_if->soft_iface = dev_get_by_name(&init_net, iface_name); | |
294 | ||
295 | if (!batman_if->soft_iface) { | |
296 | batman_if->soft_iface = softif_create(iface_name); | |
297 | ||
298 | if (!batman_if->soft_iface) | |
299 | goto err; | |
300 | ||
301 | /* dev_get_by_name() increases the reference counter for us */ | |
302 | dev_hold(batman_if->soft_iface); | |
303 | } | |
304 | ||
305 | bat_priv = netdev_priv(batman_if->soft_iface); | |
306 | batman_if->packet_len = BAT_PACKET_LEN; | |
307 | batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC); | |
308 | ||
309 | if (!batman_if->packet_buff) { | |
310 | bat_err(batman_if->soft_iface, "Can't add interface packet " | |
311 | "(%s): out of memory\n", batman_if->net_dev->name); | |
312 | goto err; | |
313 | } | |
314 | ||
315 | batman_packet = (struct batman_packet *)(batman_if->packet_buff); | |
316 | batman_packet->packet_type = BAT_PACKET; | |
317 | batman_packet->version = COMPAT_VERSION; | |
318 | batman_packet->flags = 0; | |
319 | batman_packet->ttl = 2; | |
320 | batman_packet->tq = TQ_MAX_VALUE; | |
321 | batman_packet->num_hna = 0; | |
322 | ||
323 | batman_if->if_num = bat_priv->num_ifaces; | |
324 | bat_priv->num_ifaces++; | |
325 | batman_if->if_status = IF_INACTIVE; | |
326 | orig_hash_add_if(batman_if, bat_priv->num_ifaces); | |
327 | ||
328 | batman_if->batman_adv_ptype.type = __constant_htons(ETH_P_BATMAN); | |
329 | batman_if->batman_adv_ptype.func = batman_skb_recv; | |
330 | batman_if->batman_adv_ptype.dev = batman_if->net_dev; | |
331 | kref_get(&batman_if->refcount); | |
332 | dev_add_pack(&batman_if->batman_adv_ptype); | |
333 | ||
334 | atomic_set(&batman_if->seqno, 1); | |
335 | atomic_set(&batman_if->frag_seqno, 1); | |
336 | bat_info(batman_if->soft_iface, "Adding interface: %s\n", | |
337 | batman_if->net_dev->name); | |
338 | ||
339 | if (atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu < | |
340 | ETH_DATA_LEN + BAT_HEADER_LEN) | |
341 | bat_info(batman_if->soft_iface, | |
342 | "The MTU of interface %s is too small (%i) to handle " | |
343 | "the transport of batman-adv packets. Packets going " | |
344 | "over this interface will be fragmented on layer2 " | |
345 | "which could impact the performance. Setting the MTU " | |
346 | "to %zi would solve the problem.\n", | |
347 | batman_if->net_dev->name, batman_if->net_dev->mtu, | |
348 | ETH_DATA_LEN + BAT_HEADER_LEN); | |
349 | ||
350 | if (!atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu < | |
351 | ETH_DATA_LEN + BAT_HEADER_LEN) | |
352 | bat_info(batman_if->soft_iface, | |
353 | "The MTU of interface %s is too small (%i) to handle " | |
354 | "the transport of batman-adv packets. If you experience" | |
355 | " problems getting traffic through try increasing the " | |
356 | "MTU to %zi.\n", | |
357 | batman_if->net_dev->name, batman_if->net_dev->mtu, | |
358 | ETH_DATA_LEN + BAT_HEADER_LEN); | |
359 | ||
360 | if (hardif_is_iface_up(batman_if)) | |
361 | hardif_activate_interface(batman_if); | |
362 | else | |
363 | bat_err(batman_if->soft_iface, "Not using interface %s " | |
364 | "(retrying later): interface not active\n", | |
365 | batman_if->net_dev->name); | |
366 | ||
367 | /* begin scheduling originator messages on that interface */ | |
368 | schedule_own_packet(batman_if); | |
369 | ||
370 | out: | |
371 | return 0; | |
372 | ||
373 | err: | |
374 | return -ENOMEM; | |
375 | } | |
376 | ||
377 | void hardif_disable_interface(struct batman_if *batman_if) | |
378 | { | |
379 | struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); | |
380 | ||
381 | if (batman_if->if_status == IF_ACTIVE) | |
382 | hardif_deactivate_interface(batman_if); | |
383 | ||
384 | if (batman_if->if_status != IF_INACTIVE) | |
385 | return; | |
386 | ||
387 | bat_info(batman_if->soft_iface, "Removing interface: %s\n", | |
388 | batman_if->net_dev->name); | |
389 | dev_remove_pack(&batman_if->batman_adv_ptype); | |
390 | kref_put(&batman_if->refcount, hardif_free_ref); | |
391 | ||
392 | bat_priv->num_ifaces--; | |
393 | orig_hash_del_if(batman_if, bat_priv->num_ifaces); | |
394 | ||
395 | if (batman_if == bat_priv->primary_if) { | |
396 | struct batman_if *new_if; | |
397 | ||
398 | new_if = get_active_batman_if(batman_if->soft_iface); | |
399 | set_primary_if(bat_priv, new_if); | |
400 | ||
401 | if (new_if) | |
402 | kref_put(&new_if->refcount, hardif_free_ref); | |
403 | } | |
404 | ||
405 | kfree(batman_if->packet_buff); | |
406 | batman_if->packet_buff = NULL; | |
407 | batman_if->if_status = IF_NOT_IN_USE; | |
408 | ||
409 | /* delete all references to this batman_if */ | |
410 | purge_orig_ref(bat_priv); | |
411 | purge_outstanding_packets(bat_priv, batman_if); | |
412 | dev_put(batman_if->soft_iface); | |
413 | ||
414 | /* nobody uses this interface anymore */ | |
415 | if (!bat_priv->num_ifaces) | |
416 | softif_destroy(batman_if->soft_iface); | |
417 | ||
418 | batman_if->soft_iface = NULL; | |
419 | } | |
420 | ||
421 | static struct batman_if *hardif_add_interface(struct net_device *net_dev) | |
422 | { | |
423 | struct batman_if *batman_if; | |
424 | int ret; | |
425 | ||
426 | ret = is_valid_iface(net_dev); | |
427 | if (ret != 1) | |
428 | goto out; | |
429 | ||
430 | dev_hold(net_dev); | |
431 | ||
432 | batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); | |
433 | if (!batman_if) { | |
434 | pr_err("Can't add interface (%s): out of memory\n", | |
435 | net_dev->name); | |
436 | goto release_dev; | |
437 | } | |
438 | ||
439 | ret = sysfs_add_hardif(&batman_if->hardif_obj, net_dev); | |
440 | if (ret) | |
441 | goto free_if; | |
442 | ||
443 | batman_if->if_num = -1; | |
444 | batman_if->net_dev = net_dev; | |
445 | batman_if->soft_iface = NULL; | |
446 | batman_if->if_status = IF_NOT_IN_USE; | |
447 | INIT_LIST_HEAD(&batman_if->list); | |
448 | kref_init(&batman_if->refcount); | |
449 | ||
450 | check_known_mac_addr(batman_if->net_dev); | |
451 | ||
452 | spin_lock(&if_list_lock); | |
453 | list_add_tail_rcu(&batman_if->list, &if_list); | |
454 | spin_unlock(&if_list_lock); | |
455 | ||
456 | /* extra reference for return */ | |
457 | kref_get(&batman_if->refcount); | |
458 | return batman_if; | |
459 | ||
460 | free_if: | |
461 | kfree(batman_if); | |
462 | release_dev: | |
463 | dev_put(net_dev); | |
464 | out: | |
465 | return NULL; | |
466 | } | |
467 | ||
468 | static void hardif_remove_interface(struct batman_if *batman_if) | |
469 | { | |
470 | /* first deactivate interface */ | |
471 | if (batman_if->if_status != IF_NOT_IN_USE) | |
472 | hardif_disable_interface(batman_if); | |
473 | ||
474 | if (batman_if->if_status != IF_NOT_IN_USE) | |
475 | return; | |
476 | ||
477 | batman_if->if_status = IF_TO_BE_REMOVED; | |
478 | sysfs_del_hardif(&batman_if->hardif_obj); | |
479 | call_rcu(&batman_if->rcu, hardif_free_rcu); | |
480 | } | |
481 | ||
482 | void hardif_remove_interfaces(void) | |
483 | { | |
484 | struct batman_if *batman_if, *batman_if_tmp; | |
485 | struct list_head if_queue; | |
486 | ||
487 | INIT_LIST_HEAD(&if_queue); | |
488 | ||
489 | spin_lock(&if_list_lock); | |
490 | list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) { | |
491 | list_del_rcu(&batman_if->list); | |
492 | list_add_tail(&batman_if->list, &if_queue); | |
493 | } | |
494 | spin_unlock(&if_list_lock); | |
495 | ||
496 | rtnl_lock(); | |
497 | list_for_each_entry_safe(batman_if, batman_if_tmp, &if_queue, list) { | |
498 | hardif_remove_interface(batman_if); | |
499 | } | |
500 | rtnl_unlock(); | |
501 | } | |
502 | ||
503 | static int hard_if_event(struct notifier_block *this, | |
504 | unsigned long event, void *ptr) | |
505 | { | |
506 | struct net_device *net_dev = (struct net_device *)ptr; | |
507 | struct batman_if *batman_if = get_batman_if_by_netdev(net_dev); | |
508 | struct bat_priv *bat_priv; | |
509 | ||
510 | if (!batman_if && event == NETDEV_REGISTER) | |
511 | batman_if = hardif_add_interface(net_dev); | |
512 | ||
513 | if (!batman_if) | |
514 | goto out; | |
515 | ||
516 | switch (event) { | |
517 | case NETDEV_UP: | |
518 | hardif_activate_interface(batman_if); | |
519 | break; | |
520 | case NETDEV_GOING_DOWN: | |
521 | case NETDEV_DOWN: | |
522 | hardif_deactivate_interface(batman_if); | |
523 | break; | |
524 | case NETDEV_UNREGISTER: | |
525 | spin_lock(&if_list_lock); | |
526 | list_del_rcu(&batman_if->list); | |
527 | spin_unlock(&if_list_lock); | |
528 | ||
529 | hardif_remove_interface(batman_if); | |
530 | break; | |
531 | case NETDEV_CHANGEMTU: | |
532 | if (batman_if->soft_iface) | |
533 | update_min_mtu(batman_if->soft_iface); | |
534 | break; | |
535 | case NETDEV_CHANGEADDR: | |
536 | if (batman_if->if_status == IF_NOT_IN_USE) | |
537 | goto hardif_put; | |
538 | ||
539 | check_known_mac_addr(batman_if->net_dev); | |
540 | update_mac_addresses(batman_if); | |
541 | ||
542 | bat_priv = netdev_priv(batman_if->soft_iface); | |
543 | if (batman_if == bat_priv->primary_if) | |
544 | update_primary_addr(bat_priv); | |
545 | break; | |
546 | default: | |
547 | break; | |
548 | }; | |
549 | ||
550 | hardif_put: | |
551 | kref_put(&batman_if->refcount, hardif_free_ref); | |
552 | out: | |
553 | return NOTIFY_DONE; | |
554 | } | |
555 | ||
556 | /* receive a packet with the batman ethertype coming on a hard | |
557 | * interface */ | |
fb86d764 SE |
558 | static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, |
559 | struct packet_type *ptype, | |
560 | struct net_device *orig_dev) | |
c6c8fea2 SE |
561 | { |
562 | struct bat_priv *bat_priv; | |
563 | struct batman_packet *batman_packet; | |
564 | struct batman_if *batman_if; | |
565 | int ret; | |
566 | ||
567 | batman_if = container_of(ptype, struct batman_if, batman_adv_ptype); | |
568 | skb = skb_share_check(skb, GFP_ATOMIC); | |
569 | ||
570 | /* skb was released by skb_share_check() */ | |
571 | if (!skb) | |
572 | goto err_out; | |
573 | ||
574 | /* packet should hold at least type and version */ | |
575 | if (unlikely(!pskb_may_pull(skb, 2))) | |
576 | goto err_free; | |
577 | ||
578 | /* expect a valid ethernet header here. */ | |
579 | if (unlikely(skb->mac_len != sizeof(struct ethhdr) | |
580 | || !skb_mac_header(skb))) | |
581 | goto err_free; | |
582 | ||
583 | if (!batman_if->soft_iface) | |
584 | goto err_free; | |
585 | ||
586 | bat_priv = netdev_priv(batman_if->soft_iface); | |
587 | ||
588 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) | |
589 | goto err_free; | |
590 | ||
591 | /* discard frames on not active interfaces */ | |
592 | if (batman_if->if_status != IF_ACTIVE) | |
593 | goto err_free; | |
594 | ||
595 | batman_packet = (struct batman_packet *)skb->data; | |
596 | ||
597 | if (batman_packet->version != COMPAT_VERSION) { | |
598 | bat_dbg(DBG_BATMAN, bat_priv, | |
599 | "Drop packet: incompatible batman version (%i)\n", | |
600 | batman_packet->version); | |
601 | goto err_free; | |
602 | } | |
603 | ||
604 | /* all receive handlers return whether they received or reused | |
605 | * the supplied skb. if not, we have to free the skb. */ | |
606 | ||
607 | switch (batman_packet->packet_type) { | |
608 | /* batman originator packet */ | |
609 | case BAT_PACKET: | |
610 | ret = recv_bat_packet(skb, batman_if); | |
611 | break; | |
612 | ||
613 | /* batman icmp packet */ | |
614 | case BAT_ICMP: | |
615 | ret = recv_icmp_packet(skb, batman_if); | |
616 | break; | |
617 | ||
618 | /* unicast packet */ | |
619 | case BAT_UNICAST: | |
620 | ret = recv_unicast_packet(skb, batman_if); | |
621 | break; | |
622 | ||
623 | /* fragmented unicast packet */ | |
624 | case BAT_UNICAST_FRAG: | |
625 | ret = recv_ucast_frag_packet(skb, batman_if); | |
626 | break; | |
627 | ||
628 | /* broadcast packet */ | |
629 | case BAT_BCAST: | |
630 | ret = recv_bcast_packet(skb, batman_if); | |
631 | break; | |
632 | ||
633 | /* vis packet */ | |
634 | case BAT_VIS: | |
635 | ret = recv_vis_packet(skb, batman_if); | |
636 | break; | |
637 | default: | |
638 | ret = NET_RX_DROP; | |
639 | } | |
640 | ||
641 | if (ret == NET_RX_DROP) | |
642 | kfree_skb(skb); | |
643 | ||
644 | /* return NET_RX_SUCCESS in any case as we | |
645 | * most probably dropped the packet for | |
646 | * routing-logical reasons. */ | |
647 | ||
648 | return NET_RX_SUCCESS; | |
649 | ||
650 | err_free: | |
651 | kfree_skb(skb); | |
652 | err_out: | |
653 | return NET_RX_DROP; | |
654 | } | |
655 | ||
656 | struct notifier_block hard_if_notifier = { | |
657 | .notifier_call = hard_if_event, | |
658 | }; |