aboutsummaryrefslogtreecommitdiffstats
path: root/net/key/af_key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/key/af_key.c')
-rw-r--r--net/key/af_key.c120
1 files changed, 99 insertions, 21 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index e9ef9af4a53b..6db58924368a 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -48,6 +48,17 @@ struct pfkey_sock {
48 struct sock sk; 48 struct sock sk;
49 int registered; 49 int registered;
50 int promisc; 50 int promisc;
51
52 struct {
53 uint8_t msg_version;
54 uint32_t msg_pid;
55 int (*dump)(struct pfkey_sock *sk);
56 void (*done)(struct pfkey_sock *sk);
57 union {
58 struct xfrm_policy_walk policy;
59 struct xfrm_state_walk state;
60 } u;
61 } dump;
51}; 62};
52 63
53static inline struct pfkey_sock *pfkey_sk(struct sock *sk) 64static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
@@ -55,6 +66,27 @@ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
55 return (struct pfkey_sock *)sk; 66 return (struct pfkey_sock *)sk;
56} 67}
57 68
69static int pfkey_can_dump(struct sock *sk)
70{
71 if (3 * atomic_read(&sk->sk_rmem_alloc) <= 2 * sk->sk_rcvbuf)
72 return 1;
73 return 0;
74}
75
76static int pfkey_do_dump(struct pfkey_sock *pfk)
77{
78 int rc;
79
80 rc = pfk->dump.dump(pfk);
81 if (rc == -ENOBUFS)
82 return 0;
83
84 pfk->dump.done(pfk);
85 pfk->dump.dump = NULL;
86 pfk->dump.done = NULL;
87 return rc;
88}
89
58static void pfkey_sock_destruct(struct sock *sk) 90static void pfkey_sock_destruct(struct sock *sk)
59{ 91{
60 skb_queue_purge(&sk->sk_receive_queue); 92 skb_queue_purge(&sk->sk_receive_queue);
@@ -1709,45 +1741,60 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
1709 return 0; 1741 return 0;
1710} 1742}
1711 1743
1712struct pfkey_dump_data
1713{
1714 struct sk_buff *skb;
1715 struct sadb_msg *hdr;
1716 struct sock *sk;
1717};
1718
1719static int dump_sa(struct xfrm_state *x, int count, void *ptr) 1744static int dump_sa(struct xfrm_state *x, int count, void *ptr)
1720{ 1745{
1721 struct pfkey_dump_data *data = ptr; 1746 struct pfkey_sock *pfk = ptr;
1722 struct sk_buff *out_skb; 1747 struct sk_buff *out_skb;
1723 struct sadb_msg *out_hdr; 1748 struct sadb_msg *out_hdr;
1724 1749
1750 if (!pfkey_can_dump(&pfk->sk))
1751 return -ENOBUFS;
1752
1725 out_skb = pfkey_xfrm_state2msg(x); 1753 out_skb = pfkey_xfrm_state2msg(x);
1726 if (IS_ERR(out_skb)) 1754 if (IS_ERR(out_skb))
1727 return PTR_ERR(out_skb); 1755 return PTR_ERR(out_skb);
1728 1756
1729 out_hdr = (struct sadb_msg *) out_skb->data; 1757 out_hdr = (struct sadb_msg *) out_skb->data;
1730 out_hdr->sadb_msg_version = data->hdr->sadb_msg_version; 1758 out_hdr->sadb_msg_version = pfk->dump.msg_version;
1731 out_hdr->sadb_msg_type = SADB_DUMP; 1759 out_hdr->sadb_msg_type = SADB_DUMP;
1732 out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); 1760 out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
1733 out_hdr->sadb_msg_errno = 0; 1761 out_hdr->sadb_msg_errno = 0;
1734 out_hdr->sadb_msg_reserved = 0; 1762 out_hdr->sadb_msg_reserved = 0;
1735 out_hdr->sadb_msg_seq = count; 1763 out_hdr->sadb_msg_seq = count;
1736 out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid; 1764 out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
1737 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk); 1765 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
1738 return 0; 1766 return 0;
1739} 1767}
1740 1768
1769static int pfkey_dump_sa(struct pfkey_sock *pfk)
1770{
1771 return xfrm_state_walk(&pfk->dump.u.state, dump_sa, (void *) pfk);
1772}
1773
1774static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
1775{
1776 xfrm_state_walk_done(&pfk->dump.u.state);
1777}
1778
1741static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1779static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
1742{ 1780{
1743 u8 proto; 1781 u8 proto;
1744 struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk }; 1782 struct pfkey_sock *pfk = pfkey_sk(sk);
1783
1784 if (pfk->dump.dump != NULL)
1785 return -EBUSY;
1745 1786
1746 proto = pfkey_satype2proto(hdr->sadb_msg_satype); 1787 proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1747 if (proto == 0) 1788 if (proto == 0)
1748 return -EINVAL; 1789 return -EINVAL;
1749 1790
1750 return xfrm_state_walk(proto, dump_sa, &data); 1791 pfk->dump.msg_version = hdr->sadb_msg_version;
1792 pfk->dump.msg_pid = hdr->sadb_msg_pid;
1793 pfk->dump.dump = pfkey_dump_sa;
1794 pfk->dump.done = pfkey_dump_sa_done;
1795 xfrm_state_walk_init(&pfk->dump.u.state, proto);
1796
1797 return pfkey_do_dump(pfk);
1751} 1798}
1752 1799
1753static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1800static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
@@ -1780,7 +1827,9 @@ static int check_reqid(struct xfrm_policy *xp, int dir, int count, void *ptr)
1780 1827
1781static u32 gen_reqid(void) 1828static u32 gen_reqid(void)
1782{ 1829{
1830 struct xfrm_policy_walk walk;
1783 u32 start; 1831 u32 start;
1832 int rc;
1784 static u32 reqid = IPSEC_MANUAL_REQID_MAX; 1833 static u32 reqid = IPSEC_MANUAL_REQID_MAX;
1785 1834
1786 start = reqid; 1835 start = reqid;
@@ -1788,8 +1837,10 @@ static u32 gen_reqid(void)
1788 ++reqid; 1837 ++reqid;
1789 if (reqid == 0) 1838 if (reqid == 0)
1790 reqid = IPSEC_MANUAL_REQID_MAX+1; 1839 reqid = IPSEC_MANUAL_REQID_MAX+1;
1791 if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid, 1840 xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN);
1792 (void*)&reqid) != -EEXIST) 1841 rc = xfrm_policy_walk(&walk, check_reqid, (void*)&reqid);
1842 xfrm_policy_walk_done(&walk);
1843 if (rc != -EEXIST)
1793 return reqid; 1844 return reqid;
1794 } while (reqid != start); 1845 } while (reqid != start);
1795 return 0; 1846 return 0;
@@ -2638,11 +2689,14 @@ out:
2638 2689
2639static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) 2690static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2640{ 2691{
2641 struct pfkey_dump_data *data = ptr; 2692 struct pfkey_sock *pfk = ptr;
2642 struct sk_buff *out_skb; 2693 struct sk_buff *out_skb;
2643 struct sadb_msg *out_hdr; 2694 struct sadb_msg *out_hdr;
2644 int err; 2695 int err;
2645 2696
2697 if (!pfkey_can_dump(&pfk->sk))
2698 return -ENOBUFS;
2699
2646 out_skb = pfkey_xfrm_policy2msg_prep(xp); 2700 out_skb = pfkey_xfrm_policy2msg_prep(xp);
2647 if (IS_ERR(out_skb)) 2701 if (IS_ERR(out_skb))
2648 return PTR_ERR(out_skb); 2702 return PTR_ERR(out_skb);
@@ -2652,21 +2706,40 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2652 return err; 2706 return err;
2653 2707
2654 out_hdr = (struct sadb_msg *) out_skb->data; 2708 out_hdr = (struct sadb_msg *) out_skb->data;
2655 out_hdr->sadb_msg_version = data->hdr->sadb_msg_version; 2709 out_hdr->sadb_msg_version = pfk->dump.msg_version;
2656 out_hdr->sadb_msg_type = SADB_X_SPDDUMP; 2710 out_hdr->sadb_msg_type = SADB_X_SPDDUMP;
2657 out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; 2711 out_hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
2658 out_hdr->sadb_msg_errno = 0; 2712 out_hdr->sadb_msg_errno = 0;
2659 out_hdr->sadb_msg_seq = count; 2713 out_hdr->sadb_msg_seq = count;
2660 out_hdr->sadb_msg_pid = data->hdr->sadb_msg_pid; 2714 out_hdr->sadb_msg_pid = pfk->dump.msg_pid;
2661 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, data->sk); 2715 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, &pfk->sk);
2662 return 0; 2716 return 0;
2663} 2717}
2664 2718
2719static int pfkey_dump_sp(struct pfkey_sock *pfk)
2720{
2721 return xfrm_policy_walk(&pfk->dump.u.policy, dump_sp, (void *) pfk);
2722}
2723
2724static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
2725{
2726 xfrm_policy_walk_done(&pfk->dump.u.policy);
2727}
2728
2665static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 2729static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
2666{ 2730{
2667 struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk }; 2731 struct pfkey_sock *pfk = pfkey_sk(sk);
2732
2733 if (pfk->dump.dump != NULL)
2734 return -EBUSY;
2735
2736 pfk->dump.msg_version = hdr->sadb_msg_version;
2737 pfk->dump.msg_pid = hdr->sadb_msg_pid;
2738 pfk->dump.dump = pfkey_dump_sp;
2739 pfk->dump.done = pfkey_dump_sp_done;
2740 xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);
2668 2741
2669 return xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_sp, &data); 2742 return pfkey_do_dump(pfk);
2670} 2743}
2671 2744
2672static int key_notify_policy_flush(struct km_event *c) 2745static int key_notify_policy_flush(struct km_event *c)
@@ -3671,6 +3744,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
3671 int flags) 3744 int flags)
3672{ 3745{
3673 struct sock *sk = sock->sk; 3746 struct sock *sk = sock->sk;
3747 struct pfkey_sock *pfk = pfkey_sk(sk);
3674 struct sk_buff *skb; 3748 struct sk_buff *skb;
3675 int copied, err; 3749 int copied, err;
3676 3750
@@ -3698,6 +3772,10 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
3698 3772
3699 err = (flags & MSG_TRUNC) ? skb->len : copied; 3773 err = (flags & MSG_TRUNC) ? skb->len : copied;
3700 3774
3775 if (pfk->dump.dump != NULL &&
3776 3 * atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
3777 pfkey_do_dump(pfk);
3778
3701out_free: 3779out_free:
3702 skb_free_datagram(sk, skb); 3780 skb_free_datagram(sk, skb);
3703out: 3781out: