Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef76bc23 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

[IPV6]: Add ip6_local_out



Most callers of the LOCAL_OUT chain will set the IP packet length
before doing so.  They also share the same output function dst_output.

This patch creates a new function called ip6_local_out which does all
of that and converts the appropriate users over to it.

Apart from removing duplicate code, it will also help in merging the
IPsec output path.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c439cb2e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -509,6 +509,9 @@ extern int ip6_forward(struct sk_buff *skb);
extern int			ip6_input(struct sk_buff *skb);
extern int			ip6_mc_input(struct sk_buff *skb);

extern int			__ip6_local_out(struct sk_buff *skb);
extern int			ip6_local_out(struct sk_buff *skb);

/*
 *	Extension header (options) processing
 */
+27 −6
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@
 */

#include <linux/errno.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/net.h>
@@ -70,6 +70,31 @@ static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *f
	spin_unlock_bh(&ip6_id_lock);
}

int __ip6_local_out(struct sk_buff *skb)
{
	int len;

	len = skb->len - sizeof(struct ipv6hdr);
	if (len > IPV6_MAXPLEN)
		len = 0;
	ipv6_hdr(skb)->payload_len = htons(len);

	return nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev,
		       dst_output);
}

int ip6_local_out(struct sk_buff *skb)
{
	int err;

	err = __ip6_local_out(skb);
	if (likely(err == 1))
		err = dst_output(skb);

	return err;
}
EXPORT_SYMBOL_GPL(ip6_local_out);

static int ip6_output_finish(struct sk_buff *skb)
{
	struct dst_entry *dst = skb->dst;
@@ -1403,10 +1428,6 @@ int ip6_push_pending_frames(struct sock *sk)
	*(__be32*)hdr = fl->fl6_flowlabel |
		     htonl(0x60000000 | ((int)np->cork.tclass << 20));

	if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN)
		hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
	else
		hdr->payload_len = 0;
	hdr->hop_limit = np->cork.hop_limit;
	hdr->nexthdr = proto;
	ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
@@ -1423,7 +1444,7 @@ int ip6_push_pending_frames(struct sock *sk)
		ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
	}

	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
	err = ip6_local_out(skb);
	if (err) {
		if (err > 0)
			err = np->recverr ? net_xmit_errno(err) : 0;
+1 −3
Original line number Diff line number Diff line
@@ -910,15 +910,13 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
	*(__be32*)ipv6h = fl->fl6_flowlabel | htonl(0x60000000);
	dsfield = INET_ECN_encapsulate(0, dsfield);
	ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
	ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
	ipv6h->hop_limit = t->parms.hop_limit;
	ipv6h->nexthdr = proto;
	ipv6_addr_copy(&ipv6h->saddr, &fl->fl6_src);
	ipv6_addr_copy(&ipv6h->daddr, &fl->fl6_dst);
	nf_reset(skb);
	pkt_len = skb->len;
	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
		      skb->dst->dev, dst_output);
	err = ip6_local_out(skb);

	if (net_xmit_eval(err) == 0) {
		stats->tx_bytes += pkt_len;
+1 −3
Original line number Diff line number Diff line
@@ -121,7 +121,6 @@ static void send_reset(struct sk_buff *oldskb)
	ip6h->version = 6;
	ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
	ip6h->nexthdr = IPPROTO_TCP;
	ip6h->payload_len = htons(sizeof(struct tcphdr));
	ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
	ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);

@@ -159,8 +158,7 @@ static void send_reset(struct sk_buff *oldskb)

	nf_ct_attach(nskb, oldskb);

	NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
		dst_output);
	ip6_local_out(nskb);
}

static inline void
+1 −6
Original line number Diff line number Diff line
@@ -75,16 +75,12 @@ EXPORT_SYMBOL(xfrm6_prepare_output);

static inline int xfrm6_output_one(struct sk_buff *skb)
{
	struct ipv6hdr *iph;
	int err;

	err = xfrm_output(skb);
	if (err)
		goto error_nolock;

	iph = ipv6_hdr(skb);
	iph->payload_len = htons(skb->len - sizeof(*iph));

	IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
	err = 0;

@@ -102,8 +98,7 @@ static int xfrm6_output_finish2(struct sk_buff *skb)
	while (likely((err = xfrm6_output_one(skb)) == 0)) {
		nf_reset(skb);

		err = nf_hook(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL,
			      skb->dst->dev, dst_output);
		err = __ip6_local_out(skb);
		if (unlikely(err != 1))
			break;