diff options
author | Martin Willi <martin@strongswan.org> | 2008-10-28 19:01:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-28 19:01:07 -0400 |
commit | 3a2dfbe8acb154905fdc2fd03ec56df42e6c4cc4 (patch) | |
tree | 9dbbc8324deb6463f546e53cd2ac9a676bd0fd55 | |
parent | 93adcc80f3288f1827baf6f821af818f6eeef7f9 (diff) |
xfrm: Notify changes in UDP encapsulation via netlink
Add new_mapping() implementation to the netlink xfrm_mgr to notify
address/port changes detected in UDP encapsulated ESP packets.
Signed-off-by: Martin Willi <martin@strongswan.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/xfrm.h | 14 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 52 |
2 files changed, 66 insertions, 0 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 4bc1e6b86cb2..52f3abd453a1 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
@@ -199,6 +199,9 @@ enum { | |||
199 | #define XFRM_MSG_NEWSPDINFO XFRM_MSG_NEWSPDINFO | 199 | #define XFRM_MSG_NEWSPDINFO XFRM_MSG_NEWSPDINFO |
200 | XFRM_MSG_GETSPDINFO, | 200 | XFRM_MSG_GETSPDINFO, |
201 | #define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO | 201 | #define XFRM_MSG_GETSPDINFO XFRM_MSG_GETSPDINFO |
202 | |||
203 | XFRM_MSG_MAPPING, | ||
204 | #define XFRM_MSG_MAPPING XFRM_MSG_MAPPING | ||
202 | __XFRM_MSG_MAX | 205 | __XFRM_MSG_MAX |
203 | }; | 206 | }; |
204 | #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) | 207 | #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) |
@@ -438,6 +441,15 @@ struct xfrm_user_migrate { | |||
438 | __u16 new_family; | 441 | __u16 new_family; |
439 | }; | 442 | }; |
440 | 443 | ||
444 | struct xfrm_user_mapping { | ||
445 | struct xfrm_usersa_id id; | ||
446 | __u32 reqid; | ||
447 | xfrm_address_t old_saddr; | ||
448 | xfrm_address_t new_saddr; | ||
449 | __be16 old_sport; | ||
450 | __be16 new_sport; | ||
451 | }; | ||
452 | |||
441 | #ifndef __KERNEL__ | 453 | #ifndef __KERNEL__ |
442 | /* backwards compatibility for userspace */ | 454 | /* backwards compatibility for userspace */ |
443 | #define XFRMGRP_ACQUIRE 1 | 455 | #define XFRMGRP_ACQUIRE 1 |
@@ -464,6 +476,8 @@ enum xfrm_nlgroups { | |||
464 | #define XFRMNLGRP_REPORT XFRMNLGRP_REPORT | 476 | #define XFRMNLGRP_REPORT XFRMNLGRP_REPORT |
465 | XFRMNLGRP_MIGRATE, | 477 | XFRMNLGRP_MIGRATE, |
466 | #define XFRMNLGRP_MIGRATE XFRMNLGRP_MIGRATE | 478 | #define XFRMNLGRP_MIGRATE XFRMNLGRP_MIGRATE |
479 | XFRMNLGRP_MAPPING, | ||
480 | #define XFRMNLGRP_MAPPING XFRMNLGRP_MAPPING | ||
467 | __XFRMNLGRP_MAX | 481 | __XFRMNLGRP_MAX |
468 | }; | 482 | }; |
469 | #define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) | 483 | #define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 4a8a1abb59ee..76cf56d5d834 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -2503,6 +2503,57 @@ static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, | |||
2503 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); | 2503 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); |
2504 | } | 2504 | } |
2505 | 2505 | ||
2506 | static inline size_t xfrm_mapping_msgsize(void) | ||
2507 | { | ||
2508 | return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping)); | ||
2509 | } | ||
2510 | |||
2511 | static int build_mapping(struct sk_buff *skb, struct xfrm_state *x, | ||
2512 | xfrm_address_t *new_saddr, __be16 new_sport) | ||
2513 | { | ||
2514 | struct xfrm_user_mapping *um; | ||
2515 | struct nlmsghdr *nlh; | ||
2516 | |||
2517 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0); | ||
2518 | if (nlh == NULL) | ||
2519 | return -EMSGSIZE; | ||
2520 | |||
2521 | um = nlmsg_data(nlh); | ||
2522 | |||
2523 | memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr)); | ||
2524 | um->id.spi = x->id.spi; | ||
2525 | um->id.family = x->props.family; | ||
2526 | um->id.proto = x->id.proto; | ||
2527 | memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr)); | ||
2528 | memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr)); | ||
2529 | um->new_sport = new_sport; | ||
2530 | um->old_sport = x->encap->encap_sport; | ||
2531 | um->reqid = x->props.reqid; | ||
2532 | |||
2533 | return nlmsg_end(skb, nlh); | ||
2534 | } | ||
2535 | |||
2536 | static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | ||
2537 | __be16 sport) | ||
2538 | { | ||
2539 | struct sk_buff *skb; | ||
2540 | |||
2541 | if (x->id.proto != IPPROTO_ESP) | ||
2542 | return -EINVAL; | ||
2543 | |||
2544 | if (!x->encap) | ||
2545 | return -EINVAL; | ||
2546 | |||
2547 | skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC); | ||
2548 | if (skb == NULL) | ||
2549 | return -ENOMEM; | ||
2550 | |||
2551 | if (build_mapping(skb, x, ipaddr, sport) < 0) | ||
2552 | BUG(); | ||
2553 | |||
2554 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); | ||
2555 | } | ||
2556 | |||
2506 | static struct xfrm_mgr netlink_mgr = { | 2557 | static struct xfrm_mgr netlink_mgr = { |
2507 | .id = "netlink", | 2558 | .id = "netlink", |
2508 | .notify = xfrm_send_state_notify, | 2559 | .notify = xfrm_send_state_notify, |
@@ -2511,6 +2562,7 @@ static struct xfrm_mgr netlink_mgr = { | |||
2511 | .notify_policy = xfrm_send_policy_notify, | 2562 | .notify_policy = xfrm_send_policy_notify, |
2512 | .report = xfrm_send_report, | 2563 | .report = xfrm_send_report, |
2513 | .migrate = xfrm_send_migrate, | 2564 | .migrate = xfrm_send_migrate, |
2565 | .new_mapping = xfrm_send_mapping, | ||
2514 | }; | 2566 | }; |
2515 | 2567 | ||
2516 | static int __init xfrm_user_init(void) | 2568 | static int __init xfrm_user_init(void) |