diff options
Diffstat (limited to 'net/xfrm/xfrm_output.c')
-rw-r--r-- | net/xfrm/xfrm_output.c | 19 |
1 files changed, 7 insertions, 12 deletions
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 64f2ae1fdc15..47bacd8c0250 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -67,17 +67,10 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
67 | goto error; | 67 | goto error; |
68 | } | 68 | } |
69 | 69 | ||
70 | if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { | 70 | err = x->repl->overflow(x, skb); |
71 | XFRM_SKB_CB(skb)->seq.output = ++x->replay.oseq; | 71 | if (err) { |
72 | if (unlikely(x->replay.oseq == 0)) { | 72 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR); |
73 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR); | 73 | goto error; |
74 | x->replay.oseq--; | ||
75 | xfrm_audit_state_replay_overflow(x, skb); | ||
76 | err = -EOVERFLOW; | ||
77 | goto error; | ||
78 | } | ||
79 | if (xfrm_aevent_is_on(net)) | ||
80 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); | ||
81 | } | 74 | } |
82 | 75 | ||
83 | x->curlft.bytes += skb->len; | 76 | x->curlft.bytes += skb->len; |
@@ -85,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
85 | 78 | ||
86 | spin_unlock_bh(&x->lock); | 79 | spin_unlock_bh(&x->lock); |
87 | 80 | ||
81 | skb_dst_force(skb); | ||
82 | |||
88 | err = x->type->output(x, skb); | 83 | err = x->type->output(x, skb); |
89 | if (err == -EINPROGRESS) | 84 | if (err == -EINPROGRESS) |
90 | goto out_exit; | 85 | goto out_exit; |
@@ -101,7 +96,7 @@ resume: | |||
101 | err = -EHOSTUNREACH; | 96 | err = -EHOSTUNREACH; |
102 | goto error_nolock; | 97 | goto error_nolock; |
103 | } | 98 | } |
104 | skb_dst_set(skb, dst_clone(dst)); | 99 | skb_dst_set(skb, dst); |
105 | x = dst->xfrm; | 100 | x = dst->xfrm; |
106 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); | 101 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
107 | 102 | ||