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.c37
1 files changed, 17 insertions, 20 deletions
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 34ce56c358e5..fa22ba2bb832 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
153{ 153{
154 struct socket_client *socket_client = file->private_data; 154 struct socket_client *socket_client = file->private_data;
155 struct bat_priv *bat_priv = socket_client->bat_priv; 155 struct bat_priv *bat_priv = socket_client->bat_priv;
156 struct hard_iface *primary_if = NULL;
156 struct sk_buff *skb; 157 struct sk_buff *skb;
157 struct icmp_packet_rr *icmp_packet; 158 struct icmp_packet_rr *icmp_packet;
158 159
@@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
167 return -EINVAL; 168 return -EINVAL;
168 } 169 }
169 170
170 if (!bat_priv->primary_if) 171 primary_if = primary_if_get_selected(bat_priv);
171 return -EFAULT; 172
173 if (!primary_if) {
174 len = -EFAULT;
175 goto out;
176 }
172 177
173 if (len >= sizeof(struct icmp_packet_rr)) 178 if (len >= sizeof(struct icmp_packet_rr))
174 packet_len = sizeof(struct icmp_packet_rr); 179 packet_len = sizeof(struct icmp_packet_rr);
175 180
176 skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); 181 skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
177 if (!skb) 182 if (!skb) {
178 return -ENOMEM; 183 len = -ENOMEM;
184 goto out;
185 }
179 186
180 skb_reserve(skb, sizeof(struct ethhdr)); 187 skb_reserve(skb, sizeof(struct ethhdr));
181 icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); 188 icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
@@ -218,23 +225,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
218 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) 225 if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
219 goto dst_unreach; 226 goto dst_unreach;
220 227
221 rcu_read_lock();
222 orig_node = orig_hash_find(bat_priv, icmp_packet->dst); 228 orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
223
224 if (!orig_node) 229 if (!orig_node)
225 goto unlock; 230 goto dst_unreach;
226
227 neigh_node = orig_node->router;
228 231
232 neigh_node = orig_node_get_router(orig_node);
229 if (!neigh_node) 233 if (!neigh_node)
230 goto unlock; 234 goto dst_unreach;
231
232 if (!atomic_inc_not_zero(&neigh_node->refcount)) {
233 neigh_node = NULL;
234 goto unlock;
235 }
236
237 rcu_read_unlock();
238 235
239 if (!neigh_node->if_incoming) 236 if (!neigh_node->if_incoming)
240 goto dst_unreach; 237 goto dst_unreach;
@@ -243,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
243 goto dst_unreach; 240 goto dst_unreach;
244 241
245 memcpy(icmp_packet->orig, 242 memcpy(icmp_packet->orig,
246 bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); 243 primary_if->net_dev->dev_addr, ETH_ALEN);
247 244
248 if (packet_len == sizeof(struct icmp_packet_rr)) 245 if (packet_len == sizeof(struct icmp_packet_rr))
249 memcpy(icmp_packet->rr, 246 memcpy(icmp_packet->rr,
@@ -252,14 +249,14 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
252 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); 249 send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
253 goto out; 250 goto out;
254 251
255unlock:
256 rcu_read_unlock();
257dst_unreach: 252dst_unreach:
258 icmp_packet->msg_type = DESTINATION_UNREACHABLE; 253 icmp_packet->msg_type = DESTINATION_UNREACHABLE;
259 bat_socket_add_packet(socket_client, icmp_packet, packet_len); 254 bat_socket_add_packet(socket_client, icmp_packet, packet_len);
260free_skb: 255free_skb:
261 kfree_skb(skb); 256 kfree_skb(skb);
262out: 257out:
258 if (primary_if)
259 hardif_free_ref(primary_if);
263 if (neigh_node) 260 if (neigh_node)
264 neigh_node_free_ref(neigh_node); 261 neigh_node_free_ref(neigh_node);
265 if (orig_node) 262 if (orig_node)