key: Share common code path to extract address from sockaddr{}.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
This commit is contained in:
YOSHIFUJI Hideaki 2008-04-28 02:46:24 +09:00
parent e5b56652c1
commit 5f95ac9111

View file

@ -592,25 +592,30 @@ static inline int pfkey_sockaddr_len(sa_family_t family)
return 0; return 0;
} }
static int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, static
xfrm_address_t *xaddr) int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr)
{ {
switch (((struct sockaddr*)(addr + 1))->sa_family) { switch (sa->sa_family) {
case AF_INET: case AF_INET:
xaddr->a4 = xaddr->a4 =
((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr; ((struct sockaddr_in *)sa)->sin_addr.s_addr;
return AF_INET; return AF_INET;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6: case AF_INET6:
memcpy(xaddr->a6, memcpy(xaddr->a6,
&((struct sockaddr_in6 *)(addr + 1))->sin6_addr, &((struct sockaddr_in6 *)sa)->sin6_addr,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
return AF_INET6; return AF_INET6;
#endif #endif
default:
return 0;
} }
/* NOTREACHED */ return 0;
}
static
int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr)
{
return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1),
xaddr);
} }
static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs) static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **ext_hdrs)
@ -1828,10 +1833,6 @@ static int
parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
{ {
struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
struct sockaddr_in *sin;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct sockaddr_in6 *sin6;
#endif
int mode; int mode;
if (xp->xfrm_nr >= XFRM_MAX_DEPTH) if (xp->xfrm_nr >= XFRM_MAX_DEPTH)
@ -1856,31 +1857,19 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
/* addresses present only in tunnel mode */ /* addresses present only in tunnel mode */
if (t->mode == XFRM_MODE_TUNNEL) { if (t->mode == XFRM_MODE_TUNNEL) {
struct sockaddr *sa; u8 *sa = (u8 *) (rq + 1);
sa = (struct sockaddr *)(rq+1); int family, socklen;
switch(sa->sa_family) {
case AF_INET: family = pfkey_sockaddr_extract((struct sockaddr *)sa,
sin = (struct sockaddr_in*)sa; &t->saddr);
t->saddr.a4 = sin->sin_addr.s_addr; if (!family)
sin++;
if (sin->sin_family != AF_INET)
return -EINVAL;
t->id.daddr.a4 = sin->sin_addr.s_addr;
break;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
sin6 = (struct sockaddr_in6*)sa;
memcpy(t->saddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));
sin6++;
if (sin6->sin6_family != AF_INET6)
return -EINVAL;
memcpy(t->id.daddr.a6, &sin6->sin6_addr, sizeof(struct in6_addr));
break;
#endif
default:
return -EINVAL; return -EINVAL;
}
t->encap_family = sa->sa_family; socklen = pfkey_sockaddr_len(family);
if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
&t->id.daddr) != family)
return -EINVAL;
t->encap_family = family;
} else } else
t->encap_family = xp->family; t->encap_family = xp->family;
@ -2375,44 +2364,24 @@ static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq,
xfrm_address_t *saddr, xfrm_address_t *daddr, xfrm_address_t *saddr, xfrm_address_t *daddr,
u16 *family) u16 *family)
{ {
struct sockaddr *sa = (struct sockaddr *)(rq + 1); u8 *sa = (u8 *) (rq + 1);
int af, socklen;
if (rq->sadb_x_ipsecrequest_len < if (rq->sadb_x_ipsecrequest_len <
pfkey_sockaddr_pair_size(sa->sa_family)) pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family))
return -EINVAL; return -EINVAL;
switch (sa->sa_family) { af = pfkey_sockaddr_extract((struct sockaddr *) sa,
case AF_INET: saddr);
{ if (!af)
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)sa;
if ((sin+1)->sin_family != AF_INET)
return -EINVAL;
memcpy(&saddr->a4, &sin->sin_addr, sizeof(saddr->a4));
sin++;
memcpy(&daddr->a4, &sin->sin_addr, sizeof(daddr->a4));
*family = AF_INET;
break;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case AF_INET6:
{
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)sa;
if ((sin6+1)->sin6_family != AF_INET6)
return -EINVAL;
memcpy(&saddr->a6, &sin6->sin6_addr,
sizeof(saddr->a6));
sin6++;
memcpy(&daddr->a6, &sin6->sin6_addr,
sizeof(daddr->a6));
*family = AF_INET6;
break;
}
#endif
default:
return -EINVAL; return -EINVAL;
}
socklen = pfkey_sockaddr_len(af);
if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen),
daddr) != af)
return -EINVAL;
*family = af;
return 0; return 0;
} }