struct sec_path *sp;
sp = secpath_dup(skb->sp);
- if (!sp)
+ if (!sp) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINERROR);
goto drop;
+ }
if (skb->sp)
secpath_put(skb->sp);
skb->sp = sp;
family = XFRM_SPI_SKB_CB(skb)->family;
seq = 0;
- if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
+ if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
goto drop;
+ }
do {
- if (skb->sp->len == XFRM_MAX_DEPTH)
+ if (skb->sp->len == XFRM_MAX_DEPTH) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR);
goto drop;
+ }
x = xfrm_state_lookup(daddr, spi, nexthdr, family);
- if (x == NULL)
+ if (x == NULL) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES);
goto drop;
+ }
skb->sp->xvec[skb->sp->len++] = x;
spin_lock(&x->lock);
- if (unlikely(x->km.state != XFRM_STATE_VALID))
+ if (unlikely(x->km.state != XFRM_STATE_VALID)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID);
goto drop_unlock;
+ }
- if ((x->encap ? x->encap->encap_type : 0) != encap_type)
+ if ((x->encap ? x->encap->encap_type : 0) != encap_type) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID);
goto drop_unlock;
+ }
- if (x->props.replay_window && xfrm_replay_check(x, seq))
+ if (x->props.replay_window && xfrm_replay_check(x, seq)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINSEQOUTOFWINDOW);
goto drop_unlock;
+ }
- if (xfrm_state_check_expire(x))
+ if (xfrm_state_check_expire(x)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEEXPIRED);
goto drop_unlock;
+ }
spin_unlock(&x->lock);
if (nexthdr <= 0) {
if (nexthdr == -EBADMSG)
x->stats.integrity_failed++;
+ XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEPROTOERROR);
goto drop_unlock;
}
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
- if (x->inner_mode->input(x, skb))
+ if (x->inner_mode->input(x, skb)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR);
goto drop;
+ }
if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
decaps = 1;
family = x->outer_mode->afinfo->family;
err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
- if (err < 0)
+ if (err < 0) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
goto drop;
+ }
} while (!err);
nf_reset(skb);
if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
err = PTR_ERR(policy);
- if (IS_ERR(policy))
+ if (IS_ERR(policy)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR);
goto dropdst;
+ }
}
if (!policy) {
default:
case XFRM_POLICY_BLOCK:
/* Prohibit the flow */
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK);
err = -EPERM;
goto error;
*/
dst = xfrm_find_bundle(fl, policy, family);
if (IS_ERR(dst)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
err = PTR_ERR(dst);
goto error;
}
XFRM_POLICY_OUT);
if (pols[1]) {
if (IS_ERR(pols[1])) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR);
err = PTR_ERR(pols[1]);
goto error;
}
if (pols[1]->action == XFRM_POLICY_BLOCK) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK);
err = -EPERM;
goto error;
}
nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family);
if (nx == -EAGAIN && signal_pending(current)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES);
err = -ERESTART;
goto error;
}
}
err = nx;
}
- if (err < 0)
+ if (err < 0) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES);
goto error;
+ }
}
if (nx == 0) {
/* Flow passes not transformed. */
dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig);
err = PTR_ERR(dst);
- if (IS_ERR(dst))
+ if (IS_ERR(dst)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLEGENERROR);
goto error;
+ }
for (pi = 0; pi < npols; pi++) {
read_lock_bh(&pols[pi]->lock);
if (dst)
dst_free(dst);
+ if (pol_dead)
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD);
+ else
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
err = -EHOSTUNREACH;
goto error;
}
write_unlock_bh(&policy->lock);
if (dst)
dst_free(dst);
+ XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
goto error;
}
dir &= XFRM_POLICY_MASK;
fl_dir = policy_to_flow_dir(dir);
- if (__xfrm_decode_session(skb, &fl, family, reverse) < 0)
+ if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
return 0;
+ }
+
nf_nat_decode_session(skb, &fl, family);
/* First, check used SA against their selectors. */
for (i=skb->sp->len-1; i>=0; i--) {
struct xfrm_state *x = skb->sp->xvec[i];
- if (!xfrm_selector_match(&x->sel, &fl, family))
+ if (!xfrm_selector_match(&x->sel, &fl, family)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH);
return 0;
+ }
}
}
pol = NULL;
if (sk && sk->sk_policy[dir]) {
pol = xfrm_sk_policy_lookup(sk, dir, &fl);
- if (IS_ERR(pol))
+ if (IS_ERR(pol)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
return 0;
+ }
}
if (!pol)
pol = flow_cache_lookup(&fl, family, fl_dir,
xfrm_policy_lookup);
- if (IS_ERR(pol))
+ if (IS_ERR(pol)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
return 0;
+ }
if (!pol) {
if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
xfrm_secpath_reject(xerr_idx, skb, &fl);
+ XFRM_INC_STATS(LINUX_MIB_XFRMINNOPOLS);
return 0;
}
return 1;
&fl, family,
XFRM_POLICY_IN);
if (pols[1]) {
- if (IS_ERR(pols[1]))
+ if (IS_ERR(pols[1])) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR);
return 0;
+ }
pols[1]->curlft.use_time = get_seconds();
npols ++;
}
for (pi = 0; pi < npols; pi++) {
if (pols[pi] != pol &&
- pols[pi]->action != XFRM_POLICY_ALLOW)
+ pols[pi]->action != XFRM_POLICY_ALLOW) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK);
goto reject;
- if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH)
+ }
+ if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR);
goto reject_error;
+ }
for (i = 0; i < pols[pi]->xfrm_nr; i++)
tpp[ti++] = &pols[pi]->xfrm_vec[i];
}
if (k < -1)
/* "-2 - errored_index" returned */
xerr_idx = -(2+k);
+ XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH);
goto reject;
}
}
- if (secpath_has_nontransport(sp, k, &xerr_idx))
+ if (secpath_has_nontransport(sp, k, &xerr_idx)) {
+ XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH);
goto reject;
+ }
xfrm_pols_put(pols, npols);
return 1;
}
+ XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK);
reject:
xfrm_secpath_reject(xerr_idx, skb, &fl);
{
struct flowi fl;
- if (xfrm_decode_session(skb, &fl, family) < 0)
+ if (xfrm_decode_session(skb, &fl, family) < 0) {
+ /* XXX: we should have something like FWDHDRERROR here. */
+ XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR);
return 0;
+ }
return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
}