aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2013-02-22 04:54:54 -0500
committerSteffen Klassert <steffen.klassert@secunet.com>2013-03-06 01:02:45 -0500
commita947b0a93efa9a25c012aa88848f4cf8d9b41280 (patch)
treeca5ccc41834e4c811e859724a184f223a3772ca7 /net
parent6fac41157252220678b210fcb13e2c3dad7a912a (diff)
xfrm: allow to avoid copying DSCP during encapsulation
By default, DSCP is copying during encapsulation. Copying the DSCP in IPsec tunneling may be a bit dangerous because packets with different DSCP may get reordered relative to each other in the network and then dropped by the remote IPsec GW if the reordering becomes too big compared to the replay window. It is possible to avoid this copy with netfilter rules, but it's very convenient to be able to configure it for each SA directly. This patch adds a toogle for this purpose. By default, it's not set to maintain backward compatibility. Field flags in struct xfrm_usersa_info is full, hence I add a new attribute. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/ipcomp.c1
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c8
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c7
-rw-r--r--net/xfrm/xfrm_state.c1
-rw-r--r--net/xfrm/xfrm_user.c13
5 files changed, 26 insertions, 4 deletions
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index f01d1b1aff7f..59cb8c769056 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -75,6 +75,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
75 t->props.mode = x->props.mode; 75 t->props.mode = x->props.mode;
76 t->props.saddr.a4 = x->props.saddr.a4; 76 t->props.saddr.a4 = x->props.saddr.a4;
77 t->props.flags = x->props.flags; 77 t->props.flags = x->props.flags;
78 t->props.extra_flags = x->props.extra_flags;
78 memcpy(&t->mark, &x->mark, sizeof(t->mark)); 79 memcpy(&t->mark, &x->mark, sizeof(t->mark));
79 80
80 if (xfrm_init_state(t)) 81 if (xfrm_init_state(t))
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index fe5189e2e114..eb1dd4d643f2 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -103,8 +103,12 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
103 103
104 top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family); 104 top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
105 105
106 /* DS disclosed */ 106 /* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
107 top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos, 107 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
108 top_iph->tos = 0;
109 else
110 top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
111 top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
108 XFRM_MODE_SKB_CB(skb)->tos); 112 XFRM_MODE_SKB_CB(skb)->tos);
109 113
110 flags = x->props.flags; 114 flags = x->props.flags;
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 9bf6a74a71d2..4770d515c2c8 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -49,8 +49,11 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
49 sizeof(top_iph->flow_lbl)); 49 sizeof(top_iph->flow_lbl));
50 top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family); 50 top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
51 51
52 dsfield = XFRM_MODE_SKB_CB(skb)->tos; 52 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
53 dsfield = INET_ECN_encapsulate(dsfield, dsfield); 53 dsfield = 0;
54 else
55 dsfield = XFRM_MODE_SKB_CB(skb)->tos;
56 dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
54 if (x->props.flags & XFRM_STATE_NOECN) 57 if (x->props.flags & XFRM_STATE_NOECN)
55 dsfield &= ~INET_ECN_MASK; 58 dsfield &= ~INET_ECN_MASK;
56 ipv6_change_dsfield(top_iph, 0, dsfield); 59 ipv6_change_dsfield(top_iph, 0, dsfield);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 2c341bdaf47c..78f66fa92449 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1187,6 +1187,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp)
1187 goto error; 1187 goto error;
1188 1188
1189 x->props.flags = orig->props.flags; 1189 x->props.flags = orig->props.flags;
1190 x->props.extra_flags = orig->props.extra_flags;
1190 1191
1191 x->curlft.add_time = orig->curlft.add_time; 1192 x->curlft.add_time = orig->curlft.add_time;
1192 x->km.state = orig->km.state; 1193 x->km.state = orig->km.state;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index fbd9e6cd0fd7..204cba192af8 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -515,6 +515,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
515 515
516 copy_from_user_state(x, p); 516 copy_from_user_state(x, p);
517 517
518 if (attrs[XFRMA_SA_EXTRA_FLAGS])
519 x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);
520
518 if ((err = attach_aead(&x->aead, &x->props.ealgo, 521 if ((err = attach_aead(&x->aead, &x->props.ealgo,
519 attrs[XFRMA_ALG_AEAD]))) 522 attrs[XFRMA_ALG_AEAD])))
520 goto error; 523 goto error;
@@ -779,6 +782,13 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
779 782
780 copy_to_user_state(x, p); 783 copy_to_user_state(x, p);
781 784
785 if (x->props.extra_flags) {
786 ret = nla_put_u32(skb, XFRMA_SA_EXTRA_FLAGS,
787 x->props.extra_flags);
788 if (ret)
789 goto out;
790 }
791
782 if (x->coaddr) { 792 if (x->coaddr) {
783 ret = nla_put(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); 793 ret = nla_put(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr);
784 if (ret) 794 if (ret)
@@ -2302,6 +2312,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
2302 [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, 2312 [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
2303 [XFRMA_TFCPAD] = { .type = NLA_U32 }, 2313 [XFRMA_TFCPAD] = { .type = NLA_U32 },
2304 [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, 2314 [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) },
2315 [XFRMA_SA_EXTRA_FLAGS] = { .type = NLA_U32 },
2305}; 2316};
2306 2317
2307static struct xfrm_link { 2318static struct xfrm_link {
@@ -2495,6 +2506,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
2495 x->security->ctx_len); 2506 x->security->ctx_len);
2496 if (x->coaddr) 2507 if (x->coaddr)
2497 l += nla_total_size(sizeof(*x->coaddr)); 2508 l += nla_total_size(sizeof(*x->coaddr));
2509 if (x->props.extra_flags)
2510 l += nla_total_size(sizeof(x->props.extra_flags));
2498 2511
2499 /* Must count x->lastused as it may become non-zero behind our back. */ 2512 /* Must count x->lastused as it may become non-zero behind our back. */
2500 l += nla_total_size(sizeof(u64)); 2513 l += nla_total_size(sizeof(u64));