Staging: batman-adv: Directly prepare icmp packets in socket buffer
It is unnecessary to generate an icmp packet in an extra memory region and than copying it to a new allocated skb. This also resolved the problem that we do inform the user that we couldn't send the packet because we couldn't allocate the socket buffer. Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e63760e595
commit
d52e90aeaf
@ -154,7 +154,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
|
|||||||
{
|
{
|
||||||
struct socket_client *socket_client = file->private_data;
|
struct socket_client *socket_client = file->private_data;
|
||||||
struct bat_priv *bat_priv = socket_client->bat_priv;
|
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 orig_node *orig_node;
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
size_t packet_len = sizeof(struct icmp_packet);
|
size_t packet_len = sizeof(struct icmp_packet);
|
||||||
@ -174,40 +175,53 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
|
|||||||
if (len >= sizeof(struct icmp_packet_rr))
|
if (len >= sizeof(struct icmp_packet_rr))
|
||||||
packet_len = sizeof(struct icmp_packet_rr);
|
packet_len = sizeof(struct icmp_packet_rr);
|
||||||
|
|
||||||
if (!access_ok(VERIFY_READ, buff, packet_len))
|
skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
|
||||||
return -EFAULT;
|
if (!skb)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
if (__copy_from_user(&icmp_packet, buff, packet_len))
|
skb_reserve(skb, sizeof(struct ethhdr));
|
||||||
return -EFAULT;
|
icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
|
||||||
|
|
||||||
if (icmp_packet.packet_type != BAT_ICMP) {
|
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) {
|
||||||
bat_dbg(DBG_BATMAN, bat_priv,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Error - can't send packet from char device: "
|
"Error - can't send packet from char device: "
|
||||||
"got bogus packet type (expected: BAT_ICMP)\n");
|
"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,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Error - can't send packet from char device: "
|
"Error - can't send packet from char device: "
|
||||||
"got bogus message type (expected: ECHO_REQUEST)\n");
|
"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) {
|
if (icmp_packet->version != COMPAT_VERSION) {
|
||||||
icmp_packet.msg_type = PARAMETER_PROBLEM;
|
icmp_packet->msg_type = PARAMETER_PROBLEM;
|
||||||
icmp_packet.ttl = COMPAT_VERSION;
|
icmp_packet->ttl = COMPAT_VERSION;
|
||||||
bat_socket_add_packet(socket_client, &icmp_packet, packet_len);
|
bat_socket_add_packet(socket_client, icmp_packet, packet_len);
|
||||||
goto out;
|
goto free_skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&module_state) != MODULE_ACTIVE)
|
if (atomic_read(&module_state) != MODULE_ACTIVE)
|
||||||
goto dst_unreach;
|
goto dst_unreach;
|
||||||
|
|
||||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||||
orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
|
orig_node = (struct orig_node *)hash_find(orig_hash, icmp_packet->dst);
|
||||||
|
|
||||||
if (!orig_node)
|
if (!orig_node)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
@ -226,22 +240,24 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
|
|||||||
if (batman_if->if_status != IF_ACTIVE)
|
if (batman_if->if_status != IF_ACTIVE)
|
||||||
goto dst_unreach;
|
goto dst_unreach;
|
||||||
|
|
||||||
memcpy(icmp_packet.orig,
|
memcpy(icmp_packet->orig,
|
||||||
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||||
|
|
||||||
if (packet_len == sizeof(struct icmp_packet_rr))
|
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;
|
goto out;
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
dst_unreach:
|
dst_unreach:
|
||||||
icmp_packet.msg_type = DESTINATION_UNREACHABLE;
|
icmp_packet->msg_type = DESTINATION_UNREACHABLE;
|
||||||
bat_socket_add_packet(socket_client, &icmp_packet, packet_len);
|
bat_socket_add_packet(socket_client, icmp_packet, packet_len);
|
||||||
|
free_skb:
|
||||||
|
kfree_skb(skb);
|
||||||
out:
|
out:
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user