aboutsummaryrefslogtreecommitdiffstats
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
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>
-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
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/ipv6/ipcomp6.c19
-rw-r--r--net/ipv6/mip6.c2
-rw-r--r--net/ipv6/xfrm6_mode_beet.c2
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c4
-rw-r--r--net/ipv6/xfrm6_output.c4
-rw-r--r--net/ipv6/xfrm6_tunnel.c5
14 files changed, 23 insertions, 65 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
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index a64295d164ea..9eb928598351 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -43,7 +43,6 @@
43static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) 43static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
44{ 44{
45 int err; 45 int err;
46 struct ipv6hdr *top_iph;
47 struct ip_esp_hdr *esph; 46 struct ip_esp_hdr *esph;
48 struct crypto_blkcipher *tfm; 47 struct crypto_blkcipher *tfm;
49 struct blkcipher_desc desc; 48 struct blkcipher_desc desc;
@@ -85,9 +84,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
85 pskb_put(skb, trailer, clen - skb->len); 84 pskb_put(skb, trailer, clen - skb->len);
86 85
87 skb_push(skb, -skb_network_offset(skb)); 86 skb_push(skb, -skb_network_offset(skb));
88 top_iph = ipv6_hdr(skb);
89 esph = ip_esp_hdr(skb); 87 esph = ip_esp_hdr(skb);
90 top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
91 *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb); 88 *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
92 *skb_mac_header(skb) = IPPROTO_ESP; 89 *skb_mac_header(skb) = IPPROTO_ESP;
93 90
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 8f3f32faaf4c..28fc8edfdc3a 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -119,20 +119,15 @@ out:
119static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) 119static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
120{ 120{
121 int err; 121 int err;
122 struct ipv6hdr *top_iph;
123 struct ip_comp_hdr *ipch; 122 struct ip_comp_hdr *ipch;
124 struct ipcomp_data *ipcd = x->data; 123 struct ipcomp_data *ipcd = x->data;
125 int plen, dlen; 124 int plen, dlen;
126 u8 *start, *scratch; 125 u8 *start, *scratch;
127 struct crypto_comp *tfm; 126 struct crypto_comp *tfm;
128 int cpu; 127 int cpu;
129 int hdr_len;
130
131 skb_push(skb, -skb_network_offset(skb));
132 hdr_len = skb_transport_offset(skb);
133 128
134 /* check whether datagram len is larger than threshold */ 129 /* check whether datagram len is larger than threshold */
135 if ((skb->len - hdr_len) < ipcd->threshold) { 130 if (skb->len < ipcd->threshold) {
136 goto out_ok; 131 goto out_ok;
137 } 132 }
138 133
@@ -140,9 +135,9 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
140 goto out_ok; 135 goto out_ok;
141 136
142 /* compression */ 137 /* compression */
143 plen = skb->len - hdr_len; 138 plen = skb->len;
144 dlen = IPCOMP_SCRATCH_SIZE; 139 dlen = IPCOMP_SCRATCH_SIZE;
145 start = skb_transport_header(skb); 140 start = skb->data;
146 141
147 cpu = get_cpu(); 142 cpu = get_cpu();
148 scratch = *per_cpu_ptr(ipcomp6_scratches, cpu); 143 scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
@@ -155,13 +150,9 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
155 } 150 }
156 memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen); 151 memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
157 put_cpu(); 152 put_cpu();
158 pskb_trim(skb, hdr_len + dlen + sizeof(struct ip_comp_hdr)); 153 pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
159 154
160 /* insert ipcomp header and replace datagram */ 155 /* insert ipcomp header and replace datagram */
161 top_iph = ipv6_hdr(skb);
162
163 top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
164
165 ipch = ip_comp_hdr(skb); 156 ipch = ip_comp_hdr(skb);
166 ipch->nexthdr = *skb_mac_header(skb); 157 ipch->nexthdr = *skb_mac_header(skb);
167 ipch->flags = 0; 158 ipch->flags = 0;
@@ -169,6 +160,8 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
169 *skb_mac_header(skb) = IPPROTO_COMP; 160 *skb_mac_header(skb) = IPPROTO_COMP;
170 161
171out_ok: 162out_ok:
163 skb_push(skb, -skb_network_offset(skb));
164
172 return 0; 165 return 0;
173} 166}
174 167
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 0e7a60f7393a..7fd841d41019 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -155,7 +155,6 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
155 155
156 skb_push(skb, -skb_network_offset(skb)); 156 skb_push(skb, -skb_network_offset(skb));
157 iph = ipv6_hdr(skb); 157 iph = ipv6_hdr(skb);
158 iph->payload_len = htons(skb->len - sizeof(*iph));
159 158
160 nexthdr = *skb_mac_header(skb); 159 nexthdr = *skb_mac_header(skb);
161 *skb_mac_header(skb) = IPPROTO_DSTOPTS; 160 *skb_mac_header(skb) = IPPROTO_DSTOPTS;
@@ -370,7 +369,6 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
370 369
371 skb_push(skb, -skb_network_offset(skb)); 370 skb_push(skb, -skb_network_offset(skb));
372 iph = ipv6_hdr(skb); 371 iph = ipv6_hdr(skb);
373 iph->payload_len = htons(skb->len - sizeof(*iph));
374 372
375 nexthdr = *skb_mac_header(skb); 373 nexthdr = *skb_mac_header(skb);
376 *skb_mac_header(skb) = IPPROTO_ROUTING; 374 *skb_mac_header(skb) = IPPROTO_ROUTING;
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 42c6ef839e59..13bb1e856764 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -22,8 +22,6 @@
22/* Add encapsulation header. 22/* Add encapsulation header.
23 * 23 *
24 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. 24 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
25 * The following fields in it shall be filled in by x->type->output:
26 * payload_len
27 */ 25 */
28static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) 26static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
29{ 27{
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index e79c6bdf71c1..ea2283879112 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -33,9 +33,7 @@ static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb)
33 33
34/* Add encapsulation header. 34/* Add encapsulation header.
35 * 35 *
36 * The top IP header will be constructed per RFC 2401. The following fields 36 * The top IP header will be constructed per RFC 2401.
37 * in it shall be filled in by x->type->output:
38 * payload_len
39 */ 37 */
40static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 38static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
41{ 39{
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index f21596f89984..4618c18e611d 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -47,6 +47,7 @@ static inline int xfrm6_output_one(struct sk_buff *skb)
47{ 47{
48 struct dst_entry *dst = skb->dst; 48 struct dst_entry *dst = skb->dst;
49 struct xfrm_state *x = dst->xfrm; 49 struct xfrm_state *x = dst->xfrm;
50 struct ipv6hdr *iph;
50 int err; 51 int err;
51 52
52 if (x->props.mode == XFRM_MODE_TUNNEL) { 53 if (x->props.mode == XFRM_MODE_TUNNEL) {
@@ -59,6 +60,9 @@ static inline int xfrm6_output_one(struct sk_buff *skb)
59 if (err) 60 if (err)
60 goto error_nolock; 61 goto error_nolock;
61 62
63 iph = ipv6_hdr(skb);
64 iph->payload_len = htons(skb->len - sizeof(*iph));
65
62 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; 66 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
63 err = 0; 67 err = 0;
64 68
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 00a1a3e5237c..3f8a3abde67e 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -242,12 +242,7 @@ EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
242 242
243static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 243static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
244{ 244{
245 struct ipv6hdr *top_iph;
246
247 skb_push(skb, -skb_network_offset(skb)); 245 skb_push(skb, -skb_network_offset(skb));
248 top_iph = ipv6_hdr(skb);
249 top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
250
251 return 0; 246 return 0;
252} 247}
253 248