summaryrefslogtreecommitdiffstats
path: root/net/batman-adv/icmp_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/icmp_socket.c')
-rw-r--r--net/batman-adv/icmp_socket.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index ecf6d7ffab2e..34ce56c358e5 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
@@ -24,7 +24,6 @@
#include <linux/slab.h>
#include "icmp_socket.h"
#include "send.h"
-#include "types.h"
#include "hash.h"
#include "originator.h"
#include "hard-interface.h"
@@ -157,10 +156,9 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
struct sk_buff *skb;
struct icmp_packet_rr *icmp_packet;
- struct orig_node *orig_node;
- struct batman_if *batman_if;
+ struct orig_node *orig_node = NULL;
+ struct neigh_node *neigh_node = NULL;
size_t packet_len = sizeof(struct icmp_packet);
- uint8_t dstaddr[ETH_ALEN];
if (len < sizeof(struct icmp_packet)) {
bat_dbg(DBG_BATMAN, bat_priv,
@@ -220,47 +218,52 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
goto dst_unreach;
- spin_lock_bh(&bat_priv->orig_hash_lock);
- orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
- compare_orig, choose_orig,
- icmp_packet->dst));
+ rcu_read_lock();
+ orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
if (!orig_node)
goto unlock;
- if (!orig_node->router)
+ neigh_node = orig_node->router;
+
+ if (!neigh_node)
goto unlock;
- batman_if = orig_node->router->if_incoming;
- memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+ if (!atomic_inc_not_zero(&neigh_node->refcount)) {
+ neigh_node = NULL;
+ goto unlock;
+ }
- spin_unlock_bh(&bat_priv->orig_hash_lock);
+ rcu_read_unlock();
- if (!batman_if)
+ if (!neigh_node->if_incoming)
goto dst_unreach;
- if (batman_if->if_status != IF_ACTIVE)
+ if (neigh_node->if_incoming->if_status != IF_ACTIVE)
goto dst_unreach;
memcpy(icmp_packet->orig,
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
if (packet_len == sizeof(struct icmp_packet_rr))
- memcpy(icmp_packet->rr, batman_if->net_dev->dev_addr, ETH_ALEN);
-
-
- send_skb_packet(skb, batman_if, dstaddr);
+ memcpy(icmp_packet->rr,
+ neigh_node->if_incoming->net_dev->dev_addr, ETH_ALEN);
+ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
goto out;
unlock:
- spin_unlock_bh(&bat_priv->orig_hash_lock);
+ rcu_read_unlock();
dst_unreach:
icmp_packet->msg_type = DESTINATION_UNREACHABLE;
bat_socket_add_packet(socket_client, icmp_packet, packet_len);
free_skb:
kfree_skb(skb);
out:
+ if (neigh_node)
+ neigh_node_free_ref(neigh_node);
+ if (orig_node)
+ orig_node_free_ref(orig_node);
return len;
}