diff options
-rw-r--r-- | include/net/xfrm.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/xfrm.h | 3 | ||||
-rw-r--r-- | net/ipv4/ipcomp.c | 1 | ||||
-rw-r--r-- | net/ipv4/xfrm4_mode_tunnel.c | 8 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 7 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 1 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 13 |
7 files changed, 30 insertions, 4 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 24c8886fd969..ae16531d0d35 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -162,6 +162,7 @@ struct xfrm_state { | |||
162 | xfrm_address_t saddr; | 162 | xfrm_address_t saddr; |
163 | int header_len; | 163 | int header_len; |
164 | int trailer_len; | 164 | int trailer_len; |
165 | u32 extra_flags; | ||
165 | } props; | 166 | } props; |
166 | 167 | ||
167 | struct xfrm_lifetime_cfg lft; | 168 | struct xfrm_lifetime_cfg lft; |
diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h index 28e493b5b94c..a8cd6a4a2970 100644 --- a/include/uapi/linux/xfrm.h +++ b/include/uapi/linux/xfrm.h | |||
@@ -297,6 +297,7 @@ enum xfrm_attr_type_t { | |||
297 | XFRMA_MARK, /* struct xfrm_mark */ | 297 | XFRMA_MARK, /* struct xfrm_mark */ |
298 | XFRMA_TFCPAD, /* __u32 */ | 298 | XFRMA_TFCPAD, /* __u32 */ |
299 | XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_esn */ | 299 | XFRMA_REPLAY_ESN_VAL, /* struct xfrm_replay_esn */ |
300 | XFRMA_SA_EXTRA_FLAGS, /* __u32 */ | ||
300 | __XFRMA_MAX | 301 | __XFRMA_MAX |
301 | 302 | ||
302 | #define XFRMA_MAX (__XFRMA_MAX - 1) | 303 | #define XFRMA_MAX (__XFRMA_MAX - 1) |
@@ -367,6 +368,8 @@ struct xfrm_usersa_info { | |||
367 | #define XFRM_STATE_ESN 128 | 368 | #define XFRM_STATE_ESN 128 |
368 | }; | 369 | }; |
369 | 370 | ||
371 | #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1 | ||
372 | |||
370 | struct xfrm_usersa_id { | 373 | struct xfrm_usersa_id { |
371 | xfrm_address_t daddr; | 374 | xfrm_address_t daddr; |
372 | __be32 spi; | 375 | __be32 spi; |
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 | ||
2307 | static struct xfrm_link { | 2318 | static 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)); |