Hello Patrick, I have a comment about the patch on the IPv6 input process. The kernel applied your patch will always call ip6_rcv_finish when enabling netfilter and receiving a esp packet so that it will always look up the routing table and parse extention headers twice a packet. It will probably cost.
Your ip_xfrm_transport_hook is a good idea, I think. We could call ip6_rcv_finish if the netfilter changed the addresses or otherwise we can continue the loop to avoid the cost in a similar way because we can know the change with checking skb->dst. If you fix the point, your change will resolve our issues which were mentioned in the previous mail from Kozakai-san. Patrick McHardy wrote: > [IPV4/6]: Netfilter IPsec input hooks > > When the innermost transform uses transport mode the decapsulated packet > is not visible to netfilter. Pass the packet through the PRE_ROUTING and > LOCAL_IN hooks again before handing it to upper layer protocols to make > netfilter-visibility symetrical to the output path. > > Signed-off-by: Patrick McHardy <[EMAIL PROTECTED]> > > --- > commit 08cf39d5d7d8b942431a6529daa3ab69ecfb34b5 > tree 6f2a1a85f915b1b6f89ad50cf3d8855f21a561b6 > parent b847425c693f43a63137d18e36e5c8cf0187c175 > author Patrick McHardy <[EMAIL PROTECTED]> Sat, 19 Nov 2005 21:50:22 +0100 > committer Patrick McHardy <[EMAIL PROTECTED]> Sat, 19 Nov 2005 21:50:22 +0100 > > include/linux/netfilter_ipv4.h | 2 +- > include/net/ipv6.h | 2 ++ > net/ipv4/netfilter.c | 20 ++++++++++++++++++++ > net/ipv4/xfrm4_input.c | 14 ++++++++++++++ > net/ipv6/ip6_input.c | 2 +- > net/ipv6/xfrm6_input.c | 13 +++++++++++++ > 6 files changed, 51 insertions(+), 2 deletions(-) > > diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h > index fdc4a95..e9103fe 100644 > --- a/include/linux/netfilter_ipv4.h > +++ b/include/linux/netfilter_ipv4.h > @@ -79,7 +79,7 @@ enum nf_ip_hook_priorities { > > #ifdef __KERNEL__ > extern int ip_route_me_harder(struct sk_buff **pskb); > - > +extern int ip_xfrm_transport_hook(struct sk_buff *skb); > #endif /*__KERNEL__*/ > > #endif /*__LINUX_IP_NETFILTER_H*/ > diff --git a/include/net/ipv6.h b/include/net/ipv6.h > index 6addb4d..4fbfe43 100644 > --- a/include/net/ipv6.h > +++ b/include/net/ipv6.h > @@ -414,6 +414,8 @@ extern int ipv6_rcv(struct sk_buff > *sk > struct packet_type *pt, > struct net_device *orig_dev); > > +extern int ip6_rcv_finish(struct sk_buff *skb); > + > /* > * upper-layer output functions > */ > diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c > index b93e7cd..3c39296 100644 > --- a/net/ipv4/netfilter.c > +++ b/net/ipv4/netfilter.c > @@ -105,6 +105,26 @@ int ip_dst_output(struct sk_buff *skb) > return dst_output(skb); > } > EXPORT_SYMBOL(ip_dst_output); > + > +/* > + * okfn for transport mode xfrm_input.c hook. Basically a copy of > + * ip_rcv_finish without statistics and option parsing. > + */ > +int ip_xfrm_transport_hook(struct sk_buff *skb) > +{ > + struct iphdr *iph = skb->nh.iph; > + > + if (likely(skb->dst == NULL)) { > + int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, > + skb->dev); > + if (unlikely(err)) > + goto drop; > + } > + return dst_input(skb); > +drop: > + kfree_skb(skb); > + return NET_RX_DROP; > +} > #endif /* CONFIG_XFRM */ > > /* > diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c > index 2d3849c..d90cd93 100644 > --- a/net/ipv4/xfrm4_input.c > +++ b/net/ipv4/xfrm4_input.c > @@ -11,6 +11,8 @@ > > #include <linux/module.h> > #include <linux/string.h> > +#include <linux/netfilter.h> > +#include <linux/netfilter_ipv4.h> > #include <net/inet_ecn.h> > #include <net/ip.h> > #include <net/xfrm.h> > @@ -137,6 +139,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, > memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct > sec_decap_state)); > skb->sp->len += xfrm_nr; > > + nf_reset(skb); > + > if (decaps) { > if (!(skb->dev->flags&IFF_LOOPBACK)) { > dst_release(skb->dst); > @@ -145,7 +149,17 @@ int xfrm4_rcv_encap(struct sk_buff *skb, > netif_rx(skb); > return 0; > } else { > +#ifdef CONFIG_NETFILTER > + __skb_push(skb, skb->data - skb->nh.raw); > + skb->nh.iph->tot_len = htons(skb->len); > + ip_send_check(skb->nh.iph); > + > + NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, > + ip_xfrm_transport_hook); > + return 0; > +#else > return -skb->nh.iph->protocol; > +#endif > } > > drop_unlock: > diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c > index 33d3b0e..e84b3cd 100644 > --- a/net/ipv6/ip6_input.c > +++ b/net/ipv6/ip6_input.c > @@ -48,7 +48,7 @@ > > > > -static inline int ip6_rcv_finish( struct sk_buff *skb) > +inline int ip6_rcv_finish(struct sk_buff *skb) > { > if (skb->dst == NULL) > ip6_route_input(skb); > diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c > index 28c29d7..9987416 100644 > --- a/net/ipv6/xfrm6_input.c > +++ b/net/ipv6/xfrm6_input.c > @@ -11,6 +11,8 @@ > > #include <linux/module.h> > #include <linux/string.h> > +#include <linux/netfilter.h> > +#include <linux/netfilter_ipv6.h> > #include <net/dsfield.h> > #include <net/inet_ecn.h> > #include <net/ip.h> > @@ -121,6 +123,8 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, > skb->sp->len += xfrm_nr; > skb->ip_summed = CHECKSUM_NONE; > > + nf_reset(skb); > + > if (decaps) { > if (!(skb->dev->flags&IFF_LOOPBACK)) { > dst_release(skb->dst); > @@ -129,7 +133,16 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, > netif_rx(skb); > return -1; > } else { > +#ifdef CONFIG_NETFILTER > + skb->nh.ipv6h->payload_len = htons(skb->len); > + __skb_push(skb, skb->data - skb->nh.raw); > + > + NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, > + ip6_rcv_finish); > + return -1; > +#else > return 1; > +#endif > } > > drop_unlock: > - > 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 -- Kazunori Miyazawa - 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