Hi,
Here's an updated version of the patch adding support for ipv4/ipv6
interfamily addressing for the ipsec BEET (Bound End-to-End Tunnel)
mode, as specified by the ietf draft found at:
http://www.ietf.org/internet-drafts/draft-nikander-esp-beet-mode-07.txt
The previous implementation required that both address pairs in the SA
were of the same family. This patch enables mixing ipv4 and ipv6
addresses. All combinations (4-4, 4-6, 6-4, 6-6) have been tested.
The generic interfamily fixes have been chopped off from this into
separate patches.
Signed-off-by: Joakim Koskela [EMAIL PROTECTED]
Signed-off-by: Herbert Xu [EMAIL PROTECTED]
Signed-off-by: Diego Beltrami [EMAIL PROTECTED]
Signed-off-by: Miika Komu [EMAIL PROTECTED]
---
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 6b1a31a..b41e68d 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -288,8 +288,6 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
mtu += min_t(u32, blksize - 4, rem);
break;
case XFRM_MODE_BEET:
- /* The worst case. */
- mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem);
break;
}
@@ -397,8 +395,11 @@ static int esp_init_state(struct xfrm_state *x)
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 iphdr);
- else if (x-props.mode == XFRM_MODE_BEET)
- x-props.header_len += IPV4_BEET_PHMAXLEN;
+ else if (x-props.mode == XFRM_MODE_BEET) {
+ if (x-sel.family == AF_INET) {
+ x-props.header_len += IPV4_BEET_PHMAXLEN;
+ }
+ }
if (x-encap) {
struct xfrm_encap_tmpl *encap = x-encap;
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 2f14745..be58f8e 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -656,3 +656,6 @@ int ip_options_rcv_srr(struct sk_buff *skb)
}
return 0;
}
+
+EXPORT_SYMBOL(ip_options_compile);
+
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 5e95c8a..b2e9308 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -94,7 +94,9 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32
spi,
if (x-outer_mode-input(x, skb))
goto drop;
- if (x-outer_mode-flags XFRM_MODE_FLAG_TUNNEL) {
+ if ((x-outer_mode-flags XFRM_MODE_FLAG_TUNNEL)
+ (x-props.mode != XFRM_MODE_BEET ||
+x-sel.family != AF_INET)) {
decaps = 1;
break;
}
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index e42e122..1346efc 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -6,6 +6,7 @@
*Herbert Xu [EMAIL PROTECTED]
*Abhinav Pathak [EMAIL PROTECTED]
*Jeff Ahrenholz [EMAIL PROTECTED]
+ *Joakim Koskela [EMAIL PROTECTED]
*/
#include linux/init.h
@@ -16,6 +17,7 @@
#include net/dst.h
#include net/ip.h
#include net/xfrm.h
+#include net/inet_ecn.h
/* Add encapsulation header.
*
@@ -23,88 +25,172 @@
*/
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);
-
- hdrlen = 0;
- optlen = iph-ihl * 4 - sizeof(*iph);
- if (unlikely(optlen))
- hdrlen += IPV4_BEET_PHMAXLEN - (optlen 4);
-
- skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x-props.header_len -
- 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)) {
- BUG_ON(optlen 0);
-
- ph-padlen = 4 - (optlen 4);
- ph-hdrlen = optlen / 8;
- ph-nexthdr = top_iph-protocol;
- if (ph-padlen)
- memset(ph + 1, IPOPT_NOP, ph-padlen);
-
- top_iph-protocol = IPPROTO_BEETPH;
- top_iph-ihl = sizeof(struct iphdr) / 4;
- }
+ struct dst_entry *dst = skb-dst;
+ struct iphdr *iphv4, *top_iphv4;
+ int hdrlen;
+
+ if (ip_hdr(skb)-version == 4) {
+ int optlen;
+ struct ip_beet_phdr *ph;
- top_iph-saddr = x-props.saddr.a4;
- top_iph-daddr = x-id.daddr.a4;
+ /* 4-4 */
+ iphv4 = ip_hdr(skb);
+
+ hdrlen = 0;
+ optlen = iphv4-ihl * 4 -