[netfilter-cvslog] r4274 - in trunk/patch-o-matic-ng/patchlets/rpc: . linux-2.6.12.4 linux-2.6.12.4/Documentation linux-2.6.12.4/include linux-2.6.12.4/include/linux linux-2.6.12.4/include/linux/netfilter_ipv4 linux-2.6.12.4/net linux-2.6.12.4/net/ipv4 linux-2.6.12.4/net/ipv4/netfilter

laforge at netfilter.org laforge at netfilter.org
Thu Sep 22 12:22:41 CEST 2005


Author: laforge at netfilter.org
Date: 2005-09-22 12:22:38 +0200 (Thu, 22 Sep 2005)
New Revision: 4274

Added:
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/Documentation/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/Documentation/Configure.help.ladd
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ipt_rpc.h
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Config.in.ladd
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Kconfig.ladd
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Makefile.ladd
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
   trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ipt_rpc.c
Modified:
   trunk/patch-o-matic-ng/patchlets/rpc/help
   trunk/patch-o-matic-ng/patchlets/rpc/info
Log:
add 2.6.12.4 support (David Stes)


Modified: trunk/patch-o-matic-ng/patchlets/rpc/help
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/help	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/help	2005-09-22 10:22:38 UTC (rev 4274)
@@ -55,6 +55,8 @@
 
      user at client# rusers $server
 
+The RPC module also supports Legato NetWorker backup.
+Legato NetWorker is based on both Sun RPC and REXEC (see RSH module).
 
 Warning:
 

Modified: trunk/patch-o-matic-ng/patchlets/rpc/info
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/info	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/info	2005-09-22 10:22:38 UTC (rev 4274)
@@ -1,5 +1,4 @@
 Title: rpc connection tracking helper
 Author: "Marcelo Barbosa Lima" <marcelo.lima at dcc.unicamp.br>
-Status: outdated, someone needs to port it to 2.6.x
+Status: maintained by David Stes <stes at pandora.be>
 Repository: extra
-Requires: linux < 2.6.0

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/Documentation/Configure.help.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/Documentation/Configure.help.ladd	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/Documentation/Configure.help.ladd	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,46 @@
+CONFIG_IP_NF_MATCH_STATE
+RPC match support
+CONFIG_IP_NF_MATCH_RPC
+  This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
+  matcher and tracker.
+
+  This option supplies two connection tracking modules;
+  ip_conntrack_rpc_udp and ip_conntrack_rpc_tcp, which track
+  portmapper requests using UDP and TCP respectively.
+
+  This option also adds an RPC match module for iptables, which
+  matches both via the old "record match" method and a new
+  "procedure match" method. The older method matches all RPC
+  procedure packets that relate to previously recorded packets
+  seen querying a portmapper. The newer method matches only
+  those RPC procedure packets explicitly specified by the user,
+  and that can then be related to previously recorded packets
+  seen querying a portmapper.
+
+  These three modules are required if RPCs are to be filtered
+  accurately; as RPCs are allocated pseudo-randomly to UDP and
+  TCP ports as they register with the portmapper.
+
+  Up to 8 portmapper ports per module, and up to 128 RPC
+  procedures per iptables rule, may be specified by the user,
+  to enable effective RPC management.
+
+  The nsrexec option of the RSH/RPC module supports Legato NetWorker backup.
+
+For Legato NetWorker,
+
+add options ip_conntrack_rsh range=16383 ports=7937
+add options ipt_rpc ports=7938
+add options ip_conntrack_rpc_tcp nsrexec=7937 ports=7938
+add options ip_conntrack_rpc_udp ports=7938
+
+iptables -A FORWARD -j ACCEPT -p tcp -m state --state NEW -m tcp --dport 7937
+iptables -A FORWARD -j ACCEPT -p tcp -m state --state NEW -m tcp --dport 7938
+iptables -A FORWARD -j ACCEPT -p udp -m state --state NEW -m udp --dport 7938
+iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT
+iptables -A FORWARD -m state --state RELATED -j ACCEPT
+iptables -A FORWARD -m rpc --rpcs nsrd,nsrmmd,nsrindexd,nsrmmdbd,nsrstat,nsrjb,rap,rapserv -j ACCEPT
+
+
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  If unsure, say `N'.

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ip_conntrack_rpc.h	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ip_conntrack_rpc.h	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,68 @@
+/* RPC extension for IP connection tracking, Version 2.2
+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>
+ *	- original rpc tracking module
+ *	- "recent" connection handling for kernel 2.3+ netfilter
+ *
+ * (C) 2001 by Rusty Russell <rusty at rustcorp.com.au>
+ *	- upgraded conntrack modules to oldnat api - kernel 2.4.0+
+ *
+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter at mq.edu.au>
+ *	- upgraded conntrack modules to newnat api - kernel 2.4.20+
+ *	- extended matching to support filtering on procedures
+ *
+ * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ **
+ */
+
+#include <asm/param.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/stddef.h>
+#include <linux/list.h>
+
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+
+#ifndef _IP_CONNTRACK_RPC_H
+#define _IP_CONNTRACK_RPC_H
+
+#define RPC_PORT       111
+
+
+/* Datum in RPC packets are encoded in XDR */
+#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
+
+/* Fast timeout, to deny DoS atacks */
+#define EXP (60 * HZ)
+
+/* Normal timeouts */
+#define EXPIRES (180 * HZ)
+
+/* For future conections RPC, using client's cache bindings
+ * I'll use ip_conntrack_lock to lock these lists	*/
+
+/* This identifies each request and stores protocol */
+struct request_p {
+	struct list_head list;
+
+	u_int32_t xid;   
+	u_int32_t ip;
+	u_int16_t port;
+	
+	/* Protocol */
+	u_int16_t proto;
+
+	struct timer_list timeout;
+};
+
+static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
+				u_int32_t ip, u_int32_t port) {
+	return (p->xid == xid && p->ip == ip && p->port);
+
+}
+
+#endif /* _IP_CONNTRACK_RPC_H */

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ipt_rpc.h
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ipt_rpc.h	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/include/linux/netfilter_ipv4/ipt_rpc.h	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,35 @@
+/* RPC extension for IP netfilter matching, Version 2.2
+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>
+ *	- original rpc tracking module
+ *	- "recent" connection handling for kernel 2.3+ netfilter
+ *
+ * (C) 2001 by Rusty Russell <rusty at rustcorp.com.au>
+ *	- upgraded conntrack modules to oldnat api - kernel 2.4.0+
+ *
+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter at mq.edu.au>
+ *	- upgraded conntrack modules to newnat api - kernel 2.4.20+
+ *	- extended matching to support filtering on procedures
+ *
+ * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ **
+ */
+
+#ifndef _IPT_RPC_H
+#define _IPT_RPC_H
+
+struct ipt_rpc_data;
+
+struct ipt_rpc_info {
+	int inverse;
+	int strict;
+	const char c_procs[1408];
+	int i_procs;
+	struct ipt_rpc_data *data;
+};
+
+#endif /* _IPT_RPC_H */

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Config.in.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Config.in.ladd	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Config.in.ladd	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,4 @@
+# The simple matches.
+  if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
+    dep_tristate '  RPC match support' CONFIG_IP_NF_MATCH_RPC $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
+  fi

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Kconfig.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Kconfig.ladd	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Kconfig.ladd	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,31 @@
+config IP_NF_MATCH_RPC
+	tristate  'RPC match support'
+	depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
+	help
+	  This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
+	  matcher and tracker.
+	
+	  This option supplies two connection tracking modules;
+	  ip_conntrack_rpc_udp and ip_conntrack_rpc_tcp, which track
+	  portmapper requests using UDP and TCP respectively.
+	
+	  This option also adds an RPC match module for iptables, which
+	  matches both via the old "record match" method and a new
+	  "procedure match" method. The older method matches all RPC
+	  procedure packets that relate to previously recorded packets
+	  seen querying a portmapper. The newer method matches only
+	  those RPC procedure packets explicitly specified by the user,
+	  and that can then be related to previously recorded packets
+	  seen querying a portmapper.
+	
+	  These three modules are required if RPCs are to be filtered
+	  accurately; as RPCs are allocated pseudo-randomly to UDP and
+	  TCP ports as they register with the portmapper.
+	
+	  Up to 8 portmapper ports per module, and up to 128 RPC
+	  procedures per iptables rule, may be specified by the user,
+	  to enable effective RPC management.
+	
+	
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Makefile.ladd
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Makefile.ladd	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/Makefile.ladd	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,4 @@
+# matches
+obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
+export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
+

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,562 @@
+/* RPC extension for IP (TCP) connection tracking, Version 2.2
+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>
+ *	- original rpc tracking module
+ *	- "recent" connection handling for kernel 2.3+ netfilter
+ *
+ * (C) 2001 by Rusty Russell <rusty at rustcorp.com.au>
+ *	- upgraded conntrack modules to oldnat api - kernel 2.4.0+
+ *
+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter at mq.edu.au>
+ *	- upgraded conntrack modules to newnat api - kernel 2.4.20+
+ *	- extended matching to support filtering on procedures
+ * 
+ * (c) 2004,2005 by David Stes <stes at pandora.be>
+ *      - add nsrexec option for Legato NetWorker
+ *	- upgraded to 2.6.12+ conntrack module api
+ *
+ * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ **
+ *	Module load syntax:
+ *	insmod ip_conntrack_rpc_tcp.o nsrexec=<n> ports=port1,...port<MAX_PORTS>
+ *
+ *	Please give the ports of all RPC servers you wish to connect to.
+ *      For example, ports=111,7938 for Legato NetWorker's portmapper on 7938.
+ *	If you don't specify ports, the default will be port 111 (SUN portmap).
+ *
+ *      Please specify nsrexec, the TCP port of the rexec() service of
+ *      Legato NetWorker.  For example, nsrexec=7937
+ *
+ **
+ *	Note to all:
+ *
+ *	RPCs should not be exposed to the internet - ask the Pentagon;
+ *
+ *	  "The unidentified crackers pleaded guilty in July to charges
+ *	   of juvenile delinquency stemming from a string of Pentagon
+ *	   network intrusions in February.
+ *
+ *	   The youths, going by the names TooShort and Makaveli, used
+ *	   a common server security hole to break in, according to
+ *	   Dane Jasper, owner of the California Internet service
+ *	   provider, Sonic. They used the hole, known as the 'statd'
+ *	   exploit, to attempt more than 800 break-ins, Jasper said."
+ *
+ *	From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
+ *	URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
+ **
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/tcp.h>
+
+#include <asm/param.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/stddef.h>
+#include <linux/list.h>
+
+#include <linux/netfilter_ipv4/lockhelp.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
+
+#define MAX_PORTS 8
+static int ports[MAX_PORTS];
+static int ports_n_c = 0;
+static int nsrexec = 0;
+
+#ifdef MODULE_PARM
+module_param(nsrexec,int, 0400);
+MODULE_PARM_DESC(nsrexec, "TCP port of Legato NetWorker's rexec service");
+module_param_array(ports, int, &ports_n_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
+#endif
+
+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>");
+MODULE_DESCRIPTION("RPC TCP connection tracking module");
+MODULE_LICENSE("GPL");
+
+#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
+					format, ## args)
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
+					format, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+DECLARE_RWLOCK(ipct_rpc_tcp_lock);
+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
+#include <linux/netfilter_ipv4/listhelp.h>
+
+/* For future conections RPC, using client's cache bindings
+ * I'll use ip_conntrack_lock to lock these lists	   */
+
+LIST_HEAD(request_p_list_tcp);
+
+
+static void delete_request_p(unsigned long request_p_ul) 
+{
+	struct request_p *p = (void *)request_p_ul;
+	
+	WRITE_LOCK(&ipct_rpc_tcp_lock);
+	LIST_DELETE(&request_p_list_tcp, p);
+	WRITE_UNLOCK(&ipct_rpc_tcp_lock);
+	kfree(p);
+	return;
+}
+
+
+static void req_cl(struct request_p * r)
+{
+	WRITE_LOCK(&ipct_rpc_tcp_lock);
+	del_timer(&r->timeout);
+	LIST_DELETE(&request_p_list_tcp, r);
+	WRITE_UNLOCK(&ipct_rpc_tcp_lock);
+	kfree(r);
+	return;
+}
+
+
+static void clean_request(struct list_head *list)
+{
+	struct list_head *first = list->prev;
+	struct list_head *temp = list->next;
+	struct list_head *aux;
+
+	if (list_empty(list))
+		return;
+
+	while (first != temp) {
+		aux = temp->next;
+		req_cl((struct request_p *)temp);
+		temp = aux;	
+	}
+	req_cl((struct request_p *)temp);
+	return;
+}
+
+
+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
+		     u_int16_t port)
+{
+	struct request_p *req_p;
+	
+	/* Verifies if entry already exists */
+	WRITE_LOCK(&ipct_rpc_tcp_lock);
+	req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
+		struct request_p *, xid, ip, port);
+
+	if (req_p) {
+		/* Refresh timeout */
+		if (del_timer(&req_p->timeout)) {
+			req_p->timeout.expires = jiffies + EXP;
+			add_timer(&req_p->timeout);	
+		} 
+		WRITE_UNLOCK(&ipct_rpc_tcp_lock);
+		return;	
+
+	}
+	WRITE_UNLOCK(&ipct_rpc_tcp_lock);
+	
+	/* Allocate new request_p */
+	req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
+	if (!req_p) {
+ 		DEBUGP("can't allocate request_p\n");
+		return;			
+	}
+
+        req_p->list.next = NULL;
+        req_p->list.prev = NULL;
+        req_p->xid = xid;
+        req_p->ip = ip;
+        req_p->port = port;
+        req_p->proto = proto;
+      
+	/* Initialize timer */
+	init_timer(&req_p->timeout);
+        req_p->timeout.expires = jiffies + EXP;
+	req_p->timeout.data = (unsigned long)req_p;
+	req_p->timeout.function = delete_request_p;
+	add_timer(&req_p->timeout); 
+
+	/* Put in list */
+	WRITE_LOCK(&ipct_rpc_tcp_lock);
+	list_prepend(&request_p_list_tcp, req_p);
+	WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
+	return; 
+}
+
+
+static int check_rpc_packet(const u_int32_t *data,
+			int dir, struct ip_conntrack *ct,
+			struct list_head request_p_list)
+{
+	u_int32_t xid;
+        int ret = NF_ACCEPT;
+	struct request_p *req_p;
+	struct ip_conntrack_expect *exp;
+
+
+	if (ct == NULL) {
+		DEBUGP("ct is NULL");
+		return ret;
+	}
+
+        /* Translstion's buffer for XDR */
+        u_int16_t port_buf;
+
+	/* Get XID */
+	xid = *data;
+
+ 	/* This does sanity checking on RPC payloads,
+	 * and permits only the RPC "get port" (3)
+	 * in authorised procedures in client
+	 * communications with the portmapper.
+	 */
+
+	/* perform direction dependant RPC work */
+	if (dir == IP_CT_DIR_ORIGINAL) {
+
+		data += 5;
+
+		/* Get RPC requestor */
+		if (IXDR_GET_INT32(data) != 3) {
+			DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
+			return NF_ACCEPT;
+		}
+		DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
+
+		data++;
+
+		/* Jump Credentials and Verfifier */
+		data += IXDR_GET_INT32(data) + 2;
+		data += IXDR_GET_INT32(data) + 2;
+
+		/* Get RPC procedure */
+		DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
+			(unsigned int)IXDR_GET_INT32(data));
+
+		/* Get RPC protocol and store against client parameters */
+		data = data + 2;
+		alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
+				ct->tuplehash[dir].tuple.src.u.all);
+
+		DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
+			xid, IXDR_GET_INT32(data),
+			NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
+			ntohs(ct->tuplehash[dir].tuple.src.u.all));
+
+		DEBUGP("allocated RPC request for protocol %u. [done]\n",
+			(unsigned int)IXDR_GET_INT32(data));
+
+	} else {
+
+		/* Check for returning packet's stored counterpart */
+		req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
+				  struct request_p *, xid,
+				  ct->tuplehash[!dir].tuple.src.ip,
+				  ct->tuplehash[!dir].tuple.src.u.all);
+
+		/* Drop unexpected packets */
+		if (!req_p) {
+			DEBUGP("packet is not expected. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Verifies if packet is really an RPC reply packet */
+		data++;
+		if (IXDR_GET_INT32(data) != 1) {
+			DEBUGP("packet is not a valid RPC reply. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Is status accept? */
+		data++;
+		if (IXDR_GET_INT32(data)) {
+			DEBUGP("packet is not an RPC accept. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Get Verifier length. Jump verifier */
+		data++;
+		data = data + IXDR_GET_INT32(data) + 2;
+
+		/* Is accpet status "success"? */
+		if (IXDR_GET_INT32(data)) {
+			DEBUGP("packet is not an RPC accept status of success. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Get server port number */	  
+		data++;
+		port_buf = (u_int16_t) IXDR_GET_INT32(data);
+
+		/* If a packet has made it this far then it deserves an
+		 * expectation ...  if port == 0, then this service is 
+		 * not going to be registered.
+		 */
+		if (port_buf && port_buf != nsrexec) {
+			DEBUGP("port found: %u\n", port_buf);
+
+                        exp = ip_conntrack_expect_alloc();
+                        if (!exp) {
+                          ret = NF_DROP;
+                          goto out;
+                        }
+
+			/* Watch out, Radioactive-Man! */
+			exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+			exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
+			exp->mask.src.ip = 0xffffffff;
+			exp->mask.dst.ip = 0xffffffff;
+
+			switch (req_p->proto) {
+				case IPPROTO_UDP:
+					exp->tuple.src.u.udp.port = 0;
+					exp->tuple.dst.u.udp.port = htons(port_buf);
+					exp->tuple.dst.protonum = IPPROTO_UDP;
+					exp->mask.src.u.udp.port = 0;
+					exp->mask.dst.u.udp.port = htons(0xffff);
+					exp->mask.dst.protonum = 0xff;
+					break;
+
+				case IPPROTO_TCP:
+					exp->tuple.src.u.tcp.port = 0;
+					exp->tuple.dst.u.tcp.port = htons(port_buf);
+					exp->tuple.dst.protonum = IPPROTO_TCP;
+					exp->mask.src.u.tcp.port = 0;
+					exp->mask.dst.u.tcp.port = htons(0xffff);
+					exp->mask.dst.protonum = 0xff;
+					break;
+			}
+			exp->expectfn = NULL;
+			exp->master = ct;
+
+			if (exp->master->helper == NULL) {
+				DEBUGP("master helper NULL");
+				ret = NF_ACCEPT;
+			}
+			
+			DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
+				NIPQUAD(exp->tuple.src.ip),
+				NIPQUAD(exp->tuple.dst.ip),
+				port_buf, req_p->proto);
+
+			DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
+				NIPQUAD(exp->mask.src.ip),
+				NIPQUAD(exp->mask.dst.ip),
+				exp->mask.dst.protonum);
+
+			if (ip_conntrack_expect_related(exp) != 0) {
+		                ip_conntrack_expect_free(exp);
+        		        ret = NF_DROP;
+        		}
+
+		}
+
+out:
+		req_cl(req_p);
+
+		DEBUGP("packet evaluated. [expect]\n");
+	}
+
+	return ret;
+
+}
+
+
+/* RPC TCP helper */
+/* static int help(const struct iphdr *iph, size_t len,
+		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) */
+static int help(struct sk_buff **pskb,
+		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+{
+	int dir;
+	int crp_ret;
+	struct tcphdr _tcph, *tcph;
+	const u_int32_t *data;
+	size_t tcplen;
+        struct iphdr *iph;
+        size_t len;
+
+	/* Not whole TCP header? */
+        iph=(*pskb)->nh.iph;
+	tcph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_tcph),&_tcph);
+	if (!tcph)
+		return NF_ACCEPT;
+
+	len = (*pskb)->len; /* stes */
+	data = (const u_int32_t *)tcph + tcph->doff;
+        tcplen = len - iph->ihl * 4;
+	dir = CTINFO2DIR(ctinfo);
+
+	DEBUGP("new packet to evaluate ..\n");
+
+	/* This works for packets like handshake packets, ignore */
+	if (len == ((tcph->doff + iph->ihl) * 4)) {
+		DEBUGP("packet has no data (may still be handshaking). [skip]\n");
+		return NF_ACCEPT;
+	}
+
+	/* Until there's been traffic both ways, don't look in packets. */
+	if (ctinfo != IP_CT_ESTABLISHED
+	    && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+		DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
+		DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
+		DEBUGP("packet is not yet part of a two way stream. [skip]\n");
+		return NF_ACCEPT;
+	}
+
+	/* Not whole TCP header? */
+	if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
+		DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
+		DEBUGP("packet does not contain a complete TCP header. [skip]\n");
+		return NF_ACCEPT;
+	}
+
+	/* FIXME: Source route IP option packets --RR */
+	if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
+			 csum_partial((char *) tcph, tcplen, 0))) {
+		DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
+		     tcph, tcplen, NIPQUAD(iph->saddr),
+		     NIPQUAD(iph->daddr));
+		DEBUGP("[note: failure to get past this error may indicate source routing]\n");
+		DEBUGP("packet contains a bad checksum. [skip]\n");
+		return NF_ACCEPT;
+	}
+
+	/* perform direction dependant protocol work */
+	if (dir == IP_CT_DIR_ORIGINAL) {
+
+		DEBUGP("packet is from the initiator. [cont]\n");
+
+		/* Tests if packet len is ok */
+		if ((tcplen - (tcph->doff * 4)) != 60) {
+			DEBUGP("packet length is not correct. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+	} else {
+
+		DEBUGP("packet is from the receiver. [cont]\n");
+
+		/* Tests if packet len is ok */
+		if ((tcplen - (tcph->doff * 4)) != 32) {
+			DEBUGP("packet length is not correct. [skip]\n");
+			return NF_ACCEPT;
+		}
+	}
+
+	/* Get to the data */
+	data++;
+
+	/* Check the RPC data */
+	crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
+
+	return crp_ret;
+
+}
+
+
+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
+static char rpc_names[MAX_PORTS][10];
+
+static void fini(void);
+
+static int __init init(void)
+{
+	int port, ret;
+	char *tmpname;
+
+	/* If no port given, default to standard RPC port */
+	if (ports[0] == 0)
+		ports[0] = RPC_PORT;
+
+	for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
+		memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
+
+		tmpname = &rpc_names[port][0];
+		if (ports[port] == RPC_PORT)
+			sprintf(tmpname, "rpc");
+		else
+			sprintf(tmpname, "rpc-%d", ports[port]);
+		rpc_helpers[port].name = tmpname;
+
+		rpc_helpers[port].me = THIS_MODULE;
+		rpc_helpers[port].max_expected = 1;
+		rpc_helpers[port].timeout = 5 * 60; /* stes */
+
+		rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
+		rpc_helpers[port].mask.dst.protonum = 0xff;
+
+		/* RPC can come from ports 0:65535 to ports[port] (111) */
+		rpc_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
+		rpc_helpers[port].mask.src.u.tcp.port = htons(0xffff);
+		rpc_helpers[port].mask.dst.u.tcp.port = htons(0x0);
+
+		rpc_helpers[port].help = help;
+
+		PRINTK("registering helper for port #%d: %d/TCP\n", port, ports[port]);
+		PRINTK("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+			NIPQUAD(rpc_helpers[port].tuple.dst.ip),
+			ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
+			NIPQUAD(rpc_helpers[port].tuple.src.ip),
+			ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
+		PRINTK("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+			NIPQUAD(rpc_helpers[port].mask.dst.ip),
+			ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
+			NIPQUAD(rpc_helpers[port].mask.src.ip),
+			ntohs(rpc_helpers[port].mask.src.u.tcp.port));
+
+		ret = ip_conntrack_helper_register(&rpc_helpers[port]);
+
+		if (ret) {
+			printk("ERROR registering port %d\n",
+				ports[port]);
+			fini();
+			return -EBUSY;
+		}
+		ports_n_c++;
+	}
+
+	PRINTK("%s Legato NetWorker support for port %d/TCP\n", (nsrexec)?"enabling":"disabling", nsrexec);
+
+	return 0;
+}
+
+
+/* This function is intentionally _NOT_ defined as __exit, because 
+ * it is needed by the init function */
+static void fini(void)
+{
+	int port;
+
+	DEBUGP("cleaning request list\n");
+	clean_request(&request_p_list_tcp);
+
+	for (port = 0; (port < ports_n_c) && ports[port]; port++) {
+		DEBUGP("unregistering port %d\n", ports[port]);
+		ip_conntrack_helper_unregister(&rpc_helpers[port]);
+	}
+}
+
+
+module_init(init);
+module_exit(fini);
+
+struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
+EXPORT_SYMBOL(request_p_list_tcp);
+EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
+EXPORT_SYMBOL(ipct_rpc_tcp_lock);
+

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_udp.c	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ip_conntrack_rpc_udp.c	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,536 @@
+/* RPC extension for IP (UDP) connection tracking, Version 2.2
+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>
+ *	- original rpc tracking module
+ *	- "recent" connection handling for kernel 2.3+ netfilter
+ *
+ * (C) 2001 by Rusty Russell <rusty at rustcorp.com.au>
+ *	- upgraded conntrack modules to oldnat api - kernel 2.4.0+
+ *
+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter at mq.edu.au>
+ *	- upgraded conntrack modules to newnat api - kernel 2.4.20+
+ *	- extended matching to support filtering on procedures
+ * 
+ * (c) 2004,2005 by David Stes <stes at pandora.be>
+ *	- upgraded to 2.6.12+ conntrack module api
+ *
+ * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ **
+ *	Module load syntax:
+ *	insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
+ *
+ *	Please give the ports of all RPC servers you wish to connect to.
+ *	If you don't specify ports, the default will be port 111.
+ **
+ *	Note to all:
+ *
+ *	RPCs should not be exposed to the internet - ask the Pentagon;
+ *
+ *	  "The unidentified crackers pleaded guilty in July to charges
+ *	   of juvenile delinquency stemming from a string of Pentagon
+ *	   network intrusions in February.
+ *
+ *	   The youths, going by the names TooShort and Makaveli, used
+ *	   a common server security hole to break in, according to
+ *	   Dane Jasper, owner of the California Internet service
+ *	   provider, Sonic. They used the hole, known as the 'statd'
+ *	   exploit, to attempt more than 800 break-ins, Jasper said."
+ *
+ *	From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
+ *	URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
+ **
+ */
+
+#include <linux/module.h>
+#include <linux/netfilter.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+#include <net/udp.h>
+
+#include <asm/param.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/stddef.h>
+#include <linux/list.h>
+
+#include <linux/netfilter_ipv4/lockhelp.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
+
+#define MAX_PORTS 8
+static int ports[MAX_PORTS];
+static int ports_n_c = 0;
+
+#ifdef MODULE_PARM
+module_param_array(ports, int, &ports_n_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
+#endif
+
+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>");
+MODULE_DESCRIPTION("RPC UDP connection tracking module");
+MODULE_LICENSE("GPL");
+
+#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
+					format, ## args)
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
+					format, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+DECLARE_RWLOCK(ipct_rpc_udp_lock);
+#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
+#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
+#include <linux/netfilter_ipv4/listhelp.h>
+
+/* For future conections RPC, using client's cache bindings
+ * I'll use ip_conntrack_lock to lock these lists           */
+
+LIST_HEAD(request_p_list_udp);
+
+
+static void delete_request_p(unsigned long request_p_ul)
+{
+	struct request_p *p = (void *)request_p_ul;
+	
+	WRITE_LOCK(&ipct_rpc_udp_lock);
+	LIST_DELETE(&request_p_list_udp, p);
+	WRITE_UNLOCK(&ipct_rpc_udp_lock);
+	kfree(p);
+	return;
+}
+
+
+static void req_cl(struct request_p * r)
+{
+	WRITE_LOCK(&ipct_rpc_udp_lock);
+	del_timer(&r->timeout);
+	LIST_DELETE(&request_p_list_udp, r);
+	WRITE_UNLOCK(&ipct_rpc_udp_lock);
+	kfree(r);
+	return;
+}
+
+
+static void clean_request(struct list_head *list)
+{
+	struct list_head *first = list->prev;
+	struct list_head *temp = list->next;
+	struct list_head *aux;
+
+	if (list_empty(list))
+		return;
+
+	while (first != temp) {
+		aux = temp->next;
+		req_cl((struct request_p *)temp);
+		temp = aux;	
+	}
+	req_cl((struct request_p *)temp);
+	return;
+}
+
+
+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
+		     u_int16_t port)
+{
+	struct request_p *req_p;
+        
+	/* Verifies if entry already exists */
+	WRITE_LOCK(&ipct_rpc_udp_lock);
+	req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
+		struct request_p *, xid, ip, port);
+
+	if (req_p) {
+		/* Refresh timeout */
+		if (del_timer(&req_p->timeout)) {
+			req_p->timeout.expires = jiffies + EXP;
+			add_timer(&req_p->timeout);	
+		} 
+		WRITE_UNLOCK(&ipct_rpc_udp_lock);
+		return;	
+
+	}
+	WRITE_UNLOCK(&ipct_rpc_udp_lock);
+	
+	/* Allocate new request_p */
+	req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
+	if (!req_p) {
+ 		DEBUGP("can't allocate request_p\n");
+		return;			
+	}
+
+        req_p->list.next = NULL;
+        req_p->list.prev = NULL;
+        req_p->xid = xid;
+        req_p->ip = ip;
+        req_p->port = port;
+        req_p->proto = proto;
+      
+	/* Initialize timer */
+	init_timer(&req_p->timeout);
+        req_p->timeout.expires = jiffies + EXP;
+	req_p->timeout.data = (unsigned long)req_p;
+	req_p->timeout.function = delete_request_p;
+	add_timer(&req_p->timeout); 
+
+	/* Put in list */
+	WRITE_LOCK(&ipct_rpc_udp_lock);
+	list_prepend(&request_p_list_udp, req_p);
+	WRITE_UNLOCK(&ipct_rpc_udp_lock); 
+	return; 
+
+}
+
+
+static int check_rpc_packet(const u_int32_t *data,
+			int dir, struct ip_conntrack *ct,
+			struct list_head request_p_list)
+{
+        int ret = NF_ACCEPT;
+	u_int32_t xid;
+	struct request_p *req_p;
+	struct ip_conntrack_expect *exp;
+
+	/* Translstion's buffer for XDR */
+	u_int16_t port_buf;
+
+
+	/* Get XID */
+	xid = *data;
+
+ 	/* This does sanity checking on RPC payloads,
+	 * and permits only the RPC "get port" (3)
+	 * in authorised procedures in client
+	 * communications with the portmapper.
+	 */
+
+	/* perform direction dependant RPC work */
+	if (dir == IP_CT_DIR_ORIGINAL) {
+
+		data += 5;
+
+		/* Get RPC requestor */
+		if (IXDR_GET_INT32(data) != 3) {
+			DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
+			return NF_ACCEPT;
+		}
+		DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
+
+		data++;
+
+		/* Jump Credentials and Verfifier */
+		data = data + IXDR_GET_INT32(data) + 2;
+		data = data + IXDR_GET_INT32(data) + 2;
+
+		/* Get RPC procedure */
+		DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
+			(unsigned int)IXDR_GET_INT32(data));
+
+		/* Get RPC protocol and store against client parameters */
+		data = data + 2;
+		alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
+				ct->tuplehash[dir].tuple.src.u.all);
+
+		DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
+			xid, IXDR_GET_INT32(data),
+			NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
+			ntohs(ct->tuplehash[dir].tuple.src.u.all));
+
+		DEBUGP("allocated RPC request for protocol %u. [done]\n",
+			(unsigned int)IXDR_GET_INT32(data));
+
+	} else {
+
+		/* Check for returning packet's stored counterpart */
+		req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
+				  struct request_p *, xid,
+				  ct->tuplehash[!dir].tuple.src.ip,
+				  ct->tuplehash[!dir].tuple.src.u.all);
+
+		/* Drop unexpected packets */
+		if (!req_p) {
+			DEBUGP("packet is not expected. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Verifies if packet is really an RPC reply packet */
+		data++;
+		if (IXDR_GET_INT32(data) != 1) {
+			DEBUGP("packet is not a valid RPC reply. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Is status accept? */
+		data++;
+		if (IXDR_GET_INT32(data)) {
+			DEBUGP("packet is not an RPC accept. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Get Verifier length. Jump verifier */
+		data++;
+		data = data + IXDR_GET_INT32(data) + 2;
+
+		/* Is accpet status "success"? */
+		if (IXDR_GET_INT32(data)) {
+			DEBUGP("packet is not an RPC accept status of success. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Get server port number */	  
+		data++;
+		port_buf = (u_int16_t) IXDR_GET_INT32(data);
+
+		/* If a packet has made it this far then it deserves an
+		 * expectation ...  if port == 0, then this service is 
+		 * not going to be registered.
+		 */
+		if (port_buf) {
+			DEBUGP("port found: %u\n", port_buf);
+
+                        exp = ip_conntrack_expect_alloc();
+                        if (!exp) {
+                          ret = NF_DROP;
+                          goto out;
+                        }
+
+			/* Watch out, Radioactive-Man! */
+			exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+			exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
+			exp->mask.src.ip = 0xffffffff;
+			exp->mask.dst.ip = 0xffffffff;
+
+			switch (req_p->proto) {
+				case IPPROTO_UDP:
+					exp->tuple.src.u.udp.port = 0;
+					exp->tuple.dst.u.udp.port = htons(port_buf);
+					exp->tuple.dst.protonum = IPPROTO_UDP;
+					exp->mask.src.u.udp.port = 0;
+					exp->mask.dst.u.udp.port = htons(0xffff);
+					exp->mask.dst.protonum = 0xff;
+					break;
+
+				case IPPROTO_TCP:
+					exp->tuple.src.u.tcp.port = 0;
+					exp->tuple.dst.u.tcp.port = htons(port_buf);
+					exp->tuple.dst.protonum = IPPROTO_TCP;
+					exp->mask.src.u.tcp.port = 0;
+					exp->mask.dst.u.tcp.port = htons(0xffff);
+					exp->mask.dst.protonum = 0xff;
+					break;
+			}
+			exp->expectfn = NULL;
+			exp->master = ct;
+
+			DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
+				NIPQUAD(exp->tuple.src.ip),
+				NIPQUAD(exp->tuple.dst.ip),
+				port_buf, req_p->proto);
+
+			DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
+				NIPQUAD(exp->mask.src.ip),
+				NIPQUAD(exp->mask.dst.ip),
+				exp->mask.dst.protonum);
+
+			if (ip_conntrack_expect_related(exp) != 0) {
+		                ip_conntrack_expect_free(exp);
+        		        ret = NF_DROP;
+        		}
+		}
+
+out:
+		req_cl(req_p);
+
+		DEBUGP("packet evaluated. [expect]\n");
+	}
+
+	return ret;
+}
+
+
+/* RPC UDP helper */
+/* static int help(const struct iphdr *iph, size_t len,
+		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) */
+static int help(struct sk_buff **pskb,
+		struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
+{
+	int dir;
+	int crp_ret;
+	struct udphdr _udph, *udph;
+	const u_int32_t *data;
+	size_t udplen;
+        struct iphdr *iph;
+        size_t len;
+	const u_int16_t *chsm;
+
+	/* Not whole UDP header? */
+        iph=(*pskb)->nh.iph;
+	udph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_udph),&_udph);
+	if (!udph)
+		return NF_ACCEPT;
+
+	len = (*pskb)->len; /* stes */
+	data = (const u_int32_t *)udph + 2;
+        udplen = len - iph->ihl * 4;
+	dir = CTINFO2DIR(ctinfo);
+
+	/* Checksum */
+        chsm = (const u_int16_t *)udph + 3;
+
+	DEBUGP("new packet to evaluate ..\n");
+
+	/* Not whole UDP header? */
+	if (udplen < sizeof(struct udphdr)) {
+		DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
+		DEBUGP("packet does not contain a complete UDP header. [skip]\n");
+		return NF_ACCEPT;
+	}
+
+	/* FIXME: Source route IP option packets --RR */
+	if (*chsm) {
+		if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
+		    csum_partial((char *)udph, udplen, 0))) {
+			DEBUGP("[note: failure to get past this error may indicate source routing]\n");
+			DEBUGP("packet contains a bad checksum. [skip]\n");
+			return NF_ACCEPT;
+		   } 
+	}
+
+	/* perform direction dependant protocol work */
+	if (dir == IP_CT_DIR_ORIGINAL) {
+
+		DEBUGP("packet is from the initiator. [cont]\n");
+
+		/* Tests if packet len is ok */
+		if ((udplen - sizeof(struct udphdr)) != 56) {
+			DEBUGP("packet length is not correct. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+	} else {
+
+		DEBUGP("packet is from the receiver. [cont]\n");
+
+		/* Until there's been traffic both ways, don't look in packets. */
+		if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
+			DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
+			DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
+			DEBUGP("packet is not yet part of a two way stream. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+		/* Tests if packet len is ok */
+			if ((udplen - sizeof(struct udphdr)) != 28) {
+			DEBUGP("packet length is not correct. [skip]\n");
+			return NF_ACCEPT;
+		}
+
+	}
+
+	/* Get to the data */
+	/* udp *data == *correct */
+
+	/* Check the RPC data */
+	crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
+
+	return crp_ret;
+
+}
+
+
+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
+static char rpc_names[MAX_PORTS][10];
+
+static void fini(void);
+
+static int __init init(void)
+{
+	int port, ret;
+	char *tmpname;
+
+	/* If no port given, default to standard RPC port */
+	if (ports[0] == 0)
+		ports[0] = RPC_PORT;
+
+	for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
+		memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
+
+		tmpname = &rpc_names[port][0];
+		if (ports[port] == RPC_PORT)
+			sprintf(tmpname, "rpc");
+		else
+			sprintf(tmpname, "rpc-%d", ports[port]);
+		rpc_helpers[port].name = tmpname;
+
+		rpc_helpers[port].me = THIS_MODULE;
+		rpc_helpers[port].max_expected = 1;
+		rpc_helpers[port].timeout = 5 * 60; /* stes */
+
+		rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
+		rpc_helpers[port].mask.dst.protonum = 0xff;
+
+		/* RPC can come from ports 0:65535 to ports[port] (111) */
+		rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
+		rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
+		rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
+
+		rpc_helpers[port].help = help;
+
+		PRINTK("registering helper for port #%d: %d/UDP\n", port, ports[port]);
+		PRINTK("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+			NIPQUAD(rpc_helpers[port].tuple.dst.ip),
+			ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
+			NIPQUAD(rpc_helpers[port].tuple.src.ip),
+			ntohs(rpc_helpers[port].tuple.src.u.udp.port));
+		PRINTK("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
+			NIPQUAD(rpc_helpers[port].mask.dst.ip),
+			ntohs(rpc_helpers[port].mask.dst.u.udp.port),
+			NIPQUAD(rpc_helpers[port].mask.src.ip),
+			ntohs(rpc_helpers[port].mask.src.u.udp.port));
+
+		ret = ip_conntrack_helper_register(&rpc_helpers[port]);
+
+		if (ret) {
+			printk("ERROR registering port %d\n",
+				ports[port]);
+			fini();
+			return -EBUSY;
+		}
+		ports_n_c++;
+	}
+	return 0;
+}
+
+
+/* This function is intentionally _NOT_ defined as __exit, because 
+ * it is needed by the init function */
+static void fini(void)
+{
+	int port;
+
+	DEBUGP("cleaning request list\n");
+	clean_request(&request_p_list_udp);
+
+	for (port = 0; (port < ports_n_c) && ports[port]; port++) {
+		DEBUGP("unregistering port %d\n", ports[port]);
+		ip_conntrack_helper_unregister(&rpc_helpers[port]);
+	}
+}
+
+
+module_init(init);
+module_exit(fini);
+
+struct module *ip_conntrack_rpc_udp = THIS_MODULE;
+EXPORT_SYMBOL(request_p_list_udp);
+EXPORT_SYMBOL(ip_conntrack_rpc_udp);
+EXPORT_SYMBOL(ipct_rpc_udp_lock);
+

Added: trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ipt_rpc.c
===================================================================
--- trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ipt_rpc.c	2005-09-22 10:18:12 UTC (rev 4273)
+++ trunk/patch-o-matic-ng/patchlets/rpc/linux-2.6.12.4/net/ipv4/netfilter/ipt_rpc.c	2005-09-22 10:22:38 UTC (rev 4274)
@@ -0,0 +1,439 @@
+/* RPC extension for IP connection matching, Version 2.2
+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>
+ *	- original rpc tracking module
+ *	- "recent" connection handling for kernel 2.3+ netfilter
+ *
+ * (C) 2001 by Rusty Russell <rusty at rustcorp.com.au>
+ *	- upgraded conntrack modules to oldnat api - kernel 2.4.0+
+ *
+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter at mq.edu.au>
+ *	- upgraded conntrack modules to newnat api - kernel 2.4.20+
+ *	- extended matching to support filtering on procedures
+ * 
+ * (c) 2004,2005 by David Stes <stes at pandora.be>
+ *	- upgraded to 2.6.12+ conntrack module api
+ *
+ * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ **
+ *	Module load syntax:
+ *	insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
+ *
+ *	Please give the ports of all RPC servers you wish to connect to.
+ *	If you don't specify ports, the default will be port 111.
+ **
+ *	Note to all:
+ *
+ *	RPCs should not be exposed to the internet - ask the Pentagon;
+ *
+ *	  "The unidentified crackers pleaded guilty in July to charges
+ *	   of juvenile delinquency stemming from a string of Pentagon
+ *	   network intrusions in February.
+ *
+ *	   The youths, going by the names TooShort and Makaveli, used
+ *	   a common server security hole to break in, according to
+ *	   Dane Jasper, owner of the California Internet service
+ *	   provider, Sonic. They used the hole, known as the 'statd'
+ *	   exploit, to attempt more than 800 break-ins, Jasper said."
+ *
+ *	From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
+ *	URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
+ **
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
+#include <linux/netfilter_ipv4/lockhelp.h>
+#include <linux/netfilter_ipv4/ipt_rpc.h>
+
+#define MAX_PORTS 8
+static int ports[MAX_PORTS];
+static int ports_n_c = 0;
+
+#ifdef MODULE_PARM
+module_param_array(ports, int, &ports_n_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
+#endif
+
+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima at dcc.unicamp.br>");
+MODULE_DESCRIPTION("RPC connection matching module");
+MODULE_LICENSE("GPL");
+
+#define PRINTK(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
+					format, ## args)
+
+#if 0
+#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
+					format, ## args)
+#else
+#define DEBUGP(format, args...)
+#endif
+
+/* EXPORT_NO_SYMBOLS; */
+
+/* vars from ip_conntrack_rpc_tcp */
+extern struct list_head request_p_list_tcp;
+extern struct module *ip_conntrack_rpc_tcp;
+
+/* vars from ip_conntrack_rpc_udp */
+extern struct list_head request_p_list_udp;
+extern struct module *ip_conntrack_rpc_udp;
+
+DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
+DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
+
+#define ASSERT_READ_LOCK(x)					\
+do {								\
+	if (x == &request_p_list_udp)				\
+		MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);	\
+	else if (x == &request_p_list_tcp)			\
+		MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);	\
+} while (0)
+
+#define ASSERT_WRITE_LOCK(x)					\
+do {								\
+	if (x == &request_p_list_udp)				\
+		MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);	\
+	else if (x == &request_p_list_tcp)			\
+		MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);	\
+} while (0)
+
+#include <linux/netfilter_ipv4/listhelp.h>
+
+const int IPT_RPC_CHAR_LEN = 11;
+
+
+static int k_atoi(char *string)
+{
+	unsigned int result = 0;
+	int maxoctet = IPT_RPC_CHAR_LEN;
+
+	for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
+		if (*string < 0)
+			return(0);
+		if (*string == 0)
+			break;
+		if (*string < 48 || *string > 57) {
+			return(0);
+		}
+		result = result * 10 + ( *string - 48 );
+	}
+	return(result);
+}
+
+
+static int match_rpcs(char *c_procs, int i_procs, int proc)
+{
+	int   proc_ctr;
+	char *proc_ptr;
+	unsigned int proc_num;
+
+	DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
+
+	if (i_procs == -1)
+		return 1;
+
+	for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
+
+		proc_ptr = c_procs;
+		proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
+		proc_num = k_atoi(proc_ptr);
+
+		if (proc_num == proc)
+			return 1;
+	}
+
+	return 0;
+}
+
+
+static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
+			int *hotdrop, int dir, struct ip_conntrack *ct,
+			int offset, struct list_head request_p_list)
+{
+	const struct ipt_rpc_info *rpcinfo = matchinfo;
+	struct request_p *req_p;
+	u_int32_t xid;
+
+
+	/* Get XID */
+	xid = *data;
+
+ 	/* This does sanity checking on RPC payloads,
+	 * and permits only the RPC "get port" (3)
+	 * in authorised procedures in client
+	 * communications with the portmapper.
+	 */
+
+	data += 5;
+
+	/* Get RPC requestor */
+	if (IXDR_GET_INT32(data) != 3) {
+		DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
+		if(rpcinfo->strict == 1)
+			*hotdrop = 1;
+		return 0;
+	}
+	DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
+
+	data++;
+
+	/* Jump Credentials and Verfifier */
+	data = data + IXDR_GET_INT32(data) + 2;
+	data = data + IXDR_GET_INT32(data) + 2;
+
+	/* Get RPC procedure */
+	if (match_rpcs((char *)&rpcinfo->c_procs,
+	    rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
+		DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
+			(unsigned int)IXDR_GET_INT32(data));
+
+		/* If the RPC conntrack half entry already exists .. */
+
+		switch (ct->tuplehash[0].tuple.dst.protonum) {
+			case IPPROTO_UDP:
+				WRITE_LOCK(&ipct_rpc_udp_lock);
+			case IPPROTO_TCP:
+				WRITE_LOCK(&ipct_rpc_tcp_lock);
+		}
+		req_p = LIST_FIND(&request_p_list, request_p_cmp,
+				  struct request_p *, xid,
+				  ct->tuplehash[dir].tuple.src.ip,
+				  ct->tuplehash[dir].tuple.src.u.all);
+
+		if (req_p) {
+			DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
+				xid, ct->tuplehash[dir].tuple.dst.protonum,
+				NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
+				ntohs(ct->tuplehash[dir].tuple.src.u.all));
+
+			/* .. remove it */
+			if (del_timer(&req_p->timeout))
+				req_p->timeout.expires = 0;
+
+       			LIST_DELETE(&request_p_list, req_p);
+			DEBUGP("RPC req_p removed. [done]\n");
+
+		} else {
+			DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
+				xid, ct->tuplehash[dir].tuple.dst.protonum,
+				NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
+				ntohs(ct->tuplehash[dir].tuple.src.u.all));
+
+		}
+		switch (ct->tuplehash[0].tuple.dst.protonum) {
+			case IPPROTO_UDP:
+				WRITE_UNLOCK(&ipct_rpc_udp_lock);
+			case IPPROTO_TCP:
+				WRITE_UNLOCK(&ipct_rpc_tcp_lock);
+		}
+
+		if(rpcinfo->strict == 1)
+			*hotdrop = 1;
+		return 0;
+	}
+
+	DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
+		(unsigned int)IXDR_GET_INT32(data));
+	return (1 && (!offset));
+}
+
+
+
+/* static int match(const struct sk_buff *skb, const struct net_device *in,
+		 const struct net_device *out, const void *matchinfo,
+		 int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
+*/
+static int match(const struct sk_buff *skb, const struct net_device *in,
+		 const struct net_device *out, const void *matchinfo,
+		 int offset, int *hotdrop)
+{
+	struct ip_conntrack *ct;
+	enum ip_conntrack_info ctinfo;
+	const u_int32_t *data;
+	enum ip_conntrack_dir dir;
+	const struct tcphdr *tcp;
+	const struct ipt_rpc_info *rpcinfo = matchinfo;
+	int port, portsok;
+	int tval;
+	struct iphdr *ip; /* stes */
+        void *hdr; /* stes */
+        u_int16_t datalen; /* stes */
+
+	/* Initialization stes - see 2.4 ip_tables.c ipt_do_table() */
+	ip = skb->nh.iph;
+	hdr = (u_int32_t *)ip + ip->ihl;
+	datalen = skb->len - ip->ihl * 4;
+
+	DEBUGP("new packet to evaluate ..\n");
+
+	ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
+	if (!ct) {
+		DEBUGP("no ct available [skip]\n");
+		return 0;
+	}
+
+	DEBUGP("ct detected. [cont]\n");
+	dir = CTINFO2DIR(ctinfo);
+
+	/* we only want the client to server packets for matching */
+	if (dir != IP_CT_DIR_ORIGINAL)
+		return 0;
+
+	/* This does sanity checking on UDP or TCP packets,
+	 * like their respective modules.
+	 */
+
+	switch (ct->tuplehash[0].tuple.dst.protonum) {
+
+		case IPPROTO_UDP:
+			DEBUGP("PROTO_UDP [cont]\n");
+			if (offset == 0 && datalen < sizeof(struct udphdr)) {
+				DEBUGP("packet does not contain a complete header. [drop]\n");
+				return 0;
+			}
+
+			for (port=0,portsok=0; port <= ports_n_c; port++) {
+				if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
+					portsok++;
+					break;
+				}
+			}
+			if (portsok == 0) {
+				DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
+					ntohs(ct->tuplehash[dir].tuple.dst.u.all));
+				return 0;
+			}
+
+			if ((datalen - sizeof(struct udphdr)) != 56) {
+				DEBUGP("packet length is not correct for RPC content. [skip]\n");
+				if (rpcinfo->strict == 1)
+					*hotdrop = 1;
+				return 0;
+			}
+			DEBUGP("packet length is correct. [cont]\n");
+
+			/* Get to the data */
+			data = (const u_int32_t *)hdr + 2;
+
+			/* Check the RPC data */
+			tval = check_rpc_packet(data, matchinfo, hotdrop,
+						dir, ct, offset,
+						request_p_list_udp);
+
+			return tval;
+			
+		
+		case IPPROTO_TCP:
+			DEBUGP("PROTO_TCP [cont]\n");
+			if (offset == 0 && datalen < sizeof(struct tcphdr)) {
+				DEBUGP("packet does not contain a complete header. [drop]\n");
+				return 0;
+			}
+	
+			for (port=0,portsok=0; port <= ports_n_c; port++) {
+				if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
+					portsok++;
+					break;
+				}
+			}
+			if (portsok == 0) {
+				DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
+					ntohs(ct->tuplehash[dir].tuple.dst.u.all));
+				return 0;
+			}
+
+			tcp = hdr;
+			if (datalen == (tcp->doff * 4)) {
+				DEBUGP("packet does not contain any data. [match]\n");
+				return (1 && (!offset));
+			}
+
+			/* Tests if packet len is ok */
+			if ((datalen - (tcp->doff * 4)) != 60) {
+				DEBUGP("packet length is not correct for RPC content. [skip]\n");
+				if(rpcinfo->strict == 1)
+					*hotdrop = 1;
+				return 0;
+			}
+			DEBUGP("packet length is correct. [cont]\n");
+
+			/* Get to the data */
+			data = (const u_int32_t *)tcp + tcp->doff + 1;	
+
+			/* Check the RPC data */
+			tval = check_rpc_packet(data, matchinfo, hotdrop,
+						dir, ct, offset,
+						request_p_list_tcp);
+
+			return tval;
+
+	}
+
+	DEBUGP("transport protocol=%u, is not supported [skip]\n",
+		ct->tuplehash[0].tuple.dst.protonum);
+	return 0;
+}
+
+
+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
+		   unsigned int matchsize, unsigned int hook_mask)
+{
+	if (hook_mask
+	    & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
+		| (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
+		printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
+		return 0;
+	}
+
+	if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
+		return 0;
+
+	return 1;
+}
+
+static struct ipt_match rpc_match = {
+        .name           = "rpc",
+        .match          = &match,
+        .checkentry     = &checkentry,
+        .me             = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+	int port;
+
+	/* If no port given, default to standard RPC port */
+	if (ports[0] == 0)
+		ports[0] = RPC_PORT;
+
+	PRINTK("registering match [%s] for;\n", rpc_match.name);
+	for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
+		PRINTK("  port %i (UDP|TCP);\n", ports[port]);
+		ports_n_c++;
+	}
+	
+	return ipt_register_match(&rpc_match);
+}
+
+
+static void fini(void)
+{
+	DEBUGP("unregistering match\n");
+	ipt_unregister_match(&rpc_match);
+}
+
+
+module_init(init);
+module_exit(fini);
+




More information about the netfilter-cvslog mailing list