aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_input.c')
-rw-r--r--net/xfrm/xfrm_input.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 8624cbdb2a1e..493243fc5fe5 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -119,8 +119,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
119 struct sec_path *sp; 119 struct sec_path *sp;
120 120
121 sp = secpath_dup(skb->sp); 121 sp = secpath_dup(skb->sp);
122 if (!sp) 122 if (!sp) {
123 XFRM_INC_STATS(LINUX_MIB_XFRMINERROR);
123 goto drop; 124 goto drop;
125 }
124 if (skb->sp) 126 if (skb->sp)
125 secpath_put(skb->sp); 127 secpath_put(skb->sp);
126 skb->sp = sp; 128 skb->sp = sp;
@@ -131,31 +133,45 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
131 family = XFRM_SPI_SKB_CB(skb)->family; 133 family = XFRM_SPI_SKB_CB(skb)->family;
132 134
133 seq = 0; 135 seq = 0;
134 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) 136 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
137 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
135 goto drop; 138 goto drop;
139 }
136 140
137 do { 141 do {
138 if (skb->sp->len == XFRM_MAX_DEPTH) 142 if (skb->sp->len == XFRM_MAX_DEPTH) {
143 XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR);
139 goto drop; 144 goto drop;
145 }
140 146
141 x = xfrm_state_lookup(daddr, spi, nexthdr, family); 147 x = xfrm_state_lookup(daddr, spi, nexthdr, family);
142 if (x == NULL) 148 if (x == NULL) {
149 XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES);
143 goto drop; 150 goto drop;
151 }
144 152
145 skb->sp->xvec[skb->sp->len++] = x; 153 skb->sp->xvec[skb->sp->len++] = x;
146 154
147 spin_lock(&x->lock); 155 spin_lock(&x->lock);
148 if (unlikely(x->km.state != XFRM_STATE_VALID)) 156 if (unlikely(x->km.state != XFRM_STATE_VALID)) {
157 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID);
149 goto drop_unlock; 158 goto drop_unlock;
159 }
150 160
151 if ((x->encap ? x->encap->encap_type : 0) != encap_type) 161 if ((x->encap ? x->encap->encap_type : 0) != encap_type) {
162 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID);
152 goto drop_unlock; 163 goto drop_unlock;
164 }
153 165
154 if (x->props.replay_window && xfrm_replay_check(x, seq)) 166 if (x->props.replay_window && xfrm_replay_check(x, seq)) {
167 XFRM_INC_STATS(LINUX_MIB_XFRMINSEQOUTOFWINDOW);
155 goto drop_unlock; 168 goto drop_unlock;
169 }
156 170
157 if (xfrm_state_check_expire(x)) 171 if (xfrm_state_check_expire(x)) {
172 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEEXPIRED);
158 goto drop_unlock; 173 goto drop_unlock;
174 }
159 175
160 spin_unlock(&x->lock); 176 spin_unlock(&x->lock);
161 177
@@ -171,6 +187,7 @@ resume:
171 if (nexthdr <= 0) { 187 if (nexthdr <= 0) {
172 if (nexthdr == -EBADMSG) 188 if (nexthdr == -EBADMSG)
173 x->stats.integrity_failed++; 189 x->stats.integrity_failed++;
190 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEPROTOERROR);
174 goto drop_unlock; 191 goto drop_unlock;
175 } 192 }
176 193
@@ -187,8 +204,10 @@ resume:
187 204
188 XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; 205 XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
189 206
190 if (x->inner_mode->input(x, skb)) 207 if (x->inner_mode->input(x, skb)) {
208 XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR);
191 goto drop; 209 goto drop;
210 }
192 211
193 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { 212 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
194 decaps = 1; 213 decaps = 1;
@@ -203,8 +222,10 @@ resume:
203 family = x->outer_mode->afinfo->family; 222 family = x->outer_mode->afinfo->family;
204 223
205 err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); 224 err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
206 if (err < 0) 225 if (err < 0) {
226 XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
207 goto drop; 227 goto drop;
228 }
208 } while (!err); 229 } while (!err);
209 230
210 nf_reset(skb); 231 nf_reset(skb);