1 diff -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
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
10 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
11 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
17 + * (C) 2005 by David Stes <stes@pandora.be>
18 + * - upgraded to 2.6.13 API
20 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
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.
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>
35 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
37 +#ifndef _IP_CONNTRACK_RPC_H
38 +#define _IP_CONNTRACK_RPC_H
43 +/* Datum in RPC packets are encoded in XDR */
44 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
46 +/* Fast timeout, to deny DoS atacks */
47 +#define EXP (60 * HZ)
49 +/* Normal timeouts */
50 +#define EXPIRES (180 * HZ)
52 +/* For future conections RPC, using client's cache bindings
53 + * I'll use ip_conntrack_lock to lock these lists */
55 +/* This identifies each request and stores protocol */
57 + struct list_head list;
66 + struct timer_list timeout;
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);
75 +#endif /* _IP_CONNTRACK_RPC_H */
76 diff -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
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
85 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
86 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
92 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
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.
104 +struct ipt_rpc_data;
106 +struct ipt_rpc_info {
109 + const char c_procs[1408];
111 + struct ipt_rpc_data *data;
114 +#endif /* _IPT_RPC_H */
115 diff -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'.
122 +config IP_NF_MATCH_RPC
123 + tristate 'RPC match support'
124 + depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
126 + This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
127 + matcher and tracker.
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.
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.
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.
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.
151 + If you want to compile it as a module, say M here and read
152 + <file:Documentation/modules.txt>. If unsure, say `N'.
156 diff -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
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
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
169 diff -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
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
178 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
179 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
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
189 + * (c) 2005 by David Stes <stes@pandora.be>
190 + * - upgraded to 2.6.13 conntrack module api
192 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
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.
199 + * Module load syntax:
200 + * insmod ip_conntrack_rpc_tcp.o nsrexec=<n> ports=port1,...port<MAX_PORTS>
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).
206 + * Please specify nsrexec, the TCP port of the rexec() service of
207 + * Legato NetWorker. For example, nsrexec=7937
212 + * RPCs should not be exposed to the internet - ask the Pentagon;
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.
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."
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
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>
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>
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>
246 +static int ports[MAX_PORTS];
247 +static int ports_n_c = 0;
248 +static int nsrexec = 0;
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");
257 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
258 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
259 +MODULE_LICENSE("GPL");
261 +#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
265 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
268 +#define DEBUGP(format, args...)
271 +DEFINE_RWLOCK(ipct_rpc_tcp_lock);
273 +#define ASSERT_READ_LOCK(x)
274 +#define ASSERT_WRITE_LOCK(x)
276 +#include <linux/netfilter_ipv4/listhelp.h>
278 +/* For future conections RPC, using client's cache bindings
279 + * I'll use ip_conntrack_lock to lock these lists */
281 +LIST_HEAD(request_p_list_tcp);
284 +static void delete_request_p(unsigned long request_p_ul)
286 + struct request_p *p = (void *)request_p_ul;
288 + write_lock_bh(&ipct_rpc_tcp_lock);
289 + LIST_DELETE(&request_p_list_tcp, p);
290 + write_unlock_bh(&ipct_rpc_tcp_lock);
296 +static void req_cl(struct request_p * r)
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);
307 +static void clean_request(struct list_head *list)
309 + struct list_head *first = list->prev;
310 + struct list_head *temp = list->next;
311 + struct list_head *aux;
313 + if (list_empty(list))
316 + while (first != temp) {
318 + req_cl((struct request_p *)temp);
321 + req_cl((struct request_p *)temp);
326 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
329 + struct request_p *req_p;
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);
337 + /* Refresh timeout */
338 + if (del_timer(&req_p->timeout)) {
339 + req_p->timeout.expires = jiffies + EXP;
340 + add_timer(&req_p->timeout);
342 + write_unlock_bh(&ipct_rpc_tcp_lock);
346 + write_unlock_bh(&ipct_rpc_tcp_lock);
348 + /* Allocate new request_p */
349 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
351 + DEBUGP("can't allocate request_p\n");
355 + req_p->list.next = NULL;
356 + req_p->list.prev = NULL;
359 + req_p->port = port;
360 + req_p->proto = proto;
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);
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);
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)
382 + int ret = NF_ACCEPT;
383 + struct request_p *req_p;
384 + struct ip_conntrack_expect *exp;
388 + DEBUGP("ct is NULL");
392 + /* Translstion's buffer for XDR */
393 + u_int16_t port_buf;
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.
404 + /* perform direction dependant RPC work */
405 + if (dir == IP_CT_DIR_ORIGINAL) {
409 + /* Get RPC requestor */
410 + if (IXDR_GET_INT32(data) != 3) {
411 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
414 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
418 + /* Jump Credentials and Verfifier */
419 + data += IXDR_GET_INT32(data) + 2;
420 + data += IXDR_GET_INT32(data) + 2;
422 + /* Get RPC procedure */
423 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
424 + (unsigned int)IXDR_GET_INT32(data));
426 + /* Get RPC protocol and store against client parameters */
428 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
429 + ct->tuplehash[dir].tuple.src.u.all);
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));
436 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
437 + (unsigned int)IXDR_GET_INT32(data));
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);
447 + /* Drop unexpected packets */
449 + DEBUGP("packet is not expected. [skip]\n");
453 + /* Verifies if packet is really an RPC reply packet */
455 + if (IXDR_GET_INT32(data) != 1) {
456 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
460 + /* Is status accept? */
462 + if (IXDR_GET_INT32(data)) {
463 + DEBUGP("packet is not an RPC accept. [skip]\n");
467 + /* Get Verifier length. Jump verifier */
469 + data = data + IXDR_GET_INT32(data) + 2;
471 + /* Is accpet status "success"? */
472 + if (IXDR_GET_INT32(data)) {
473 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
477 + /* Get server port number */
479 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
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.
485 + if (port_buf && port_buf != nsrexec) {
486 + DEBUGP("port found: %u\n", port_buf);
488 + exp = ip_conntrack_expect_alloc(ct);
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;
500 + switch (req_p->proto) {
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;
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;
519 + exp->expectfn = NULL;
522 + if (exp->master->helper == NULL) {
523 + DEBUGP("master helper NULL");
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);
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);
537 + if (ip_conntrack_expect_related(exp) != 0) {
546 + DEBUGP("packet evaluated. [expect]\n");
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)
562 + struct tcphdr _tcph, *tcph;
563 + const u_int32_t *data;
568 + /* Not whole TCP header? */
569 + iph=(*pskb)->nh.iph;
570 + tcph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_tcph),&_tcph);
574 + len = (*pskb)->len; /* stes */
575 + data = (const u_int32_t *)tcph + tcph->doff;
576 + tcplen = len - iph->ihl * 4;
577 + dir = CTINFO2DIR(ctinfo);
579 + DEBUGP("new packet to evaluate ..\n");
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");
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");
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");
603 + /* perform direction dependant protocol work */
604 + if (dir == IP_CT_DIR_ORIGINAL) {
606 + DEBUGP("packet is from the initiator. [cont]\n");
608 + /* Tests if packet len is ok */
609 + if ((tcplen - (tcph->doff * 4)) != 60) {
610 + DEBUGP("packet length is not correct. [skip]\n");
616 + DEBUGP("packet is from the receiver. [cont]\n");
618 + /* Tests if packet len is ok */
619 + if ((tcplen - (tcph->doff * 4)) != 32) {
620 + DEBUGP("packet length is not correct. [skip]\n");
625 + /* Get to the data */
628 + /* Check the RPC data */
629 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
636 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
637 +static char rpc_names[MAX_PORTS][10];
639 +static void fini(void);
641 +static int __init init(void)
646 + /* If no port given, default to standard RPC port */
648 + ports[0] = RPC_PORT;
650 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
651 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
653 + tmpname = &rpc_names[port][0];
654 + if (ports[port] == RPC_PORT)
655 + sprintf(tmpname, "rpc");
657 + sprintf(tmpname, "rpc-%d", ports[port]);
658 + rpc_helpers[port].name = tmpname;
660 + rpc_helpers[port].me = THIS_MODULE;
661 + rpc_helpers[port].max_expected = 1;
662 + rpc_helpers[port].timeout = 5 * 60; /* stes */
664 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
665 + rpc_helpers[port].mask.dst.protonum = 0xff;
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);
672 + rpc_helpers[port].help = help;
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));
686 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
689 + printk("ERROR registering port %d\n",
697 + PRINTK("%s Legato NetWorker support for port %d/TCP\n", (nsrexec)?"enabling":"disabling", nsrexec);
703 +/* This function is intentionally _NOT_ defined as __exit, because
704 + * it is needed by the init function */
705 +static void fini(void)
709 + DEBUGP("cleaning request list\n");
710 + clean_request(&request_p_list_tcp);
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]);
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);
727 diff -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
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
736 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
737 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
743 + * (c) 2004,2005 by David Stes <stes@pandora.be>
744 + * - upgraded to 2.6.12+ conntrack module api
746 + * (c) 2005 by David Stes <stes@pandora.be>
747 + * - upgraded to 2.6.13 api
749 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
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.
756 + * Module load syntax:
757 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
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.
764 + * RPCs should not be exposed to the internet - ask the Pentagon;
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.
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."
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
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>
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>
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>
798 +static int ports[MAX_PORTS];
799 +static int ports_n_c = 0;
802 +module_param_array(ports, int, &ports_n_c, 0400);
803 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
806 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
807 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
808 +MODULE_LICENSE("GPL");
810 +#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
814 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
817 +#define DEBUGP(format, args...)
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>
825 +/* For future conections RPC, using client's cache bindings
826 + * I'll use ip_conntrack_lock to lock these lists */
828 +LIST_HEAD(request_p_list_udp);
831 +static void delete_request_p(unsigned long request_p_ul)
833 + struct request_p *p = (void *)request_p_ul;
835 + write_lock_bh(&ipct_rpc_udp_lock);
836 + LIST_DELETE(&request_p_list_udp, p);
837 + write_unlock_bh(&ipct_rpc_udp_lock);
843 +static void req_cl(struct request_p * r)
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);
854 +static void clean_request(struct list_head *list)
856 + struct list_head *first = list->prev;
857 + struct list_head *temp = list->next;
858 + struct list_head *aux;
860 + if (list_empty(list))
863 + while (first != temp) {
865 + req_cl((struct request_p *)temp);
868 + req_cl((struct request_p *)temp);
873 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
876 + struct request_p *req_p;
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);
884 + /* Refresh timeout */
885 + if (del_timer(&req_p->timeout)) {
886 + req_p->timeout.expires = jiffies + EXP;
887 + add_timer(&req_p->timeout);
889 + write_unlock_bh(&ipct_rpc_udp_lock);
893 + write_unlock_bh(&ipct_rpc_udp_lock);
895 + /* Allocate new request_p */
896 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
898 + DEBUGP("can't allocate request_p\n");
902 + req_p->list.next = NULL;
903 + req_p->list.prev = NULL;
906 + req_p->port = port;
907 + req_p->proto = proto;
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);
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);
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)
929 + int ret = NF_ACCEPT;
931 + struct request_p *req_p;
932 + struct ip_conntrack_expect *exp;
934 + /* Translstion's buffer for XDR */
935 + u_int16_t port_buf;
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.
947 + /* perform direction dependant RPC work */
948 + if (dir == IP_CT_DIR_ORIGINAL) {
952 + /* Get RPC requestor */
953 + if (IXDR_GET_INT32(data) != 3) {
954 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
957 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
961 + /* Jump Credentials and Verfifier */
962 + data = data + IXDR_GET_INT32(data) + 2;
963 + data = data + IXDR_GET_INT32(data) + 2;
965 + /* Get RPC procedure */
966 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
967 + (unsigned int)IXDR_GET_INT32(data));
969 + /* Get RPC protocol and store against client parameters */
971 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
972 + ct->tuplehash[dir].tuple.src.u.all);
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));
979 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
980 + (unsigned int)IXDR_GET_INT32(data));
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);
990 + /* Drop unexpected packets */
992 + DEBUGP("packet is not expected. [skip]\n");
996 + /* Verifies if packet is really an RPC reply packet */
998 + if (IXDR_GET_INT32(data) != 1) {
999 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
1003 + /* Is status accept? */
1005 + if (IXDR_GET_INT32(data)) {
1006 + DEBUGP("packet is not an RPC accept. [skip]\n");
1010 + /* Get Verifier length. Jump verifier */
1012 + data = data + IXDR_GET_INT32(data) + 2;
1014 + /* Is accpet status "success"? */
1015 + if (IXDR_GET_INT32(data)) {
1016 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
1020 + /* Get server port number */
1022 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
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.
1029 + DEBUGP("port found: %u\n", port_buf);
1031 + exp = ip_conntrack_expect_alloc(ct);
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;
1043 + switch (req_p->proto) {
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;
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;
1062 + exp->expectfn = NULL;
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);
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);
1075 + if (ip_conntrack_expect_related(exp) != 0) {
1083 + DEBUGP("packet evaluated. [expect]\n");
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)
1098 + struct udphdr _udph, *udph;
1099 + const u_int32_t *data;
1101 + struct iphdr *iph;
1103 + const u_int16_t *chsm;
1105 + /* Not whole UDP header? */
1106 + iph=(*pskb)->nh.iph;
1107 + udph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_udph),&_udph);
1111 + len = (*pskb)->len; /* stes */
1112 + data = (const u_int32_t *)udph + 2;
1113 + udplen = len - iph->ihl * 4;
1114 + dir = CTINFO2DIR(ctinfo);
1117 + chsm = (const u_int16_t *)udph + 3;
1119 + DEBUGP("new packet to evaluate ..\n");
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");
1128 + /* perform direction dependant protocol work */
1129 + if (dir == IP_CT_DIR_ORIGINAL) {
1131 + DEBUGP("packet is from the initiator. [cont]\n");
1133 + /* Tests if packet len is ok */
1134 + if ((udplen - sizeof(struct udphdr)) != 56) {
1135 + DEBUGP("packet length is not correct. [skip]\n");
1141 + DEBUGP("packet is from the receiver. [cont]\n");
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");
1151 + /* Tests if packet len is ok */
1152 + if ((udplen - sizeof(struct udphdr)) != 28) {
1153 + DEBUGP("packet length is not correct. [skip]\n");
1159 + /* Get to the data */
1160 + /* udp *data == *correct */
1162 + /* Check the RPC data */
1163 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
1170 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
1171 +static char rpc_names[MAX_PORTS][10];
1173 +static void fini(void);
1175 +static int __init init(void)
1180 + /* If no port given, default to standard RPC port */
1181 + if (ports[0] == 0)
1182 + ports[0] = RPC_PORT;
1184 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1185 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
1187 + tmpname = &rpc_names[port][0];
1188 + if (ports[port] == RPC_PORT)
1189 + sprintf(tmpname, "rpc");
1191 + sprintf(tmpname, "rpc-%d", ports[port]);
1192 + rpc_helpers[port].name = tmpname;
1194 + rpc_helpers[port].me = THIS_MODULE;
1195 + rpc_helpers[port].max_expected = 1;
1196 + rpc_helpers[port].timeout = 5 * 60; /* stes */
1198 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
1199 + rpc_helpers[port].mask.dst.protonum = 0xff;
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);
1206 + rpc_helpers[port].help = help;
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));
1220 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
1223 + printk("ERROR registering port %d\n",
1234 +/* This function is intentionally _NOT_ defined as __exit, because
1235 + * it is needed by the init function */
1236 +static void fini(void)
1240 + DEBUGP("cleaning request list\n");
1241 + clean_request(&request_p_list_udp);
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]);
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);
1258 diff -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
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
1267 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1268 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
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
1278 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
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.
1285 + * Module load syntax:
1286 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
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.
1293 + * RPCs should not be exposed to the internet - ask the Pentagon;
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.
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."
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
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>
1320 +#define MAX_PORTS 8
1321 +static int ports[MAX_PORTS];
1322 +static int ports_n_c = 0;
1325 +module_param_array(ports, int, &ports_n_c, 0400);
1326 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
1329 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
1330 +MODULE_DESCRIPTION("RPC connection matching module");
1331 +MODULE_LICENSE("GPL");
1333 +#define PRINTK(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1337 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1340 +#define DEBUGP(format, args...)
1343 +/* EXPORT_NO_SYMBOLS; */
1345 +/* vars from ip_conntrack_rpc_tcp */
1346 +extern struct list_head request_p_list_tcp;
1347 +extern struct module *ip_conntrack_rpc_tcp;
1349 +/* vars from ip_conntrack_rpc_udp */
1350 +extern struct list_head request_p_list_udp;
1351 +extern struct module *ip_conntrack_rpc_udp;
1353 +extern rwlock_t ipct_rpc_tcp_lock;
1354 +extern rwlock_t ipct_rpc_udp_lock;
1356 +#define ASSERT_READ_LOCK(x)
1357 +#define ASSERT_WRITE_LOCK(x)
1360 +#define ASSERT_READ_LOCK(x) \
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); \
1368 +#define ASSERT_WRITE_LOCK(x) \
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); \
1377 +#include <linux/netfilter_ipv4/listhelp.h>
1379 +const int IPT_RPC_CHAR_LEN = 11;
1381 +static int k_atoi(char *string)
1383 + unsigned int result = 0;
1384 + int maxoctet = IPT_RPC_CHAR_LEN;
1386 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
1391 + if (*string < 48 || *string > 57) {
1394 + result = result * 10 + ( *string - 48 );
1400 +static int match_rpcs(char *c_procs, int i_procs, int proc)
1404 + unsigned int proc_num;
1406 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
1408 + if (i_procs == -1)
1411 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
1413 + proc_ptr = c_procs;
1414 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
1415 + proc_num = k_atoi(proc_ptr);
1417 + if (proc_num == proc)
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)
1429 + const struct ipt_rpc_info *rpcinfo = matchinfo;
1430 + struct request_p *req_p;
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.
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)
1452 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
1456 + /* Jump Credentials and Verfifier */
1457 + data = data + IXDR_GET_INT32(data) + 2;
1458 + data = data + IXDR_GET_INT32(data) + 2;
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));
1466 + /* If the RPC conntrack half entry already exists .. */
1468 + switch (ct->tuplehash[0].tuple.dst.protonum) {
1470 + write_lock_bh(&ipct_rpc_udp_lock);
1472 + write_lock_bh(&ipct_rpc_tcp_lock);
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);
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));
1485 + /* .. remove it */
1486 + if (del_timer(&req_p->timeout))
1487 + req_p->timeout.expires = 0;
1489 + LIST_DELETE(&request_p_list, req_p);
1490 + DEBUGP("RPC req_p removed. [done]\n");
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));
1499 + switch (ct->tuplehash[0].tuple.dst.protonum) {
1501 + write_unlock_bh(&ipct_rpc_udp_lock);
1503 + write_unlock_bh(&ipct_rpc_tcp_lock);
1506 + if(rpcinfo->strict == 1)
1511 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
1512 + (unsigned int)IXDR_GET_INT32(data));
1513 + return (1 && (!offset));
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)
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)
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;
1534 + struct iphdr *ip; /* stes */
1535 + void *hdr; /* stes */
1536 + u_int16_t datalen; /* stes */
1538 + /* Initialization stes - see 2.4 ip_tables.c ipt_do_table() */
1540 + hdr = (u_int32_t *)ip + ip->ihl;
1541 + datalen = skb->len - ip->ihl * 4;
1543 + DEBUGP("new packet to evaluate ..\n");
1545 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
1547 + DEBUGP("no ct available [skip]\n");
1551 + DEBUGP("ct detected. [cont]\n");
1552 + dir = CTINFO2DIR(ctinfo);
1554 + /* we only want the client to server packets for matching */
1555 + if (dir != IP_CT_DIR_ORIGINAL)
1558 + /* This does sanity checking on UDP or TCP packets,
1559 + * like their respective modules.
1562 + switch (ct->tuplehash[0].tuple.dst.protonum) {
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");
1571 + for (port=0,portsok=0; port <= ports_n_c; port++) {
1572 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
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));
1583 + if ((datalen - sizeof(struct udphdr)) != 56) {
1584 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
1585 + if (rpcinfo->strict == 1)
1589 + DEBUGP("packet length is correct. [cont]\n");
1591 + /* Get to the data */
1592 + data = (const u_int32_t *)hdr + 2;
1594 + /* Check the RPC data */
1595 + tval = check_rpc_packet(data, matchinfo, hotdrop,
1597 + request_p_list_udp);
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");
1609 + for (port=0,portsok=0; port <= ports_n_c; port++) {
1610 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
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));
1622 + if (datalen == (tcp->doff * 4)) {
1623 + DEBUGP("packet does not contain any data. [match]\n");
1624 + return (1 && (!offset));
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)
1634 + DEBUGP("packet length is correct. [cont]\n");
1636 + /* Get to the data */
1637 + data = (const u_int32_t *)tcp + tcp->doff + 1;
1639 + /* Check the RPC data */
1640 + tval = check_rpc_packet(data, matchinfo, hotdrop,
1642 + request_p_list_tcp);
1648 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
1649 + ct->tuplehash[0].tuple.dst.protonum);
1654 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
1655 + unsigned int matchsize, unsigned int 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");
1664 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
1670 +static struct ipt_match rpc_match = {
1673 + .checkentry = &checkentry,
1674 + .me = THIS_MODULE,
1677 +static int __init init(void)
1681 + /* If no port given, default to standard RPC port */
1682 + if (ports[0] == 0)
1683 + ports[0] = RPC_PORT;
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]);
1691 + return ipt_register_match(&rpc_match);
1695 +static void fini(void)
1697 + DEBUGP("unregistering match\n");
1698 + ipt_unregister_match(&rpc_match);