aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2006-08-23 23:44:06 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:08:30 -0400
commit97a64b4577ae2bc5599dbd008a3cd9e25de9b9f5 (patch)
tree424700fb0a41b28c5615d0d21ca74d699e1fa872
parentdf0ba92a99ca757039dfa84a929281ea3f7a50e8 (diff)
[XFRM]: Introduce XFRM_MSG_REPORT.
XFRM_MSG_REPORT is a message as notification of state protocol and selector from kernel to user-space. Mobile IPv6 will use it when inbound reject is occurred at route optimization to make user-space know a binding error requirement. Based on MIPL2 kernel patch. Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/xfrm.h12
-rw-r--r--include/net/xfrm.h2
-rw-r--r--net/xfrm/xfrm_state.c19
-rw-r--r--net/xfrm/xfrm_user.c46
4 files changed, 79 insertions, 0 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 1d8c1f22c12d..4009f4445fa9 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -166,6 +166,10 @@ enum {
166#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE 166#define XFRM_MSG_NEWAE XFRM_MSG_NEWAE
167 XFRM_MSG_GETAE, 167 XFRM_MSG_GETAE,
168#define XFRM_MSG_GETAE XFRM_MSG_GETAE 168#define XFRM_MSG_GETAE XFRM_MSG_GETAE
169
170 XFRM_MSG_REPORT,
171#define XFRM_MSG_REPORT XFRM_MSG_REPORT
172
169 __XFRM_MSG_MAX 173 __XFRM_MSG_MAX
170}; 174};
171#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) 175#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -325,12 +329,18 @@ struct xfrm_usersa_flush {
325 __u8 proto; 329 __u8 proto;
326}; 330};
327 331
332struct xfrm_user_report {
333 __u8 proto;
334 struct xfrm_selector sel;
335};
336
328#ifndef __KERNEL__ 337#ifndef __KERNEL__
329/* backwards compatibility for userspace */ 338/* backwards compatibility for userspace */
330#define XFRMGRP_ACQUIRE 1 339#define XFRMGRP_ACQUIRE 1
331#define XFRMGRP_EXPIRE 2 340#define XFRMGRP_EXPIRE 2
332#define XFRMGRP_SA 4 341#define XFRMGRP_SA 4
333#define XFRMGRP_POLICY 8 342#define XFRMGRP_POLICY 8
343#define XFRMGRP_REPORT 0x10
334#endif 344#endif
335 345
336enum xfrm_nlgroups { 346enum xfrm_nlgroups {
@@ -346,6 +356,8 @@ enum xfrm_nlgroups {
346#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY 356#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY
347 XFRMNLGRP_AEVENTS, 357 XFRMNLGRP_AEVENTS,
348#define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS 358#define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS
359 XFRMNLGRP_REPORT,
360#define XFRMNLGRP_REPORT XFRMNLGRP_REPORT
349 __XFRMNLGRP_MAX 361 __XFRMNLGRP_MAX
350}; 362};
351#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) 363#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 9ebbdc1dd471..0b223eed4c9b 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -381,6 +381,7 @@ struct xfrm_mgr
381 struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir); 381 struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
382 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); 382 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
383 int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); 383 int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
384 int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
384}; 385};
385 386
386extern int xfrm_register_km(struct xfrm_mgr *km); 387extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -1043,6 +1044,7 @@ extern void xfrm_init_pmtu(struct dst_entry *dst);
1043extern wait_queue_head_t km_waitq; 1044extern wait_queue_head_t km_waitq;
1044extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); 1045extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
1045extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); 1046extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid);
1047extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
1046 1048
1047extern void xfrm_input_init(void); 1049extern void xfrm_input_init(void);
1048extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); 1050extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 3da89c01ea71..a26ef6952c30 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1055,6 +1055,25 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
1055} 1055}
1056EXPORT_SYMBOL(km_policy_expired); 1056EXPORT_SYMBOL(km_policy_expired);
1057 1057
1058int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr)
1059{
1060 int err = -EINVAL;
1061 int ret;
1062 struct xfrm_mgr *km;
1063
1064 read_lock(&xfrm_km_lock);
1065 list_for_each_entry(km, &xfrm_km_list, list) {
1066 if (km->report) {
1067 ret = km->report(proto, sel, addr);
1068 if (!ret)
1069 err = ret;
1070 }
1071 }
1072 read_unlock(&xfrm_km_lock);
1073 return err;
1074}
1075EXPORT_SYMBOL(km_report);
1076
1058int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) 1077int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
1059{ 1078{
1060 int err; 1079 int err;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 770bd2410749..7303b820bea4 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1491,6 +1491,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
1491 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), 1491 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0),
1492 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), 1492 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
1493 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), 1493 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
1494 [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
1494}; 1495};
1495 1496
1496#undef XMSGSIZE 1497#undef XMSGSIZE
@@ -2058,12 +2059,57 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_ev
2058 2059
2059} 2060}
2060 2061
2062static int build_report(struct sk_buff *skb, u8 proto,
2063 struct xfrm_selector *sel, xfrm_address_t *addr)
2064{
2065 struct xfrm_user_report *ur;
2066 struct nlmsghdr *nlh;
2067 unsigned char *b = skb->tail;
2068
2069 nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur));
2070 ur = NLMSG_DATA(nlh);
2071 nlh->nlmsg_flags = 0;
2072
2073 ur->proto = proto;
2074 memcpy(&ur->sel, sel, sizeof(ur->sel));
2075
2076 if (addr)
2077 RTA_PUT(skb, XFRMA_COADDR, sizeof(*addr), addr);
2078
2079 nlh->nlmsg_len = skb->tail - b;
2080 return skb->len;
2081
2082nlmsg_failure:
2083rtattr_failure:
2084 skb_trim(skb, b - skb->data);
2085 return -1;
2086}
2087
2088static int xfrm_send_report(u8 proto, struct xfrm_selector *sel,
2089 xfrm_address_t *addr)
2090{
2091 struct sk_buff *skb;
2092 size_t len;
2093
2094 len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct xfrm_user_report)));
2095 skb = alloc_skb(len, GFP_ATOMIC);
2096 if (skb == NULL)
2097 return -ENOMEM;
2098
2099 if (build_report(skb, proto, sel, addr) < 0)
2100 BUG();
2101
2102 NETLINK_CB(skb).dst_group = XFRMNLGRP_REPORT;
2103 return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC);
2104}
2105
2061static struct xfrm_mgr netlink_mgr = { 2106static struct xfrm_mgr netlink_mgr = {
2062 .id = "netlink", 2107 .id = "netlink",
2063 .notify = xfrm_send_state_notify, 2108 .notify = xfrm_send_state_notify,
2064 .acquire = xfrm_send_acquire, 2109 .acquire = xfrm_send_acquire,
2065 .compile_policy = xfrm_compile_policy, 2110 .compile_policy = xfrm_compile_policy,
2066 .notify_policy = xfrm_send_policy_notify, 2111 .notify_policy = xfrm_send_policy_notify,
2112 .report = xfrm_send_report,
2067}; 2113};
2068 2114
2069static int __init xfrm_user_init(void) 2115static int __init xfrm_user_init(void)