summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2015-03-02 00:09:42 -0600
committerDavid S. Miller <davem@davemloft.net>2015-03-02 16:43:41 -0500
commit945db424bfbcb7b72a92702a487dc0000cd1efed (patch)
treeb1228e2999e98fd7d3e62979b84c005ca48343c9
parentabb7b755d9af48c762a6f814e4cead677e694f93 (diff)
ax25: Stop depending on arp_find
Have ax25_neigh_output perform ordinary arp resolution before calling ax25_neigh_xmit. Call dev_hard_header in ax25_neigh_output with a destination address so it will not fail, and the destination mac address will not need to be set in ax25_neigh_xmit. Remove arp_find from ax25_neigh_xmit (the ordinary arp resolution added to ax25_neigh_output removes the need for calling arp_find). Document how close ax25_neigh_output is to neigh_resolve_output. Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-hams@vger.kernel.org Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ax25/ax25_ip.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index 08803e820f1d..e030c64ebfb7 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -115,9 +115,6 @@ static int ax25_neigh_xmit(struct sk_buff *skb)
dst = (ax25_address *)(bp + 1);
src = (ax25_address *)(bp + 8);
- if (arp_find(bp + 1, skb))
- return 1;
-
route = ax25_get_route(dst, NULL);
if (route) {
digipeat = route->digipeat;
@@ -218,16 +215,35 @@ put:
static int ax25_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
{
- struct net_device *dev = skb->dev;
-
- __skb_pull(skb, skb_network_offset(skb));
-
- if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
- skb->len) < 0 &&
- ax25_neigh_xmit(skb));
- return 0;
+ /* Except for calling ax25_neigh_xmit instead of
+ * dev_queue_xmit this is neigh_resolve_output.
+ */
+ int rc = 0;
+
+ if (!neigh_event_send(neigh, skb)) {
+ int err;
+ struct net_device *dev = neigh->dev;
+ unsigned int seq;
+
+ do {
+ __skb_pull(skb, skb_network_offset(skb));
+ seq = read_seqbegin(&neigh->ha_lock);
+ err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+ neigh->ha, NULL, skb->len);
+ } while (read_seqretry(&neigh->ha_lock, seq));
+
+ if (err >= 0) {
+ ax25_neigh_xmit(skb);
+ } else
+ goto out_kfree_skb;
+ }
+out:
+ return rc;
- return dev_queue_xmit(skb);
+out_kfree_skb:
+ rc = -EINVAL;
+ kfree_skb(skb);
+ goto out;
}
int ax25_neigh_construct(struct neighbour *neigh)