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