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