diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/xfrm6_state.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 9c95b9d3e110..e0b8f3c5caa2 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -156,12 +156,109 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto, | |||
156 | return x0; | 156 | return x0; |
157 | } | 157 | } |
158 | 158 | ||
159 | static int | ||
160 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | ||
161 | { | ||
162 | int i; | ||
163 | int j = 0; | ||
164 | |||
165 | /* Rule 1: select IPsec transport except AH */ | ||
166 | for (i = 0; i < n; i++) { | ||
167 | if (src[i]->props.mode == XFRM_MODE_TRANSPORT && | ||
168 | src[i]->id.proto != IPPROTO_AH) { | ||
169 | dst[j++] = src[i]; | ||
170 | src[i] = NULL; | ||
171 | } | ||
172 | } | ||
173 | if (j == n) | ||
174 | goto end; | ||
175 | |||
176 | /* XXX: Rule 2: select MIPv6 RO or inbound trigger */ | ||
177 | |||
178 | /* Rule 3: select IPsec transport AH */ | ||
179 | for (i = 0; i < n; i++) { | ||
180 | if (src[i] && | ||
181 | src[i]->props.mode == XFRM_MODE_TRANSPORT && | ||
182 | src[i]->id.proto == IPPROTO_AH) { | ||
183 | dst[j++] = src[i]; | ||
184 | src[i] = NULL; | ||
185 | } | ||
186 | } | ||
187 | if (j == n) | ||
188 | goto end; | ||
189 | |||
190 | /* Rule 4: select IPsec tunnel */ | ||
191 | for (i = 0; i < n; i++) { | ||
192 | if (src[i] && | ||
193 | src[i]->props.mode == XFRM_MODE_TUNNEL) { | ||
194 | dst[j++] = src[i]; | ||
195 | src[i] = NULL; | ||
196 | } | ||
197 | } | ||
198 | if (likely(j == n)) | ||
199 | goto end; | ||
200 | |||
201 | /* Final rule */ | ||
202 | for (i = 0; i < n; i++) { | ||
203 | if (src[i]) { | ||
204 | dst[j++] = src[i]; | ||
205 | src[i] = NULL; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | end: | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int | ||
214 | __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | ||
215 | { | ||
216 | int i; | ||
217 | int j = 0; | ||
218 | |||
219 | /* Rule 1: select IPsec transport */ | ||
220 | for (i = 0; i < n; i++) { | ||
221 | if (src[i]->mode == XFRM_MODE_TRANSPORT) { | ||
222 | dst[j++] = src[i]; | ||
223 | src[i] = NULL; | ||
224 | } | ||
225 | } | ||
226 | if (j == n) | ||
227 | goto end; | ||
228 | |||
229 | /* XXX: Rule 2: select MIPv6 RO or inbound trigger */ | ||
230 | |||
231 | /* Rule 3: select IPsec tunnel */ | ||
232 | for (i = 0; i < n; i++) { | ||
233 | if (src[i] && | ||
234 | src[i]->mode == XFRM_MODE_TUNNEL) { | ||
235 | dst[j++] = src[i]; | ||
236 | src[i] = NULL; | ||
237 | } | ||
238 | } | ||
239 | if (likely(j == n)) | ||
240 | goto end; | ||
241 | |||
242 | /* Final rule */ | ||
243 | for (i = 0; i < n; i++) { | ||
244 | if (src[i]) { | ||
245 | dst[j++] = src[i]; | ||
246 | src[i] = NULL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | end: | ||
251 | return 0; | ||
252 | } | ||
253 | |||
159 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { | 254 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { |
160 | .family = AF_INET6, | 255 | .family = AF_INET6, |
161 | .init_tempsel = __xfrm6_init_tempsel, | 256 | .init_tempsel = __xfrm6_init_tempsel, |
162 | .state_lookup = __xfrm6_state_lookup, | 257 | .state_lookup = __xfrm6_state_lookup, |
163 | .state_lookup_byaddr = __xfrm6_state_lookup_byaddr, | 258 | .state_lookup_byaddr = __xfrm6_state_lookup_byaddr, |
164 | .find_acq = __xfrm6_find_acq, | 259 | .find_acq = __xfrm6_find_acq, |
260 | .tmpl_sort = __xfrm6_tmpl_sort, | ||
261 | .state_sort = __xfrm6_state_sort, | ||
165 | }; | 262 | }; |
166 | 263 | ||
167 | void __init xfrm6_state_init(void) | 264 | void __init xfrm6_state_init(void) |