aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/routing.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r--net/batman-adv/routing.c185
1 files changed, 82 insertions, 103 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 457dfef9c5fc..3281a504c20a 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -25,10 +25,10 @@
25#include "icmp_socket.h" 25#include "icmp_socket.h"
26#include "translation-table.h" 26#include "translation-table.h"
27#include "originator.h" 27#include "originator.h"
28#include "unicast.h"
29#include "bridge_loop_avoidance.h" 28#include "bridge_loop_avoidance.h"
30#include "distributed-arp-table.h" 29#include "distributed-arp-table.h"
31#include "network-coding.h" 30#include "network-coding.h"
31#include "fragmentation.h"
32 32
33static int batadv_route_unicast_packet(struct sk_buff *skb, 33static int batadv_route_unicast_packet(struct sk_buff *skb,
34 struct batadv_hard_iface *recv_if); 34 struct batadv_hard_iface *recv_if);
@@ -258,7 +258,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
258 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 258 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
259 259
260 /* add data to device queue */ 260 /* add data to device queue */
261 if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { 261 if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
262 batadv_socket_receive_packet(icmp_packet, icmp_len); 262 batadv_socket_receive_packet(icmp_packet, icmp_len);
263 goto out; 263 goto out;
264 } 264 }
@@ -269,7 +269,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
269 269
270 /* answer echo request (ping) */ 270 /* answer echo request (ping) */
271 /* get routing information */ 271 /* get routing information */
272 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig); 272 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
273 if (!orig_node) 273 if (!orig_node)
274 goto out; 274 goto out;
275 275
@@ -279,10 +279,11 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
279 279
280 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 280 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
281 281
282 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 282 memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
283 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); 283 memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
284 icmp_packet->msg_type = BATADV_ECHO_REPLY; 284 ETH_ALEN);
285 icmp_packet->header.ttl = BATADV_TTL; 285 icmp_packet->icmph.msg_type = BATADV_ECHO_REPLY;
286 icmp_packet->icmph.header.ttl = BATADV_TTL;
286 287
287 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 288 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
288 ret = NET_RX_SUCCESS; 289 ret = NET_RX_SUCCESS;
@@ -306,9 +307,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
306 icmp_packet = (struct batadv_icmp_packet *)skb->data; 307 icmp_packet = (struct batadv_icmp_packet *)skb->data;
307 308
308 /* send TTL exceeded if packet is an echo request (traceroute) */ 309 /* send TTL exceeded if packet is an echo request (traceroute) */
309 if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) { 310 if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
310 pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n", 311 pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
311 icmp_packet->orig, icmp_packet->dst); 312 icmp_packet->icmph.orig, icmp_packet->icmph.dst);
312 goto out; 313 goto out;
313 } 314 }
314 315
@@ -317,7 +318,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
317 goto out; 318 goto out;
318 319
319 /* get routing information */ 320 /* get routing information */
320 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig); 321 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
321 if (!orig_node) 322 if (!orig_node)
322 goto out; 323 goto out;
323 324
@@ -327,10 +328,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
327 328
328 icmp_packet = (struct batadv_icmp_packet *)skb->data; 329 icmp_packet = (struct batadv_icmp_packet *)skb->data;
329 330
330 memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); 331 memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
331 memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); 332 memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
332 icmp_packet->msg_type = BATADV_TTL_EXCEEDED; 333 ETH_ALEN);
333 icmp_packet->header.ttl = BATADV_TTL; 334 icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
335 icmp_packet->icmph.header.ttl = BATADV_TTL;
334 336
335 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 337 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
336 ret = NET_RX_SUCCESS; 338 ret = NET_RX_SUCCESS;
@@ -379,7 +381,9 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
379 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 381 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
380 382
381 /* add record route information if not full */ 383 /* add record route information if not full */
382 if ((hdr_size == sizeof(struct batadv_icmp_packet_rr)) && 384 if ((icmp_packet->icmph.msg_type == BATADV_ECHO_REPLY ||
385 icmp_packet->icmph.msg_type == BATADV_ECHO_REQUEST) &&
386 (hdr_size == sizeof(struct batadv_icmp_packet_rr)) &&
383 (icmp_packet->rr_cur < BATADV_RR_LEN)) { 387 (icmp_packet->rr_cur < BATADV_RR_LEN)) {
384 memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]), 388 memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
385 ethhdr->h_dest, ETH_ALEN); 389 ethhdr->h_dest, ETH_ALEN);
@@ -387,15 +391,15 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
387 } 391 }
388 392
389 /* packet for me */ 393 /* packet for me */
390 if (batadv_is_my_mac(bat_priv, icmp_packet->dst)) 394 if (batadv_is_my_mac(bat_priv, icmp_packet->icmph.dst))
391 return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size); 395 return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size);
392 396
393 /* TTL exceeded */ 397 /* TTL exceeded */
394 if (icmp_packet->header.ttl < 2) 398 if (icmp_packet->icmph.header.ttl < 2)
395 return batadv_recv_icmp_ttl_exceeded(bat_priv, skb); 399 return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
396 400
397 /* get routing information */ 401 /* get routing information */
398 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->dst); 402 orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.dst);
399 if (!orig_node) 403 if (!orig_node)
400 goto out; 404 goto out;
401 405
@@ -406,7 +410,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
406 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data; 410 icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
407 411
408 /* decrement ttl */ 412 /* decrement ttl */
409 icmp_packet->header.ttl--; 413 icmp_packet->icmph.header.ttl--;
410 414
411 /* route it */ 415 /* route it */
412 if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP) 416 if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
@@ -651,11 +655,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
651{ 655{
652 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); 656 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
653 struct batadv_orig_node *orig_node = NULL; 657 struct batadv_orig_node *orig_node = NULL;
654 struct batadv_neigh_node *neigh_node = NULL;
655 struct batadv_unicast_packet *unicast_packet; 658 struct batadv_unicast_packet *unicast_packet;
656 struct ethhdr *ethhdr = eth_hdr(skb); 659 struct ethhdr *ethhdr = eth_hdr(skb);
657 int res, hdr_len, ret = NET_RX_DROP; 660 int res, hdr_len, ret = NET_RX_DROP;
658 struct sk_buff *new_skb;
659 661
660 unicast_packet = (struct batadv_unicast_packet *)skb->data; 662 unicast_packet = (struct batadv_unicast_packet *)skb->data;
661 663
@@ -672,46 +674,12 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
672 if (!orig_node) 674 if (!orig_node)
673 goto out; 675 goto out;
674 676
675 /* find_router() increases neigh_nodes refcount if found. */
676 neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
677
678 if (!neigh_node)
679 goto out;
680
681 /* create a copy of the skb, if needed, to modify it. */ 677 /* create a copy of the skb, if needed, to modify it. */
682 if (skb_cow(skb, ETH_HLEN) < 0) 678 if (skb_cow(skb, ETH_HLEN) < 0)
683 goto out; 679 goto out;
684 680
685 unicast_packet = (struct batadv_unicast_packet *)skb->data;
686
687 if (unicast_packet->header.packet_type == BATADV_UNICAST &&
688 atomic_read(&bat_priv->fragmentation) &&
689 skb->len > neigh_node->if_incoming->net_dev->mtu) {
690 ret = batadv_frag_send_skb(skb, bat_priv,
691 neigh_node->if_incoming,
692 neigh_node->addr);
693 goto out;
694 }
695
696 if (unicast_packet->header.packet_type == BATADV_UNICAST_FRAG &&
697 batadv_frag_can_reassemble(skb,
698 neigh_node->if_incoming->net_dev->mtu)) {
699 ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
700
701 if (ret == NET_RX_DROP)
702 goto out;
703
704 /* packet was buffered for late merge */
705 if (!new_skb) {
706 ret = NET_RX_SUCCESS;
707 goto out;
708 }
709
710 skb = new_skb;
711 unicast_packet = (struct batadv_unicast_packet *)skb->data;
712 }
713
714 /* decrement ttl */ 681 /* decrement ttl */
682 unicast_packet = (struct batadv_unicast_packet *)skb->data;
715 unicast_packet->header.ttl--; 683 unicast_packet->header.ttl--;
716 684
717 switch (unicast_packet->header.packet_type) { 685 switch (unicast_packet->header.packet_type) {
@@ -746,8 +714,6 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
746 } 714 }
747 715
748out: 716out:
749 if (neigh_node)
750 batadv_neigh_node_free_ref(neigh_node);
751 if (orig_node) 717 if (orig_node)
752 batadv_orig_node_free_ref(orig_node); 718 batadv_orig_node_free_ref(orig_node);
753 return ret; 719 return ret;
@@ -1001,51 +967,6 @@ rx_success:
1001 return batadv_route_unicast_packet(skb, recv_if); 967 return batadv_route_unicast_packet(skb, recv_if);
1002} 968}
1003 969
1004int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
1005 struct batadv_hard_iface *recv_if)
1006{
1007 struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
1008 struct batadv_unicast_frag_packet *unicast_packet;
1009 int hdr_size = sizeof(*unicast_packet);
1010 struct sk_buff *new_skb = NULL;
1011 int ret;
1012
1013 if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
1014 return NET_RX_DROP;
1015
1016 if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size))
1017 return NET_RX_DROP;
1018
1019 unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
1020
1021 /* packet for me */
1022 if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
1023 ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
1024
1025 if (ret == NET_RX_DROP)
1026 return NET_RX_DROP;
1027
1028 /* packet was buffered for late merge */
1029 if (!new_skb)
1030 return NET_RX_SUCCESS;
1031
1032 if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
1033 hdr_size))
1034 goto rx_success;
1035 if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
1036 hdr_size))
1037 goto rx_success;
1038
1039 batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
1040 sizeof(struct batadv_unicast_packet), NULL);
1041
1042rx_success:
1043 return NET_RX_SUCCESS;
1044 }
1045
1046 return batadv_route_unicast_packet(skb, recv_if);
1047}
1048
1049/** 970/**
1050 * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets 971 * batadv_recv_unicast_tvlv - receive and process unicast tvlv packets
1051 * @skb: unicast tvlv packet to process 972 * @skb: unicast tvlv packet to process
@@ -1095,6 +1016,64 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
1095 return ret; 1016 return ret;
1096} 1017}
1097 1018
1019/**
1020 * batadv_recv_frag_packet - process received fragment
1021 * @skb: the received fragment
1022 * @recv_if: interface that the skb is received on
1023 *
1024 * This function does one of the three following things: 1) Forward fragment, if
1025 * the assembled packet will exceed our MTU; 2) Buffer fragment, if we till
1026 * lack further fragments; 3) Merge fragments, if we have all needed parts.
1027 *
1028 * Return NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise.
1029 */
1030int batadv_recv_frag_packet(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_orig_node *orig_node_src = NULL;
1035 struct batadv_frag_packet *frag_packet;
1036 int ret = NET_RX_DROP;
1037
1038 if (batadv_check_unicast_packet(bat_priv, skb,
1039 sizeof(*frag_packet)) < 0)
1040 goto out;
1041
1042 frag_packet = (struct batadv_frag_packet *)skb->data;
1043 orig_node_src = batadv_orig_hash_find(bat_priv, frag_packet->orig);
1044 if (!orig_node_src)
1045 goto out;
1046
1047 /* Route the fragment if it is not for us and too big to be merged. */
1048 if (!batadv_is_my_mac(bat_priv, frag_packet->dest) &&
1049 batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) {
1050 ret = NET_RX_SUCCESS;
1051 goto out;
1052 }
1053
1054 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX);
1055 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len);
1056
1057 /* Add fragment to buffer and merge if possible. */
1058 if (!batadv_frag_skb_buffer(&skb, orig_node_src))
1059 goto out;
1060
1061 /* Deliver merged packet to the appropriate handler, if it was
1062 * merged
1063 */
1064 if (skb)
1065 batadv_batman_skb_recv(skb, recv_if->net_dev,
1066 &recv_if->batman_adv_ptype, NULL);
1067
1068 ret = NET_RX_SUCCESS;
1069
1070out:
1071 if (orig_node_src)
1072 batadv_orig_node_free_ref(orig_node_src);
1073
1074 return ret;
1075}
1076
1098int batadv_recv_bcast_packet(struct sk_buff *skb, 1077int batadv_recv_bcast_packet(struct sk_buff *skb,
1099 struct batadv_hard_iface *recv_if) 1078 struct batadv_hard_iface *recv_if)
1100{ 1079{