* [PATCH] [XFRM] Beet: Fix output for ipv6 @ 2008-02-08 16:12 Joakim Koskela 2008-02-25 20:31 ` Joakim Koskela 0 siblings, 1 reply; 7+ messages in thread From: Joakim Koskela @ 2008-02-08 16:12 UTC (permalink / raw) To: netdev Hi, This patch fixes the ipv6 mode of ipsec beet. It has been using logic similar to tunnel mode, making it crash during esp packaging. Signed-off-by: Joakim Koskela <jookos@gmail.com> --- net/ipv6/xfrm6_mode_beet.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 0527d11..0395800 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c @@ -40,11 +40,14 @@ static void xfrm6_beet_make_header(struct sk_buff *skb) static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) { struct ipv6hdr *top_iph; + u8 *prevhdr; + int hdr_len; + 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->mac_header = skb->network_header + - offsetof(struct ipv6hdr, nexthdr); - skb->transport_header = skb->network_header + sizeof(*top_iph); + skb->transport_header = skb->network_header + hdr_len; + __skb_pull(skb, hdr_len); xfrm6_beet_make_header(skb); ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] [XFRM] Beet: Fix output for ipv6 2008-02-08 16:12 [PATCH] [XFRM] Beet: Fix output for ipv6 Joakim Koskela @ 2008-02-25 20:31 ` Joakim Koskela 2008-03-06 11:08 ` Herbert Xu 0 siblings, 1 reply; 7+ messages in thread From: Joakim Koskela @ 2008-02-25 20:31 UTC (permalink / raw) To: netdev, Herbert Xu Hi Herbert, Have you had a chance to look this, or are you working on something else for it? On Friday 08 February 2008 18:12, Joakim Koskela wrote: > Hi, > > This patch fixes the ipv6 mode of ipsec beet. It has been using logic > similar to tunnel mode, making it crash during esp packaging. > > Signed-off-by: Joakim Koskela <jookos@gmail.com> > --- > net/ipv6/xfrm6_mode_beet.c | 9 ++++++--- > 1 files changed, 6 insertions(+), 3 deletions(-) > > diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c > index 0527d11..0395800 100644 > --- a/net/ipv6/xfrm6_mode_beet.c > +++ b/net/ipv6/xfrm6_mode_beet.c > @@ -40,11 +40,14 @@ static void xfrm6_beet_make_header(struct sk_buff *skb) > static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) > { > struct ipv6hdr *top_iph; > + u8 *prevhdr; > + int hdr_len; > > + 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->mac_header = skb->network_header + > - offsetof(struct ipv6hdr, nexthdr); > - skb->transport_header = skb->network_header + sizeof(*top_iph); > + skb->transport_header = skb->network_header + hdr_len; > + __skb_pull(skb, hdr_len); > > xfrm6_beet_make_header(skb); > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] [XFRM] Beet: Fix output for ipv6 2008-02-25 20:31 ` Joakim Koskela @ 2008-03-06 11:08 ` Herbert Xu 2008-03-07 17:22 ` Joakim Koskela 2008-03-07 17:52 ` [RFC PATCH]: Fix output for BEET ipsec Joakim Koskela 0 siblings, 2 replies; 7+ messages in thread From: Herbert Xu @ 2008-03-06 11:08 UTC (permalink / raw) To: Joakim Koskela; +Cc: netdev On Mon, Feb 25, 2008 at 10:31:00PM +0200, Joakim Koskela wrote: > Hi Herbert, > > Have you had a chance to look this, or are you working on something else for > it? Sorry, I've been flat out lately so I missed your patch. > On Friday 08 February 2008 18:12, Joakim Koskela wrote: > > > > This patch fixes the ipv6 mode of ipsec beet. It has been using logic > > similar to tunnel mode, making it crash during esp packaging. > > > > Signed-off-by: Joakim Koskela <jookos@gmail.com> > > --- > > net/ipv6/xfrm6_mode_beet.c | 9 ++++++--- > > 1 files changed, 6 insertions(+), 3 deletions(-) > > > > diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c > > index 0527d11..0395800 100644 > > --- a/net/ipv6/xfrm6_mode_beet.c > > +++ b/net/ipv6/xfrm6_mode_beet.c > > @@ -40,11 +40,14 @@ static void xfrm6_beet_make_header(struct sk_buff *skb) > > static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) > > { > > struct ipv6hdr *top_iph; > > + u8 *prevhdr; > > + int hdr_len; > > > > + 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->mac_header = skb->network_header + > > - offsetof(struct ipv6hdr, nexthdr); > > - skb->transport_header = skb->network_header + sizeof(*top_iph); > > + skb->transport_header = skb->network_header + hdr_len; > > + __skb_pull(skb, hdr_len); After a quick a look I have to say that I don't think this is right. BEET is supposed to wrap around all extension headers so we shouldn't call hdr_offset. In fact the packet could be IPv4 for all we know. So why don't you show us the crash that you're experiencing? Thanks, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] [XFRM] Beet: Fix output for ipv6 2008-03-06 11:08 ` Herbert Xu @ 2008-03-07 17:22 ` Joakim Koskela 2008-03-26 13:30 ` Herbert Xu 2008-03-07 17:52 ` [RFC PATCH]: Fix output for BEET ipsec Joakim Koskela 1 sibling, 1 reply; 7+ messages in thread From: Joakim Koskela @ 2008-03-07 17:22 UTC (permalink / raw) To: Herbert Xu; +Cc: netdev On Thursday 06 March 2008 13:08, Herbert Xu wrote: > After a quick a look I have to say that I don't think this is > right. BEET is supposed to wrap around all extension headers > so we shouldn't call hdr_offset. In fact the packet could be > IPv4 for all we know. > > So why don't you show us the crash that you're experiencing? > > Thanks, Thanks for checking this out. I didn't actually think about interfamily in this patch at all as it didn't work for me without any patching either, this was only for fixing the 6-6 case. We've been using another patch (which sort of builds on this one) for interfamily, I could actually send it (as a rfc) in just a minute (it's sort of ugly, follows the old model of handling ipv4/6 differently in x_beet_output), was sort of waiting to get feedback for the 6-6 case before introducing interfamily. But anyway - here's the trace from the crash I get. I just do a manual key setup and try to get a ping through. ------------[ cut here ]------------ invalid opcode: 0000 [#5] PREEMPT Process ping6 (pid: 5445, ti=dc3ac000 task=dc3940b0 task.ti=dc3ac000) Stack: df9dea40 00000004 dbb14494 dc3adc1c db87f000 dbb9d880 dbb45540 c0457290 0000008c df9dea40 00000001 c04726b2 00000000 00000000 dbb9d880 dbb45560 dbd16248 dbb45540 c03d16a4 0000007c dbd16240 c0475aaf 0000007c dbb14400 Call Trace: [<c0457290>] ip6_pol_route_output+0x0/0x20 [<c04726b2>] xfrm6_dst_lookup+0x32/0x80 [<c03d16a4>] skb_to_sgvec+0x14/0x30 [<c0475aaf>] esp6_output+0x1bf/0x290 [<c04412df>] xfrm_output_resume+0x2bf/0x360 [<c044d4a1>] ip6_append_data+0xa41/0xc10 [<c044aa35>] ip6_local_out+0x15/0x20 [<c044c781>] ip6_push_pending_frames+0x2a1/0x3f0 [<c046250b>] rawv6_sendmsg+0x99b/0xcf0 [<c03d45c8>] memcpy_toiovec+0x38/0x50 [<c03eb40c>] netlink_recvmsg+0x1ec/0x2c0 [<c011d2f0>] update_curr+0x70/0x110 [<c041dfd7>] inet_sendmsg+0x37/0x70 [<c03cc85d>] sock_sendmsg+0xcd/0x100 [<c01368d0>] autoremove_wake_function+0x0/0x50 [<c03ccc14>] sys_sendto+0x114/0x160 [<c015af71>] __do_fault+0x171/0x3b0 [<c0150a00>] filemap_fault+0x0/0x460 [<c015cde2>] handle_mm_fault+0xf2/0x5e0 [<c03cdd58>] sys_socketcall+0x198/0x280 [<c0104082>] sysenter_past_esp+0x5f/0x85 [<c04c0000>] quirk_piix4_acpi+0x30/0x170 ======================= Code: ff ff c7 44 24 0c 16 09 00 00 c7 44 24 08 27 98 59 c0 c7 44 24 04 39 98 59 c0 c7 04 24 30 ce 59 c0 e8 c5 35 d5 ff e9 02 ff ff ff <0f> 0b eb fe 0f 0b eb fe 90 8d b4 26 00 00 00 00 53 89 d3 83 ec EIP: [<c03d1680>] __skb_to_sgvec+0x280/0x290 SS:ESP 0068:dc3adbc0 Modules linked in: radeon drm rfcomm l2cap binfmt_misc ppdev lp cpufreq_userspace cpufreq_conservative cpufreq_powersave cpufreq_ondemand ipt_TTL ipt_ttl ipt_REDIRECT ipt_recent ipt_NETMAP ipt_MASQUERADE ipt_ECN ipt_ecn ipt_addrtype nf_nat_tftp nf_nat_snmp_basic nf_nat_sip nf_nat_pptp nf_nat_proto_gre nf_nat_irc nf_nat_h323 nf_nat_ftp nf_nat_amanda ts_kmp nf_conntrack_amanda nf_conntrack_tftp nf_conntrack_sip nf_conntrack_proto_sctp nf_conntrack_pptp nf_conntrack_proto_gre nf_conntrack_netbios_ns nf_conntrack_irc nf_conntrack_h323 nf_conntrack_ftp xt_tcpmss xt_pkttype xt_mark xt_mac xt_limit xt_length xt_helper xt_hashlimit xt_dccp xt_conntrack xt_CONNMARK xt_connmark xt_state iptable_nat nf_nat nf_conntrack_ipv4 nf_conntrack nls_cp437 loop 8250_pci hci_usb bluetooth snd_intel8x0 snd_intel 8x0m snd_ac97_codec ac97_bus snd_pcm_oss snd_mixer_oss irtty_sir snd_pcm sir_dev snd_timer 8250_pnp irda snd 8250 serial_core crc_ccitt parport_pc parport ipw2100 floppy soundcore ide_cd_mod i2c_ 801 snd_page_alloc cdrom ieee80211 ieee80211_crypt e1000 ehci_hcd uhci_hcd usbcore evdev Pid: 5445, comm: ping6 Tainted: G D (2.6.25-rc3-00135-g1ff82fe #1) EIP: 0060:[<c03d1680>] EFLAGS: 00010206 CPU: 0 EIP is at __skb_to_sgvec+0x280/0x290 EAX: dbb9d880 EBX: 00000250 ECX: dbb45540 EDX: dbd16300 ESI: 00000000 EDI: 00000028 EBP: 0000008c ESP: dc3adbc0 DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 ---[ end trace 778e504de7e3b1e3 ]--- ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] [XFRM] Beet: Fix output for ipv6 2008-03-07 17:22 ` Joakim Koskela @ 2008-03-26 13:30 ` Herbert Xu 2008-03-26 23:51 ` David Miller 0 siblings, 1 reply; 7+ messages in thread From: Herbert Xu @ 2008-03-26 13:30 UTC (permalink / raw) To: David S. Miller, Joakim Koskela; +Cc: netdev On Fri, Mar 07, 2008 at 07:22:23PM +0200, Joakim Koskela wrote: > > Thanks for checking this out. I didn't actually think about > interfamily in this patch at all as it didn't work for me without any > patching either, this was only for fixing the 6-6 case. We've been > using another patch (which sort of builds on this one) for > interfamily, I could actually send it (as a rfc) in just a minute > (it's sort of ugly, follows the old model of handling ipv4/6 > differently in x_beet_output), was sort of waiting to get feedback for > the 6-6 case before introducing interfamily. > > But anyway - here's the trace from the crash I get. I just do a manual > key setup and try to get a ping through. Sorry, I dropped the ball on this. I've found the problem thanks to your report. [IPSEC]: Fix BEET output The IPv6 BEET output function is incorrectly including the inner header in the payload to be protected. This causes a crash as the packet doesn't actually have that many bytes for a second header. The IPv4 BEET output on the other hand is broken when it comes to handling an inner IPv6 header since it always assumes an inner IPv4 header. This patch fixes both by making sure that neither BEET output function touches the inner header at all. All access is now done through the protocol-independent cb structure. Two new attributes are added to make this work, the IP header length and the IPv4 option length. They're filled in by the inner mode's output function. Thanks to Joakim Koskela for finding this problem. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Cheers, -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 619c53b..700cb26 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -530,6 +530,9 @@ struct xfrm_mode_skb_cb { __be16 id; __be16 frag_off; + /* IP header length (excluding options or extension headers). */ + u8 ihl; + /* TOS for IPv4, class for IPv6. */ u8 tos; @@ -539,6 +542,9 @@ struct xfrm_mode_skb_cb { /* Protocol for IPv4, NH for IPv6. */ u8 protocol; + /* Option length for IPv4, zero for IPv6. */ + u8 optlen; + /* Used by IPv6 only, zero for IPv4. */ u8 flow_lbl[3]; }; diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index b47030b..9c798ab 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c @@ -39,13 +39,11 @@ static void xfrm4_beet_make_header(struct sk_buff *skb) static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) { struct ip_beet_phdr *ph; - struct iphdr *iph, *top_iph; + struct iphdr *top_iph; int hdrlen, optlen; - iph = ip_hdr(skb); - hdrlen = 0; - optlen = iph->ihl * 4 - sizeof(*iph); + optlen = XFRM_MODE_SKB_CB(skb)->optlen; if (unlikely(optlen)) hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); @@ -53,11 +51,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) hdrlen); skb->mac_header = skb->network_header + offsetof(struct iphdr, protocol); - skb->transport_header = skb->network_header + sizeof(*iph); + skb->transport_header = skb->network_header + sizeof(*top_iph); xfrm4_beet_make_header(skb); - ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); + ph = (struct ip_beet_phdr *) + __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen); top_iph = ip_hdr(skb); diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index fdeebe6..07735ed 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c @@ -52,10 +52,12 @@ int xfrm4_extract_header(struct sk_buff *skb) { struct iphdr *iph = ip_hdr(skb); + XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); XFRM_MODE_SKB_CB(skb)->id = iph->id; XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off; XFRM_MODE_SKB_CB(skb)->tos = iph->tos; XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl; + XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph); memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0, sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 0527d11..d6ce400 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c @@ -45,6 +45,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) skb->mac_header = skb->network_header + offsetof(struct ipv6hdr, nexthdr); skb->transport_header = skb->network_header + sizeof(*top_iph); + __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl); xfrm6_beet_make_header(skb); diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index dc817e0..ff1e1db 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c @@ -174,10 +174,12 @@ int xfrm6_extract_header(struct sk_buff *skb) { struct ipv6hdr *iph = ipv6_hdr(skb); + XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); XFRM_MODE_SKB_CB(skb)->id = 0; XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; + XFRM_MODE_SKB_CB(skb)->optlen = 0; memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] [XFRM] Beet: Fix output for ipv6 2008-03-26 13:30 ` Herbert Xu @ 2008-03-26 23:51 ` David Miller 0 siblings, 0 replies; 7+ messages in thread From: David Miller @ 2008-03-26 23:51 UTC (permalink / raw) To: herbert; +Cc: joakim.koskela, netdev From: Herbert Xu <herbert@gondor.apana.org.au> Date: Wed, 26 Mar 2008 21:30:26 +0800 > [IPSEC]: Fix BEET output Applied to net-2.6, thanks Herbert! ^ permalink raw reply [flat|nested] 7+ messages in thread
* [RFC PATCH]: Fix output for BEET ipsec 2008-03-06 11:08 ` Herbert Xu 2008-03-07 17:22 ` Joakim Koskela @ 2008-03-07 17:52 ` Joakim Koskela 1 sibling, 0 replies; 7+ messages in thread From: Joakim Koskela @ 2008-03-07 17:52 UTC (permalink / raw) To: netdev; +Cc: Herbert Xu This patch fixes the ipsec BEET (Bound End-to-End Tunnel) mode interfamily handling of the net-2.6 (25-rc3) kernel, as specified by the ietf draft found at: http://www.ietf.org/internet-drafts/draft-nikander-esp-beet-mode-08.txt It is sent as a RFC as it doesn't fit that neatly into the newly cleaned-up xfrm model - I suspect that there could be a better way to solve this. Signed-off-by: Joakim Koskela <jookos@gmail.com> --- net/ipv4/esp4.c | 10 +++- net/ipv4/xfrm4_mode_beet.c | 104 +++++++++++++++++++++++++++++--------------- net/ipv6/esp6.c | 6 +++ net/ipv6/xfrm6_mode_beet.c | 83 ++++++++++++++++++++++++++++++----- 4 files changed, 153 insertions(+), 50 deletions(-) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 091e670..20d214f 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -404,7 +404,8 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) break; case XFRM_MODE_BEET: /* The worst case. */ - mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem); + /* These will be see to in the esp header_len */ + /* mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem); */ break; } @@ -575,8 +576,11 @@ static int esp_init_state(struct xfrm_state *x) crypto_aead_ivsize(aead); 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/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index b47030b..83db9b2 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c @@ -6,6 +6,7 @@ * Herbert Xu <herbert@gondor.apana.org.au> * Abhinav Pathak <abhinav.pathak@hiit.fi> * Jeff Ahrenholz <ahrenholz@gmail.com> + * Joakim Koskela <jookos@gmail.com> */ #include <linux/init.h> @@ -38,45 +39,78 @@ static void xfrm4_beet_make_header(struct sk_buff *skb) */ 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); - - xfrm4_beet_make_header(skb); - - ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); - - top_iph = ip_hdr(skb); - - 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; + if (iph->version == 4) { + struct ip_beet_phdr *ph; + int hdrlen, optlen; + + 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); + + xfrm4_beet_make_header(skb); + + ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); + + top_iph = ip_hdr(skb); + + 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; + } + + top_iph->saddr = x->props.saddr.a4; + top_iph->daddr = x->id.daddr.a4; + +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + } else if (iph->version == 6) { + struct dst_entry *dst = skb->dst; + + int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); + u8 protocol = ipv6_hdr(skb)->nexthdr; + + /* Inner = 6, Outer = 4 : changing the external IP hdr + * to the outer addresses + */ + skb_set_network_header(skb, delta - x->props.header_len); + skb->transport_header = skb->network_header + sizeof(*iph); + skb->mac_header = skb->network_header + + offsetof(struct iphdr, protocol); + skb_pull(skb, sizeof(struct ipv6hdr)); + + top_iph = ip_hdr(skb); + top_iph->ihl = 5; + top_iph->version = 4; + top_iph->id = 0; + top_iph->frag_off = htons(IP_DF); + top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); + top_iph->protocol = protocol; + + top_iph->saddr = x->props.saddr.a4; + top_iph->daddr = x->id.daddr.a4; + IPCB(skb)->flags = 0; + + skb->protocol = htons(ETH_P_IP); + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); +#endif } - - top_iph->saddr = x->props.saddr.a4; - top_iph->daddr = x->id.daddr.a4; - return 0; } diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 0ec1402..984a03e 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -344,6 +344,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) rem = mtu & (align - 1); mtu &= ~(align - 1); + /* hm, is this right? maybe we shouldn't do this for beet either? */ if (x->props.mode != XFRM_MODE_TUNNEL) { u32 padsize = ((blksize - 1) & 7) + 1; mtu -= blksize - padsize; @@ -521,6 +522,11 @@ static int esp6_init_state(struct xfrm_state *x) crypto_aead_ivsize(aead); switch (x->props.mode) { case XFRM_MODE_BEET: + if (x->sel.family == AF_INET) { + x->props.header_len += IPV4_BEET_PHMAXLEN + + (sizeof(struct ipv6hdr) - sizeof(struct iphdr)); + } + break; case XFRM_MODE_TRANSPORT: break; case XFRM_MODE_TUNNEL: diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index 0527d11..2547c51 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c @@ -6,6 +6,7 @@ * Herbert Xu <herbert@gondor.apana.org.au> * Abhinav Pathak <abhinav.pathak@hiit.fi> * Jeff Ahrenholz <ahrenholz@gmail.com> + * Joakim Koskela <jookos@gmail.com> */ #include <linux/init.h> @@ -40,18 +41,76 @@ static void xfrm6_beet_make_header(struct sk_buff *skb) static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) { struct ipv6hdr *top_iph; - - skb_set_network_header(skb, -x->props.header_len); - skb->mac_header = skb->network_header + - offsetof(struct ipv6hdr, nexthdr); - skb->transport_header = skb->network_header + sizeof(*top_iph); - - xfrm6_beet_make_header(skb); - - top_iph = ipv6_hdr(skb); - - ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); - ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); + int hdr_len; + + if (ip_hdr(skb)->version == 6) { + u8 *prevhdr; + + 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->transport_header = skb->network_header + hdr_len; + __skb_pull(skb, hdr_len); + + xfrm6_beet_make_header(skb); + + top_iph = ipv6_hdr(skb); + + ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); + ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); + } else { + struct dst_entry *dst = skb->dst; + struct iphdr *iphv4; + int flags, optlen, dsfield; + struct ip_beet_phdr *ph; + u8 protocol; + + iphv4 = ip_hdr(skb); + hdr_len = 0; + optlen = iphv4->ihl * 4 - sizeof(*iphv4); + if (unlikely(optlen)) + hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4); + + skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len - + hdr_len); + skb->mac_header = skb->network_header + offsetof(struct ipv6hdr, nexthdr); + skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); + + ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iphv4) - hdr_len); + if (unlikely(optlen)) { + + BUG_ON(optlen < 0); + + ph->padlen = 4 - (optlen & 4); + ph->hdrlen = optlen / 8; + ph->nexthdr = iphv4->protocol; + if (ph->padlen) + memset(ph + 1, IPOPT_NOP, ph->padlen); + + protocol = IPPROTO_BEETPH; + } else + protocol = iphv4->protocol; + + top_iph = ipv6_hdr(skb); + + /* DS disclosed */ + top_iph->version = 6; + top_iph->priority = 0; + top_iph->flow_lbl[0] = 0; + top_iph->flow_lbl[1] = 0; + top_iph->flow_lbl[2] = 0; + dsfield = ipv6_get_dsfield(top_iph); + dsfield = INET_ECN_encapsulate(dsfield, dsfield); + flags = x->props.flags; + if (flags & XFRM_STATE_NOECN) + dsfield &= ~INET_ECN_MASK; + ipv6_change_dsfield(top_iph, 0, dsfield); + + top_iph->nexthdr = protocol; + top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); + ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); + ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); + } return 0; } ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2008-03-26 23:51 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-02-08 16:12 [PATCH] [XFRM] Beet: Fix output for ipv6 Joakim Koskela 2008-02-25 20:31 ` Joakim Koskela 2008-03-06 11:08 ` Herbert Xu 2008-03-07 17:22 ` Joakim Koskela 2008-03-26 13:30 ` Herbert Xu 2008-03-26 23:51 ` David Miller 2008-03-07 17:52 ` [RFC PATCH]: Fix output for BEET ipsec Joakim Koskela
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox