aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorArnaud Ebalard <arno@natisbad.org>2008-10-05 16:33:42 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-05 16:33:42 -0400
commit13c1d18931ebb5cf407cb348ef2cd6284d68902d (patch)
tree6d590f85e48b4cce8f67e42c65b88fce8fcc49c6 /net/xfrm
parent95430c0b140c31cb9e39f876afe1c0e9947d1aaf (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.c5
-rw-r--r--net/xfrm/xfrm_state.c5
-rw-r--r--net/xfrm/xfrm_user.c57
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
2681int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 2681int 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
1816int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1816int 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
1712static int copy_from_user_migrate(struct xfrm_migrate *ma, 1712static 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
1798static inline size_t xfrm_migrate_msgsize(int num_migrate) 1811static 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
1824static 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
1805static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, 1832static 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
1838static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1868static 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
1854static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, 1885static 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
1906static struct xfrm_link { 1939static struct xfrm_link {