aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-10 18:45:52 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:55:56 -0400
commitceb1eec8291175686d0208e66595ff83bc0624e2 (patch)
tree83a7fdc7d292f1dbb80f32563d9573810bfe6e42 /net/ipv4
parent87bdc48d304191313203df9b98d783e1ab5a55ab (diff)
[IPSEC]: Move IP length/checksum setting out of transforms
This patch moves the setting of the IP length and checksum fields out of the transforms and into the xfrmX_output functions. This would help future efforts in merging the transforms themselves. It also adds an optimisation to ipcomp due to the fact that the transport offset is guaranteed to be zero. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/esp4.c7
-rw-r--r--net/ipv4/ipcomp.c22
-rw-r--r--net/ipv4/xfrm4_mode_beet.c3
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c5
-rw-r--r--net/ipv4/xfrm4_output.c5
-rw-r--r--net/ipv4/xfrm4_tunnel.c5
7 files changed, 12 insertions, 37 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index d69706405d58..60925fedbf16 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -115,8 +115,6 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
115 memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); 115 memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
116 } 116 }
117 117
118 ip_send_check(top_iph);
119
120 err = 0; 118 err = 0;
121 119
122error: 120error:
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 66eb4968b910..8377bedf3f66 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -16,7 +16,6 @@
16static int esp_output(struct xfrm_state *x, struct sk_buff *skb) 16static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
17{ 17{
18 int err; 18 int err;
19 struct iphdr *top_iph;
20 struct ip_esp_hdr *esph; 19 struct ip_esp_hdr *esph;
21 struct crypto_blkcipher *tfm; 20 struct crypto_blkcipher *tfm;
22 struct blkcipher_desc desc; 21 struct blkcipher_desc desc;
@@ -59,9 +58,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
59 pskb_put(skb, trailer, clen - skb->len); 58 pskb_put(skb, trailer, clen - skb->len);
60 59
61 skb_push(skb, -skb_network_offset(skb)); 60 skb_push(skb, -skb_network_offset(skb));
62 top_iph = ip_hdr(skb);
63 esph = ip_esp_hdr(skb); 61 esph = ip_esp_hdr(skb);
64 top_iph->tot_len = htons(skb->len + alen);
65 *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb); 62 *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
66 *skb_mac_header(skb) = IPPROTO_ESP; 63 *skb_mac_header(skb) = IPPROTO_ESP;
67 64
@@ -76,7 +73,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
76 uh = (struct udphdr *)esph; 73 uh = (struct udphdr *)esph;
77 uh->source = encap->encap_sport; 74 uh->source = encap->encap_sport;
78 uh->dest = encap->encap_dport; 75 uh->dest = encap->encap_dport;
79 uh->len = htons(skb->len + alen - top_iph->ihl*4); 76 uh->len = htons(skb->len + alen - skb_transport_offset(skb));
80 uh->check = 0; 77 uh->check = 0;
81 78
82 switch (encap->encap_type) { 79 switch (encap->encap_type) {
@@ -136,8 +133,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
136unlock: 133unlock:
137 spin_unlock_bh(&x->lock); 134 spin_unlock_bh(&x->lock);
138 135
139 ip_send_check(top_iph);
140
141error: 136error:
142 return err; 137 return err;
143} 138}
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 78d6ddb02d1d..32b02deca2ec 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -98,10 +98,9 @@ out:
98static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) 98static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
99{ 99{
100 struct ipcomp_data *ipcd = x->data; 100 struct ipcomp_data *ipcd = x->data;
101 const int ihlen = skb_transport_offset(skb); 101 const int plen = skb->len;
102 const int plen = skb->len - ihlen;
103 int dlen = IPCOMP_SCRATCH_SIZE; 102 int dlen = IPCOMP_SCRATCH_SIZE;
104 u8 *start = skb_transport_header(skb); 103 u8 *start = skb->data;
105 const int cpu = get_cpu(); 104 const int cpu = get_cpu();
106 u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu); 105 u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
107 struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu); 106 struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
@@ -118,7 +117,7 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
118 memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen); 117 memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
119 put_cpu(); 118 put_cpu();
120 119
121 pskb_trim(skb, ihlen + dlen + sizeof(struct ip_comp_hdr)); 120 pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
122 return 0; 121 return 0;
123 122
124out: 123out:
@@ -131,13 +130,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
131 int err; 130 int err;
132 struct ip_comp_hdr *ipch; 131 struct ip_comp_hdr *ipch;
133 struct ipcomp_data *ipcd = x->data; 132 struct ipcomp_data *ipcd = x->data;
134 int hdr_len = 0;
135 struct iphdr *iph = ip_hdr(skb);
136 133
137 skb_push(skb, -skb_network_offset(skb)); 134 if (skb->len < ipcd->threshold) {
138 iph->tot_len = htons(skb->len);
139 hdr_len = iph->ihl * 4;
140 if ((skb->len - hdr_len) < ipcd->threshold) {
141 /* Don't bother compressing */ 135 /* Don't bother compressing */
142 goto out_ok; 136 goto out_ok;
143 } 137 }
@@ -146,25 +140,19 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
146 goto out_ok; 140 goto out_ok;
147 141
148 err = ipcomp_compress(x, skb); 142 err = ipcomp_compress(x, skb);
149 iph = ip_hdr(skb);
150 143
151 if (err) { 144 if (err) {
152 goto out_ok; 145 goto out_ok;
153 } 146 }
154 147
155 /* Install ipcomp header, convert into ipcomp datagram. */ 148 /* Install ipcomp header, convert into ipcomp datagram. */
156 iph->tot_len = htons(skb->len);
157 ipch = ip_comp_hdr(skb); 149 ipch = ip_comp_hdr(skb);
158 ipch->nexthdr = *skb_mac_header(skb); 150 ipch->nexthdr = *skb_mac_header(skb);
159 ipch->flags = 0; 151 ipch->flags = 0;
160 ipch->cpi = htons((u16 )ntohl(x->id.spi)); 152 ipch->cpi = htons((u16 )ntohl(x->id.spi));
161 *skb_mac_header(skb) = IPPROTO_COMP; 153 *skb_mac_header(skb) = IPPROTO_COMP;
162 ip_send_check(iph);
163 return 0;
164
165out_ok: 154out_ok:
166 if (x->props.mode == XFRM_MODE_TUNNEL) 155 skb_push(skb, -skb_network_offset(skb));
167 ip_send_check(iph);
168 return 0; 156 return 0;
169} 157}
170 158
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 7226c6486c01..73d2338bec55 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -20,9 +20,6 @@
20/* Add encapsulation header. 20/* Add encapsulation header.
21 * 21 *
22 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. 22 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
23 * The following fields in it shall be filled in by x->type->output:
24 * tot_len
25 * check
26 */ 23 */
27static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) 24static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
28{ 25{
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index f1d41ea34785..1ae9d32276f0 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -31,10 +31,7 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
31 31
32/* Add encapsulation header. 32/* Add encapsulation header.
33 * 33 *
34 * The top IP header will be constructed per RFC 2401. The following fields 34 * The top IP header will be constructed per RFC 2401.
35 * in it shall be filled in by x->type->output:
36 * tot_len
37 * check
38 */ 35 */
39static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 36static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
40{ 37{
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 04805c7d79c3..434ef302ba83 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -44,6 +44,7 @@ static inline int xfrm4_output_one(struct sk_buff *skb)
44{ 44{
45 struct dst_entry *dst = skb->dst; 45 struct dst_entry *dst = skb->dst;
46 struct xfrm_state *x = dst->xfrm; 46 struct xfrm_state *x = dst->xfrm;
47 struct iphdr *iph;
47 int err; 48 int err;
48 49
49 if (x->props.mode == XFRM_MODE_TUNNEL) { 50 if (x->props.mode == XFRM_MODE_TUNNEL) {
@@ -56,6 +57,10 @@ static inline int xfrm4_output_one(struct sk_buff *skb)
56 if (err) 57 if (err)
57 goto error_nolock; 58 goto error_nolock;
58 59
60 iph = ip_hdr(skb);
61 iph->tot_len = htons(skb->len);
62 ip_send_check(iph);
63
59 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; 64 IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
60 err = 0; 65 err = 0;
61 66
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index be572f918b5e..e1fafc1562d8 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -12,12 +12,7 @@
12 12
13static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) 13static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
14{ 14{
15 struct iphdr *iph = ip_hdr(skb);
16
17 skb_push(skb, -skb_network_offset(skb)); 15 skb_push(skb, -skb_network_offset(skb));
18 iph->tot_len = htons(skb->len);
19 ip_send_check(iph);
20
21 return 0; 16 return 0;
22} 17}
23 18