diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/key/af_key.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index 4e1830999482..0e1dbfbb9b10 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -1767,11 +1767,11 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1767 | 1767 | ||
1768 | /* addresses present only in tunnel mode */ | 1768 | /* addresses present only in tunnel mode */ |
1769 | if (t->mode == XFRM_MODE_TUNNEL) { | 1769 | if (t->mode == XFRM_MODE_TUNNEL) { |
1770 | switch (xp->family) { | 1770 | struct sockaddr *sa; |
1771 | sa = (struct sockaddr *)(rq+1); | ||
1772 | switch(sa->sa_family) { | ||
1771 | case AF_INET: | 1773 | case AF_INET: |
1772 | sin = (void*)(rq+1); | 1774 | sin = (struct sockaddr_in*)sa; |
1773 | if (sin->sin_family != AF_INET) | ||
1774 | return -EINVAL; | ||
1775 | t->saddr.a4 = sin->sin_addr.s_addr; | 1775 | t->saddr.a4 = sin->sin_addr.s_addr; |
1776 | sin++; | 1776 | sin++; |
1777 | if (sin->sin_family != AF_INET) | 1777 | if (sin->sin_family != AF_INET) |
@@ -1780,9 +1780,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1780 | break; | 1780 | break; |
1781 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 1781 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1782 | case AF_INET6: | 1782 | case AF_INET6: |
1783 | sin6 = (void *)(rq+1); | 1783 | sin6 = (struct sockaddr_in6*)sa; |
1784 | if (sin6->sin6_family != AF_INET6) | ||
1785 | return -EINVAL; | ||
1786 | memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); | 1784 | memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); |
1787 | sin6++; | 1785 | sin6++; |
1788 | if (sin6->sin6_family != AF_INET6) | 1786 | if (sin6->sin6_family != AF_INET6) |
@@ -1793,7 +1791,10 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1793 | default: | 1791 | default: |
1794 | return -EINVAL; | 1792 | return -EINVAL; |
1795 | } | 1793 | } |
1796 | } | 1794 | t->encap_family = sa->sa_family; |
1795 | } else | ||
1796 | t->encap_family = xp->family; | ||
1797 | |||
1797 | /* No way to set this via kame pfkey */ | 1798 | /* No way to set this via kame pfkey */ |
1798 | t->aalgos = t->ealgos = t->calgos = ~0; | 1799 | t->aalgos = t->ealgos = t->calgos = ~0; |
1799 | xp->xfrm_nr++; | 1800 | xp->xfrm_nr++; |
@@ -1830,18 +1831,25 @@ static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp) | |||
1830 | 1831 | ||
1831 | static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) | 1832 | static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) |
1832 | { | 1833 | { |
1834 | struct xfrm_tmpl *t; | ||
1833 | int sockaddr_size = pfkey_sockaddr_size(xp->family); | 1835 | int sockaddr_size = pfkey_sockaddr_size(xp->family); |
1834 | int socklen = (xp->family == AF_INET ? | 1836 | int socklen = 0; |
1835 | sizeof(struct sockaddr_in) : | 1837 | int i; |
1836 | sizeof(struct sockaddr_in6)); | 1838 | |
1839 | for (i=0; i<xp->xfrm_nr; i++) { | ||
1840 | t = xp->xfrm_vec + i; | ||
1841 | socklen += (t->encap_family == AF_INET ? | ||
1842 | sizeof(struct sockaddr_in) : | ||
1843 | sizeof(struct sockaddr_in6)); | ||
1844 | } | ||
1837 | 1845 | ||
1838 | return sizeof(struct sadb_msg) + | 1846 | return sizeof(struct sadb_msg) + |
1839 | (sizeof(struct sadb_lifetime) * 3) + | 1847 | (sizeof(struct sadb_lifetime) * 3) + |
1840 | (sizeof(struct sadb_address) * 2) + | 1848 | (sizeof(struct sadb_address) * 2) + |
1841 | (sockaddr_size * 2) + | 1849 | (sockaddr_size * 2) + |
1842 | sizeof(struct sadb_x_policy) + | 1850 | sizeof(struct sadb_x_policy) + |
1843 | (xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) + | 1851 | (xp->xfrm_nr * sizeof(struct sadb_x_ipsecrequest)) + |
1844 | (socklen * 2))) + | 1852 | (socklen * 2) + |
1845 | pfkey_xfrm_policy2sec_ctx_size(xp); | 1853 | pfkey_xfrm_policy2sec_ctx_size(xp); |
1846 | } | 1854 | } |
1847 | 1855 | ||
@@ -1999,7 +2007,9 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
1999 | 2007 | ||
2000 | req_size = sizeof(struct sadb_x_ipsecrequest); | 2008 | req_size = sizeof(struct sadb_x_ipsecrequest); |
2001 | if (t->mode == XFRM_MODE_TUNNEL) | 2009 | if (t->mode == XFRM_MODE_TUNNEL) |
2002 | req_size += 2*socklen; | 2010 | req_size += ((t->encap_family == AF_INET ? |
2011 | sizeof(struct sockaddr_in) : | ||
2012 | sizeof(struct sockaddr_in6)) * 2); | ||
2003 | else | 2013 | else |
2004 | size -= 2*socklen; | 2014 | size -= 2*socklen; |
2005 | rq = (void*)skb_put(skb, req_size); | 2015 | rq = (void*)skb_put(skb, req_size); |
@@ -2015,7 +2025,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
2015 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; | 2025 | rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; |
2016 | rq->sadb_x_ipsecrequest_reqid = t->reqid; | 2026 | rq->sadb_x_ipsecrequest_reqid = t->reqid; |
2017 | if (t->mode == XFRM_MODE_TUNNEL) { | 2027 | if (t->mode == XFRM_MODE_TUNNEL) { |
2018 | switch (xp->family) { | 2028 | switch (t->encap_family) { |
2019 | case AF_INET: | 2029 | case AF_INET: |
2020 | sin = (void*)(rq+1); | 2030 | sin = (void*)(rq+1); |
2021 | sin->sin_family = AF_INET; | 2031 | sin->sin_family = AF_INET; |