@@ -69,7 +69,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
* are flooded through the net */
if ((!directlink) &&
(!(batman_packet->flags & DIRECTLINK)) &&
- (batman_packet->header.ttl != 1) &&
+ (batman_packet->header.ttl != 2) &&
/* own packets originating non-primary
* interfaces leave only that interface */
@@ -80,7 +80,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
/* if the incoming packet is sent via this one
* interface only - we still can aggregate */
if ((directlink) &&
- (new_batman_packet->header.ttl == 1) &&
+ (new_batman_packet->header.ttl == 2) &&
(forw_packet->if_incoming == if_incoming) &&
/* packets from direct neighbors or
@@ -314,7 +314,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name)
batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
batman_packet->header.packet_type = BAT_PACKET;
batman_packet->header.version = COMPAT_VERSION;
- batman_packet->header.ttl = 2;
+ batman_packet->header.ttl = 3;
batman_packet->flags = 0;
batman_packet->tq = TQ_MAX_VALUE;
batman_packet->num_hna = 0;
@@ -930,73 +930,6 @@ out:
return ret;
}
-static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
- struct sk_buff *skb)
-{
- struct orig_node *orig_node = NULL;
- struct neigh_node *neigh_node = NULL;
- struct icmp_packet *icmp_packet;
- int ret = NET_RX_DROP;
-
- icmp_packet = (struct icmp_packet *)skb->data;
-
- /* send TTL exceeded if packet is an echo request (traceroute) */
- if (icmp_packet->msg_type != ECHO_REQUEST) {
- pr_debug("Warning - can't forward icmp packet from %pM to "
- "%pM: ttl exceeded\n", icmp_packet->orig,
- icmp_packet->dst);
- goto out;
- }
-
- if (!bat_priv->primary_if)
- goto out;
-
- /* get routing information */
- rcu_read_lock();
- orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
-
- if (!orig_node)
- goto unlock;
-
- neigh_node = orig_node->router;
-
- if (!neigh_node)
- goto unlock;
-
- if (!atomic_inc_not_zero(&neigh_node->refcount)) {
- neigh_node = NULL;
- goto unlock;
- }
-
- rcu_read_unlock();
-
- /* create a copy of the skb, if needed, to modify it. */
- if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
- goto out;
-
- icmp_packet = (struct icmp_packet *)skb->data;
-
- memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
- memcpy(icmp_packet->orig,
- bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
- icmp_packet->msg_type = TTL_EXCEEDED;
- icmp_packet->header.ttl = TTL;
-
- send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
- ret = NET_RX_SUCCESS;
- goto out;
-
-unlock:
- rcu_read_unlock();
-out:
- if (neigh_node)
- neigh_node_free_ref(neigh_node);
- if (orig_node)
- orig_node_free_ref(orig_node);
- return ret;
-}
-
-
int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
{
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
@@ -1045,10 +978,6 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
if (is_my_mac(icmp_packet->dst))
return recv_my_icmp_packet(bat_priv, skb, hdr_size);
- /* TTL exceeded */
- if (icmp_packet->header.ttl < 2)
- return recv_icmp_ttl_exceeded(bat_priv, skb);
-
/* get routing information */
rcu_read_lock();
orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
@@ -1074,9 +1003,6 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
icmp_packet = (struct icmp_packet_rr *)skb->data;
- /* decrement ttl */
- icmp_packet->header.ttl--;
-
/* route it */
send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
ret = NET_RX_SUCCESS;
@@ -1269,20 +1195,11 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
struct orig_node *orig_node = NULL;
struct neigh_node *neigh_node = NULL;
struct unicast_packet *unicast_packet;
- struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
int ret = NET_RX_DROP;
struct sk_buff *new_skb;
unicast_packet = (struct unicast_packet *)skb->data;
- /* TTL exceeded */
- if (unicast_packet->header.ttl < 2) {
- pr_debug("Warning - can't forward unicast packet from %pM to "
- "%pM: ttl exceeded\n", ethhdr->h_source,
- unicast_packet->dest);
- goto out;
- }
-
/* get routing information */
rcu_read_lock();
orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
@@ -1327,12 +1244,8 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
}
skb = new_skb;
- unicast_packet = (struct unicast_packet *)skb->data;
}
- /* decrement ttl */
- unicast_packet->header.ttl--;
-
/* route it */
send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
ret = NET_RX_SUCCESS;
@@ -1435,9 +1348,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
if (is_my_mac(bcast_packet->orig))
goto out;
- if (bcast_packet->header.ttl < 2)
- goto out;
-
rcu_read_lock();
orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
@@ -22,6 +22,7 @@
#include "main.h"
#include "send.h"
#include "routing.h"
+#include "hash.h"
#include "translation-table.h"
#include "soft-interface.h"
#include "hard-interface.h"
@@ -53,13 +54,105 @@ static unsigned long forward_send_time(void)
return jiffies + msecs_to_jiffies(random32() % (JITTER/2));
}
+static int send_icmp_ttl_exceeded(struct bat_priv *bat_priv,
+ struct sk_buff *skb)
+{
+ struct orig_node *orig_node = NULL;
+ struct neigh_node *neigh_node = NULL;
+ struct icmp_packet *icmp_packet;
+ int ret = NET_RX_DROP;
+
+ icmp_packet = (struct icmp_packet *)skb->data;
+
+ /* send TTL exceeded if packet is an echo request (traceroute) */
+ if (icmp_packet->msg_type != ECHO_REQUEST) {
+ pr_debug("Warning - can't forward icmp packet from %pM to "
+ "%pM: ttl exceeded\n", icmp_packet->orig,
+ icmp_packet->dst);
+ goto out;
+ }
+
+ if (!bat_priv->primary_if)
+ goto out;
+
+ /* get routing information */
+ rcu_read_lock();
+ orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
+
+ if (!orig_node)
+ goto unlock;
+
+ neigh_node = orig_node->router;
+
+ if (!neigh_node)
+ goto unlock;
+
+ if (!atomic_inc_not_zero(&neigh_node->refcount)) {
+ neigh_node = NULL;
+ goto unlock;
+ }
+
+ rcu_read_unlock();
+
+ /* create a copy of the skb, if needed, to modify it. */
+ if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
+ goto out;
+
+ icmp_packet = (struct icmp_packet *)skb->data;
+
+ memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+ memcpy(icmp_packet->orig,
+ bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+ icmp_packet->msg_type = TTL_EXCEEDED;
+ icmp_packet->header.ttl = TTL;
+
+ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+ ret = NET_RX_SUCCESS;
+ goto out;
+
+unlock:
+ rcu_read_unlock();
+out:
+ if (neigh_node)
+ neigh_node_free_ref(neigh_node);
+ if (orig_node)
+ orig_node_free_ref(orig_node);
+ return ret;
+}
+
+static void print_ttl_exceeded(struct sk_buff *skb, int packet_type,
+ struct bat_priv *bat_priv) {
+ switch (packet_type) {
+ case BAT_PACKET:
+ bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
+ break;
+ case BAT_ICMP:
+ send_icmp_ttl_exceeded(bat_priv, skb);
+ break;
+ case BAT_VIS:
+ pr_debug("Error - can't send vis packet: ttl exceeded\n");
+ break;
+ case BAT_UNICAST:
+ pr_debug("Warning - can't forward unicast packet from %pM to "
+ "%pM: ttl exceeded\n",
+ ((struct ethhdr *)skb->data)->h_source,
+ ((struct unicast_packet *)skb->data)->dest);
+ break;
+ default:
+ break;
+ }
+}
+
/* send out an already prepared packet to the given address via the
- * specified batman interface */
+ * specified batman interface; drops it if the current TTL is 1 or less
+ * or else reduces the TTL by one */
int send_skb_packet(struct sk_buff *skb,
struct hard_iface *hard_iface,
uint8_t *dst_addr)
{
struct ethhdr *ethhdr;
+ struct batman_header *batman_header;
+ struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
if (hard_iface->if_status != IF_ACTIVE)
goto send_skb_err;
@@ -73,6 +166,15 @@ int send_skb_packet(struct sk_buff *skb,
goto send_skb_err;
}
+ if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet))))
+ goto send_skb_err;
+ batman_header = (struct batman_header *) skb->data;
+ if (batman_header->ttl <= 1) {
+ print_ttl_exceeded(skb, batman_header->packet_type, bat_priv);
+ goto send_skb_err;
+ }
+ batman_header->ttl--;
+
/* push to the ethernet header. */
if (my_skb_head_push(skb, sizeof(struct ethhdr)) < 0)
goto send_skb_err;
@@ -182,7 +284,7 @@ static void send_packet(struct forw_packet *forw_packet)
/* multihomed peer assumed */
/* non-primary OGMs are only broadcasted on their interface */
- if ((directlink && (batman_packet->header.ttl == 1)) ||
+ if ((directlink && (batman_packet->header.ttl == 2)) ||
(forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
/* FIXME: what about aggregated packets ? */
@@ -311,15 +413,9 @@ void schedule_forward_packet(struct orig_node *orig_node,
unsigned char in_tq, in_ttl, tq_avg = 0;
unsigned long send_time;
- if (batman_packet->header.ttl <= 1) {
- bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
- return;
- }
-
in_tq = batman_packet->tq;
in_ttl = batman_packet->header.ttl;
- batman_packet->header.ttl--;
memcpy(batman_packet->prev_sender, ethhdr->h_source, ETH_ALEN);
/* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast
@@ -332,7 +428,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
if (orig_node->router->last_ttl)
batman_packet->header.ttl =
- orig_node->router->last_ttl - 1;
+ orig_node->router->last_ttl;
}
tq_avg = orig_node->router->tq_avg;
@@ -344,8 +440,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
bat_dbg(DBG_BATMAN, bat_priv,
"Forwarding packet: tq_orig: %i, tq_avg: %i, "
"tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
- in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
- batman_packet->header.ttl);
+ in_tq, tq_avg, batman_packet->tq, in_ttl,
+ batman_packet->header.ttl - 1);
batman_packet->seqno = htonl(batman_packet->seqno);
@@ -400,7 +496,6 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
{
struct forw_packet *forw_packet;
- struct bcast_packet *bcast_packet;
if (!atomic_dec_not_zero(&bat_priv->bcast_queue_left)) {
bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
@@ -419,10 +514,6 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb)
if (!skb)
goto packet_free;
- /* as we have a copy now, it is safe to decrease the TTL */
- bcast_packet = (struct bcast_packet *)skb->data;
- bcast_packet->header.ttl--;
-
skb_reset_mac_header(skb);
forw_packet->skb = skb;
@@ -250,7 +250,6 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
memcpy(frag1, &tmp_uc, sizeof(struct unicast_packet));
- frag1->header.ttl--;
frag1->header.version = COMPAT_VERSION;
frag1->header.packet_type = BAT_UNICAST_FRAG;
@@ -327,8 +326,6 @@ find_router:
if (atomic_read(&bat_priv->fragmentation) &&
data_len + sizeof(struct unicast_packet) >
neigh_node->if_incoming->net_dev->mtu) {
- /* send frag skb decreases ttl */
- unicast_packet->header.ttl++;
ret = frag_send_skb(skb, bat_priv,
neigh_node->if_incoming, neigh_node->addr);
goto out;
@@ -819,20 +819,14 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info)
struct vis_packet *packet;
packet = (struct vis_packet *)info->skb_packet->data;
- if (packet->header.ttl < 2) {
- pr_debug("Error - can't send vis packet: ttl exceeded\n");
- return;
- }
memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr,
ETH_ALEN);
- packet->header.ttl--;
if (is_broadcast_ether_addr(packet->target_orig))
broadcast_vis_packet(bat_priv, info);
else
unicast_vis_packet(bat_priv, info);
- packet->header.ttl++; /* restore TTL */
}
/* called from timer; send (and maybe generate) vis packet. */