All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: davem@davemloft.net
Cc: netfilter-devel@lists.netfilter.org, Patrick McHardy <kaber@trash.net>
Subject: [NETFILTER 08/08]: nf_conntrack: UDPLITE support
Date: Sat, 14 Jul 2007 17:12:44 +0200 (MEST)	[thread overview]
Message-ID: <20070714151200.9829.67499.sendpatchset@localhost.localdomain> (raw)
In-Reply-To: <20070714151150.9829.47674.sendpatchset@localhost.localdomain>

[NETFILTER]: nf_conntrack: UDPLITE support

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 15e277fed17d039cf1866e2232578d50dee24cba
tree 73162bbea0ce866a151ad12fab92c3de8dfc115a
parent 48b2bed5b1229eb77b3df402e70c9c7e8360212d
author Patrick McHardy <kaber@trash.net> Sat, 14 Jul 2007 17:02:32 +0200
committer Patrick McHardy <kaber@trash.net> Sat, 14 Jul 2007 17:05:35 +0200

 net/netfilter/Kconfig                      |   10 +
 net/netfilter/Makefile                     |    1 
 net/netfilter/nf_conntrack_proto_udplite.c |  266 ++++++++++++++++++++++++++++
 3 files changed, 277 insertions(+), 0 deletions(-)

diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 9415b9a..3ac39f1 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -102,6 +102,16 @@ config NF_CT_PROTO_SCTP
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NF_CT_PROTO_UDPLITE
+	tristate 'UDP-Lite protocol connection tracking support (EXPERIMENTAL)'
+	depends on EXPERIMENTAL && NF_CONNTRACK
+	help
+	  With this option enabled, the layer 3 independent connection
+	  tracking code will be able to do state tracking on UDP-Lite
+	  connections.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NF_CONNTRACK_AMANDA
 	tristate "Amanda backup protocol support"
 	depends on NF_CONNTRACK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 3e4a16a..0c054bf 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
 # SCTP protocol connection tracking
 obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
 obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+obj-$(CONFIG_NF_CT_PROTO_UDPLITE) += nf_conntrack_proto_udplite.o
 
 # netlink interface for nf_conntrack
 obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
new file mode 100644
index 0000000..93e747b
--- /dev/null
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -0,0 +1,266 @@
+/* (C) 1999-2001 Paul `Rusty' Russell
+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
+ * (C) 2007 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/udp.h>
+#include <linux/seq_file.h>
+#include <linux/skbuff.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <net/netfilter/nf_conntrack_l4proto.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+
+static unsigned int nf_ct_udplite_timeout __read_mostly = 30*HZ;
+static unsigned int nf_ct_udplite_timeout_stream __read_mostly = 180*HZ;
+
+static int udplite_pkt_to_tuple(const struct sk_buff *skb,
+				unsigned int dataoff,
+				struct nf_conntrack_tuple *tuple)
+{
+	struct udphdr _hdr, *hp;
+
+	hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hp == NULL)
+		return 0;
+
+	tuple->src.u.udp.port = hp->source;
+	tuple->dst.u.udp.port = hp->dest;
+	return 1;
+}
+
+static int udplite_invert_tuple(struct nf_conntrack_tuple *tuple,
+				const struct nf_conntrack_tuple *orig)
+{
+	tuple->src.u.udp.port = orig->dst.u.udp.port;
+	tuple->dst.u.udp.port = orig->src.u.udp.port;
+	return 1;
+}
+
+/* Print out the per-protocol part of the tuple. */
+static int udplite_print_tuple(struct seq_file *s,
+			       const struct nf_conntrack_tuple *tuple)
+{
+	return seq_printf(s, "sport=%hu dport=%hu ",
+			  ntohs(tuple->src.u.udp.port),
+			  ntohs(tuple->dst.u.udp.port));
+}
+
+/* Print out the private part of the conntrack. */
+static int udplite_print_conntrack(struct seq_file *s,
+				   const struct nf_conn *conntrack)
+{
+	return 0;
+}
+
+/* Returns verdict for packet, and may modify conntracktype */
+static int udplite_packet(struct nf_conn *conntrack,
+			  const struct sk_buff *skb,
+			  unsigned int dataoff,
+			  enum ip_conntrack_info ctinfo,
+			  int pf,
+			  unsigned int hooknum)
+{
+	/* If we've seen traffic both ways, this is some kind of UDP
+	   stream.  Extend timeout. */
+	if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
+		nf_ct_refresh_acct(conntrack, ctinfo, skb,
+				   nf_ct_udplite_timeout_stream);
+		/* Also, more likely to be important, and not a probe */
+		if (!test_and_set_bit(IPS_ASSURED_BIT, &conntrack->status))
+			nf_conntrack_event_cache(IPCT_STATUS, skb);
+	} else
+		nf_ct_refresh_acct(conntrack, ctinfo, skb,
+				   nf_ct_udplite_timeout);
+
+	return NF_ACCEPT;
+}
+
+/* Called when a new connection for this protocol found. */
+static int udplite_new(struct nf_conn *conntrack, const struct sk_buff *skb,
+		       unsigned int dataoff)
+{
+	return 1;
+}
+
+static int udplite_error(struct sk_buff *skb, unsigned int dataoff,
+			 enum ip_conntrack_info *ctinfo,
+			 int pf,
+			 unsigned int hooknum)
+{
+	unsigned int udplen = skb->len - dataoff;
+	struct udphdr _hdr, *hdr;
+	unsigned int cscov;
+
+	/* Header is too small? */
+	hdr = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
+	if (hdr == NULL) {
+		if (LOG_INVALID(IPPROTO_UDPLITE))
+			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+				      "nf_ct_udplite: short packet ");
+		return -NF_ACCEPT;
+	}
+
+	cscov = ntohs(hdr->len);
+	if (cscov == 0)
+		cscov = udplen;
+	else if (cscov < sizeof(*hdr) || cscov > udplen) {
+		if (LOG_INVALID(IPPROTO_UDPLITE))
+			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+				"nf_ct_udplite: invalid checksum coverage ");
+		return -NF_ACCEPT;
+	}
+
+	/* UDPLITE mandates checksums */
+	if (!hdr->check) {
+		if (LOG_INVALID(IPPROTO_UDPLITE))
+			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+				      "nf_ct_udplite: checksum missing ");
+		return -NF_ACCEPT;
+	}
+
+	/* Checksum invalid? Ignore. */
+	if (nf_conntrack_checksum && !skb_csum_unnecessary(skb) &&
+	    ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+	     (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING))) {
+		if (pf == PF_INET) {
+			struct iphdr *iph = ip_hdr(skb);
+
+			skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
+						       udplen, IPPROTO_UDPLITE, 0);
+		} else {
+			struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+			__wsum hsum = skb_checksum(skb, 0, dataoff, 0);
+
+			skb->csum = ~csum_unfold(
+				csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
+						udplen, IPPROTO_UDPLITE,
+						csum_sub(0, hsum)));
+		}
+
+		skb->ip_summed = CHECKSUM_NONE;
+		if (__skb_checksum_complete_head(skb, dataoff + cscov)) {
+			if (LOG_INVALID(IPPROTO_UDPLITE))
+				nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
+					      "nf_ct_udplite: bad UDPLite "
+					      "checksum ");
+			return -NF_ACCEPT;
+		}
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+
+	return NF_ACCEPT;
+}
+
+#ifdef CONFIG_SYSCTL
+static unsigned int udplite_sysctl_table_users;
+static struct ctl_table_header *udplite_sysctl_header;
+static struct ctl_table udplite_sysctl_table[] = {
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nf_conntrack_udplite_timeout",
+		.data		= &nf_ct_udplite_timeout,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nf_conntrack_udplite_timeout_stream",
+		.data		= &nf_ct_udplite_timeout_stream,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+	},
+	{
+		.ctl_name	= 0
+	}
+};
+#endif /* CONFIG_SYSCTL */
+
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
+{
+	.l3proto		= PF_INET,
+	.l4proto		= IPPROTO_UDPLITE,
+	.name			= "udplite",
+	.pkt_to_tuple		= udplite_pkt_to_tuple,
+	.invert_tuple		= udplite_invert_tuple,
+	.print_tuple		= udplite_print_tuple,
+	.print_conntrack	= udplite_print_conntrack,
+	.packet			= udplite_packet,
+	.new			= udplite_new,
+	.error			= udplite_error,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &udplite_sysctl_table_users,
+	.ctl_table_header	= &udplite_sysctl_header,
+	.ctl_table		= udplite_sysctl_table,
+#endif
+};
+
+static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
+{
+	.l3proto		= PF_INET6,
+	.l4proto		= IPPROTO_UDPLITE,
+	.name			= "udplite",
+	.pkt_to_tuple		= udplite_pkt_to_tuple,
+	.invert_tuple		= udplite_invert_tuple,
+	.print_tuple		= udplite_print_tuple,
+	.print_conntrack	= udplite_print_conntrack,
+	.packet			= udplite_packet,
+	.new			= udplite_new,
+	.error			= udplite_error,
+#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
+#ifdef CONFIG_SYSCTL
+	.ctl_table_users	= &udplite_sysctl_table_users,
+	.ctl_table_header	= &udplite_sysctl_header,
+	.ctl_table		= udplite_sysctl_table,
+#endif
+};
+
+static int __init nf_conntrack_proto_udplite_init(void)
+{
+	int err;
+
+	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite4);
+	if (err < 0)
+		goto err1;
+	err = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udplite6);
+	if (err < 0)
+		goto err2;
+	return 0;
+err2:
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+err1:
+	return err;
+}
+
+static void __exit nf_conntrack_proto_udplite_exit(void)
+{
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
+	nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
+}
+
+module_init(nf_conntrack_proto_udplite_init);
+module_exit(nf_conntrack_proto_udplite_exit);
+
+MODULE_LICENSE("GPL");

  parent reply	other threads:[~2007-07-14 15:12 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-14 15:12 [NETFILTER 00/08]: Netfilter Update part II Patrick McHardy
2007-07-14 15:12 ` [NETFILTER 01/08]: nf_conntrack: Increment error count on parsing IPv4 header Patrick McHardy
2007-07-15  3:44   ` David Miller
2007-07-14 15:12 ` [NETFILTER 02/08]: nf_conntrack: make l3proto->prepare() generic and renames it Patrick McHardy
2007-07-15  3:45   ` David Miller
2007-07-14 15:12 ` [NETFILTER 03/08]: nf_conntrack: Introduces nf_ct_get_tuplepr and uses it Patrick McHardy
2007-07-14 15:12 ` [NETFILTER 04/08]: nf_conntrack: Don't track locally generated special ICMP error Patrick McHardy
2007-07-15  3:45   ` David Miller
2007-07-14 15:12 ` [NETFILTER 05/08]: Lower *tables printk severity Patrick McHardy
2007-07-15  3:46   ` David Miller
2007-07-14 15:12 ` [NETFILTER 06/08]: x_tables: add connlimit match Patrick McHardy
2007-07-15  3:47   ` David Miller
2007-07-14 15:12 ` [NETFILTER 07/08]: nf_conntrack: mark protocols __read_mostly Patrick McHardy
2007-07-15  3:48   ` David Miller
2007-07-14 15:12 ` Patrick McHardy [this message]
2007-07-14 16:54   ` [NETFILTER 08/08]: nf_conntrack: UDPLITE support Yasuyuki KOZAKAI
     [not found]   ` <200707141654.l6EGs6XG008905@toshiba.co.jp>
2007-07-14 23:05     ` Patrick McHardy
2007-07-16  8:07       ` Yasuyuki KOZAKAI
2007-07-15  3:48   ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070714151200.9829.67499.sendpatchset@localhost.localdomain \
    --to=kaber@trash.net \
    --cc=davem@davemloft.net \
    --cc=netfilter-devel@lists.netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.