diff options
| author | Herbert Xu <herbert@gondor.apana.org.au> | 2003-07-27 02:32:07 -0700 |
|---|---|---|
| committer | David S. Miller <davem@kernel.bkbits.net> | 2003-07-27 02:32:07 -0700 |
| commit | 596aac2cab7581d015f58ccf7fb97be5d06c06fa (patch) | |
| tree | 8db22027240dca73d52903ba96b69b3e0688858c /net | |
| parent | 872d1c7a5963bdbcc78cce3283db0fd52fafa39d (diff) | |
[IPSEC]: Use per-SA flag to control ECN propagation.
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/ah4.c | 3 | ||||
| -rw-r--r-- | net/ipv4/esp4.c | 3 | ||||
| -rw-r--r-- | net/ipv4/ipcomp.c | 3 | ||||
| -rw-r--r-- | net/ipv4/xfrm4_input.c | 12 | ||||
| -rw-r--r-- | net/ipv6/ah6.c | 3 | ||||
| -rw-r--r-- | net/ipv6/esp6.c | 3 | ||||
| -rw-r--r-- | net/ipv6/ipcomp6.c | 3 | ||||
| -rw-r--r-- | net/ipv6/xfrm6_input.c | 11 | ||||
| -rw-r--r-- | net/key/af_key.c | 4 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 2 |
10 files changed, 47 insertions, 0 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 030bc3605b99..4641b35a273c 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -1,5 +1,6 @@ #include <linux/config.h> #include <linux/module.h> +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/ah.h> @@ -123,6 +124,8 @@ static int ah_output(struct sk_buff *skb) top_iph->tos = iph->tos; top_iph->ttl = iph->ttl; if (x->props.mode) { + if (x->props.flags & XFRM_STATE_NOECN) + IP_ECN_clear(top_iph); top_iph->frag_off = iph->frag_off&~htons(IP_MF|IP_OFFSET); memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); } else { diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 93289a96545a..af293a7bc687 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -1,5 +1,6 @@ #include <linux/config.h> #include <linux/module.h> +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/esp.h> @@ -109,6 +110,8 @@ int esp_output(struct sk_buff *skb) top_iph->ihl = 5; top_iph->version = 4; top_iph->tos = iph->tos; /* DS disclosed */ + if (x->props.flags & XFRM_STATE_NOECN) + IP_ECN_clear(top_iph); top_iph->tot_len = htons(skb->len + alen); top_iph->frag_off = iph->frag_off&htons(IP_DF); if (!(top_iph->frag_off)) diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index f3356664be06..f968969d61d8 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -18,6 +18,7 @@ #include <asm/scatterlist.h> #include <linux/crypto.h> #include <linux/pfkeyv2.h> +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/icmp.h> @@ -210,6 +211,8 @@ static int ipcomp_output(struct sk_buff *skb) top_iph = (struct iphdr *)skb_push(skb, sizeof(struct ip_comp_hdr)); memcpy(top_iph, &tmp_iph, iph->ihl * 4); iph = top_iph; + if (x->props.mode && (x->props.flags & XFRM_STATE_NOECN)) + IP_ECN_clear(iph); iph->tot_len = htons(skb->len); iph->protocol = IPPROTO_COMP; iph->check = 0; diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 4b9797600d74..9a10d736d62a 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -10,6 +10,7 @@ */ #include <linux/slab.h> +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> @@ -20,6 +21,15 @@ int xfrm4_rcv(struct sk_buff *skb) return xfrm4_rcv_encap(skb, 0); } +static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) +{ + struct iphdr *inner_iph = skb->nh.iph; + + if (INET_ECN_is_ce(outer_iph->tos) && + INET_ECN_is_not_ce(inner_iph->tos)) + IP_ECN_set_ce(inner_iph); +} + int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) { int err; @@ -75,6 +85,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) if (iph->protocol != IPPROTO_IPIP) goto drop; skb->nh.raw = skb->data; + if (!(x->props.flags & XFRM_STATE_NOECN)) + ipip_ecn_decapsulate(iph, skb); iph = skb->nh.iph; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); decaps = 1; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 6696e519f134..07d92a2e48a3 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -26,6 +26,7 @@ #include <linux/config.h> #include <linux/module.h> +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/ah.h> @@ -220,6 +221,8 @@ int ah6_output(struct sk_buff *skb) skb->nh.ipv6h->flow_lbl[0] = iph->flow_lbl[0]; skb->nh.ipv6h->flow_lbl[1] = iph->flow_lbl[1]; skb->nh.ipv6h->flow_lbl[2] = iph->flow_lbl[2]; + if (x->props.flags & XFRM_STATE_NOECN) + IP6_ECN_clear(skb->nh.ipv6h); } else { memcpy(skb->nh.ipv6h, iph, hdr_len); skb->nh.raw[nh_offset] = IPPROTO_AH; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index a9a384465160..e78cee3ed056 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -26,6 +26,7 @@ #include <linux/config.h> #include <linux/module.h> +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/esp.h> @@ -121,6 +122,8 @@ int esp6_output(struct sk_buff *skb) top_iph->flow_lbl[0] = iph->flow_lbl[0]; top_iph->flow_lbl[1] = iph->flow_lbl[1]; top_iph->flow_lbl[2] = iph->flow_lbl[2]; + if (x->props.flags & XFRM_STATE_NOECN) + IP6_ECN_clear(top_iph); top_iph->nexthdr = IPPROTO_ESP; top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr)); top_iph->hop_limit = iph->hop_limit; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 307439f2a7c6..2101765131c9 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -32,6 +32,7 @@ */ #include <linux/config.h> #include <linux/module.h> +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/xfrm.h> #include <net/ipcomp.h> @@ -201,6 +202,8 @@ static int ipcomp6_output(struct sk_buff *skb) memcpy(top_iph, tmp_iph, hdr_len); kfree(tmp_iph); + if (x->props.mode && (x->props.flags & XFRM_STATE_NOECN)) + IP6_ECN_clear(top_iph); top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); skb->nh.raw = skb->data; /* top_iph */ ip6_find_1stfragopt(skb, &prevhdr); diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 7505f945fc8c..e38196564362 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -9,12 +9,21 @@ * IPv6 support */ +#include <net/inet_ecn.h> #include <net/ip.h> #include <net/ipv6.h> #include <net/xfrm.h> static kmem_cache_t *secpath_cachep; +static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph, + struct sk_buff *skb) +{ + if (INET_ECN_is_ce(ip6_get_dsfield(iph)) && + INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h))) + IP6_ECN_set_ce(skb->nh.ipv6h); +} + int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) { struct sk_buff *skb = *pskb; @@ -71,6 +80,8 @@ int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) if (nexthdr != IPPROTO_IPV6) goto drop; skb->nh.raw = skb->data; + if (!(x->props.flags & XFRM_STATE_NOECN)) + ipip6_ecn_decapsulate(iph, skb); iph = skb->nh.ipv6h; decaps = 1; break; diff --git a/net/key/af_key.c b/net/key/af_key.c index f481a136dad4..ec9fe27e1e37 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -681,6 +681,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, } sa->sadb_sa_flags = 0; + if (x->props.flags & XFRM_STATE_NOECN) + sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; /* hard time */ if (hsc & 2) { @@ -957,6 +959,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, x->id.proto = proto; x->id.spi = sa->sadb_sa_spi; x->props.replay_window = sa->sadb_sa_replay; + if (sa->sadb_sa_flags & SADB_SAFLAGS_NOECN) + x->props.flags |= XFRM_STATE_NOECN; lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; if (lifetime != NULL) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b2dd1296f7b6..f10711c7e0fb 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -201,6 +201,7 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * x->props.reqid = p->reqid; x->props.family = p->family; x->props.saddr = p->saddr; + x->props.flags = p->flags; } static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, @@ -305,6 +306,7 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) p->replay_window = x->props.replay_window; p->reqid = x->props.reqid; p->family = x->props.family; + p->flags = x->props.flags; p->seq = x->km.seq; } |
