diff options
Diffstat (limited to 'net/key/af_key.c')
-rw-r--r-- | net/key/af_key.c | 107 |
1 files changed, 38 insertions, 69 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index 2b05cb6c15c6..771bd61d6303 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -592,25 +592,30 @@ static inline int pfkey_sockaddr_len(sa_family_t family) | |||
592 | return 0; | 592 | return 0; |
593 | } | 593 | } |
594 | 594 | ||
595 | static int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, | 595 | static |
596 | xfrm_address_t *xaddr) | 596 | int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr) |
597 | { | 597 | { |
598 | switch (((struct sockaddr*)(addr + 1))->sa_family) { | 598 | switch (sa->sa_family) { |
599 | case AF_INET: | 599 | case AF_INET: |
600 | xaddr->a4 = | 600 | xaddr->a4 = |
601 | ((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr; | 601 | ((struct sockaddr_in *)sa)->sin_addr.s_addr; |
602 | return AF_INET; | 602 | return AF_INET; |
603 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 603 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
604 | case AF_INET6: | 604 | case AF_INET6: |
605 | memcpy(xaddr->a6, | 605 | memcpy(xaddr->a6, |
606 | &((struct sockaddr_in6 *)(addr + 1))->sin6_addr, | 606 | &((struct sockaddr_in6 *)sa)->sin6_addr, |
607 | sizeof(struct in6_addr)); | 607 | sizeof(struct in6_addr)); |
608 | return AF_INET6; | 608 | return AF_INET6; |
609 | #endif | 609 | #endif |
610 | default: | ||
611 | return 0; | ||
612 | } | 610 | } |
613 | /* NOTREACHED */ | 611 | return 0; |
612 | } | ||
613 | |||
614 | static | ||
615 | int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr) | ||
616 | { | ||
617 | return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1), | ||
618 | xaddr); | ||
614 | } | 619 | } |
615 | 620 | ||
616 | static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs) | 621 | static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs) |
@@ -1828,10 +1833,6 @@ static int | |||
1828 | parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | 1833 | parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) |
1829 | { | 1834 | { |
1830 | struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; | 1835 | struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; |
1831 | struct sockaddr_in *sin; | ||
1832 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1833 | struct sockaddr_in6 *sin6; | ||
1834 | #endif | ||
1835 | int mode; | 1836 | int mode; |
1836 | 1837 | ||
1837 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) | 1838 | if (xp->xfrm_nr >= XFRM_MAX_DEPTH) |
@@ -1856,31 +1857,19 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) | |||
1856 | 1857 | ||
1857 | /* addresses present only in tunnel mode */ | 1858 | /* addresses present only in tunnel mode */ |
1858 | if (t->mode == XFRM_MODE_TUNNEL) { | 1859 | if (t->mode == XFRM_MODE_TUNNEL) { |
1859 | struct sockaddr *sa; | 1860 | u8 *sa = (u8 *) (rq + 1); |
1860 | sa = (struct sockaddr *)(rq+1); | 1861 | int family, socklen; |
1861 | switch(sa->sa_family) { | 1862 | |
1862 | case AF_INET: | 1863 | family = pfkey_sockaddr_extract((struct sockaddr *)sa, |
1863 | sin = (struct sockaddr_in*)sa; | 1864 | &t->saddr); |
1864 | t->saddr.a4 = sin->sin_addr.s_addr; | 1865 | if (!family) |
1865 | sin++; | ||
1866 | if (sin->sin_family != AF_INET) | ||
1867 | return -EINVAL; | ||
1868 | t->id.daddr.a4 = sin->sin_addr.s_addr; | ||
1869 | break; | ||
1870 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
1871 | case AF_INET6: | ||
1872 | sin6 = (struct sockaddr_in6*)sa; | ||
1873 | memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); | ||
1874 | sin6++; | ||
1875 | if (sin6->sin6_family != AF_INET6) | ||
1876 | return -EINVAL; | ||
1877 | memcpy(t->id.daddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr)); | ||
1878 | break; | ||
1879 | #endif | ||
1880 | default: | ||
1881 | return -EINVAL; | 1866 | return -EINVAL; |
1882 | } | 1867 | |
1883 | t->encap_family = sa->sa_family; | 1868 | socklen = pfkey_sockaddr_len(family); |
1869 | if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen), | ||
1870 | &t->id.daddr) != family) | ||
1871 | return -EINVAL; | ||
1872 | t->encap_family = family; | ||
1884 | } else | 1873 | } else |
1885 | t->encap_family = xp->family; | 1874 | t->encap_family = xp->family; |
1886 | 1875 | ||
@@ -2375,44 +2364,24 @@ static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, | |||
2375 | xfrm_address_t *saddr, xfrm_address_t *daddr, | 2364 | xfrm_address_t *saddr, xfrm_address_t *daddr, |
2376 | u16 *family) | 2365 | u16 *family) |
2377 | { | 2366 | { |
2378 | struct sockaddr *sa = (struct sockaddr *)(rq + 1); | 2367 | u8 *sa = (u8 *) (rq + 1); |
2368 | int af, socklen; | ||
2369 | |||
2379 | if (rq->sadb_x_ipsecrequest_len < | 2370 | if (rq->sadb_x_ipsecrequest_len < |
2380 | pfkey_sockaddr_pair_size(sa->sa_family)) | 2371 | pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family)) |
2381 | return -EINVAL; | 2372 | return -EINVAL; |
2382 | 2373 | ||
2383 | switch (sa->sa_family) { | 2374 | af = pfkey_sockaddr_extract((struct sockaddr *) sa, |
2384 | case AF_INET: | 2375 | saddr); |
2385 | { | 2376 | if (!af) |
2386 | struct sockaddr_in *sin; | 2377 | return -EINVAL; |
2387 | sin = (struct sockaddr_in *)sa; | 2378 | |
2388 | if ((sin+1)->sin_family != AF_INET) | 2379 | socklen = pfkey_sockaddr_len(af); |
2389 | return -EINVAL; | 2380 | if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen), |
2390 | memcpy(&saddr->a4, &sin->sin_addr, sizeof(saddr->a4)); | 2381 | daddr) != af) |
2391 | sin++; | ||
2392 | memcpy(&daddr->a4, &sin->sin_addr, sizeof(daddr->a4)); | ||
2393 | *family = AF_INET; | ||
2394 | break; | ||
2395 | } | ||
2396 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
2397 | case AF_INET6: | ||
2398 | { | ||
2399 | struct sockaddr_in6 *sin6; | ||
2400 | sin6 = (struct sockaddr_in6 *)sa; | ||
2401 | if ((sin6+1)->sin6_family != AF_INET6) | ||
2402 | return -EINVAL; | ||
2403 | memcpy(&saddr->a6, &sin6->sin6_addr, | ||
2404 | sizeof(saddr->a6)); | ||
2405 | sin6++; | ||
2406 | memcpy(&daddr->a6, &sin6->sin6_addr, | ||
2407 | sizeof(daddr->a6)); | ||
2408 | *family = AF_INET6; | ||
2409 | break; | ||
2410 | } | ||
2411 | #endif | ||
2412 | default: | ||
2413 | return -EINVAL; | 2382 | return -EINVAL; |
2414 | } | ||
2415 | 2383 | ||
2384 | *family = af; | ||
2416 | return 0; | 2385 | return 0; |
2417 | } | 2386 | } |
2418 | 2387 | ||