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/xfrm_user.c | |
| 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/xfrm_user.c')
| -rw-r--r-- | net/xfrm/xfrm_user.c | 57 |
1 files changed, 45 insertions, 12 deletions
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 { |
