1 diff -Nur --exclude '*.orig' linux/include/linux/netfilter/nf_conntrack_rpc.h linux/include/linux/netfilter/nf_conntrack_rpc.h
2 --- linux/include/linux/netfilter/nf_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
3 +++ linux/include/linux/netfilter/nf_conntrack_rpc.h 2006-05-04 11:26:08.000000000 +0200
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 <net/netfilter/nf_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 -Nur --exclude '*.orig' linux/include/linux/netfilter_ipv4/ipt_rpc.h linux/include/linux/netfilter_ipv4/ipt_rpc.h
77 --- linux/include/linux/netfilter_ipv4/ipt_rpc.h 1970-01-01 01:00:00.000000000 +0100
78 +++ linux/include/linux/netfilter_ipv4/ipt_rpc.h 2006-05-04 11:26:08.000000000 +0200
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 -Nur --exclude '*.orig' linux/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
116 --- linux/net/ipv4/netfilter/Kconfig 2006-05-02 23:38:44.000000000 +0200
117 +++ linux/net/ipv4/netfilter/Kconfig 2006-05-04 11:26:08.000000000 +0200
119 Allows altering the ARP packet payload: source and destination
120 hardware and network addresses.
122 +config IP_NF_MATCH_RPC
123 + tristate 'RPC match support'
124 + depends on 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 -Nur --exclude '*.orig' linux/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
157 --- linux/net/ipv4/netfilter/Makefile 2006-05-02 23:38:44.000000000 +0200
158 +++ linux/net/ipv4/netfilter/Makefile 2006-05-04 11:26:08.000000000 +0200
160 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
161 diff -Nur --exclude '*.orig' linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
162 --- linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 1970-01-01 01:00:00.000000000 +0100
163 +++ linux/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c 2007-08-15 03:04:53.000000000 +0200
165 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
166 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
167 + * - original rpc tracking module
168 + * - "recent" connection handling for kernel 2.3+ netfilter
170 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
171 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
173 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
174 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
175 + * - extended matching to support filtering on procedures
177 + * (c) 2004,2005 by David Stes <stes@pandora.be>
178 + * - add nsrexec option for Legato NetWorker
179 + * - upgraded to 2.6.12+ conntrack module api
181 + * (c) 2005 by David Stes <stes@pandora.be>
182 + * - upgraded to 2.6.13 conntrack module api
184 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
186 + * This program is free software; you can redistribute it and/or
187 + * modify it under the terms of the GNU General Public License
188 + * as published by the Free Software Foundation; either version
189 + * 2 of the License, or (at your option) any later version.
191 + * Module load syntax:
192 + * insmod ip_conntrack_rpc_tcp.o nsrexec=<n> ports=port1,...port<MAX_PORTS>
194 + * Please give the ports of all RPC servers you wish to connect to.
195 + * For example, ports=111,7938 for Legato NetWorker's portmapper on 7938.
196 + * If you don't specify ports, the default will be port 111 (SUN portmap).
198 + * Please specify nsrexec, the TCP port of the rexec() service of
199 + * Legato NetWorker. For example, nsrexec=7937
204 + * RPCs should not be exposed to the internet - ask the Pentagon;
206 + * "The unidentified crackers pleaded guilty in July to charges
207 + * of juvenile delinquency stemming from a string of Pentagon
208 + * network intrusions in February.
210 + * The youths, going by the names TooShort and Makaveli, used
211 + * a common server security hole to break in, according to
212 + * Dane Jasper, owner of the California Internet service
213 + * provider, Sonic. They used the hole, known as the 'statd'
214 + * exploit, to attempt more than 800 break-ins, Jasper said."
216 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
217 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
221 +#include <linux/module.h>
222 +#include <linux/netfilter.h>
223 +#include <linux/ip.h>
224 +#include <net/checksum.h>
225 +#include <net/tcp.h>
227 +#include <asm/param.h>
228 +#include <linux/sched.h>
229 +#include <linux/timer.h>
230 +#include <linux/stddef.h>
231 +#include <linux/list.h>
233 +#include <linux/netfilter_ipv4/ip_tables.h>
234 +#include <net/netfilter/nf_conntrack_expect.h>
235 +#include <net/netfilter/nf_conntrack_helper.h>
236 +#include <linux/netfilter/nf_conntrack_rpc.h>
239 +static int ports[MAX_PORTS];
240 +static int ports_n_c = 0;
241 +static int nsrexec = 0;
244 +module_param(nsrexec,int, 0400);
245 +MODULE_PARM_DESC(nsrexec, "TCP port of Legato NetWorker's rexec service");
246 +module_param_array(ports, int, &ports_n_c, 0400);
247 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
250 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
251 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
252 +MODULE_LICENSE("GPL");
254 +#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
258 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
261 +#define DEBUGP(format, args...)
264 +DEFINE_RWLOCK(ipct_rpc_tcp_lock);
266 +//#define ASSERT_READ_LOCK(x)
267 +//#define ASSERT_WRITE_LOCK(x)
269 +//#include <linux/netfilter_ipv4/listhelp.h>
271 +/* For future conections RPC, using client's cache bindings
272 + * I'll use ip_conntrack_lock to lock these lists */
274 +LIST_HEAD(request_p_list_tcp);
277 +static void delete_request_p(unsigned long request_p_ul)
279 + struct request_p *p = (void *)request_p_ul;
281 + write_lock_bh(&ipct_rpc_tcp_lock);
282 + list_del(&p->list);
283 + write_unlock_bh(&ipct_rpc_tcp_lock);
289 +static void req_cl(struct request_p * r)
291 + write_lock_bh(&ipct_rpc_tcp_lock);
292 + del_timer(&r->timeout);
293 + list_del(&r->list);
294 + write_unlock_bh(&ipct_rpc_tcp_lock);
300 +static void clean_request(struct list_head *list)
302 + struct list_head *first = list->prev;
303 + struct list_head *temp = list->next;
304 + struct list_head *aux;
306 + if (list_empty(list))
309 + while (first != temp) {
311 + req_cl((struct request_p *)temp);
314 + req_cl((struct request_p *)temp);
319 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
322 + struct request_p *req_p = NULL, *p;
324 + /* Verifies if entry already exists */
325 + write_lock_bh(&ipct_rpc_tcp_lock);
326 +// req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
327 +// struct request_p *, xid, ip, port);
329 + list_for_each_entry(p, &request_p_list_tcp, list)
330 + if (p->xid == xid && p->ip == ip && p->port == port)
334 + /* Refresh timeout */
335 + if (del_timer(&req_p->timeout)) {
336 + req_p->timeout.expires = jiffies + EXP;
337 + add_timer(&req_p->timeout);
339 + write_unlock_bh(&ipct_rpc_tcp_lock);
343 + write_unlock_bh(&ipct_rpc_tcp_lock);
345 + /* Allocate new request_p */
346 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
348 + DEBUGP("can't allocate request_p\n");
352 + req_p->list.next = NULL;
353 + req_p->list.prev = NULL;
356 + req_p->port = port;
357 + req_p->proto = proto;
359 + /* Initialize timer */
360 + init_timer(&req_p->timeout);
361 + req_p->timeout.expires = jiffies + EXP;
362 + req_p->timeout.data = (unsigned long)req_p;
363 + req_p->timeout.function = delete_request_p;
364 + add_timer(&req_p->timeout);
367 + write_lock_bh(&ipct_rpc_tcp_lock);
368 + list_add(req_p, &request_p_list_tcp);
369 + write_unlock_bh(&ipct_rpc_tcp_lock);
374 +static int check_rpc_packet(const u_int32_t *data,
375 + int dir, struct nf_conn *ct,
376 + struct list_head request_p_list)
379 + int ret = NF_ACCEPT;
380 + struct request_p *req_p = NULL, *p;
381 + struct nf_conntrack_expect *exp;
385 + DEBUGP("ct is NULL");
389 + /* Translstion's buffer for XDR */
390 + u_int16_t port_buf;
395 + /* This does sanity checking on RPC payloads,
396 + * and permits only the RPC "get port" (3)
397 + * in authorised procedures in client
398 + * communications with the portmapper.
401 + /* perform direction dependant RPC work */
402 + if (dir == IP_CT_DIR_ORIGINAL) {
406 + /* Get RPC requestor */
407 + if (IXDR_GET_INT32(data) != 3) {
408 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
411 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
415 + /* Jump Credentials and Verfifier */
416 + data += IXDR_GET_INT32(data) + 2;
417 + data += IXDR_GET_INT32(data) + 2;
419 + /* Get RPC procedure */
420 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
421 + (unsigned int)IXDR_GET_INT32(data));
423 + /* Get RPC protocol and store against client parameters */
425 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.u3.ip,
426 + ct->tuplehash[dir].tuple.src.u.all);
428 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
429 + xid, IXDR_GET_INT32(data),
430 + NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
431 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
433 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
434 + (unsigned int)IXDR_GET_INT32(data));
438 + /* Check for returning packet's stored counterpart */
439 + /* req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
440 + struct request_p *, xid,
441 + ct->tuplehash[!dir].tuple.src.u3.ip,
442 + ct->tuplehash[!dir].tuple.src.u.all);
445 + list_for_each_entry(p, &request_p_list_tcp, list)
446 + if (p->xid == xid &&
447 + p->ip == ct->tuplehash[!dir].tuple.src.u3.ip &&
448 + p->port == ct->tuplehash[!dir].tuple.src.u.all)
451 + /* Drop unexpected packets */
453 + DEBUGP("packet is not expected. [skip]\n");
457 + /* Verifies if packet is really an RPC reply packet */
459 + if (IXDR_GET_INT32(data) != 1) {
460 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
464 + /* Is status accept? */
466 + if (IXDR_GET_INT32(data)) {
467 + DEBUGP("packet is not an RPC accept. [skip]\n");
471 + /* Get Verifier length. Jump verifier */
473 + data = data + IXDR_GET_INT32(data) + 2;
475 + /* Is accpet status "success"? */
476 + if (IXDR_GET_INT32(data)) {
477 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
481 + /* Get server port number */
483 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
485 + /* If a packet has made it this far then it deserves an
486 + * expectation ... if port == 0, then this service is
487 + * not going to be registered.
489 + if (port_buf && port_buf != nsrexec) {
490 + DEBUGP("port found: %u\n", port_buf);
492 + exp = nf_ct_expect_alloc(ct);
498 + /* Watch out, Radioactive-Man! */
499 + exp->tuple.src.u3.ip = ct->tuplehash[!dir].tuple.src.u3.ip;
500 + exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
501 + exp->mask.src.u3.ip = 0xffffffff;
503 + switch (req_p->proto) {
505 + exp->tuple.src.u.udp.port = 0;
506 + exp->tuple.dst.u.udp.port = htons(port_buf);
507 + exp->tuple.dst.protonum = IPPROTO_UDP;
508 + exp->mask.src.u.udp.port = 0;
512 + exp->tuple.src.u.tcp.port = 0;
513 + exp->tuple.dst.u.tcp.port = htons(port_buf);
514 + exp->tuple.dst.protonum = IPPROTO_TCP;
515 + exp->mask.src.u.tcp.port = 0;
518 + exp->expectfn = NULL;
521 + struct nf_conn_help *m_help = nfct_help(exp->master);
522 + if (m_help->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.u3.ip),
529 + NIPQUAD(exp->tuple.dst.u3.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.u3.ip),
534 + NIPQUAD(exp->mask.dst.u3.ip),
535 + exp->mask.dst.protonum);
537 + if (nf_ct_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 nf_conn *ct, enum ip_conntrack_info ctinfo) */
557 +static int help(struct sk_buff **pskb,
558 + struct nf_conn *ct, enum ip_conntrack_info ctinfo)
562 + struct tcphdr _tcph, *tcph;
563 + const u_int32_t *data;
568 + /* Not whole TCP header? */
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 nf_conntrack_helper rpc_helpers[MAX_PORTS];
637 +static char rpc_names[MAX_PORTS][10];
638 +static const struct nf_conntrack_expect_policy rpc_exp_policy = {
640 + .timeout = 5 * 60, /* stes */
643 +static void fini(void);
645 +static int __init init(void)
650 + /* If no port given, default to standard RPC port */
652 + ports[0] = RPC_PORT;
654 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
655 + memset(&rpc_helpers[port], 0, sizeof(struct nf_conntrack_helper));
657 + tmpname = &rpc_names[port][0];
658 + if (ports[port] == RPC_PORT)
659 + sprintf(tmpname, "rpc");
661 + sprintf(tmpname, "rpc-%d", ports[port]);
662 + rpc_helpers[port].name = tmpname;
664 + rpc_helpers[port].me = THIS_MODULE;
665 + rpc_helpers[port].expect_policy = &rpc_exp_policy;
667 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
669 + /* RPC can come from ports 0:65535 to ports[port] (111) */
670 + rpc_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
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.u3.ip),
677 + ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
678 + NIPQUAD(rpc_helpers[port].tuple.src.u3.ip),
679 + ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
681 + ret = nf_conntrack_helper_register(&rpc_helpers[port]);
684 + printk("ERROR registering port %d\n",
692 + PRINTK("%s Legato NetWorker support for port %d/TCP\n", (nsrexec)?"enabling":"disabling", nsrexec);
698 +/* This function is intentionally _NOT_ defined as __exit, because
699 + * it is needed by the init function */
700 +static void fini(void)
704 + DEBUGP("cleaning request list\n");
705 + clean_request(&request_p_list_tcp);
707 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
708 + DEBUGP("unregistering port %d\n", ports[port]);
709 + nf_conntrack_helper_unregister(&rpc_helpers[port]);
717 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
718 +EXPORT_SYMBOL(request_p_list_tcp);
719 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
720 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
722 diff -Nur --exclude '*.orig' linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
723 --- linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 1970-01-01 01:00:00.000000000 +0100
724 +++ linux/net/ipv4/netfilter/ip_conntrack_rpc_udp.c 2007-08-15 01:44:02.000000000 +0200
726 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
727 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
728 + * - original rpc tracking module
729 + * - "recent" connection handling for kernel 2.3+ netfilter
731 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
732 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
734 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
735 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
736 + * - extended matching to support filtering on procedures
738 + * (c) 2004,2005 by David Stes <stes@pandora.be>
739 + * - upgraded to 2.6.12+ conntrack module api
741 + * (c) 2005 by David Stes <stes@pandora.be>
742 + * - upgraded to 2.6.13 api
744 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
746 + * This program is free software; you can redistribute it and/or
747 + * modify it under the terms of the GNU General Public License
748 + * as published by the Free Software Foundation; either version
749 + * 2 of the License, or (at your option) any later version.
751 + * Module load syntax:
752 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
754 + * Please give the ports of all RPC servers you wish to connect to.
755 + * If you don't specify ports, the default will be port 111.
759 + * RPCs should not be exposed to the internet - ask the Pentagon;
761 + * "The unidentified crackers pleaded guilty in July to charges
762 + * of juvenile delinquency stemming from a string of Pentagon
763 + * network intrusions in February.
765 + * The youths, going by the names TooShort and Makaveli, used
766 + * a common server security hole to break in, according to
767 + * Dane Jasper, owner of the California Internet service
768 + * provider, Sonic. They used the hole, known as the 'statd'
769 + * exploit, to attempt more than 800 break-ins, Jasper said."
771 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
772 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
776 +#include <linux/module.h>
777 +#include <linux/netfilter.h>
778 +#include <linux/ip.h>
779 +#include <net/checksum.h>
780 +#include <net/udp.h>
782 +#include <asm/param.h>
783 +#include <linux/sched.h>
784 +#include <linux/timer.h>
785 +#include <linux/stddef.h>
786 +#include <linux/list.h>
787 +#include <linux/udp.h>
789 +#include <linux/netfilter_ipv4/ip_tables.h>
790 +#include <net/netfilter/nf_conntrack_expect.h>
791 +#include <net/netfilter/nf_conntrack_helper.h>
792 +#include <linux/netfilter/nf_conntrack_rpc.h>
795 +static int ports[MAX_PORTS];
796 +static int ports_n_c = 0;
799 +module_param_array(ports, int, &ports_n_c, 0400);
800 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
803 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
804 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
805 +MODULE_LICENSE("GPL");
807 +#define PRINTK(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
811 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
814 +#define DEBUGP(format, args...)
817 +DEFINE_RWLOCK(ipct_rpc_udp_lock);
818 +//#define ASSERT_READ_LOCK(x)
819 +//#define ASSERT_WRITE_LOCK(x)
820 +//#include <linux/netfilter_ipv4/listhelp.h>
822 +/* For future conections RPC, using client's cache bindings
823 + * I'll use ip_conntrack_lock to lock these lists */
825 +LIST_HEAD(request_p_list_udp);
828 +static void delete_request_p(unsigned long request_p_ul)
830 + struct request_p *p = (void *)request_p_ul;
832 + write_lock_bh(&ipct_rpc_udp_lock);
833 + list_del(&p->list);
834 + write_unlock_bh(&ipct_rpc_udp_lock);
840 +static void req_cl(struct request_p * r)
842 + write_lock_bh(&ipct_rpc_udp_lock);
843 + del_timer(&r->timeout);
844 + list_del(&r->list);
845 + write_unlock_bh(&ipct_rpc_udp_lock);
851 +static void clean_request(struct list_head *list)
853 + struct list_head *first = list->prev;
854 + struct list_head *temp = list->next;
855 + struct list_head *aux;
857 + if (list_empty(list))
860 + while (first != temp) {
862 + req_cl((struct request_p *)temp);
865 + req_cl((struct request_p *)temp);
870 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
873 + struct request_p *req_p = NULL, *p;
875 + /* Verifies if entry already exists */
876 + write_lock_bh(&ipct_rpc_udp_lock);
877 +// req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
878 +// struct request_p *, xid, ip, port);
880 + list_for_each_entry(p, &request_p_list_udp, list)
881 + if (p->xid == xid && p->ip == ip && p->port == port)
885 + /* Refresh timeout */
886 + if (del_timer(&req_p->timeout)) {
887 + req_p->timeout.expires = jiffies + EXP;
888 + add_timer(&req_p->timeout);
890 + write_unlock_bh(&ipct_rpc_udp_lock);
894 + write_unlock_bh(&ipct_rpc_udp_lock);
896 + /* Allocate new request_p */
897 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
899 + DEBUGP("can't allocate request_p\n");
903 + req_p->list.next = NULL;
904 + req_p->list.prev = NULL;
907 + req_p->port = port;
908 + req_p->proto = proto;
910 + /* Initialize timer */
911 + init_timer(&req_p->timeout);
912 + req_p->timeout.expires = jiffies + EXP;
913 + req_p->timeout.data = (unsigned long)req_p;
914 + req_p->timeout.function = delete_request_p;
915 + add_timer(&req_p->timeout);
918 + write_lock_bh(&ipct_rpc_udp_lock);
919 + list_add(req_p, &request_p_list_udp);
920 + write_unlock_bh(&ipct_rpc_udp_lock);
926 +static int check_rpc_packet(const u_int32_t *data,
927 + int dir, struct nf_conn *ct,
928 + struct list_head request_p_list)
930 + int ret = NF_ACCEPT;
932 + struct request_p *req_p = NULL, *p;
933 + struct nf_conntrack_expect *exp;
935 + /* Translstion's buffer for XDR */
936 + u_int16_t port_buf;
942 + /* This does sanity checking on RPC payloads,
943 + * and permits only the RPC "get port" (3)
944 + * in authorised procedures in client
945 + * communications with the portmapper.
948 + /* perform direction dependant RPC work */
949 + if (dir == IP_CT_DIR_ORIGINAL) {
953 + /* Get RPC requestor */
954 + if (IXDR_GET_INT32(data) != 3) {
955 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
958 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
962 + /* Jump Credentials and Verfifier */
963 + data = data + IXDR_GET_INT32(data) + 2;
964 + data = data + IXDR_GET_INT32(data) + 2;
966 + /* Get RPC procedure */
967 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
968 + (unsigned int)IXDR_GET_INT32(data));
970 + /* Get RPC protocol and store against client parameters */
972 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.u3.ip,
973 + ct->tuplehash[dir].tuple.src.u.all);
975 + DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
976 + xid, IXDR_GET_INT32(data),
977 + NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
978 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
980 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
981 + (unsigned int)IXDR_GET_INT32(data));
985 + /* Check for returning packet's stored counterpart */
986 + /* req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
987 + struct request_p *, xid,
988 + ct->tuplehash[!dir].tuple.src.u3.ip,
989 + ct->tuplehash[!dir].tuple.src.u.all);
992 + list_for_each_entry(p, &request_p_list_udp, list)
993 + if (p->xid == xid &&
994 + p->ip == ct->tuplehash[!dir].tuple.src.u3.ip &&
995 + p->port == ct->tuplehash[!dir].tuple.src.u.all)
998 + /* Drop unexpected packets */
1000 + DEBUGP("packet is not expected. [skip]\n");
1004 + /* Verifies if packet is really an RPC reply packet */
1006 + if (IXDR_GET_INT32(data) != 1) {
1007 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
1011 + /* Is status accept? */
1013 + if (IXDR_GET_INT32(data)) {
1014 + DEBUGP("packet is not an RPC accept. [skip]\n");
1018 + /* Get Verifier length. Jump verifier */
1020 + data = data + IXDR_GET_INT32(data) + 2;
1022 + /* Is accpet status "success"? */
1023 + if (IXDR_GET_INT32(data)) {
1024 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
1028 + /* Get server port number */
1030 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
1032 + /* If a packet has made it this far then it deserves an
1033 + * expectation ... if port == 0, then this service is
1034 + * not going to be registered.
1037 + DEBUGP("port found: %u\n", port_buf);
1039 + exp = nf_ct_expect_alloc(ct);
1045 + /* Watch out, Radioactive-Man! */
1046 + exp->tuple.src.u3.ip = ct->tuplehash[!dir].tuple.src.u3.ip;
1047 + exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
1048 + exp->mask.src.u3.ip = 0xffffffff;
1050 + switch (req_p->proto) {
1052 + exp->tuple.src.u.udp.port = 0;
1053 + exp->tuple.dst.u.udp.port = htons(port_buf);
1054 + exp->tuple.dst.protonum = IPPROTO_UDP;
1055 + exp->mask.src.u.udp.port = 0;
1059 + exp->tuple.src.u.tcp.port = 0;
1060 + exp->tuple.dst.u.tcp.port = htons(port_buf);
1061 + exp->tuple.dst.protonum = IPPROTO_TCP;
1062 + exp->mask.src.u.tcp.port = 0;
1065 + exp->expectfn = NULL;
1068 + DEBUGP("expect related ip %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
1069 + NIPQUAD(exp->tuple.src.u3.ip),
1070 + NIPQUAD(exp->tuple.dst.u3.ip),
1071 + port_buf, req_p->proto);
1073 + DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
1074 + NIPQUAD(exp->mask.src.u3.ip),
1075 + NIPQUAD(exp->mask.dst.u3.ip),
1076 + exp->mask.dst.protonum);
1078 + if (nf_ct_expect_related(exp) != 0) {
1086 + DEBUGP("packet evaluated. [expect]\n");
1093 +/* RPC UDP helper */
1094 +/* static int help(const struct iphdr *iph, size_t len,
1095 + struct nf_conn *ct, enum ip_conntrack_info ctinfo) */
1096 +static int help(struct sk_buff **pskb,
1097 + struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1101 + struct udphdr _udph, *udph;
1102 + const u_int32_t *data;
1104 + struct iphdr *iph;
1106 + const u_int16_t *chsm;
1108 + /* Not whole UDP header? */
1109 + iph=ip_hdr(*pskb);
1110 + udph = skb_header_pointer(*pskb,iph->ihl*4,sizeof(_udph),&_udph);
1114 + len = (*pskb)->len; /* stes */
1115 + data = (const u_int32_t *)udph + 2;
1116 + udplen = len - iph->ihl * 4;
1117 + dir = CTINFO2DIR(ctinfo);
1120 + chsm = (const u_int16_t *)udph + 3;
1122 + DEBUGP("new packet to evaluate ..\n");
1124 + /* Not whole UDP header? */
1125 + if (udplen < sizeof(struct udphdr)) {
1126 + DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
1127 + DEBUGP("packet does not contain a complete UDP header. [skip]\n");
1131 + /* perform direction dependant protocol work */
1132 + if (dir == IP_CT_DIR_ORIGINAL) {
1134 + DEBUGP("packet is from the initiator. [cont]\n");
1136 + /* Tests if packet len is ok */
1137 + if ((udplen - sizeof(struct udphdr)) != 56) {
1138 + DEBUGP("packet length is not correct. [skip]\n");
1144 + DEBUGP("packet is from the receiver. [cont]\n");
1146 + /* Until there's been traffic both ways, don't look in packets. */
1147 + if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1148 + DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
1149 + DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
1150 + DEBUGP("packet is not yet part of a two way stream. [skip]\n");
1154 + /* Tests if packet len is ok */
1155 + if ((udplen - sizeof(struct udphdr)) != 28) {
1156 + DEBUGP("packet length is not correct. [skip]\n");
1162 + /* Get to the data */
1163 + /* udp *data == *correct */
1165 + /* Check the RPC data */
1166 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
1173 +static struct nf_conntrack_helper rpc_helpers[MAX_PORTS];
1174 +static char rpc_names[MAX_PORTS][10];
1175 +static const struct nf_conntrack_expect_policy rpc_exp_policy = {
1176 + .max_expected = 1,
1177 + .timeout = 5 * 60, /* stes */
1180 +static void fini(void);
1182 +static int __init init(void)
1187 + /* If no port given, default to standard RPC port */
1188 + if (ports[0] == 0)
1189 + ports[0] = RPC_PORT;
1191 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1192 + memset(&rpc_helpers[port], 0, sizeof(struct nf_conntrack_helper));
1194 + tmpname = &rpc_names[port][0];
1195 + if (ports[port] == RPC_PORT)
1196 + sprintf(tmpname, "rpc");
1198 + sprintf(tmpname, "rpc-%d", ports[port]);
1199 + rpc_helpers[port].name = tmpname;
1201 + rpc_helpers[port].me = THIS_MODULE;
1202 + rpc_helpers[port].expect_policy = &rpc_exp_policy;
1204 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
1206 + /* RPC can come from ports 0:65535 to ports[port] (111) */
1207 + rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
1209 + rpc_helpers[port].help = help;
1211 + PRINTK("registering helper for port #%d: %d/UDP\n", port, ports[port]);
1212 + PRINTK("helper match ip %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
1213 + NIPQUAD(rpc_helpers[port].tuple.dst.u3.ip),
1214 + ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
1215 + NIPQUAD(rpc_helpers[port].tuple.src.u3.ip),
1216 + ntohs(rpc_helpers[port].tuple.src.u.udp.port));
1218 + ret = nf_conntrack_helper_register(&rpc_helpers[port]);
1221 + printk("ERROR registering port %d\n",
1232 +/* This function is intentionally _NOT_ defined as __exit, because
1233 + * it is needed by the init function */
1234 +static void fini(void)
1238 + DEBUGP("cleaning request list\n");
1239 + clean_request(&request_p_list_udp);
1241 + for (port = 0; (port < ports_n_c) && ports[port]; port++) {
1242 + DEBUGP("unregistering port %d\n", ports[port]);
1243 + nf_conntrack_helper_unregister(&rpc_helpers[port]);
1251 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
1252 +EXPORT_SYMBOL(request_p_list_udp);
1253 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
1254 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
1256 diff -Nur --exclude '*.orig' linux/net/ipv4/netfilter/ipt_rpc.c linux/net/ipv4/netfilter/ipt_rpc.c
1257 --- linux/net/ipv4/netfilter/ipt_rpc.c 1970-01-01 01:00:00.000000000 +0100
1258 +++ linux/net/ipv4/netfilter/ipt_rpc.c 2007-08-15 01:40:43.000000000 +0200
1260 +/* RPC extension for IP connection matching, Version 2.2
1261 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
1262 + * - original rpc tracking module
1263 + * - "recent" connection handling for kernel 2.3+ netfilter
1265 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1266 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1268 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1269 + * - upgraded conntrack modules to newnat api - kernel 2.4.20+
1270 + * - extended matching to support filtering on procedures
1272 + * (c) 2004,2005 by David Stes <stes@pandora.be>
1273 + * - upgraded to 2.6.12+ conntrack module api
1274 + * - upgraded to 2.6.13 api
1276 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
1278 + * This program is free software; you can redistribute it and/or
1279 + * modify it under the terms of the GNU General Public License
1280 + * as published by the Free Software Foundation; either version
1281 + * 2 of the License, or (at your option) any later version.
1283 + * Module load syntax:
1284 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
1286 + * Please give the ports of all RPC servers you wish to connect to.
1287 + * If you don't specify ports, the default will be port 111.
1291 + * RPCs should not be exposed to the internet - ask the Pentagon;
1293 + * "The unidentified crackers pleaded guilty in July to charges
1294 + * of juvenile delinquency stemming from a string of Pentagon
1295 + * network intrusions in February.
1297 + * The youths, going by the names TooShort and Makaveli, used
1298 + * a common server security hole to break in, according to
1299 + * Dane Jasper, owner of the California Internet service
1300 + * provider, Sonic. They used the hole, known as the 'statd'
1301 + * exploit, to attempt more than 800 break-ins, Jasper said."
1303 + * From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
1304 + * URL: http://www.wired.com/news/politics/0,1283,16098,00.html
1308 +#include <linux/module.h>
1309 +#include <linux/skbuff.h>
1310 +#include <linux/list.h>
1311 +#include <linux/udp.h>
1312 +#include <linux/tcp.h>
1313 +#include <linux/netfilter_ipv4/ip_tables.h>
1314 +#include <linux/netfilter/nf_conntrack_rpc.h>
1315 +#include <linux/netfilter_ipv4/ipt_rpc.h>
1317 +#define MAX_PORTS 8
1318 +static int ports[MAX_PORTS];
1319 +static int ports_n_c = 0;
1322 +module_param_array(ports, int, &ports_n_c, 0400);
1323 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
1326 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
1327 +MODULE_DESCRIPTION("RPC connection matching module");
1328 +MODULE_LICENSE("GPL");
1330 +#define PRINTK(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1334 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
1337 +#define DEBUGP(format, args...)
1340 +/* EXPORT_NO_SYMBOLS; */
1342 +/* vars from ip_conntrack_rpc_tcp */
1343 +extern struct list_head request_p_list_tcp;
1344 +extern struct module *ip_conntrack_rpc_tcp;
1346 +/* vars from ip_conntrack_rpc_udp */
1347 +extern struct list_head request_p_list_udp;
1348 +extern struct module *ip_conntrack_rpc_udp;
1350 +extern rwlock_t ipct_rpc_tcp_lock;
1351 +extern rwlock_t ipct_rpc_udp_lock;
1353 +#define ASSERT_READ_LOCK(x)
1354 +#define ASSERT_WRITE_LOCK(x)
1357 +#define ASSERT_READ_LOCK(x) \
1359 + if (x == &request_p_list_udp) \
1360 + MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock); \
1361 + else if (x == &request_p_list_tcp) \
1362 + MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock); \
1365 +#define ASSERT_WRITE_LOCK(x) \
1367 + if (x == &request_p_list_udp) \
1368 + MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock); \
1369 + else if (x == &request_p_list_tcp) \
1370 + MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock); \
1374 +const int IPT_RPC_CHAR_LEN = 11;
1376 +static int k_atoi(char *string)
1378 + unsigned int result = 0;
1379 + int maxoctet = IPT_RPC_CHAR_LEN;
1381 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
1386 + if (*string < 48 || *string > 57) {
1389 + result = result * 10 + ( *string - 48 );
1395 +static int match_rpcs(char *c_procs, int i_procs, int proc)
1399 + unsigned int proc_num;
1401 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
1403 + if (i_procs == -1)
1406 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
1408 + proc_ptr = c_procs;
1409 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
1410 + proc_num = k_atoi(proc_ptr);
1412 + if (proc_num == proc)
1420 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
1421 + int *hotdrop, int dir, struct nf_conn *ct,
1422 + int offset, struct list_head request_p_list)
1424 + const struct ipt_rpc_info *rpcinfo = matchinfo;
1425 + struct request_p *req_p = NULL, *p;
1432 + /* This does sanity checking on RPC payloads,
1433 + * and permits only the RPC "get port" (3)
1434 + * in authorised procedures in client
1435 + * communications with the portmapper.
1440 + /* Get RPC requestor */
1441 + if (IXDR_GET_INT32(data) != 3) {
1442 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
1443 + if(rpcinfo->strict == 1)
1447 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
1451 + /* Jump Credentials and Verfifier */
1452 + data = data + IXDR_GET_INT32(data) + 2;
1453 + data = data + IXDR_GET_INT32(data) + 2;
1455 + /* Get RPC procedure */
1456 + if (match_rpcs((char *)&rpcinfo->c_procs,
1457 + rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
1458 + DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
1459 + (unsigned int)IXDR_GET_INT32(data));
1461 + /* If the RPC conntrack half entry already exists .. */
1463 + switch (ct->tuplehash[0].tuple.dst.protonum) {
1465 + write_lock_bh(&ipct_rpc_udp_lock);
1467 + write_lock_bh(&ipct_rpc_tcp_lock);
1469 +/* req_p = LIST_FIND(&request_p_list, request_p_cmp,
1470 + struct request_p *, xid,
1471 + ct->tuplehash[dir].tuple.src.u3.ip,
1472 + ct->tuplehash[dir].tuple.src.u.all);
1474 + list_for_each_entry(p, &request_p_list, list)
1475 + if (p->xid == xid &&
1476 + p->ip == ct->tuplehash[!dir].tuple.src.u3.ip &&
1477 + p->port == ct->tuplehash[!dir].tuple.src.u.all)
1481 + DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1482 + xid, ct->tuplehash[dir].tuple.dst.protonum,
1483 + NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
1484 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
1486 + /* .. remove it */
1487 + if (del_timer(&req_p->timeout))
1488 + req_p->timeout.expires = 0;
1490 + list_del(&req_p->list);
1491 + DEBUGP("RPC req_p removed. [done]\n");
1494 + DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
1495 + xid, ct->tuplehash[dir].tuple.dst.protonum,
1496 + NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip),
1497 + ntohs(ct->tuplehash[dir].tuple.src.u.all));
1500 + switch (ct->tuplehash[0].tuple.dst.protonum) {
1502 + write_unlock_bh(&ipct_rpc_udp_lock);
1504 + write_unlock_bh(&ipct_rpc_tcp_lock);
1507 + if(rpcinfo->strict == 1)
1512 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
1513 + (unsigned int)IXDR_GET_INT32(data));
1514 + return (1 && (!offset));
1519 +/* static int match(const struct sk_buff *skb, const struct net_device *in,
1520 + const struct net_device *out, const void *matchinfo,
1521 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
1523 +static int match(const struct sk_buff *skb, const struct net_device *in,
1524 + const struct net_device *out, const void *matchinfo,
1525 + int offset, unsigned int protoff, int *hotdrop)
1527 + struct nf_conn *ct;
1528 + enum ip_conntrack_info ctinfo;
1529 + const u_int32_t *data;
1530 + enum ip_conntrack_dir dir;
1531 + const struct tcphdr *tcp;
1532 + const struct ipt_rpc_info *rpcinfo = matchinfo;
1533 + int port, portsok;
1535 + struct iphdr *ip; /* stes */
1536 + void *hdr; /* stes */
1537 + u_int16_t datalen; /* stes */
1539 + /* Initialization stes - see 2.4 ip_tables.c ipt_do_table() */
1541 + hdr = (u_int32_t *)ip + ip->ihl;
1542 + datalen = skb->len - ip->ihl * 4;
1544 + DEBUGP("new packet to evaluate ..\n");
1546 + ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
1548 + DEBUGP("no ct available [skip]\n");
1552 + DEBUGP("ct detected. [cont]\n");
1553 + dir = CTINFO2DIR(ctinfo);
1555 + /* we only want the client to server packets for matching */
1556 + if (dir != IP_CT_DIR_ORIGINAL)
1559 + /* This does sanity checking on UDP or TCP packets,
1560 + * like their respective modules.
1563 + switch (ct->tuplehash[0].tuple.dst.protonum) {
1566 + DEBUGP("PROTO_UDP [cont]\n");
1567 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
1568 + DEBUGP("packet does not contain a complete header. [drop]\n");
1572 + for (port=0,portsok=0; port <= ports_n_c; port++) {
1573 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
1578 + if (portsok == 0) {
1579 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
1580 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
1584 + if ((datalen - sizeof(struct udphdr)) != 56) {
1585 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
1586 + if (rpcinfo->strict == 1)
1590 + DEBUGP("packet length is correct. [cont]\n");
1592 + /* Get to the data */
1593 + data = (const u_int32_t *)hdr + 2;
1595 + /* Check the RPC data */
1596 + tval = check_rpc_packet(data, matchinfo, hotdrop,
1598 + request_p_list_udp);
1604 + DEBUGP("PROTO_TCP [cont]\n");
1605 + if (offset == 0 && datalen < sizeof(struct tcphdr)) {
1606 + DEBUGP("packet does not contain a complete header. [drop]\n");
1610 + for (port=0,portsok=0; port <= ports_n_c; port++) {
1611 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
1616 + if (portsok == 0) {
1617 + DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
1618 + ntohs(ct->tuplehash[dir].tuple.dst.u.all));
1623 + if (datalen == (tcp->doff * 4)) {
1624 + DEBUGP("packet does not contain any data. [match]\n");
1625 + return (1 && (!offset));
1628 + /* Tests if packet len is ok */
1629 + if ((datalen - (tcp->doff * 4)) != 60) {
1630 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
1631 + if(rpcinfo->strict == 1)
1635 + DEBUGP("packet length is correct. [cont]\n");
1637 + /* Get to the data */
1638 + data = (const u_int32_t *)tcp + tcp->doff + 1;
1640 + /* Check the RPC data */
1641 + tval = check_rpc_packet(data, matchinfo, hotdrop,
1643 + request_p_list_tcp);
1649 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
1650 + ct->tuplehash[0].tuple.dst.protonum);
1655 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
1656 + unsigned int matchsize, unsigned int hook_mask)
1659 + & ~((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING)
1660 + | (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_LOCAL_OUT))) {
1661 + printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
1665 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
1671 +static struct xt_match rpc_match = {
1673 + .family = AF_INET,
1675 + .matchsize = sizeof(struct ipt_rpc_info),
1676 + .checkentry = checkentry,
1677 + .me = THIS_MODULE,
1680 +static int __init init(void)
1684 + /* If no port given, default to standard RPC port */
1685 + if (ports[0] == 0)
1686 + ports[0] = RPC_PORT;
1688 + PRINTK("registering match [%s] for;\n", rpc_match.name);
1689 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
1690 + PRINTK(" port %i (UDP|TCP);\n", ports[port]);
1694 + return xt_register_match(&rpc_match);
1698 +static void fini(void)
1700 + DEBUGP("unregistering match\n");
1701 + xt_unregister_match(&rpc_match);