Skip to content

Commit

Permalink
[XFRM]: Trace which secpath state is reject factor.
Browse files Browse the repository at this point in the history
For Mobile IPv6 usage, it is required to trace which secpath state is
reject factor in order to notify it to user space (to know the address
which cannot be used route optimized communication).

Based on MIPL2 kernel patch.

This patch was also written by: Henrik Petander <petander@tcs.hut.fi>

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Masahide NAKAMURA authored and David S. Miller committed Sep 22, 2006
1 parent 2ce4272 commit df0ba92
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
1 change: 1 addition & 0 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ struct xfrm_type
void (*destructor)(struct xfrm_state *);
int (*input)(struct xfrm_state *, struct sk_buff *skb);
int (*output)(struct xfrm_state *, struct sk_buff *pskb);
int (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *);
int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
xfrm_address_t *(*local_addr)(struct xfrm_state *, xfrm_address_t *);
xfrm_address_t *(*remote_addr)(struct xfrm_state *, xfrm_address_t *);
Expand Down
55 changes: 48 additions & 7 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,23 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
}
EXPORT_SYMBOL(xfrm_lookup);

static inline int
xfrm_secpath_reject(int idx, struct sk_buff *skb, struct flowi *fl)
{
struct xfrm_state *x;
int err;

if (!skb->sp || idx < 0 || idx >= skb->sp->len)
return 0;
x = skb->sp->xvec[idx];
if (!x->type->reject)
return 0;
xfrm_state_hold(x);
err = x->type->reject(x, skb, fl);
xfrm_state_put(x);
return err;
}

/* When skb is transformed back to its "native" form, we have to
* check policy restrictions. At the moment we make this in maximally
* stupid way. Shame on me. :-) Of course, connected sockets must
Expand All @@ -1010,6 +1027,13 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
xfrm_state_addr_cmp(tmpl, x, family));
}

/*
* 0 or more than 0 is returned when validation is succeeded (either bypass
* because of optional transport mode, or next index of the mathced secpath
* state with the template.
* -1 is returned when no matching template is found.
* Otherwise "-2 - errored_index" is returned.
*/
static inline int
xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
unsigned short family)
Expand All @@ -1024,8 +1048,11 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
for (; idx < sp->len; idx++) {
if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
return ++idx;
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT)
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
if (start == -1)
start = -2-idx;
break;
}
}
return start;
}
Expand All @@ -1046,11 +1073,14 @@ xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family
}
EXPORT_SYMBOL(xfrm_decode_session);

static inline int secpath_has_nontransport(struct sec_path *sp, int k)
static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp)
{
for (; k < sp->len; k++) {
if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT)
if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) {
if (idxp)
*idxp = k;
return 1;
}
}

return 0;
Expand All @@ -1062,6 +1092,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
struct xfrm_policy *pol;
struct flowi fl;
u8 fl_dir = policy_to_flow_dir(dir);
int xerr_idx = -1;
int *xerr_idxp = &xerr_idx;

if (xfrm_decode_session(skb, &fl, family) < 0)
return 0;
Expand All @@ -1086,8 +1118,13 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
pol = flow_cache_lookup(&fl, family, fl_dir,
xfrm_policy_lookup);

if (!pol)
return !skb->sp || !secpath_has_nontransport(skb->sp, 0);
if (!pol) {
if (skb->sp && secpath_has_nontransport(skb->sp, 0, xerr_idxp)) {
xfrm_secpath_reject(xerr_idx, skb, &fl);
return 0;
}
return 1;
}

pol->curlft.use_time = (unsigned long)xtime.tv_sec;

Expand All @@ -1107,18 +1144,22 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
*/
for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) {
k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family);
if (k < 0)
if (k < 0) {
if (k < -1 && xerr_idxp)
*xerr_idxp = -(2+k);
goto reject;
}
}

if (secpath_has_nontransport(sp, k))
if (secpath_has_nontransport(sp, k, xerr_idxp))
goto reject;

xfrm_pol_put(pol);
return 1;
}

reject:
xfrm_secpath_reject(xerr_idx, skb, &fl);
xfrm_pol_put(pol);
return 0;
}
Expand Down

0 comments on commit df0ba92

Please sign in to comment.