aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_user.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 82f36d396fca..079a5d315759 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1632,6 +1632,176 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
1632 return 0; 1632 return 0;
1633} 1633}
1634 1634
1635#ifdef CONFIG_XFRM_MIGRATE
1636static int verify_user_migrate(struct rtattr **xfrma)
1637{
1638 struct rtattr *rt = xfrma[XFRMA_MIGRATE-1];
1639 struct xfrm_user_migrate *um;
1640
1641 if (!rt)
1642 return -EINVAL;
1643
1644 if ((rt->rta_len - sizeof(*rt)) < sizeof(*um))
1645 return -EINVAL;
1646
1647 return 0;
1648}
1649
1650static int copy_from_user_migrate(struct xfrm_migrate *ma,
1651 struct rtattr **xfrma, int *num)
1652{
1653 struct rtattr *rt = xfrma[XFRMA_MIGRATE-1];
1654 struct xfrm_user_migrate *um;
1655 int i, num_migrate;
1656
1657 um = RTA_DATA(rt);
1658 num_migrate = (rt->rta_len - sizeof(*rt)) / sizeof(*um);
1659
1660 if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH)
1661 return -EINVAL;
1662
1663 for (i = 0; i < num_migrate; i++, um++, ma++) {
1664 memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr));
1665 memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr));
1666 memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr));
1667 memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr));
1668
1669 ma->proto = um->proto;
1670 ma->mode = um->mode;
1671 ma->reqid = um->reqid;
1672
1673 ma->old_family = um->old_family;
1674 ma->new_family = um->new_family;
1675 }
1676
1677 *num = i;
1678 return 0;
1679}
1680
1681static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
1682 struct rtattr **xfrma)
1683{
1684 struct xfrm_userpolicy_id *pi = NLMSG_DATA(nlh);
1685 struct xfrm_migrate m[XFRM_MAX_DEPTH];
1686 u8 type;
1687 int err;
1688 int n = 0;
1689
1690 err = verify_user_migrate((struct rtattr **)xfrma);
1691 if (err)
1692 return err;
1693
1694 err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
1695 if (err)
1696 return err;
1697
1698 err = copy_from_user_migrate((struct xfrm_migrate *)m,
1699 (struct rtattr **)xfrma, &n);
1700 if (err)
1701 return err;
1702
1703 if (!n)
1704 return 0;
1705
1706 xfrm_migrate(&pi->sel, pi->dir, type, m, n);
1707
1708 return 0;
1709}
1710#else
1711static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
1712 struct rtattr **xfrma)
1713{
1714 return -ENOPROTOOPT;
1715}
1716#endif
1717
1718#ifdef CONFIG_XFRM_MIGRATE
1719static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb)
1720{
1721 struct xfrm_user_migrate um;
1722
1723 memset(&um, 0, sizeof(um));
1724 um.proto = m->proto;
1725 um.mode = m->mode;
1726 um.reqid = m->reqid;
1727 um.old_family = m->old_family;
1728 memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr));
1729 memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr));
1730 um.new_family = m->new_family;
1731 memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr));
1732 memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr));
1733
1734 RTA_PUT(skb, XFRMA_MIGRATE, sizeof(um), &um);
1735 return 0;
1736
1737rtattr_failure:
1738 return -1;
1739}
1740
1741static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m,
1742 int num_migrate, struct xfrm_selector *sel,
1743 u8 dir, u8 type)
1744{
1745 struct xfrm_migrate *mp;
1746 struct xfrm_userpolicy_id *pol_id;
1747 struct nlmsghdr *nlh;
1748 unsigned char *b = skb->tail;
1749 int i;
1750
1751 nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id));
1752 pol_id = NLMSG_DATA(nlh);
1753 nlh->nlmsg_flags = 0;
1754
1755 /* copy data from selector, dir, and type to the pol_id */
1756 memset(pol_id, 0, sizeof(*pol_id));
1757 memcpy(&pol_id->sel, sel, sizeof(pol_id->sel));
1758 pol_id->dir = dir;
1759
1760 if (copy_to_user_policy_type(type, skb) < 0)
1761 goto nlmsg_failure;
1762
1763 for (i = 0, mp = m ; i < num_migrate; i++, mp++) {
1764 if (copy_to_user_migrate(mp, skb) < 0)
1765 goto nlmsg_failure;
1766 }
1767
1768 nlh->nlmsg_len = skb->tail - b;
1769 return skb->len;
1770nlmsg_failure:
1771 skb_trim(skb, b - skb->data);
1772 return -1;
1773}
1774
1775static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1776 struct xfrm_migrate *m, int num_migrate)
1777{
1778 struct sk_buff *skb;
1779 size_t len;
1780
1781 len = RTA_SPACE(sizeof(struct xfrm_user_migrate) * num_migrate);
1782 len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_id));
1783#ifdef CONFIG_XFRM_SUB_POLICY
1784 len += RTA_SPACE(sizeof(struct xfrm_userpolicy_type));
1785#endif
1786 skb = alloc_skb(len, GFP_ATOMIC);
1787 if (skb == NULL)
1788 return -ENOMEM;
1789
1790 /* build migrate */
1791 if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0)
1792 BUG();
1793
1794 NETLINK_CB(skb).dst_group = XFRMNLGRP_MIGRATE;
1795 return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE,
1796 GFP_ATOMIC);
1797}
1798#else
1799static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
1800 struct xfrm_migrate *m, int num_migrate)
1801{
1802 return -ENOPROTOOPT;
1803}
1804#endif
1635 1805
1636#define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) 1806#define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type))
1637 1807
@@ -1653,6 +1823,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
1653 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), 1823 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
1654 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), 1824 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id),
1655 [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), 1825 [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
1826 [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
1656}; 1827};
1657 1828
1658#undef XMSGSIZE 1829#undef XMSGSIZE
@@ -1679,6 +1850,7 @@ static struct xfrm_link {
1679 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, 1850 [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy },
1680 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, 1851 [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae },
1681 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, 1852 [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae },
1853 [XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate },
1682}; 1854};
1683 1855
1684static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) 1856static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp)
@@ -2285,6 +2457,7 @@ static struct xfrm_mgr netlink_mgr = {
2285 .compile_policy = xfrm_compile_policy, 2457 .compile_policy = xfrm_compile_policy,
2286 .notify_policy = xfrm_send_policy_notify, 2458 .notify_policy = xfrm_send_policy_notify,
2287 .report = xfrm_send_report, 2459 .report = xfrm_send_report,
2460 .migrate = xfrm_send_migrate,
2288}; 2461};
2289 2462
2290static int __init xfrm_user_init(void) 2463static int __init xfrm_user_init(void)