[XFRM] MIPv6: Fix to input RO state correctly.

Disable spin_lock during xfrm_type.input() function.
Follow design as IPsec inbound does.

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Masahide NAKAMURA 2007-12-20 20:41:57 -08:00 committed by David S. Miller
parent a1b051405b
commit 9473e1f631

View File

@ -63,10 +63,26 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
struct xfrm_state *x = NULL; struct xfrm_state *x = NULL;
int wildcard = 0; int wildcard = 0;
xfrm_address_t *xany; xfrm_address_t *xany;
struct xfrm_state *xfrm_vec_one = NULL;
int nh = 0; int nh = 0;
int i = 0; int i = 0;
/* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
struct sec_path *sp;
sp = secpath_dup(skb->sp);
if (!sp) {
goto drop;
}
if (skb->sp)
secpath_put(skb->sp);
skb->sp = sp;
}
if (1 + skb->sp->len == XFRM_MAX_DEPTH) {
goto drop;
}
xany = (xfrm_address_t *)&in6addr_any; xany = (xfrm_address_t *)&in6addr_any;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
@ -119,47 +135,35 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
continue; continue;
} }
spin_unlock(&x->lock);
nh = x->type->input(x, skb); nh = x->type->input(x, skb);
if (nh <= 0) { if (nh <= 0) {
spin_unlock(&x->lock);
xfrm_state_put(x); xfrm_state_put(x);
x = NULL; x = NULL;
continue; continue;
} }
x->curlft.bytes += skb->len; /* Found a state */
x->curlft.packets++;
spin_unlock(&x->lock);
xfrm_vec_one = x;
break; break;
} }
if (!xfrm_vec_one) if (!x) {
goto drop; goto drop;
/* Allocate new secpath or COW existing one. */
if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
struct sec_path *sp;
sp = secpath_dup(skb->sp);
if (!sp)
goto drop;
if (skb->sp)
secpath_put(skb->sp);
skb->sp = sp;
} }
if (1 + skb->sp->len > XFRM_MAX_DEPTH) skb->sp->xvec[skb->sp->len++] = x;
goto drop;
skb->sp->xvec[skb->sp->len] = xfrm_vec_one; spin_lock(&x->lock);
skb->sp->len ++;
x->curlft.bytes += skb->len;
x->curlft.packets++;
spin_unlock(&x->lock);
return 1; return 1;
drop: drop:
if (xfrm_vec_one)
xfrm_state_put(xfrm_vec_one);
return -1; return -1;
} }