diff options
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r-- | net/batman-adv/routing.c | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 319f2906c71a..2f1f88923df8 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "unicast.h" | 29 | #include "unicast.h" |
30 | #include "bridge_loop_avoidance.h" | 30 | #include "bridge_loop_avoidance.h" |
31 | #include "distributed-arp-table.h" | 31 | #include "distributed-arp-table.h" |
32 | #include "network-coding.h" | ||
32 | 33 | ||
33 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 34 | static int batadv_route_unicast_packet(struct sk_buff *skb, |
34 | struct batadv_hard_iface *recv_if); | 35 | struct batadv_hard_iface *recv_if); |
@@ -548,6 +549,17 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig, | |||
548 | return router; | 549 | return router; |
549 | } | 550 | } |
550 | 551 | ||
552 | /** | ||
553 | * batadv_check_unicast_packet - Check for malformed unicast packets | ||
554 | * @bat_priv: the bat priv with all the soft interface information | ||
555 | * @skb: packet to check | ||
556 | * @hdr_size: size of header to pull | ||
557 | * | ||
558 | * Check for short header and bad addresses in given packet. Returns negative | ||
559 | * value when check fails and 0 otherwise. The negative value depends on the | ||
560 | * reason: -ENODATA for bad header, -EBADR for broadcast destination or source, | ||
561 | * and -EREMOTE for non-local (other host) destination. | ||
562 | */ | ||
551 | static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, | 563 | static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, |
552 | struct sk_buff *skb, int hdr_size) | 564 | struct sk_buff *skb, int hdr_size) |
553 | { | 565 | { |
@@ -555,21 +567,21 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv, | |||
555 | 567 | ||
556 | /* drop packet if it has not necessary minimum size */ | 568 | /* drop packet if it has not necessary minimum size */ |
557 | if (unlikely(!pskb_may_pull(skb, hdr_size))) | 569 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
558 | return -1; | 570 | return -ENODATA; |
559 | 571 | ||
560 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 572 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
561 | 573 | ||
562 | /* packet with unicast indication but broadcast recipient */ | 574 | /* packet with unicast indication but broadcast recipient */ |
563 | if (is_broadcast_ether_addr(ethhdr->h_dest)) | 575 | if (is_broadcast_ether_addr(ethhdr->h_dest)) |
564 | return -1; | 576 | return -EBADR; |
565 | 577 | ||
566 | /* packet with broadcast sender address */ | 578 | /* packet with broadcast sender address */ |
567 | if (is_broadcast_ether_addr(ethhdr->h_source)) | 579 | if (is_broadcast_ether_addr(ethhdr->h_source)) |
568 | return -1; | 580 | return -EBADR; |
569 | 581 | ||
570 | /* not for me */ | 582 | /* not for me */ |
571 | if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest)) | 583 | if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest)) |
572 | return -1; | 584 | return -EREMOTE; |
573 | 585 | ||
574 | return 0; | 586 | return 0; |
575 | } | 587 | } |
@@ -852,15 +864,18 @@ static int batadv_route_unicast_packet(struct sk_buff *skb, | |||
852 | /* decrement ttl */ | 864 | /* decrement ttl */ |
853 | unicast_packet->header.ttl--; | 865 | unicast_packet->header.ttl--; |
854 | 866 | ||
855 | /* Update stats counter */ | 867 | /* network code packet if possible */ |
856 | batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); | 868 | if (batadv_nc_skb_forward(skb, neigh_node, ethhdr)) { |
857 | batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, | 869 | ret = NET_RX_SUCCESS; |
858 | skb->len + ETH_HLEN); | 870 | } else if (batadv_send_skb_to_orig(skb, orig_node, recv_if)) { |
859 | |||
860 | /* route it */ | ||
861 | if (batadv_send_skb_to_orig(skb, orig_node, recv_if)) | ||
862 | ret = NET_RX_SUCCESS; | 871 | ret = NET_RX_SUCCESS; |
863 | 872 | ||
873 | /* Update stats counter */ | ||
874 | batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); | ||
875 | batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, | ||
876 | skb->len + ETH_HLEN); | ||
877 | } | ||
878 | |||
864 | out: | 879 | out: |
865 | if (neigh_node) | 880 | if (neigh_node) |
866 | batadv_neigh_node_free_ref(neigh_node); | 881 | batadv_neigh_node_free_ref(neigh_node); |
@@ -1035,7 +1050,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1035 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; | 1050 | struct batadv_unicast_4addr_packet *unicast_4addr_packet; |
1036 | uint8_t *orig_addr; | 1051 | uint8_t *orig_addr; |
1037 | struct batadv_orig_node *orig_node = NULL; | 1052 | struct batadv_orig_node *orig_node = NULL; |
1038 | int hdr_size = sizeof(*unicast_packet); | 1053 | int check, hdr_size = sizeof(*unicast_packet); |
1039 | bool is4addr; | 1054 | bool is4addr; |
1040 | 1055 | ||
1041 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 1056 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
@@ -1046,7 +1061,16 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1046 | if (is4addr) | 1061 | if (is4addr) |
1047 | hdr_size = sizeof(*unicast_4addr_packet); | 1062 | hdr_size = sizeof(*unicast_4addr_packet); |
1048 | 1063 | ||
1049 | if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0) | 1064 | /* function returns -EREMOTE for promiscuous packets */ |
1065 | check = batadv_check_unicast_packet(bat_priv, skb, hdr_size); | ||
1066 | |||
1067 | /* Even though the packet is not for us, we might save it to use for | ||
1068 | * decoding a later received coded packet | ||
1069 | */ | ||
1070 | if (check == -EREMOTE) | ||
1071 | batadv_nc_skb_store_sniffed_unicast(bat_priv, skb); | ||
1072 | |||
1073 | if (check < 0) | ||
1050 | return NET_RX_DROP; | 1074 | return NET_RX_DROP; |
1051 | 1075 | ||
1052 | if (!batadv_check_unicast_ttvn(bat_priv, skb)) | 1076 | if (!batadv_check_unicast_ttvn(bat_priv, skb)) |