aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h15
-rw-r--r--net/key/af_key.c19
-rw-r--r--net/xfrm/xfrm_state.c31
-rw-r--r--net/xfrm/xfrm_user.c6
4 files changed, 71 insertions, 0 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index afa5730fb3bd..5313ccfdeedf 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -594,6 +594,7 @@ struct xfrm_mgr {
594 const struct xfrm_migrate *m, 594 const struct xfrm_migrate *m,
595 int num_bundles, 595 int num_bundles,
596 const struct xfrm_kmaddress *k); 596 const struct xfrm_kmaddress *k);
597 bool (*is_alive)(const struct km_event *c);
597}; 598};
598 599
599int xfrm_register_km(struct xfrm_mgr *km); 600int xfrm_register_km(struct xfrm_mgr *km);
@@ -1646,6 +1647,20 @@ static inline int xfrm_aevent_is_on(struct net *net)
1646 rcu_read_unlock(); 1647 rcu_read_unlock();
1647 return ret; 1648 return ret;
1648} 1649}
1650
1651static inline int xfrm_acquire_is_on(struct net *net)
1652{
1653 struct sock *nlsk;
1654 int ret = 0;
1655
1656 rcu_read_lock();
1657 nlsk = rcu_dereference(net->xfrm.nlsk);
1658 if (nlsk)
1659 ret = netlink_has_listeners(nlsk, XFRMNLGRP_ACQUIRE);
1660 rcu_read_unlock();
1661
1662 return ret;
1663}
1649#endif 1664#endif
1650 1665
1651static inline int xfrm_alg_len(const struct xfrm_algo *alg) 1666static inline int xfrm_alg_len(const struct xfrm_algo *alg)
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 1a04c1329362..e1c69d024197 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3059,6 +3059,24 @@ static u32 get_acqseq(void)
3059 return res; 3059 return res;
3060} 3060}
3061 3061
3062static bool pfkey_is_alive(const struct km_event *c)
3063{
3064 struct netns_pfkey *net_pfkey = net_generic(c->net, pfkey_net_id);
3065 struct sock *sk;
3066 bool is_alive = false;
3067
3068 rcu_read_lock();
3069 sk_for_each_rcu(sk, &net_pfkey->table) {
3070 if (pfkey_sk(sk)->registered) {
3071 is_alive = true;
3072 break;
3073 }
3074 }
3075 rcu_read_unlock();
3076
3077 return is_alive;
3078}
3079
3062static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp) 3080static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp)
3063{ 3081{
3064 struct sk_buff *skb; 3082 struct sk_buff *skb;
@@ -3784,6 +3802,7 @@ static struct xfrm_mgr pfkeyv2_mgr =
3784 .new_mapping = pfkey_send_new_mapping, 3802 .new_mapping = pfkey_send_new_mapping,
3785 .notify_policy = pfkey_send_policy_notify, 3803 .notify_policy = pfkey_send_policy_notify,
3786 .migrate = pfkey_send_migrate, 3804 .migrate = pfkey_send_migrate,
3805 .is_alive = pfkey_is_alive,
3787}; 3806};
3788 3807
3789static int __net_init pfkey_net_init(struct net *net) 3808static int __net_init pfkey_net_init(struct net *net)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index a26b7aa79475..0bf12f665b9b 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -161,6 +161,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
161int __xfrm_state_delete(struct xfrm_state *x); 161int __xfrm_state_delete(struct xfrm_state *x);
162 162
163int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); 163int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
164bool km_is_alive(const struct km_event *c);
164void km_state_expired(struct xfrm_state *x, int hard, u32 portid); 165void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
165 166
166static DEFINE_SPINLOCK(xfrm_type_lock); 167static DEFINE_SPINLOCK(xfrm_type_lock);
@@ -788,6 +789,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
788 struct xfrm_state *best = NULL; 789 struct xfrm_state *best = NULL;
789 u32 mark = pol->mark.v & pol->mark.m; 790 u32 mark = pol->mark.v & pol->mark.m;
790 unsigned short encap_family = tmpl->encap_family; 791 unsigned short encap_family = tmpl->encap_family;
792 struct km_event c;
791 793
792 to_put = NULL; 794 to_put = NULL;
793 795
@@ -832,6 +834,17 @@ found:
832 error = -EEXIST; 834 error = -EEXIST;
833 goto out; 835 goto out;
834 } 836 }
837
838 c.net = net;
839 /* If the KMs have no listeners (yet...), avoid allocating an SA
840 * for each and every packet - garbage collection might not
841 * handle the flood.
842 */
843 if (!km_is_alive(&c)) {
844 error = -ESRCH;
845 goto out;
846 }
847
835 x = xfrm_state_alloc(net); 848 x = xfrm_state_alloc(net);
836 if (x == NULL) { 849 if (x == NULL) {
837 error = -ENOMEM; 850 error = -ENOMEM;
@@ -1793,6 +1806,24 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address
1793} 1806}
1794EXPORT_SYMBOL(km_report); 1807EXPORT_SYMBOL(km_report);
1795 1808
1809bool km_is_alive(const struct km_event *c)
1810{
1811 struct xfrm_mgr *km;
1812 bool is_alive = false;
1813
1814 rcu_read_lock();
1815 list_for_each_entry_rcu(km, &xfrm_km_list, list) {
1816 if (km->is_alive && km->is_alive(c)) {
1817 is_alive = true;
1818 break;
1819 }
1820 }
1821 rcu_read_unlock();
1822
1823 return is_alive;
1824}
1825EXPORT_SYMBOL(km_is_alive);
1826
1796int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) 1827int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
1797{ 1828{
1798 int err; 1829 int err;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ade9988f6e33..d7694f258294 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -2982,6 +2982,11 @@ static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
2982 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); 2982 return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC);
2983} 2983}
2984 2984
2985static bool xfrm_is_alive(const struct km_event *c)
2986{
2987 return (bool)xfrm_acquire_is_on(c->net);
2988}
2989
2985static struct xfrm_mgr netlink_mgr = { 2990static struct xfrm_mgr netlink_mgr = {
2986 .id = "netlink", 2991 .id = "netlink",
2987 .notify = xfrm_send_state_notify, 2992 .notify = xfrm_send_state_notify,
@@ -2991,6 +2996,7 @@ static struct xfrm_mgr netlink_mgr = {
2991 .report = xfrm_send_report, 2996 .report = xfrm_send_report,
2992 .migrate = xfrm_send_migrate, 2997 .migrate = xfrm_send_migrate,
2993 .new_mapping = xfrm_send_mapping, 2998 .new_mapping = xfrm_send_mapping,
2999 .is_alive = xfrm_is_alive,
2994}; 3000};
2995 3001
2996static int __net_init xfrm_user_net_init(struct net *net) 3002static int __net_init xfrm_user_net_init(struct net *net)