]>
Commit | Line | Data |
---|---|---|
5beef3c9 | 1 | /* |
9b6d10b7 | 2 | * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: |
5beef3c9 AL |
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" | |
5beef3c9 AL |
24 | #include "soft-interface.h" |
25 | #include "send.h" | |
26 | #include "translation-table.h" | |
27 | #include "routing.h" | |
208e13e4 ML |
28 | #include "bat_sysfs.h" |
29 | #include "originator.h" | |
5beef3c9 | 30 | #include "hash.h" |
5beef3c9 | 31 | |
208e13e4 | 32 | #include <linux/if_arp.h> |
96d592ed | 33 | #include <linux/netfilter_bridge.h> |
5beef3c9 | 34 | |
208e13e4 | 35 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) |
5beef3c9 | 36 | |
208e13e4 | 37 | struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev) |
5beef3c9 AL |
38 | { |
39 | struct batman_if *batman_if; | |
40 | ||
41 | rcu_read_lock(); | |
42 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
208e13e4 | 43 | if (batman_if->net_dev == net_dev) |
5beef3c9 AL |
44 | goto out; |
45 | } | |
46 | ||
47 | batman_if = NULL; | |
48 | ||
49 | out: | |
50 | rcu_read_unlock(); | |
51 | return batman_if; | |
52 | } | |
53 | ||
208e13e4 ML |
54 | static int is_valid_iface(struct net_device *net_dev) |
55 | { | |
56 | if (net_dev->flags & IFF_LOOPBACK) | |
57 | return 0; | |
58 | ||
59 | if (net_dev->type != ARPHRD_ETHER) | |
60 | return 0; | |
61 | ||
62 | if (net_dev->addr_len != ETH_ALEN) | |
63 | return 0; | |
64 | ||
65 | /* no batman over batman */ | |
66 | #ifdef HAVE_NET_DEVICE_OPS | |
67 | if (net_dev->netdev_ops->ndo_start_xmit == interface_tx) | |
68 | return 0; | |
69 | #else | |
70 | if (net_dev->hard_start_xmit == interface_tx) | |
71 | return 0; | |
72 | #endif | |
73 | ||
74 | /* Device is being bridged */ | |
f350a0a8 | 75 | /* if (net_dev->priv_flags & IFF_BRIDGE_PORT) |
208e13e4 ML |
76 | return 0; */ |
77 | ||
78 | return 1; | |
79 | } | |
80 | ||
81 | static struct batman_if *get_active_batman_if(void) | |
5beef3c9 AL |
82 | { |
83 | struct batman_if *batman_if; | |
5beef3c9 | 84 | |
208e13e4 | 85 | /* TODO: should check interfaces belonging to bat_priv */ |
5beef3c9 AL |
86 | rcu_read_lock(); |
87 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
208e13e4 ML |
88 | if (batman_if->if_status == IF_ACTIVE) |
89 | goto out; | |
5beef3c9 | 90 | } |
208e13e4 ML |
91 | |
92 | batman_if = NULL; | |
93 | ||
94 | out: | |
5beef3c9 | 95 | rcu_read_unlock(); |
208e13e4 ML |
96 | return batman_if; |
97 | } | |
5beef3c9 | 98 | |
208e13e4 ML |
99 | static void set_primary_if(struct bat_priv *bat_priv, |
100 | struct batman_if *batman_if) | |
101 | { | |
102 | struct batman_packet *batman_packet; | |
103 | ||
104 | bat_priv->primary_if = batman_if; | |
105 | ||
106 | if (!bat_priv->primary_if) | |
107 | return; | |
108 | ||
109 | set_main_if_addr(batman_if->net_dev->dev_addr); | |
110 | ||
111 | batman_packet = (struct batman_packet *)(batman_if->packet_buff); | |
e35fd5ec | 112 | batman_packet->flags = PRIMARIES_FIRST_HOP; |
208e13e4 ML |
113 | batman_packet->ttl = TTL; |
114 | ||
115 | /*** | |
116 | * hacky trick to make sure that we send the HNA information via | |
117 | * our new primary interface | |
118 | */ | |
119 | atomic_set(&hna_local_changed, 1); | |
120 | } | |
121 | ||
122 | static bool hardif_is_iface_up(struct batman_if *batman_if) | |
123 | { | |
124 | if (batman_if->net_dev->flags & IFF_UP) | |
125 | return true; | |
126 | ||
127 | return false; | |
128 | } | |
129 | ||
130 | static void update_mac_addresses(struct batman_if *batman_if) | |
131 | { | |
f86b9984 SE |
132 | if (!batman_if || !batman_if->packet_buff) |
133 | return; | |
134 | ||
208e13e4 ML |
135 | addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr); |
136 | ||
137 | memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig, | |
138 | batman_if->net_dev->dev_addr, ETH_ALEN); | |
139 | memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender, | |
140 | batman_if->net_dev->dev_addr, ETH_ALEN); | |
5beef3c9 AL |
141 | } |
142 | ||
143 | static void check_known_mac_addr(uint8_t *addr) | |
144 | { | |
145 | struct batman_if *batman_if; | |
5beef3c9 AL |
146 | |
147 | rcu_read_lock(); | |
148 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
208e13e4 ML |
149 | if ((batman_if->if_status != IF_ACTIVE) && |
150 | (batman_if->if_status != IF_TO_BE_ACTIVATED)) | |
5beef3c9 AL |
151 | continue; |
152 | ||
153 | if (!compare_orig(batman_if->net_dev->dev_addr, addr)) | |
154 | continue; | |
155 | ||
c1641862 SE |
156 | pr_warning("The newly added mac address (%pM) already exists " |
157 | "on: %s\n", addr, batman_if->dev); | |
158 | pr_warning("It is strongly recommended to keep mac addresses " | |
159 | "unique to avoid problems!\n"); | |
5beef3c9 AL |
160 | } |
161 | rcu_read_unlock(); | |
162 | } | |
163 | ||
208e13e4 ML |
164 | int hardif_min_mtu(void) |
165 | { | |
166 | struct batman_if *batman_if; | |
167 | /* allow big frames if all devices are capable to do so | |
168 | * (have MTU > 1500 + BAT_HEADER_LEN) */ | |
169 | int min_mtu = ETH_DATA_LEN; | |
170 | ||
171 | rcu_read_lock(); | |
172 | list_for_each_entry_rcu(batman_if, &if_list, list) { | |
173 | if ((batman_if->if_status == IF_ACTIVE) || | |
174 | (batman_if->if_status == IF_TO_BE_ACTIVATED)) | |
175 | min_mtu = MIN(batman_if->net_dev->mtu - BAT_HEADER_LEN, | |
176 | min_mtu); | |
177 | } | |
178 | rcu_read_unlock(); | |
179 | ||
180 | return min_mtu; | |
181 | } | |
182 | ||
5beef3c9 AL |
183 | /* adjusts the MTU if a new interface with a smaller MTU appeared. */ |
184 | void update_min_mtu(void) | |
185 | { | |
186 | int min_mtu; | |
187 | ||
188 | min_mtu = hardif_min_mtu(); | |
189 | if (soft_device->mtu != min_mtu) | |
190 | soft_device->mtu = min_mtu; | |
191 | } | |
192 | ||
c1641862 SE |
193 | static void hardif_activate_interface(struct net_device *net_dev, |
194 | struct bat_priv *bat_priv, | |
208e13e4 | 195 | struct batman_if *batman_if) |
5beef3c9 | 196 | { |
208e13e4 ML |
197 | if (batman_if->if_status != IF_INACTIVE) |
198 | return; | |
5beef3c9 | 199 | |
208e13e4 ML |
200 | update_mac_addresses(batman_if); |
201 | batman_if->if_status = IF_TO_BE_ACTIVATED; | |
5beef3c9 | 202 | |
208e13e4 ML |
203 | /** |
204 | * the first active interface becomes our primary interface or | |
205 | * the next active interface after the old primay interface was removed | |
206 | */ | |
207 | if (!bat_priv->primary_if) | |
208 | set_primary_if(bat_priv, batman_if); | |
5beef3c9 | 209 | |
c1641862 | 210 | bat_info(net_dev, "Interface activated: %s\n", batman_if->dev); |
5beef3c9 | 211 | |
208e13e4 ML |
212 | if (atomic_read(&module_state) == MODULE_INACTIVE) |
213 | activate_module(); | |
5beef3c9 | 214 | |
208e13e4 ML |
215 | update_min_mtu(); |
216 | return; | |
5beef3c9 AL |
217 | } |
218 | ||
c1641862 SE |
219 | static void hardif_deactivate_interface(struct net_device *net_dev, |
220 | struct batman_if *batman_if) | |
5beef3c9 | 221 | { |
208e13e4 ML |
222 | if ((batman_if->if_status != IF_ACTIVE) && |
223 | (batman_if->if_status != IF_TO_BE_ACTIVATED)) | |
5beef3c9 AL |
224 | return; |
225 | ||
208e13e4 | 226 | batman_if->if_status = IF_INACTIVE; |
5beef3c9 | 227 | |
c1641862 | 228 | bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev); |
208e13e4 ML |
229 | |
230 | update_min_mtu(); | |
5beef3c9 AL |
231 | } |
232 | ||
208e13e4 | 233 | int hardif_enable_interface(struct batman_if *batman_if) |
5beef3c9 | 234 | { |
208e13e4 ML |
235 | /* FIXME: each batman_if will be attached to a softif */ |
236 | struct bat_priv *bat_priv = netdev_priv(soft_device); | |
237 | struct batman_packet *batman_packet; | |
5beef3c9 | 238 | |
208e13e4 ML |
239 | if (batman_if->if_status != IF_NOT_IN_USE) |
240 | goto out; | |
5beef3c9 | 241 | |
208e13e4 ML |
242 | batman_if->packet_len = BAT_PACKET_LEN; |
243 | batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC); | |
5beef3c9 | 244 | |
208e13e4 | 245 | if (!batman_if->packet_buff) { |
c1641862 SE |
246 | bat_err(soft_device, "Can't add interface packet (%s): " |
247 | "out of memory\n", batman_if->dev); | |
208e13e4 ML |
248 | goto err; |
249 | } | |
5beef3c9 | 250 | |
208e13e4 ML |
251 | batman_packet = (struct batman_packet *)(batman_if->packet_buff); |
252 | batman_packet->packet_type = BAT_PACKET; | |
253 | batman_packet->version = COMPAT_VERSION; | |
254 | batman_packet->flags = 0; | |
255 | batman_packet->ttl = 2; | |
256 | batman_packet->tq = TQ_MAX_VALUE; | |
257 | batman_packet->num_hna = 0; | |
5beef3c9 | 258 | |
208e13e4 ML |
259 | batman_if->if_num = bat_priv->num_ifaces; |
260 | bat_priv->num_ifaces++; | |
261 | batman_if->if_status = IF_INACTIVE; | |
262 | orig_hash_add_if(batman_if, bat_priv->num_ifaces); | |
5beef3c9 | 263 | |
208e13e4 | 264 | atomic_set(&batman_if->seqno, 1); |
c1641862 | 265 | bat_info(soft_device, "Adding interface: %s\n", batman_if->dev); |
5beef3c9 | 266 | |
208e13e4 | 267 | if (hardif_is_iface_up(batman_if)) |
c1641862 | 268 | hardif_activate_interface(soft_device, bat_priv, batman_if); |
208e13e4 | 269 | else |
c1641862 SE |
270 | bat_err(soft_device, "Not using interface %s " |
271 | "(retrying later): interface not active\n", | |
272 | batman_if->dev); | |
5beef3c9 | 273 | |
208e13e4 ML |
274 | /* begin scheduling originator messages on that interface */ |
275 | schedule_own_packet(batman_if); | |
5beef3c9 | 276 | |
208e13e4 ML |
277 | out: |
278 | return 0; | |
5beef3c9 | 279 | |
208e13e4 ML |
280 | err: |
281 | return -ENOMEM; | |
5beef3c9 AL |
282 | } |
283 | ||
208e13e4 | 284 | void hardif_disable_interface(struct batman_if *batman_if) |
5beef3c9 | 285 | { |
208e13e4 ML |
286 | /* FIXME: each batman_if will be attached to a softif */ |
287 | struct bat_priv *bat_priv = netdev_priv(soft_device); | |
5beef3c9 | 288 | |
208e13e4 | 289 | if (batman_if->if_status == IF_ACTIVE) |
c1641862 | 290 | hardif_deactivate_interface(soft_device, batman_if); |
5beef3c9 | 291 | |
208e13e4 ML |
292 | if (batman_if->if_status != IF_INACTIVE) |
293 | return; | |
5beef3c9 | 294 | |
c1641862 | 295 | bat_info(soft_device, "Removing interface: %s\n", batman_if->dev); |
208e13e4 ML |
296 | bat_priv->num_ifaces--; |
297 | orig_hash_del_if(batman_if, bat_priv->num_ifaces); | |
5beef3c9 | 298 | |
208e13e4 ML |
299 | if (batman_if == bat_priv->primary_if) |
300 | set_primary_if(bat_priv, get_active_batman_if()); | |
5beef3c9 | 301 | |
208e13e4 ML |
302 | kfree(batman_if->packet_buff); |
303 | batman_if->packet_buff = NULL; | |
304 | batman_if->if_status = IF_NOT_IN_USE; | |
5beef3c9 | 305 | |
208e13e4 ML |
306 | if ((atomic_read(&module_state) == MODULE_ACTIVE) && |
307 | (bat_priv->num_ifaces == 0)) | |
308 | deactivate_module(); | |
5beef3c9 AL |
309 | } |
310 | ||
208e13e4 | 311 | static struct batman_if *hardif_add_interface(struct net_device *net_dev) |
5beef3c9 AL |
312 | { |
313 | struct batman_if *batman_if; | |
208e13e4 | 314 | int ret; |
5beef3c9 | 315 | |
208e13e4 ML |
316 | ret = is_valid_iface(net_dev); |
317 | if (ret != 1) | |
318 | goto out; | |
5beef3c9 | 319 | |
51a00eaf SE |
320 | dev_hold(net_dev); |
321 | ||
208e13e4 | 322 | batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); |
5beef3c9 | 323 | if (!batman_if) { |
c1641862 | 324 | pr_err("Can't add interface (%s): out of memory\n", |
208e13e4 | 325 | net_dev->name); |
51a00eaf | 326 | goto release_dev; |
5beef3c9 AL |
327 | } |
328 | ||
208e13e4 ML |
329 | batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC); |
330 | if (!batman_if->dev) | |
331 | goto free_if; | |
5beef3c9 | 332 | |
208e13e4 ML |
333 | ret = sysfs_add_hardif(&batman_if->hardif_obj, net_dev); |
334 | if (ret) | |
335 | goto free_dev; | |
5beef3c9 | 336 | |
208e13e4 ML |
337 | batman_if->if_num = -1; |
338 | batman_if->net_dev = net_dev; | |
339 | batman_if->if_status = IF_NOT_IN_USE; | |
f86b9984 | 340 | batman_if->packet_buff = NULL; |
5beef3c9 AL |
341 | INIT_LIST_HEAD(&batman_if->list); |
342 | ||
208e13e4 ML |
343 | check_known_mac_addr(batman_if->net_dev->dev_addr); |
344 | list_add_tail_rcu(&batman_if->list, &if_list); | |
345 | return batman_if; | |
5beef3c9 | 346 | |
208e13e4 ML |
347 | free_dev: |
348 | kfree(batman_if->dev); | |
349 | free_if: | |
350 | kfree(batman_if); | |
51a00eaf SE |
351 | release_dev: |
352 | dev_put(net_dev); | |
208e13e4 ML |
353 | out: |
354 | return NULL; | |
355 | } | |
5beef3c9 | 356 | |
208e13e4 ML |
357 | static void hardif_free_interface(struct rcu_head *rcu) |
358 | { | |
359 | struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu); | |
5beef3c9 | 360 | |
208e13e4 ML |
361 | /* delete all references to this batman_if */ |
362 | purge_orig(NULL); | |
363 | purge_outstanding_packets(batman_if); | |
5beef3c9 | 364 | |
208e13e4 ML |
365 | kfree(batman_if->dev); |
366 | kfree(batman_if); | |
367 | } | |
5beef3c9 | 368 | |
208e13e4 ML |
369 | static void hardif_remove_interface(struct batman_if *batman_if) |
370 | { | |
371 | /* first deactivate interface */ | |
372 | if (batman_if->if_status != IF_NOT_IN_USE) | |
373 | hardif_disable_interface(batman_if); | |
5beef3c9 | 374 | |
208e13e4 ML |
375 | if (batman_if->if_status != IF_NOT_IN_USE) |
376 | return; | |
5beef3c9 | 377 | |
208e13e4 ML |
378 | batman_if->if_status = IF_TO_BE_REMOVED; |
379 | list_del_rcu(&batman_if->list); | |
380 | sysfs_del_hardif(&batman_if->hardif_obj); | |
51a00eaf | 381 | dev_put(batman_if->net_dev); |
208e13e4 | 382 | call_rcu(&batman_if->rcu, hardif_free_interface); |
5beef3c9 AL |
383 | } |
384 | ||
208e13e4 | 385 | void hardif_remove_interfaces(void) |
5beef3c9 | 386 | { |
208e13e4 ML |
387 | struct batman_if *batman_if, *batman_if_tmp; |
388 | ||
389 | list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) | |
390 | hardif_remove_interface(batman_if); | |
5beef3c9 AL |
391 | } |
392 | ||
393 | static int hard_if_event(struct notifier_block *this, | |
208e13e4 | 394 | unsigned long event, void *ptr) |
5beef3c9 | 395 | { |
208e13e4 ML |
396 | struct net_device *net_dev = (struct net_device *)ptr; |
397 | struct batman_if *batman_if = get_batman_if_by_netdev(net_dev); | |
398 | /* FIXME: each batman_if will be attached to a softif */ | |
399 | struct bat_priv *bat_priv = netdev_priv(soft_device); | |
400 | ||
1189f130 SE |
401 | if (!batman_if && event == NETDEV_REGISTER) |
402 | batman_if = hardif_add_interface(net_dev); | |
5beef3c9 AL |
403 | |
404 | if (!batman_if) | |
405 | goto out; | |
406 | ||
407 | switch (event) { | |
208e13e4 | 408 | case NETDEV_UP: |
c1641862 | 409 | hardif_activate_interface(soft_device, bat_priv, batman_if); |
208e13e4 | 410 | break; |
5beef3c9 AL |
411 | case NETDEV_GOING_DOWN: |
412 | case NETDEV_DOWN: | |
c1641862 | 413 | hardif_deactivate_interface(soft_device, batman_if); |
5beef3c9 | 414 | break; |
208e13e4 ML |
415 | case NETDEV_UNREGISTER: |
416 | hardif_remove_interface(batman_if); | |
417 | break; | |
418 | case NETDEV_CHANGENAME: | |
419 | break; | |
420 | case NETDEV_CHANGEADDR: | |
421 | check_known_mac_addr(batman_if->net_dev->dev_addr); | |
422 | update_mac_addresses(batman_if); | |
423 | if (batman_if == bat_priv->primary_if) | |
424 | set_primary_if(bat_priv, batman_if); | |
5beef3c9 | 425 | break; |
5beef3c9 | 426 | default: |
5beef3c9 AL |
427 | break; |
428 | }; | |
429 | ||
5beef3c9 AL |
430 | out: |
431 | return NOTIFY_DONE; | |
432 | } | |
433 | ||
96d592ed LL |
434 | static int batman_skb_recv_finish(struct sk_buff *skb) |
435 | { | |
436 | return NF_ACCEPT; | |
437 | } | |
438 | ||
e7017195 SW |
439 | /* receive a packet with the batman ethertype coming on a hard |
440 | * interface */ | |
441 | int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | |
442 | struct packet_type *ptype, struct net_device *orig_dev) | |
443 | { | |
84ec0864 ML |
444 | /* FIXME: each orig_node->batman_if will be attached to a softif */ |
445 | struct bat_priv *bat_priv = netdev_priv(soft_device); | |
e7017195 SW |
446 | struct batman_packet *batman_packet; |
447 | struct batman_if *batman_if; | |
e7017195 SW |
448 | int ret; |
449 | ||
da6d6c7a | 450 | skb = skb_share_check(skb, GFP_ATOMIC); |
e7017195 | 451 | |
da6d6c7a ML |
452 | /* skb was released by skb_share_check() */ |
453 | if (!skb) | |
454 | goto err_out; | |
e7017195 | 455 | |
af71b816 ML |
456 | if (atomic_read(&module_state) != MODULE_ACTIVE) |
457 | goto err_free; | |
458 | ||
96d592ed LL |
459 | /* if netfilter/ebtables wants to block incoming batman |
460 | * packets then give them a chance to do so here */ | |
461 | ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL, | |
462 | batman_skb_recv_finish); | |
463 | if (ret != 1) | |
464 | goto err_out; | |
465 | ||
e7017195 SW |
466 | /* packet should hold at least type and version */ |
467 | if (unlikely(skb_headlen(skb) < 2)) | |
468 | goto err_free; | |
469 | ||
470 | /* expect a valid ethernet header here. */ | |
471 | if (unlikely(skb->mac_len != sizeof(struct ethhdr) | |
472 | || !skb_mac_header(skb))) | |
473 | goto err_free; | |
474 | ||
208e13e4 | 475 | batman_if = get_batman_if_by_netdev(skb->dev); |
e7017195 SW |
476 | if (!batman_if) |
477 | goto err_free; | |
478 | ||
af71b816 | 479 | /* discard frames on not active interfaces */ |
208e13e4 | 480 | if (batman_if->if_status != IF_ACTIVE) |
af71b816 ML |
481 | goto err_free; |
482 | ||
e7017195 SW |
483 | batman_packet = (struct batman_packet *)skb->data; |
484 | ||
485 | if (batman_packet->version != COMPAT_VERSION) { | |
84ec0864 | 486 | bat_dbg(DBG_BATMAN, bat_priv, |
e7017195 SW |
487 | "Drop packet: incompatible batman version (%i)\n", |
488 | batman_packet->version); | |
489 | goto err_free; | |
490 | } | |
491 | ||
492 | /* all receive handlers return whether they received or reused | |
493 | * the supplied skb. if not, we have to free the skb. */ | |
494 | ||
495 | switch (batman_packet->packet_type) { | |
496 | /* batman originator packet */ | |
497 | case BAT_PACKET: | |
498 | ret = recv_bat_packet(skb, batman_if); | |
499 | break; | |
500 | ||
501 | /* batman icmp packet */ | |
502 | case BAT_ICMP: | |
503 | ret = recv_icmp_packet(skb); | |
504 | break; | |
505 | ||
506 | /* unicast packet */ | |
507 | case BAT_UNICAST: | |
11f79dec | 508 | ret = recv_unicast_packet(skb, batman_if); |
e7017195 SW |
509 | break; |
510 | ||
511 | /* broadcast packet */ | |
512 | case BAT_BCAST: | |
513 | ret = recv_bcast_packet(skb); | |
514 | break; | |
515 | ||
516 | /* vis packet */ | |
517 | case BAT_VIS: | |
518 | ret = recv_vis_packet(skb); | |
519 | break; | |
520 | default: | |
521 | ret = NET_RX_DROP; | |
522 | } | |
da6d6c7a | 523 | |
e7017195 SW |
524 | if (ret == NET_RX_DROP) |
525 | kfree_skb(skb); | |
526 | ||
527 | /* return NET_RX_SUCCESS in any case as we | |
528 | * most probably dropped the packet for | |
529 | * routing-logical reasons. */ | |
530 | ||
531 | return NET_RX_SUCCESS; | |
532 | ||
533 | err_free: | |
da6d6c7a ML |
534 | kfree_skb(skb); |
535 | err_out: | |
536 | return NET_RX_DROP; | |
e7017195 SW |
537 | } |
538 | ||
5beef3c9 | 539 | struct notifier_block hard_if_notifier = { |
bad2239e | 540 | .notifier_call = hard_if_event, |
5beef3c9 | 541 | }; |