diff options
-rw-r--r-- | include/linux/xfrm.h | 1 | ||||
-rw-r--r-- | include/net/xfrm.h | 3 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 6 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 28 |
4 files changed, 37 insertions, 1 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index a7c9e4cfb15b..b53f799189af 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
@@ -235,6 +235,7 @@ enum xfrm_attr_type_t { | |||
235 | XFRMA_REPLAY_THRESH, | 235 | XFRMA_REPLAY_THRESH, |
236 | XFRMA_ETIMER_THRESH, | 236 | XFRMA_ETIMER_THRESH, |
237 | XFRMA_SRCADDR, /* xfrm_address_t */ | 237 | XFRMA_SRCADDR, /* xfrm_address_t */ |
238 | XFRMA_COADDR, /* xfrm_address_t */ | ||
238 | __XFRMA_MAX | 239 | __XFRMA_MAX |
239 | 240 | ||
240 | #define XFRMA_MAX (__XFRMA_MAX - 1) | 241 | #define XFRMA_MAX (__XFRMA_MAX - 1) |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index aa93cc1f6299..872a2a4022b2 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -134,6 +134,9 @@ struct xfrm_state | |||
134 | /* Data for encapsulator */ | 134 | /* Data for encapsulator */ |
135 | struct xfrm_encap_tmpl *encap; | 135 | struct xfrm_encap_tmpl *encap; |
136 | 136 | ||
137 | /* Data for care-of address */ | ||
138 | xfrm_address_t *coaddr; | ||
139 | |||
137 | /* IPComp needs an IPIP tunnel for handling uncompressed packets */ | 140 | /* IPComp needs an IPIP tunnel for handling uncompressed packets */ |
138 | struct xfrm_state *tunnel; | 141 | struct xfrm_state *tunnel; |
139 | 142 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f05371556cce..3da89c01ea71 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -78,6 +78,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
78 | kfree(x->ealg); | 78 | kfree(x->ealg); |
79 | kfree(x->calg); | 79 | kfree(x->calg); |
80 | kfree(x->encap); | 80 | kfree(x->encap); |
81 | kfree(x->coaddr); | ||
81 | if (x->mode) | 82 | if (x->mode) |
82 | xfrm_put_mode(x->mode); | 83 | xfrm_put_mode(x->mode); |
83 | if (x->type) { | 84 | if (x->type) { |
@@ -603,6 +604,11 @@ out: | |||
603 | if (likely(x1->km.state == XFRM_STATE_VALID)) { | 604 | if (likely(x1->km.state == XFRM_STATE_VALID)) { |
604 | if (x->encap && x1->encap) | 605 | if (x->encap && x1->encap) |
605 | memcpy(x1->encap, x->encap, sizeof(*x1->encap)); | 606 | memcpy(x1->encap, x->encap, sizeof(*x1->encap)); |
607 | if (x->coaddr && x1->coaddr) { | ||
608 | memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr)); | ||
609 | } | ||
610 | if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel))) | ||
611 | memcpy(&x1->sel, &x->sel, sizeof(x1->sel)); | ||
606 | memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); | 612 | memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); |
607 | x1->km.dying = 0; | 613 | x1->km.dying = 0; |
608 | 614 | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b5f8ab71aa54..939808de9e20 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -187,11 +187,14 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, | |||
187 | goto out; | 187 | goto out; |
188 | if ((err = verify_sec_ctx_len(xfrma))) | 188 | if ((err = verify_sec_ctx_len(xfrma))) |
189 | goto out; | 189 | goto out; |
190 | if ((err = verify_one_addr(xfrma, XFRMA_COADDR, NULL))) | ||
191 | goto out; | ||
190 | 192 | ||
191 | err = -EINVAL; | 193 | err = -EINVAL; |
192 | switch (p->mode) { | 194 | switch (p->mode) { |
193 | case XFRM_MODE_TRANSPORT: | 195 | case XFRM_MODE_TRANSPORT: |
194 | case XFRM_MODE_TUNNEL: | 196 | case XFRM_MODE_TUNNEL: |
197 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
195 | break; | 198 | break; |
196 | 199 | ||
197 | default: | 200 | default: |
@@ -276,6 +279,24 @@ static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg) | |||
276 | return security_xfrm_state_alloc(x, uctx); | 279 | return security_xfrm_state_alloc(x, uctx); |
277 | } | 280 | } |
278 | 281 | ||
282 | static int attach_one_addr(xfrm_address_t **addrpp, struct rtattr *u_arg) | ||
283 | { | ||
284 | struct rtattr *rta = u_arg; | ||
285 | xfrm_address_t *p, *uaddrp; | ||
286 | |||
287 | if (!rta) | ||
288 | return 0; | ||
289 | |||
290 | uaddrp = RTA_DATA(rta); | ||
291 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
292 | if (!p) | ||
293 | return -ENOMEM; | ||
294 | |||
295 | memcpy(p, uaddrp, sizeof(*p)); | ||
296 | *addrpp = p; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
279 | static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) | 300 | static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) |
280 | { | 301 | { |
281 | memcpy(&x->id, &p->id, sizeof(x->id)); | 302 | memcpy(&x->id, &p->id, sizeof(x->id)); |
@@ -365,7 +386,8 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | |||
365 | goto error; | 386 | goto error; |
366 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) | 387 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) |
367 | goto error; | 388 | goto error; |
368 | 389 | if ((err = attach_one_addr(&x->coaddr, xfrma[XFRMA_COADDR-1]))) | |
390 | goto error; | ||
369 | err = xfrm_init_state(x); | 391 | err = xfrm_init_state(x); |
370 | if (err) | 392 | if (err) |
371 | goto error; | 393 | goto error; |
@@ -569,6 +591,10 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | |||
569 | uctx->ctx_len = x->security->ctx_len; | 591 | uctx->ctx_len = x->security->ctx_len; |
570 | memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len); | 592 | memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len); |
571 | } | 593 | } |
594 | |||
595 | if (x->coaddr) | ||
596 | RTA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); | ||
597 | |||
572 | nlh->nlmsg_len = skb->tail - b; | 598 | nlh->nlmsg_len = skb->tail - b; |
573 | out: | 599 | out: |
574 | sp->this_idx++; | 600 | sp->this_idx++; |