aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/xfrm.h1
-rw-r--r--include/net/xfrm.h3
-rw-r--r--net/xfrm/xfrm_state.c6
-rw-r--r--net/xfrm/xfrm_user.c28
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
282static 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
279static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) 300static 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;
573out: 599out:
574 sp->this_idx++; 600 sp->this_idx++;