* [PATCH 1/7] [IPSEC] esp: Remove NAT-T checksum invalidation for BEET
2007-10-10 14:39 [0/7] IPsec: More input/output clean-ups Herbert Xu
@ 2007-10-10 14:40 ` Herbert Xu
2007-10-10 22:42 ` David Miller
2007-10-10 14:40 ` [PATCH 2/7] [IPSEC] beet: Fix extension header support on output Herbert Xu
` (5 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2007-10-10 14:40 UTC (permalink / raw)
To: David S. Miller, netdev, Herbert Xu
[IPSEC] esp: Remove NAT-T checksum invalidation for BEET
I pointed this out back when this patch was first proposed but it looks like
it got lost along the way.
The checksum only needs to be ignored for NAT-T in transport mode where
we lose the original inner addresses due to NAT. With BEET the inner
addresses will be intact so the checksum remains valid.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/esp4.c | 3 +--
1 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 452910d..1af332d 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -261,8 +261,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
* as per draft-ietf-ipsec-udp-encaps-06,
* section 3.1.2
*/
- if (x->props.mode == XFRM_MODE_TRANSPORT ||
- x->props.mode == XFRM_MODE_BEET)
+ if (x->props.mode == XFRM_MODE_TRANSPORT)
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 1/7] [IPSEC] esp: Remove NAT-T checksum invalidation for BEET
2007-10-10 14:40 ` [PATCH 1/7] [IPSEC] esp: Remove NAT-T checksum invalidation for BEET Herbert Xu
@ 2007-10-10 22:42 ` David Miller
0 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2007-10-10 22:42 UTC (permalink / raw)
To: herbert; +Cc: netdev
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 10 Oct 2007 22:40:10 +0800
> [IPSEC] esp: Remove NAT-T checksum invalidation for BEET
>
> I pointed this out back when this patch was first proposed but it looks like
> it got lost along the way.
>
> The checksum only needs to be ignored for NAT-T in transport mode where
> we lose the original inner addresses due to NAT. With BEET the inner
> addresses will be intact so the checksum remains valid.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Applied.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/7] [IPSEC] beet: Fix extension header support on output
2007-10-10 14:39 [0/7] IPsec: More input/output clean-ups Herbert Xu
2007-10-10 14:40 ` [PATCH 1/7] [IPSEC] esp: Remove NAT-T checksum invalidation for BEET Herbert Xu
@ 2007-10-10 14:40 ` Herbert Xu
2007-10-10 22:42 ` David Miller
2007-10-10 14:40 ` [PATCH 3/7] [IPSEC]: Set skb->data to payload in x->mode->output Herbert Xu
` (4 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2007-10-10 14:40 UTC (permalink / raw)
To: David S. Miller, netdev, Herbert Xu
[IPSEC] beet: Fix extension header support on output
The beet output function completely kills any extension headers by replacing
them with the IPv6 header. This is because it essentially ignores the
result of ip6_find_1stfragopt by simply acting as if there aren't any
extension headers.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv6/xfrm6_mode_beet.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 65e6b2a..d9366df 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -44,9 +44,9 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
memmove(skb->data, iph, hdr_len);
- skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr));
+ skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
skb_reset_network_header(skb);
- skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+ skb_set_transport_header(skb, hdr_len);
top_iph = ipv6_hdr(skb);
ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 3/7] [IPSEC]: Set skb->data to payload in x->mode->output
2007-10-10 14:39 [0/7] IPsec: More input/output clean-ups Herbert Xu
2007-10-10 14:40 ` [PATCH 1/7] [IPSEC] esp: Remove NAT-T checksum invalidation for BEET Herbert Xu
2007-10-10 14:40 ` [PATCH 2/7] [IPSEC] beet: Fix extension header support on output Herbert Xu
@ 2007-10-10 14:40 ` Herbert Xu
2007-10-10 22:44 ` David Miller
2007-10-10 14:40 ` [PATCH 4/7] [IPSEC]: Use IPv6 calling convention as the convention for x->mode->output Herbert Xu
` (3 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2007-10-10 14:40 UTC (permalink / raw)
To: David S. Miller, netdev, Herbert Xu
[IPSEC]: Set skb->data to payload in x->mode->output
This patch changes the calling convention so that on entry from
x->mode->output and before entry into x->type->output skb->data
will point to the payload instead of the IP header.
This is essentially a redistribution of skb_push/skb_pull calls
with the aim of minimising them on the common path of tunnel +
ESP.
It'll also let us use the same calling convention between IPv4
and IPv6 with the next patch.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/ah4.c | 1 +
net/ipv4/esp4.c | 6 ++----
net/ipv4/ipcomp.c | 1 +
net/ipv4/xfrm4_mode_beet.c | 5 +++--
net/ipv4/xfrm4_mode_transport.c | 4 ++--
net/ipv4/xfrm4_mode_tunnel.c | 3 +--
net/ipv4/xfrm4_tunnel.c | 1 +
net/ipv6/ah6.c | 1 +
net/ipv6/esp6.c | 9 ++-------
net/ipv6/ipcomp6.c | 5 ++++-
net/ipv6/mip6.c | 2 ++
net/ipv6/xfrm6_mode_beet.c | 13 +++++++------
net/ipv6/xfrm6_mode_ro.c | 12 ++++++------
net/ipv6/xfrm6_mode_transport.c | 12 ++++++------
net/ipv6/xfrm6_mode_tunnel.c | 13 +++++++------
net/ipv6/xfrm6_tunnel.c | 1 +
16 files changed, 47 insertions(+), 42 deletions(-)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 3513149..dbb1f11 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -66,6 +66,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
char buf[60];
} tmp_iph;
+ skb_push(skb, -skb_network_offset(skb));
top_iph = ip_hdr(skb);
iph = &tmp_iph.iph;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 1af332d..0f5e838 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -28,9 +28,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
int alen;
int nfrags;
- /* Strip IP+ESP header. */
- __skb_pull(skb, skb_transport_offset(skb));
- /* Now skb is pure payload to encrypt */
+ /* skb is pure payload to encrypt */
err = -ENOMEM;
@@ -60,7 +58,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
tail[clen - skb->len - 2] = (clen - skb->len) - 2;
pskb_put(skb, trailer, clen - skb->len);
- __skb_push(skb, -skb_network_offset(skb));
+ skb_push(skb, -skb_network_offset(skb));
top_iph = ip_hdr(skb);
esph = (struct ip_esp_hdr *)(skb_network_header(skb) +
top_iph->ihl * 4);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index e787044..1929d45 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -134,6 +134,7 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
int hdr_len = 0;
struct iphdr *iph = ip_hdr(skb);
+ skb_push(skb, -skb_network_offset(skb));
iph->tot_len = htons(skb->len);
hdr_len = iph->ihl * 4;
if ((skb->len - hdr_len) < ipcd->threshold) {
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index a73e710..77888f5 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -40,10 +40,11 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
if (unlikely(optlen))
hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
- skb_push(skb, x->props.header_len - IPV4_BEET_PHMAXLEN + hdrlen);
- skb_reset_network_header(skb);
+ skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len -
+ hdrlen);
top_iph = ip_hdr(skb);
skb->transport_header += sizeof(*iph) - hdrlen;
+ __skb_pull(skb, sizeof(*iph) - hdrlen);
memmove(top_iph, iph, sizeof(*iph));
if (unlikely(optlen)) {
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index 6010471..10499d2 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -27,8 +27,8 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
int ihl = iph->ihl * 4;
skb->transport_header = skb->network_header + ihl;
- skb_push(skb, x->props.header_len);
- skb_reset_network_header(skb);
+ skb_set_network_header(skb, -x->props.header_len);
+ __skb_pull(skb, ihl);
memmove(skb_network_header(skb), iph, ihl);
return 0;
}
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 9963700..bac1a91 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -49,8 +49,7 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
iph = ip_hdr(skb);
skb->transport_header = skb->network_header;
- skb_push(skb, x->props.header_len);
- skb_reset_network_header(skb);
+ skb_set_network_header(skb, -x->props.header_len);
top_iph = ip_hdr(skb);
top_iph->ihl = 5;
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 9275c79..be572f9 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -14,6 +14,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
+ skb_push(skb, -skb_network_offset(skb));
iph->tot_len = htons(skb->len);
ip_send_check(iph);
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index c51d775..ac6bae1 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -236,6 +236,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
char hdrs[0];
} *tmp_ext;
+ skb_push(skb, -skb_network_offset(skb));
top_iph = ipv6_hdr(skb);
top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 7355bb0..21c93f0 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -54,13 +54,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
int nfrags;
u8 *tail;
struct esp_data *esp = x->data;
- int hdr_len = (skb_transport_offset(skb) +
- sizeof(*esph) + esp->conf.ivlen);
- /* Strip IP+ESP header. */
- __skb_pull(skb, hdr_len);
-
- /* Now skb is pure payload to encrypt */
+ /* skb is pure payload to encrypt */
err = -ENOMEM;
/* Round to block size */
@@ -89,7 +84,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
tail[clen-skb->len - 2] = (clen - skb->len) - 2;
pskb_put(skb, trailer, clen - skb->len);
- __skb_push(skb, -skb_network_offset(skb));
+ skb_push(skb, -skb_network_offset(skb));
top_iph = ipv6_hdr(skb);
esph = (struct ipv6_esp_hdr *)skb_transport_header(skb);
top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 71a14c0..87e6407 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -128,7 +128,10 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
u8 *start, *scratch;
struct crypto_comp *tfm;
int cpu;
- int hdr_len = skb_transport_offset(skb);
+ int hdr_len;
+
+ skb_push(skb, -skb_network_offset(skb));
+ hdr_len = skb_transport_offset(skb);
/* check whether datagram len is larger than threshold */
if ((skb->len - hdr_len) < ipcd->threshold) {
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 6475bac..0e7a60f 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -153,6 +153,7 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
u8 nexthdr;
int len;
+ skb_push(skb, -skb_network_offset(skb));
iph = ipv6_hdr(skb);
iph->payload_len = htons(skb->len - sizeof(*iph));
@@ -367,6 +368,7 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
struct rt2_hdr *rt2;
u8 nexthdr;
+ skb_push(skb, -skb_network_offset(skb));
iph = ipv6_hdr(skb);
iph->payload_len = htons(skb->len - sizeof(*iph));
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index d9366df..bca018d 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -29,8 +29,8 @@
* filled in by x->type->output and the mac header will be set to the
* nextheader field of the extension header directly preceding the
* encapsulation header, or in its absence, that of the top IP header.
- * The value of skb->data and the network header will always point to the
- * top IP header.
+ * The value of the network header will always point to the top IP header
+ * while skb->data will point to the payload.
*/
static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -38,16 +38,17 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
u8 *prevhdr;
int hdr_len;
- skb_push(skb, x->props.header_len);
iph = ipv6_hdr(skb);
hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
- memmove(skb->data, iph, hdr_len);
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
- skb_reset_network_header(skb);
- skb_set_transport_header(skb, hdr_len);
+ skb_set_network_header(skb, -x->props.header_len);
+ skb_set_transport_header(skb, hdr_len - x->props.header_len);
+ __skb_pull(skb, hdr_len);
+
top_iph = ipv6_hdr(skb);
+ memmove(top_iph, iph, hdr_len);
ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 2575804..5c29b36 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -42,8 +42,8 @@
* filled in by x->type->output and the mac header will be set to the
* nextheader field of the extension header directly preceding the
* encapsulation header, or in its absence, that of the top IP header.
- * The value of skb->data and the network header will always point to the
- * top IP header.
+ * The value of the network header will always point to the top IP header
+ * while skb->data will point to the payload.
*/
static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -51,14 +51,14 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
u8 *prevhdr;
int hdr_len;
- skb_push(skb, x->props.header_len);
iph = ipv6_hdr(skb);
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
- skb_reset_network_header(skb);
- skb_set_transport_header(skb, hdr_len);
- memmove(skb->data, iph, hdr_len);
+ skb_set_network_header(skb, -x->props.header_len);
+ skb_set_transport_header(skb, hdr_len - x->props.header_len);
+ __skb_pull(skb, hdr_len);
+ memmove(ipv6_hdr(skb), iph, hdr_len);
x->lastused = get_seconds();
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index 65c166b..f2ee186 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -23,8 +23,8 @@
* filled in by x->type->output and the mac header will be set to the
* nextheader field of the extension header directly preceding the
* encapsulation header, or in its absence, that of the top IP header.
- * The value of skb->data and the network header will always point to the
- * top IP header.
+ * The value of the network header will always point to the top IP header
+ * while skb->data will point to the payload.
*/
static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -32,14 +32,14 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
u8 *prevhdr;
int hdr_len;
- skb_push(skb, x->props.header_len);
iph = ipv6_hdr(skb);
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
- skb_reset_network_header(skb);
- skb_set_transport_header(skb, hdr_len);
- memmove(skb->data, iph, hdr_len);
+ skb_set_network_header(skb, -x->props.header_len);
+ skb_set_transport_header(skb, hdr_len - x->props.header_len);
+ __skb_pull(skb, hdr_len);
+ memmove(ipv6_hdr(skb), iph, hdr_len);
return 0;
}
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 3dd40af..01bd7d1 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -41,8 +41,8 @@ static inline void ip6ip_ecn_decapsulate(struct sk_buff *skb)
* filled in by x->type->output and the mac header will be set to the
* nextheader field of the extension header directly preceding the
* encapsulation header, or in its absence, that of the top IP header.
- * The value of skb->data and the network header will always point to the
- * top IP header.
+ * The value of the network header will always point to the top IP header
+ * while skb->data will point to the payload.
*/
static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -51,12 +51,13 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
struct ipv6hdr *iph, *top_iph;
int dsfield;
- skb_push(skb, x->props.header_len);
iph = ipv6_hdr(skb);
- skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr));
- skb_reset_network_header(skb);
- skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+ skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr) -
+ x->props.header_len);
+ skb_set_network_header(skb, -x->props.header_len);
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr) -
+ x->props.header_len);
top_iph = ipv6_hdr(skb);
top_iph->version = 6;
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index aeb0607..00a1a3e 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -244,6 +244,7 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *top_iph;
+ skb_push(skb, -skb_network_offset(skb));
top_iph = ipv6_hdr(skb);
top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 3/7] [IPSEC]: Set skb->data to payload in x->mode->output
2007-10-10 14:40 ` [PATCH 3/7] [IPSEC]: Set skb->data to payload in x->mode->output Herbert Xu
@ 2007-10-10 22:44 ` David Miller
0 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2007-10-10 22:44 UTC (permalink / raw)
To: herbert; +Cc: netdev
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 10 Oct 2007 22:40:12 +0800
> [IPSEC]: Set skb->data to payload in x->mode->output
>
> This patch changes the calling convention so that on entry from
> x->mode->output and before entry into x->type->output skb->data
> will point to the payload instead of the IP header.
>
> This is essentially a redistribution of skb_push/skb_pull calls
> with the aim of minimising them on the common path of tunnel +
> ESP.
>
> It'll also let us use the same calling convention between IPv4
> and IPv6 with the next patch.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Applied.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 4/7] [IPSEC]: Use IPv6 calling convention as the convention for x->mode->output
2007-10-10 14:39 [0/7] IPsec: More input/output clean-ups Herbert Xu
` (2 preceding siblings ...)
2007-10-10 14:40 ` [PATCH 3/7] [IPSEC]: Set skb->data to payload in x->mode->output Herbert Xu
@ 2007-10-10 14:40 ` Herbert Xu
2007-10-10 22:44 ` David Miller
2007-10-10 14:40 ` [PATCH 5/7] [IPSEC]: Get rid of ipv6_{auth,esp,comp}_hdr Herbert Xu
` (2 subsequent siblings)
6 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2007-10-10 14:40 UTC (permalink / raw)
To: David S. Miller, netdev, Herbert Xu
[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>
---
include/net/xfrm.h | 12 ++++++++++++
net/ipv4/ah4.c | 6 +++---
net/ipv4/esp4.c | 11 +++++------
net/ipv4/ipcomp.c | 10 +++++-----
net/ipv4/xfrm4_mode_beet.c | 17 +++++++----------
net/ipv4/xfrm4_mode_transport.c | 7 +++----
net/ipv4/xfrm4_mode_tunnel.c | 7 +++----
net/ipv6/xfrm6_mode_beet.c | 9 +--------
net/ipv6/xfrm6_mode_ro.c | 9 +--------
net/ipv6/xfrm6_mode_transport.c | 9 +--------
net/ipv6/xfrm6_mode_tunnel.c | 14 +++-----------
11 files changed, 44 insertions(+), 67 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 1c116dc..77be396 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -300,6 +300,18 @@ extern void xfrm_put_type(struct xfrm_type *type);
struct xfrm_mode {
int (*input)(struct xfrm_state *x, struct sk_buff *skb);
+
+ /*
+ * Add encapsulation header.
+ *
+ * On exit, the transport header will be set to the start of the
+ * encapsulation header to be filled in by x->type->output and
+ * the mac header will be set to the nextheader (protocol for
+ * IPv4) field of the extension header directly preceding the
+ * encapsulation header, or in its absence, that of the top IP
+ * header. The value of the network header will always point
+ * to the top IP header while skb->data will point to the payload.
+ */
int (*output)(struct xfrm_state *x,struct sk_buff *skb);
struct module *owner;
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index dbb1f11..e4f7aa3 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)
goto error;
}
- ah = (struct ip_auth_hdr *)((char *)top_iph+top_iph->ihl*4);
- ah->nexthdr = top_iph->protocol;
+ ah = (struct ip_auth_hdr *)skb_transport_header(skb);
+ ah->nexthdr = *skb_mac_header(skb);
+ *skb_mac_header(skb) = IPPROTO_AH;
top_iph->tos = 0;
top_iph->tot_len = htons(skb->len);
top_iph->frag_off = 0;
top_iph->ttl = 0;
- top_iph->protocol = IPPROTO_AH;
top_iph->check = 0;
ahp = x->data;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 0f5e838..93153d1 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)
skb_push(skb, -skb_network_offset(skb));
top_iph = ip_hdr(skb);
- esph = (struct ip_esp_hdr *)(skb_network_header(skb) +
- top_iph->ihl * 4);
+ esph = (struct ip_esp_hdr *)skb_transport_header(skb);
top_iph->tot_len = htons(skb->len + alen);
- *(skb_tail_pointer(trailer) - 1) = top_iph->protocol;
+ *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
+ *skb_mac_header(skb) = IPPROTO_ESP;
spin_lock_bh(&x->lock);
@@ -91,9 +91,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
break;
}
- top_iph->protocol = IPPROTO_UDP;
- } else
- top_iph->protocol = IPPROTO_ESP;
+ *skb_mac_header(skb) = IPPROTO_UDP;
+ }
esph->spi = x->id.spi;
esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 1929d45..bf74f64 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -98,10 +98,10 @@ out:
static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipcomp_data *ipcd = x->data;
- const int ihlen = ip_hdrlen(skb);
+ const int ihlen = skb_transport_offset(skb);
const int plen = skb->len - ihlen;
int dlen = IPCOMP_SCRATCH_SIZE;
- u8 *start = skb->data + ihlen;
+ u8 *start = skb_transport_header(skb);
const int cpu = get_cpu();
u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
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)
/* Install ipcomp header, convert into ipcomp datagram. */
iph->tot_len = htons(skb->len);
- ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4);
- ipch->nexthdr = iph->protocol;
+ ipch = (struct ip_comp_hdr *)skb_transport_header(skb);
+ ipch->nexthdr = *skb_mac_header(skb);
ipch->flags = 0;
ipch->cpi = htons((u16 )ntohl(x->id.spi));
- iph->protocol = IPPROTO_COMP;
+ *skb_mac_header(skb) = IPPROTO_COMP;
ip_send_check(iph);
return 0;
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 77888f5..7226c64 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -23,17 +23,14 @@
* The following fields in it shall be filled in by x->type->output:
* tot_len
* check
- *
- * On exit, skb->h will be set to the start of the payload to be processed
- * by x->type->output and skb->nh will be set to the top IP header.
*/
static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
+ struct ip_beet_phdr *ph;
struct iphdr *iph, *top_iph;
int hdrlen, optlen;
iph = ip_hdr(skb);
- skb->transport_header = skb->network_header;
hdrlen = 0;
optlen = iph->ihl * 4 - sizeof(*iph);
@@ -42,17 +39,17 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len -
hdrlen);
- top_iph = ip_hdr(skb);
- skb->transport_header += sizeof(*iph) - hdrlen;
- __skb_pull(skb, sizeof(*iph) - hdrlen);
+ skb->mac_header = skb->network_header +
+ offsetof(struct iphdr, protocol);
+ skb->transport_header = skb->network_header + sizeof(*iph);
+
+ ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);
+ top_iph = ip_hdr(skb);
memmove(top_iph, iph, sizeof(*iph));
if (unlikely(optlen)) {
- struct ip_beet_phdr *ph;
-
BUG_ON(optlen < 0);
- ph = (struct ip_beet_phdr *)skb_transport_header(skb);
ph->padlen = 4 - (optlen & 4);
ph->hdrlen = optlen / 8;
ph->nexthdr = top_iph->protocol;
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
index 10499d2..fd840c7 100644
--- a/net/ipv4/xfrm4_mode_transport.c
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -17,17 +17,16 @@
*
* The IP header will be moved forward to make space for the encapsulation
* header.
- *
- * On exit, skb->h will be set to the start of the payload to be processed
- * by x->type->output and skb->nh will be set to the top IP header.
*/
static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
int ihl = iph->ihl * 4;
- skb->transport_header = skb->network_header + ihl;
skb_set_network_header(skb, -x->props.header_len);
+ skb->mac_header = skb->network_header +
+ offsetof(struct iphdr, protocol);
+ skb->transport_header = skb->network_header + ihl;
__skb_pull(skb, ihl);
memmove(skb_network_header(skb), iph, ihl);
return 0;
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index bac1a91..f1d41ea 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)
* in it shall be filled in by x->type->output:
* tot_len
* check
- *
- * On exit, skb->h will be set to the start of the payload to be processed
- * by x->type->output and skb->nh will be set to the top IP header.
*/
static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -47,9 +44,11 @@ static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
int flags;
iph = ip_hdr(skb);
- skb->transport_header = skb->network_header;
skb_set_network_header(skb, -x->props.header_len);
+ skb->mac_header = skb->network_header +
+ offsetof(struct iphdr, protocol);
+ skb->transport_header = skb->network_header + sizeof(*iph);
top_iph = ip_hdr(skb);
top_iph->ihl = 5;
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index bca018d..42c6ef8 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -24,13 +24,6 @@
* The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
* The following fields in it shall be filled in by x->type->output:
* payload_len
- *
- * On exit, skb->h will be set to the start of the encapsulation header to be
- * filled in by x->type->output and the mac header will be set to the
- * nextheader field of the extension header directly preceding the
- * encapsulation header, or in its absence, that of the top IP header.
- * The value of the network header will always point to the top IP header
- * while skb->data will point to the payload.
*/
static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -44,7 +37,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
skb_set_network_header(skb, -x->props.header_len);
- skb_set_transport_header(skb, hdr_len - x->props.header_len);
+ skb->transport_header = skb->network_header + hdr_len;
__skb_pull(skb, hdr_len);
top_iph = ipv6_hdr(skb);
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
index 5c29b36..957ae36 100644
--- a/net/ipv6/xfrm6_mode_ro.c
+++ b/net/ipv6/xfrm6_mode_ro.c
@@ -37,13 +37,6 @@
*
* The IP header and mutable extension headers will be moved forward to make
* space for the route optimization header.
- *
- * On exit, skb->h will be set to the start of the encapsulation header to be
- * filled in by x->type->output and the mac header will be set to the
- * nextheader field of the extension header directly preceding the
- * encapsulation header, or in its absence, that of the top IP header.
- * The value of the network header will always point to the top IP header
- * while skb->data will point to the payload.
*/
static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -56,7 +49,7 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
skb_set_network_header(skb, -x->props.header_len);
- skb_set_transport_header(skb, hdr_len - x->props.header_len);
+ skb->transport_header = skb->network_header + hdr_len;
__skb_pull(skb, hdr_len);
memmove(ipv6_hdr(skb), iph, hdr_len);
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
index f2ee186..4e34410 100644
--- a/net/ipv6/xfrm6_mode_transport.c
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -18,13 +18,6 @@
*
* The IP header and mutable extension headers will be moved forward to make
* space for the encapsulation header.
- *
- * On exit, skb->h will be set to the start of the encapsulation header to be
- * filled in by x->type->output and the mac header will be set to the
- * nextheader field of the extension header directly preceding the
- * encapsulation header, or in its absence, that of the top IP header.
- * The value of the network header will always point to the top IP header
- * while skb->data will point to the payload.
*/
static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -37,7 +30,7 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
skb_set_network_header(skb, -x->props.header_len);
- skb_set_transport_header(skb, hdr_len - x->props.header_len);
+ skb->transport_header = skb->network_header + hdr_len;
__skb_pull(skb, hdr_len);
memmove(ipv6_hdr(skb), iph, hdr_len);
return 0;
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 01bd7d1..e79c6bd 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)
* The top IP header will be constructed per RFC 2401. The following fields
* in it shall be filled in by x->type->output:
* payload_len
- *
- * On exit, skb->h will be set to the start of the encapsulation header to be
- * filled in by x->type->output and the mac header will be set to the
- * nextheader field of the extension header directly preceding the
- * encapsulation header, or in its absence, that of the top IP header.
- * The value of the network header will always point to the top IP header
- * while skb->data will point to the payload.
*/
static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -53,11 +46,10 @@ static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
iph = ipv6_hdr(skb);
- skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr) -
- x->props.header_len);
skb_set_network_header(skb, -x->props.header_len);
- skb_set_transport_header(skb, sizeof(struct ipv6hdr) -
- x->props.header_len);
+ skb->mac_header = skb->network_header +
+ offsetof(struct ipv6hdr, nexthdr);
+ skb->transport_header = skb->network_header + sizeof(*iph);
top_iph = ipv6_hdr(skb);
top_iph->version = 6;
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 4/7] [IPSEC]: Use IPv6 calling convention as the convention for x->mode->output
2007-10-10 14:40 ` [PATCH 4/7] [IPSEC]: Use IPv6 calling convention as the convention for x->mode->output Herbert Xu
@ 2007-10-10 22:44 ` David Miller
0 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2007-10-10 22:44 UTC (permalink / raw)
To: herbert; +Cc: netdev
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 10 Oct 2007 22:40:13 +0800
> [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>
Applied.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 5/7] [IPSEC]: Get rid of ipv6_{auth,esp,comp}_hdr
2007-10-10 14:39 [0/7] IPsec: More input/output clean-ups Herbert Xu
` (3 preceding siblings ...)
2007-10-10 14:40 ` [PATCH 4/7] [IPSEC]: Use IPv6 calling convention as the convention for x->mode->output Herbert Xu
@ 2007-10-10 14:40 ` Herbert Xu
2007-10-10 22:45 ` David Miller
2007-10-10 14:40 ` [PATCH 6/7] [IPSEC]: Move IP length/checksum setting out of transforms Herbert Xu
2007-10-10 14:40 ` [PATCH 7/7] [IPSEC]: Move IP protocol setting from transforms into xfrm4_input.c Herbert Xu
6 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2007-10-10 14:40 UTC (permalink / raw)
To: David S. Miller, netdev, Herbert Xu
[IPSEC]: Get rid of ipv6_{auth,esp,comp}_hdr
This patch removes the duplicate ipv6_{auth,esp,comp}_hdr structures since
they're identical to the IPv4 versions. Duplicating them would only create
problems for ourselves later when we need to add things like extended
sequence numbers.
I've also added transport header type conversion headers for these types
which are now used by the transforms.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/linux/ipv6.h | 21 ---------------------
include/net/ah.h | 7 +++++++
include/net/esp.h | 7 +++++++
include/net/ipcomp.h | 11 ++++++++++-
net/ipv4/ah4.c | 18 +++++++++---------
net/ipv4/esp4.c | 10 +++++-----
net/ipv4/ipcomp.c | 2 +-
net/ipv6/ah6.c | 16 ++++++++--------
net/ipv6/esp6.c | 18 +++++++++---------
net/ipv6/ipcomp6.c | 17 ++++++++---------
10 files changed, 64 insertions(+), 63 deletions(-)
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 4ca60c3..5d35a4c 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -96,27 +96,6 @@ struct ipv6_destopt_hao {
struct in6_addr addr;
} __attribute__ ((__packed__));
-struct ipv6_auth_hdr {
- __u8 nexthdr;
- __u8 hdrlen; /* This one is measured in 32 bit units! */
- __be16 reserved;
- __be32 spi;
- __be32 seq_no; /* Sequence number */
- __u8 auth_data[0]; /* Length variable but >=4. Mind the 64 bit alignment! */
-};
-
-struct ipv6_esp_hdr {
- __be32 spi;
- __be32 seq_no; /* Sequence number */
- __u8 enc_data[0]; /* Length variable but >=8. Mind the 64 bit alignment! */
-};
-
-struct ipv6_comp_hdr {
- __u8 nexthdr;
- __u8 flags;
- __be16 cpi;
-};
-
/*
* IPv6 fixed header
*
diff --git a/include/net/ah.h b/include/net/ah.h
index 5e758c2..ae1c322 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -38,4 +38,11 @@ out:
return err;
}
+struct ip_auth_hdr;
+
+static inline struct ip_auth_hdr *ip_auth_hdr(const struct sk_buff *skb)
+{
+ return (struct ip_auth_hdr *)skb_transport_header(skb);
+}
+
#endif
diff --git a/include/net/esp.h b/include/net/esp.h
index e793d76..c1bc529 100644
--- a/include/net/esp.h
+++ b/include/net/esp.h
@@ -53,4 +53,11 @@ static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb,
return crypto_hash_final(&desc, esp->auth.work_icv);
}
+struct ip_esp_hdr;
+
+static inline struct ip_esp_hdr *ip_esp_hdr(const struct sk_buff *skb)
+{
+ return (struct ip_esp_hdr *)skb_transport_header(skb);
+}
+
#endif
diff --git a/include/net/ipcomp.h b/include/net/ipcomp.h
index 87c1af3..330b74e 100644
--- a/include/net/ipcomp.h
+++ b/include/net/ipcomp.h
@@ -1,14 +1,23 @@
#ifndef _NET_IPCOMP_H
#define _NET_IPCOMP_H
-#include <linux/crypto.h>
#include <linux/types.h>
#define IPCOMP_SCRATCH_SIZE 65400
+struct crypto_comp;
+
struct ipcomp_data {
u16 threshold;
struct crypto_comp **tfms;
};
+struct ip_comp_hdr;
+struct sk_buff;
+
+static inline struct ip_comp_hdr *ip_comp_hdr(const struct sk_buff *skb)
+{
+ return (struct ip_comp_hdr *)skb_transport_header(skb);
+}
+
#endif
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e4f7aa3..d697064 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -82,7 +82,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
goto error;
}
- ah = (struct ip_auth_hdr *)skb_transport_header(skb);
+ ah = ip_auth_hdr(skb);
ah->nexthdr = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_AH;
@@ -93,8 +93,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->check = 0;
ahp = x->data;
- ah->hdrlen = (XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
- ahp->icv_trunc_len) >> 2) - 2;
+ ah->hdrlen = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
ah->reserved = 0;
ah->spi = x->id.spi;
@@ -134,15 +133,15 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
struct ah_data *ahp;
char work_buf[60];
- if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
+ if (!pskb_may_pull(skb, sizeof(*ah)))
goto out;
- ah = (struct ip_auth_hdr*)skb->data;
+ ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
ah_hlen = (ah->hdrlen + 2) << 2;
- if (ah_hlen != XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_full_len) &&
- ah_hlen != XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len))
+ if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
+ ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len))
goto out;
if (!pskb_may_pull(skb, ah_hlen))
@@ -156,7 +155,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
- ah = (struct ip_auth_hdr*)skb->data;
+ ah = (struct ip_auth_hdr *)skb->data;
iph = ip_hdr(skb);
ihl = skb->data - skb_network_header(skb);
@@ -266,7 +265,8 @@ static int ah_init_state(struct xfrm_state *x)
if (!ahp->work_icv)
goto error;
- x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len);
+ x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
+ ahp->icv_trunc_len);
if (x->props.mode == XFRM_MODE_TUNNEL)
x->props.header_len += sizeof(struct iphdr);
x->data = ahp;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 93153d1..66eb496 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -60,7 +60,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
skb_push(skb, -skb_network_offset(skb));
top_iph = ip_hdr(skb);
- esph = (struct ip_esp_hdr *)skb_transport_header(skb);
+ esph = ip_esp_hdr(skb);
top_iph->tot_len = htons(skb->len + alen);
*(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_ESP;
@@ -157,7 +157,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
struct sk_buff *trailer;
int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
int alen = esp->auth.icv_trunc_len;
- int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
+ int elen = skb->len - sizeof(*esph) - esp->conf.ivlen - alen;
int nfrags;
int ihl;
u8 nexthdr[2];
@@ -165,7 +165,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
int padlen;
int err;
- if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
+ if (!pskb_may_pull(skb, sizeof(*esph)))
goto out;
if (elen <= 0 || (elen & (blksize-1)))
@@ -193,7 +193,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
- esph = (struct ip_esp_hdr*)skb->data;
+ esph = (struct ip_esp_hdr *)skb->data;
/* Get ivec. This can be wrong, check against another impls. */
if (esp->conf.ivlen)
@@ -206,7 +206,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
if (!sg)
goto out;
}
- skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen);
+ skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen, elen);
err = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index bf74f64..78d6ddb 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -154,7 +154,7 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
/* Install ipcomp header, convert into ipcomp datagram. */
iph->tot_len = htons(skb->len);
- ipch = (struct ip_comp_hdr *)skb_transport_header(skb);
+ ipch = ip_comp_hdr(skb);
ipch->nexthdr = *skb_mac_header(skb);
ipch->flags = 0;
ipch->cpi = htons((u16 )ntohl(x->id.spi));
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index ac6bae1..f9f6891 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -270,7 +270,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
goto error_free_iph;
}
- ah = (struct ip_auth_hdr *)skb_transport_header(skb);
+ ah = ip_auth_hdr(skb);
ah->nexthdr = nexthdr;
top_iph->priority = 0;
@@ -280,8 +280,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->hop_limit = 0;
ahp = x->data;
- ah->hdrlen = (XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) +
- ahp->icv_trunc_len) >> 2) - 2;
+ ah->hdrlen = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
ah->reserved = 0;
ah->spi = x->id.spi;
@@ -327,7 +326,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
* There is offset of AH before IPv6 header after the process.
*/
- struct ipv6_auth_hdr *ah;
+ struct ip_auth_hdr *ah;
struct ipv6hdr *ip6h;
struct ah_data *ahp;
unsigned char *tmp_hdr = NULL;
@@ -346,13 +345,13 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
goto out;
hdr_len = skb->data - skb_network_header(skb);
- ah = (struct ipv6_auth_hdr*)skb->data;
+ ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
nexthdr = ah->nexthdr;
ah_hlen = (ah->hdrlen + 2) << 2;
- if (ah_hlen != XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_full_len) &&
- ah_hlen != XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len))
+ if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
+ ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len))
goto out;
if (!pskb_may_pull(skb, ah_hlen))
@@ -474,7 +473,8 @@ static int ah6_init_state(struct xfrm_state *x)
if (!ahp->work_icv)
goto error;
- x->props.header_len = XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len);
+ x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
+ ahp->icv_trunc_len);
if (x->props.mode == XFRM_MODE_TUNNEL)
x->props.header_len += sizeof(struct ipv6hdr);
x->data = ahp;
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 21c93f0..a64295d 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -44,7 +44,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
struct ipv6hdr *top_iph;
- struct ipv6_esp_hdr *esph;
+ struct ip_esp_hdr *esph;
struct crypto_blkcipher *tfm;
struct blkcipher_desc desc;
struct sk_buff *trailer;
@@ -86,7 +86,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
skb_push(skb, -skb_network_offset(skb));
top_iph = ipv6_hdr(skb);
- esph = (struct ipv6_esp_hdr *)skb_transport_header(skb);
+ esph = ip_esp_hdr(skb);
top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
*(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_ESP;
@@ -142,19 +142,19 @@ error:
static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *iph;
- struct ipv6_esp_hdr *esph;
+ struct ip_esp_hdr *esph;
struct esp_data *esp = x->data;
struct crypto_blkcipher *tfm = esp->conf.tfm;
struct blkcipher_desc desc = { .tfm = tfm };
struct sk_buff *trailer;
int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4);
int alen = esp->auth.icv_trunc_len;
- int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen;
+ int elen = skb->len - sizeof(*esph) - esp->conf.ivlen - alen;
int hdr_len = skb_network_header_len(skb);
int nfrags;
int ret = 0;
- if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) {
+ if (!pskb_may_pull(skb, sizeof(*esph))) {
ret = -EINVAL;
goto out;
}
@@ -189,7 +189,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
- esph = (struct ipv6_esp_hdr*)skb->data;
+ esph = (struct ip_esp_hdr *)skb->data;
iph = ipv6_hdr(skb);
/* Get ivec. This can be wrong, check against another impls. */
@@ -208,7 +208,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
goto out;
}
}
- skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen);
+ skb_to_sgvec(skb, sg, sizeof(*esph) + esp->conf.ivlen, elen);
ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen);
if (unlikely(sg != &esp->sgbuf[0]))
kfree(sg);
@@ -260,7 +260,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
int type, int code, int offset, __be32 info)
{
struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
- struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset);
+ struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
struct xfrm_state *x;
if (type != ICMPV6_DEST_UNREACH &&
@@ -356,7 +356,7 @@ static int esp6_init_state(struct xfrm_state *x)
if (crypto_blkcipher_setkey(tfm, x->ealg->alg_key,
(x->ealg->alg_key_len + 7) / 8))
goto error;
- x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
+ x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
if (x->props.mode == XFRM_MODE_TUNNEL)
x->props.header_len += sizeof(struct ipv6hdr);
x->data = esp;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 87e6407..8f3f32f 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -65,7 +65,7 @@ static LIST_HEAD(ipcomp6_tfms_list);
static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
{
int err = -ENOMEM;
- struct ipv6_comp_hdr *ipch;
+ struct ip_comp_hdr *ipch;
int plen, dlen;
struct ipcomp_data *ipcd = x->data;
u8 *start, *scratch;
@@ -92,12 +92,10 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
tfm = *per_cpu_ptr(ipcd->tfms, cpu);
err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen);
- if (err) {
- err = -EINVAL;
+ if (err)
goto out_put_cpu;
- }
- if (dlen < (plen + sizeof(struct ipv6_comp_hdr))) {
+ if (dlen < (plen + sizeof(*ipch))) {
err = -EINVAL;
goto out_put_cpu;
}
@@ -122,7 +120,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
struct ipv6hdr *top_iph;
- struct ipv6_comp_hdr *ipch;
+ struct ip_comp_hdr *ipch;
struct ipcomp_data *ipcd = x->data;
int plen, dlen;
u8 *start, *scratch;
@@ -151,7 +149,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
tfm = *per_cpu_ptr(ipcd->tfms, cpu);
err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
- if (err || (dlen + sizeof(struct ipv6_comp_hdr)) >= plen) {
+ if (err || (dlen + sizeof(*ipch)) >= plen) {
put_cpu();
goto out_ok;
}
@@ -164,7 +162,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
- ipch = (struct ipv6_comp_hdr *)start;
+ ipch = ip_comp_hdr(skb);
ipch->nexthdr = *skb_mac_header(skb);
ipch->flags = 0;
ipch->cpi = htons((u16 )ntohl(x->id.spi));
@@ -179,7 +177,8 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
{
__be32 spi;
struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
- struct ipv6_comp_hdr *ipcomph = (struct ipv6_comp_hdr*)(skb->data+offset);
+ struct ip_comp_hdr *ipcomph =
+ (struct ip_comp_hdr *)(skb->data + offset);
struct xfrm_state *x;
if (type != ICMPV6_DEST_UNREACH && type != ICMPV6_PKT_TOOBIG)
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 5/7] [IPSEC]: Get rid of ipv6_{auth,esp,comp}_hdr
2007-10-10 14:40 ` [PATCH 5/7] [IPSEC]: Get rid of ipv6_{auth,esp,comp}_hdr Herbert Xu
@ 2007-10-10 22:45 ` David Miller
0 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2007-10-10 22:45 UTC (permalink / raw)
To: herbert; +Cc: netdev
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 10 Oct 2007 22:40:14 +0800
> [IPSEC]: Get rid of ipv6_{auth,esp,comp}_hdr
>
> This patch removes the duplicate ipv6_{auth,esp,comp}_hdr structures since
> they're identical to the IPv4 versions. Duplicating them would only create
> problems for ourselves later when we need to add things like extended
> sequence numbers.
>
> I've also added transport header type conversion headers for these types
> which are now used by the transforms.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Applied.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 6/7] [IPSEC]: Move IP length/checksum setting out of transforms
2007-10-10 14:39 [0/7] IPsec: More input/output clean-ups Herbert Xu
` (4 preceding siblings ...)
2007-10-10 14:40 ` [PATCH 5/7] [IPSEC]: Get rid of ipv6_{auth,esp,comp}_hdr Herbert Xu
@ 2007-10-10 14:40 ` Herbert Xu
2007-10-10 22:46 ` David Miller
2007-10-10 14:40 ` [PATCH 7/7] [IPSEC]: Move IP protocol setting from transforms into xfrm4_input.c Herbert Xu
6 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2007-10-10 14:40 UTC (permalink / raw)
To: David S. Miller, netdev, Herbert Xu
[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>
---
net/ipv4/ah4.c | 2 --
net/ipv4/esp4.c | 7 +------
net/ipv4/ipcomp.c | 22 +++++-----------------
net/ipv4/xfrm4_mode_beet.c | 3 ---
net/ipv4/xfrm4_mode_tunnel.c | 5 +----
net/ipv4/xfrm4_output.c | 5 +++++
net/ipv4/xfrm4_tunnel.c | 5 -----
net/ipv6/esp6.c | 3 ---
net/ipv6/ipcomp6.c | 19 ++++++-------------
net/ipv6/mip6.c | 2 --
net/ipv6/xfrm6_mode_beet.c | 2 --
net/ipv6/xfrm6_mode_tunnel.c | 4 +---
net/ipv6/xfrm6_output.c | 4 ++++
net/ipv6/xfrm6_tunnel.c | 5 -----
14 files changed, 23 insertions(+), 65 deletions(-)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index d697064..60925fe 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)
memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
}
- ip_send_check(top_iph);
-
err = 0;
error:
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 66eb496..8377bed 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -16,7 +16,6 @@
static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- struct iphdr *top_iph;
struct ip_esp_hdr *esph;
struct crypto_blkcipher *tfm;
struct blkcipher_desc desc;
@@ -59,9 +58,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
pskb_put(skb, trailer, clen - skb->len);
skb_push(skb, -skb_network_offset(skb));
- top_iph = ip_hdr(skb);
esph = ip_esp_hdr(skb);
- top_iph->tot_len = htons(skb->len + alen);
*(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_ESP;
@@ -76,7 +73,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
uh = (struct udphdr *)esph;
uh->source = encap->encap_sport;
uh->dest = encap->encap_dport;
- uh->len = htons(skb->len + alen - top_iph->ihl*4);
+ uh->len = htons(skb->len + alen - skb_transport_offset(skb));
uh->check = 0;
switch (encap->encap_type) {
@@ -136,8 +133,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
unlock:
spin_unlock_bh(&x->lock);
- ip_send_check(top_iph);
-
error:
return err;
}
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 78d6ddb..32b02de 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -98,10 +98,9 @@ out:
static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipcomp_data *ipcd = x->data;
- const int ihlen = skb_transport_offset(skb);
- const int plen = skb->len - ihlen;
+ const int plen = skb->len;
int dlen = IPCOMP_SCRATCH_SIZE;
- u8 *start = skb_transport_header(skb);
+ u8 *start = skb->data;
const int cpu = get_cpu();
u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
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)
memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
put_cpu();
- pskb_trim(skb, ihlen + dlen + sizeof(struct ip_comp_hdr));
+ pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
return 0;
out:
@@ -131,13 +130,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
int err;
struct ip_comp_hdr *ipch;
struct ipcomp_data *ipcd = x->data;
- int hdr_len = 0;
- struct iphdr *iph = ip_hdr(skb);
- skb_push(skb, -skb_network_offset(skb));
- iph->tot_len = htons(skb->len);
- hdr_len = iph->ihl * 4;
- if ((skb->len - hdr_len) < ipcd->threshold) {
+ if (skb->len < ipcd->threshold) {
/* Don't bother compressing */
goto out_ok;
}
@@ -146,25 +140,19 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
goto out_ok;
err = ipcomp_compress(x, skb);
- iph = ip_hdr(skb);
if (err) {
goto out_ok;
}
/* Install ipcomp header, convert into ipcomp datagram. */
- iph->tot_len = htons(skb->len);
ipch = ip_comp_hdr(skb);
ipch->nexthdr = *skb_mac_header(skb);
ipch->flags = 0;
ipch->cpi = htons((u16 )ntohl(x->id.spi));
*skb_mac_header(skb) = IPPROTO_COMP;
- ip_send_check(iph);
- return 0;
-
out_ok:
- if (x->props.mode == XFRM_MODE_TUNNEL)
- ip_send_check(iph);
+ skb_push(skb, -skb_network_offset(skb));
return 0;
}
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 7226c64..73d2338 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -20,9 +20,6 @@
/* Add encapsulation header.
*
* The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
- * The following fields in it shall be filled in by x->type->output:
- * tot_len
- * check
*/
static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index f1d41ea..1ae9d32 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)
/* Add encapsulation header.
*
- * The top IP header will be constructed per RFC 2401. The following fields
- * in it shall be filled in by x->type->output:
- * tot_len
- * check
+ * The top IP header will be constructed per RFC 2401.
*/
static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 04805c7..434ef30 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)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
+ struct iphdr *iph;
int err;
if (x->props.mode == XFRM_MODE_TUNNEL) {
@@ -56,6 +57,10 @@ static inline int xfrm4_output_one(struct sk_buff *skb)
if (err)
goto error_nolock;
+ iph = ip_hdr(skb);
+ iph->tot_len = htons(skb->len);
+ ip_send_check(iph);
+
IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
err = 0;
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index be572f9..e1fafc1 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -12,12 +12,7 @@
static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
{
- struct iphdr *iph = ip_hdr(skb);
-
skb_push(skb, -skb_network_offset(skb));
- iph->tot_len = htons(skb->len);
- ip_send_check(iph);
-
return 0;
}
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index a64295d..9eb9285 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -43,7 +43,6 @@
static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- struct ipv6hdr *top_iph;
struct ip_esp_hdr *esph;
struct crypto_blkcipher *tfm;
struct blkcipher_desc desc;
@@ -85,9 +84,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
pskb_put(skb, trailer, clen - skb->len);
skb_push(skb, -skb_network_offset(skb));
- top_iph = ipv6_hdr(skb);
esph = ip_esp_hdr(skb);
- top_iph->payload_len = htons(skb->len + alen - sizeof(*top_iph));
*(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_ESP;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 8f3f32f..28fc8ed 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -119,20 +119,15 @@ out:
static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
- struct ipv6hdr *top_iph;
struct ip_comp_hdr *ipch;
struct ipcomp_data *ipcd = x->data;
int plen, dlen;
u8 *start, *scratch;
struct crypto_comp *tfm;
int cpu;
- int hdr_len;
-
- skb_push(skb, -skb_network_offset(skb));
- hdr_len = skb_transport_offset(skb);
/* check whether datagram len is larger than threshold */
- if ((skb->len - hdr_len) < ipcd->threshold) {
+ if (skb->len < ipcd->threshold) {
goto out_ok;
}
@@ -140,9 +135,9 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
goto out_ok;
/* compression */
- plen = skb->len - hdr_len;
+ plen = skb->len;
dlen = IPCOMP_SCRATCH_SIZE;
- start = skb_transport_header(skb);
+ start = skb->data;
cpu = get_cpu();
scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
@@ -155,13 +150,9 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
}
memcpy(start + sizeof(struct ip_comp_hdr), scratch, dlen);
put_cpu();
- pskb_trim(skb, hdr_len + dlen + sizeof(struct ip_comp_hdr));
+ pskb_trim(skb, dlen + sizeof(struct ip_comp_hdr));
/* insert ipcomp header and replace datagram */
- top_iph = ipv6_hdr(skb);
-
- top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
-
ipch = ip_comp_hdr(skb);
ipch->nexthdr = *skb_mac_header(skb);
ipch->flags = 0;
@@ -169,6 +160,8 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
*skb_mac_header(skb) = IPPROTO_COMP;
out_ok:
+ skb_push(skb, -skb_network_offset(skb));
+
return 0;
}
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 0e7a60f..7fd841d 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)
skb_push(skb, -skb_network_offset(skb));
iph = ipv6_hdr(skb);
- iph->payload_len = htons(skb->len - sizeof(*iph));
nexthdr = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_DSTOPTS;
@@ -370,7 +369,6 @@ static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb)
skb_push(skb, -skb_network_offset(skb));
iph = ipv6_hdr(skb);
- iph->payload_len = htons(skb->len - sizeof(*iph));
nexthdr = *skb_mac_header(skb);
*skb_mac_header(skb) = IPPROTO_ROUTING;
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 42c6ef8..13bb1e8 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -22,8 +22,6 @@
/* Add encapsulation header.
*
* The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
- * The following fields in it shall be filled in by x->type->output:
- * payload_len
*/
static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
{
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index e79c6bd..ea22838 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)
/* Add encapsulation header.
*
- * The top IP header will be constructed per RFC 2401. The following fields
- * in it shall be filled in by x->type->output:
- * payload_len
+ * The top IP header will be constructed per RFC 2401.
*/
static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index f21596f..4618c18 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)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
+ struct ipv6hdr *iph;
int err;
if (x->props.mode == XFRM_MODE_TUNNEL) {
@@ -59,6 +60,9 @@ static inline int xfrm6_output_one(struct sk_buff *skb)
if (err)
goto error_nolock;
+ iph = ipv6_hdr(skb);
+ iph->payload_len = htons(skb->len - sizeof(*iph));
+
IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
err = 0;
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 00a1a3e..3f8a3ab 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -242,12 +242,7 @@ EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
{
- struct ipv6hdr *top_iph;
-
skb_push(skb, -skb_network_offset(skb));
- top_iph = ipv6_hdr(skb);
- top_iph->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
-
return 0;
}
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 6/7] [IPSEC]: Move IP length/checksum setting out of transforms
2007-10-10 14:40 ` [PATCH 6/7] [IPSEC]: Move IP length/checksum setting out of transforms Herbert Xu
@ 2007-10-10 22:46 ` David Miller
0 siblings, 0 replies; 15+ messages in thread
From: David Miller @ 2007-10-10 22:46 UTC (permalink / raw)
To: herbert; +Cc: netdev
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 10 Oct 2007 22:40:15 +0800
> [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>
APplied.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 7/7] [IPSEC]: Move IP protocol setting from transforms into xfrm4_input.c
2007-10-10 14:39 [0/7] IPsec: More input/output clean-ups Herbert Xu
` (5 preceding siblings ...)
2007-10-10 14:40 ` [PATCH 6/7] [IPSEC]: Move IP length/checksum setting out of transforms Herbert Xu
@ 2007-10-10 14:40 ` Herbert Xu
2007-10-10 22:46 ` David Miller
6 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2007-10-10 14:40 UTC (permalink / raw)
To: David S. Miller, netdev, Herbert Xu
[IPSEC]: Move IP protocol setting from transforms into xfrm4_input.c
This patch makes the IPv4 x->type->input functions return the next protocol
instead of setting it directly. This is identical to how we do things in
IPv6 and will help us merge common code on the input path.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/ah4.c | 5 +++--
net/ipv4/esp4.c | 3 +--
net/ipv4/ipcomp.c | 7 ++++---
net/ipv4/xfrm4_input.c | 7 ++++++-
net/ipv4/xfrm4_tunnel.c | 2 +-
5 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 60925fe..4e8e3b0 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -125,6 +125,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{
int ah_hlen;
int ihl;
+ int nexthdr;
int err = -EINVAL;
struct iphdr *iph;
struct ip_auth_hdr *ah;
@@ -136,6 +137,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
+ nexthdr = ah->nexthdr;
ah_hlen = (ah->hdrlen + 2) << 2;
if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
@@ -182,13 +184,12 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
goto out;
}
}
- ((struct iphdr*)work_buf)->protocol = ah->nexthdr;
skb->network_header += ah_hlen;
memcpy(skb_network_header(skb), work_buf, ihl);
skb->transport_header = skb->network_header;
__skb_pull(skb, ah_hlen + ihl);
- return 0;
+ return nexthdr;
out:
return err;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 8377bed..6b1a31a 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -257,12 +257,11 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
- iph->protocol = nexthdr[1];
pskb_trim(skb, skb->len - alen - padlen - 2);
__skb_pull(skb, sizeof(*esph) + esp->conf.ivlen);
skb_set_transport_header(skb, -ihl);
- return 0;
+ return nexthdr[1];
out:
return -EINVAL;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 32b02de..0bfeb02 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -75,7 +75,6 @@ out:
static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
int err = -ENOMEM;
- struct iphdr *iph;
struct ip_comp_hdr *ipch;
if (skb_linearize_cow(skb))
@@ -84,12 +83,14 @@ static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
/* Remove ipcomp header and decompress original payload */
- iph = ip_hdr(skb);
ipch = (void *)skb->data;
- iph->protocol = ipch->nexthdr;
skb->transport_header = skb->network_header + sizeof(*ipch);
__skb_pull(skb, sizeof(*ipch));
err = ipcomp_decompress(x, skb);
+ if (err)
+ goto out;
+
+ err = ipch->nexthdr;
out:
return err;
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 2fa1082..e9bbfde 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -54,12 +54,14 @@ static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
int xfrm_nr = 0;
int decaps = 0;
int err = xfrm4_parse_spi(skb, ip_hdr(skb)->protocol, &spi, &seq);
+ unsigned int nhoff = offsetof(struct iphdr, protocol);
if (err != 0)
goto drop;
do {
const struct iphdr *iph = ip_hdr(skb);
+ int nexthdr;
if (xfrm_nr == XFRM_MAX_DEPTH)
goto drop;
@@ -82,9 +84,12 @@ static int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (xfrm_state_check_expire(x))
goto drop_unlock;
- if (x->type->input(x, skb))
+ nexthdr = x->type->input(x, skb);
+ if (nexthdr <= 0)
goto drop_unlock;
+ skb_network_header(skb)[nhoff] = nexthdr;
+
/* only the first xfrm gets the encap type */
encap_type = 0;
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index e1fafc1..1312417 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -18,7 +18,7 @@ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb)
{
- return 0;
+ return IPPROTO_IP;
}
static int ipip_init_state(struct xfrm_state *x)
^ permalink raw reply related [flat|nested] 15+ messages in thread