From patchwork Sat Feb 27 06:40:01 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shan Wei X-Patchwork-Id: 46423 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id D7947B7D26 for ; Sat, 27 Feb 2010 17:40:21 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753197Ab0B0GkG (ORCPT ); Sat, 27 Feb 2010 01:40:06 -0500 Received: from cn.fujitsu.com ([222.73.24.84]:50076 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1753092Ab0B0GkC (ORCPT ); Sat, 27 Feb 2010 01:40:02 -0500 Received: from tang.cn.fujitsu.com (tang.cn.fujitsu.com [10.167.250.3]) by song.cn.fujitsu.com (Postfix) with ESMTP id 3DA7317010C; Sat, 27 Feb 2010 14:40:02 +0800 (CST) Received: from fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id o1R6d3Bi007446; Sat, 27 Feb 2010 14:39:03 +0800 Received: from [10.167.141.214] (unknown [10.167.141.214]) by fnst.cn.fujitsu.com (Postfix) with ESMTPA id 084C6D4867; Sat, 27 Feb 2010 14:41:55 +0800 (CST) Message-ID: <4B88BE41.8070000@cn.fujitsu.com> Date: Sat, 27 Feb 2010 14:40:01 +0800 From: Shan Wei User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: Patrick McHardy , David Miller , Alexey Dobriyan , Yasuyuki KOZAKAI , "netdev@vger.kernel.org" , netfilter-devel@vger.kernel.org Subject: [RFC PATCH net-next 4/7]IPv6:netfilter: Send an ICMPv6 "Fragment Reassembly Timeout" message when enabling connection track Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org An end host with IPv6 connection track enable should send an ICMP "Fragment Reassembly Timeout" message when defraging timeout according to the section 4.5 in RFC2460. This patch supports it and adds counter value of Ip6ReasmTimeout and Ip6ReasmFails. Quote Begin: Section 4.5 in RFC2460. If insufficient fragments are received to complete reassembly of a packet within 60 seconds of the reception of the first-arriving fragment of that packet, reassembly of that packet must be abandoned and all the fragments that have been received for that packet must be discarded. If the first fragment (i.e., the one with a Fragment Offset of zero) has been received, an ICMP Time Exceeded -- Fragment Reassembly Time Exceeded message should be sent to the source of that fragment. Quote End. Signed-off-by: Shan Wei --- include/linux/skbuff.h | 5 +++ net/ipv6/netfilter/nf_conntrack_reasm.c | 48 ++++++++++++++++++++++++++++++- net/ipv6/route.c | 1 + 3 files changed, 53 insertions(+), 1 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index ba0f8e3..e0b72e4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -431,6 +431,11 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb) return (struct rtable *)skb_dst(skb); } +static inline struct rt6_info *skb_r6table(const struct sk_buff *skb) +{ + return (struct rt6_info *)skb_dst(skb); +} + extern void kfree_skb(struct sk_buff *skb); extern void consume_skb(struct sk_buff *skb); extern void __kfree_skb(struct sk_buff *skb); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 8f68373..27d8ac1 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -27,10 +27,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -64,6 +66,7 @@ struct nf_ct_frag6_queue struct in6_addr saddr; struct in6_addr daddr; + int iif; unsigned int csum; __u16 nhoffset; }; @@ -205,6 +208,8 @@ static void nf_ct_frag6_evictor(struct net *net) static void nf_ct_frag6_expire(unsigned long data) { struct nf_ct_frag6_queue *fq; + struct net_device *dev = NULL; + struct net *net; fq = container_of((struct inet_frag_queue *)data, struct nf_ct_frag6_queue, q); @@ -215,7 +220,44 @@ static void nf_ct_frag6_expire(unsigned long data) goto out; fq_kill(fq); + net = container_of(fq->q.net, struct net, ipv6.frags); + rcu_read_lock(); + dev = dev_get_by_index_rcu(net, fq->iif); + if (!dev) + goto out_rcu_unlock; + + IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); + IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); + + /* Don't send error if the first segment did not arrive. */ + if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) + goto out_rcu_unlock; + + /* + * Only search router table for the head fragment, + * when defraging timeout at PRE_ROUTING HOOK. + */ + if (fq->user == IP6_DEFRAG_CONNTRACK_IN) { + struct sk_buff *head = fq->q.fragments; + + head->dev = dev; + ip6_route_input(head); + if (!skb_dst(head)) + goto out_rcu_unlock; + + /* + * Only an end host needs to send an ICMP "Fragment Reassembly + * Timeout" message, per section 4.5 of RFC2460. + */ + if (!(skb_r6table(head)->rt6i_flags & RTF_LOCAL)) + goto out_rcu_unlock; + /* Send an ICMP "Fragment Reassembly Timeout" message. */ + icmpv6_send(head, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0); + } + +out_rcu_unlock: + rcu_read_unlock(); out: spin_unlock(&fq->q.lock); fq_put(fq); @@ -405,7 +447,11 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, else fq->q.fragments = skb; - skb->dev = NULL; + if (skb->dev) { + fq->iif = skb->dev->ifindex; + skb->dev = NULL; + } + fq->q.stamp = skb->tstamp; fq->q.meat += skb->len; atomic_add(skb->truesize, &fq->q.net->mem); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 88c0a5c..ef4bdd9 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -802,6 +802,7 @@ void ip6_route_input(struct sk_buff *skb) skb_dst_set(skb, fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input)); } +EXPORT_SYMBOL(ip6_route_input); static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, struct flowi *fl, int flags)