Root/
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 "routing.h" |
22 | #include "send.h" |
23 | #include "soft-interface.h" |
24 | #include "hard-interface.h" |
25 | #include "icmp_socket.h" |
26 | #include "translation-table.h" |
27 | #include "originator.h" |
28 | #include "bridge_loop_avoidance.h" |
29 | #include "distributed-arp-table.h" |
30 | #include "network-coding.h" |
31 | #include "fragmentation.h" |
32 | |
33 | #include <linux/if_vlan.h> |
34 | |
35 | static int batadv_route_unicast_packet(struct sk_buff *skb, |
36 | struct batadv_hard_iface *recv_if); |
37 | |
38 | static void _batadv_update_route(struct batadv_priv *bat_priv, |
39 | struct batadv_orig_node *orig_node, |
40 | struct batadv_neigh_node *neigh_node) |
41 | { |
42 | struct batadv_neigh_node *curr_router; |
43 | |
44 | curr_router = batadv_orig_node_get_router(orig_node); |
45 | |
46 | /* route deleted */ |
47 | if ((curr_router) && (!neigh_node)) { |
48 | batadv_dbg(BATADV_DBG_ROUTES, bat_priv, |
49 | "Deleting route towards: %pM\n", orig_node->orig); |
50 | batadv_tt_global_del_orig(bat_priv, orig_node, -1, |
51 | "Deleted route towards originator"); |
52 | |
53 | /* route added */ |
54 | } else if ((!curr_router) && (neigh_node)) { |
55 | batadv_dbg(BATADV_DBG_ROUTES, bat_priv, |
56 | "Adding route towards: %pM (via %pM)\n", |
57 | orig_node->orig, neigh_node->addr); |
58 | /* route changed */ |
59 | } else if (neigh_node && curr_router) { |
60 | batadv_dbg(BATADV_DBG_ROUTES, bat_priv, |
61 | "Changing route towards: %pM (now via %pM - was via %pM)\n", |
62 | orig_node->orig, neigh_node->addr, |
63 | curr_router->addr); |
64 | } |
65 | |
66 | if (curr_router) |
67 | batadv_neigh_node_free_ref(curr_router); |
68 | |
69 | /* increase refcount of new best neighbor */ |
70 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) |
71 | neigh_node = NULL; |
72 | |
73 | spin_lock_bh(&orig_node->neigh_list_lock); |
74 | rcu_assign_pointer(orig_node->router, neigh_node); |
75 | spin_unlock_bh(&orig_node->neigh_list_lock); |
76 | |
77 | /* decrease refcount of previous best neighbor */ |
78 | if (curr_router) |
79 | batadv_neigh_node_free_ref(curr_router); |
80 | } |
81 | |
82 | void batadv_update_route(struct batadv_priv *bat_priv, |
83 | struct batadv_orig_node *orig_node, |
84 | struct batadv_neigh_node *neigh_node) |
85 | { |
86 | struct batadv_neigh_node *router = NULL; |
87 | |
88 | if (!orig_node) |
89 | goto out; |
90 | |
91 | router = batadv_orig_node_get_router(orig_node); |
92 | |
93 | if (router != neigh_node) |
94 | _batadv_update_route(bat_priv, orig_node, neigh_node); |
95 | |
96 | out: |
97 | if (router) |
98 | batadv_neigh_node_free_ref(router); |
99 | } |
100 | |
101 | /* caller must hold the neigh_list_lock */ |
102 | void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node, |
103 | struct batadv_neigh_node *neigh_node) |
104 | { |
105 | /* this neighbor is not part of our candidate list */ |
106 | if (list_empty(&neigh_node->bonding_list)) |
107 | goto out; |
108 | |
109 | list_del_rcu(&neigh_node->bonding_list); |
110 | INIT_LIST_HEAD(&neigh_node->bonding_list); |
111 | batadv_neigh_node_free_ref(neigh_node); |
112 | atomic_dec(&orig_node->bond_candidates); |
113 | |
114 | out: |
115 | return; |
116 | } |
117 | |
118 | /** |
119 | * batadv_bonding_candidate_add - consider a new link for bonding mode towards |
120 | * the given originator |
121 | * @bat_priv: the bat priv with all the soft interface information |
122 | * @orig_node: the target node |
123 | * @neigh_node: the neighbor representing the new link to consider for bonding |
124 | * mode |
125 | */ |
126 | void batadv_bonding_candidate_add(struct batadv_priv *bat_priv, |
127 | struct batadv_orig_node *orig_node, |
128 | struct batadv_neigh_node *neigh_node) |
129 | { |
130 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; |
131 | struct batadv_neigh_node *tmp_neigh_node, *router = NULL; |
132 | uint8_t interference_candidate = 0; |
133 | |
134 | spin_lock_bh(&orig_node->neigh_list_lock); |
135 | |
136 | /* only consider if it has the same primary address ... */ |
137 | if (!batadv_compare_eth(orig_node->orig, |
138 | neigh_node->orig_node->primary_addr)) |
139 | goto candidate_del; |
140 | |
141 | router = batadv_orig_node_get_router(orig_node); |
142 | if (!router) |
143 | goto candidate_del; |
144 | |
145 | |
146 | /* ... and is good enough to be considered */ |
147 | if (bao->bat_neigh_is_equiv_or_better(neigh_node, router)) |
148 | goto candidate_del; |
149 | |
150 | /* check if we have another candidate with the same mac address or |
151 | * interface. If we do, we won't select this candidate because of |
152 | * possible interference. |
153 | */ |
154 | hlist_for_each_entry_rcu(tmp_neigh_node, |
155 | &orig_node->neigh_list, list) { |
156 | if (tmp_neigh_node == neigh_node) |
157 | continue; |
158 | |
159 | /* we only care if the other candidate is even |
160 | * considered as candidate. |
161 | */ |
162 | if (list_empty(&tmp_neigh_node->bonding_list)) |
163 | continue; |
164 | |
165 | if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) || |
166 | (batadv_compare_eth(neigh_node->addr, |
167 | tmp_neigh_node->addr))) { |
168 | interference_candidate = 1; |
169 | break; |
170 | } |
171 | } |
172 | |
173 | /* don't care further if it is an interference candidate */ |
174 | if (interference_candidate) |
175 | goto candidate_del; |
176 | |
177 | /* this neighbor already is part of our candidate list */ |
178 | if (!list_empty(&neigh_node->bonding_list)) |
179 | goto out; |
180 | |
181 | if (!atomic_inc_not_zero(&neigh_node->refcount)) |
182 | goto out; |
183 | |
184 | list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list); |
185 | atomic_inc(&orig_node->bond_candidates); |
186 | goto out; |
187 | |
188 | candidate_del: |
189 | batadv_bonding_candidate_del(orig_node, neigh_node); |
190 | |
191 | out: |
192 | spin_unlock_bh(&orig_node->neigh_list_lock); |
193 | |
194 | if (router) |
195 | batadv_neigh_node_free_ref(router); |
196 | } |
197 | |
198 | /* copy primary address for bonding */ |
199 | void |
200 | batadv_bonding_save_primary(const struct batadv_orig_node *orig_node, |
201 | struct batadv_orig_node *orig_neigh_node, |
202 | const struct batadv_ogm_packet *batman_ogm_packet) |
203 | { |
204 | if (!(batman_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP)) |
205 | return; |
206 | |
207 | memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN); |
208 | } |
209 | |
210 | /* checks whether the host restarted and is in the protection time. |
211 | * returns: |
212 | * 0 if the packet is to be accepted |
213 | * 1 if the packet is to be ignored. |
214 | */ |
215 | int batadv_window_protected(struct batadv_priv *bat_priv, int32_t seq_num_diff, |
216 | unsigned long *last_reset) |
217 | { |
218 | if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE || |
219 | seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) { |
220 | if (!batadv_has_timed_out(*last_reset, |
221 | BATADV_RESET_PROTECTION_MS)) |
222 | return 1; |
223 | |
224 | *last_reset = jiffies; |
225 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
226 | "old packet received, start protection\n"); |
227 | } |
228 | |
229 | return 0; |
230 | } |
231 | |
232 | bool batadv_check_management_packet(struct sk_buff *skb, |
233 | struct batadv_hard_iface *hard_iface, |
234 | int header_len) |
235 | { |
236 | struct ethhdr *ethhdr; |
237 | |
238 | /* drop packet if it has not necessary minimum size */ |
239 | if (unlikely(!pskb_may_pull(skb, header_len))) |
240 | return false; |
241 | |
242 | ethhdr = eth_hdr(skb); |
243 | |
244 | /* packet with broadcast indication but unicast recipient */ |
245 | if (!is_broadcast_ether_addr(ethhdr->h_dest)) |
246 | return false; |
247 | |
248 | /* packet with broadcast sender address */ |
249 | if (is_broadcast_ether_addr(ethhdr->h_source)) |
250 | return false; |
251 | |
252 | /* create a copy of the skb, if needed, to modify it. */ |
253 | if (skb_cow(skb, 0) < 0) |
254 | return false; |
255 | |
256 | /* keep skb linear */ |
257 | if (skb_linearize(skb) < 0) |
258 | return false; |
259 | |
260 | return true; |
261 | } |
262 | |
263 | /** |
264 | * batadv_recv_my_icmp_packet - receive an icmp packet locally |
265 | * @bat_priv: the bat priv with all the soft interface information |
266 | * @skb: icmp packet to process |
267 | * |
268 | * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP |
269 | * otherwise. |
270 | */ |
271 | static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, |
272 | struct sk_buff *skb) |
273 | { |
274 | struct batadv_hard_iface *primary_if = NULL; |
275 | struct batadv_orig_node *orig_node = NULL; |
276 | struct batadv_icmp_header *icmph; |
277 | int res, ret = NET_RX_DROP; |
278 | |
279 | icmph = (struct batadv_icmp_header *)skb->data; |
280 | |
281 | switch (icmph->msg_type) { |
282 | case BATADV_ECHO_REPLY: |
283 | case BATADV_DESTINATION_UNREACHABLE: |
284 | case BATADV_TTL_EXCEEDED: |
285 | /* receive the packet */ |
286 | if (skb_linearize(skb) < 0) |
287 | break; |
288 | |
289 | batadv_socket_receive_packet(icmph, skb->len); |
290 | break; |
291 | case BATADV_ECHO_REQUEST: |
292 | /* answer echo request (ping) */ |
293 | primary_if = batadv_primary_if_get_selected(bat_priv); |
294 | if (!primary_if) |
295 | goto out; |
296 | |
297 | /* get routing information */ |
298 | orig_node = batadv_orig_hash_find(bat_priv, icmph->orig); |
299 | if (!orig_node) |
300 | goto out; |
301 | |
302 | /* create a copy of the skb, if needed, to modify it. */ |
303 | if (skb_cow(skb, ETH_HLEN) < 0) |
304 | goto out; |
305 | |
306 | icmph = (struct batadv_icmp_header *)skb->data; |
307 | |
308 | memcpy(icmph->dst, icmph->orig, ETH_ALEN); |
309 | memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
310 | icmph->msg_type = BATADV_ECHO_REPLY; |
311 | icmph->ttl = BATADV_TTL; |
312 | |
313 | res = batadv_send_skb_to_orig(skb, orig_node, NULL); |
314 | if (res != NET_XMIT_DROP) |
315 | ret = NET_RX_SUCCESS; |
316 | |
317 | break; |
318 | default: |
319 | /* drop unknown type */ |
320 | goto out; |
321 | } |
322 | out: |
323 | if (primary_if) |
324 | batadv_hardif_free_ref(primary_if); |
325 | if (orig_node) |
326 | batadv_orig_node_free_ref(orig_node); |
327 | return ret; |
328 | } |
329 | |
330 | static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv, |
331 | struct sk_buff *skb) |
332 | { |
333 | struct batadv_hard_iface *primary_if = NULL; |
334 | struct batadv_orig_node *orig_node = NULL; |
335 | struct batadv_icmp_packet *icmp_packet; |
336 | int ret = NET_RX_DROP; |
337 | |
338 | icmp_packet = (struct batadv_icmp_packet *)skb->data; |
339 | |
340 | /* send TTL exceeded if packet is an echo request (traceroute) */ |
341 | if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { |
342 | pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n", |
343 | icmp_packet->orig, icmp_packet->dst); |
344 | goto out; |
345 | } |
346 | |
347 | primary_if = batadv_primary_if_get_selected(bat_priv); |
348 | if (!primary_if) |
349 | goto out; |
350 | |
351 | /* get routing information */ |
352 | orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig); |
353 | if (!orig_node) |
354 | goto out; |
355 | |
356 | /* create a copy of the skb, if needed, to modify it. */ |
357 | if (skb_cow(skb, ETH_HLEN) < 0) |
358 | goto out; |
359 | |
360 | icmp_packet = (struct batadv_icmp_packet *)skb->data; |
361 | |
362 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
363 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, |
364 | ETH_ALEN); |
365 | icmp_packet->msg_type = BATADV_TTL_EXCEEDED; |
366 | icmp_packet->ttl = BATADV_TTL; |
367 | |
368 | if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) |
369 | ret = NET_RX_SUCCESS; |
370 | |
371 | out: |
372 | if (primary_if) |
373 | batadv_hardif_free_ref(primary_if); |
374 | if (orig_node) |
375 | batadv_orig_node_free_ref(orig_node); |
376 | return ret; |
377 | } |
378 | |
379 | |
380 | int batadv_recv_icmp_packet(struct sk_buff *skb, |
381 | struct batadv_hard_iface *recv_if) |
382 | { |
383 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
384 | struct batadv_icmp_header *icmph; |
385 | struct batadv_icmp_packet_rr *icmp_packet_rr; |
386 | struct ethhdr *ethhdr; |
387 | struct batadv_orig_node *orig_node = NULL; |
388 | int hdr_size = sizeof(struct batadv_icmp_header); |
389 | int ret = NET_RX_DROP; |
390 | |
391 | /* drop packet if it has not necessary minimum size */ |
392 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
393 | goto out; |
394 | |
395 | ethhdr = eth_hdr(skb); |
396 | |
397 | /* packet with unicast indication but broadcast recipient */ |
398 | if (is_broadcast_ether_addr(ethhdr->h_dest)) |
399 | goto out; |
400 | |
401 | /* packet with broadcast sender address */ |
402 | if (is_broadcast_ether_addr(ethhdr->h_source)) |
403 | goto out; |
404 | |
405 | /* not for me */ |
406 | if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest)) |
407 | goto out; |
408 | |
409 | icmph = (struct batadv_icmp_header *)skb->data; |
410 | |
411 | /* add record route information if not full */ |
412 | if ((icmph->msg_type == BATADV_ECHO_REPLY || |
413 | icmph->msg_type == BATADV_ECHO_REQUEST) && |
414 | (skb->len >= sizeof(struct batadv_icmp_packet_rr))) { |
415 | if (skb_linearize(skb) < 0) |
416 | goto out; |
417 | |
418 | /* create a copy of the skb, if needed, to modify it. */ |
419 | if (skb_cow(skb, ETH_HLEN) < 0) |
420 | goto out; |
421 | |
422 | icmph = (struct batadv_icmp_header *)skb->data; |
423 | icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmph; |
424 | if (icmp_packet_rr->rr_cur >= BATADV_RR_LEN) |
425 | goto out; |
426 | |
427 | memcpy(&(icmp_packet_rr->rr[icmp_packet_rr->rr_cur]), |
428 | ethhdr->h_dest, ETH_ALEN); |
429 | icmp_packet_rr->rr_cur++; |
430 | } |
431 | |
432 | /* packet for me */ |
433 | if (batadv_is_my_mac(bat_priv, icmph->dst)) |
434 | return batadv_recv_my_icmp_packet(bat_priv, skb); |
435 | |
436 | /* TTL exceeded */ |
437 | if (icmph->ttl < 2) |
438 | return batadv_recv_icmp_ttl_exceeded(bat_priv, skb); |
439 | |
440 | /* get routing information */ |
441 | orig_node = batadv_orig_hash_find(bat_priv, icmph->dst); |
442 | if (!orig_node) |
443 | goto out; |
444 | |
445 | /* create a copy of the skb, if needed, to modify it. */ |
446 | if (skb_cow(skb, ETH_HLEN) < 0) |
447 | goto out; |
448 | |
449 | icmph = (struct batadv_icmp_header *)skb->data; |
450 | |
451 | /* decrement ttl */ |
452 | icmph->ttl--; |
453 | |
454 | /* route it */ |
455 | if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP) |
456 | ret = NET_RX_SUCCESS; |
457 | |
458 | out: |
459 | if (orig_node) |
460 | batadv_orig_node_free_ref(orig_node); |
461 | return ret; |
462 | } |
463 | |
464 | /* In the bonding case, send the packets in a round |
465 | * robin fashion over the remaining interfaces. |
466 | * |
467 | * This method rotates the bonding list and increases the |
468 | * returned router's refcount. |
469 | */ |
470 | static struct batadv_neigh_node * |
471 | batadv_find_bond_router(struct batadv_orig_node *primary_orig, |
472 | const struct batadv_hard_iface *recv_if) |
473 | { |
474 | struct batadv_neigh_node *tmp_neigh_node; |
475 | struct batadv_neigh_node *router = NULL, *first_candidate = NULL; |
476 | |
477 | rcu_read_lock(); |
478 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, |
479 | bonding_list) { |
480 | if (!first_candidate) |
481 | first_candidate = tmp_neigh_node; |
482 | |
483 | /* recv_if == NULL on the first node. */ |
484 | if (tmp_neigh_node->if_incoming == recv_if) |
485 | continue; |
486 | |
487 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) |
488 | continue; |
489 | |
490 | router = tmp_neigh_node; |
491 | break; |
492 | } |
493 | |
494 | /* use the first candidate if nothing was found. */ |
495 | if (!router && first_candidate && |
496 | atomic_inc_not_zero(&first_candidate->refcount)) |
497 | router = first_candidate; |
498 | |
499 | if (!router) |
500 | goto out; |
501 | |
502 | /* selected should point to the next element |
503 | * after the current router |
504 | */ |
505 | spin_lock_bh(&primary_orig->neigh_list_lock); |
506 | /* this is a list_move(), which unfortunately |
507 | * does not exist as rcu version |
508 | */ |
509 | list_del_rcu(&primary_orig->bond_list); |
510 | list_add_rcu(&primary_orig->bond_list, |
511 | &router->bonding_list); |
512 | spin_unlock_bh(&primary_orig->neigh_list_lock); |
513 | |
514 | out: |
515 | rcu_read_unlock(); |
516 | return router; |
517 | } |
518 | |
519 | /** |
520 | * batadv_find_ifalter_router - find the best of the remaining candidates which |
521 | * are not using this interface |
522 | * @bat_priv: the bat priv with all the soft interface information |
523 | * @primary_orig: the destination |
524 | * @recv_if: the interface that the router returned by this function has to not |
525 | * use |
526 | * |
527 | * Returns the best candidate towards primary_orig that is not using recv_if. |
528 | * Increases the returned neighbor's refcount |
529 | */ |
530 | static struct batadv_neigh_node * |
531 | batadv_find_ifalter_router(struct batadv_priv *bat_priv, |
532 | struct batadv_orig_node *primary_orig, |
533 | const struct batadv_hard_iface *recv_if) |
534 | { |
535 | struct batadv_neigh_node *router = NULL, *first_candidate = NULL; |
536 | struct batadv_algo_ops *bao = bat_priv->bat_algo_ops; |
537 | struct batadv_neigh_node *tmp_neigh_node; |
538 | |
539 | rcu_read_lock(); |
540 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, |
541 | bonding_list) { |
542 | if (!first_candidate) |
543 | first_candidate = tmp_neigh_node; |
544 | |
545 | /* recv_if == NULL on the first node. */ |
546 | if (tmp_neigh_node->if_incoming == recv_if) |
547 | continue; |
548 | |
549 | if (router && bao->bat_neigh_cmp(tmp_neigh_node, router)) |
550 | continue; |
551 | |
552 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) |
553 | continue; |
554 | |
555 | /* decrement refcount of previously selected router */ |
556 | if (router) |
557 | batadv_neigh_node_free_ref(router); |
558 | |
559 | /* we found a better router (or at least one valid router) */ |
560 | router = tmp_neigh_node; |
561 | } |
562 | |
563 | /* use the first candidate if nothing was found. */ |
564 | if (!router && first_candidate && |
565 | atomic_inc_not_zero(&first_candidate->refcount)) |
566 | router = first_candidate; |
567 | |
568 | rcu_read_unlock(); |
569 | return router; |
570 | } |
571 | |
572 | /** |
573 | * batadv_check_unicast_packet - Check for malformed unicast packets |
574 | * @bat_priv: the bat priv with all the soft interface information |
575 | * @skb: packet to check |
576 | * @hdr_size: size of header to pull |
577 | * |
578 | * Check for short header and bad addresses in given packet. Returns negative |
579 | * value when check fails and 0 otherwise. The negative value depends on the |
580 | * reason: -ENODATA for bad header, -EBADR for broadcast destination or source, |
581 | * and -EREMOTE for non-local (other host) destination. |
582 | */ |
583 | static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, |
584 | struct sk_buff *skb, int hdr_size) |
585 | { |
586 | struct ethhdr *ethhdr; |
587 | |
588 | /* drop packet if it has not necessary minimum size */ |
589 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
590 | return -ENODATA; |
591 | |
592 | ethhdr = eth_hdr(skb); |
593 | |
594 | /* packet with unicast indication but broadcast recipient */ |
595 | if (is_broadcast_ether_addr(ethhdr->h_dest)) |
596 | return -EBADR; |
597 | |
598 | /* packet with broadcast sender address */ |
599 | if (is_broadcast_ether_addr(ethhdr->h_source)) |
600 | return -EBADR; |
601 | |
602 | /* not for me */ |
603 | if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest)) |
604 | return -EREMOTE; |
605 | |
606 | return 0; |
607 | } |
608 | |
609 | /* find a suitable router for this originator, and use |
610 | * bonding if possible. increases the found neighbors |
611 | * refcount. |
612 | */ |
613 | struct batadv_neigh_node * |
614 | batadv_find_router(struct batadv_priv *bat_priv, |
615 | struct batadv_orig_node *orig_node, |
616 | const struct batadv_hard_iface *recv_if) |
617 | { |
618 | struct batadv_orig_node *primary_orig_node; |
619 | struct batadv_orig_node *router_orig; |
620 | struct batadv_neigh_node *router; |
621 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; |
622 | int bonding_enabled; |
623 | uint8_t *primary_addr; |
624 | |
625 | if (!orig_node) |
626 | return NULL; |
627 | |
628 | router = batadv_orig_node_get_router(orig_node); |
629 | if (!router) |
630 | goto err; |
631 | |
632 | /* without bonding, the first node should |
633 | * always choose the default router. |
634 | */ |
635 | bonding_enabled = atomic_read(&bat_priv->bonding); |
636 | |
637 | rcu_read_lock(); |
638 | /* select default router to output */ |
639 | router_orig = router->orig_node; |
640 | if (!router_orig) |
641 | goto err_unlock; |
642 | |
643 | if ((!recv_if) && (!bonding_enabled)) |
644 | goto return_router; |
645 | |
646 | primary_addr = router_orig->primary_addr; |
647 | |
648 | /* if we have something in the primary_addr, we can search |
649 | * for a potential bonding candidate. |
650 | */ |
651 | if (batadv_compare_eth(primary_addr, zero_mac)) |
652 | goto return_router; |
653 | |
654 | /* find the orig_node which has the primary interface. might |
655 | * even be the same as our router_orig in many cases |
656 | */ |
657 | if (batadv_compare_eth(primary_addr, router_orig->orig)) { |
658 | primary_orig_node = router_orig; |
659 | } else { |
660 | primary_orig_node = batadv_orig_hash_find(bat_priv, |
661 | primary_addr); |
662 | if (!primary_orig_node) |
663 | goto return_router; |
664 | |
665 | batadv_orig_node_free_ref(primary_orig_node); |
666 | } |
667 | |
668 | /* with less than 2 candidates, we can't do any |
669 | * bonding and prefer the original router. |
670 | */ |
671 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) |
672 | goto return_router; |
673 | |
674 | /* all nodes between should choose a candidate which |
675 | * is is not on the interface where the packet came |
676 | * in. |
677 | */ |
678 | batadv_neigh_node_free_ref(router); |
679 | |
680 | if (bonding_enabled) |
681 | router = batadv_find_bond_router(primary_orig_node, recv_if); |
682 | else |
683 | router = batadv_find_ifalter_router(bat_priv, primary_orig_node, |
684 | recv_if); |
685 | |
686 | return_router: |
687 | if (router && router->if_incoming->if_status != BATADV_IF_ACTIVE) |
688 | goto err_unlock; |
689 | |
690 | rcu_read_unlock(); |
691 | return router; |
692 | err_unlock: |
693 | rcu_read_unlock(); |
694 | err: |
695 | if (router) |
696 | batadv_neigh_node_free_ref(router); |
697 | return NULL; |
698 | } |
699 | |
700 | static int batadv_route_unicast_packet(struct sk_buff *skb, |
701 | struct batadv_hard_iface *recv_if) |
702 | { |
703 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
704 | struct batadv_orig_node *orig_node = NULL; |
705 | struct batadv_unicast_packet *unicast_packet; |
706 | struct ethhdr *ethhdr = eth_hdr(skb); |
707 | int res, hdr_len, ret = NET_RX_DROP; |
708 | |
709 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
710 | |
711 | /* TTL exceeded */ |
712 | if (unicast_packet->ttl < 2) { |
713 | pr_debug("Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n", |
714 | ethhdr->h_source, unicast_packet->dest); |
715 | goto out; |
716 | } |
717 | |
718 | /* get routing information */ |
719 | orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->dest); |
720 | |
721 | if (!orig_node) |
722 | goto out; |
723 | |
724 | /* create a copy of the skb, if needed, to modify it. */ |
725 | if (skb_cow(skb, ETH_HLEN) < 0) |
726 | goto out; |
727 | |
728 | /* decrement ttl */ |
729 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
730 | unicast_packet->ttl--; |
731 | |
732 | switch (unicast_packet->packet_type) { |
733 | case BATADV_UNICAST_4ADDR: |
734 | hdr_len = sizeof(struct batadv_unicast_4addr_packet); |
735 | break; |
736 | case BATADV_UNICAST: |
737 | hdr_len = sizeof(struct batadv_unicast_packet); |
738 | break; |
739 | default: |
740 | /* other packet types not supported - yet */ |
741 | hdr_len = -1; |
742 | break; |
743 | } |
744 | |
745 | if (hdr_len > 0) |
746 | batadv_skb_set_priority(skb, hdr_len); |
747 | |
748 | res = batadv_send_skb_to_orig(skb, orig_node, recv_if); |
749 | |
750 | /* translate transmit result into receive result */ |
751 | if (res == NET_XMIT_SUCCESS) { |
752 | /* skb was transmitted and consumed */ |
753 | batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); |
754 | batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, |
755 | skb->len + ETH_HLEN); |
756 | |
757 | ret = NET_RX_SUCCESS; |
758 | } else if (res == NET_XMIT_POLICED) { |
759 | /* skb was buffered and consumed */ |
760 | ret = NET_RX_SUCCESS; |
761 | } |
762 | |
763 | out: |
764 | if (orig_node) |
765 | batadv_orig_node_free_ref(orig_node); |
766 | return ret; |
767 | } |
768 | |
769 | /** |
770 | * batadv_reroute_unicast_packet - update the unicast header for re-routing |
771 | * @bat_priv: the bat priv with all the soft interface information |
772 | * @unicast_packet: the unicast header to be updated |
773 | * @dst_addr: the payload destination |
774 | * @vid: VLAN identifier |
775 | * |
776 | * Search the translation table for dst_addr and update the unicast header with |
777 | * the new corresponding information (originator address where the destination |
778 | * client currently is and its known TTVN) |
779 | * |
780 | * Returns true if the packet header has been updated, false otherwise |
781 | */ |
782 | static bool |
783 | batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, |
784 | struct batadv_unicast_packet *unicast_packet, |
785 | uint8_t *dst_addr, unsigned short vid) |
786 | { |
787 | struct batadv_orig_node *orig_node = NULL; |
788 | struct batadv_hard_iface *primary_if = NULL; |
789 | bool ret = false; |
790 | uint8_t *orig_addr, orig_ttvn; |
791 | |
792 | if (batadv_is_my_client(bat_priv, dst_addr, vid)) { |
793 | primary_if = batadv_primary_if_get_selected(bat_priv); |
794 | if (!primary_if) |
795 | goto out; |
796 | orig_addr = primary_if->net_dev->dev_addr; |
797 | orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
798 | } else { |
799 | orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr, |
800 | vid); |
801 | if (!orig_node) |
802 | goto out; |
803 | |
804 | if (batadv_compare_eth(orig_node->orig, unicast_packet->dest)) |
805 | goto out; |
806 | |
807 | orig_addr = orig_node->orig; |
808 | orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
809 | } |
810 | |
811 | /* update the packet header */ |
812 | memcpy(unicast_packet->dest, orig_addr, ETH_ALEN); |
813 | unicast_packet->ttvn = orig_ttvn; |
814 | |
815 | ret = true; |
816 | out: |
817 | if (primary_if) |
818 | batadv_hardif_free_ref(primary_if); |
819 | if (orig_node) |
820 | batadv_orig_node_free_ref(orig_node); |
821 | |
822 | return ret; |
823 | } |
824 | |
825 | static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, |
826 | struct sk_buff *skb, int hdr_len) { |
827 | struct batadv_unicast_packet *unicast_packet; |
828 | struct batadv_hard_iface *primary_if; |
829 | struct batadv_orig_node *orig_node; |
830 | uint8_t curr_ttvn, old_ttvn; |
831 | struct ethhdr *ethhdr; |
832 | unsigned short vid; |
833 | int is_old_ttvn; |
834 | |
835 | /* check if there is enough data before accessing it */ |
836 | if (pskb_may_pull(skb, hdr_len + ETH_HLEN) < 0) |
837 | return 0; |
838 | |
839 | /* create a copy of the skb (in case of for re-routing) to modify it. */ |
840 | if (skb_cow(skb, sizeof(*unicast_packet)) < 0) |
841 | return 0; |
842 | |
843 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
844 | vid = batadv_get_vid(skb, hdr_len); |
845 | ethhdr = (struct ethhdr *)(skb->data + hdr_len); |
846 | |
847 | /* check if the destination client was served by this node and it is now |
848 | * roaming. In this case, it means that the node has got a ROAM_ADV |
849 | * message and that it knows the new destination in the mesh to re-route |
850 | * the packet to |
851 | */ |
852 | if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) { |
853 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, |
854 | ethhdr->h_dest, vid)) |
855 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, |
856 | bat_priv, |
857 | "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", |
858 | unicast_packet->dest, |
859 | ethhdr->h_dest); |
860 | /* at this point the mesh destination should have been |
861 | * substituted with the originator address found in the global |
862 | * table. If not, let the packet go untouched anyway because |
863 | * there is nothing the node can do |
864 | */ |
865 | return 1; |
866 | } |
867 | |
868 | /* retrieve the TTVN known by this node for the packet destination. This |
869 | * value is used later to check if the node which sent (or re-routed |
870 | * last time) the packet had an updated information or not |
871 | */ |
872 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
873 | if (!batadv_is_my_mac(bat_priv, unicast_packet->dest)) { |
874 | orig_node = batadv_orig_hash_find(bat_priv, |
875 | unicast_packet->dest); |
876 | /* if it is not possible to find the orig_node representing the |
877 | * destination, the packet can immediately be dropped as it will |
878 | * not be possible to deliver it |
879 | */ |
880 | if (!orig_node) |
881 | return 0; |
882 | |
883 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
884 | batadv_orig_node_free_ref(orig_node); |
885 | } |
886 | |
887 | /* check if the TTVN contained in the packet is fresher than what the |
888 | * node knows |
889 | */ |
890 | is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn); |
891 | if (!is_old_ttvn) |
892 | return 1; |
893 | |
894 | old_ttvn = unicast_packet->ttvn; |
895 | /* the packet was forged based on outdated network information. Its |
896 | * destination can possibly be updated and forwarded towards the new |
897 | * target host |
898 | */ |
899 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, |
900 | ethhdr->h_dest, vid)) { |
901 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, |
902 | "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", |
903 | unicast_packet->dest, ethhdr->h_dest, |
904 | old_ttvn, curr_ttvn); |
905 | return 1; |
906 | } |
907 | |
908 | /* the packet has not been re-routed: either the destination is |
909 | * currently served by this node or there is no destination at all and |
910 | * it is possible to drop the packet |
911 | */ |
912 | if (!batadv_is_my_client(bat_priv, ethhdr->h_dest, vid)) |
913 | return 0; |
914 | |
915 | /* update the header in order to let the packet be delivered to this |
916 | * node's soft interface |
917 | */ |
918 | primary_if = batadv_primary_if_get_selected(bat_priv); |
919 | if (!primary_if) |
920 | return 0; |
921 | |
922 | memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); |
923 | |
924 | batadv_hardif_free_ref(primary_if); |
925 | |
926 | unicast_packet->ttvn = curr_ttvn; |
927 | |
928 | return 1; |
929 | } |
930 | |
931 | /** |
932 | * batadv_recv_unhandled_unicast_packet - receive and process packets which |
933 | * are in the unicast number space but not yet known to the implementation |
934 | * @skb: unicast tvlv packet to process |
935 | * @recv_if: pointer to interface this packet was received on |
936 | * |
937 | * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP |
938 | * otherwise. |
939 | */ |
940 | int batadv_recv_unhandled_unicast_packet(struct sk_buff *skb, |
941 | struct batadv_hard_iface *recv_if) |
942 | { |
943 | struct batadv_unicast_packet *unicast_packet; |
944 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
945 | int check, hdr_size = sizeof(*unicast_packet); |
946 | |
947 | check = batadv_check_unicast_packet(bat_priv, skb, hdr_size); |
948 | if (check < 0) |
949 | return NET_RX_DROP; |
950 | |
951 | /* we don't know about this type, drop it. */ |
952 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
953 | if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) |
954 | return NET_RX_DROP; |
955 | |
956 | return batadv_route_unicast_packet(skb, recv_if); |
957 | } |
958 | |
959 | int batadv_recv_unicast_packet(struct sk_buff *skb, |
960 | struct batadv_hard_iface *recv_if) |
961 | { |
962 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
963 | struct batadv_unicast_packet *unicast_packet; |
964 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; |
965 | uint8_t *orig_addr; |
966 | struct batadv_orig_node *orig_node = NULL; |
967 | int check, hdr_size = sizeof(*unicast_packet); |
968 | bool is4addr; |
969 | |
970 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
971 | unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; |
972 | |
973 | is4addr = unicast_packet->packet_type == BATADV_UNICAST_4ADDR; |
974 | /* the caller function should have already pulled 2 bytes */ |
975 | if (is4addr) |
976 | hdr_size = sizeof(*unicast_4addr_packet); |
977 | |
978 | /* function returns -EREMOTE for promiscuous packets */ |
979 | check = batadv_check_unicast_packet(bat_priv, skb, hdr_size); |
980 | |
981 | /* Even though the packet is not for us, we might save it to use for |
982 | * decoding a later received coded packet |
983 | */ |
984 | if (check == -EREMOTE) |
985 | batadv_nc_skb_store_sniffed_unicast(bat_priv, skb); |
986 | |
987 | if (check < 0) |
988 | return NET_RX_DROP; |
989 | if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size)) |
990 | return NET_RX_DROP; |
991 | |
992 | /* packet for me */ |
993 | if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) { |
994 | if (is4addr) { |
995 | batadv_dat_inc_counter(bat_priv, |
996 | unicast_4addr_packet->subtype); |
997 | orig_addr = unicast_4addr_packet->src; |
998 | orig_node = batadv_orig_hash_find(bat_priv, orig_addr); |
999 | } |
1000 | |
1001 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, |
1002 | hdr_size)) |
1003 | goto rx_success; |
1004 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, |
1005 | hdr_size)) |
1006 | goto rx_success; |
1007 | |
1008 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1009 | orig_node); |
1010 | |
1011 | rx_success: |
1012 | if (orig_node) |
1013 | batadv_orig_node_free_ref(orig_node); |
1014 | |
1015 | return NET_RX_SUCCESS; |
1016 | } |
1017 | |
1018 | return batadv_route_unicast_packet(skb, recv_if); |
1019 | } |
1020 | |
1021 | /** |
1022 | * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets |
1023 | * @skb: unicast tvlv packet to process |
1024 | * @recv_if: pointer to interface this packet was received on |
1025 | * @dst_addr: the payload destination |
1026 | * |
1027 | * Returns NET_RX_SUCCESS if the packet has been consumed or NET_RX_DROP |
1028 | * otherwise. |
1029 | */ |
1030 | int batadv_recv_unicast_tvlv(struct sk_buff *skb, |
1031 | struct batadv_hard_iface *recv_if) |
1032 | { |
1033 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
1034 | struct batadv_unicast_tvlv_packet *unicast_tvlv_packet; |
1035 | unsigned char *tvlv_buff; |
1036 | uint16_t tvlv_buff_len; |
1037 | int hdr_size = sizeof(*unicast_tvlv_packet); |
1038 | int ret = NET_RX_DROP; |
1039 | |
1040 | if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0) |
1041 | return NET_RX_DROP; |
1042 | |
1043 | /* the header is likely to be modified while forwarding */ |
1044 | if (skb_cow(skb, hdr_size) < 0) |
1045 | return NET_RX_DROP; |
1046 | |
1047 | /* packet needs to be linearized to access the tvlv content */ |
1048 | if (skb_linearize(skb) < 0) |
1049 | return NET_RX_DROP; |
1050 | |
1051 | unicast_tvlv_packet = (struct batadv_unicast_tvlv_packet *)skb->data; |
1052 | |
1053 | tvlv_buff = (unsigned char *)(skb->data + hdr_size); |
1054 | tvlv_buff_len = ntohs(unicast_tvlv_packet->tvlv_len); |
1055 | |
1056 | if (tvlv_buff_len > skb->len - hdr_size) |
1057 | return NET_RX_DROP; |
1058 | |
1059 | ret = batadv_tvlv_containers_process(bat_priv, false, NULL, |
1060 | unicast_tvlv_packet->src, |
1061 | unicast_tvlv_packet->dst, |
1062 | tvlv_buff, tvlv_buff_len); |
1063 | |
1064 | if (ret != NET_RX_SUCCESS) |
1065 | ret = batadv_route_unicast_packet(skb, recv_if); |
1066 | |
1067 | return ret; |
1068 | } |
1069 | |
1070 | /** |
1071 | * batadv_recv_frag_packet - process received fragment |
1072 | * @skb: the received fragment |
1073 | * @recv_if: interface that the skb is received on |
1074 | * |
1075 | * This function does one of the three following things: 1) Forward fragment, if |
1076 | * the assembled packet will exceed our MTU; 2) Buffer fragment, if we till |
1077 | * lack further fragments; 3) Merge fragments, if we have all needed parts. |
1078 | * |
1079 | * Return NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise. |
1080 | */ |
1081 | int batadv_recv_frag_packet(struct sk_buff *skb, |
1082 | struct batadv_hard_iface *recv_if) |
1083 | { |
1084 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
1085 | struct batadv_orig_node *orig_node_src = NULL; |
1086 | struct batadv_frag_packet *frag_packet; |
1087 | int ret = NET_RX_DROP; |
1088 | |
1089 | if (batadv_check_unicast_packet(bat_priv, skb, |
1090 | sizeof(*frag_packet)) < 0) |
1091 | goto out; |
1092 | |
1093 | frag_packet = (struct batadv_frag_packet *)skb->data; |
1094 | orig_node_src = batadv_orig_hash_find(bat_priv, frag_packet->orig); |
1095 | if (!orig_node_src) |
1096 | goto out; |
1097 | |
1098 | /* Route the fragment if it is not for us and too big to be merged. */ |
1099 | if (!batadv_is_my_mac(bat_priv, frag_packet->dest) && |
1100 | batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) { |
1101 | ret = NET_RX_SUCCESS; |
1102 | goto out; |
1103 | } |
1104 | |
1105 | batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX); |
1106 | batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len); |
1107 | |
1108 | /* Add fragment to buffer and merge if possible. */ |
1109 | if (!batadv_frag_skb_buffer(&skb, orig_node_src)) |
1110 | goto out; |
1111 | |
1112 | /* Deliver merged packet to the appropriate handler, if it was |
1113 | * merged |
1114 | */ |
1115 | if (skb) |
1116 | batadv_batman_skb_recv(skb, recv_if->net_dev, |
1117 | &recv_if->batman_adv_ptype, NULL); |
1118 | |
1119 | ret = NET_RX_SUCCESS; |
1120 | |
1121 | out: |
1122 | if (orig_node_src) |
1123 | batadv_orig_node_free_ref(orig_node_src); |
1124 | |
1125 | return ret; |
1126 | } |
1127 | |
1128 | int batadv_recv_bcast_packet(struct sk_buff *skb, |
1129 | struct batadv_hard_iface *recv_if) |
1130 | { |
1131 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); |
1132 | struct batadv_orig_node *orig_node = NULL; |
1133 | struct batadv_bcast_packet *bcast_packet; |
1134 | struct ethhdr *ethhdr; |
1135 | int hdr_size = sizeof(*bcast_packet); |
1136 | int ret = NET_RX_DROP; |
1137 | int32_t seq_diff; |
1138 | |
1139 | /* drop packet if it has not necessary minimum size */ |
1140 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
1141 | goto out; |
1142 | |
1143 | ethhdr = eth_hdr(skb); |
1144 | |
1145 | /* packet with broadcast indication but unicast recipient */ |
1146 | if (!is_broadcast_ether_addr(ethhdr->h_dest)) |
1147 | goto out; |
1148 | |
1149 | /* packet with broadcast sender address */ |
1150 | if (is_broadcast_ether_addr(ethhdr->h_source)) |
1151 | goto out; |
1152 | |
1153 | /* ignore broadcasts sent by myself */ |
1154 | if (batadv_is_my_mac(bat_priv, ethhdr->h_source)) |
1155 | goto out; |
1156 | |
1157 | bcast_packet = (struct batadv_bcast_packet *)skb->data; |
1158 | |
1159 | /* ignore broadcasts originated by myself */ |
1160 | if (batadv_is_my_mac(bat_priv, bcast_packet->orig)) |
1161 | goto out; |
1162 | |
1163 | if (bcast_packet->ttl < 2) |
1164 | goto out; |
1165 | |
1166 | orig_node = batadv_orig_hash_find(bat_priv, bcast_packet->orig); |
1167 | |
1168 | if (!orig_node) |
1169 | goto out; |
1170 | |
1171 | spin_lock_bh(&orig_node->bcast_seqno_lock); |
1172 | |
1173 | /* check whether the packet is a duplicate */ |
1174 | if (batadv_test_bit(orig_node->bcast_bits, orig_node->last_bcast_seqno, |
1175 | ntohl(bcast_packet->seqno))) |
1176 | goto spin_unlock; |
1177 | |
1178 | seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; |
1179 | |
1180 | /* check whether the packet is old and the host just restarted. */ |
1181 | if (batadv_window_protected(bat_priv, seq_diff, |
1182 | &orig_node->bcast_seqno_reset)) |
1183 | goto spin_unlock; |
1184 | |
1185 | /* mark broadcast in flood history, update window position |
1186 | * if required. |
1187 | */ |
1188 | if (batadv_bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1)) |
1189 | orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno); |
1190 | |
1191 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1192 | |
1193 | /* check whether this has been sent by another originator before */ |
1194 | if (batadv_bla_check_bcast_duplist(bat_priv, skb)) |
1195 | goto out; |
1196 | |
1197 | batadv_skb_set_priority(skb, sizeof(struct batadv_bcast_packet)); |
1198 | |
1199 | /* rebroadcast packet */ |
1200 | batadv_add_bcast_packet_to_list(bat_priv, skb, 1); |
1201 | |
1202 | /* don't hand the broadcast up if it is from an originator |
1203 | * from the same backbone. |
1204 | */ |
1205 | if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) |
1206 | goto out; |
1207 | |
1208 | if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size)) |
1209 | goto rx_success; |
1210 | if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size)) |
1211 | goto rx_success; |
1212 | |
1213 | /* broadcast for me */ |
1214 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1215 | orig_node); |
1216 | |
1217 | rx_success: |
1218 | ret = NET_RX_SUCCESS; |
1219 | goto out; |
1220 | |
1221 | spin_unlock: |
1222 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1223 | out: |
1224 | if (orig_node) |
1225 | batadv_orig_node_free_ref(orig_node); |
1226 | return ret; |
1227 | } |
1228 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9