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