]> git.pld-linux.org Git - packages/kernel.git/blame - pom-ng-rpc-20061213.patch
- revert
[packages/kernel.git] / pom-ng-rpc-20061213.patch
CommitLineData
1aedc22c 1diff -NurpP --minimal linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.19/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
2--- linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
3+++ linux-2.6.19/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 2006-12-14 11:25:47.000000000 +0100
4@@ -0,0 +1,71 @@
5+/* RPC extension for IP connection tracking, Version 2.2
6+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
7+ * - original rpc tracking module
8+ * - "recent" connection handling for kernel 2.3+ netfilter
9+ *
10+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
11+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
12+ *
13+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
14+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
15+ * - extended matching to support filtering on procedures
16+ *
17+ * (C) 2005 by David Stes <stes@pandora.be>
18+ * - upgraded to 2.6.13 API
19+ *
20+ * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
21+ *
22+ * This program is free software; you can redistribute it and/or
23+ * modify it under the terms of the GNU General Public License
24+ * as published by the Free Software Foundation; either version
25+ * 2 of the License, or (at your option) any later version.
26+ **
27+ */
28+
29+#include <asm/param.h>
30+#include <linux/sched.h>
31+#include <linux/timer.h>
32+#include <linux/stddef.h>
33+#include <linux/list.h>
34+
35+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
36+
37+#ifndef _IP_CONNTRACK_RPC_H
38+#define _IP_CONNTRACK_RPC_H
39+
40+#define RPC_PORT 111
41+
42+
43+/* Datum in RPC packets are encoded in XDR */
44+#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
45+
46+/* Fast timeout, to deny DoS atacks */
47+#define EXP (60 * HZ)
48+
49+/* Normal timeouts */
50+#define EXPIRES (180 * HZ)
51+
52+/* For future conections RPC, using client's cache bindings
53+ * I'll use ip_conntrack_lock to lock these lists */
54+
55+/* This identifies each request and stores protocol */
56+struct request_p {
57+ struct list_head list;
58+
59+ u_int32_t xid;
60+ u_int32_t ip;
61+ u_int16_t port;
62+
63+ /* Protocol */
64+ u_int16_t proto;
65+
66+ struct timer_list timeout;
67+};
68+
69+static inline int request_p_cmp(const struct request_p *p, u_int32_t xid,
70+ u_int32_t ip, u_int32_t port) {
71+ return (p->xid == xid && p->ip == ip && p->port);
72+
73+}
74+
75+#endif /* _IP_CONNTRACK_RPC_H */
76diff -NurpP --minimal linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.19/include/linux/netfilter_ipv4/ipt_rpc.h
77--- linux-2.6.19-pom-ng/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
78+++ linux-2.6.19/include/linux/netfilter_ipv4/ipt_rpc.h 2006-12-14 11:25:47.000000000 +0100
79@@ -0,0 +1,35 @@
80+/* RPC extension for IP netfilter matching, Version 2.2
81+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
82+ * - original rpc tracking module
83+ * - "recent" connection handling for kernel 2.3+ netfilter
84+ *
85+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
86+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
87+ *
88+ * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
89+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
90+ * - extended matching to support filtering on procedures
91+ *
92+ * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
93+ *
94+ * This program is free software; you can redistribute it and/or
95+ * modify it under the terms of the GNU General Public License
96+ * as published by the Free Software Foundation; either version
97+ * 2 of the License, or (at your option) any later version.
98+ **
99+ */
100+
101+#ifndef _IPT_RPC_H
102+#define _IPT_RPC_H
103+
104+struct ipt_rpc_data;
105+
106+struct ipt_rpc_info {
107+ int inverse;
108+ int strict;
109+ const char c_procs[1408];
110+ int i_procs;
111+ struct ipt_rpc_data *data;
112+};
113+
114+#endif /* _IPT_RPC_H */
115diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/Kconfig linux-2.6.19/net/ipv4/netfilter/Kconfig
116--- linux-2.6.19-pom-ng/net/ipv4/netfilter/Kconfig 2006-12-14 11:13:22.000000000 +0100
117+++ linux-2.6.19/net/ipv4/netfilter/Kconfig 2006-12-14 11:25:47.000000000 +0100
118@@ -820,5 +820,37 @@ config IP_NF_MMS
119 If you want to compile it as a module, say M here and read
120 <file:Documentation/modules.txt>. If unsure, say `Y'.
121
122+config IP_NF_MATCH_RPC
123+ tristate 'RPC match support'
124+ depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
125+ help
126+ This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
127+ matcher and tracker.
128+
129+ This option supplies two connection tracking modules;
130+ ip_conntrack_rpc_udp and ip_conntrack_rpc_tcp, which track
131+ portmapper requests using UDP and TCP respectively.
132+
133+ This option also adds an RPC match module for iptables, which
134+ matches both via the old "record match" method and a new
135+ "procedure match" method. The older method matches all RPC
136+ procedure packets that relate to previously recorded packets
137+ seen querying a portmapper. The newer method matches only
138+ those RPC procedure packets explicitly specified by the user,
139+ and that can then be related to previously recorded packets
140+ seen querying a portmapper.
141+
142+ These three modules are required if RPCs are to be filtered
143+ accurately; as RPCs are allocated pseudo-randomly to UDP and
144+ TCP ports as they register with the portmapper.
145+
146+ Up to 8 portmapper ports per module, and up to 128 RPC
147+ procedures per iptables rule, may be specified by the user,
148+ to enable effective RPC management.
149+
150+
151+ If you want to compile it as a module, say M here and read
152+ <file:Documentation/modules.txt>. If unsure, say `N'.
153+
154 endmenu
155
156diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/Makefile linux-2.6.19/net/ipv4/netfilter/Makefile
157--- linux-2.6.19-pom-ng/net/ipv4/netfilter/Makefile 2006-12-14 11:13:22.000000000 +0100
158+++ linux-2.6.19/net/ipv4/netfilter/Makefile 2006-12-14 11:25:47.000000000 +0100
159@@ -55,6 +55,9 @@ obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
160 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
161
162 # matches
163+obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
164+export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
165+
166 obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
167 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
168 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
169diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
170--- linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
171+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2006-12-14 11:25:47.000000000 +0100
172@@ -0,0 +1,554 @@
173+/* RPC extension for IP (TCP) connection tracking, Version 2.2
174+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
175+ * - original rpc tracking module
176+ * - "recent" connection handling for kernel 2.3+ netfilter
177+ *
178+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
179+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
180+ *
181+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
182+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
183+ * - extended matching to support filtering on procedures
184+ *
185+ * (c) 2004,2005 by David Stes <stes@pandora.be>
186+ * - add nsrexec option for Legato NetWorker
187+ * - upgraded to 2.6.12+ conntrack module api
188+ *
189+ * (c) 2005 by David Stes <stes@pandora.be>
190+ * - upgraded to 2.6.13 conntrack module api
191+ *
192+ * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
193+ *
194+ * This program is free software; you can redistribute it and/or
195+ * modify it under the terms of the GNU General Public License
196+ * as published by the Free Software Foundation; either version
197+ * 2 of the License, or (at your option) any later version.
198+ **
199+ * Module load syntax:
200+ * insmod ip_conntrack_rpc_tcp.o nsrexec=<n> ports=port1,...port<MAX_PORTS>
201+ *
202+ * Please give the ports of all RPC servers you wish to connect to.
203+ * For example, ports=111,7938 for Legato NetWorker's portmapper on 7938.
204+ * If you don't specify ports, the default will be port 111 (SUN portmap).
205+ *
206+ * Please specify nsrexec, the TCP port of the rexec() service of
207+ * Legato NetWorker. For example, nsrexec=7937
208+ *
209+ **
210+ * Note to all:
211+ *
212+ * RPCs should not be exposed to the internet - ask the Pentagon;
213+ *
214+ * "The unidentified crackers pleaded guilty in July to charges
215+ * of juvenile delinquency stemming from a string of Pentagon
216+ * network intrusions in February.
217+ *
218+ * The youths, going by the names TooShort and Makaveli, used
219+ * a common server security hole to break in, according to
220+ * Dane Jasper, owner of the California Internet service
221+ * provider, Sonic. They used the hole, known as the 'statd'
222+ * exploit, to attempt more than 800 break-ins, Jasper said."
223+ *
224+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
225+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
226+ **
227+ */
228+
229+#include <linux/module.h>
230+#include <linux/netfilter.h>
231+#include <linux/ip.h>
232+#include <net/checksum.h>
233+#include <net/tcp.h>
234+
235+#include <asm/param.h>
236+#include <linux/sched.h>
237+#include <linux/timer.h>
238+#include <linux/stddef.h>
239+#include <linux/list.h>
240+
241+#include <linux/netfilter_ipv4/ip_tables.h>
242+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
243+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
244+
245+#define MAX_PORTS 8
246+static int ports[MAX_PORTS];
247+static int ports_n_c = 0;
248+static int nsrexec = 0;
249+
250+#ifdef MODULE_PARM
251+module_param(nsrexec,int, 0400);
252+MODULE_PARM_DESC(nsrexec, "TCP port of Legato NetWorker's rexec service");
253+module_param_array(ports, int, &ports_n_c, 0400);
254+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
255+#endif
256+
257+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
258+MODULE_DESCRIPTION("RPC TCP connection tracking module");
259+MODULE_LICENSE("GPL");
260+
261+#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
262+ format, ## args)
263+
264+#if 0
265+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
266+ format, ## args)
267+#else
268+#define DEBUGP(format, args...)
269+#endif
270+
271+DEFINE_RWLOCK(ipct_rpc_tcp_lock);
272+
273+#define ASSERT_READ_LOCK(x)
274+#define ASSERT_WRITE_LOCK(x)
275+
276+#include <linux/netfilter_ipv4/listhelp.h>
277+
278+/* For future conections RPC, using client's cache bindings
279+ * I'll use ip_conntrack_lock to lock these lists */
280+
281+LIST_HEAD(request_p_list_tcp);
282+
283+
284+static void delete_request_p(unsigned long request_p_ul)
285+{
286+ struct request_p *p = (void *)request_p_ul;
287+
288+ write_lock_bh(&ipct_rpc_tcp_lock);
289+ LIST_DELETE(&request_p_list_tcp, p);
290+ write_unlock_bh(&ipct_rpc_tcp_lock);
291+ kfree(p);
292+ return;
293+}
294+
295+
296+static void req_cl(struct request_p * r)
297+{
298+ write_lock_bh(&ipct_rpc_tcp_lock);
299+ del_timer(&r->timeout);
300+ LIST_DELETE(&request_p_list_tcp, r);
301+ write_unlock_bh(&ipct_rpc_tcp_lock);
302+ kfree(r);
303+ return;
304+}
305+
306+
307+static void clean_request(struct list_head *list)
308+{
309+ struct list_head *first = list->prev;
310+ struct list_head *temp = list->next;
311+ struct list_head *aux;
312+
313+ if (list_empty(list))
314+ return;
315+
316+ while (first != temp) {
317+ aux = temp->next;
318+ req_cl((struct request_p *)temp);
319+ temp = aux;
320+ }
321+ req_cl((struct request_p *)temp);
322+ return;
323+}
324+
325+
326+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
327+ u_int16_t port)
328+{
329+ struct request_p *req_p;
330+
331+ /* Verifies if entry already exists */
332+ write_lock_bh(&ipct_rpc_tcp_lock);
333+ req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
334+ struct request_p *, xid, ip, port);
335+
336+ if (req_p) {
337+ /* Refresh timeout */
338+ if (del_timer(&req_p->timeout)) {
339+ req_p->timeout.expires = jiffies + EXP;
340+ add_timer(&req_p->timeout);
341+ }
342+ write_unlock_bh(&ipct_rpc_tcp_lock);
343+ return;
344+
345+ }
346+ write_unlock_bh(&ipct_rpc_tcp_lock);
347+
348+ /* Allocate new request_p */
349+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
350+ if (!req_p) {
351+ DEBUGP("can't allocate request_p\n");
352+ return;
353+ }
354+
355+ req_p->list.next = NULL;
356+ req_p->list.prev = NULL;
357+ req_p->xid = xid;
358+ req_p->ip = ip;
359+ req_p->port = port;
360+ req_p->proto = proto;
361+
362+ /* Initialize timer */
363+ init_timer(&req_p->timeout);
364+ req_p->timeout.expires = jiffies + EXP;
365+ req_p->timeout.data = (unsigned long)req_p;
366+ req_p->timeout.function = delete_request_p;
367+ add_timer(&req_p->timeout);
368+
369+ /* Put in list */
370+ write_lock_bh(&ipct_rpc_tcp_lock);
371+ list_prepend(&request_p_list_tcp, req_p);
372+ write_unlock_bh(&ipct_rpc_tcp_lock);
373+ return;
374+}
375+
376+
377+static int check_rpc_packet(const u_int32_t *data,
378+ int dir, struct ip_conntrack *ct,
379+ struct list_head request_p_list)
380+{
381+ u_int32_t xid;
382+ int ret = NF_ACCEPT;
383+ struct request_p *req_p;
384+ struct ip_conntrack_expect *exp;
385+
386+
387+ if (ct == NULL) {
388+ DEBUGP("ct is NULL");
389+ return ret;
390+ }
391+
392+ /* Translstion's buffer for XDR */
393+ u_int16_t port_buf;
394+
395+ /* Get XID */
396+ xid = *data;
397+
398+ /* This does sanity checking on RPC payloads,
399+ * and permits only the RPC "get port" (3)
400+ * in authorised procedures in client
401+ * communications with the portmapper.
402+ */
403+
404+ /* perform direction dependant RPC work */
405+ if (dir == IP_CT_DIR_ORIGINAL) {
406+
407+ data += 5;
408+
409+ /* Get RPC requestor */
410+ if (IXDR_GET_INT32(data) != 3) {
411+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
412+ return NF_ACCEPT;
413+ }
414+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
415+
416+ data++;
417+
418+ /* Jump Credentials and Verfifier */
419+ data += IXDR_GET_INT32(data) + 2;
420+ data += IXDR_GET_INT32(data) + 2;
421+
422+ /* Get RPC procedure */
423+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
424+ (unsigned int)IXDR_GET_INT32(data));
425+
426+ /* Get RPC protocol and store against client parameters */
427+ data = data + 2;
428+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
429+ ct->tuplehash[dir].tuple.src.u.all);
430+
431+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
432+ xid, IXDR_GET_INT32(data),
433+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
434+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
435+
436+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
437+ (unsigned int)IXDR_GET_INT32(data));
438+
439+ } else {
440+
441+ /* Check for returning packet's stored counterpart */
442+ req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
443+ struct request_p *, xid,
444+ ct->tuplehash[!dir].tuple.src.ip,
445+ ct->tuplehash[!dir].tuple.src.u.all);
446+
447+ /* Drop unexpected packets */
448+ if (!req_p) {
449+ DEBUGP("packet is not expected. [skip]\n");
450+ return NF_ACCEPT;
451+ }
452+
453+ /* Verifies if packet is really an RPC reply packet */
454+ data++;
455+ if (IXDR_GET_INT32(data) != 1) {
456+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
457+ return NF_ACCEPT;
458+ }
459+
460+ /* Is status accept? */
461+ data++;
462+ if (IXDR_GET_INT32(data)) {
463+ DEBUGP("packet is not an RPC accept. [skip]\n");
464+ return NF_ACCEPT;
465+ }
466+
467+ /* Get Verifier length. Jump verifier */
468+ data++;
469+ data = data + IXDR_GET_INT32(data) + 2;
470+
471+ /* Is accpet status "success"? */
472+ if (IXDR_GET_INT32(data)) {
473+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
474+ return NF_ACCEPT;
475+ }
476+
477+ /* Get server port number */
478+ data++;
479+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
480+
481+ /* If a packet has made it this far then it deserves an
482+ * expectation ... if port == 0, then this service is
483+ * not going to be registered.
484+ */
485+ if (port_buf && port_buf != nsrexec) {
486+ DEBUGP("port found: %u\n", port_buf);
487+
488+ exp = ip_conntrack_expect_alloc(ct);
489+ if (!exp) {
490+ ret = NF_DROP;
491+ goto out;
492+ }
493+
494+ /* Watch out, Radioactive-Man! */
495+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
496+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
497+ exp->mask.src.ip = 0xffffffff;
498+ exp->mask.dst.ip = 0xffffffff;
499+
500+ switch (req_p->proto) {
501+ case IPPROTO_UDP:
502+ exp->tuple.src.u.udp.port = 0;
503+ exp->tuple.dst.u.udp.port = htons(port_buf);
504+ exp->tuple.dst.protonum = IPPROTO_UDP;
505+ exp->mask.src.u.udp.port = 0;
506+ exp->mask.dst.u.udp.port = htons(0xffff);
507+ exp->mask.dst.protonum = 0xff;
508+ break;
509+
510+ case IPPROTO_TCP:
511+ exp->tuple.src.u.tcp.port = 0;
512+ exp->tuple.dst.u.tcp.port = htons(port_buf);
513+ exp->tuple.dst.protonum = IPPROTO_TCP;
514+ exp->mask.src.u.tcp.port = 0;
515+ exp->mask.dst.u.tcp.port = htons(0xffff);
516+ exp->mask.dst.protonum = 0xff;
517+ break;
518+ }
519+ exp->expectfn = NULL;
520+ exp->master = ct;
521+
522+ if (exp->master->helper == NULL) {
523+ DEBUGP("master helper NULL");
524+ ret = NF_ACCEPT;
525+ }
526+
527+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
528+ NIPQUAD(exp->tuple.src.ip),
529+ NIPQUAD(exp->tuple.dst.ip),
530+ port_buf, req_p->proto);
531+
532+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
533+ NIPQUAD(exp->mask.src.ip),
534+ NIPQUAD(exp->mask.dst.ip),
535+ exp->mask.dst.protonum);
536+
537+ if (ip_conntrack_expect_related(exp) != 0) {
538+ ret = NF_DROP;
539+ }
540+
541+ }
542+
543+out:
544+ req_cl(req_p);
545+
546+ DEBUGP("packet evaluated. [expect]\n");
547+ }
548+
549+ return ret;
550+
551+}
552+
553+
554+/* RPC TCP helper */
555+/* static int help(const struct iphdr *iph, size_t len,
556+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) */
557+static int help(struct sk_buff **pskb,
558+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
559+{
560+ int dir;
561+ int crp_ret;
562+ struct tcphdr _tcph, *tcph;
563+ const u_int32_t *data;
564+ size_t tcplen;
565+ struct iphdr *iph;
566+ size_t len;
567+
568+ /* Not whole TCP header? */
569+ iph=(*pskb)->nh.iph;
570+ tcph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_tcph),&_tcph);
571+ if (!tcph)
572+ return NF_ACCEPT;
573+
574+ len = (*pskb)->len; /* stes */
575+ data = (const u_int32_t *)tcph + tcph->doff;
576+ tcplen = len - iph->ihl * 4;
577+ dir = CTINFO2DIR(ctinfo);
578+
579+ DEBUGP("new packet to evaluate ..\n");
580+
581+ /* This works for packets like handshake packets, ignore */
582+ if (len == ((tcph->doff + iph->ihl) * 4)) {
583+ DEBUGP("packet has no data (may still be handshaking). [skip]\n");
584+ return NF_ACCEPT;
585+ }
586+
587+ /* Until there's been traffic both ways, don't look in packets. */
588+ if (ctinfo != IP_CT_ESTABLISHED
589+ && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
590+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
591+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
592+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
593+ return NF_ACCEPT;
594+ }
595+
596+ /* Not whole TCP header? */
597+ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
598+ DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
599+ DEBUGP("packet does not contain a complete TCP header. [skip]\n");
600+ return NF_ACCEPT;
601+ }
602+
603+ /* perform direction dependant protocol work */
604+ if (dir == IP_CT_DIR_ORIGINAL) {
605+
606+ DEBUGP("packet is from the initiator. [cont]\n");
607+
608+ /* Tests if packet len is ok */
609+ if ((tcplen - (tcph->doff * 4)) != 60) {
610+ DEBUGP("packet length is not correct. [skip]\n");
611+ return NF_ACCEPT;
612+ }
613+
614+ } else {
615+
616+ DEBUGP("packet is from the receiver. [cont]\n");
617+
618+ /* Tests if packet len is ok */
619+ if ((tcplen - (tcph->doff * 4)) != 32) {
620+ DEBUGP("packet length is not correct. [skip]\n");
621+ return NF_ACCEPT;
622+ }
623+ }
624+
625+ /* Get to the data */
626+ data++;
627+
628+ /* Check the RPC data */
629+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
630+
631+ return crp_ret;
632+
633+}
634+
635+
636+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
637+static char rpc_names[MAX_PORTS][10];
638+
639+static void fini(void);
640+
641+static int __init init(void)
642+{
643+ int port, ret;
644+ char *tmpname;
645+
646+ /* If no port given, default to standard RPC port */
647+ if (ports[0] == 0)
648+ ports[0] = RPC_PORT;
649+
650+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
651+ memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
652+
653+ tmpname = &rpc_names[port][0];
654+ if (ports[port] == RPC_PORT)
655+ sprintf(tmpname, "rpc");
656+ else
657+ sprintf(tmpname, "rpc-%d", ports[port]);
658+ rpc_helpers[port].name = tmpname;
659+
660+ rpc_helpers[port].me = THIS_MODULE;
661+ rpc_helpers[port].max_expected = 1;
662+ rpc_helpers[port].timeout = 5 * 60; /* stes */
663+
664+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
665+ rpc_helpers[port].mask.dst.protonum = 0xff;
666+
667+ /* RPC can come from ports 0:65535 to ports[port] (111) */
668+ rpc_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
669+ rpc_helpers[port].mask.src.u.tcp.port = htons(0xffff);
670+ rpc_helpers[port].mask.dst.u.tcp.port = htons(0x0);
671+
672+ rpc_helpers[port].help = help;
673+
674+ PRINTK("registering helper for port #%d: %d/TCP\n", port, ports[port]);
675+ PRINTK("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
676+ NIPQUAD(rpc_helpers[port].tuple.dst.ip),
677+ ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
678+ NIPQUAD(rpc_helpers[port].tuple.src.ip),
679+ ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
680+ PRINTK("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
681+ NIPQUAD(rpc_helpers[port].mask.dst.ip),
682+ ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
683+ NIPQUAD(rpc_helpers[port].mask.src.ip),
684+ ntohs(rpc_helpers[port].mask.src.u.tcp.port));
685+
686+ ret = ip_conntrack_helper_register(&rpc_helpers[port]);
687+
688+ if (ret) {
689+ printk("ERROR registering port %d\n",
690+ ports[port]);
691+ fini();
692+ return -EBUSY;
693+ }
694+ ports_n_c++;
695+ }
696+
697+ PRINTK("%s Legato NetWorker support for port %d/TCP\n", (nsrexec)?"enabling":"disabling", nsrexec);
698+
699+ return 0;
700+}
701+
702+
703+/* This function is intentionally _NOT_ defined as __exit, because
704+ * it is needed by the init function */
705+static void fini(void)
706+{
707+ int port;
708+
709+ DEBUGP("cleaning request list\n");
710+ clean_request(&request_p_list_tcp);
711+
712+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
713+ DEBUGP("unregistering port %d\n", ports[port]);
714+ ip_conntrack_helper_unregister(&rpc_helpers[port]);
715+ }
716+}
717+
718+
719+module_init(init);
720+module_exit(fini);
721+
722+struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
723+EXPORT_SYMBOL(request_p_list_tcp);
724+EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
725+EXPORT_SYMBOL(ipct_rpc_tcp_lock);
726+
727diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.19/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
728--- linux-2.6.19-pom-ng/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
729+++ linux-2.6.19/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2006-12-14 11:25:47.000000000 +0100
730@@ -0,0 +1,527 @@
731+/* RPC extension for IP (UDP) connection tracking, Version 2.2
732+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
733+ * - original rpc tracking module
734+ * - "recent" connection handling for kernel 2.3+ netfilter
735+ *
736+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
737+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
738+ *
739+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
740+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
741+ * - extended matching to support filtering on procedures
742+ *
743+ * (c) 2004,2005 by David Stes <stes@pandora.be>
744+ * - upgraded to 2.6.12+ conntrack module api
745+ *
746+ * (c) 2005 by David Stes <stes@pandora.be>
747+ * - upgraded to 2.6.13 api
748+ *
749+ * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
750+ *
751+ * This program is free software; you can redistribute it and/or
752+ * modify it under the terms of the GNU General Public License
753+ * as published by the Free Software Foundation; either version
754+ * 2 of the License, or (at your option) any later version.
755+ **
756+ * Module load syntax:
757+ * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
758+ *
759+ * Please give the ports of all RPC servers you wish to connect to.
760+ * If you don't specify ports, the default will be port 111.
761+ **
762+ * Note to all:
763+ *
764+ * RPCs should not be exposed to the internet - ask the Pentagon;
765+ *
766+ * "The unidentified crackers pleaded guilty in July to charges
767+ * of juvenile delinquency stemming from a string of Pentagon
768+ * network intrusions in February.
769+ *
770+ * The youths, going by the names TooShort and Makaveli, used
771+ * a common server security hole to break in, according to
772+ * Dane Jasper, owner of the California Internet service
773+ * provider, Sonic. They used the hole, known as the 'statd'
774+ * exploit, to attempt more than 800 break-ins, Jasper said."
775+ *
776+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
777+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
778+ **
779+ */
780+
781+#include <linux/module.h>
782+#include <linux/netfilter.h>
783+#include <linux/ip.h>
784+#include <net/checksum.h>
785+#include <net/udp.h>
786+
787+#include <asm/param.h>
788+#include <linux/sched.h>
789+#include <linux/timer.h>
790+#include <linux/stddef.h>
791+#include <linux/list.h>
792+
793+#include <linux/netfilter_ipv4/ip_tables.h>
794+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
795+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
796+
797+#define MAX_PORTS 8
798+static int ports[MAX_PORTS];
799+static int ports_n_c = 0;
800+
801+#ifdef MODULE_PARM
802+module_param_array(ports, int, &ports_n_c, 0400);
803+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
804+#endif
805+
806+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
807+MODULE_DESCRIPTION("RPC UDP connection tracking module");
808+MODULE_LICENSE("GPL");
809+
810+#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
811+ format, ## args)
812+
813+#if 0
814+#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
815+ format, ## args)
816+#else
817+#define DEBUGP(format, args...)
818+#endif
819+
820+DEFINE_RWLOCK(ipct_rpc_udp_lock);
821+#define ASSERT_READ_LOCK(x)
822+#define ASSERT_WRITE_LOCK(x)
823+#include <linux/netfilter_ipv4/listhelp.h>
824+
825+/* For future conections RPC, using client's cache bindings
826+ * I'll use ip_conntrack_lock to lock these lists */
827+
828+LIST_HEAD(request_p_list_udp);
829+
830+
831+static void delete_request_p(unsigned long request_p_ul)
832+{
833+ struct request_p *p = (void *)request_p_ul;
834+
835+ write_lock_bh(&ipct_rpc_udp_lock);
836+ LIST_DELETE(&request_p_list_udp, p);
837+ write_unlock_bh(&ipct_rpc_udp_lock);
838+ kfree(p);
839+ return;
840+}
841+
842+
843+static void req_cl(struct request_p * r)
844+{
845+ write_lock_bh(&ipct_rpc_udp_lock);
846+ del_timer(&r->timeout);
847+ LIST_DELETE(&request_p_list_udp, r);
848+ write_unlock_bh(&ipct_rpc_udp_lock);
849+ kfree(r);
850+ return;
851+}
852+
853+
854+static void clean_request(struct list_head *list)
855+{
856+ struct list_head *first = list->prev;
857+ struct list_head *temp = list->next;
858+ struct list_head *aux;
859+
860+ if (list_empty(list))
861+ return;
862+
863+ while (first != temp) {
864+ aux = temp->next;
865+ req_cl((struct request_p *)temp);
866+ temp = aux;
867+ }
868+ req_cl((struct request_p *)temp);
869+ return;
870+}
871+
872+
873+static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
874+ u_int16_t port)
875+{
876+ struct request_p *req_p;
877+
878+ /* Verifies if entry already exists */
879+ write_lock_bh(&ipct_rpc_udp_lock);
880+ req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
881+ struct request_p *, xid, ip, port);
882+
883+ if (req_p) {
884+ /* Refresh timeout */
885+ if (del_timer(&req_p->timeout)) {
886+ req_p->timeout.expires = jiffies + EXP;
887+ add_timer(&req_p->timeout);
888+ }
889+ write_unlock_bh(&ipct_rpc_udp_lock);
890+ return;
891+
892+ }
893+ write_unlock_bh(&ipct_rpc_udp_lock);
894+
895+ /* Allocate new request_p */
896+ req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
897+ if (!req_p) {
898+ DEBUGP("can't allocate request_p\n");
899+ return;
900+ }
901+
902+ req_p->list.next = NULL;
903+ req_p->list.prev = NULL;
904+ req_p->xid = xid;
905+ req_p->ip = ip;
906+ req_p->port = port;
907+ req_p->proto = proto;
908+
909+ /* Initialize timer */
910+ init_timer(&req_p->timeout);
911+ req_p->timeout.expires = jiffies + EXP;
912+ req_p->timeout.data = (unsigned long)req_p;
913+ req_p->timeout.function = delete_request_p;
914+ add_timer(&req_p->timeout);
915+
916+ /* Put in list */
917+ write_lock_bh(&ipct_rpc_udp_lock);
918+ list_prepend(&request_p_list_udp, req_p);
919+ write_unlock_bh(&ipct_rpc_udp_lock);
920+ return;
921+
922+}
923+
924+
925+static int check_rpc_packet(const u_int32_t *data,
926+ int dir, struct ip_conntrack *ct,
927+ struct list_head request_p_list)
928+{
929+ int ret = NF_ACCEPT;
930+ u_int32_t xid;
931+ struct request_p *req_p;
932+ struct ip_conntrack_expect *exp;
933+
934+ /* Translstion's buffer for XDR */
935+ u_int16_t port_buf;
936+
937+
938+ /* Get XID */
939+ xid = *data;
940+
941+ /* This does sanity checking on RPC payloads,
942+ * and permits only the RPC "get port" (3)
943+ * in authorised procedures in client
944+ * communications with the portmapper.
945+ */
946+
947+ /* perform direction dependant RPC work */
948+ if (dir == IP_CT_DIR_ORIGINAL) {
949+
950+ data += 5;
951+
952+ /* Get RPC requestor */
953+ if (IXDR_GET_INT32(data) != 3) {
954+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
955+ return NF_ACCEPT;
956+ }
957+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
958+
959+ data++;
960+
961+ /* Jump Credentials and Verfifier */
962+ data = data + IXDR_GET_INT32(data) + 2;
963+ data = data + IXDR_GET_INT32(data) + 2;
964+
965+ /* Get RPC procedure */
966+ DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
967+ (unsigned int)IXDR_GET_INT32(data));
968+
969+ /* Get RPC protocol and store against client parameters */
970+ data = data + 2;
971+ alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
972+ ct->tuplehash[dir].tuple.src.u.all);
973+
974+ DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
975+ xid, IXDR_GET_INT32(data),
976+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
977+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
978+
979+ DEBUGP("allocated RPC request for protocol %u. [done]\n",
980+ (unsigned int)IXDR_GET_INT32(data));
981+
982+ } else {
983+
984+ /* Check for returning packet's stored counterpart */
985+ req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
986+ struct request_p *, xid,
987+ ct->tuplehash[!dir].tuple.src.ip,
988+ ct->tuplehash[!dir].tuple.src.u.all);
989+
990+ /* Drop unexpected packets */
991+ if (!req_p) {
992+ DEBUGP("packet is not expected. [skip]\n");
993+ return NF_ACCEPT;
994+ }
995+
996+ /* Verifies if packet is really an RPC reply packet */
997+ data++;
998+ if (IXDR_GET_INT32(data) != 1) {
999+ DEBUGP("packet is not a valid RPC reply. [skip]\n");
1000+ return NF_ACCEPT;
1001+ }
1002+
1003+ /* Is status accept? */
1004+ data++;
1005+ if (IXDR_GET_INT32(data)) {
1006+ DEBUGP("packet is not an RPC accept. [skip]\n");
1007+ return NF_ACCEPT;
1008+ }
1009+
1010+ /* Get Verifier length. Jump verifier */
1011+ data++;
1012+ data = data + IXDR_GET_INT32(data) + 2;
1013+
1014+ /* Is accpet status "success"? */
1015+ if (IXDR_GET_INT32(data)) {
1016+ DEBUGP("packet is not an RPC accept status of success. [skip]\n");
1017+ return NF_ACCEPT;
1018+ }
1019+
1020+ /* Get server port number */
1021+ data++;
1022+ port_buf = (u_int16_t) IXDR_GET_INT32(data);
1023+
1024+ /* If a packet has made it this far then it deserves an
1025+ * expectation ... if port == 0, then this service is
1026+ * not going to be registered.
1027+ */
1028+ if (port_buf) {
1029+ DEBUGP("port found: %u\n", port_buf);
1030+
1031+ exp = ip_conntrack_expect_alloc(ct);
1032+ if (!exp) {
1033+ ret = NF_DROP;
1034+ goto out;
1035+ }
1036+
1037+ /* Watch out, Radioactive-Man! */
1038+ exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
1039+ exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
1040+ exp->mask.src.ip = 0xffffffff;
1041+ exp->mask.dst.ip = 0xffffffff;
1042+
1043+ switch (req_p->proto) {
1044+ case IPPROTO_UDP:
1045+ exp->tuple.src.u.udp.port = 0;
1046+ exp->tuple.dst.u.udp.port = htons(port_buf);
1047+ exp->tuple.dst.protonum = IPPROTO_UDP;
1048+ exp->mask.src.u.udp.port = 0;
1049+ exp->mask.dst.u.udp.port = htons(0xffff);
1050+ exp->mask.dst.protonum = 0xff;
1051+ break;
1052+
1053+ case IPPROTO_TCP:
1054+ exp->tuple.src.u.tcp.port = 0;
1055+ exp->tuple.dst.u.tcp.port = htons(port_buf);
1056+ exp->tuple.dst.protonum = IPPROTO_TCP;
1057+ exp->mask.src.u.tcp.port = 0;
1058+ exp->mask.dst.u.tcp.port = htons(0xffff);
1059+ exp->mask.dst.protonum = 0xff;
1060+ break;
1061+ }
1062+ exp->expectfn = NULL;
1063+ exp->master = ct;
1064+
1065+ DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
1066+ NIPQUAD(exp->tuple.src.ip),
1067+ NIPQUAD(exp->tuple.dst.ip),
1068+ port_buf, req_p->proto);
1069+
1070+ DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
1071+ NIPQUAD(exp->mask.src.ip),
1072+ NIPQUAD(exp->mask.dst.ip),
1073+ exp->mask.dst.protonum);
1074+
1075+ if (ip_conntrack_expect_related(exp) != 0) {
1076+ ret = NF_DROP;
1077+ }
1078+ }
1079+
1080+out:
1081+ req_cl(req_p);
1082+
1083+ DEBUGP("packet evaluated. [expect]\n");
1084+ }
1085+
1086+ return ret;
1087+}
1088+
1089+
1090+/* RPC UDP helper */
1091+/* static int help(const struct iphdr *iph, size_t len,
1092+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) */
1093+static int help(struct sk_buff **pskb,
1094+ struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
1095+{
1096+ int dir;
1097+ int crp_ret;
1098+ struct udphdr _udph, *udph;
1099+ const u_int32_t *data;
1100+ size_t udplen;
1101+ struct iphdr *iph;
1102+ size_t len;
1103+ const u_int16_t *chsm;
1104+
1105+ /* Not whole UDP header? */
1106+ iph=(*pskb)->nh.iph;
1107+ udph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_udph),&_udph);
1108+ if (!udph)
1109+ return NF_ACCEPT;
1110+
1111+ len = (*pskb)->len; /* stes */
1112+ data = (const u_int32_t *)udph + 2;
1113+ udplen = len - iph->ihl * 4;
1114+ dir = CTINFO2DIR(ctinfo);
1115+
1116+ /* Checksum */
1117+ chsm = (const u_int16_t *)udph + 3;
1118+
1119+ DEBUGP("new packet to evaluate ..\n");
1120+
1121+ /* Not whole UDP header? */
1122+ if (udplen < sizeof(struct udphdr)) {
1123+ DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
1124+ DEBUGP("packet does not contain a complete UDP header. [skip]\n");
1125+ return NF_ACCEPT;
1126+ }
1127+
1128+ /* perform direction dependant protocol work */
1129+ if (dir == IP_CT_DIR_ORIGINAL) {
1130+
1131+ DEBUGP("packet is from the initiator. [cont]\n");
1132+
1133+ /* Tests if packet len is ok */
1134+ if ((udplen - sizeof(struct udphdr)) != 56) {
1135+ DEBUGP("packet length is not correct. [skip]\n");
1136+ return NF_ACCEPT;
1137+ }
1138+
1139+ } else {
1140+
1141+ DEBUGP("packet is from the receiver. [cont]\n");
1142+
1143+ /* Until there's been traffic both ways, don't look in packets. */
1144+ if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1145+ DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
1146+ DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
1147+ DEBUGP("packet is not yet part of a two way stream. [skip]\n");
1148+ return NF_ACCEPT;
1149+ }
1150+
1151+ /* Tests if packet len is ok */
1152+ if ((udplen - sizeof(struct udphdr)) != 28) {
1153+ DEBUGP("packet length is not correct. [skip]\n");
1154+ return NF_ACCEPT;
1155+ }
1156+
1157+ }
1158+
1159+ /* Get to the data */
1160+ /* udp *data == *correct */
1161+
1162+ /* Check the RPC data */
1163+ crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
1164+
1165+ return crp_ret;
1166+
1167+}
1168+
1169+
1170+static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
1171+static char rpc_names[MAX_PORTS][10];
1172+
1173+static void fini(void);
1174+
1175+static int __init init(void)
1176+{
1177+ int port, ret;
1178+ char *tmpname;
1179+
1180+ /* If no port given, default to standard RPC port */
1181+ if (ports[0] == 0)
1182+ ports[0] = RPC_PORT;
1183+
1184+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1185+ memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
1186+
1187+ tmpname = &rpc_names[port][0];
1188+ if (ports[port] == RPC_PORT)
1189+ sprintf(tmpname, "rpc");
1190+ else
1191+ sprintf(tmpname, "rpc-%d", ports[port]);
1192+ rpc_helpers[port].name = tmpname;
1193+
1194+ rpc_helpers[port].me = THIS_MODULE;
1195+ rpc_helpers[port].max_expected = 1;
1196+ rpc_helpers[port].timeout = 5 * 60; /* stes */
1197+
1198+ rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
1199+ rpc_helpers[port].mask.dst.protonum = 0xff;
1200+
1201+ /* RPC can come from ports 0:65535 to ports[port] (111) */
1202+ rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
1203+ rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
1204+ rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
1205+
1206+ rpc_helpers[port].help = help;
1207+
1208+ PRINTK("registering helper for port #%d: %d/UDP\n", port, ports[port]);
1209+ PRINTK("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1210+ NIPQUAD(rpc_helpers[port].tuple.dst.ip),
1211+ ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
1212+ NIPQUAD(rpc_helpers[port].tuple.src.ip),
1213+ ntohs(rpc_helpers[port].tuple.src.u.udp.port));
1214+ PRINTK("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1215+ NIPQUAD(rpc_helpers[port].mask.dst.ip),
1216+ ntohs(rpc_helpers[port].mask.dst.u.udp.port),
1217+ NIPQUAD(rpc_helpers[port].mask.src.ip),
1218+ ntohs(rpc_helpers[port].mask.src.u.udp.port));
1219+
1220+ ret = ip_conntrack_helper_register(&rpc_helpers[port]);
1221+
1222+ if (ret) {
1223+ printk("ERROR registering port %d\n",
1224+ ports[port]);
1225+ fini();
1226+ return -EBUSY;
1227+ }
1228+ ports_n_c++;
1229+ }
1230+ return 0;
1231+}
1232+
1233+
1234+/* This function is intentionally _NOT_ defined as __exit, because
1235+ * it is needed by the init function */
1236+static void fini(void)
1237+{
1238+ int port;
1239+
1240+ DEBUGP("cleaning request list\n");
1241+ clean_request(&request_p_list_udp);
1242+
1243+ for (port = 0; (port < ports_n_c) && ports[port]; port++) {
1244+ DEBUGP("unregistering port %d\n", ports[port]);
1245+ ip_conntrack_helper_unregister(&rpc_helpers[port]);
1246+ }
1247+}
1248+
1249+
1250+module_init(init);
1251+module_exit(fini);
1252+
1253+struct module *ip_conntrack_rpc_udp = THIS_MODULE;
1254+EXPORT_SYMBOL(request_p_list_udp);
1255+EXPORT_SYMBOL(ip_conntrack_rpc_udp);
1256+EXPORT_SYMBOL(ipct_rpc_udp_lock);
1257+
1258diff -NurpP --minimal linux-2.6.19-pom-ng/net/ipv4/netfilter/ipt_rpc.c linux-2.6.19/net/ipv4/netfilter/ipt_rpc.c
1259--- linux-2.6.19-pom-ng/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
1260+++ linux-2.6.19/net/ipv4/netfilter/ipt_rpc.c 2006-12-14 11:25:47.000000000 +0100
1261@@ -0,0 +1,443 @@
1262+/* RPC extension for IP connection matching, Version 2.2
1263+ * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
1264+ * - original rpc tracking module
1265+ * - "recent" connection handling for kernel 2.3+ netfilter
1266+ *
1267+ * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1268+ * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1269+ *
1270+ * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1271+ * - upgraded conntrack modules to newnat api - kernel 2.4.20+
1272+ * - extended matching to support filtering on procedures
1273+ *
1274+ * (c) 2004,2005 by David Stes <stes@pandora.be>
1275+ * - upgraded to 2.6.12+ conntrack module api
1276+ * - upgraded to 2.6.13 api
1277+ *
1278+ * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
1279+ *
1280+ * This program is free software; you can redistribute it and/or
1281+ * modify it under the terms of the GNU General Public License
1282+ * as published by the Free Software Foundation; either version
1283+ * 2 of the License, or (at your option) any later version.
1284+ **
1285+ * Module load syntax:
1286+ * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
1287+ *
1288+ * Please give the ports of all RPC servers you wish to connect to.
1289+ * If you don't specify ports, the default will be port 111.
1290+ **
1291+ * Note to all:
1292+ *
1293+ * RPCs should not be exposed to the internet - ask the Pentagon;
1294+ *
1295+ * "The unidentified crackers pleaded guilty in July to charges
1296+ * of juvenile delinquency stemming from a string of Pentagon
1297+ * network intrusions in February.
1298+ *
1299+ * The youths, going by the names TooShort and Makaveli, used
1300+ * a common server security hole to break in, according to
1301+ * Dane Jasper, owner of the California Internet service
1302+ * provider, Sonic. They used the hole, known as the 'statd'
1303+ * exploit, to attempt more than 800 break-ins, Jasper said."
1304+ *
1305+ * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
1306+ * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
1307+ **
1308+ */
1309+
1310+#include <linux/module.h>
1311+#include <linux/skbuff.h>
1312+#include <linux/list.h>
1313+#include <linux/udp.h>
1314+#include <linux/tcp.h>
1315+#include <linux/netfilter_ipv4/ip_conntrack.h>
1316+#include <linux/netfilter_ipv4/ip_tables.h>
1317+#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
1318+#include <linux/netfilter_ipv4/ipt_rpc.h>
1319+
1320+#define MAX_PORTS 8
1321+static int ports[MAX_PORTS];
1322+static int ports_n_c = 0;
1323+
1324+#ifdef MODULE_PARM
1325+module_param_array(ports, int, &ports_n_c, 0400);
1326+MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
1327+#endif
1328+
1329+MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
1330+MODULE_DESCRIPTION("RPC connection matching module");
1331+MODULE_LICENSE("GPL");
1332+
1333+#define PRINTK(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1334+ format, ## args)
1335+
1336+#if 0
1337+#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1338+ format, ## args)
1339+#else
1340+#define DEBUGP(format, args...)
1341+#endif
1342+
1343+/* EXPORT_NO_SYMBOLS; */
1344+
1345+/* vars from ip_conntrack_rpc_tcp */
1346+extern struct list_head request_p_list_tcp;
1347+extern struct module *ip_conntrack_rpc_tcp;
1348+
1349+/* vars from ip_conntrack_rpc_udp */
1350+extern struct list_head request_p_list_udp;
1351+extern struct module *ip_conntrack_rpc_udp;
1352+
1353+extern rwlock_t ipct_rpc_tcp_lock;
1354+extern rwlock_t ipct_rpc_udp_lock;
1355+
1356+#define ASSERT_READ_LOCK(x)
1357+#define ASSERT_WRITE_LOCK(x)
1358+
1359+#if 0
1360+#define ASSERT_READ_LOCK(x) \
1361+do { \
1362+ if (x == &request_p_list_udp) \
1363+ MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
1364+ else if (x == &request_p_list_tcp) \
1365+ MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
1366+} while (0)
1367+
1368+#define ASSERT_WRITE_LOCK(x) \
1369+do { \
1370+ if (x == &request_p_list_udp) \
1371+ MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
1372+ else if (x == &request_p_list_tcp) \
1373+ MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
1374+} while (0)
1375+#endif
1376+
1377+#include <linux/netfilter_ipv4/listhelp.h>
1378+
1379+const int IPT_RPC_CHAR_LEN = 11;
1380+
1381+static int k_atoi(char *string)
1382+{
1383+ unsigned int result = 0;
1384+ int maxoctet = IPT_RPC_CHAR_LEN;
1385+
1386+ for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
1387+ if (*string < 0)
1388+ return(0);
1389+ if (*string == 0)
1390+ break;
1391+ if (*string < 48 || *string > 57) {
1392+ return(0);
1393+ }
1394+ result = result * 10 + ( *string - 48 );
1395+ }
1396+ return(result);
1397+}
1398+
1399+
1400+static int match_rpcs(char *c_procs, int i_procs, int proc)
1401+{
1402+ int proc_ctr;
1403+ char *proc_ptr;
1404+ unsigned int proc_num;
1405+
1406+ DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
1407+
1408+ if (i_procs == -1)
1409+ return 1;
1410+
1411+ for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
1412+
1413+ proc_ptr = c_procs;
1414+ proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
1415+ proc_num = k_atoi(proc_ptr);
1416+
1417+ if (proc_num == proc)
1418+ return 1;
1419+ }
1420+
1421+ return 0;
1422+}
1423+
1424+
1425+static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
1426+ int *hotdrop, int dir, struct ip_conntrack *ct,
1427+ int offset, struct list_head request_p_list)
1428+{
1429+ const struct ipt_rpc_info *rpcinfo = matchinfo;
1430+ struct request_p *req_p;
1431+ u_int32_t xid;
1432+
1433+
1434+ /* Get XID */
1435+ xid = *data;
1436+
1437+ /* This does sanity checking on RPC payloads,
1438+ * and permits only the RPC "get port" (3)
1439+ * in authorised procedures in client
1440+ * communications with the portmapper.
1441+ */
1442+
1443+ data += 5;
1444+
1445+ /* Get RPC requestor */
1446+ if (IXDR_GET_INT32(data) != 3) {
1447+ DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
1448+ if(rpcinfo->strict == 1)
1449+ *hotdrop = 1;
1450+ return 0;
1451+ }
1452+ DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
1453+
1454+ data++;
1455+
1456+ /* Jump Credentials and Verfifier */
1457+ data = data + IXDR_GET_INT32(data) + 2;
1458+ data = data + IXDR_GET_INT32(data) + 2;
1459+
1460+ /* Get RPC procedure */
1461+ if (match_rpcs((char *)&rpcinfo->c_procs,
1462+ rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
1463+ DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
1464+ (unsigned int)IXDR_GET_INT32(data));
1465+
1466+ /* If the RPC conntrack half entry already exists .. */
1467+
1468+ switch (ct->tuplehash[0].tuple.dst.protonum) {
1469+ case IPPROTO_UDP:
1470+ write_lock_bh(&ipct_rpc_udp_lock);
1471+ case IPPROTO_TCP:
1472+ write_lock_bh(&ipct_rpc_tcp_lock);
1473+ }
1474+ req_p = LIST_FIND(&request_p_list, request_p_cmp,
1475+ struct request_p *, xid,
1476+ ct->tuplehash[dir].tuple.src.ip,
1477+ ct->tuplehash[dir].tuple.src.u.all);
1478+
1479+ if (req_p) {
1480+ DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1481+ xid, ct->tuplehash[dir].tuple.dst.protonum,
1482+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
1483+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
1484+
1485+ /* .. remove it */
1486+ if (del_timer(&req_p->timeout))
1487+ req_p->timeout.expires = 0;
1488+
1489+ LIST_DELETE(&request_p_list, req_p);
1490+ DEBUGP("RPC req_p removed. [done]\n");
1491+
1492+ } else {
1493+ DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1494+ xid, ct->tuplehash[dir].tuple.dst.protonum,
1495+ NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
1496+ ntohs(ct->tuplehash[dir].tuple.src.u.all));
1497+
1498+ }
1499+ switch (ct->tuplehash[0].tuple.dst.protonum) {
1500+ case IPPROTO_UDP:
1501+ write_unlock_bh(&ipct_rpc_udp_lock);
1502+ case IPPROTO_TCP:
1503+ write_unlock_bh(&ipct_rpc_tcp_lock);
1504+ }
1505+
1506+ if(rpcinfo->strict == 1)
1507+ *hotdrop = 1;
1508+ return 0;
1509+ }
1510+
1511+ DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
1512+ (unsigned int)IXDR_GET_INT32(data));
1513+ return (1 && (!offset));
1514+}
1515+
1516+
1517+
1518+/* static int match(const struct sk_buff *skb, const struct net_device *in,
1519+ const struct net_device *out, const void *matchinfo,
1520+ int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
1521+*/
1522+static int match(const struct sk_buff *skb, const struct net_device *in,
1523+ const struct net_device *out, const void *matchinfo,
1524+ int offset, int *hotdrop)
1525+{
1526+ struct ip_conntrack *ct;
1527+ enum ip_conntrack_info ctinfo;
1528+ const u_int32_t *data;
1529+ enum ip_conntrack_dir dir;
1530+ const struct tcphdr *tcp;
1531+ const struct ipt_rpc_info *rpcinfo = matchinfo;
1532+ int port, portsok;
1533+ int tval;
1534+ struct iphdr *ip; /* stes */
1535+ void *hdr; /* stes */
1536+ u_int16_t datalen; /* stes */
1537+
1538+ /* Initialization stes - see 2.4 ip_tables.c ipt_do_table() */
1539+ ip = skb->nh.iph;
1540+ hdr = (u_int32_t *)ip + ip->ihl;
1541+ datalen = skb->len - ip->ihl * 4;
1542+
1543+ DEBUGP("new packet to evaluate ..\n");
1544+
1545+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
1546+ if (!ct) {
1547+ DEBUGP("no ct available [skip]\n");
1548+ return 0;
1549+ }
1550+
1551+ DEBUGP("ct detected. [cont]\n");
1552+ dir = CTINFO2DIR(ctinfo);
1553+
1554+ /* we only want the client to server packets for matching */
1555+ if (dir != IP_CT_DIR_ORIGINAL)
1556+ return 0;
1557+
1558+ /* This does sanity checking on UDP or TCP packets,
1559+ * like their respective modules.
1560+ */
1561+
1562+ switch (ct->tuplehash[0].tuple.dst.protonum) {
1563+
1564+ case IPPROTO_UDP:
1565+ DEBUGP("PROTO_UDP [cont]\n");
1566+ if (offset == 0 && datalen < sizeof(struct udphdr)) {
1567+ DEBUGP("packet does not contain a complete header. [drop]\n");
1568+ return 0;
1569+ }
1570+
1571+ for (port=0,portsok=0; port <= ports_n_c; port++) {
1572+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
1573+ portsok++;
1574+ break;
1575+ }
1576+ }
1577+ if (portsok == 0) {
1578+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
1579+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
1580+ return 0;
1581+ }
1582+
1583+ if ((datalen - sizeof(struct udphdr)) != 56) {
1584+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
1585+ if (rpcinfo->strict == 1)
1586+ *hotdrop = 1;
1587+ return 0;
1588+ }
1589+ DEBUGP("packet length is correct. [cont]\n");
1590+
1591+ /* Get to the data */
1592+ data = (const u_int32_t *)hdr + 2;
1593+
1594+ /* Check the RPC data */
1595+ tval = check_rpc_packet(data, matchinfo, hotdrop,
1596+ dir, ct, offset,
1597+ request_p_list_udp);
1598+
1599+ return tval;
1600+
1601+
1602+ case IPPROTO_TCP:
1603+ DEBUGP("PROTO_TCP [cont]\n");
1604+ if (offset == 0 && datalen < sizeof(struct tcphdr)) {
1605+ DEBUGP("packet does not contain a complete header. [drop]\n");
1606+ return 0;
1607+ }
1608+
1609+ for (port=0,portsok=0; port <= ports_n_c; port++) {
1610+ if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
1611+ portsok++;
1612+ break;
1613+ }
1614+ }
1615+ if (portsok == 0) {
1616+ DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
1617+ ntohs(ct->tuplehash[dir].tuple.dst.u.all));
1618+ return 0;
1619+ }
1620+
1621+ tcp = hdr;
1622+ if (datalen == (tcp->doff * 4)) {
1623+ DEBUGP("packet does not contain any data. [match]\n");
1624+ return (1 && (!offset));
1625+ }
1626+
1627+ /* Tests if packet len is ok */
1628+ if ((datalen - (tcp->doff * 4)) != 60) {
1629+ DEBUGP("packet length is not correct for RPC content. [skip]\n");
1630+ if(rpcinfo->strict == 1)
1631+ *hotdrop = 1;
1632+ return 0;
1633+ }
1634+ DEBUGP("packet length is correct. [cont]\n");
1635+
1636+ /* Get to the data */
1637+ data = (const u_int32_t *)tcp + tcp->doff + 1;
1638+
1639+ /* Check the RPC data */
1640+ tval = check_rpc_packet(data, matchinfo, hotdrop,
1641+ dir, ct, offset,
1642+ request_p_list_tcp);
1643+
1644+ return tval;
1645+
1646+ }
1647+
1648+ DEBUGP("transport protocol=%u, is not supported [skip]\n",
1649+ ct->tuplehash[0].tuple.dst.protonum);
1650+ return 0;
1651+}
1652+
1653+
1654+static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
1655+ unsigned int matchsize, unsigned int hook_mask)
1656+{
1657+ if (hook_mask
1658+ & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
1659+ | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
1660+ printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
1661+ return 0;
1662+ }
1663+
1664+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
1665+ return 0;
1666+
1667+ return 1;
1668+}
1669+
1670+static struct ipt_match rpc_match = {
1671+ .name = "rpc",
1672+ .match = &match,
1673+ .checkentry = &checkentry,
1674+ .me = THIS_MODULE,
1675+};
1676+
1677+static int __init init(void)
1678+{
1679+ int port;
1680+
1681+ /* If no port given, default to standard RPC port */
1682+ if (ports[0] == 0)
1683+ ports[0] = RPC_PORT;
1684+
1685+ PRINTK("registering match [%s] for;\n", rpc_match.name);
1686+ for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1687+ PRINTK(" port %i (UDP|TCP);\n", ports[port]);
1688+ ports_n_c++;
1689+ }
1690+
1691+ return ipt_register_match(&rpc_match);
1692+}
1693+
1694+
1695+static void fini(void)
1696+{
1697+ DEBUGP("unregistering match\n");
1698+ ipt_unregister_match(&rpc_match);
1699+}
1700+
1701+
1702+module_init(init);
1703+module_exit(fini);
1704+
This page took 0.385734 seconds and 4 git commands to generate.