diff options
Diffstat (limited to 'net/batman-adv/icmp_socket.c')
-rw-r--r-- | net/batman-adv/icmp_socket.c | 43 |
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 | ||
256 | unlock: | 255 | unlock: |
257 | spin_unlock_bh(&bat_priv->orig_hash_lock); | 256 | rcu_read_unlock(); |
258 | dst_unreach: | 257 | dst_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); |
261 | free_skb: | 260 | free_skb: |
262 | kfree_skb(skb); | 261 | kfree_skb(skb); |
263 | out: | 262 | out: |
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 | ||