aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorSteffen Klassert <steffen.klassert@secunet.com>2011-03-07 19:10:27 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-13 23:22:31 -0400
commitd8647b79c3b7e223ac051439d165bc8e7bbb832f (patch)
treec3d0e377c77f4c0c138c339c3ac0c66dbb1d232b /net/xfrm
parent2cd084678fc1eb75aec4f7ae3d339d232c00ec61 (diff)
xfrm: Add user interface for esn and big anti-replay windows
This patch adds a netlink based user interface to configure esn and big anti-replay windows. The new netlink attribute XFRMA_REPLAY_ESN_VAL is used to configure the new implementation. If the XFRM_STATE_ESN flag is set, we use esn and support for big anti-replay windows for the configured state. If this flag is not set we use the new implementation with 32 bit sequence numbers. A big anti-replay window can be configured in this case anyway. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_state.c2
-rw-r--r--net/xfrm/xfrm_user.c99
2 files changed, 87 insertions, 14 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 23779d19fe02..d575f0534868 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -356,6 +356,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
356 kfree(x->calg); 356 kfree(x->calg);
357 kfree(x->encap); 357 kfree(x->encap);
358 kfree(x->coaddr); 358 kfree(x->coaddr);
359 kfree(x->replay_esn);
360 kfree(x->preplay_esn);
359 if (x->inner_mode) 361 if (x->inner_mode)
360 xfrm_put_mode(x->inner_mode); 362 xfrm_put_mode(x->inner_mode);
361 if (x->inner_mode_iaf) 363 if (x->inner_mode_iaf)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index f7b3c857c989..706385ae3e4b 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -119,6 +119,19 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
119 return 0; 119 return 0;
120} 120}
121 121
122static inline int verify_replay(struct xfrm_usersa_info *p,
123 struct nlattr **attrs)
124{
125 struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
126
127 if (!rt)
128 return 0;
129
130 if (p->replay_window != 0)
131 return -EINVAL;
132
133 return 0;
134}
122 135
123static int verify_newsa_info(struct xfrm_usersa_info *p, 136static int verify_newsa_info(struct xfrm_usersa_info *p,
124 struct nlattr **attrs) 137 struct nlattr **attrs)
@@ -214,6 +227,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
214 goto out; 227 goto out;
215 if ((err = verify_sec_ctx_len(attrs))) 228 if ((err = verify_sec_ctx_len(attrs)))
216 goto out; 229 goto out;
230 if ((err = verify_replay(p, attrs)))
231 goto out;
217 232
218 err = -EINVAL; 233 err = -EINVAL;
219 switch (p->mode) { 234 switch (p->mode) {
@@ -345,6 +360,33 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
345 return 0; 360 return 0;
346} 361}
347 362
363static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn,
364 struct xfrm_replay_state_esn **preplay_esn,
365 struct nlattr *rta)
366{
367 struct xfrm_replay_state_esn *p, *pp, *up;
368
369 if (!rta)
370 return 0;
371
372 up = nla_data(rta);
373
374 p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
375 if (!p)
376 return -ENOMEM;
377
378 pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
379 if (!pp) {
380 kfree(p);
381 return -ENOMEM;
382 }
383
384 *replay_esn = p;
385 *preplay_esn = pp;
386
387 return 0;
388}
389
348static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) 390static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
349{ 391{
350 int len = 0; 392 int len = 0;
@@ -380,10 +422,20 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
380static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) 422static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
381{ 423{
382 struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; 424 struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
425 struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
383 struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; 426 struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
384 struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; 427 struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
385 struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; 428 struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
386 429
430 if (re) {
431 struct xfrm_replay_state_esn *replay_esn;
432 replay_esn = nla_data(re);
433 memcpy(x->replay_esn, replay_esn,
434 xfrm_replay_state_esn_len(replay_esn));
435 memcpy(x->preplay_esn, replay_esn,
436 xfrm_replay_state_esn_len(replay_esn));
437 }
438
387 if (rp) { 439 if (rp) {
388 struct xfrm_replay_state *replay; 440 struct xfrm_replay_state *replay;
389 replay = nla_data(rp); 441 replay = nla_data(rp);
@@ -467,13 +519,14 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
467 security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) 519 security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX])))
468 goto error; 520 goto error;
469 521
522 if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
523 attrs[XFRMA_REPLAY_ESN_VAL])))
524 goto error;
525
470 x->km.seq = p->seq; 526 x->km.seq = p->seq;
471 x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; 527 x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth;
472 /* sysctl_xfrm_aevent_etime is in 100ms units */ 528 /* sysctl_xfrm_aevent_etime is in 100ms units */
473 x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; 529 x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M;
474 x->preplay.bitmap = 0;
475 x->preplay.seq = x->replay.seq+x->replay_maxdiff;
476 x->preplay.oseq = x->replay.oseq +x->replay_maxdiff;
477 530
478 if ((err = xfrm_init_replay(x))) 531 if ((err = xfrm_init_replay(x)))
479 goto error; 532 goto error;
@@ -709,6 +762,10 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
709 if (xfrm_mark_put(skb, &x->mark)) 762 if (xfrm_mark_put(skb, &x->mark))
710 goto nla_put_failure; 763 goto nla_put_failure;
711 764
765 if (x->replay_esn)
766 NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
767 xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn);
768
712 if (x->security && copy_sec_ctx(x->security, skb) < 0) 769 if (x->security && copy_sec_ctx(x->security, skb) < 0)
713 goto nla_put_failure; 770 goto nla_put_failure;
714 771
@@ -1578,10 +1635,14 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1578 return 0; 1635 return 0;
1579} 1636}
1580 1637
1581static inline size_t xfrm_aevent_msgsize(void) 1638static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x)
1582{ 1639{
1640 size_t replay_size = x->replay_esn ?
1641 xfrm_replay_state_esn_len(x->replay_esn) :
1642 sizeof(struct xfrm_replay_state);
1643
1583 return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) 1644 return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
1584 + nla_total_size(sizeof(struct xfrm_replay_state)) 1645 + nla_total_size(replay_size)
1585 + nla_total_size(sizeof(struct xfrm_lifetime_cur)) 1646 + nla_total_size(sizeof(struct xfrm_lifetime_cur))
1586 + nla_total_size(sizeof(struct xfrm_mark)) 1647 + nla_total_size(sizeof(struct xfrm_mark))
1587 + nla_total_size(4) /* XFRM_AE_RTHR */ 1648 + nla_total_size(4) /* XFRM_AE_RTHR */
@@ -1606,7 +1667,13 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct
1606 id->reqid = x->props.reqid; 1667 id->reqid = x->props.reqid;
1607 id->flags = c->data.aevent; 1668 id->flags = c->data.aevent;
1608 1669
1609 NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); 1670 if (x->replay_esn)
1671 NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
1672 xfrm_replay_state_esn_len(x->replay_esn),
1673 x->replay_esn);
1674 else
1675 NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
1676
1610 NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); 1677 NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft);
1611 1678
1612 if (id->flags & XFRM_AE_RTHR) 1679 if (id->flags & XFRM_AE_RTHR)
@@ -1639,16 +1706,16 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1639 struct xfrm_aevent_id *p = nlmsg_data(nlh); 1706 struct xfrm_aevent_id *p = nlmsg_data(nlh);
1640 struct xfrm_usersa_id *id = &p->sa_id; 1707 struct xfrm_usersa_id *id = &p->sa_id;
1641 1708
1642 r_skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);
1643 if (r_skb == NULL)
1644 return -ENOMEM;
1645
1646 mark = xfrm_mark_get(attrs, &m); 1709 mark = xfrm_mark_get(attrs, &m);
1647 1710
1648 x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); 1711 x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
1649 if (x == NULL) { 1712 if (x == NULL)
1650 kfree_skb(r_skb);
1651 return -ESRCH; 1713 return -ESRCH;
1714
1715 r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
1716 if (r_skb == NULL) {
1717 xfrm_state_put(x);
1718 return -ENOMEM;
1652 } 1719 }
1653 1720
1654 /* 1721 /*
@@ -1680,9 +1747,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1680 struct xfrm_mark m; 1747 struct xfrm_mark m;
1681 struct xfrm_aevent_id *p = nlmsg_data(nlh); 1748 struct xfrm_aevent_id *p = nlmsg_data(nlh);
1682 struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; 1749 struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
1750 struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
1683 struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; 1751 struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
1684 1752
1685 if (!lt && !rp) 1753 if (!lt && !rp && !re)
1686 return err; 1754 return err;
1687 1755
1688 /* pedantic mode - thou shalt sayeth replaceth */ 1756 /* pedantic mode - thou shalt sayeth replaceth */
@@ -2147,6 +2215,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
2147 [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, 2215 [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
2148 [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, 2216 [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
2149 [XFRMA_TFCPAD] = { .type = NLA_U32 }, 2217 [XFRMA_TFCPAD] = { .type = NLA_U32 },
2218 [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) },
2150}; 2219};
2151 2220
2152static struct xfrm_link { 2221static struct xfrm_link {
@@ -2274,7 +2343,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event
2274 struct net *net = xs_net(x); 2343 struct net *net = xs_net(x);
2275 struct sk_buff *skb; 2344 struct sk_buff *skb;
2276 2345
2277 skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC); 2346 skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
2278 if (skb == NULL) 2347 if (skb == NULL)
2279 return -ENOMEM; 2348 return -ENOMEM;
2280 2349
@@ -2328,6 +2397,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
2328 l += nla_total_size(sizeof(*x->encap)); 2397 l += nla_total_size(sizeof(*x->encap));
2329 if (x->tfcpad) 2398 if (x->tfcpad)
2330 l += nla_total_size(sizeof(x->tfcpad)); 2399 l += nla_total_size(sizeof(x->tfcpad));
2400 if (x->replay_esn)
2401 l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn));
2331 if (x->security) 2402 if (x->security)
2332 l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + 2403 l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
2333 x->security->ctx_len); 2404 x->security->ctx_len);