Skip to content

Commit

Permalink
[XFRM] MIP6: Fix address keys for routing search.
Browse files Browse the repository at this point in the history
Each MIPv6 XFRM state (DSTOPT/RH2) holds either destination or source
address to be mangled in the IPv6 header (that is "CoA").
On Inter-MN communication after both nodes binds each other,
they use route optimized traffic two MIPv6 states applied, and
both source and destination address in the IPv6 header
are replaced by the states respectively.
The packet format is correct, however, next-hop routing search
are not.
This patch fixes it by remembering address pairs for later states.

Based on patch from Masahide NAKAMURA <nakam@linux-ipv6.org>.

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
  • Loading branch information
YOSHIFUJI Hideaki committed Mar 25, 2008
1 parent df8ea19 commit 9bb182a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 9 deletions.
17 changes: 17 additions & 0 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,23 @@ xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
return NULL;
}

static __inline__
void xfrm_flowi_addr_get(struct flowi *fl,
xfrm_address_t *saddr, xfrm_address_t *daddr,
unsigned short family)
{
switch(family) {
case AF_INET:
memcpy(&saddr->a4, &fl->fl4_src, sizeof(saddr->a4));
memcpy(&daddr->a4, &fl->fl4_dst, sizeof(daddr->a4));
break;
case AF_INET6:
ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->fl6_src);
ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->fl6_dst);
break;
}
}

static __inline__ int
__xfrm4_state_addr_check(struct xfrm_state *x,
xfrm_address_t *daddr, xfrm_address_t *saddr)
Expand Down
49 changes: 40 additions & 9 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,52 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
return 0;
}

static inline struct dst_entry *__xfrm_dst_lookup(int tos,
xfrm_address_t *saddr,
xfrm_address_t *daddr,
int family)
{
struct xfrm_policy_afinfo *afinfo;
struct dst_entry *dst;

afinfo = xfrm_policy_get_afinfo(family);
if (unlikely(afinfo == NULL))
return ERR_PTR(-EAFNOSUPPORT);

dst = afinfo->dst_lookup(tos, saddr, daddr);

xfrm_policy_put_afinfo(afinfo);

return dst;
}

static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos,
xfrm_address_t *prev_saddr,
xfrm_address_t *prev_daddr,
int family)
{
xfrm_address_t *saddr = &x->props.saddr;
xfrm_address_t *daddr = &x->id.daddr;
struct xfrm_policy_afinfo *afinfo;
struct dst_entry *dst;

if (x->type->flags & XFRM_TYPE_LOCAL_COADDR)
if (x->type->flags & XFRM_TYPE_LOCAL_COADDR) {
saddr = x->coaddr;
if (x->type->flags & XFRM_TYPE_REMOTE_COADDR)
daddr = prev_daddr;
}
if (x->type->flags & XFRM_TYPE_REMOTE_COADDR) {
saddr = prev_saddr;
daddr = x->coaddr;
}

afinfo = xfrm_policy_get_afinfo(family);
if (unlikely(afinfo == NULL))
return ERR_PTR(-EAFNOSUPPORT);
dst = __xfrm_dst_lookup(tos, saddr, daddr, family);

if (!IS_ERR(dst)) {
if (prev_saddr != saddr)
memcpy(prev_saddr, saddr, sizeof(*prev_saddr));
if (prev_daddr != daddr)
memcpy(prev_daddr, daddr, sizeof(*prev_daddr));
}

dst = afinfo->dst_lookup(tos, saddr, daddr);
xfrm_policy_put_afinfo(afinfo);
return dst;
}

Expand Down Expand Up @@ -1354,6 +1381,9 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
int trailer_len = 0;
int tos;
int family = policy->selector.family;
xfrm_address_t saddr, daddr;

xfrm_flowi_addr_get(fl, &saddr, &daddr, family);

tos = xfrm_get_tos(fl, family);
err = tos;
Expand Down Expand Up @@ -1384,7 +1414,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,

if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
family = xfrm[i]->props.family;
dst = xfrm_dst_lookup(xfrm[i], tos, family);
dst = xfrm_dst_lookup(xfrm[i], tos, &saddr, &daddr,
family);
err = PTR_ERR(dst);
if (IS_ERR(dst))
goto put_states;
Expand Down

0 comments on commit 9bb182a

Please sign in to comment.