|
@@ -156,12 +156,109 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto,
|
|
|
return x0;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ int j = 0;
|
|
|
+
|
|
|
+ /* Rule 1: select IPsec transport except AH */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
|
|
|
+ src[i]->id.proto != IPPROTO_AH) {
|
|
|
+ dst[j++] = src[i];
|
|
|
+ src[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (j == n)
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ /* XXX: Rule 2: select MIPv6 RO or inbound trigger */
|
|
|
+
|
|
|
+ /* Rule 3: select IPsec transport AH */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ if (src[i] &&
|
|
|
+ src[i]->props.mode == XFRM_MODE_TRANSPORT &&
|
|
|
+ src[i]->id.proto == IPPROTO_AH) {
|
|
|
+ dst[j++] = src[i];
|
|
|
+ src[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (j == n)
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ /* Rule 4: select IPsec tunnel */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ if (src[i] &&
|
|
|
+ src[i]->props.mode == XFRM_MODE_TUNNEL) {
|
|
|
+ dst[j++] = src[i];
|
|
|
+ src[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (likely(j == n))
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ /* Final rule */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ if (src[i]) {
|
|
|
+ dst[j++] = src[i];
|
|
|
+ src[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ end:
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ int j = 0;
|
|
|
+
|
|
|
+ /* Rule 1: select IPsec transport */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ if (src[i]->mode == XFRM_MODE_TRANSPORT) {
|
|
|
+ dst[j++] = src[i];
|
|
|
+ src[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (j == n)
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ /* XXX: Rule 2: select MIPv6 RO or inbound trigger */
|
|
|
+
|
|
|
+ /* Rule 3: select IPsec tunnel */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ if (src[i] &&
|
|
|
+ src[i]->mode == XFRM_MODE_TUNNEL) {
|
|
|
+ dst[j++] = src[i];
|
|
|
+ src[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (likely(j == n))
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ /* Final rule */
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
+ if (src[i]) {
|
|
|
+ dst[j++] = src[i];
|
|
|
+ src[i] = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ end:
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static struct xfrm_state_afinfo xfrm6_state_afinfo = {
|
|
|
.family = AF_INET6,
|
|
|
.init_tempsel = __xfrm6_init_tempsel,
|
|
|
.state_lookup = __xfrm6_state_lookup,
|
|
|
.state_lookup_byaddr = __xfrm6_state_lookup_byaddr,
|
|
|
.find_acq = __xfrm6_find_acq,
|
|
|
+ .tmpl_sort = __xfrm6_tmpl_sort,
|
|
|
+ .state_sort = __xfrm6_state_sort,
|
|
|
};
|
|
|
|
|
|
void __init xfrm6_state_init(void)
|