diff options
author | Masahide NAKAMURA <nakam@linux-ipv6.org> | 2007-12-20 23:41:57 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:59:37 -0500 |
commit | 9473e1f631de339c50bde1e3bd09e1045fe90fd5 (patch) | |
tree | 5a9f4901ec220f594b8d77685c29b521578551b3 | |
parent | a1b051405bc16222d92c73b0c26d65b333a154ee (diff) |
[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>
-rw-r--r-- | net/ipv6/xfrm6_input.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 74f3aacebb5e..f835ab458f5b 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -63,10 +63,26 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
63 | struct xfrm_state *x = NULL; | 63 | struct xfrm_state *x = NULL; |
64 | int wildcard = 0; | 64 | int wildcard = 0; |
65 | xfrm_address_t *xany; | 65 | xfrm_address_t *xany; |
66 | struct xfrm_state *xfrm_vec_one = NULL; | ||
67 | int nh = 0; | 66 | int nh = 0; |
68 | int i = 0; | 67 | int i = 0; |
69 | 68 | ||
69 | /* Allocate new secpath or COW existing one. */ | ||
70 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { | ||
71 | struct sec_path *sp; | ||
72 | |||
73 | sp = secpath_dup(skb->sp); | ||
74 | if (!sp) { | ||
75 | goto drop; | ||
76 | } | ||
77 | if (skb->sp) | ||
78 | secpath_put(skb->sp); | ||
79 | skb->sp = sp; | ||
80 | } | ||
81 | |||
82 | if (1 + skb->sp->len == XFRM_MAX_DEPTH) { | ||
83 | goto drop; | ||
84 | } | ||
85 | |||
70 | xany = (xfrm_address_t *)&in6addr_any; | 86 | xany = (xfrm_address_t *)&in6addr_any; |
71 | 87 | ||
72 | for (i = 0; i < 3; i++) { | 88 | for (i = 0; i < 3; i++) { |
@@ -119,47 +135,35 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | |||
119 | continue; | 135 | continue; |
120 | } | 136 | } |
121 | 137 | ||
138 | spin_unlock(&x->lock); | ||
139 | |||
122 | nh = x->type->input(x, skb); | 140 | nh = x->type->input(x, skb); |
123 | if (nh <= 0) { | 141 | if (nh <= 0) { |
124 | spin_unlock(&x->lock); | ||
125 | xfrm_state_put(x); | 142 | xfrm_state_put(x); |
126 | x = NULL; | 143 | x = NULL; |
127 | continue; | 144 | continue; |
128 | } | 145 | } |
129 | 146 | ||
130 | x->curlft.bytes += skb->len; | 147 | /* Found a state */ |
131 | x->curlft.packets++; | ||
132 | |||
133 | spin_unlock(&x->lock); | ||
134 | |||
135 | xfrm_vec_one = x; | ||
136 | break; | 148 | break; |
137 | } | 149 | } |
138 | 150 | ||
139 | if (!xfrm_vec_one) | 151 | if (!x) { |
140 | goto drop; | 152 | goto drop; |
141 | |||
142 | /* Allocate new secpath or COW existing one. */ | ||
143 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { | ||
144 | struct sec_path *sp; | ||
145 | sp = secpath_dup(skb->sp); | ||
146 | if (!sp) | ||
147 | goto drop; | ||
148 | if (skb->sp) | ||
149 | secpath_put(skb->sp); | ||
150 | skb->sp = sp; | ||
151 | } | 153 | } |
152 | 154 | ||
153 | if (1 + skb->sp->len > XFRM_MAX_DEPTH) | 155 | skb->sp->xvec[skb->sp->len++] = x; |
154 | goto drop; | 156 | |
157 | spin_lock(&x->lock); | ||
155 | 158 | ||
156 | skb->sp->xvec[skb->sp->len] = xfrm_vec_one; | 159 | x->curlft.bytes += skb->len; |
157 | skb->sp->len ++; | 160 | x->curlft.packets++; |
161 | |||
162 | spin_unlock(&x->lock); | ||
158 | 163 | ||
159 | return 1; | 164 | return 1; |
165 | |||
160 | drop: | 166 | drop: |
161 | if (xfrm_vec_one) | ||
162 | xfrm_state_put(xfrm_vec_one); | ||
163 | return -1; | 167 | return -1; |
164 | } | 168 | } |
165 | 169 | ||