]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/xfrm4_output.c
[IPV4]: Add ip_local_out
[linux-2.6-omap-h63xx.git] / net / ipv4 / xfrm4_output.c
index c4a7156962bd58797d93b7c21051bcc797c98de9..0ffc3d07848942b78eb41025a175876d81b4fbe5 100644 (file)
@@ -8,11 +8,12 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/compiler.h>
 #include <linux/if_ether.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/netfilter_ipv4.h>
+#include <net/dst.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/icmp.h>
@@ -25,8 +26,6 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
        if (IPCB(skb)->flags & IPSKB_XFRM_TUNNEL_SIZE)
                goto out;
 
-       IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
-
        if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->local_df)
                goto out;
 
@@ -40,27 +39,42 @@ out:
        return ret;
 }
 
-static inline int xfrm4_output_one(struct sk_buff *skb)
+int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct dst_entry *dst = skb->dst;
-       struct xfrm_state *x = dst->xfrm;
-       struct iphdr *iph;
        int err;
 
-       if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
-               err = xfrm4_tunnel_check_size(skb);
-               if (err)
-                       goto error_nolock;
-       }
+       err = xfrm4_tunnel_check_size(skb);
+       if (err)
+               return err;
+
+       return xfrm4_extract_header(skb);
+}
+
+int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int err;
+
+       err = x->inner_mode->afinfo->extract_output(x, skb);
+       if (err)
+               return err;
+
+       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+       IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
+
+       skb->protocol = htons(ETH_P_IP);
+
+       return x->outer_mode->output2(x, skb);
+}
+EXPORT_SYMBOL(xfrm4_prepare_output);
+
+static inline int xfrm4_output_one(struct sk_buff *skb)
+{
+       int err;
 
        err = xfrm_output(skb);
        if (err)
                goto error_nolock;
 
-       iph = ip_hdr(skb);
-       iph->tot_len = htons(skb->len);
-       ip_send_check(iph);
-
        IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
        err = 0;
 
@@ -78,8 +92,7 @@ static int xfrm4_output_finish2(struct sk_buff *skb)
        while (likely((err = xfrm4_output_one(skb)) == 0)) {
                nf_reset(skb);
 
-               err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
-                             skb->dst->dev, dst_output);
+               err = __ip_local_out(skb);
                if (unlikely(err != 1))
                        break;