aboutsummaryrefslogtreecommitdiffstats
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 @@
1/* 1/*
2 * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors: 2 * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
3 * 3 *
4 * Marek Lindner 4 * Marek Lindner
5 * 5 *
@@ -24,7 +24,6 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include "icmp_socket.h" 25#include "icmp_socket.h"
26#include "send.h" 26#include "send.h"
27#include "types.h"
28#include "hash.h" 27#include "hash.h"
29#include "originator.h" 28#include "originator.h"
30#include "hard-interface.h" 29#include "hard-interface.h"
@@ -157,10 +156,9 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
157 struct sk_buff *skb; 156 struct sk_buff *skb;
158 struct icmp_packet_rr *icmp_packet; 157 struct icmp_packet_rr *icmp_packet;
159 158
160 struct orig_node *orig_node; 159 struct orig_node *orig_node = NULL;
161 struct batman_if *batman_if; 160 struct neigh_node *neigh_node = NULL;
162 size_t packet_len = sizeof(struct icmp_packet); 161 size_t packet_len = sizeof(struct icmp_packet);
163 uint8_t dstaddr[ETH_ALEN];
164 162
165 if (len < sizeof(struct icmp_packet)) { 163 if (len < sizeof(struct icmp_packet)) {
166 bat_dbg(DBG_BATMAN, bat_priv, 164 bat_dbg(DBG_BATMAN, bat_priv,
@@ -220,47 +218,52 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
220 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) 218 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
221 goto dst_unreach; 219 goto dst_unreach;
222 220
223 spin_lock_bh(&bat_priv->orig_hash_lock); 221 rcu_read_lock();
224 orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, 222 orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
225 compare_orig, choose_orig,
226 icmp_packet->dst));
227 223
228 if (!orig_node) 224 if (!orig_node)
229 goto unlock; 225 goto unlock;
230 226
231 if (!orig_node->router) 227 neigh_node = orig_node->router;
228
229 if (!neigh_node)
232 goto unlock; 230 goto unlock;
233 231
234 batman_if = orig_node->router->if_incoming; 232 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
235 memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); 233 neigh_node = NULL;
234 goto unlock;
235 }
236 236
237 spin_unlock_bh(&bat_priv->orig_hash_lock); 237 rcu_read_unlock();
238 238
239 if (!batman_if) 239 if (!neigh_node->if_incoming)
240 goto dst_unreach; 240 goto dst_unreach;
241 241
242 if (batman_if->if_status != IF_ACTIVE) 242 if (neigh_node->if_incoming->if_status != IF_ACTIVE)
243 goto dst_unreach; 243 goto dst_unreach;
244 244
245 memcpy(icmp_packet->orig, 245 memcpy(icmp_packet->orig,
246 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 246 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
247 247
248 if (packet_len == sizeof(struct icmp_packet_rr)) 248 if (packet_len == sizeof(struct icmp_packet_rr))
249 memcpy(icmp_packet->rr, batman_if->net_dev->dev_addr, ETH_ALEN); 249 memcpy(icmp_packet->rr,
250 250 neigh_node->if_incoming->net_dev->dev_addr, ETH_ALEN);
251
252 send_skb_packet(skb, batman_if, dstaddr);
253 251
252 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
254 goto out; 253 goto out;
255 254
256unlock: 255unlock:
257 spin_unlock_bh(&bat_priv->orig_hash_lock); 256 rcu_read_unlock();
258dst_unreach: 257dst_unreach:
259 icmp_packet->msg_type = DESTINATION_UNREACHABLE; 258 icmp_packet->msg_type = DESTINATION_UNREACHABLE;
260 bat_socket_add_packet(socket_client, icmp_packet, packet_len); 259 bat_socket_add_packet(socket_client, icmp_packet, packet_len);
261free_skb: 260free_skb:
262 kfree_skb(skb); 261 kfree_skb(skb);
263out: 262out:
263 if (neigh_node)
264 neigh_node_free_ref(neigh_node);
265 if (orig_node)
266 orig_node_free_ref(orig_node);
264 return len; 267 return len;
265} 268}
266 269