Commit d52e90ae authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Greg Kroah-Hartman

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: default avatarSven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e63760e5
...@@ -154,7 +154,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, ...@@ -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, ...@@ -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, ...@@ -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, send_skb_packet(skb, batman_if, dstaddr);
packet_len, 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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment