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