aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaud Ebalard <arno@natisbad.org>2008-10-05 16:33:42 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-05 16:33:42 -0400
commit13c1d18931ebb5cf407cb348ef2cd6284d68902d (patch)
tree6d590f85e48b4cce8f67e42c65b88fce8fcc49c6
parent95430c0b140c31cb9e39f876afe1c0e9947d1aaf (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.h13
-rw-r--r--include/linux/xfrm.h10
-rw-r--r--include/net/xfrm.h15
-rw-r--r--net/key/af_key.c86
-rw-r--r--net/xfrm/xfrm_policy.c5
-rw-r--r--net/xfrm/xfrm_state.c5
-rw-r--r--net/xfrm/xfrm_user.c57
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 */
231struct 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 */
421struct xfrm_user_kmaddress {
422 xfrm_address_t local;
423 xfrm_address_t remote;
424 __u32 reserved;
425 __u16 family;
426};
427
418struct xfrm_user_migrate { 428struct 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
495struct xfrm_kmaddress {
496 xfrm_address_t local;
497 xfrm_address_t remote;
498 u32 reserved;
499 u16 family;
500};
501
495struct xfrm_migrate { 502struct 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
537extern int xfrm_register_km(struct xfrm_mgr *km); 544extern 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
1434extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1441extern 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);
1436extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m); 1444extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
1437extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x, 1445extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
1438 struct xfrm_migrate *m); 1446 struct xfrm_migrate *m);
1439extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1447extern 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
1443extern wait_queue_head_t km_waitq; 1452extern 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
2387static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, 2388static 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-