diff options
Diffstat (limited to 'net/batman-adv/icmp_socket.c')
| -rw-r--r-- | net/batman-adv/icmp_socket.c | 37 | 
1 files changed, 17 insertions, 20 deletions
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 34ce56c358e..fa22ba2bb83 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,  {  	struct socket_client *socket_client = file->private_data;  	struct bat_priv *bat_priv = socket_client->bat_priv; +	struct hard_iface *primary_if = NULL;  	struct sk_buff *skb;  	struct icmp_packet_rr *icmp_packet; @@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,  		return -EINVAL;  	} -	if (!bat_priv->primary_if) -		return -EFAULT; +	primary_if = primary_if_get_selected(bat_priv); + +	if (!primary_if) { +		len = -EFAULT; +		goto out; +	}  	if (len >= sizeof(struct icmp_packet_rr))  		packet_len = sizeof(struct icmp_packet_rr);  	skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); -	if (!skb) -		return -ENOMEM; +	if (!skb) { +		len = -ENOMEM; +		goto out; +	}  	skb_reserve(skb, sizeof(struct ethhdr));  	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,  	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)  		goto dst_unreach; -	rcu_read_lock();  	orig_node = orig_hash_find(bat_priv, icmp_packet->dst); -  	if (!orig_node) -		goto unlock; - -	neigh_node = orig_node->router; +		goto dst_unreach; +	neigh_node = orig_node_get_router(orig_node);  	if (!neigh_node) -		goto unlock; - -	if (!atomic_inc_not_zero(&neigh_node->refcount)) { -		neigh_node = NULL; -		goto unlock; -	} - -	rcu_read_unlock(); +		goto dst_unreach;  	if (!neigh_node->if_incoming)  		goto dst_unreach; @@ -243,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,  		goto dst_unreach;  	memcpy(icmp_packet->orig, -	       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); +	       primary_if->net_dev->dev_addr, ETH_ALEN);  	if (packet_len == sizeof(struct icmp_packet_rr))  		memcpy(icmp_packet->rr, @@ -252,14 +249,14 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,  	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);  	goto out; -unlock: -	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 (primary_if) +		hardif_free_ref(primary_if);  	if (neigh_node)  		neigh_node_free_ref(neigh_node);  	if (orig_node)  |