diff options
author | Arnaud Ebalard <arno@natisbad.org> | 2008-10-05 16:33:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-05 16:33:42 -0400 |
commit | 13c1d18931ebb5cf407cb348ef2cd6284d68902d (patch) | |
tree | 6d590f85e48b4cce8f67e42c65b88fce8fcc49c6 /net/xfrm | |
parent | 95430c0b140c31cb9e39f876afe1c0e9947d1aaf (diff) |
xfrm: MIGRATE enhancements (draft-ebalard-mext-pfkey-enhanced-migrate)
Provides implementation of the enhancements of XFRM/PF_KEY MIGRATE mechanism
specified in draft-ebalard-mext-pfkey-enhanced-migrate-00. Defines associated
PF_KEY SADB_X_EXT_KMADDRESS extension and XFRM/netlink XFRMA_KMADDRESS
attribute.
Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 5 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 5 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 57 |
3 files changed, 51 insertions, 16 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b7ec08025ffb..832b47c1de80 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -2679,7 +2679,8 @@ static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate) | |||
2679 | } | 2679 | } |
2680 | 2680 | ||
2681 | int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 2681 | int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
2682 | struct xfrm_migrate *m, int num_migrate) | 2682 | struct xfrm_migrate *m, int num_migrate, |
2683 | struct xfrm_kmaddress *k) | ||
2683 | { | 2684 | { |
2684 | int i, err, nx_cur = 0, nx_new = 0; | 2685 | int i, err, nx_cur = 0, nx_new = 0; |
2685 | struct xfrm_policy *pol = NULL; | 2686 | struct xfrm_policy *pol = NULL; |
@@ -2723,7 +2724,7 @@ int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
2723 | } | 2724 | } |
2724 | 2725 | ||
2725 | /* Stage 5 - announce */ | 2726 | /* Stage 5 - announce */ |
2726 | km_migrate(sel, dir, type, m, num_migrate); | 2727 | km_migrate(sel, dir, type, m, num_migrate, k); |
2727 | 2728 | ||
2728 | xfrm_pol_put(pol); | 2729 | xfrm_pol_put(pol); |
2729 | 2730 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 747fd8c291a7..508337f97249 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1814,7 +1814,8 @@ EXPORT_SYMBOL(km_policy_expired); | |||
1814 | 1814 | ||
1815 | #ifdef CONFIG_XFRM_MIGRATE | 1815 | #ifdef CONFIG_XFRM_MIGRATE |
1816 | int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1816 | int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1817 | struct xfrm_migrate *m, int num_migrate) | 1817 | struct xfrm_migrate *m, int num_migrate, |
1818 | struct xfrm_kmaddress *k) | ||
1818 | { | 1819 | { |
1819 | int err = -EINVAL; | 1820 | int err = -EINVAL; |
1820 | int ret; | 1821 | int ret; |
@@ -1823,7 +1824,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
1823 | read_lock(&xfrm_km_lock); | 1824 | read_lock(&xfrm_km_lock); |
1824 | list_for_each_entry(km, &xfrm_km_list, list) { | 1825 | list_for_each_entry(km, &xfrm_km_list, list) { |
1825 | if (km->migrate) { | 1826 | if (km->migrate) { |
1826 | ret = km->migrate(sel, dir, type, m, num_migrate); | 1827 | ret = km->migrate(sel, dir, type, m, num_migrate, k); |
1827 | if (!ret) | 1828 | if (!ret) |
1828 | err = ret; | 1829 | err = ret; |
1829 | } | 1830 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 76f75df21e15..4a8a1abb59ee 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1710,12 +1710,23 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1710 | 1710 | ||
1711 | #ifdef CONFIG_XFRM_MIGRATE | 1711 | #ifdef CONFIG_XFRM_MIGRATE |
1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, | 1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, |
1713 | struct xfrm_kmaddress *k, | ||
1713 | struct nlattr **attrs, int *num) | 1714 | struct nlattr **attrs, int *num) |
1714 | { | 1715 | { |
1715 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; | 1716 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; |
1716 | struct xfrm_user_migrate *um; | 1717 | struct xfrm_user_migrate *um; |
1717 | int i, num_migrate; | 1718 | int i, num_migrate; |
1718 | 1719 | ||
1720 | if (k != NULL) { | ||
1721 | struct xfrm_user_kmaddress *uk; | ||
1722 | |||
1723 | uk = nla_data(attrs[XFRMA_KMADDRESS]); | ||
1724 | memcpy(&k->local, &uk->local, sizeof(k->local)); | ||
1725 | memcpy(&k->remote, &uk->remote, sizeof(k->remote)); | ||
1726 | k->family = uk->family; | ||
1727 | k->reserved = uk->reserved; | ||
1728 | } | ||
1729 | |||
1719 | um = nla_data(rt); | 1730 | um = nla_data(rt); |
1720 | num_migrate = nla_len(rt) / sizeof(*um); | 1731 | num_migrate = nla_len(rt) / sizeof(*um); |
1721 | 1732 | ||
@@ -1745,6 +1756,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1745 | { | 1756 | { |
1746 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); | 1757 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); |
1747 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | 1758 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
1759 | struct xfrm_kmaddress km, *kmp; | ||
1748 | u8 type; | 1760 | u8 type; |
1749 | int err; | 1761 | int err; |
1750 | int n = 0; | 1762 | int n = 0; |
@@ -1752,19 +1764,20 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1752 | if (attrs[XFRMA_MIGRATE] == NULL) | 1764 | if (attrs[XFRMA_MIGRATE] == NULL) |
1753 | return -EINVAL; | 1765 | return -EINVAL; |
1754 | 1766 | ||
1767 | kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; | ||
1768 | |||
1755 | err = copy_from_user_policy_type(&type, attrs); | 1769 | err = copy_from_user_policy_type(&type, attrs); |
1756 | if (err) | 1770 | if (err) |
1757 | return err; | 1771 | return err; |
1758 | 1772 | ||
1759 | err = copy_from_user_migrate((struct xfrm_migrate *)m, | 1773 | err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); |
1760 | attrs, &n); | ||
1761 | if (err) | 1774 | if (err) |
1762 | return err; | 1775 | return err; |
1763 | 1776 | ||
1764 | if (!n) | 1777 | if (!n) |
1765 | return 0; | 1778 | return 0; |
1766 | 1779 | ||
1767 | xfrm_migrate(&pi->sel, pi->dir, type, m, n); | 1780 | xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); |
1768 | 1781 | ||
1769 | return 0; | 1782 | return 0; |
1770 | } | 1783 | } |
@@ -1795,16 +1808,30 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) | |||
1795 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); | 1808 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); |
1796 | } | 1809 | } |
1797 | 1810 | ||
1798 | static inline size_t xfrm_migrate_msgsize(int num_migrate) | 1811 | static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb) |
1812 | { | ||
1813 | struct xfrm_user_kmaddress uk; | ||
1814 | |||
1815 | memset(&uk, 0, sizeof(uk)); | ||
1816 | uk.family = k->family; | ||
1817 | uk.reserved = k->reserved; | ||
1818 | memcpy(&uk.local, &k->local, sizeof(uk.local)); | ||
1819 | memcpy(&uk.remote, &k->local, sizeof(uk.remote)); | ||
1820 | |||
1821 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); | ||
1822 | } | ||
1823 | |||
1824 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | ||
1799 | { | 1825 | { |
1800 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) | 1826 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) |
1801 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) | 1827 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) |
1802 | + userpolicy_type_attrsize(); | 1828 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) |
1829 | + userpolicy_type_attrsize(); | ||
1803 | } | 1830 | } |
1804 | 1831 | ||
1805 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | 1832 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, |
1806 | int num_migrate, struct xfrm_selector *sel, | 1833 | int num_migrate, struct xfrm_kmaddress *k, |
1807 | u8 dir, u8 type) | 1834 | struct xfrm_selector *sel, u8 dir, u8 type) |
1808 | { | 1835 | { |
1809 | struct xfrm_migrate *mp; | 1836 | struct xfrm_migrate *mp; |
1810 | struct xfrm_userpolicy_id *pol_id; | 1837 | struct xfrm_userpolicy_id *pol_id; |
@@ -1821,6 +1848,9 @@ static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | |||
1821 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); | 1848 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); |
1822 | pol_id->dir = dir; | 1849 | pol_id->dir = dir; |
1823 | 1850 | ||
1851 | if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) | ||
1852 | goto nlmsg_failure; | ||
1853 | |||
1824 | if (copy_to_user_policy_type(type, skb) < 0) | 1854 | if (copy_to_user_policy_type(type, skb) < 0) |
1825 | goto nlmsg_failure; | 1855 | goto nlmsg_failure; |
1826 | 1856 | ||
@@ -1836,23 +1866,25 @@ nlmsg_failure: | |||
1836 | } | 1866 | } |
1837 | 1867 | ||
1838 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1868 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1839 | struct xfrm_migrate *m, int num_migrate) | 1869 | struct xfrm_migrate *m, int num_migrate, |
1870 | struct xfrm_kmaddress *k) | ||
1840 | { | 1871 | { |
1841 | struct sk_buff *skb; | 1872 | struct sk_buff *skb; |
1842 | 1873 | ||
1843 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate), GFP_ATOMIC); | 1874 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); |
1844 | if (skb == NULL) | 1875 | if (skb == NULL) |
1845 | return -ENOMEM; | 1876 | return -ENOMEM; |
1846 | 1877 | ||
1847 | /* build migrate */ | 1878 | /* build migrate */ |
1848 | if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0) | 1879 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) |
1849 | BUG(); | 1880 | BUG(); |
1850 | 1881 | ||
1851 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); | 1882 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
1852 | } | 1883 | } |
1853 | #else | 1884 | #else |
1854 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1885 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
1855 | struct xfrm_migrate *m, int num_migrate) | 1886 | struct xfrm_migrate *m, int num_migrate, |
1887 | struct xfrm_kmaddress *k) | ||
1856 | { | 1888 | { |
1857 | return -ENOPROTOOPT; | 1889 | return -ENOPROTOOPT; |
1858 | } | 1890 | } |
@@ -1901,6 +1933,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
1901 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, | 1933 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, |
1902 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, | 1934 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, |
1903 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, | 1935 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, |
1936 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, | ||
1904 | }; | 1937 | }; |
1905 | 1938 | ||
1906 | static struct xfrm_link { | 1939 | static struct xfrm_link { |