Merge branch 'linux-2.6'
[powerpc.git] / net / xfrm / xfrm_output.c
index 75f289b..f4bfd6c 100644 (file)
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
-#include <linux/time.h>
 #include <net/dst.h>
 #include <net/xfrm.h>
 
+static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int nhead = x->props.header_len + LL_RESERVED_SPACE(skb->dst->dev)
+               - skb_headroom(skb);
+
+       if (nhead > 0)
+               return pskb_expand_head(skb, nhead, 0, GFP_ATOMIC);
+
+       /* Check tail too... */
+       return 0;
+}
+
+static int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int err = xfrm_state_check_expire(x);
+       if (err < 0)
+               goto err;
+       err = xfrm_state_check_space(x, skb);
+err:
+       return err;
+}
+
 int xfrm_output(struct sk_buff *skb)
 {
        struct dst_entry *dst = skb->dst;
@@ -36,23 +57,24 @@ int xfrm_output(struct sk_buff *skb)
                if (err)
                        goto error;
 
-               err = x->mode->output(x, skb);
-               if (err)
-                       goto error;
+               if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
+                       XFRM_SKB_CB(skb)->seq = ++x->replay.oseq;
+                       if (xfrm_aevent_is_on())
+                               xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+               }
 
-               err = x->type->output(x, skb);
+               err = x->outer_mode->output(x, skb);
                if (err)
                        goto error;
 
                x->curlft.bytes += skb->len;
                x->curlft.packets++;
 
-               if (x->props.mode == XFRM_MODE_ROUTEOPTIMIZATION)
-                       x->lastused = get_seconds();
-
                spin_unlock_bh(&x->lock);
 
-               skb_reset_network_header(skb);
+               err = x->type->output(x, skb);
+               if (err)
+                       goto error_nolock;
 
                if (!(skb->dst = dst_pop(dst))) {
                        err = -EHOSTUNREACH;
@@ -60,7 +82,7 @@ int xfrm_output(struct sk_buff *skb)
                }
                dst = skb->dst;
                x = dst->xfrm;
-       } while (x && (x->props.mode != XFRM_MODE_TUNNEL));
+       } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
 
        err = 0;