diff options
| author | Arnaud Ebalard <arno@natisbad.org> | 2008-10-05 16:33:42 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-10-05 16:33:42 -0400 |
| commit | 13c1d18931ebb5cf407cb348ef2cd6284d68902d (patch) | |
| tree | 6d590f85e48b4cce8f67e42c65b88fce8fcc49c6 | |
| parent | 95430c0b140c31cb9e39f876afe1c0e9947d1aaf (diff) | |
xfrm: MIGRATE enhancements (draft-ebalard-mext-pfkey-enhanced-migrate)
Provides implementation of the enhancements of XFRM/PF_KEY MIGRATE mechanism
specified in draft-ebalard-mext-pfkey-enhanced-migrate-00. Defines associated
PF_KEY SADB_X_EXT_KMADDRESS extension and XFRM/netlink XFRMA_KMADDRESS
attribute.
Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/linux/pfkeyv2.h | 13 | ||||
| -rw-r--r-- | include/linux/xfrm.h | 10 | ||||
| -rw-r--r-- | include/net/xfrm.h | 15 | ||||
| -rw-r--r-- | net/key/af_key.c | 86 | ||||
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 5 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 5 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 57 |
7 files changed, 154 insertions, 37 deletions
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index 700725ddcaae..01b262959f2e 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h | |||
| @@ -226,6 +226,15 @@ struct sadb_x_sec_ctx { | |||
| 226 | } __attribute__((packed)); | 226 | } __attribute__((packed)); |
| 227 | /* sizeof(struct sadb_sec_ctx) = 8 */ | 227 | /* sizeof(struct sadb_sec_ctx) = 8 */ |
| 228 | 228 | ||
| 229 | /* Used by MIGRATE to pass addresses IKE will use to perform | ||
| 230 | * negotiation with the peer */ | ||
| 231 | struct sadb_x_kmaddress { | ||
| 232 | uint16_t sadb_x_kmaddress_len; | ||
| 233 | uint16_t sadb_x_kmaddress_exttype; | ||
| 234 | uint32_t sadb_x_kmaddress_reserved; | ||
| 235 | } __attribute__((packed)); | ||
| 236 | /* sizeof(struct sadb_x_kmaddress) == 8 */ | ||
| 237 | |||
| 229 | /* Message types */ | 238 | /* Message types */ |
| 230 | #define SADB_RESERVED 0 | 239 | #define SADB_RESERVED 0 |
| 231 | #define SADB_GETSPI 1 | 240 | #define SADB_GETSPI 1 |
| @@ -346,7 +355,9 @@ struct sadb_x_sec_ctx { | |||
| 346 | #define SADB_X_EXT_NAT_T_DPORT 22 | 355 | #define SADB_X_EXT_NAT_T_DPORT 22 |
| 347 | #define SADB_X_EXT_NAT_T_OA 23 | 356 | #define SADB_X_EXT_NAT_T_OA 23 |
| 348 | #define SADB_X_EXT_SEC_CTX 24 | 357 | #define SADB_X_EXT_SEC_CTX 24 |
| 349 | #define SADB_EXT_MAX 24 | 358 | /* Used with MIGRATE to pass @ to IKE for negotiation */ |
| 359 | #define SADB_X_EXT_KMADDRESS 25 | ||
| 360 | #define SADB_EXT_MAX 25 | ||
| 350 | 361 | ||
| 351 | /* Identity Extension values */ | 362 | /* Identity Extension values */ |
| 352 | #define SADB_IDENTTYPE_RESERVED 0 | 363 | #define SADB_IDENTTYPE_RESERVED 0 |
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index fb0c215a3051..4bc1e6b86cb2 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
| @@ -279,6 +279,7 @@ enum xfrm_attr_type_t { | |||
| 279 | XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ | 279 | XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ |
| 280 | XFRMA_MIGRATE, | 280 | XFRMA_MIGRATE, |
| 281 | XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ | 281 | XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ |
| 282 | XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */ | ||
| 282 | __XFRMA_MAX | 283 | __XFRMA_MAX |
| 283 | 284 | ||
| 284 | #define XFRMA_MAX (__XFRMA_MAX - 1) | 285 | #define XFRMA_MAX (__XFRMA_MAX - 1) |
| @@ -415,6 +416,15 @@ struct xfrm_user_report { | |||
| 415 | struct xfrm_selector sel; | 416 | struct xfrm_selector sel; |
| 416 | }; | 417 | }; |
| 417 | 418 | ||
| 419 | /* Used by MIGRATE to pass addresses IKE should use to perform | ||
| 420 | * SA negotiation with the peer */ | ||
| 421 | struct xfrm_user_kmaddress { | ||
| 422 | xfrm_address_t local; | ||
| 423 | xfrm_address_t remote; | ||
| 424 | __u32 reserved; | ||
| 425 | __u16 family; | ||
| 426 | }; | ||
| 427 | |||
| 418 | struct xfrm_user_migrate { | 428 | struct xfrm_user_migrate { |
| 419 | xfrm_address_t old_daddr; | 429 | xfrm_address_t old_daddr; |
| 420 | xfrm_address_t old_saddr; | 430 | xfrm_address_t old_saddr; |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index b98d2056f27f..11c890ad8ebb 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -492,6 +492,13 @@ struct xfrm_policy | |||
| 492 | struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; | 492 | struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; |
| 493 | }; | 493 | }; |
| 494 | 494 | ||
| 495 | struct xfrm_kmaddress { | ||
| 496 | xfrm_address_t local; | ||
| 497 | xfrm_address_t remote; | ||
| 498 | u32 reserved; | ||
| 499 | u16 family; | ||
| 500 | }; | ||
| 501 | |||
| 495 | struct xfrm_migrate { | 502 | struct xfrm_migrate { |
| 496 | xfrm_address_t old_daddr; | 503 | xfrm_address_t old_daddr; |
| 497 | xfrm_address_t old_saddr; | 504 | xfrm_address_t old_saddr; |
| @@ -531,7 +538,7 @@ struct xfrm_mgr | |||
| 531 | int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); | 538 | int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); |
| 532 | int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); | 539 | int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); |
| 533 | int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); | 540 | int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); |
| 534 | int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles); | 541 | int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles, struct xfrm_kmaddress *k); |
| 535 | }; | 542 | }; |
| 536 | 543 | ||
| 537 | extern int xfrm_register_km(struct xfrm_mgr *km); | 544 | extern int xfrm_register_km(struct xfrm_mgr *km); |
| @@ -1432,12 +1439,14 @@ extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, | |||
| 1432 | 1439 | ||
| 1433 | #ifdef CONFIG_XFRM_MIGRATE | 1440 | #ifdef CONFIG_XFRM_MIGRATE |
| 1434 | extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1441 | extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 1435 | struct xfrm_migrate *m, int num_bundles); | 1442 | struct xfrm_migrate *m, int num_bundles, |
| 1443 | struct xfrm_kmaddress *k); | ||
| 1436 | extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m); | 1444 | extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m); |
| 1437 | extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x, | 1445 | extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x, |
| 1438 | struct xfrm_migrate *m); | 1446 | struct xfrm_migrate *m); |
| 1439 | extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1447 | extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 1440 | struct xfrm_migrate *m, int num_bundles); | 1448 | struct xfrm_migrate *m, int num_bundles, |
| 1449 | struct xfrm_kmaddress *k); | ||
| 1441 | #endif | 1450 | #endif |
| 1442 | 1451 | ||
| 1443 | extern wait_queue_head_t km_waitq; | 1452 | extern wait_queue_head_t km_waitq; |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 7ae641df70bd..362fe317e1f3 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -398,6 +398,7 @@ static u8 sadb_ext_min_len[] = { | |||
| 398 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), | 398 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), |
| 399 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), | 399 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), |
| 400 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), | 400 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), |
| 401 | [SADB_X_EXT_KMADDRESS] = (u8) sizeof(struct sadb_x_kmaddress), | ||
| 401 | }; | 402 | }; |
| 402 | 403 | ||
| 403 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ | 404 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ |
| @@ -2384,24 +2385,21 @@ static int pfkey_sockaddr_pair_size(sa_family_t family) | |||
| 2384 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); | 2385 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); |
| 2385 | } | 2386 | } |
| 2386 | 2387 | ||
| 2387 | static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, | 2388 | static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, |
| 2388 | xfrm_address_t *saddr, xfrm_address_t *daddr, | 2389 | xfrm_address_t *saddr, xfrm_address_t *daddr, |
| 2389 | u16 *family) | 2390 | u16 *family) |
| 2390 | { | 2391 | { |
| 2391 | u8 *sa = (u8 *) (rq + 1); | ||
| 2392 | int af, socklen; | 2392 | int af, socklen; |
| 2393 | 2393 | ||
| 2394 | if (rq->sadb_x_ipsecrequest_len < | 2394 | if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) |
| 2395 | pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family)) | ||
| 2396 | return -EINVAL; | 2395 | return -EINVAL; |
| 2397 | 2396 | ||
| 2398 | af = pfkey_sockaddr_extract((struct sockaddr *) sa, | 2397 | af = pfkey_sockaddr_extract(sa, saddr); |
| 2399 | saddr); | ||
| 2400 | if (!af) | 2398 | if (!af) |
| 2401 | return -EINVAL; | 2399 | return -EINVAL; |
| 2402 | 2400 | ||
| 2403 | socklen = pfkey_sockaddr_len(af); | 2401 | socklen = pfkey_sockaddr_len(af); |
| 2404 | if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen), | 2402 | if (pfkey_sockaddr_extract((struct sockaddr *) (((u8 *)sa) + socklen), |
| 2405 | daddr) != af) | 2403 | daddr) != af) |
| 2406 | return -EINVAL; | 2404 | return -EINVAL; |
| 2407 | 2405 | ||
| @@ -2421,7 +2419,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
| 2421 | return -EINVAL; | 2419 | return -EINVAL; |
| 2422 | 2420 | ||
| 2423 | /* old endoints */ | 2421 | /* old endoints */ |
| 2424 | err = parse_sockaddr_pair(rq1, &m->old_saddr, &m->old_daddr, | 2422 | err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), |
| 2423 | rq1->sadb_x_ipsecrequest_len, | ||
| 2424 | &m->old_saddr, &m->old_daddr, | ||
| 2425 | &m->old_family); | 2425 | &m->old_family); |
| 2426 | if (err) | 2426 | if (err) |
| 2427 | return err; | 2427 | return err; |
| @@ -2434,7 +2434,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
| 2434 | return -EINVAL; | 2434 | return -EINVAL; |
| 2435 | 2435 | ||
| 2436 | /* new endpoints */ | 2436 | /* new endpoints */ |
| 2437 | err = parse_sockaddr_pair(rq2, &m->new_saddr, &m->new_daddr, | 2437 | err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), |
| 2438 | rq2->sadb_x_ipsecrequest_len, | ||
| 2439 | &m->new_saddr, &m- | ||
