diff options
Diffstat (limited to 'drivers/staging/batman-adv/icmp_socket.c')
-rw-r--r-- | drivers/staging/batman-adv/icmp_socket.c | 73 |
1 files changed, 47 insertions, 26 deletions
diff --git a/drivers/staging/batman-adv/icmp_socket.c b/drivers/staging/batman-adv/icmp_socket.c index 3ae7dd2..48856ca 100644 --- a/drivers/staging/batman-adv/icmp_socket.c +++ b/drivers/staging/batman-adv/icmp_socket.c @@ -45,6 +45,8 @@ static int bat_socket_open(struct inode *inode, struct file *file) unsigned int i; struct socket_client *socket_client; + nonseekable_open(inode, file); + socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL); if (!socket_client) @@ -154,7 +156,9 @@ 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 icmp_packet_rr icmp_packet; + struct sk_buff *skb; + struct icmp_packet_rr *icmp_packet; + struct orig_node *orig_node; struct batman_if *batman_if; size_t packet_len = sizeof(struct icmp_packet); @@ -174,40 +178,54 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (len >= sizeof(struct icmp_packet_rr)) packet_len = sizeof(struct icmp_packet_rr); - if (!access_ok(VERIFY_READ, buff, packet_len)) - return -EFAULT; + skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); + if (!skb) + return -ENOMEM; - if (__copy_from_user(&icmp_packet, buff, packet_len)) - return -EFAULT; + skb_reserve(skb, sizeof(struct ethhdr)); + icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); + + if (!access_ok(VERIFY_READ, buff, packet_len)) { + len = -EFAULT; + goto free_skb; + } + + if (__copy_from_user(icmp_packet, buff, packet_len)) { + len = -EFAULT; + goto free_skb; + } - if (icmp_packet.packet_type != BAT_ICMP) { + if (icmp_packet->packet_type != BAT_ICMP) { bat_dbg(DBG_BATMAN, bat_priv, "Error - can't send packet from char device: " "got bogus packet type (expected: BAT_ICMP)\n"); - return -EINVAL; + len = -EINVAL; + goto free_skb; } - if (icmp_packet.msg_type != ECHO_REQUEST) { + if (icmp_packet->msg_type != ECHO_REQUEST) { bat_dbg(DBG_BATMAN, bat_priv, "Error - can't send packet from char device: " "got bogus message type (expected: ECHO_REQUEST)\n"); - return -EINVAL; + len = -EINVAL; + goto free_skb; } - icmp_packet.uid = socket_client->index; + icmp_packet->uid = socket_client->index; - if (icmp_packet.version != COMPAT_VERSION) { - icmp_packet.msg_type = PARAMETER_PROBLEM; - icmp_packet.ttl = COMPAT_VERSION; - bat_socket_add_packet(socket_client, &icmp_packet, packet_len); - goto out; + if (icmp_packet->version != COMPAT_VERSION) { + icmp_packet->msg_type = PARAMETER_PROBLEM; + icmp_packet->ttl = COMPAT_VERSION; + bat_socket_add_packet(socket_client, icmp_packet, packet_len); + goto free_skb; } - if (atomic_read(&module_state) != MODULE_ACTIVE) + if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto dst_unreach; - spin_lock_irqsave(&orig_hash_lock, flags); - orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst)); + spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash, + icmp_packet->dst)); if (!orig_node) goto unlock; @@ -218,7 +236,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, batman_if = orig_node->router->if_incoming; memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); if (!batman_if) goto dst_unreach; @@ -226,22 +244,24 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (batman_if->if_status != IF_ACTIVE) goto dst_unreach; - memcpy(icmp_packet.orig, + memcpy(icmp_packet->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); if (packet_len == sizeof(struct icmp_packet_rr)) - memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN); + memcpy(icmp_packet->rr, batman_if->net_dev->dev_addr, ETH_ALEN); + - send_raw_packet((unsigned char *)&icmp_packet, - packet_len, batman_if, dstaddr); + send_skb_packet(skb, batman_if, dstaddr); goto out; unlock: - spin_unlock_irqrestore(&orig_hash_lock, flags); + spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); dst_unreach: - icmp_packet.msg_type = DESTINATION_UNREACHABLE; - bat_socket_add_packet(socket_client, &icmp_packet, packet_len); + icmp_packet->msg_type = DESTINATION_UNREACHABLE; + bat_socket_add_packet(socket_client, icmp_packet, packet_len); +free_skb: + kfree_skb(skb); out: return len; } @@ -265,6 +285,7 @@ static const struct file_operations fops = { .read = bat_socket_read, .write = bat_socket_write, .poll = bat_socket_poll, + .llseek = no_llseek, }; int bat_socket_setup(struct bat_priv *bat_priv) |