Joakim Koskela wrote: > diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c > index fa1902d..7a39f4c 100644 > --- a/net/ipv4/xfrm4_input.c > +++ b/net/ipv4/xfrm4_input.c > @@ -108,7 +108,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) > if (x->mode->input(x, skb)) > goto drop; > > - if (x->props.mode == XFRM_MODE_TUNNEL) { > + if (x->props.mode == XFRM_MODE_TUNNEL || > + x->props.mode == XFRM_MODE_BEET) { > decaps = 1; > break; > }
I was under the impression that one of the main points of BEET is that it offers tunnel semantics but does only transport mode processing. Its necessary for inter-family tunnels, but shouldn't this be avoided for normal use? > - ph->padlen = 4 - (optlen & 4); > - ph->hdrlen = optlen / 8; > - ph->nexthdr = top_iph->protocol; > - if (ph->padlen) > - memset(ph + 1, IPOPT_NOP, ph->padlen); > - > + ph = (struct ip_beet_phdr *)skb_transport_header(skb); > + ph->padlen = 4 - (optlen & 4); > + ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; Reintroduces pseudo-header length bug. > + ph->nexthdr = iphv4->protocol; > + top_iphv4->protocol = IPPROTO_BEETPH; > + top_iphv4->ihl = sizeof(struct iphdr) / 4; Where did padding go? > static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) > { > - if (unlikely(iph->protocol == IPPROTO_BEETPH)) { > - struct ip_beet_phdr *ph; > - > - if (!pskb_may_pull(skb, sizeof(*ph))) > - goto out; > - ph = (struct ip_beet_phdr *)(ipip_hdr(skb) + 1); > - > - phlen = sizeof(*ph) + ph->padlen; > - optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen); > - if (optlen < 0 || optlen & 3 || optlen > 250) > - goto out; > + if (unlikely(iph->protocol == IPPROTO_BEETPH)) { > + struct ip_beet_phdr *ph = > + (struct ip_beet_phdr*)(iph + 1); > + > + if (!pskb_may_pull(skb, sizeof(*ph))) > + goto out; > + > + phlen = ph->hdrlen * 8; > + optlen = phlen - ph->padlen - sizeof(*ph); Reintroduces header length bug. > diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c > index 44ef208..8db7910 100644 > --- a/net/ipv4/xfrm4_output.c > +++ b/net/ipv4/xfrm4_output.c > @@ -53,7 +53,8 @@ static int xfrm4_output_one(struct sk_buff *skb) > goto error_nolock; > } > > - if (x->props.mode == XFRM_MODE_TUNNEL) { > + if (x->props.mode == XFRM_MODE_TUNNEL || > + x->props.mode == XFRM_MODE_BEET) { > err = xfrm4_tunnel_check_size(skb); Its not a real tunnel and all packets are generated locally, why does it need to send ICMPs? > if (err) > @@ -81,10 +82,15 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct > xfrm_state **xfrm, int > } > } > }; > + union { > + struct in6_addr *in6; > + struct in_addr *in; > + } remote, local; > int i; > int err; > int header_len = 0; > int trailer_len = 0; > + unsigned short encap_family = 0; > > dst = dst_prev = NULL; > dst_hold(&rt->u.dst); > @@ -113,12 +119,24 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, > struct xfrm_state **xfrm, int > > dst1->next = dst_prev; > dst_prev = dst1; > - > + if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { > + encap_family = xfrm[i]->props.family; > + if (encap_family == AF_INET) { > + remote.in = (struct in_addr *) > + &xfrm[i]->id.daddr.a4; > + local.in = (struct in_addr *) > + &xfrm[i]->props.saddr.a4; > + } else if (encap_family == AF_INET6) { > + remote.in6 = (struct in6_addr *) > + xfrm[i]->id.daddr.a6; > + local.in6 = (struct in6_addr *) > + xfrm[i]->props.saddr.a6; > + } No ifdefs here? > + } > header_len += xfrm[i]->props.header_len; > trailer_len += xfrm[i]->props.trailer_len; > > - if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) { > - unsigned short encap_family = xfrm[i]->props.family; > + if (encap_family) { > switch (encap_family) { > case AF_INET: > fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4; > @@ -198,6 +216,12 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct > xfrm_state **xfrm, int > } > > xfrm_init_pmtu(dst); > + if (encap_family == AF_INET6) { > + /* The worst case */ > + int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); > + u32 mtu = dst_mtu(dst); > + xfrm4_update_pmtu(dst, mtu - delta); This should be known at configuration time, why do you need to call xfrm4_update_pmtu? Just set header_len correctly. > diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c > index 5685103..57c2dba 100644 > --- a/net/ipv4/xfrm4_tunnel.c > +++ b/net/ipv4/xfrm4_tunnel.c > @@ -27,7 +27,8 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct > sk_buff *skb) > > static int ipip_init_state(struct xfrm_state *x) > { > - if (x->props.mode != XFRM_MODE_TUNNEL) > + if (x->props.mode != XFRM_MODE_TUNNEL || > + x->props.mode != XFRM_MODE_BEET) > return -EINVAL; Looks like a bug fix that should be seperated. > @@ -365,6 +366,8 @@ static int esp6_init_state(struct xfrm_state *x) > x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; > if (x->props.mode == XFRM_MODE_TUNNEL) > x->props.header_len += sizeof(struct ipv6hdr); > + else if (x->props.mode == XFRM_MODE_BEET) > + x->props.header_len += IPV4_BEET_PHMAXLEN; Seems wrong, you don't do option encapsulation for IPv6. All you do is subtract this length again. What you probably should do is account for the IPv4 header *if* it is an interfamiyl tunnel. > diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c > index c858537..bfb3d7b 100644 > --- a/net/ipv6/xfrm6_input.c > +++ b/net/ipv6/xfrm6_input.c > @@ -73,7 +73,8 @@ int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi) > if (x->mode->input(x, skb)) > goto drop; > > - if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */ > + if (x->props.mode == XFRM_MODE_TUNNEL || > + x->props.mode == XFRM_MODE_BEET) { /* XXX */ > decaps = 1; Same as for IPv4. I lost interest here, but the reintroduced bugs make me think that some old version was simply rediffed without even checking the output and the state initialization also seems to need a bit more work. - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html