aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-10 18:44:44 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:55:54 -0400
commit37fedd3aab6517daec628764c5d66dd8761fbe5f (patch)
tree12227aec3944168bff04173dccd580240f4496aa
parent7b277b1a5fb147cb828e5d8b9780cee60f31a9bf (diff)
[IPSEC]: Use IPv6 calling convention as the convention for x->mode->output
The IPv6 calling convention for x->mode->output is more general and could help an eventual protocol-generic x->type->output implementation. This patch adopts it for IPv4 as well and modifies the IPv4 type output functions accordingly. It also rewrites the IPv6 mac/transport header calculation to be based off the network header where practical. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/xfrm.h12
-rw-r--r--net/ipv4/ah4.c6
-rw-r--r--net/ipv4/esp4.c11
-rw-r--r--net/ipv4/ipcomp.c10
-rw-r--r--net/ipv4/xfrm4_mode_beet.c17
-rw-r--r--net/ipv4/xfrm4_mode_transport.c7
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c7
-rw-r--r--net/ipv6/xfrm6_mode_beet.c9
-rw-r--r--net/ipv6/xfrm6_mode_ro.c9
-rw-r--r--net/ipv6/xfrm6_mode_transport.c9
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c14
11 files changed, 44 insertions, 67 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1c116dc03e0e..77be396ca633 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -300,6 +300,18 @@ extern void xfrm_put_type(struct xfrm_type *type);
300 300
301struct xfrm_mode { 301struct xfrm_mode {
302 int (*input)(struct xfrm_state *x, struct sk_buff *skb); 302 int (*input)(struct xfrm_state *x, struct sk_buff *skb);
303
304 /*
305 * Add encapsulation header.
306 *
307 * On exit, the transport header will be set to the start of the
308 * encapsulation header to be filled in by x->type->output and
309 * the mac header will be set to the nextheader (protocol for
310 * IPv4) field of the extension header directly preceding the
311 * encapsulation header, or in its absence, that of the top IP
312 * header. The value of the network header will always point
313 * to the top IP header while skb->data will point to the payload.
314 */
303 int (*output)(struct xfrm_state *x,struct sk_buff *skb); 315 int (*output)(struct xfrm_state *x,struct sk_buff *skb);
304 316
305 struct module *owner; 317 struct module *owner;
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index dbb1f11721e4..e4f7aa39978d 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -82,14 +82,14 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
82 goto error; 82 goto error;
83 } 83 }
84 84
85 ah = (struct ip_auth_hdr *)((char *)top_iph+top_iph->ihl*4); 85 ah = (struct ip_auth_hdr *)skb_transport_header(skb);
86 ah->nexthdr = top_iph->protocol; 86 ah->nexthdr = *skb_mac_header(skb);
87 *skb_mac_header(skb) = IPPROTO_AH;
87 88
88 top_iph->tos = 0; 89 top_iph->tos = 0;
89 top_iph->tot_len = htons(skb->len); 90 top_iph->tot_len = htons(skb->len);
90 top_iph->frag_off = 0; 91 top_iph->frag_off = 0;
91 top_iph->ttl = 0; 92 top_iph->ttl = 0;
92 top_iph->protocol = IPPROTO_AH;
93 top_iph->check = 0; 93 top_iph->check = 0;
94 94
95 ahp = x->data; 95 ahp = x->data;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 0f5e8387ccb4..93153d105619 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -60,10 +60,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
60 60
61 skb_push(skb, -skb_network_offset(skb)); 61 skb_push(skb, -skb_network_offset(skb));
62 top_iph = ip_hdr(skb); 62 top_iph = ip_hdr(skb);
63 esph = (struct ip_esp_hdr *)(skb_network_header(skb) + 63 esph = (struct ip_esp_hdr *)skb_transport_header(skb);
64 top_iph->ihl * 4);
65 top_iph->tot_len = htons(skb->len + alen); 64 top_iph->tot_len = htons(skb->len + alen);
66 *(skb_tail_pointer(trailer) - 1) = top_iph->protocol; 65 *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
66 *skb_mac_header(skb) = IPPROTO_ESP;
67 67
68 spin_lock_bh(&x->lock); 68 spin_lock_bh(&x->lock);
69 69
@@ -91,9 +91,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
91 break; 91 break;
92 } 92 }
93 93
94 top_iph->protocol = IPPROTO_UDP; 94 *skb_mac_header(skb) = IPPROTO_UDP;
95 } else 95 }
96 top_iph->protocol = IPPROTO_ESP;
97 96
98 esph->spi = x->id.spi; 97 esph->spi = x->id.spi;
99 esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq); 98 esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 1929d451dab5..bf74f64fe5fb 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -98,10 +98,10 @@ 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 = ip_hdrlen(skb); 101 const int ihlen = skb_transport_offset(skb);
102 const int plen = skb->len - ihlen; 102 const int plen = skb->len - ihlen;
103 int dlen = IPCOMP_SCRATCH_SIZE; 103 int dlen = IPCOMP_SCRATCH_SIZE;
104 u8 *start = skb->data + ihlen; 104 u8 *start = skb_transport_header(skb);
105 const int cpu = get_cpu(); 105 const int cpu = get_cpu();
106 u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu); 106 u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
107 struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu); 107 struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
@@ -154,11 +154,11 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
154 154
155 /* Install ipcomp header, convert into ipcomp datagram. */ 155 /* Install ipcomp header, convert into ipcomp datagram. */
156 iph->tot_len = htons(skb->len); 156 iph->tot_len = htons(skb->len);
157 ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4); 157 ipch = (struct ip_comp_hdr *)skb_transport_header(skb);
158 ipch->nexthdr = iph->protocol; 158 ipch->nexthdr = *skb_mac_header(skb);
159 ipch->flags = 0; 159 ipch->flags = 0;
160 ipch->cpi = htons((u16 )ntohl(x->id.spi)); 160 ipch->cpi = htons((u16 )ntohl(x->id.spi));
161 iph->protocol = IPPROTO_COMP; 161 *skb_mac_header(skb) = IPPROTO_COMP;
162 ip_send_check(iph); 162 ip_send_check(iph);
163 return 0; 163 return 0;
164 164
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 77888f596737..7226c6486c01 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -23,17 +23,14 @@
23 * The following fields in it shall be filled in by x->type->output: 23 * The following fields in it shall be filled in by x->type->output:
24 * tot_len 24 * tot_len
25 * check 25 * check
26 *
27 * On exit, skb->h will be set to the start of the payload to be processed
28 * by x->type->output and skb->nh will be set to the top IP header.
29 */ 26 */
30static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) 27static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
31{ 28{
29 struct ip_beet_phdr *ph;
32 struct iphdr *iph, *top_iph; 30 struct iphdr *iph, *top_iph;
33 int hdrlen, optlen; 31 int hdrlen, optlen;
34 32
35 iph = ip_hdr(skb); 33 iph = ip_hdr(skb);
36 skb->transport_header = skb->network_header;
37 34
38 hdrlen = 0; 35 hdrlen = 0;
39 optlen = iph->ihl * 4 - sizeof(*iph); 36 optlen = iph->ihl * 4 - sizeof(*iph);
@@ -42,17 +39,17 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
42 39
43 skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len - 40 skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len -
44 hdrlen); 41 hdrlen);
45 top_iph = ip_hdr(skb); 42 skb->mac_header = skb->network_header +
46 skb->transport_header += sizeof(*iph) - hdrlen; 43 offsetof(struct iphdr, protocol);
47 __skb_pull(skb, sizeof(*iph) - hdrlen); 44 skb->transport_header = skb->network_header + sizeof(*iph);
45
46 ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);
48 47
48 top_iph = ip_hdr(skb);
49 memmove(top_iph, iph, sizeof(*iph)); 49 memmove(top_iph, iph, sizeof(*iph));
50 if (unlikely(optlen)) { 50 if (unlikely(optlen)) {
51 struct ip_beet_phdr *ph;
52
53 BUG_ON(optlen < 0); 51 BUG_ON(optlen < 0);
54 52
55 ph = (struct ip_beet_phdr *)skb_transport_header(skb);
56 ph->padlen = 4 - (optlen & 4); 53 ph->padlen = 4 - (optlen & 4);
57 ph->hdrlen = optlen / 8; 54 ph->hdrlen = optlen / 8;
58 ph->nexthdr = top_iph->protocol; 55 ph->nexthdr = top_iph->protocol;
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index 10499d2ec65e..fd840c7d75ea 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -17,17 +17,16 @@
17 * 17 *
18 * The IP header will be moved forward to make space for the encapsulation 18 * The IP header will be moved forward to make space for the encapsulation
19 * header. 19 * header.
20 *
21 * On exit, skb->h will be set to the start of the payload to be processed
22 * by x->type->output and skb->nh will be set to the top IP header.
23 */ 20 */
24static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb) 21static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
25{ 22{
26 struct iphdr *iph = ip_hdr(skb); 23 struct iphdr *iph = ip_hdr(skb);
27 int ihl = iph->ihl * 4; 24 int ihl = iph->ihl * 4;
28 25
29 skb->transport_header = skb->network_header + ihl;
30 skb_set_network_header(skb, -x->props.header_len); 26 skb_set_network_header(skb, -x->props.header_len);
27 skb->mac_header = skb->network_header +
28 offsetof(struct iphdr, protocol);
29 skb->transport_header = skb->network_header + ihl;
31 __skb_pull(skb, ihl); 30 __skb_pull(skb, ihl);
32 memmove(skb_network_header(skb), iph, ihl); 31 memmove(skb_network_header(skb), iph, ihl);
33 return 0; 32 return 0;
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index bac1a91f0cbe..f1d41ea34785 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -35,9 +35,6 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
35 * in it shall be filled in by x->type->output: 35 * in it shall be filled in by x->type->output:
36 * tot_len 36 * tot_len
37 * check 37 * check
38 *
39 * On exit, skb->h will be set to the start of the payload to be processed
40 * by x->type->output and skb->nh will be set to the top IP header.
41 */ 38 */
42static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 39static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
43{ 40{
@@ -47,9 +44,11 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
47 int flags; 44 int flags;
48 45
49 iph = ip_hdr(skb); 46 iph = ip_hdr(skb);
50 skb->transport_header = skb->network_header;
51 47
52 skb_set_network_header(skb, -x->props.header_len); 48 skb_set_network_header(skb, -x->props.header_len);
49 skb->mac_header = skb->network_header +
50 offsetof(struct iphdr, protocol);
51 skb->transport_header = skb->network_header + sizeof(*iph);
53 top_iph = ip_hdr(skb); 52 top_iph = ip_hdr(skb);
54 53
55 top_iph->ihl = 5; 54 top_iph->ihl = 5;
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index bca018d19ec6..42c6ef839e59 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -24,13 +24,6 @@
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: 25 * The following fields in it shall be filled in by x->type->output:
26 * payload_len 26 * payload_len
27 *
28 * On exit, skb->h will be set to the start of the encapsulation header to be
29 * filled in by x->type->output and the mac header will be set to the
30 * nextheader field of the extension header directly preceding the
31 * encapsulation header, or in its absence, that of the top IP header.
32 * The value of the network header will always point to the top IP header
33 * while skb->data will point to the payload.
34 */ 27 */
35static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) 28static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
36{ 29{
@@ -44,7 +37,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
44 37
45 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 38 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
46 skb_set_network_header(skb, -x->props.header_len); 39 skb_set_network_header(skb, -x->props.header_len);
47 skb_set_transport_header(skb, hdr_len - x->props.header_len); 40 skb->transport_header = skb->network_header + hdr_len;
48 __skb_pull(skb, hdr_len); 41 __skb_pull(skb, hdr_len);
49 42
50 top_iph = ipv6_hdr(skb); 43 top_iph = ipv6_hdr(skb);
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 5c29b367b432..957ae36b6695 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -37,13 +37,6 @@
37 * 37 *
38 * The IP header and mutable extension headers will be moved forward to make 38 * The IP header and mutable extension headers will be moved forward to make
39 * space for the route optimization header. 39 * space for the route optimization header.
40 *
41 * On exit, skb->h will be set to the start of the encapsulation header to be
42 * filled in by x->type->output and the mac header will be set to the
43 * nextheader field of the extension header directly preceding the
44 * encapsulation header, or in its absence, that of the top IP header.
45 * The value of the network header will always point to the top IP header
46 * while skb->data will point to the payload.
47 */ 40 */
48static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) 41static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
49{ 42{
@@ -56,7 +49,7 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
56 hdr_len = x->type->hdr_offset(x, skb, &prevhdr); 49 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
57 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 50 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
58 skb_set_network_header(skb, -x->props.header_len); 51 skb_set_network_header(skb, -x->props.header_len);
59 skb_set_transport_header(skb, hdr_len - x->props.header_len); 52 skb->transport_header = skb->network_header + hdr_len;
60 __skb_pull(skb, hdr_len); 53 __skb_pull(skb, hdr_len);
61 memmove(ipv6_hdr(skb), iph, hdr_len); 54 memmove(ipv6_hdr(skb), iph, hdr_len);
62 55
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index f2ee186494ed..4e344105b3fd 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -18,13 +18,6 @@
18 * 18 *
19 * The IP header and mutable extension headers will be moved forward to make 19 * The IP header and mutable extension headers will be moved forward to make
20 * space for the encapsulation header. 20 * space for the encapsulation header.
21 *
22 * On exit, skb->h will be set to the start of the encapsulation header to be
23 * filled in by x->type->output and the mac header will be set to the
24 * nextheader field of the extension header directly preceding the
25 * encapsulation header, or in its absence, that of the top IP header.
26 * The value of the network header will always point to the top IP header
27 * while skb->data will point to the payload.
28 */ 21 */
29static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) 22static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
30{ 23{
@@ -37,7 +30,7 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
37 hdr_len = x->type->hdr_offset(x, skb, &prevhdr); 30 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
38 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 31 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
39 skb_set_network_header(skb, -x->props.header_len); 32 skb_set_network_header(skb, -x->props.header_len);
40 skb_set_transport_header(skb, hdr_len - x->props.header_len); 33 skb->transport_header = skb->network_header + hdr_len;
41 __skb_pull(skb, hdr_len); 34 __skb_pull(skb, hdr_len);
42 memmove(ipv6_hdr(skb), iph, hdr_len); 35 memmove(ipv6_hdr(skb), iph, hdr_len);
43 return 0; 36 return 0;
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 01bd7d11ea1b..e79c6bdf71c1 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -36,13 +36,6 @@ static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb)
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. The following fields
37 * in it shall be filled in by x->type->output: 37 * in it shall be filled in by x->type->output:
38 * payload_len 38 * payload_len
39 *
40 * On exit, skb->h will be set to the start of the encapsulation header to be
41 * filled in by x->type->output and the mac header will be set to the
42 * nextheader field of the extension header directly preceding the
43 * encapsulation header, or in its absence, that of the top IP header.
44 * The value of the network header will always point to the top IP header
45 * while skb->data will point to the payload.
46 */ 39 */
47static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 40static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
48{ 41{
@@ -53,11 +46,10 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
53 46
54 iph = ipv6_hdr(skb); 47 iph = ipv6_hdr(skb);
55 48
56 skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr) -
57 x->props.header_len);
58 skb_set_network_header(skb, -x->props.header_len); 49 skb_set_network_header(skb, -x->props.header_len);
59 skb_set_transport_header(skb, sizeof(struct ipv6hdr) - 50 skb->mac_header = skb->network_header +
60 x->props.header_len); 51 offsetof(struct ipv6hdr, nexthdr);
52 skb->transport_header = skb->network_header + sizeof(*iph);
61 top_iph = ipv6_hdr(skb); 53 top_iph = ipv6_hdr(skb);
62 54
63 top_iph->version = 6; 55 top_iph->version = 6;