batman-adv: Make bat_priv->primary_if an rcu protected pointer
[pandora-kernel.git] / net / batman-adv / icmp_socket.c
index 49079c2..fa22ba2 100644 (file)
@@ -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);
@@ -233,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,
@@ -248,6 +255,8 @@ dst_unreach:
 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)