aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_state.c19
-rw-r--r--net/xfrm/xfrm_user.c46
2 files changed, 65 insertions, 0 deletions
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)