Care-of address is carried by state as a transformation option like IPsec encryption/authentication algorithm. Based on MIPL2 kernel patch. --- include/linux/xfrm.h | 1 + include/net/xfrm.h | 5 +++++ net/xfrm/xfrm_state.c | 10 +++++++++ net/xfrm/xfrm_user.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 68 insertions(+), 1 deletions(-)
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 47e39f6..597a7c7 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -235,6 +235,7 @@ enum xfrm_attr_type_t { XFRMA_REPLAY_VAL, XFRMA_REPLAY_THRESH, XFRMA_ETIMER_THRESH, + XFRMA_ADDR, /* xfrm_address_t */ __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index f551bc6..de62a8f 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -135,6 +135,11 @@ #endif /* Data for encapsulator */ struct xfrm_encap_tmpl *encap; +#ifdef CONFIG_XFRM_ADVANCED + /* Data for care-of address */ + xfrm_address_t *coaddr; +#endif + /* IPComp needs an IPIP tunnel for handling uncompressed packets */ struct xfrm_state *tunnel; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 60def7a..1bdeecf 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -80,6 +80,9 @@ static void xfrm_state_gc_destroy(struct kfree(x->ealg); kfree(x->calg); kfree(x->encap); +#ifdef CONFIG_XFRM_ADVANCED + kfree(x->coaddr); +#endif if (x->type) { x->type->destructor(x); xfrm_put_type(x->type); @@ -619,6 +622,13 @@ out: if (likely(x1->km.state == XFRM_STATE_VALID)) { if (x->encap && x1->encap) memcpy(x1->encap, x->encap, sizeof(*x1->encap)); +#ifdef CONFIG_XFRM_ADVANCED + if (x->coaddr && x1->coaddr) { + memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr)); + } + if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel))) + memcpy(&x1->sel, &x->sel, sizeof(x1->sel)); +#endif memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); x1->km.dying = 0; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 85051a2..13fe172 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -110,6 +110,21 @@ static inline int verify_sec_ctx_len(str return 0; } +#ifdef CONFIG_XFRM_ADVANCED +static int verify_one_addr(struct rtattr **xfrma) +{ + struct rtattr *rt = xfrma[XFRMA_ADDR - 1]; + xfrm_address_t *addr; + + if (!rt) + return 0; + + if ((rt->rta_len - sizeof(*rt)) < sizeof(*addr)) + return -EINVAL; + + return 0; +} +#endif static int verify_newsa_info(struct xfrm_usersa_info *p, struct rtattr **xfrma) @@ -170,11 +185,18 @@ #endif goto out; if ((err = verify_sec_ctx_len(xfrma))) goto out; +#ifdef CONFIG_XFRM_ADVANCED + if ((err = verify_one_addr(xfrma))) + goto out; +#endif err = -EINVAL; switch (p->mode) { case XFRM_MODE_TRANSPORT: case XFRM_MODE_TUNNEL: +#ifdef CONFIG_XFRM_ADVANCED + case XFRM_MODE_ROUTEOPTIMIZATION: +#endif break; default: @@ -258,6 +280,26 @@ static int attach_sec_ctx(struct xfrm_st return security_xfrm_state_alloc(x, uctx); } +#ifdef CONFIG_XFRM_ADVANCED +static int attach_one_addr(xfrm_address_t **addrpp, struct rtattr *u_arg) +{ + struct rtattr *rta = u_arg; + xfrm_address_t *p, *uaddrp; + + if (!rta) + return 0; + + uaddrp = RTA_DATA(rta); + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + memcpy(p, uaddrp, sizeof(*p)); + *addrpp = p; + return 0; +} +#endif + static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { memcpy(&x->id, &p->id, sizeof(x->id)); @@ -347,7 +389,10 @@ static struct xfrm_state *xfrm_state_con goto error; if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) goto error; - +#ifdef CONFIG_XFRM_ADVANCED + if ((err = attach_one_addr(&x->coaddr, xfrma[XFRMA_ADDR-1]))) + goto error; +#endif err = xfrm_init_state(x); if (err) goto error; @@ -526,6 +571,12 @@ static int dump_one_state(struct xfrm_st uctx->ctx_len = x->security->ctx_len; memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len); } + +#ifdef CONFIG_XFRM_ADVANCED + if (x->coaddr) + RTA_PUT(skb, XFRMA_ADDR, sizeof(*x->coaddr), x->coaddr); +#endif + nlh->nlmsg_len = skb->tail - b; out: sp->this_idx++; -- 1.4.1 - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html