]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.5-patch-o-matic-ng-extra-20040330.patch
- obsolete
[packages/kernel.git] / 2.6.5-patch-o-matic-ng-extra-20040330.patch
1 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_helpers.h linux-2.6.5-rc3/include/linux/netfilter_helpers.h
2 --- linux-2.6.5-rc3.org/include/linux/netfilter_helpers.h       1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.5-rc3/include/linux/netfilter_helpers.h   2004-03-30 11:52:01.000000000 +0200
4 @@ -0,0 +1,133 @@
5 +/*
6 + * Helpers for netfiler modules.  This file provides implementations for basic
7 + * functions such as strncasecmp(), etc.
8 + *
9 + * gcc will warn for defined but unused functions, so we only include the
10 + * functions requested.  The following macros are used:
11 + *   NF_NEED_STRNCASECMP        nf_strncasecmp()
12 + *   NF_NEED_STRTOU16           nf_strtou16()
13 + *   NF_NEED_STRTOU32           nf_strtou32()
14 + */
15 +#ifndef _NETFILTER_HELPERS_H
16 +#define _NETFILTER_HELPERS_H
17 +
18 +/* Only include these functions for kernel code. */
19 +#ifdef __KERNEL__
20 +
21 +#include <linux/ctype.h>
22 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
23 +
24 +/*
25 + * The standard strncasecmp()
26 + */
27 +#ifdef NF_NEED_STRNCASECMP
28 +static int
29 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
30 +{
31 +    if (s1 == NULL || s2 == NULL)
32 +    {
33 +        if (s1 == NULL && s2 == NULL)
34 +        {
35 +            return 0;
36 +        }
37 +        return (s1 == NULL) ? -1 : 1;
38 +    }
39 +    while (len > 0 && tolower(*s1) == tolower(*s2))
40 +    {
41 +        len--;
42 +        s1++;
43 +        s2++;
44 +    }
45 +    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
46 +}
47 +#endif /* NF_NEED_STRNCASECMP */
48 +
49 +/*
50 + * Parse a string containing a 16-bit unsigned integer.
51 + * Returns the number of chars used, or zero if no number is found.
52 + */
53 +#ifdef NF_NEED_STRTOU16
54 +static int
55 +nf_strtou16(const char* pbuf, u_int16_t* pval)
56 +{
57 +    int n = 0;
58 +
59 +    *pval = 0;
60 +    while (isdigit(pbuf[n]))
61 +    {
62 +        *pval = (*pval * 10) + (pbuf[n] - '0');
63 +        n++;
64 +    }
65 +
66 +    return n;
67 +}
68 +#endif /* NF_NEED_STRTOU16 */
69 +
70 +/*
71 + * Parse a string containing a 32-bit unsigned integer.
72 + * Returns the number of chars used, or zero if no number is found.
73 + */
74 +#ifdef NF_NEED_STRTOU32
75 +static int
76 +nf_strtou32(const char* pbuf, u_int32_t* pval)
77 +{
78 +    int n = 0;
79 +
80 +    *pval = 0;
81 +    while (pbuf[n] >= '0' && pbuf[n] <= '9')
82 +    {
83 +        *pval = (*pval * 10) + (pbuf[n] - '0');
84 +        n++;
85 +    }
86 +
87 +    return n;
88 +}
89 +#endif /* NF_NEED_STRTOU32 */
90 +
91 +/*
92 + * Given a buffer and length, advance to the next line and mark the current
93 + * line.
94 + */
95 +#ifdef NF_NEED_NEXTLINE
96 +static int
97 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
98 +{
99 +    uint    off = *poff;
100 +    uint    physlen = 0;
101 +
102 +    if (off >= len)
103 +    {
104 +        return 0;
105 +    }
106 +
107 +    while (p[off] != '\n')
108 +    {
109 +        if (len-off <= 1)
110 +        {
111 +            return 0;
112 +        }
113 +
114 +        physlen++;
115 +        off++;
116 +    }
117 +
118 +    /* if we saw a crlf, physlen needs adjusted */
119 +    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
120 +    {
121 +        physlen--;
122 +    }
123 +
124 +    /* advance past the newline */
125 +    off++;
126 +
127 +    *plineoff = *poff;
128 +    *plinelen = physlen;
129 +    *poff = off;
130 +
131 +    return 1;
132 +}
133 +#endif /* NF_NEED_NEXTLINE */
134 +
135 +#endif /* __KERNEL__ */
136 +
137 +#endif /* _NETFILTER_HELPERS_H */
138 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
139 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h     2004-03-30 11:31:19.000000000 +0200
140 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-03-30 11:53:01.000000000 +0200
141 @@ -64,6 +64,11 @@
142  };
143  
144  /* Add protocol helper include file here */
145 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
146 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
147 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
148 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
149 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
150  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
151  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
152  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
153 @@ -71,6 +76,12 @@
154  /* per expectation: application helper private data */
155  union ip_conntrack_expect_help {
156         /* insert conntrack helper private data (expect) here */
157 +       struct ip_ct_talk_expect exp_talk_info;
158 +       struct ip_ct_rtsp_expect exp_rtsp_info;
159 +       struct ip_ct_rtsp_master ct_rtsp_info;
160 +       struct ip_ct_rsh_expect exp_rsh_info;
161 +       struct ip_ct_mms_expect exp_mms_info;
162 +       struct ip_ct_h225_expect exp_h225_info;
163         struct ip_ct_amanda_expect exp_amanda_info;
164         struct ip_ct_ftp_expect exp_ftp_info;
165         struct ip_ct_irc_expect exp_irc_info;
166 @@ -85,6 +96,10 @@
167  /* per conntrack: application helper private data */
168  union ip_conntrack_help {
169         /* insert conntrack helper private data (master) here */
170 +       struct ip_ct_talk_master ct_talk_info;
171 +       struct ip_ct_rsh_master ct_rsh_info;
172 +       struct ip_ct_mms_master ct_mms_info;
173 +       struct ip_ct_h225_master ct_h225_info;
174         struct ip_ct_ftp_master ct_ftp_info;
175         struct ip_ct_irc_master ct_irc_info;
176  };
177 @@ -206,6 +221,10 @@
178         } nat;
179  #endif /* CONFIG_IP_NF_NAT_NEEDED */
180  
181 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
182 +       unsigned long mark;
183 +#endif
184 +
185  };
186  
187  /* get master conntrack via master expectation */
188 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
189 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h     1970-01-01 01:00:00.000000000 +0100
190 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 2004-03-30 11:50:58.000000000 +0200
191 @@ -0,0 +1,70 @@
192 +#ifndef _IP_CT_CUSEEME
193 +#define _IP_CT_CUSEEME
194 +
195 +#define CUSEEME_PORT 7648
196 +
197 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
198 +
199 +#pragma pack(1)
200 +/* CuSeeMe data header */
201 +struct cu_header {
202 +       u_int16_t       dest_family;
203 +       u_int16_t       dest_port;
204 +       u_int32_t       dest_addr;
205 +       int16_t         family;
206 +       u_int16_t       port;
207 +       u_int32_t       addr;
208 +       u_int32_t       seq;
209 +       u_int16_t       msg;
210 +       u_int16_t       data_type;
211 +                               /* possible values:
212 +                                * 1    small video
213 +                                * 2    big video
214 +                                * 3    audio
215 +                                * 100  acknowledge connectivity when there
216 +                                *      is nothing else to send
217 +                                * 101  OpenContinue packet
218 +                                * 104  display a text message and 
219 +                                *      disconnect (used by reflector to
220 +                                *      kick clients off)
221 +                                * 105  display a text message (welcome
222 +                                *      message from reflector)
223 +                                * 106  exchanged among reflectors for
224 +                                *      reflector interoperation
225 +                                * 107  carry aux stream data when there is
226 +                                *      no video to piggy-back on
227 +                                * 108  obsolete (used in Mac alpha version)
228 +                                * 109  obsolete (used in Mac alpha version)
229 +                                * 110  used for data rate control
230 +                                * 111  used for data rate control
231 +                                * 256  aux data control messages
232 +                                * 257  aux data packets
233 +                                * */
234 +       u_int16_t       packet_len;
235 +};
236 +
237 +/* Open Continue Header */
238 +struct oc_header {
239 +       struct cu_header        cu_head;
240 +       u_int16_t       client_count; /* Number of client info structs */
241 +       u_int32_t       seq_no;
242 +       char            user_name[20];
243 +       char            stuff[4];     /* Flags, version stuff, etc */
244 +};
245 +
246 +/* Client info structures */
247 +struct client_info {
248 +       u_int32_t       address;      /* Client address */
249 +       char            stuff[8];     /* Flags, pruning bitfield, packet counts, etc */
250 +};
251 +#pragma pack()
252 +
253 +/* This structure is per expected connection */
254 +struct ip_ct_cuseeme_expect {
255 +};
256 +
257 +/* This structure exists only once per master */
258 +struct ip_ct_cuseeme_master {
259 +};
260 +
261 +#endif /* _IP_CT_CUSEEME */
262 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
263 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h        1970-01-01 01:00:00.000000000 +0100
264 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h    2004-03-30 11:51:04.000000000 +0200
265 @@ -0,0 +1,31 @@
266 +#ifndef _IP_CONNTRACK_H323_H
267 +#define _IP_CONNTRACK_H323_H
268 +/* H.323 connection tracking. */
269 +
270 +#ifdef __KERNEL__
271 +/* Protects H.323 related data */
272 +#include <linux/netfilter_ipv4/lockhelp.h>
273 +DECLARE_LOCK_EXTERN(ip_h323_lock);
274 +#endif
275 +
276 +/* Default H.225 port */
277 +#define H225_PORT      1720
278 +
279 +/* This structure is per expected connection */
280 +struct ip_ct_h225_expect {
281 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
282 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
283 +       unsigned int offset;            /* offset of the address in the payload */
284 +};
285 +
286 +/* This structure exists only once per master */
287 +struct ip_ct_h225_master {
288 +       int is_h225;                            /* H.225 or H.245 connection */
289 +#ifdef CONFIG_IP_NF_NAT_NEEDED
290 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
291 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
292 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
293 +#endif
294 +};
295 +
296 +#endif /* _IP_CONNTRACK_H323_H */
297 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
298 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
299 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h     2004-03-30 11:51:24.000000000 +0200
300 @@ -0,0 +1,31 @@
301 +#ifndef _IP_CONNTRACK_MMS_H
302 +#define _IP_CONNTRACK_MMS_H
303 +/* MMS tracking. */
304 +
305 +#ifdef __KERNEL__
306 +#include <linux/netfilter_ipv4/lockhelp.h>
307 +
308 +DECLARE_LOCK_EXTERN(ip_mms_lock);
309 +
310 +#define MMS_PORT                         1755
311 +#define MMS_SRV_MSG_ID                   196610
312 +
313 +#define MMS_SRV_MSG_OFFSET               36
314 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
315 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
316 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
317 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
318 +#endif
319 +
320 +/* This structure is per expected connection */
321 +struct ip_ct_mms_expect {
322 +       u_int32_t len;
323 +       u_int32_t padding;
324 +       u_int16_t port;
325 +};
326 +
327 +/* This structure exists only once per master */
328 +struct ip_ct_mms_master {
329 +};
330 +
331 +#endif /* _IP_CONNTRACK_MMS_H */
332 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
333 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h      1970-01-01 01:00:00.000000000 +0100
334 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h  2004-03-30 11:51:52.000000000 +0200
335 @@ -0,0 +1,21 @@
336 +#ifndef _IP_CT_QUAKE3
337 +#define _IP_CT_QUAKE3
338 +
339 +/* Don't confuse with 27960, often used as the Server Port */
340 +#define QUAKE3_MASTER_PORT 27950
341 +
342 +struct quake3_search {
343 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
344 +       const char *pattern;
345 +       size_t plen;
346 +}; 
347 +
348 +/* This structure is per expected connection */
349 +struct ip_ct_quake3_expect {
350 +};
351 +
352 +/* This structure exists only once per master */
353 +struct ip_ct_quake3_master {
354 +};
355 +
356 +#endif /* _IP_CT_QUAKE3 */
357 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
358 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
359 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h     2004-03-30 11:51:55.000000000 +0200
360 @@ -0,0 +1,68 @@
361 +/* RPC extension for IP connection tracking, Version 2.2
362 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
363 + *     - original rpc tracking module
364 + *     - "recent" connection handling for kernel 2.3+ netfilter
365 + *
366 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
367 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
368 + *
369 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
370 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
371 + *     - extended matching to support filtering on procedures
372 + *
373 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
374 + *
375 + *     This program is free software; you can redistribute it and/or
376 + *     modify it under the terms of the GNU General Public License
377 + *     as published by the Free Software Foundation; either version
378 + *     2 of the License, or (at your option) any later version.
379 + **
380 + */
381 +
382 +#include <asm/param.h>
383 +#include <linux/sched.h>
384 +#include <linux/timer.h>
385 +#include <linux/stddef.h>
386 +#include <linux/list.h>
387 +
388 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
389 +
390 +#ifndef _IP_CONNTRACK_RPC_H
391 +#define _IP_CONNTRACK_RPC_H
392 +
393 +#define RPC_PORT       111
394 +
395 +
396 +/* Datum in RPC packets are encoded in XDR */
397 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
398 +
399 +/* Fast timeout, to deny DoS atacks */
400 +#define EXP (60 * HZ)
401 +
402 +/* Normal timeouts */
403 +#define EXPIRES (180 * HZ)
404 +
405 +/* For future conections RPC, using client's cache bindings
406 + * I'll use ip_conntrack_lock to lock these lists      */
407 +
408 +/* This identifies each request and stores protocol */
409 +struct request_p {
410 +       struct list_head list;
411 +
412 +       u_int32_t xid;   
413 +       u_int32_t ip;
414 +       u_int16_t port;
415 +       
416 +       /* Protocol */
417 +       u_int16_t proto;
418 +
419 +       struct timer_list timeout;
420 +};
421 +
422 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
423 +                               u_int32_t ip, u_int32_t port) {
424 +       return (p->xid == xid && p->ip == ip && p->port);
425 +
426 +}
427 +
428 +#endif /* _IP_CONNTRACK_RPC_H */
429 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
430 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
431 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h     2004-03-30 11:51:56.000000000 +0200
432 @@ -0,0 +1,35 @@
433 +/* RSH extension for IP connection tracking, Version 1.0
434 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
435 + * based on HW's ip_conntrack_irc.c     
436 + *
437 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
438 + *
439 + *      This program is free software; you can redistribute it and/or
440 + *      modify it under the terms of the GNU General Public License
441 + *      as published by the Free Software Foundation; either version
442 + *      2 of the License, or (at your option) any later version.
443 + */
444 +#ifndef _IP_CONNTRACK_RSH_H
445 +#define _IP_CONNTRACK_RSH_H
446 +
447 +#ifdef __KERNEL__
448 +#include <linux/netfilter_ipv4/lockhelp.h>
449 +
450 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
451 +#endif
452 +
453 +
454 +#define RSH_PORT       514
455 +
456 +/* This structure is per expected connection */
457 +struct ip_ct_rsh_expect
458 +{
459 +       u_int16_t port;
460 +};
461 +
462 +/* This structure exists only once per master */
463 +struct ip_ct_rsh_master {
464 +};
465 +
466 +#endif /* _IP_CONNTRACK_RSH_H */
467 +
468 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
469 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h        1970-01-01 01:00:00.000000000 +0100
470 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h    2004-03-30 11:52:01.000000000 +0200
471 @@ -0,0 +1,68 @@
472 +/*
473 + * RTSP extension for IP connection tracking.
474 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
475 + * based on ip_conntrack_irc.h
476 + *
477 + *      This program is free software; you can redistribute it and/or
478 + *      modify it under the terms of the GNU General Public License
479 + *      as published by the Free Software Foundation; either version
480 + *      2 of the License, or (at your option) any later version.
481 + */
482 +#ifndef _IP_CONNTRACK_RTSP_H
483 +#define _IP_CONNTRACK_RTSP_H
484 +
485 +/* #define IP_NF_RTSP_DEBUG */
486 +#define IP_NF_RTSP_VERSION "0.01"
487 +
488 +/* port block types */
489 +typedef enum {
490 +    pb_single,  /* client_port=x */
491 +    pb_range,   /* client_port=x-y */
492 +    pb_discon   /* client_port=x/y (rtspbis) */
493 +} portblock_t;
494 +
495 +/* We record seq number and length of rtsp headers here, all in host order. */
496 +
497 +/*
498 + * This structure is per expected connection.  It is a member of struct
499 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
500 + * there and we are expected to only store the length of the data which
501 + * needs replaced.  If a packet contains multiple RTSP messages, we create
502 + * one expected connection per message.
503 + *
504 + * We use these variables to mark the entire header block.  This may seem
505 + * like overkill, but the nature of RTSP requires it.  A header may appear
506 + * multiple times in a message.  We must treat two Transport headers the
507 + * same as one Transport header with two entries.
508 + */
509 +struct ip_ct_rtsp_expect
510 +{
511 +    u_int32_t   len;        /* length of header block */
512 +    portblock_t pbtype;     /* Type of port block that was requested */
513 +    u_int16_t   loport;     /* Port that was requested, low or first */
514 +    u_int16_t   hiport;     /* Port that was requested, high or second */
515 +#if 0
516 +    uint        method;     /* RTSP method */
517 +    uint        cseq;       /* CSeq from request */
518 +#endif
519 +};
520 +
521 +/* This structure exists only once per master */
522 +struct ip_ct_rtsp_master
523 +{
524 +    /* Empty (?) */
525 +};
526 +
527 +
528 +#ifdef __KERNEL__
529 +
530 +#include <linux/netfilter_ipv4/lockhelp.h>
531 +
532 +#define RTSP_PORT   554
533 +
534 +/* Protects rtsp part of conntracks */
535 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
536 +
537 +#endif /* __KERNEL__ */
538 +
539 +#endif /* _IP_CONNTRACK_RTSP_H */
540 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
541 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h        1970-01-01 01:00:00.000000000 +0100
542 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h    2004-03-30 11:53:01.000000000 +0200
543 @@ -0,0 +1,152 @@
544 +#ifndef _IP_CONNTRACK_TALK_H
545 +#define _IP_CONNTRACK_TALK_H
546 +/* TALK tracking. */
547 +
548 +#ifdef __KERNEL__
549 +#include <linux/in.h>
550 +#include <linux/netfilter_ipv4/lockhelp.h>
551 +
552 +/* Protects talk part of conntracks */
553 +DECLARE_LOCK_EXTERN(ip_talk_lock);
554 +#endif
555 +
556 +
557 +#define TALK_PORT      517
558 +#define NTALK_PORT     518
559 +
560 +/* talk structures and constants from <protocols/talkd.h> */
561 +
562 +/*
563 + * 4.3BSD struct sockaddr
564 + */
565 +struct talk_addr {
566 +       u_int16_t ta_family;
567 +       u_int16_t ta_port;
568 +       u_int32_t ta_addr;
569 +       u_int32_t ta_junk1;
570 +       u_int32_t ta_junk2;
571 +};
572 +
573 +#define        TALK_OLD_NSIZE  9
574 +#define        TALK_NSIZE      12
575 +#define        TALK_TTY_NSIZE  16
576 +
577 +/*
578 + * Client->server request message formats.
579 + */
580 +struct talk_msg {
581 +       u_char  type;           /* request type, see below */
582 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
583 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
584 +       u_char  pad;
585 +       u_int32_t id_num;       /* message id */
586 +       int32_t pid;            /* caller's process id */
587 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
588 +       struct  talk_addr addr;         /* old (4.3) style */
589 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
590 +};
591 +
592 +struct ntalk_msg {
593 +       u_char  vers;           /* protocol version */
594 +       u_char  type;           /* request type, see below */
595 +       u_char  answer;         /* not used */
596 +       u_char  pad;
597 +       u_int32_t id_num;       /* message id */
598 +       struct  talk_addr addr;         /* old (4.3) style */
599 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
600 +       int32_t pid;            /* caller's process id */
601 +       char    l_name[TALK_NSIZE];/* caller's name */
602 +       char    r_name[TALK_NSIZE];/* callee's name */
603 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
604 +};
605 +
606 +struct ntalk2_msg {
607 +       u_char  vers;           /* talk protocol version    */
608 +       u_char  type;           /* request type             */
609 +       u_char  answer;         /*  */
610 +       u_char  extended;       /* !0 if additional parts   */
611 +       u_int32_t id_num;       /* message id number (dels) */
612 +       struct  talk_addr addr;         /* target address   */
613 +       struct  talk_addr ctl_addr;     /* reply to address */
614 +       int32_t pid;            /* caller's process id */
615 +       char    l_name[TALK_NSIZE];  /* caller's name */
616 +       char    r_name[TALK_NSIZE];  /* callee's name */
617 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
618 +};
619 +
620 +/*
621 + * Server->client response message formats.
622 + */
623 +struct talk_response {
624 +       u_char  type;           /* type of request message, see below */
625 +       u_char  answer;         /* response to request message, see below */
626 +       u_char  pad[2];
627 +       u_int32_t id_num;       /* message id */
628 +       struct  talk_addr addr; /* address for establishing conversation */
629 +};
630 +
631 +struct ntalk_response {
632 +       u_char  vers;           /* protocol version */
633 +       u_char  type;           /* type of request message, see below */
634 +       u_char  answer;         /* response to request message, see below */
635 +       u_char  pad;
636 +       u_int32_t id_num;       /* message id */
637 +       struct  talk_addr addr; /* address for establishing conversation */
638 +};
639 +
640 +struct ntalk2_response {
641 +       u_char  vers;           /* protocol version         */
642 +       u_char  type;           /* type of request message  */
643 +       u_char  answer;         /* response to request      */
644 +       u_char  rvers;          /* Version of answering vers*/
645 +       u_int32_t id_num;       /* message id number        */
646 +       struct  talk_addr addr; /* address for connection   */
647 +       /* This is at the end to compatiblize this with NTALK version.   */
648 +       char    r_name[TALK_NSIZE]; /* callee's name            */
649 +};
650 +
651 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
652 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
653 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
654 +
655 +#define        TALK_VERSION    0               /* protocol versions */
656 +#define        NTALK_VERSION   1
657 +#define        NTALK2_VERSION  2
658 +
659 +/* message type values */
660 +#define LEAVE_INVITE   0       /* leave invitation with server */
661 +#define LOOK_UP                1       /* check for invitation by callee */
662 +#define DELETE         2       /* delete invitation by caller */
663 +#define ANNOUNCE       3       /* announce invitation by caller */
664 +/* NTALK2 */
665 +#define REPLY_QUERY    4       /* request reply data from local daemon */
666 +
667 +/* answer values */
668 +#define SUCCESS                0       /* operation completed properly */
669 +#define NOT_HERE       1       /* callee not logged in */
670 +#define FAILED         2       /* operation failed for unexplained reason */
671 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
672 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
673 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
674 +#define        BADVERSION      6       /* request has invalid protocol version */
675 +#define        BADADDR         7       /* request has invalid addr value */
676 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
677 +/* NTALK2 */
678 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
679 +#define TRY_HERE       10      /* Not on this machine, try this      */
680 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
681 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
682 +
683 +/* We don't really need much for talk */
684 +struct ip_ct_talk_expect
685 +{
686 +       /* Port that was to be used */
687 +       u_int16_t port;
688 +};
689 +
690 +/* This structure exists only once per master */
691 +struct ip_ct_talk_master
692 +{
693 +};
694 +
695 +#endif /* _IP_CONNTRACK_TALK_H */
696 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
697 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h     1970-01-01 01:00:00.000000000 +0100
698 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-03-30 11:48:14.000000000 +0200
699 @@ -0,0 +1,25 @@
700 +#ifndef _IPT_CONNMARK_H_target
701 +#define _IPT_CONNMARK_H_target
702 +
703 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
704 + * by Henrik Nordstrom <hno@marasystems.com>
705 + *
706 + * This program is free software; you can redistribute it and/or modify
707 + * it under the terms of the GNU General Public License as published by
708 + * the Free Software Foundation; either version 2 of the License, or
709 + * (at your option) any later version.
710 + */
711 +
712 +enum {
713 +       IPT_CONNMARK_SET = 0,
714 +       IPT_CONNMARK_SAVE,
715 +       IPT_CONNMARK_RESTORE
716 +};
717 +
718 +struct ipt_connmark_target_info {
719 +       unsigned long mark;
720 +       unsigned long mask;
721 +       u_int8_t mode;
722 +};
723 +
724 +#endif /*_IPT_CONNMARK_H_target*/
725 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
726 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h       1970-01-01 01:00:00.000000000 +0100
727 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h   2004-03-30 11:48:25.000000000 +0200
728 @@ -0,0 +1,13 @@
729 +#ifndef _IPT_IPMARK_H_target
730 +#define _IPT_IPMARK_H_target
731 +
732 +struct ipt_ipmark_target_info {
733 +       unsigned long andmask;
734 +       unsigned long ormask;
735 +       unsigned int addr;
736 +};
737 +
738 +#define IPT_IPMARK_SRC    0
739 +#define IPT_IPMARK_DST    1
740 +
741 +#endif /*_IPT_IPMARK_H_target*/
742 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h
743 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h        1970-01-01 01:00:00.000000000 +0100
744 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h    2004-03-30 11:48:31.000000000 +0200
745 @@ -0,0 +1,22 @@
746 +/* Header file for iptables ipt_ROUTE target
747 + *
748 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
749 + *
750 + * This software is distributed under GNU GPL v2, 1991
751 + */
752 +#ifndef _IPT_ROUTE_H_target
753 +#define _IPT_ROUTE_H_target
754 +
755 +#define IPT_ROUTE_IFNAMSIZ 16
756 +
757 +struct ipt_route_target_info {
758 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
759 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
760 +       u_int32_t gw;                           /* IP address of gateway */
761 +       u_int8_t  flags;
762 +};
763 +
764 +/* Values for "flags" field */
765 +#define IPT_ROUTE_CONTINUE        0x01
766 +
767 +#endif /*_IPT_ROUTE_H_target*/
768 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_TCPLAG.h
769 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h       1970-01-01 01:00:00.000000000 +0100
770 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_TCPLAG.h   2004-03-30 11:50:30.000000000 +0200
771 @@ -0,0 +1,10 @@
772 +#ifndef _IPT_TCPLAG_H
773 +#define _IPT_TCPLAG_H
774 +
775 +struct ipt_tcplag
776 +{
777 +       unsigned char level;
778 +       unsigned char prefix[ 15 ];
779 +};
780 +
781 +#endif
782 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
783 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h  1970-01-01 01:00:00.000000000 +0100
784 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_XOR.h      2004-03-30 11:50:41.000000000 +0200
785 @@ -0,0 +1,9 @@
786 +#ifndef _IPT_XOR_H
787 +#define _IPT_XOR_H
788 +
789 +struct ipt_XOR_info {
790 +       char            key[30];
791 +       u_int8_t        block_size;
792 +};
793 +
794 +#endif /* _IPT_XOR_H */
795 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
796 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h     1970-01-01 01:00:00.000000000 +0100
797 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-03-30 11:50:44.000000000 +0200
798 @@ -0,0 +1,11 @@
799 +#ifndef _IPT_ADDRTYPE_H
800 +#define _IPT_ADDRTYPE_H
801 +
802 +struct ipt_addrtype_info {
803 +       u_int16_t       source;         /* source-type mask */
804 +       u_int16_t       dest;           /* dest-type mask */
805 +       int             invert_source;
806 +       int             invert_dest;
807 +};
808 +
809 +#endif
810 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_condition.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_condition.h
811 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_condition.h    1970-01-01 01:00:00.000000000 +0100
812 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_condition.h        2004-03-30 11:50:47.000000000 +0200
813 @@ -0,0 +1,11 @@
814 +#ifndef __IPT_CONDITION_MATCH__
815 +#define __IPT_CONDITION_MATCH__
816 +
817 +#define CONDITION_NAME_LEN  32
818 +
819 +struct condition_info {
820 +       char name[CONDITION_NAME_LEN];
821 +       int  invert;
822 +};
823 +
824 +#endif
825 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
826 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h     1970-01-01 01:00:00.000000000 +0100
827 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-03-30 11:48:14.000000000 +0200
828 @@ -0,0 +1,18 @@
829 +#ifndef _IPT_CONNMARK_H
830 +#define _IPT_CONNMARK_H
831 +
832 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
833 + * by Henrik Nordstrom <hno@marasystems.com>
834 + *
835 + * This program is free software; you can redistribute it and/or modify
836 + * it under the terms of the GNU General Public License as published by
837 + * the Free Software Foundation; either version 2 of the License, or
838 + * (at your option) any later version.
839 + */
840 +
841 +struct ipt_connmark_info {
842 +       unsigned long mark, mask;
843 +       u_int8_t invert;
844 +};
845 +
846 +#endif /*_IPT_CONNMARK_H*/
847 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_policy.h
848 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h       1970-01-01 01:00:00.000000000 +0100
849 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_policy.h   2004-03-30 11:51:40.000000000 +0200
850 @@ -0,0 +1,52 @@
851 +#ifndef _IPT_POLICY_H
852 +#define _IPT_POLICY_H
853 +
854 +#define POLICY_MAX_ELEM        4
855 +
856 +enum ipt_policy_flags
857 +{
858 +       POLICY_MATCH_IN         = 0x1,
859 +       POLICY_MATCH_OUT        = 0x2,
860 +       POLICY_MATCH_NONE       = 0x4,
861 +       POLICY_MATCH_STRICT     = 0x8,
862 +};
863 +
864 +enum ipt_policy_modes
865 +{
866 +       POLICY_MODE_TRANSPORT,
867 +       POLICY_MODE_TUNNEL
868 +};
869 +
870 +struct ipt_policy_spec
871 +{
872 +       u_int8_t        saddr:1,
873 +                       daddr:1,
874 +                       proto:1,
875 +                       mode:1,
876 +                       spi:1,
877 +                       reqid:1;
878 +};
879 +
880 +struct ipt_policy_elem
881 +{
882 +       u_int32_t       saddr;
883 +       u_int32_t       smask;
884 +       u_int32_t       daddr;
885 +       u_int32_t       dmask;
886 +       u_int32_t       spi;
887 +       u_int32_t       reqid;
888 +       u_int8_t        proto;
889 +       u_int8_t        mode;
890 +
891 +       struct ipt_policy_spec  match;
892 +       struct ipt_policy_spec  invert;
893 +};
894 +
895 +struct ipt_policy_info
896 +{
897 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
898 +       u_int16_t flags;
899 +       u_int16_t len;
900 +};
901 +
902 +#endif /* _IPT_POLICY_H */
903 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_rpc.h
904 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h  1970-01-01 01:00:00.000000000 +0100
905 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_rpc.h      2004-03-30 11:51:55.000000000 +0200
906 @@ -0,0 +1,35 @@
907 +/* RPC extension for IP netfilter matching, Version 2.2
908 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
909 + *     - original rpc tracking module
910 + *     - "recent" connection handling for kernel 2.3+ netfilter
911 + *
912 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
913 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
914 + *
915 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
916 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
917 + *     - extended matching to support filtering on procedures
918 + *
919 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
920 + *
921 + *     This program is free software; you can redistribute it and/or
922 + *     modify it under the terms of the GNU General Public License
923 + *     as published by the Free Software Foundation; either version
924 + *     2 of the License, or (at your option) any later version.
925 + **
926 + */
927 +
928 +#ifndef _IPT_RPC_H
929 +#define _IPT_RPC_H
930 +
931 +struct ipt_rpc_data;
932 +
933 +struct ipt_rpc_info {
934 +       int inverse;
935 +       int strict;
936 +       const char c_procs[1408];
937 +       int i_procs;
938 +       struct ipt_rpc_data *data;
939 +};
940 +
941 +#endif /* _IPT_RPC_H */
942 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_string.h
943 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv4/ipt_string.h       1970-01-01 01:00:00.000000000 +0100
944 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv4/ipt_string.h   2004-03-30 11:52:56.000000000 +0200
945 @@ -0,0 +1,21 @@
946 +#ifndef _IPT_STRING_H
947 +#define _IPT_STRING_H
948 +
949 +/* *** PERFORMANCE TWEAK ***
950 + * Packet size and search string threshold,
951 + * above which sublinear searches is used. */
952 +#define IPT_STRING_HAYSTACK_THRESH     100
953 +#define IPT_STRING_NEEDLE_THRESH       20
954 +
955 +#define BM_MAX_NLEN 256
956 +#define BM_MAX_HLEN 1024
957 +
958 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
959 +
960 +struct ipt_string_info {
961 +    char string[BM_MAX_NLEN];
962 +    u_int16_t invert;
963 +    u_int16_t len;
964 +};
965 +
966 +#endif /* _IPT_STRING_H */
967 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h
968 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h       1970-01-01 01:00:00.000000000 +0100
969 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h   2004-03-30 11:48:31.000000000 +0200
970 @@ -0,0 +1,22 @@
971 +/* Header file for iptables ip6t_ROUTE target
972 + *
973 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
974 + *
975 + * This software is distributed under GNU GPL v2, 1991
976 + */
977 +#ifndef _IPT_ROUTE_H_target
978 +#define _IPT_ROUTE_H_target
979 +
980 +#define IP6T_ROUTE_IFNAMSIZ 16
981 +
982 +struct ip6t_route_target_info {
983 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
984 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
985 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
986 +       u_int8_t  flags;
987 +};
988 +
989 +/* Values for "flags" field */
990 +#define IP6T_ROUTE_CONTINUE        0x01
991 +
992 +#endif /*_IP6T_ROUTE_H_target*/
993 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_condition.h
994 --- linux-2.6.5-rc3.org/include/linux/netfilter_ipv6/ip6t_condition.h   1970-01-01 01:00:00.000000000 +0100
995 +++ linux-2.6.5-rc3/include/linux/netfilter_ipv6/ip6t_condition.h       2004-03-30 11:50:47.000000000 +0200
996 @@ -0,0 +1,11 @@
997 +#ifndef __IP6T_CONDITION_MATCH__
998 +#define __IP6T_CONDITION_MATCH__
999 +
1000 +#define CONDITION6_NAME_LEN  32
1001 +
1002 +struct condition6_info {
1003 +       char name[CONDITION6_NAME_LEN];
1004 +       int  invert;
1005 +};
1006 +
1007 +#endif
1008 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/linux/netfilter_mime.h linux-2.6.5-rc3/include/linux/netfilter_mime.h
1009 --- linux-2.6.5-rc3.org/include/linux/netfilter_mime.h  1970-01-01 01:00:00.000000000 +0100
1010 +++ linux-2.6.5-rc3/include/linux/netfilter_mime.h      2004-03-30 11:52:01.000000000 +0200
1011 @@ -0,0 +1,89 @@
1012 +/*
1013 + * MIME functions for netfilter modules.  This file provides implementations
1014 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
1015 + * HTTP, RTSP, SIP, etc.
1016 + *
1017 + * gcc will warn for defined but unused functions, so we only include the
1018 + * functions requested.  The following macros are used:
1019 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
1020 + */
1021 +#ifndef _NETFILTER_MIME_H
1022 +#define _NETFILTER_MIME_H
1023 +
1024 +/* Only include these functions for kernel code. */
1025 +#ifdef __KERNEL__
1026 +
1027 +#include <linux/ctype.h>
1028 +
1029 +/*
1030 + * Given a buffer and length, advance to the next line and mark the current
1031 + * line.  If the current line is empty, *plinelen will be set to zero.  If
1032 + * not, it will be set to the actual line length (including CRLF).
1033 + *
1034 + * 'line' in this context means logical line (includes LWS continuations).
1035 + * Returns 1 on success, 0 on failure.
1036 + */
1037 +#ifdef NF_NEED_MIME_NEXTLINE
1038 +static int
1039 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1040 +{
1041 +    uint    off = *poff;
1042 +    uint    physlen = 0;
1043 +    int     is_first_line = 1;
1044 +
1045 +    if (off >= len)
1046 +    {
1047 +        return 0;
1048 +    }
1049 +
1050 +    do
1051 +    {
1052 +        while (p[off] != '\n')
1053 +        {
1054 +            if (len-off <= 1)
1055 +            {
1056 +                return 0;
1057 +            }
1058 +
1059 +            physlen++;
1060 +            off++;
1061 +        }
1062 +
1063 +        /* if we saw a crlf, physlen needs adjusted */
1064 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1065 +        {
1066 +            physlen--;
1067 +        }
1068 +
1069 +        /* advance past the newline */
1070 +        off++;
1071 +
1072 +        /* check for an empty line */
1073 +        if (physlen == 0)
1074 +        {
1075 +            break;
1076 +        }
1077 +
1078 +        /* check for colon on the first physical line */
1079 +        if (is_first_line)
1080 +        {
1081 +            is_first_line = 0;
1082 +            if (memchr(p+(*poff), ':', physlen) == NULL)
1083 +            {
1084 +                return 0;
1085 +            }
1086 +        }
1087 +    }
1088 +    while (p[off] == ' ' || p[off] == '\t');
1089 +
1090 +    *plineoff = *poff;
1091 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
1092 +    *poff = off;
1093 +
1094 +    return 1;
1095 +}
1096 +#endif /* NF_NEED_MIME_NEXTLINE */
1097 +
1098 +#endif /* __KERNEL__ */
1099 +
1100 +#endif /* _NETFILTER_MIME_H */
1101 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/net/tcp.h linux-2.6.5-rc3/include/net/tcp.h
1102 --- linux-2.6.5-rc3.org/include/net/tcp.h       2004-03-30 05:25:33.000000000 +0200
1103 +++ linux-2.6.5-rc3/include/net/tcp.h   2004-03-30 11:51:33.000000000 +0200
1104 @@ -162,6 +162,7 @@
1105  extern void tcp_bucket_unlock(struct sock *sk);
1106  extern int tcp_port_rover;
1107  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
1108 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
1109  
1110  /* These are AF independent. */
1111  static __inline__ int tcp_bhashfn(__u16 lport)
1112 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/include/net/udp.h linux-2.6.5-rc3/include/net/udp.h
1113 --- linux-2.6.5-rc3.org/include/net/udp.h       2004-03-30 05:27:01.000000000 +0200
1114 +++ linux-2.6.5-rc3/include/net/udp.h   2004-03-30 11:51:33.000000000 +0200
1115 @@ -74,6 +74,8 @@
1116  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
1117  extern int     udp_disconnect(struct sock *sk, int flags);
1118  
1119 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
1120 +
1121  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
1122  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
1123  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
1124 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/core/netfilter.c linux-2.6.5-rc3/net/core/netfilter.c
1125 --- linux-2.6.5-rc3.org/net/core/netfilter.c    2004-03-30 11:31:19.000000000 +0200
1126 +++ linux-2.6.5-rc3/net/core/netfilter.c        2004-03-30 11:51:26.000000000 +0200
1127 @@ -60,6 +60,10 @@
1128  } queue_handler[NPROTO];
1129  static rwlock_t queue_handler_lock = RW_LOCK_UNLOCKED;
1130  
1131 +/**
1132 + * nf_register_hook - Register with a netfilter hook
1133 + * @reg: Hook operations to be registered
1134 + */
1135  int nf_register_hook(struct nf_hook_ops *reg)
1136  {
1137         struct list_head *i;
1138 @@ -76,6 +80,10 @@
1139         return 0;
1140  }
1141  
1142 +/**
1143 + * nf_unregister_hook - Unregister from a netfilter hook
1144 + * @reg: hook operations to be unregistered
1145 + */
1146  void nf_unregister_hook(struct nf_hook_ops *reg)
1147  {
1148         spin_lock_bh(&nf_hook_lock);
1149 @@ -388,6 +396,18 @@
1150         return NF_ACCEPT;
1151  }
1152  
1153 +/**
1154 + * nf_register_queue_handler - Registere a queue handler with netfilter
1155 + * @pf: protocol family
1156 + * @outfn: function called by core to enqueue a packet
1157 + * @data: opaque parameter, passed through
1158 + *
1159 + * This function registers a queue handler with netfilter.  There can only
1160 + * be one queue handler for every protocol family.
1161 + *
1162 + * A queue handler _must_ reinject every packet via nf_reinject, no
1163 + * matter what.
1164 + */
1165  int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
1166  {      
1167         int ret;
1168 @@ -405,7 +425,12 @@
1169         return ret;
1170  }
1171  
1172 -/* The caller must flush their queue before this */
1173 +/**
1174 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
1175 + * @pf: protocol family
1176 + *
1177 + * The caller must flush their queue before unregistering
1178 + */
1179  int nf_unregister_queue_handler(int pf)
1180  {
1181         write_lock_bh(&queue_handler_lock);
1182 @@ -548,6 +573,15 @@
1183         return ret;
1184  }
1185  
1186 +/**
1187 + * nf_reinject - Reinject a packet from a queue handler
1188 + * @skb: the packet to be reinjected
1189 + * @info: info which was passed to the outfn() of the queue handler
1190 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
1191 + *
1192 + * This is the function called by a queue handler to reinject a
1193 + * packet.
1194 + */
1195  void nf_reinject(struct sk_buff *skb, struct nf_info *info,
1196                  unsigned int verdict)
1197  {
1198 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.5-rc3/net/ipv4/netfilter/Kconfig
1199 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/Kconfig      2004-03-30 11:31:20.000000000 +0200
1200 +++ linux-2.6.5-rc3/net/ipv4/netfilter/Kconfig  2004-03-30 11:53:01.000000000 +0200
1201 @@ -706,5 +706,149 @@
1202         depends on IP_NF_IPTABLES
1203           help
1204  
1205 +config IP_NF_CONNTRACK_MARK
1206 +       bool  'Connection mark tracking support'
1207 +
1208 +config IP_NF_TARGET_CONNMARK
1209 +       tristate  'CONNMARK target support'
1210 +       depends on IP_NF_MANGLE
1211 +
1212 +config IP_NF_MATCH_CONNMARK
1213 +       tristate  ' Connection mark match support'
1214 +       depends on IP_NF_IPTABLES
1215 +         help
1216 +
1217 +config IP_NF_TARGET_IPMARK
1218 +       tristate  'IPMARK target support'
1219 +       depends on IP_NF_MANGLE
1220 +         help
1221 +
1222 +config IP_NF_TARGET_ROUTE
1223 +       tristate  'ROUTE target support'
1224 +       depends on IP_NF_MANGLE
1225 +         help
1226 +
1227 +config IP_NF_TARGET_TARPIT
1228 +       tristate 'TARPIT target support'
1229 +       depends on IP_NF_FILTER
1230 +         help
1231 +
1232 +config IP_NF_TARGET_TCPLAG
1233 +       tristate  'TCPLAG target support'
1234 +       depends on IP_NF_IPTABLES
1235 +         help
1236 +
1237 +config IP_NF_TARGET_XOR
1238 +       tristate  'XOR target support'
1239 +       depends on IP_NF_MANGLE
1240 +         help
1241 +
1242 +config IP_NF_MATCH_ADDRTYPE
1243 +       tristate  'address type match support'
1244 +       depends on IP_NF_IPTABLES
1245 +         help
1246 +
1247 +config IP_NF_MATCH_CONDITION
1248 +       tristate  'condition match support'
1249 +       depends on IP_NF_IPTABLES
1250 +         help
1251 +
1252 +config IP_NF_NAT_CUSEEME
1253 +       tristate
1254 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1255 +       default IP_NF_NAT if IP_NF_CUSEEME=y
1256 +       default m if IP_NF_CUSEEME=m
1257 +
1258 +config IP_NF_CUSEEME
1259 +       tristate  'CuSeeMe protocol support'
1260 +       depends on IP_NF_CONNTRACK
1261 +         help
1262 +
1263 +config IP_NF_EGG
1264 +       tristate  'Eggdrop bot support'
1265 +       depends on IP_NF_CONNTRACK
1266 +         help
1267 +
1268 +config IP_NF_NAT_H323
1269 +       tristate
1270 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1271 +       default IP_NF_NAT if IP_NF_H323=y
1272 +       default m if IP_NF_H323=m
1273 +
1274 +config IP_NF_H323
1275 +       tristate  'H.323 (netmeeting) support'
1276 +       depends on IP_NF_CONNTRACK
1277 +         help
1278 +
1279 +config IP_NF_NAT_MMS
1280 +       tristate
1281 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1282 +       default IP_NF_NAT if IP_NF_MMS=y
1283 +       default m if IP_NF_MMS=m
1284 +
1285 +config IP_NF_MMS
1286 +       tristate  'MMS protocol support'
1287 +       depends on IP_NF_CONNTRACK
1288 +         help
1289 +
1290 +config IP_NF_MATCH_POLICY
1291 +       tristate "IPsec policy match support"
1292 +       depends on IP_NF_IPTABLES && XFRM
1293 +       help
1294 +         Policy matching allows you to match packets based on the
1295 +         IPsec policy that was used during decapsulation/will
1296 +         be used during encapsulation.
1297 +
1298 +         To compile it as a module, choose M here.  If unsure, say N.
1299 +         help
1300 +
1301 +config IP_NF_NAT_QUAKE3
1302 +       tristate
1303 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1304 +       default IP_NF_NAT if IP_NF_QUAKE3=y
1305 +       default m if IP_NF_QUAKE3=m
1306 +
1307 +config IP_NF_QUAKE3
1308 +       tristate "Quake3 protocol support"
1309 +       depends on IP_NF_CONNTRACK
1310 +         help
1311 +
1312 +config IP_NF_MATCH_RPC
1313 +       tristate  'RPC match support'
1314 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1315 +         help
1316 +
1317 +config IP_NF_RSH
1318 +       tristate  'RSH protocol support'
1319 +       depends on IP_NF_CONNTRACK
1320 +         help
1321 +
1322 +config IP_NF_NAT_RTSP
1323 +       tristate
1324 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1325 +       default IP_NF_NAT if IP_NF_RTSP=y
1326 +       default m if IP_NF_RTSP=m
1327 +
1328 +config IP_NF_RTSP
1329 +       tristate  ' RTSP protocol support'
1330 +       depends on IP_NF_CONNTRACK
1331 +         help
1332 +
1333 +config IP_NF_MATCH_STRING
1334 +       tristate  'String match support'
1335 +       depends on IP_NF_IPTABLES
1336 +         help
1337 +
1338 +config IP_NF_NAT_TALK
1339 +       tristate
1340 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1341 +       default IP_NF_NAT if IP_NF_TALK=y
1342 +       default m if IP_NF_TALK=m
1343 +
1344 +config IP_NF_TALK
1345 +       tristate  'talk protocol support'
1346 +       depends on IP_NF_CONNTRACK
1347 +         help
1348 +
1349  endmenu
1350  
1351 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.5-rc3/net/ipv4/netfilter/Makefile
1352 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/Makefile     2004-03-30 11:31:20.000000000 +0200
1353 +++ linux-2.6.5-rc3/net/ipv4/netfilter/Makefile 2004-03-30 11:53:01.000000000 +0200
1354 @@ -19,17 +19,56 @@
1355  # connection tracking
1356  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1357  
1358 +# talk protocol support
1359 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1360 +ifdef CONFIG_IP_NF_TALK
1361 +       export-objs += ip_conntrack_talk.o
1362 +endif
1363 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1364 +
1365
1366 +# H.323 support
1367 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1368 +ifdef CONFIG_IP_NF_H323
1369 +       export-objs += ip_conntrack_h323.o
1370 +endif
1371 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1372 +
1373 +
1374  # connection tracking helpers
1375 +
1376 +# rtsp protocol support
1377 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
1378 +ifdef CONFIG_IP_NF_NAT_RTSP
1379 +       export-objs += ip_conntrack_rtsp.o
1380 +endif
1381 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
1382 +
1383 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1384 +ifdef CONFIG_IP_NF_NAT_QUAKE3
1385 +       export-objs += ip_conntrack_quake3.o
1386 +endif
1387 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1388 +ifdef CONFIG_IP_NF_MMS
1389 +       export-objs += ip_conntrack_mms.o
1390 +endif
1391  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1392  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1393  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1394 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1395 +
1396 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
1397 +
1398  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1399  
1400  # NAT helpers 
1401 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
1402  obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
1403  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1404  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1405  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1406 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1407 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1408  
1409  # generic IP tables 
1410  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1411 @@ -41,6 +80,9 @@
1412  obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1413  
1414  # matches
1415 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1416 +export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
1417 +
1418  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1419  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1420  obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
1421 @@ -55,9 +97,11 @@
1422  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1423  
1424  obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1425 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
1426  
1427  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1428  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1429 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
1430  
1431  obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1432  
1433 @@ -89,12 +133,15 @@
1434  
1435  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1436  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1437 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
1438  obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1439  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1440  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1441 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
1442  obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1443  
1444  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1445 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
1446  
1447  # targets
1448  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
1449 @@ -102,14 +149,20 @@
1450  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
1451  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
1452  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
1453 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
1454 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
1455  obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
1456  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
1457  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
1458 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
1459  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
1460  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
1461  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1462  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1463  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1464 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
1465 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
1466 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
1467  obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1468  obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1469  obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1470 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_core.c
1471 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c  2004-03-30 11:31:19.000000000 +0200
1472 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_core.c      2004-03-30 11:51:26.000000000 +0200
1473 @@ -15,6 +15,8 @@
1474   * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
1475   *     - add usage/reference counts to ip_conntrack_expect
1476   *     - export ip_conntrack[_expect]_{find_get,put} functions
1477 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
1478 + *     - added DocBook-style comments for public API
1479   * */
1480  
1481  #include <linux/config.h>
1482 @@ -90,6 +92,10 @@
1483         return p;
1484  }
1485  
1486 +/**
1487 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
1488 + * @protocol: protocol number
1489 + */
1490  struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
1491  {
1492         struct ip_conntrack_protocol *p;
1493 @@ -113,6 +119,11 @@
1494  static int ip_conntrack_hash_rnd_initted;
1495  static unsigned int ip_conntrack_hash_rnd;
1496  
1497 +/**
1498 + * hash_conntrack - Calculate the position of an entry in the connection 
1499 + * tracking table.
1500 + * @tuple: conntrack tuple which we want to calculate the hash position
1501 + */
1502  static u_int32_t
1503  hash_conntrack(const struct ip_conntrack_tuple *tuple)
1504  {
1505 @@ -125,6 +136,19 @@
1506                              ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
1507  }
1508  
1509 +/**
1510 + * get_tuple - set all the fields of a tuple which is passed as parameter
1511 + * given a network buffer.
1512 + * @iph:pointer an IP header. 
1513 + * @skb:network buffer for which we want to generate the tuple
1514 + * @dataoff: FIXME: Deprecated?
1515 + * @tuple: tuple which will be generate. Used as return parameter.
1516 + * @protocol: structure which contains pointer to protocol specific functions.
1517 + *
1518 + * Note: This function doesn't allocate space for the tuple passed as 
1519 + * parameter. The function pkt_to_packet which set all the protocol specific
1520 + * fields of a given tuple.
1521 + */
1522  int
1523  get_tuple(const struct iphdr *iph,
1524           const struct sk_buff *skb,
1525 @@ -146,6 +170,15 @@
1526         return protocol->pkt_to_tuple(skb, dataoff, tuple);
1527  }
1528  
1529 +/**
1530 + * invert_tuple - Returns the inverse of a given tuple. It is used to 
1531 + * calculate the tuple which represents the other sense of the flow
1532 + * of a connection.
1533 + * @inverse: the inverted tuple. Use as return value.
1534 + * @orig: the original tuple which will be inverted.
1535 + * @protocol: a pointer to the protocol structure which contains all the
1536 + * specifical functions available for this tuple.
1537 + */
1538  static int
1539  invert_tuple(struct ip_conntrack_tuple *inverse,
1540              const struct ip_conntrack_tuple *orig,
1541 @@ -161,7 +194,15 @@
1542  
1543  /* ip_conntrack_expect helper functions */
1544  
1545 -/* Compare tuple parts depending on mask. */
1546 +/**
1547 + * expect_cmp - compare a tuple with a expectation depending on a mask
1548 + * @i: pointer to an expectation.
1549 + * @tuple: tuple which will be compared with the expectation tuple.
1550 + *
1551 + * Actually the tuple field of an expectation is compared with a tuple
1552 + * This function is used by LIST_FIND to find a expectation which match a te
1553 + * given tuple.
1554 + */
1555  static inline int expect_cmp(const struct ip_conntrack_expect *i,
1556                              const struct ip_conntrack_tuple *tuple)
1557  {
1558 @@ -169,6 +210,10 @@
1559         return ip_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask);
1560  }
1561  
1562 +/**
1563 + * destroy_expect - Release all the resources allocated by an expectation.
1564 + * @exp: pointer to the expectation which we want to release.
1565 + */
1566  static void
1567  destroy_expect(struct ip_conntrack_expect *exp)
1568  {
1569 @@ -179,7 +224,11 @@
1570         kfree(exp);
1571  }
1572  
1573 -
1574 +/**
1575 + * ip_conntrack_expect_put - it decrements the counter of use related 
1576 + * associated to an expectation and it calls destroy_expect.
1577 + * @exp: pointer to the expectation which we want to release.
1578 + */
1579  inline void ip_conntrack_expect_put(struct ip_conntrack_expect *exp)
1580  {
1581         IP_NF_ASSERT(exp);
1582 @@ -199,7 +248,14 @@
1583                          struct ip_conntrack_expect *, tuple);
1584  }
1585  
1586 -/* Find a expectation corresponding to a tuple. */
1587 +/**
1588 + * ip_conntrack_find_get - find conntrack according to tuple
1589 + * @tuple: conntrack tuple for which we search conntrack
1590 + * @ignored_conntrack: ignore this conntrack during search
1591 + *
1592 + * This function increments the reference count of the found
1593 + * conntrack (if any).
1594 + */
1595  struct ip_conntrack_expect *
1596  ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple)
1597  {
1598 @@ -382,7 +438,14 @@
1599         return h;
1600  }
1601  
1602 -/* Find a connection corresponding to a tuple. */
1603 +/**
1604 + * ip_conntrack_find_get - find conntrack according to tuple
1605 + * @tuple: conntrack tuple for which we search conntrack
1606 + * @ignored_conntrack: ignore this conntrack during search
1607 + *
1608 + * This function increments the reference count of the found
1609 + * conntrack (if any).
1610 + */
1611  struct ip_conntrack_tuple_hash *
1612  ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
1613                       const struct ip_conntrack *ignored_conntrack)
1614 @@ -410,7 +473,14 @@
1615         return ct;
1616  }
1617  
1618 -/* Return conntrack and conntrack_info given skb->nfct->master */
1619 +/**
1620 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
1621 + * @skb: skb for which we want to find conntrack and conntrack_info
1622 + * @ctinfo: pointer to ctinfo, used as return value
1623 + *
1624 + * This function resolves the respective conntrack and conntrack_info
1625 + * structures for the connection this packet (skb) is part of.
1626 + */
1627  struct ip_conntrack *
1628  ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
1629  {
1630 @@ -480,8 +550,14 @@
1631         return NF_DROP;
1632  }
1633  
1634 -/* Returns true if a connection correspondings to the tuple (required
1635 -   for NAT). */
1636 +/**
1637 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
1638 + * @tuple: tuple to be used for this test
1639 + * @ignored_conntrack: conntrack which is excluded from result
1640 + *
1641 + * This function is called by the NAT code in order to find out if
1642 + * a particular tuple is already in use by some connection.
1643 + */
1644  int
1645  ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
1646                          const struct ip_conntrack *ignored_conntrack)
1647 @@ -607,7 +683,13 @@
1648  {
1649         return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
1650  }
1651 -
1652 +/**
1653 + * ip_ct_find_helper - Find application helper according to tuple
1654 + * @tuple: tuple for which helper needs to be found
1655 + *
1656 + * This function is used to determine if any registered conntrack helper
1657 + * is to be used for the given tuple.
1658 + */
1659  struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
1660  {
1661         return LIST_FIND(&helpers, helper_cmp,
1662 @@ -717,6 +799,9 @@
1663                  __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1664                  conntrack->master = expected;
1665                  expected->sibling = conntrack;
1666 +#if CONFIG_IP_NF_CONNTRACK_MARK
1667 +               conntrack->mark = expected->expectant->mark;
1668 +#endif
1669                  LIST_DELETE(&ip_conntrack_expect_list, expected);
1670                  expected->expectant->expecting--;
1671                  nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1672 @@ -910,6 +995,14 @@
1673         return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
1674  }
1675  
1676 +/**
1677 + * ip_conntrack_unexpect_related - Unexpect a related connection
1678 + * @expect: expecattin to be removed
1679 + *
1680 + * This function removes an existing expectation, that has not yet been
1681 + * confirmed (i.e. expectation was issued, but expected connection didn't
1682 + * arrive yet)
1683 + */
1684  inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
1685  {
1686         WRITE_LOCK(&ip_conntrack_lock);
1687 @@ -927,7 +1020,20 @@
1688         WRITE_UNLOCK(&ip_conntrack_lock);
1689  }
1690  
1691 -/* Add a related connection. */
1692 +/**
1693 + * ip_conntrack_expect_related - Expect a related connection
1694 + * @related_to: master conntrack
1695 + * @expect: expectation with all values filled in
1696 + *
1697 + * This function is called by conntrack application helpers who
1698 + * have detected that the control (master) connection is just about
1699 + * to negotiate a related slave connection. 
1700 + *
1701 + * Note: This function allocates it's own struct ip_conntrack_expect,
1702 + * copying the values from the 'expect' parameter.  Thus, 'expect' can
1703 + * be allocated on the stack and does not need to be valid after this
1704 + * function returns.
1705 + */
1706  int ip_conntrack_expect_related(struct ip_conntrack *related_to,
1707                                 struct ip_conntrack_expect *expect)
1708  {
1709 @@ -1057,7 +1163,15 @@
1710         return ret;
1711  }
1712  
1713 -/* Change tuple in an existing expectation */
1714 +/**
1715 + * ip_conntrack_change_expect - Change tuple in existing expectation
1716 + * @expect: expectation which is to be changed
1717 + * @newtuple: new tuple for expect
1718 + *
1719 + * This function is mostly called by NAT application helpers, who want to
1720 + * change an expectation issued by their respective conntrack application
1721 + * helper counterpart.
1722 + */
1723  int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
1724                                struct ip_conntrack_tuple *newtuple)
1725  {
1726 @@ -1098,8 +1212,15 @@
1727         return ret;
1728  }
1729  
1730 -/* Alter reply tuple (maybe alter helper).  If it's already taken,
1731 -   return 0 and don't do alteration. */
1732 +/**
1733 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
1734 + * @conntrack: conntrack whose reply tuple we want to alter
1735 + * @newreply: designated reply tuple for this conntrack
1736 + *
1737 + * This function alters the reply tuple of a conntrack to the given
1738 + * newreply tuple.  If this newreply tuple is already taken, return 0
1739 + * and don't do alteration
1740 + */
1741  int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
1742                              const struct ip_conntrack_tuple *newreply)
1743  {
1744 @@ -1124,6 +1245,13 @@
1745         return 1;
1746  }
1747  
1748 +/**
1749 + * ip_conntrack_helper_register - Register a conntrack application helper
1750 + * @me: structure describing the helper
1751 + *
1752 + * This function is called by conntrack application helpers to register
1753 + * themselves with the conntrack core.
1754 + */
1755  int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
1756  {
1757         WRITE_LOCK(&ip_conntrack_lock);
1758 @@ -1145,6 +1273,13 @@
1759         return 0;
1760  }
1761  
1762 +/**
1763 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
1764 + * @me: structure describing the helper
1765 + *
1766 + * This function is called by conntrack application helpers to unregister
1767 + * themselvers from the conntrack core.
1768 + */
1769  void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
1770  {
1771         unsigned int i;
1772 @@ -1163,7 +1298,14 @@
1773         synchronize_net();
1774  }
1775  
1776 -/* Refresh conntrack for this many jiffies. */
1777 +/**
1778 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
1779 + * @ct: conntrack which we want to refresh
1780 + * @extra_jiffies: number of jiffies to add
1781 + *
1782 + * This function is called by protocol helpers and application helpers in
1783 + * order to change the expiration timer of a conntrack entry.
1784 + */
1785  void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
1786  {
1787         IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
1788 @@ -1182,7 +1324,16 @@
1789         WRITE_UNLOCK(&ip_conntrack_lock);
1790  }
1791  
1792 -/* Returns new sk_buff, or NULL */
1793 +
1794 +/**
1795 + * ip_ct_gather_frags - Gather fragments of a particular skb
1796 + * @skb: pointer to sk_buff of fragmented IP packet
1797 + *
1798 + * This code is just a wrapper around the defragmentation code in the core IPv4
1799 + * stack.  It also takes care of nonlinear skb's.
1800 + *
1801 + * Returns new sk_buff, or NULL
1802 + */
1803  struct sk_buff *
1804  ip_ct_gather_frags(struct sk_buff *skb)
1805  {
1806 @@ -1266,6 +1417,16 @@
1807         return h;
1808  }
1809  
1810 +/**
1811 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
1812 + * @kill: callback function selecting which entries to delete
1813 + * @data: opaque data pointer, becomes 2nd argument for kill function
1814 + *
1815 + * This function can be used to selectively delete elements of the conntrack
1816 + * hashtable.  The function iterates over the list of conntrack entries and
1817 + * calls the 'kill' function for every entry.  If the return value is true,
1818 + * the connection is deleted (death_by_timeout).
1819 + */
1820  void
1821  ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
1822                         void *data)
1823 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
1824 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c   1970-01-01 01:00:00.000000000 +0100
1825 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_egg.c       2004-03-30 11:51:02.000000000 +0200
1826 @@ -0,0 +1,237 @@
1827 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
1828 + * based on ip_conntrack_irc.c 
1829 + *
1830 + *      This module only supports the share userfile-send command,
1831 + *      used by eggdrops to share it's userfile.
1832 + *
1833 + *      There are no support for NAT at the moment.
1834 + *
1835 + *      This program is free software; you can redistribute it and/or
1836 + *      modify it under the terms of the GNU General Public License
1837 + *      as published by the Free Software Foundation; either version
1838 + *      2 of the License, or (at your option) any later version.
1839 + *
1840 + *     Module load syntax:
1841 + *     
1842 + *     please give the ports of all Eggdrops You have running
1843 + *      on your system, the default port is 3333.
1844 + *
1845 + *      2001-04-19: Security update. IP addresses are now compared
1846 + *                  to prevent unauthorized "related" access.
1847 + *
1848 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
1849 + *                 Port to netfilter 'newnat' API.
1850 + */
1851 +
1852 +#include <linux/module.h>
1853 +#include <linux/netfilter.h>
1854 +#include <linux/ip.h>
1855 +#include <net/checksum.h>
1856 +#include <net/tcp.h>
1857 +
1858 +#include <linux/netfilter_ipv4/lockhelp.h>
1859 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1860 +
1861 +#define MAX_PORTS 8
1862 +static int ports[MAX_PORTS];
1863 +static int ports_c = 0;
1864 +static unsigned int egg_timeout = 300;
1865 +
1866 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
1867 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
1868 +MODULE_LICENSE("GPL");
1869 +#ifdef MODULE_PARM
1870 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
1871 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
1872 +#endif
1873 +
1874 +DECLARE_LOCK(ip_egg_lock);
1875 +struct module *ip_conntrack_egg = THIS_MODULE;
1876 +
1877 +#if 0
1878 +#define DEBUGP printk
1879 +#else
1880 +#define DEBUGP(format, args...)
1881 +#endif
1882 +
1883 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
1884 +/* tries to get the ip_addr and port out of a eggdrop command
1885 +   return value: -1 on failure, 0 on success 
1886 +   data                pointer to first byte of DCC command data
1887 +   data_end    pointer to last byte of dcc command data
1888 +   ip          returns parsed ip of dcc command
1889 +   port                returns parsed port of dcc command */
1890 +{
1891 +       if (data > data_end)
1892 +               return -1;
1893 +       
1894 +       *ip = simple_strtoul(data, &data, 10);
1895 +
1896 +       /* skip blanks between ip and port */
1897 +       while (*data == ' ' && data < data_end)
1898 +               data++;
1899 +
1900 +       *port = simple_strtoul(data, &data, 10);
1901 +       return 0;
1902 +}
1903 +
1904 +
1905 +static int help(const struct iphdr *iph, size_t len,
1906 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
1907 +{
1908 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
1909 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
1910 +       char *data = (char *) tcph + tcph->doff * 4;
1911 +       char *data_limit;
1912 +       u_int32_t tcplen = len - iph->ihl * 4;
1913 +       u_int32_t datalen = tcplen - tcph->doff * 4;
1914 +       int dir = CTINFO2DIR(ctinfo);
1915 +       int bytes_scanned = 0;
1916 +       struct ip_conntrack_expect exp;
1917 +
1918 +       u_int32_t egg_ip;
1919 +       u_int16_t egg_port;
1920 +
1921 +       DEBUGP("entered\n");
1922 +
1923 +       /* If packet is coming from IRC server */
1924 +       if (dir != IP_CT_DIR_REPLY)
1925 +               return NF_ACCEPT;
1926 +
1927 +       /* Until there's been traffic both ways, don't look in packets. */
1928 +       if (ctinfo != IP_CT_ESTABLISHED
1929 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
1930 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
1931 +               return NF_ACCEPT;
1932 +       }
1933 +
1934 +       /* Not whole TCP header? */
1935 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
1936 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
1937 +               return NF_ACCEPT;
1938 +       }
1939 +
1940 +       /* Checksum invalid?  Ignore. */
1941 +       /* FIXME: Source route IP option packets --RR */
1942 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
1943 +                        csum_partial((char *) tcph, tcplen, 0))) {
1944 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
1945 +                       tcph, tcplen, NIPQUAD(iph->saddr),
1946 +                       NIPQUAD(iph->daddr));
1947 +               return NF_ACCEPT;
1948 +       }
1949 +
1950 +       data_limit = (char *) data + datalen;
1951 +       while (datalen > 5 && bytes_scanned < 128) {
1952 +               if (memcmp(data, "s us ", 5)) {
1953 +                       data++;
1954 +                       datalen--;
1955 +                       bytes_scanned++;
1956 +                       continue;
1957 +               }
1958 +
1959 +               data += 5;
1960 +
1961 +               DEBUGP("Userfile-share found in connection "
1962 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
1963 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
1964 +
1965 +               if (parse_command((char *) data, data_limit, &egg_ip,
1966 +                                 &egg_port)) {
1967 +                       DEBUGP("no data in userfile-share pkt\n");
1968 +                       return NF_ACCEPT;
1969 +               }
1970 +
1971 +               memset(&exp, 0, sizeof(exp));
1972 +
1973 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
1974 +                       if (net_ratelimit())
1975 +                               printk("Forged Eggdrop command from "
1976 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
1977 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
1978 +                                      HIPQUAD(egg_ip), egg_port);
1979 +                       return NF_ACCEPT;
1980 +               }
1981 +
1982 +               exp.tuple.src.ip = iph->daddr;
1983 +               exp.tuple.src.u.tcp.port = 0;
1984 +               exp.tuple.dst.ip = htonl(egg_ip);
1985 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
1986 +               exp.tuple.dst.protonum = IPPROTO_TCP;
1987 +
1988 +               exp.mask.dst.u.tcp.port = 0xffff;
1989 +               exp.mask.dst.protonum = 0xffff;
1990 +
1991 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
1992 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
1993 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
1994 +
1995 +               ip_conntrack_expect_related(ct, &exp);
1996 +               break;
1997 +       }
1998 +       return NF_ACCEPT;
1999 +}
2000 +
2001 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
2002 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
2003 +
2004 +static void deregister_helpers(void) {
2005 +       int i;
2006 +       
2007 +       for (i = 0; i < ports_c; i++) {
2008 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
2009 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
2010 +       }
2011 +}
2012 +
2013 +static int __init init(void)
2014 +{
2015 +       int i, ret;
2016 +       char *tmpname;
2017 +
2018 +       /* If no port given, default to standard eggdrop port */
2019 +       if (ports[0] == 0)
2020 +               ports[0] = 3333;
2021 +
2022 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2023 +               memset(&egg_helpers[i], 0,
2024 +                      sizeof(struct ip_conntrack_helper));
2025 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
2026 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
2027 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
2028 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
2029 +               egg_helpers[i].max_expected = 1;
2030 +               egg_helpers[i].timeout = egg_timeout;
2031 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2032 +               egg_helpers[i].me = THIS_MODULE;
2033 +               egg_helpers[i].help = help;
2034 +
2035 +               tmpname = &egg_names[i][0];
2036 +               if (ports[i] == 3333)
2037 +                       sprintf(tmpname, "eggdrop");
2038 +               else
2039 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
2040 +               egg_helpers[i].name = tmpname;
2041 +
2042 +               DEBUGP("port #%d: %d\n", i, ports[i]);
2043 +
2044 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
2045 +
2046 +               if (ret) {
2047 +                       printk("ip_conntrack_egg: ERROR registering helper "
2048 +                               "for port %d\n", ports[i]);
2049 +                       deregister_helpers();
2050 +                       return 1;
2051 +               }
2052 +               ports_c++;
2053 +       }
2054 +       return 0;
2055 +}
2056 +
2057 +static void __exit fini(void)
2058 +{
2059 +       deregister_helpers();
2060 +}
2061 +
2062 +module_init(init);
2063 +module_exit(fini);
2064 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
2065 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c  1970-01-01 01:00:00.000000000 +0100
2066 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_h323.c      2004-03-30 11:51:04.000000000 +0200
2067 @@ -0,0 +1,308 @@
2068 +/* 
2069 + * H.323 'brute force' extension for H.323 connection tracking. 
2070 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2071 + *
2072 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
2073 + * (http://www.coritel.it/projects/sofia/nat/)
2074 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
2075 + * the unregistered helpers to the conntrack entries.
2076 + */
2077 +
2078 +
2079 +#include <linux/module.h>
2080 +#include <linux/netfilter.h>
2081 +#include <linux/ip.h>
2082 +#include <net/checksum.h>
2083 +#include <net/tcp.h>
2084 +
2085 +#include <linux/netfilter_ipv4/lockhelp.h>
2086 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2087 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2088 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2089 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
2090 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
2091 +
2092 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
2093 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
2094 +MODULE_LICENSE("GPL");
2095 +
2096 +DECLARE_LOCK(ip_h323_lock);
2097 +struct module *ip_conntrack_h323 = THIS_MODULE;
2098 +
2099 +#if 0
2100 +#define DEBUGP printk
2101 +#else
2102 +#define DEBUGP(format, args...)
2103 +#endif
2104 +
2105 +/* FIXME: This should be in userspace.  Later. */
2106 +static int h245_help(const struct iphdr *iph, size_t len,
2107 +                    struct ip_conntrack *ct,
2108 +                    enum ip_conntrack_info ctinfo)
2109 +{
2110 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2111 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2112 +       unsigned char *data_limit;
2113 +       u_int32_t tcplen = len - iph->ihl * 4;
2114 +       u_int32_t datalen = tcplen - tcph->doff * 4;
2115 +       int dir = CTINFO2DIR(ctinfo);
2116 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2117 +       struct ip_conntrack_expect expect, *exp = &expect;
2118 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2119 +       u_int16_t data_port;
2120 +       u_int32_t data_ip;
2121 +       unsigned int i;
2122 +
2123 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2124 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
2125 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
2126 +
2127 +       /* Can't track connections formed before we registered */
2128 +       if (!info)
2129 +               return NF_ACCEPT;
2130 +               
2131 +       /* Until there's been traffic both ways, don't look in packets. */
2132 +       if (ctinfo != IP_CT_ESTABLISHED
2133 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2134 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
2135 +               return NF_ACCEPT;
2136 +       }
2137 +
2138 +       /* Not whole TCP header or too short packet? */
2139 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2140 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
2141 +               return NF_ACCEPT;
2142 +       }
2143 +
2144 +       /* Checksum invalid?  Ignore. */
2145 +       /* FIXME: Source route IP option packets --RR */
2146 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2147 +                             csum_partial((char *)tcph, tcplen, 0))) {
2148 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2149 +                      tcph, tcplen, NIPQUAD(iph->saddr),
2150 +                      NIPQUAD(iph->daddr));
2151 +               return NF_ACCEPT;
2152 +       }
2153 +
2154 +       data_limit = (unsigned char *) data + datalen;
2155 +       /* bytes: 0123   45
2156 +                 ipadrr port */
2157 +       for (i = 0; data < (data_limit - 5); data++, i++) {
2158 +               data_ip = *((u_int32_t *)data);
2159 +               if (data_ip == iph->saddr) {
2160 +                       data_port = *((u_int16_t *)(data + 4));
2161 +                       memset(&expect, 0, sizeof(expect));
2162 +                       /* update the H.225 info */
2163 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
2164 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2165 +                               NIPQUAD(iph->saddr), ntohs(data_port));
2166 +                       LOCK_BH(&ip_h323_lock);
2167 +                       info->is_h225 = H225_PORT + 1;
2168 +                       exp_info->port = data_port;
2169 +                       exp_info->dir = dir;
2170 +                       exp_info->offset = i;
2171 +
2172 +                       exp->seq = ntohl(tcph->seq) + i;
2173 +                   
2174 +                       exp->tuple = ((struct ip_conntrack_tuple)
2175 +                               { { ct->tuplehash[!dir].tuple.src.ip,
2176 +                                   { 0 } },
2177 +                                 { data_ip,
2178 +                                   { .tcp = { data_port } },
2179 +                                   IPPROTO_UDP }});
2180 +                       exp->mask = ((struct ip_conntrack_tuple)
2181 +                               { { 0xFFFFFFFF, { 0 } },
2182 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2183 +       
2184 +                       exp->expectfn = NULL;
2185 +                       
2186 +                       /* Ignore failure; should only happen with NAT */
2187 +                       ip_conntrack_expect_related(ct, exp);
2188 +
2189 +                       UNLOCK_BH(&ip_h323_lock);
2190 +               }
2191 +       }
2192 +
2193 +       return NF_ACCEPT;
2194 +
2195 +}
2196 +
2197 +/* H.245 helper is not registered! */
2198 +static struct ip_conntrack_helper h245 = 
2199 +       { { NULL, NULL },
2200 +          "H.245",                             /* name */
2201 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
2202 +          NULL,                                        /* module */
2203 +          8,                                   /* max_ expected */
2204 +          240,                                 /* timeout */
2205 +          { { 0, { 0 } },                      /* tuple */
2206 +            { 0, { 0 }, IPPROTO_TCP } },
2207 +          { { 0, { 0xFFFF } },                 /* mask */
2208 +            { 0, { 0 }, 0xFFFF } },
2209 +          h245_help                            /* helper */
2210 +       };
2211 +
2212 +static int h225_expect(struct ip_conntrack *ct)
2213 +{
2214 +       WRITE_LOCK(&ip_conntrack_lock);
2215 +       ct->helper = &h245;
2216 +       DEBUGP("h225_expect: helper for %p added\n", ct);
2217 +       WRITE_UNLOCK(&ip_conntrack_lock);
2218 +       
2219 +       return NF_ACCEPT;       /* unused */
2220 +}
2221 +
2222 +/* FIXME: This should be in userspace.  Later. */
2223 +static int h225_help(const struct iphdr *iph, size_t len,
2224 +                    struct ip_conntrack *ct,
2225 +                    enum ip_conntrack_info ctinfo)
2226 +{
2227 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2228 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2229 +       unsigned char *data_limit;
2230 +       u_int32_t tcplen = len - iph->ihl * 4;
2231 +       u_int32_t datalen = tcplen - tcph->doff * 4;
2232 +       int dir = CTINFO2DIR(ctinfo);
2233 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2234 +       struct ip_conntrack_expect expect, *exp = &expect;
2235 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2236 +       u_int16_t data_port;
2237 +       u_int32_t data_ip;
2238 +       unsigned int i;
2239 +       
2240 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2241 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
2242 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
2243 +
2244 +       /* Can't track connections formed before we registered */
2245 +       if (!info)
2246 +               return NF_ACCEPT;
2247 +
2248 +       /* Until there's been traffic both ways, don't look in packets. */
2249 +       if (ctinfo != IP_CT_ESTABLISHED
2250 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2251 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
2252 +               return NF_ACCEPT;
2253 +       }
2254 +
2255 +       /* Not whole TCP header or too short packet? */
2256 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2257 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
2258 +               return NF_ACCEPT;
2259 +       }
2260 +
2261 +       /* Checksum invalid?  Ignore. */
2262 +       /* FIXME: Source route IP option packets --RR */
2263 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2264 +                             csum_partial((char *)tcph, tcplen, 0))) {
2265 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2266 +                      tcph, tcplen, NIPQUAD(iph->saddr),
2267 +                      NIPQUAD(iph->daddr));
2268 +               return NF_ACCEPT;
2269 +       }
2270 +       
2271 +       data_limit = (unsigned char *) data + datalen;
2272 +       /* bytes: 0123   45
2273 +                 ipadrr port */
2274 +       for (i = 0; data < (data_limit - 5); data++, i++) {
2275 +               data_ip = *((u_int32_t *)data);
2276 +               if (data_ip == iph->saddr) {
2277 +                       data_port = *((u_int16_t *)(data + 4));
2278 +                       if (data_port == tcph->source) {
2279 +                               /* Signal address */
2280 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
2281 +                                       NIPQUAD(iph->saddr));
2282 +                               /* Update the H.225 info so that NAT can mangle the address/port
2283 +                                  even when we have no expected connection! */
2284 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2285 +                               LOCK_BH(&ip_h323_lock);
2286 +                               info->dir = dir;
2287 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
2288 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
2289 +                               UNLOCK_BH(&ip_h323_lock);
2290 +#endif
2291 +                       } else {
2292 +                               memset(&expect, 0, sizeof(expect));
2293 +
2294 +                               /* update the H.225 info */
2295 +                               LOCK_BH(&ip_h323_lock);
2296 +                               info->is_h225 = H225_PORT;
2297 +                               exp_info->port = data_port;
2298 +                               exp_info->dir = dir;
2299 +                               exp_info->offset = i;
2300 +
2301 +                               exp->seq = ntohl(tcph->seq) + i;
2302 +
2303 +                               exp->tuple = ((struct ip_conntrack_tuple)
2304 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
2305 +                                           { 0 } },
2306 +                                         { data_ip,
2307 +                                           { .tcp = { data_port } },
2308 +                                           IPPROTO_TCP }});
2309 +                               exp->mask = ((struct ip_conntrack_tuple)
2310 +                                       { { 0xFFFFFFFF, { 0 } },
2311 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2312 +       
2313 +                               exp->expectfn = h225_expect;
2314 +                               
2315 +                               /* Ignore failure */
2316 +                               ip_conntrack_expect_related(ct, exp);
2317 +
2318 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
2319 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2320 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
2321 +
2322 +                               UNLOCK_BH(&ip_h323_lock);
2323 +                       }  
2324 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2325 +               } else if (data_ip == iph->daddr) {
2326 +                       data_port = *((u_int16_t *)(data + 4));
2327 +                       if (data_port == tcph->dest) {
2328 +                               /* Signal address */
2329 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
2330 +                                       NIPQUAD(iph->daddr));
2331 +                               /* Update the H.225 info so that NAT can mangle the address/port
2332 +                                  even when we have no expected connection! */
2333 +                               LOCK_BH(&ip_h323_lock);
2334 +                               info->dir = dir;
2335 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
2336 +                               info->offset[IP_CT_DIR_REPLY] = i;
2337 +                               UNLOCK_BH(&ip_h323_lock);
2338 +                       }
2339 +#endif
2340 +               }
2341 +       }
2342 +
2343 +       return NF_ACCEPT;
2344 +
2345 +}
2346 +
2347 +static struct ip_conntrack_helper h225 = 
2348 +       { { NULL, NULL },
2349 +         "H.225",                                      /* name */
2350 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
2351 +         THIS_MODULE,                                  /* module */
2352 +         2,                                            /* max_expected */
2353 +         240,                                          /* timeout */
2354 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
2355 +           { 0, { 0 }, IPPROTO_TCP } },
2356 +         { { 0, { 0xFFFF } },                          /* mask */
2357 +           { 0, { 0 }, 0xFFFF } },
2358 +         h225_help                                     /* helper */
2359 +       };
2360 +
2361 +static int __init init(void)
2362 +{
2363 +       return ip_conntrack_helper_register(&h225);
2364 +}
2365 +
2366 +static void __exit fini(void)
2367 +{
2368 +       /* Unregister H.225 helper */   
2369 +       ip_conntrack_helper_unregister(&h225);
2370 +}
2371 +
2372 +EXPORT_SYMBOL(ip_h323_lock);
2373 +
2374 +module_init(init);
2375 +module_exit(fini);
2376 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
2377 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c   1970-01-01 01:00:00.000000000 +0100
2378 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_mms.c       2004-03-30 11:51:24.000000000 +0200
2379 @@ -0,0 +1,308 @@
2380 +/* MMS extension for IP connection tracking
2381 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2382 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
2383 + *
2384 + * ip_conntrack_mms.c v0.3 2002-09-22
2385 + *
2386 + *      This program is free software; you can redistribute it and/or
2387 + *      modify it under the terms of the GNU General Public License
2388 + *      as published by the Free Software Foundation; either version
2389 + *      2 of the License, or (at your option) any later version.
2390 + *
2391 + *      Module load syntax:
2392 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
2393 + *
2394 + *      Please give the ports of all MMS servers You wish to connect to.
2395 + *      If you don't specify ports, the default will be TCP port 1755.
2396 + *
2397 + *      More info on MMS protocol, firewalls and NAT:
2398 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
2399 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
2400 + *
2401 + *      The SDP project people are reverse-engineering MMS:
2402 + *      http://get.to/sdp
2403 + */
2404 +
2405 +#include <linux/config.h>
2406 +#include <linux/module.h>
2407 +#include <linux/netfilter.h>
2408 +#include <linux/ip.h>
2409 +#include <linux/ctype.h>
2410 +#include <net/checksum.h>
2411 +#include <net/tcp.h>
2412 +
2413 +#include <linux/netfilter_ipv4/lockhelp.h>
2414 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2415 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
2416 +
2417 +DECLARE_LOCK(ip_mms_lock);
2418 +struct module *ip_conntrack_mms = THIS_MODULE;
2419 +
2420 +#define MAX_PORTS 8
2421 +static int ports[MAX_PORTS];
2422 +static int ports_c;
2423 +#ifdef MODULE_PARM
2424 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2425 +#endif
2426 +
2427 +#if 0 
2428 +#define DEBUGP printk
2429 +#else
2430 +#define DEBUGP(format, args...)
2431 +#endif
2432 +
2433 +EXPORT_SYMBOL(ip_mms_lock);
2434 +
2435 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2436 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
2437 +MODULE_LICENSE("GPL");
2438 +
2439 +/* #define isdigit(c) (c >= '0' && c <= '9') */
2440 +
2441 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
2442 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
2443 +{
2444 +       int i;
2445 +       for (i = 0; i < unicode_size; ++i) {
2446 +               string[i] = (char)(unicode[i]);
2447 +       }
2448 +       string[unicode_size] = 0x00;
2449 +}
2450 +
2451 +__inline static int atoi(char *s) 
2452 +{
2453 +       int i=0;
2454 +       while (isdigit(*s)) {
2455 +               i = i*10 + *(s++) - '0';
2456 +       }
2457 +       return i;
2458 +}
2459 +
2460 +/* convert ip address string like "192.168.0.10" to unsigned int */
2461 +__inline static u_int32_t asciiiptoi(char *s)
2462 +{
2463 +       unsigned int i, j, k;
2464 +
2465 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
2466 +               i+=atoi(s);
2467 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
2468 +                       ;
2469 +       }
2470 +       i+=atoi(s);
2471 +       return ntohl(i);
2472 +}
2473 +
2474 +int parse_mms(const char *data, 
2475 +             const unsigned int datalen,
2476 +             u_int32_t *mms_ip,
2477 +             u_int16_t *mms_proto,
2478 +             u_int16_t *mms_port,
2479 +             char **mms_string_b,
2480 +             char **mms_string_e,
2481 +             char **mms_padding_e)
2482 +{
2483 +       int unicode_size, i;
2484 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
2485 +       char getlengthstring[28];
2486 +       
2487 +       for(unicode_size=0; 
2488 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2489 +           unicode_size++)
2490 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
2491 +                       return -1; /* out of bounds - incomplete packet */
2492 +       
2493 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2494 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2495 +       
2496 +       /* IP address ? */
2497 +       *mms_ip = asciiiptoi(tempstring+2);
2498 +       
2499 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2500 +               
2501 +       /* protocol ? */
2502 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
2503 +               *mms_proto = IPPROTO_TCP;
2504 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2505 +               *mms_proto = IPPROTO_UDP;
2506 +
2507 +       /* port ? */
2508 +       *mms_port = atoi(tempstring+7+i);
2509 +
2510 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
2511 +          unicode string, one to the end of the string, and one to the end 
2512 +          of the packet, since we must keep track of the number of bytes 
2513 +          between end of the unicode string and the end of packet (padding) */
2514 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2515 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2516 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2517 +       return 0;
2518 +}
2519 +
2520 +
2521 +/* FIXME: This should be in userspace.  Later. */
2522 +static int help(const struct iphdr *iph, size_t len,
2523 +               struct ip_conntrack *ct,
2524 +               enum ip_conntrack_info ctinfo)
2525 +{
2526 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2527 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2528 +       const char *data = (const char *)tcph + tcph->doff * 4;
2529 +       unsigned int tcplen = len - iph->ihl * 4;
2530 +       unsigned int datalen = tcplen - tcph->doff * 4;
2531 +       int dir = CTINFO2DIR(ctinfo);
2532 +       struct ip_conntrack_expect expect, *exp = &expect; 
2533 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2534 +       
2535 +       u_int32_t mms_ip;
2536 +       u_int16_t mms_proto;
2537 +       char mms_proto_string[8];
2538 +       u_int16_t mms_port;
2539 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
2540 +            
2541 +       /* Until there's been traffic both ways, don't look in packets. */
2542 +       if (ctinfo != IP_CT_ESTABLISHED
2543 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2544 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2545 +               return NF_ACCEPT;
2546 +       }
2547 +
2548 +       /* Not whole TCP header? */
2549 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2550 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2551 +               return NF_ACCEPT;
2552 +       }
2553 +
2554 +       /* Checksum invalid?  Ignore. */
2555 +       /* FIXME: Source route IP option packets --RR */
2556 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2557 +           csum_partial((char *)tcph, tcplen, 0))) {
2558 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2559 +                      tcph, tcplen, NIPQUAD(iph->saddr),
2560 +                      NIPQUAD(iph->daddr));
2561 +               return NF_ACCEPT;
2562 +       }
2563 +       
2564 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2565 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
2566 +          the client has already sent a packet to the server with the server's hostname 
2567 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
2568 +          server will break the connection if this doesn't correspond to its own host 
2569 +          header. The client can also connect to an IP address; if it's the server's IP
2570 +          address, it will not break the connection. When doing DNAT on a connection 
2571 +          where the client uses a server's IP address, the nat module should detect
2572 +          this and change this string accordingly to the DNATed address. This should
2573 +          probably be done by checking for an IP address, then storing it as a member
2574 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2575 +          */
2576 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
2577 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2578 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
2579 +                      (u8)*(data+36), (u8)*(data+37), 
2580 +                      (u8)*(data+38), (u8)*(data+39),
2581 +                      datalen);
2582 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2583 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
2584 +                       if(net_ratelimit())
2585 +                               /* FIXME: more verbose debugging ? */
2586 +                               printk(KERN_WARNING
2587 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
2588 +
2589 +               memset(&expect, 0, sizeof(expect));
2590 +
2591 +               sprintf(mms_proto_string, "(%u)", mms_proto);
2592 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2593 +                      mms_proto == IPPROTO_TCP ? "TCP"
2594 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2595 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2596 +                      NIPQUAD(mms_ip),
2597 +                      mms_port);
2598 +               
2599 +               /* it's possible that the client will just ask the server to tunnel
2600 +                  the stream over the same TCP session (from port 1755): there's 
2601 +                  shouldn't be a need to add an expectation in that case, but it
2602 +                  makes NAT packet mangling so much easier */
2603 +               LOCK_BH(&ip_mms_lock);
2604 +
2605 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2606 +               
2607 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2608 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
2609 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
2610 +               exp_mms_info->port    = mms_port;
2611 +               
2612 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2613 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2614 +               
2615 +               exp->tuple = ((struct ip_conntrack_tuple)
2616 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2617 +                             { mms_ip,
2618 +                               { .tcp = { (__u16) ntohs(mms_port) } },
2619 +                               mms_proto } }
2620 +                            );
2621 +               exp->mask  = ((struct ip_conntrack_tuple)
2622 +                            { { 0xFFFFFFFF, { 0 } },
2623 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2624 +               exp->expectfn = NULL;
2625 +               ip_conntrack_expect_related(ct, &expect);
2626 +               UNLOCK_BH(&ip_mms_lock);
2627 +       }
2628 +
2629 +       return NF_ACCEPT;
2630 +}
2631 +
2632 +static struct ip_conntrack_helper mms[MAX_PORTS];
2633 +static char mms_names[MAX_PORTS][10];
2634 +
2635 +/* Not __exit: called from init() */
2636 +static void fini(void)
2637 +{
2638 +       int i;
2639 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2640 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2641 +                               ports[i]);
2642 +               ip_conntrack_helper_unregister(&mms[i]);
2643 +       }
2644 +}
2645 +
2646 +static int __init init(void)
2647 +{
2648 +       int i, ret;
2649 +       char *tmpname;
2650 +
2651 +       if (ports[0] == 0)
2652 +               ports[0] = MMS_PORT;
2653 +
2654 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2655 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2656 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2657 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
2658 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
2659 +               mms[i].mask.dst.protonum = 0xFFFF;
2660 +               mms[i].max_expected = 1;
2661 +               mms[i].timeout = 0;
2662 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2663 +               mms[i].me = THIS_MODULE;
2664 +               mms[i].help = help;
2665 +
2666 +               tmpname = &mms_names[i][0];
2667 +               if (ports[i] == MMS_PORT)
2668 +                       sprintf(tmpname, "mms");
2669 +               else
2670 +                       sprintf(tmpname, "mms-%d", ports[i]);
2671 +               mms[i].name = tmpname;
2672 +
2673 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
2674 +                               ports[i]);
2675 +               ret = ip_conntrack_helper_register(&mms[i]);
2676 +
2677 +               if (ret) {
2678 +                       fini();
2679 +                       return ret;
2680 +               }
2681 +               ports_c++;
2682 +       }
2683 +       return 0;
2684 +}
2685 +
2686 +module_init(init);
2687 +module_exit(fini);
2688 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
2689 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c        1970-01-01 01:00:00.000000000 +0100
2690 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c    2004-03-30 11:51:52.000000000 +0200
2691 @@ -0,0 +1,156 @@
2692 +/* Quake3 extension for IP connection tracking
2693 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2694 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
2695 + *
2696 + * ip_conntrack_quake3.c v0.04 2002-08-31
2697 + *
2698 + *      This program is free software; you can redistribute it and/or
2699 + *      modify it under the terms of the GNU General Public License
2700 + *      as published by the Free Software Foundation; either version
2701 + *      2 of the License, or (at your option) any later version.
2702 + *
2703 + *      Module load syntax:
2704 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
2705 + *
2706 + *      please give the ports of all Quake3 master servers You wish to 
2707 + *      connect to. If you don't specify ports, the default will be UDP 
2708 + *      port 27950.
2709 + *
2710 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
2711 + */
2712 +
2713 +#include <linux/module.h>
2714 +#include <linux/ip.h>
2715 +#include <linux/udp.h>
2716 +
2717 +#include <linux/netfilter.h>
2718 +#include <linux/netfilter_ipv4/ip_tables.h>
2719 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2720 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
2721 +
2722 +struct module *ip_conntrack_quake3 = THIS_MODULE;
2723 +
2724 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2725 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
2726 +MODULE_LICENSE("GPL");
2727 +
2728 +#define MAX_PORTS 8
2729 +static int ports[MAX_PORTS];
2730 +static int ports_c = 0;
2731 +#ifdef MODULE_PARM
2732 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2733 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
2734 +#endif
2735 +
2736 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
2737 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
2738 +#if 0 
2739 +#define DEBUGP printk
2740 +#else
2741 +#define DEBUGP(format, args...)
2742 +#endif
2743 +
2744 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
2745 +
2746 +static int quake3_help(const struct iphdr *iph, size_t len,
2747 +       struct ip_conntrack *ct,
2748 +       enum ip_conntrack_info ctinfo)
2749 +{
2750 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
2751 +       int dir = CTINFO2DIR(ctinfo);
2752 +       struct ip_conntrack_expect exp;
2753 +       int i;
2754 +       
2755 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
2756 +       if (ctinfo != IP_CT_ESTABLISHED
2757 +           && ctinfo != IP_CT_IS_REPLY) {
2758 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
2759 +               return NF_ACCEPT;
2760 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
2761 +       
2762 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
2763 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
2764 +                   i+6 < ntohs(udph->len);
2765 +                   i+=7) {
2766 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
2767 +                              i, ntohs(udph->len),
2768 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
2769 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
2770 +
2771 +                       memset(&exp, 0, sizeof(exp));
2772 +
2773 +                       exp.tuple = ((struct ip_conntrack_tuple)
2774 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2775 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
2776 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
2777 +                                        IPPROTO_UDP } }
2778 +                                   );
2779 +                       exp.mask  = ((struct ip_conntrack_tuple)
2780 +                                    { { 0xFFFFFFFF, { 0 } },
2781 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
2782 +                       exp.expectfn = NULL;
2783 +
2784 +                       ip_conntrack_expect_related(ct, &exp);
2785 +               }
2786 +
2787 +       }
2788 +       
2789 +       return(NF_ACCEPT);
2790 +}
2791 +
2792 +static struct ip_conntrack_helper quake3[MAX_PORTS];
2793 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
2794 +
2795 +static void fini(void)
2796 +{
2797 +       int i;
2798 +
2799 +       for(i = 0 ; (i < ports_c); i++) {
2800 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
2801 +                                       ports[i]);
2802 +               ip_conntrack_helper_unregister(&quake3[i]);
2803 +       } 
2804 +}
2805 +
2806 +static int __init init(void)
2807 +{
2808 +       int i, ret;
2809 +       char *tmpname;
2810 +
2811 +       if(!ports[0])
2812 +               ports[0]=QUAKE3_MASTER_PORT;
2813 +
2814 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
2815 +               /* Create helper structure */
2816 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
2817 +
2818 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
2819 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
2820 +               quake3[i].mask.dst.protonum = 0xFFFF;
2821 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
2822 +               quake3[i].help = quake3_help;
2823 +               quake3[i].me = THIS_MODULE;
2824 +
2825 +               tmpname = &quake3_names[i][0];
2826 +               if (ports[i] == QUAKE3_MASTER_PORT)
2827 +                       sprintf(tmpname, "quake3");
2828 +               else
2829 +                       sprintf(tmpname, "quake3-%d", i);
2830 +               quake3[i].name = tmpname;
2831 +               
2832 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
2833 +                      ports[i]);
2834 +
2835 +               ret=ip_conntrack_helper_register(&quake3[i]);
2836 +               if(ret) {
2837 +                       fini();
2838 +                       return(ret);
2839 +               }
2840 +               ports_c++;
2841 +       }
2842 +
2843 +       return(0);
2844 +}
2845 +
2846 +module_init(init);
2847 +module_exit(fini);
2848 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
2849 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c       1970-01-01 01:00:00.000000000 +0100
2850 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c   2004-03-30 11:51:55.000000000 +0200
2851 @@ -0,0 +1,508 @@
2852 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
2853 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
2854 + *     - original rpc tracking module
2855 + *     - "recent" connection handling for kernel 2.3+ netfilter
2856 + *
2857 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
2858 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
2859 + *
2860 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
2861 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
2862 + *     - extended matching to support filtering on procedures
2863 + *
2864 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
2865 + *
2866 + *     This program is free software; you can redistribute it and/or
2867 + *     modify it under the terms of the GNU General Public License
2868 + *     as published by the Free Software Foundation; either version
2869 + *     2 of the License, or (at your option) any later version.
2870 + **
2871 + *     Module load syntax:
2872 + *     insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
2873 + *
2874 + *     Please give the ports of all RPC servers you wish to connect to.
2875 + *     If you don't specify ports, the default will be port 111.
2876 + **
2877 + *     Note to all:
2878 + *
2879 + *     RPCs should not be exposed to the internet - ask the Pentagon;
2880 + *
2881 + *       "The unidentified crackers pleaded guilty in July to charges
2882 + *        of juvenile delinquency stemming from a string of Pentagon
2883 + *        network intrusions in February.
2884 + *
2885 + *        The youths, going by the names TooShort and Makaveli, used
2886 + *        a common server security hole to break in, according to
2887 + *        Dane Jasper, owner of the California Internet service
2888 + *        provider, Sonic. They used the hole, known as the 'statd'
2889 + *        exploit, to attempt more than 800 break-ins, Jasper said."
2890 + *
2891 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
2892 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
2893 + **
2894 + */
2895 +
2896 +#include <linux/module.h>
2897 +#include <linux/netfilter.h>
2898 +#include <linux/ip.h>
2899 +#include <net/checksum.h>
2900 +#include <net/tcp.h>
2901 +
2902 +#include <asm/param.h>
2903 +#include <linux/sched.h>
2904 +#include <linux/timer.h>
2905 +#include <linux/stddef.h>
2906 +#include <linux/list.h>
2907 +
2908 +#include <linux/netfilter_ipv4/lockhelp.h>
2909 +#include <linux/netfilter_ipv4/ip_tables.h>
2910 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2911 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
2912 +
2913 +#define MAX_PORTS 8
2914 +static int ports[MAX_PORTS];
2915 +static int ports_n_c = 0;
2916 +
2917 +#ifdef MODULE_PARM
2918 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2919 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
2920 +#endif
2921 +
2922 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
2923 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
2924 +MODULE_LICENSE("GPL");
2925 +
2926 +#if 0
2927 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
2928 +                                       format, ## args)
2929 +#else
2930 +#define DEBUGP(format, args...)
2931 +#endif
2932 +
2933 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
2934 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
2935 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
2936 +#include <linux/netfilter_ipv4/listhelp.h>
2937 +
2938 +/* For future conections RPC, using client's cache bindings
2939 + * I'll use ip_conntrack_lock to lock these lists         */
2940 +
2941 +LIST_HEAD(request_p_list_tcp);
2942 +
2943 +
2944 +static void delete_request_p(unsigned long request_p_ul) 
2945 +{
2946 +       struct request_p *p = (void *)request_p_ul;
2947 +       
2948 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
2949 +       LIST_DELETE(&request_p_list_tcp, p);
2950 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
2951 +       kfree(p);
2952 +       return;
2953 +}
2954 +
2955 +
2956 +static void req_cl(struct request_p * r)
2957 +{
2958 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
2959 +       del_timer(&r->timeout);
2960 +       LIST_DELETE(&request_p_list_tcp, r);
2961 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
2962 +       kfree(r);
2963 +       return;
2964 +}
2965 +
2966 +
2967 +static void clean_request(struct list_head *list)
2968 +{
2969 +       struct list_head *first = list->prev;
2970 +       struct list_head *temp = list->next;
2971 +       struct list_head *aux;
2972 +
2973 +       if (list_empty(list))
2974 +               return;
2975 +
2976 +       while (first != temp) {
2977 +               aux = temp->next;
2978 +               req_cl((struct request_p *)temp);
2979 +               temp = aux;     
2980 +       }
2981 +       req_cl((struct request_p *)temp);
2982 +       return;
2983 +}
2984 +
2985 +
2986 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
2987 +                    u_int16_t port)
2988 +{
2989 +       struct request_p *req_p;
2990 +       
2991 +       /* Verifies if entry already exists */
2992 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
2993 +       req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
2994 +               struct request_p *, xid, ip, port);
2995 +
2996 +       if (req_p) {
2997 +               /* Refresh timeout */
2998 +               if (del_timer(&req_p->timeout)) {
2999 +                       req_p->timeout.expires = jiffies + EXP;
3000 +                       add_timer(&req_p->timeout);     
3001 +               } 
3002 +               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3003 +               return; 
3004 +
3005 +       }
3006 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3007 +       
3008 +       /* Allocate new request_p */
3009 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3010 +       if (!req_p) {
3011 +               DEBUGP("can't allocate request_p\n");
3012 +               return;                 
3013 +       }
3014 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
3015 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3016 +                       NULL }}); 
3017 +      
3018 +       /* Initialize timer */
3019 +       init_timer(&req_p->timeout);
3020 +       req_p->timeout.function = delete_request_p;
3021 +       add_timer(&req_p->timeout); 
3022 +
3023 +       /* Put in list */
3024 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3025 +       list_prepend(&request_p_list_tcp, req_p);
3026 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
3027 +       return; 
3028 +
3029 +}
3030 +
3031 +
3032 +static int check_rpc_packet(const u_int32_t *data,
3033 +                       int dir, struct ip_conntrack *ct,
3034 +                       struct list_head request_p_list)
3035 +{
3036 +       struct request_p *req_p;
3037 +       u_int32_t xid;
3038 +       struct ip_conntrack_expect expect, *exp = &expect;
3039 +
3040 +        /* Translstion's buffer for XDR */
3041 +        u_int16_t port_buf;
3042 +
3043 +
3044 +       /* Get XID */
3045 +       xid = *data;
3046 +
3047 +       /* This does sanity checking on RPC payloads,
3048 +        * and permits only the RPC "get port" (3)
3049 +        * in authorised procedures in client
3050 +        * communications with the portmapper.
3051 +        */
3052 +
3053 +       /* perform direction dependant RPC work */
3054 +       if (dir == IP_CT_DIR_ORIGINAL) {
3055 +
3056 +               data += 5;
3057 +
3058 +               /* Get RPC requestor */
3059 +               if (IXDR_GET_INT32(data) != 3) {
3060 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3061 +                       return NF_ACCEPT;
3062 +               }
3063 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3064 +
3065 +               data++;
3066 +
3067 +               /* Jump Credentials and Verfifier */
3068 +               data += IXDR_GET_INT32(data) + 2;
3069 +               data += IXDR_GET_INT32(data) + 2;
3070 +
3071 +               /* Get RPC procedure */
3072 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3073 +                       (unsigned int)IXDR_GET_INT32(data));
3074 +
3075 +               /* Get RPC protocol and store against client parameters */
3076 +               data = data + 2;
3077 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3078 +                               ct->tuplehash[dir].tuple.src.u.all);
3079 +
3080 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3081 +                       xid, IXDR_GET_INT32(data),
3082 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3083 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
3084 +
3085 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
3086 +                       (unsigned int)IXDR_GET_INT32(data));
3087 +
3088 +       } else {
3089 +
3090 +               /* Check for returning packet's stored counterpart */
3091 +               req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3092 +                                 struct request_p *, xid,
3093 +                                 ct->tuplehash[!dir].tuple.src.ip,
3094 +                                 ct->tuplehash[!dir].tuple.src.u.all);
3095 +
3096 +               /* Drop unexpected packets */
3097 +               if (!req_p) {
3098 +                       DEBUGP("packet is not expected. [skip]\n");
3099 +                       return NF_ACCEPT;
3100 +               }
3101 +
3102 +               /* Verifies if packet is really an RPC reply packet */
3103 +               data = data++;
3104 +               if (IXDR_GET_INT32(data) != 1) {
3105 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
3106 +                       return NF_ACCEPT;
3107 +               }
3108 +
3109 +               /* Is status accept? */
3110 +               data++;
3111 +               if (IXDR_GET_INT32(data)) {
3112 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
3113 +                       return NF_ACCEPT;
3114 +               }
3115 +
3116 +               /* Get Verifier length. Jump verifier */
3117 +               data++;
3118 +               data = data + IXDR_GET_INT32(data) + 2;
3119 +
3120 +               /* Is accpet status "success"? */
3121 +               if (IXDR_GET_INT32(data)) {
3122 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3123 +                       return NF_ACCEPT;
3124 +               }
3125 +
3126 +               /* Get server port number */      
3127 +               data++;
3128 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
3129 +
3130 +               /* If a packet has made it this far then it deserves an
3131 +                * expectation ...  if port == 0, then this service is 
3132 +                * not going to be registered.
3133 +                */
3134 +               if (port_buf) {
3135 +                       DEBUGP("port found: %u\n", port_buf);
3136 +
3137 +                       memset(&expect, 0, sizeof(expect));
3138 +
3139 +                       /* Watch out, Radioactive-Man! */
3140 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3141 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3142 +                       exp->mask.src.ip = 0xffffffff;
3143 +                       exp->mask.dst.ip = 0xffffffff;
3144 +
3145 +                       switch (req_p->proto) {
3146 +                               case IPPROTO_UDP:
3147 +                                       exp->tuple.src.u.udp.port = 0;
3148 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
3149 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
3150 +                                       exp->mask.src.u.udp.port = 0;
3151 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
3152 +                                       exp->mask.dst.protonum = 0xffff;
3153 +                                       break;
3154 +
3155 +                               case IPPROTO_TCP:
3156 +                                       exp->tuple.src.u.tcp.port = 0;
3157 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
3158 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
3159 +                                       exp->mask.src.u.tcp.port = 0;
3160 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
3161 +                                       exp->mask.dst.protonum = 0xffff;
3162 +                                       break;
3163 +                       }
3164 +                       exp->expectfn = NULL;
3165 +
3166 +                       ip_conntrack_expect_related(ct, &expect);
3167 +
3168 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3169 +                               NIPQUAD(exp->tuple.src.ip),
3170 +                               NIPQUAD(exp->tuple.dst.ip),
3171 +                               port_buf, req_p->proto);
3172 +
3173 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3174 +                               NIPQUAD(exp->mask.src.ip),
3175 +                               NIPQUAD(exp->mask.dst.ip),
3176 +                               exp->mask.dst.protonum);
3177 +
3178 +               }
3179 +
3180 +               req_cl(req_p);
3181 +
3182 +               DEBUGP("packet evaluated. [expect]\n");
3183 +               return NF_ACCEPT;
3184 +       }
3185 +
3186 +       return NF_ACCEPT;
3187 +
3188 +}
3189 +
3190 +
3191 +/* RPC TCP helper */
3192 +static int help(const struct iphdr *iph, size_t len,
3193 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3194 +{
3195 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3196 +       const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3197 +       size_t tcplen = len - iph->ihl * 4;
3198 +
3199 +       int dir = CTINFO2DIR(ctinfo);
3200 +       int crp_ret;
3201 +
3202 +
3203 +       DEBUGP("new packet to evaluate ..\n");
3204 +
3205 +       /* This works for packets like handshake packets, ignore */
3206 +       if (len == ((tcph->doff + iph->ihl) * 4)) {
3207 +               DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3208 +               return NF_ACCEPT;
3209 +       }
3210 +
3211 +       /* Until there's been traffic both ways, don't look in packets. */
3212 +       if (ctinfo != IP_CT_ESTABLISHED
3213 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3214 +               DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3215 +               DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3216 +               DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3217 +               return NF_ACCEPT;
3218 +       }
3219 +
3220 +       /* Not whole TCP header? */
3221 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3222 +               DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3223 +               DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3224 +               return NF_ACCEPT;
3225 +       }
3226 +
3227 +       /* FIXME: Source route IP option packets --RR */
3228 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3229 +                        csum_partial((char *) tcph, tcplen, 0))) {
3230 +               DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3231 +                    tcph, tcplen, NIPQUAD(iph->saddr),
3232 +                    NIPQUAD(iph->daddr));
3233 +               DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3234 +               DEBUGP("packet contains a bad checksum. [skip]\n");
3235 +               return NF_ACCEPT;
3236 +       }
3237 +
3238 +       /* perform direction dependant protocol work */
3239 +       if (dir == IP_CT_DIR_ORIGINAL) {
3240 +
3241 +               DEBUGP("packet is from the initiator. [cont]\n");
3242 +
3243 +               /* Tests if packet len is ok */
3244 +               if ((tcplen - (tcph->doff * 4)) != 60) {
3245 +                       DEBUGP("packet length is not correct. [skip]\n");
3246 +                       return NF_ACCEPT;
3247 +               }
3248 +
3249 +       } else {
3250 +
3251 +               DEBUGP("packet is from the receiver. [cont]\n");
3252 +
3253 +               /* Tests if packet len is ok */
3254 +               if ((tcplen - (tcph->doff * 4)) != 32) {
3255 +                       DEBUGP("packet length is not correct. [skip]\n");
3256 +                       return NF_ACCEPT;
3257 +               }
3258 +       }
3259 +
3260 +       /* Get to the data */
3261 +       data++;
3262 +
3263 +       /* Check the RPC data */
3264 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
3265 +
3266 +       return crp_ret;
3267 +
3268 +}
3269 +
3270 +
3271 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3272 +
3273 +static void fini(void);
3274 +
3275 +
3276 +static int __init init(void)
3277 +{
3278 +       int port, ret;
3279 +       static char name[10];
3280 +
3281 +
3282 +       /* If no port given, default to standard RPC port */
3283 +       if (ports[0] == 0)
3284 +               ports[0] = RPC_PORT;
3285 +
3286 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3287 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3288 +
3289 +                if (ports[port] == RPC_PORT)
3290 +                        sprintf(name, "rpc");
3291 +                else
3292 +                        sprintf(name, "rpc-%d", port);
3293 +
3294 +               rpc_helpers[port].name = name;
3295 +               rpc_helpers[port].me = THIS_MODULE;
3296 +               rpc_helpers[port].max_expected = 1;
3297 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3298 +               rpc_helpers[port].timeout = 0;
3299 +
3300 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
3301 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
3302 +
3303 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
3304 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3305 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3306 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3307 +
3308 +               rpc_helpers[port].help = help;
3309 +
3310 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
3311 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3312 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3313 +                       ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
3314 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
3315 +                       ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
3316 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3317 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
3318 +                       ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
3319 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
3320 +                       ntohs(rpc_helpers[port].mask.src.u.tcp.port));
3321 +
3322 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3323 +
3324 +               if (ret) {
3325 +                       printk("ERROR registering port %d\n",
3326 +                               ports[port]);
3327 +                       fini();
3328 +                       return -EBUSY;
3329 +               }
3330 +               ports_n_c++;
3331 +       }
3332 +       return 0;
3333 +}
3334 +
3335 +
3336 +/* This function is intentionally _NOT_ defined as __exit, because 
3337 + * it is needed by the init function */
3338 +static void fini(void)
3339 +{
3340 +       int port;
3341 +
3342 +       DEBUGP("cleaning request list\n");
3343 +       clean_request(&request_p_list_tcp);
3344 +
3345 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3346 +               DEBUGP("unregistering port %d\n", ports[port]);
3347 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
3348 +       }
3349 +}
3350 +
3351 +
3352 +module_init(init);
3353 +module_exit(fini);
3354 +
3355 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
3356 +EXPORT_SYMBOL(request_p_list_tcp);
3357 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
3358 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
3359 +
3360 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
3361 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c       1970-01-01 01:00:00.000000000 +0100
3362 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c   2004-03-30 11:51:55.000000000 +0200
3363 @@ -0,0 +1,503 @@
3364 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
3365 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3366 + *     - original rpc tracking module
3367 + *     - "recent" connection handling for kernel 2.3+ netfilter
3368 + *
3369 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3370 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3371 + *
3372 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3373 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
3374 + *     - extended matching to support filtering on procedures
3375 + *
3376 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
3377 + *
3378 + *     This program is free software; you can redistribute it and/or
3379 + *     modify it under the terms of the GNU General Public License
3380 + *     as published by the Free Software Foundation; either version
3381 + *     2 of the License, or (at your option) any later version.
3382 + **
3383 + *     Module load syntax:
3384 + *     insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
3385 + *
3386 + *     Please give the ports of all RPC servers you wish to connect to.
3387 + *     If you don't specify ports, the default will be port 111.
3388 + **
3389 + *     Note to all:
3390 + *
3391 + *     RPCs should not be exposed to the internet - ask the Pentagon;
3392 + *
3393 + *       "The unidentified crackers pleaded guilty in July to charges
3394 + *        of juvenile delinquency stemming from a string of Pentagon
3395 + *        network intrusions in February.
3396 + *
3397 + *        The youths, going by the names TooShort and Makaveli, used
3398 + *        a common server security hole to break in, according to
3399 + *        Dane Jasper, owner of the California Internet service
3400 + *        provider, Sonic. They used the hole, known as the 'statd'
3401 + *        exploit, to attempt more than 800 break-ins, Jasper said."
3402 + *
3403 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3404 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
3405 + **
3406 + */
3407 +
3408 +#include <linux/module.h>
3409 +#include <linux/netfilter.h>
3410 +#include <linux/ip.h>
3411 +#include <net/checksum.h>
3412 +#include <net/udp.h>
3413 +
3414 +#include <asm/param.h>
3415 +#include <linux/sched.h>
3416 +#include <linux/timer.h>
3417 +#include <linux/stddef.h>
3418 +#include <linux/list.h>
3419 +
3420 +#include <linux/netfilter_ipv4/lockhelp.h>
3421 +#include <linux/netfilter_ipv4/ip_tables.h>
3422 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3423 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3424 +
3425 +#define MAX_PORTS 8
3426 +static int ports[MAX_PORTS];
3427 +static int ports_n_c = 0;
3428 +
3429 +#ifdef MODULE_PARM
3430 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3431 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3432 +#endif
3433 +
3434 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3435 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
3436 +MODULE_LICENSE("GPL");
3437 +
3438 +#if 0
3439 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
3440 +                                       format, ## args)
3441 +#else
3442 +#define DEBUGP(format, args...)
3443 +#endif
3444 +
3445 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
3446 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
3447 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
3448 +#include <linux/netfilter_ipv4/listhelp.h>
3449 +
3450 +/* For future conections RPC, using client's cache bindings
3451 + * I'll use ip_conntrack_lock to lock these lists           */
3452 +
3453 +LIST_HEAD(request_p_list_udp);
3454 +
3455 +
3456 +static void delete_request_p(unsigned long request_p_ul)
3457 +{
3458 +       struct request_p *p = (void *)request_p_ul;
3459 +       
3460 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3461 +       LIST_DELETE(&request_p_list_udp, p);
3462 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
3463 +       kfree(p);
3464 +       return;
3465 +}
3466 +
3467 +
3468 +static void req_cl(struct request_p * r)
3469 +{
3470 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3471 +       del_timer(&r->timeout);
3472 +       LIST_DELETE(&request_p_list_udp, r);
3473 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
3474 +       kfree(r);
3475 +       return;
3476 +}
3477 +
3478 +
3479 +static void clean_request(struct list_head *list)
3480 +{
3481 +       struct list_head *first = list->prev;
3482 +       struct list_head *temp = list->next;
3483 +       struct list_head *aux;
3484 +
3485 +       if (list_empty(list))
3486 +               return;
3487 +
3488 +       while (first != temp) {
3489 +               aux = temp->next;
3490 +               req_cl((struct request_p *)temp);
3491 +               temp = aux;     
3492 +       }
3493 +       req_cl((struct request_p *)temp);
3494 +       return;
3495 +}
3496 +
3497 +
3498 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3499 +                    u_int16_t port)
3500 +{
3501 +       struct request_p *req_p;
3502 +        
3503 +       /* Verifies if entry already exists */
3504 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3505 +       req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3506 +               struct request_p *, xid, ip, port);
3507 +
3508 +       if (req_p) {
3509 +               /* Refresh timeout */
3510 +               if (del_timer(&req_p->timeout)) {
3511 +                       req_p->timeout.expires = jiffies + EXP;
3512 +                       add_timer(&req_p->timeout);     
3513 +               } 
3514 +               WRITE_UNLOCK(&ipct_rpc_udp_lock);
3515 +               return; 
3516 +
3517 +       }
3518 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
3519 +       
3520 +       /* Allocate new request_p */
3521 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3522 +       if (!req_p) {
3523 +               DEBUGP("can't allocate request_p\n");
3524 +               return;                 
3525 +       }
3526 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
3527 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3528 +                       NULL }}); 
3529 +      
3530 +       /* Initialize timer */
3531 +       init_timer(&req_p->timeout);
3532 +       req_p->timeout.function = delete_request_p;
3533 +       add_timer(&req_p->timeout); 
3534 +
3535 +       /* Put in list */
3536 +       WRITE_LOCK(&ipct_rpc_udp_lock);
3537 +       list_prepend(&request_p_list_udp, req_p);
3538 +       WRITE_UNLOCK(&ipct_rpc_udp_lock); 
3539 +       return; 
3540 +
3541 +}
3542 +
3543 +
3544 +static int check_rpc_packet(const u_int32_t *data,
3545 +                       int dir, struct ip_conntrack *ct,
3546 +                       struct list_head request_p_list)
3547 +{
3548 +       struct request_p *req_p;
3549 +       u_int32_t xid;
3550 +       struct ip_conntrack_expect expect, *exp = &expect;
3551 +
3552 +       /* Translstion's buffer for XDR */
3553 +       u_int16_t port_buf;
3554 +
3555 +
3556 +       /* Get XID */
3557 +       xid = *data;
3558 +
3559 +       /* This does sanity checking on RPC payloads,
3560 +        * and permits only the RPC "get port" (3)
3561 +        * in authorised procedures in client
3562 +        * communications with the portmapper.
3563 +        */
3564 +
3565 +       /* perform direction dependant RPC work */
3566 +       if (dir == IP_CT_DIR_ORIGINAL) {
3567 +
3568 +               data += 5;
3569 +
3570 +               /* Get RPC requestor */
3571 +               if (IXDR_GET_INT32(data) != 3) {
3572 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3573 +                       return NF_ACCEPT;
3574 +               }
3575 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3576 +
3577 +               data++;
3578 +
3579 +               /* Jump Credentials and Verfifier */
3580 +               data = data + IXDR_GET_INT32(data) + 2;
3581 +               data = data + IXDR_GET_INT32(data) + 2;
3582 +
3583 +               /* Get RPC procedure */
3584 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3585 +                       (unsigned int)IXDR_GET_INT32(data));
3586 +
3587 +               /* Get RPC protocol and store against client parameters */
3588 +               data = data + 2;
3589 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3590 +                               ct->tuplehash[dir].tuple.src.u.all);
3591 +
3592 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3593 +                       xid, IXDR_GET_INT32(data),
3594 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3595 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
3596 +
3597 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
3598 +                       (unsigned int)IXDR_GET_INT32(data));
3599 +
3600 +       } else {
3601 +
3602 +               /* Check for returning packet's stored counterpart */
3603 +               req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
3604 +                                 struct request_p *, xid,
3605 +                                 ct->tuplehash[!dir].tuple.src.ip,
3606 +                                 ct->tuplehash[!dir].tuple.src.u.all);
3607 +
3608 +               /* Drop unexpected packets */
3609 +               if (!req_p) {
3610 +                       DEBUGP("packet is not expected. [skip]\n");
3611 +                       return NF_ACCEPT;
3612 +               }
3613 +
3614 +               /* Verifies if packet is really an RPC reply packet */
3615 +               data = data++;
3616 +               if (IXDR_GET_INT32(data) != 1) {
3617 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
3618 +                       return NF_ACCEPT;
3619 +               }
3620 +
3621 +               /* Is status accept? */
3622 +               data++;
3623 +               if (IXDR_GET_INT32(data)) {
3624 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
3625 +                       return NF_ACCEPT;
3626 +               }
3627 +
3628 +               /* Get Verifier length. Jump verifier */
3629 +               data++;
3630 +               data = data + IXDR_GET_INT32(data) + 2;
3631 +
3632 +               /* Is accpet status "success"? */
3633 +               if (IXDR_GET_INT32(data)) {
3634 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3635 +                       return NF_ACCEPT;
3636 +               }
3637 +
3638 +               /* Get server port number */      
3639 +               data++;
3640 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
3641 +
3642 +               /* If a packet has made it this far then it deserves an
3643 +                * expectation ...  if port == 0, then this service is 
3644 +                * not going to be registered.
3645 +                */
3646 +               if (port_buf) {
3647 +                       DEBUGP("port found: %u\n", port_buf);
3648 +
3649 +                       memset(&expect, 0, sizeof(expect));
3650 +
3651 +                       /* Watch out, Radioactive-Man! */
3652 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3653 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3654 +                       exp->mask.src.ip = 0xffffffff;
3655 +                       exp->mask.dst.ip = 0xffffffff;
3656 +
3657 +                       switch (req_p->proto) {
3658 +                               case IPPROTO_UDP:
3659 +                                       exp->tuple.src.u.udp.port = 0;
3660 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
3661 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
3662 +                                       exp->mask.src.u.udp.port = 0;
3663 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
3664 +                                       exp->mask.dst.protonum = 0xffff;
3665 +                                       break;
3666 +
3667 +                               case IPPROTO_TCP:
3668 +                                       exp->tuple.src.u.tcp.port = 0;
3669 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
3670 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
3671 +                                       exp->mask.src.u.tcp.port = 0;
3672 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
3673 +                                       exp->mask.dst.protonum = 0xffff;
3674 +                                       break;
3675 +                       }
3676 +                       exp->expectfn = NULL;
3677 +
3678 +                       ip_conntrack_expect_related(ct, &expect);
3679 +
3680 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3681 +                               NIPQUAD(exp->tuple.src.ip),
3682 +                               NIPQUAD(exp->tuple.dst.ip),
3683 +                               port_buf, req_p->proto);
3684 +
3685 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3686 +                               NIPQUAD(exp->mask.src.ip),
3687 +                               NIPQUAD(exp->mask.dst.ip),
3688 +                               exp->mask.dst.protonum);
3689 +
3690 +               }
3691 +
3692 +               req_cl(req_p);
3693 +
3694 +               DEBUGP("packet evaluated. [expect]\n");
3695 +               return NF_ACCEPT;
3696 +       }
3697 +
3698 +       return NF_ACCEPT;
3699 +
3700 +}
3701 +
3702 +
3703 +/* RPC UDP helper */
3704 +static int help(const struct iphdr *iph, size_t len,
3705 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3706 +{
3707 +       struct udphdr *udph = (void *) iph + iph->ihl * 4;
3708 +       const u_int32_t *data = (const u_int32_t *)udph + 2;
3709 +       size_t udplen = len - iph->ihl * 4;
3710 +       int dir = CTINFO2DIR(ctinfo);
3711 +       int crp_ret;
3712 +
3713 +       /* Checksum */
3714 +       const u_int16_t *chsm = (const u_int16_t *)udph + 3;
3715 +
3716 +
3717 +       DEBUGP("new packet to evaluate ..\n");
3718 +
3719 +       /* Not whole UDP header? */
3720 +       if (udplen < sizeof(struct udphdr)) {
3721 +               DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
3722 +               DEBUGP("packet does not contain a complete UDP header. [skip]\n");
3723 +               return NF_ACCEPT;
3724 +       }
3725 +
3726 +       /* FIXME: Source route IP option packets --RR */
3727 +       if (*chsm) {
3728 +               if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
3729 +                   csum_partial((char *)udph, udplen, 0))) {
3730 +                       DEBUGP("[note: failure to get past this error may indicate source routing]\n");
3731 +                       DEBUGP("packet contains a bad checksum. [skip]\n");
3732 +                       return NF_ACCEPT;
3733 +                  } 
3734 +       }
3735 +
3736 +       /* perform direction dependant protocol work */
3737 +       if (dir == IP_CT_DIR_ORIGINAL) {
3738 +
3739 +               DEBUGP("packet is from the initiator. [cont]\n");
3740 +
3741 +               /* Tests if packet len is ok */
3742 +               if ((udplen - sizeof(struct udphdr)) != 56) {
3743 +                       DEBUGP("packet length is not correct. [skip]\n");
3744 +                       return NF_ACCEPT;
3745 +               }
3746 +
3747 +       } else {
3748 +
3749 +               DEBUGP("packet is from the receiver. [cont]\n");
3750 +
3751 +               /* Until there's been traffic both ways, don't look in packets. */
3752 +               if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3753 +                       DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3754 +                       DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3755 +                       DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3756 +                       return NF_ACCEPT;
3757 +               }
3758 +
3759 +               /* Tests if packet len is ok */
3760 +                       if ((udplen - sizeof(struct udphdr)) != 28) {
3761 +                       DEBUGP("packet length is not correct. [skip]\n");
3762 +                       return NF_ACCEPT;
3763 +               }
3764 +
3765 +       }
3766 +
3767 +       /* Get to the data */
3768 +       /* udp *data == *correct */
3769 +
3770 +       /* Check the RPC data */
3771 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
3772 +
3773 +       return crp_ret;
3774 +
3775 +}
3776 +
3777 +
3778 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
3779 +
3780 +static void fini(void);
3781 +
3782 +
3783 +static int __init init(void)
3784 +{
3785 +       int port, ret;
3786 +       static char name[10];
3787 +
3788 +
3789 +       /* If no port given, default to standard RPC port */
3790 +       if (ports[0] == 0)
3791 +               ports[0] = RPC_PORT;
3792 +
3793 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
3794 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
3795 +
3796 +                if (ports[port] == RPC_PORT)
3797 +                        sprintf(name, "rpc");
3798 +                else
3799 +                        sprintf(name, "rpc-%d", port);
3800 +
3801 +               rpc_helpers[port].name = name;
3802 +               rpc_helpers[port].me = THIS_MODULE;
3803 +               rpc_helpers[port].max_expected = 1;
3804 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3805 +               rpc_helpers[port].timeout = 0;
3806 +
3807 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
3808 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
3809 +
3810 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
3811 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
3812 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
3813 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
3814 +
3815 +               rpc_helpers[port].help = help;
3816 +
3817 +               DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
3818 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3819 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
3820 +                       ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
3821 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
3822 +                       ntohs(rpc_helpers[port].tuple.src.u.udp.port));
3823 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3824 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
3825 +                       ntohs(rpc_helpers[port].mask.dst.u.udp.port),
3826 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
3827 +                       ntohs(rpc_helpers[port].mask.src.u.udp.port));
3828 +
3829 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
3830 +
3831 +               if (ret) {
3832 +                       printk("ERROR registering port %d\n",
3833 +                               ports[port]);
3834 +                       fini();
3835 +                       return -EBUSY;
3836 +               }
3837 +               ports_n_c++;
3838 +       }
3839 +       return 0;
3840 +}
3841 +
3842 +
3843 +/* This function is intentionally _NOT_ defined as __exit, because 
3844 + * it is needed by the init function */
3845 +static void fini(void)
3846 +{
3847 +       int port;
3848 +
3849 +       DEBUGP("cleaning request list\n");
3850 +       clean_request(&request_p_list_udp);
3851 +
3852 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
3853 +               DEBUGP("unregistering port %d\n", ports[port]);
3854 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
3855 +       }
3856 +}
3857 +
3858 +
3859 +module_init(init);
3860 +module_exit(fini);
3861 +
3862 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
3863 +EXPORT_SYMBOL(request_p_list_udp);
3864 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
3865 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
3866 +
3867 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
3868 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c   1970-01-01 01:00:00.000000000 +0100
3869 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c       2004-03-30 11:51:56.000000000 +0200
3870 @@ -0,0 +1,331 @@
3871 +/* RSH extension for IP connection tracking, Version 1.0
3872 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3873 + * based on HW's ip_conntrack_irc.c    
3874 + *
3875 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
3876 + *
3877 + *      This program is free software; you can redistribute it and/or
3878 + *      modify it under the terms of the GNU General Public License
3879 + *      as published by the Free Software Foundation; either version
3880 + *      2 of the License, or (at your option) any later version.
3881 + **
3882 + *     Module load syntax:
3883 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
3884 + *     
3885 + *     please give the ports of all RSH servers You wish to connect to.
3886 + *     If You don't specify ports, the default will be port 514
3887 + **
3888 + *      Note to all:
3889 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
3890 + *        unfortunately I babysit some sysadmins that won't migrate
3891 + *       their legacy crap, in our second tier.
3892 + */
3893 +
3894 +
3895 +/*
3896 + *  Some docco ripped from the net to teach me all there is to know about
3897 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
3898 + *  this module).
3899 + *
3900 + *  I have no idea what "unix rshd man pages" these guys have .. but that
3901 + *  is some pretty detailed docco!
3902 + **
3903 + *
3904 + *  4. Of the rsh protocol.
3905 + *  -----------------------
3906 + * 
3907 + *   The rshd listens on TCP port #514. The following info is from the unix
3908 + *   rshd man pages :
3909 + * 
3910 + *   "Service Request Protocol
3911 + * 
3912 + *    When the rshd daemon receives a service request, it initiates the
3913 + *    following protocol:
3914 + * 
3915 + *     1. The rshd daemon checks the source port number for the request.
3916 + *        If the port number is not in the range 0 through 1023, the rshd daemon
3917 + *        terminates the connection.
3918 + * 
3919 + *     2. The rshd daemon reads characters from the socket up to a null byte.
3920 + *        The string read is interpreted as an ASCII number (base 10). If this
3921 + *        number is nonzero, the rshd daemon interprets it as the port number
3922 + *        of a secondary stream to be used as standard error. A second connection
3923 + *        is created to the specified port on the client host. The source port
3924 + *        on the local host is in the range 0 through 1023.
3925 + * 
3926 + *     3. The rshd daemon uses the source address of the initial connection
3927 + *        request to determine the name of the client host. If the name cannot
3928 + *        be determined, the rshd daemon uses the dotted decimal representation
3929 + *        of the client host's address.
3930 + * 
3931 + *     4. The rshd daemon retrieves the following information from the initial
3932 + *        socket:
3933 + * 
3934 + *         * A null-terminated string of at most 16 bytes interpreted as
3935 + *           the user name of the user on the client host.
3936 + * 
3937 + *         * A null-terminated string of at most 16 bytes interpreted as
3938 + *           the user name to be used on the local server host.
3939 + * 
3940 + *         * Another null-terminated string interpreted as a command line
3941 + *           to be passed to a shell on the local server host.
3942 + * 
3943 + *     5. The rshd daemon attempts to validate the user using the following steps:
3944 + * 
3945 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
3946 + *            file and tries to switch to the home directory (using the chdir
3947 + *            subroutine). If either the lookup or the directory change fails,
3948 + *            the rshd daemon terminates the connection.
3949 + * 
3950 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
3951 + *            the /etc/hosts.equiv file to see if the name of the client
3952 + *            workstation is listed. If the client workstation is listed as an
3953 + *            equivalent host, the rshd daemon validates the user.
3954 + * 
3955 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
3956 + *            authenticate the user by checking the .rhosts file.
3957 + * 
3958 + *         d. If either the $HOME/.rhosts authentication fails or the
3959 + *            client host is not an equivalent host, the rshd daemon
3960 + *            terminates the connection.
3961 + * 
3962 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
3963 + *        on the initial connection and passes the command line to the user's
3964 + *        local login shell. The shell then inherits the network connections
3965 + *        established by the rshd daemon."
3966 + * 
3967 + */
3968 +
3969 +
3970 +#include <linux/module.h>
3971 +#include <linux/netfilter.h>
3972 +#include <linux/ip.h>
3973 +#include <net/checksum.h>
3974 +#include <net/tcp.h>
3975 +
3976 +#include <linux/netfilter_ipv4/lockhelp.h>
3977 +#include <linux/netfilter_ipv4/ip_tables.h>
3978 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3979 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
3980 +
3981 +#define MAX_PORTS 8
3982 +static int ports[MAX_PORTS];
3983 +static int ports_n_c = 0;
3984 +
3985 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
3986 +MODULE_DESCRIPTION("RSH connection tracking module");
3987 +MODULE_LICENSE("GPL");
3988 +#ifdef MODULE_PARM
3989 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3990 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
3991 +#endif
3992 +
3993 +DECLARE_LOCK(ip_rsh_lock);
3994 +struct module *ip_conntrack_rsh = THIS_MODULE;
3995 +
3996 +#if 0
3997 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
3998 +                                       format, ## args)
3999 +#else
4000 +#define DEBUGP(format, args...)
4001 +#endif
4002 +
4003 +
4004 +
4005 +/* FIXME: This should be in userspace.  Later. */
4006 +static int help(const struct iphdr *iph, size_t len,
4007 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4008 +{
4009 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4010 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4011 +       const char *data = (const char *) tcph + tcph->doff * 4;
4012 +       u_int32_t tcplen = len - iph->ihl * 4;
4013 +       int dir = CTINFO2DIR(ctinfo);
4014 +        struct ip_conntrack_expect expect, *exp = &expect;
4015 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4016 +       u_int16_t port;
4017 +       int maxoctet;
4018 +
4019 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
4020 +        *  original array size used in rshd/glibc) -- is there a
4021 +        *  vulnerability in rshd.c in the looped port *= 10?
4022 +        */
4023 +
4024 +
4025 +       DEBUGP("entered\n");
4026 +
4027 +       /* bail if packet is not from RSH client */
4028 +       if (dir == IP_CT_DIR_REPLY)
4029 +               return NF_ACCEPT;
4030 +
4031 +       /* Until there's been traffic both ways, don't look in packets. */
4032 +       if (ctinfo != IP_CT_ESTABLISHED
4033 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4034 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
4035 +               return NF_ACCEPT;
4036 +       }
4037 +
4038 +       /* Not whole TCP header? */
4039 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4040 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4041 +               return NF_ACCEPT;
4042 +       }
4043 +
4044 +       /* Checksum invalid?  Ignore. */
4045 +       /* FIXME: Source route IP option packets --RR */
4046 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4047 +                        csum_partial((char *) tcph, tcplen, 0))) {
4048 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4049 +                    tcph, tcplen, NIPQUAD(iph->saddr),
4050 +                    NIPQUAD(iph->daddr));
4051 +               return NF_ACCEPT;
4052 +       }
4053 +
4054 +       /* find the rsh stderr port */
4055 +       maxoctet = 4;
4056 +       port = 0;
4057 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4058 +               if (*data < 0)
4059 +                       return(1);
4060 +               if (*data == 0)
4061 +                       break;
4062 +               if (*data < 48 || *data > 57) {
4063 +                       DEBUGP("these aren't the packets you're looking for ..\n");
4064 +                       return NF_ACCEPT;
4065 +               }
4066 +               port = port * 10 + ( *data - 48 );
4067 +       }
4068 +
4069 +       /* dont relate sessions that try to expose the client */
4070 +       DEBUGP("found port %u\n", port);
4071 +       if (port > 1023) {
4072 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
4073 +               return NF_ACCEPT;
4074 +       }
4075 +
4076 +
4077 +       LOCK_BH(&ip_rsh_lock);
4078 +
4079 +       /*  new(,related) connection is;
4080 +        *          reply + dst (uint)port + src port (0:1023)
4081 +        */
4082 +       memset(&expect, 0, sizeof(expect));
4083 +
4084 +       /*  save some discovered data, in case someone ever wants to write
4085 +        *  a NAT module for this bastard ..
4086 +        */
4087 +       exp_rsh_info->port = port;
4088 +
4089 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4090 +
4091 +
4092 +       /* Watch out, Radioactive-Man! */
4093 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4094 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4095 +       exp->tuple.src.u.tcp.port = 0;
4096 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4097 +       exp->tuple.dst.protonum = IPPROTO_TCP;
4098 +
4099 +       exp->mask.src.ip = 0xffffffff;
4100 +       exp->mask.dst.ip = 0xffffffff;
4101 +
4102 +       exp->mask.src.u.tcp.port = htons(0xfc00);
4103 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
4104 +       exp->mask.dst.protonum = 0xffff;
4105 +
4106 +       exp->expectfn = NULL;
4107 +
4108 +       ip_conntrack_expect_related(ct, &expect);
4109 +
4110 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4111 +               NIPQUAD(exp->tuple.src.ip),
4112 +               ntohs(exp->tuple.src.u.tcp.port),
4113 +               NIPQUAD(exp->tuple.dst.ip),
4114 +               ntohs(exp->tuple.dst.u.tcp.port));
4115 +
4116 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4117 +               NIPQUAD(exp->mask.src.ip),
4118 +               ntohs(exp->mask.src.u.tcp.port),
4119 +               NIPQUAD(exp->mask.dst.ip),
4120 +               ntohs(exp->mask.dst.u.tcp.port));
4121 +       UNLOCK_BH(&ip_rsh_lock);
4122 +
4123 +       return NF_ACCEPT;
4124 +}
4125 +
4126 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4127 +
4128 +static void fini(void);
4129 +
4130 +static int __init init(void)
4131 +{
4132 +       int port, ret;
4133 +       static char name[10];
4134 +
4135 +
4136 +       /* If no port given, default to standard RSH port */
4137 +       if (ports[0] == 0)
4138 +               ports[0] = RSH_PORT;
4139 +
4140 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4141 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4142 +
4143 +                if (ports[port] == RSH_PORT)
4144 +                        sprintf(name, "rsh");
4145 +                else
4146 +                        sprintf(name, "rsh-%d", port);
4147 +
4148 +               rsh_helpers[port].name = name;
4149 +               rsh_helpers[port].me = THIS_MODULE;
4150 +               rsh_helpers[port].max_expected = 1;
4151 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4152 +               rsh_helpers[port].timeout = 0;
4153 +
4154 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4155 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
4156 +
4157 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
4158 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4159 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4160 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4161 +
4162 +               rsh_helpers[port].help = help;
4163 +
4164 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4165 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4166 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
4167 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4168 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4169 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4170 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4171 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
4172 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4173 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
4174 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4175 +
4176 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4177 +
4178 +               if (ret) {
4179 +                       printk("ERROR registering port %d\n",
4180 +                               ports[port]);
4181 +                       fini();
4182 +                       return -EBUSY;
4183 +               }
4184 +               ports_n_c++;
4185 +       }
4186 +       return 0;
4187 +}
4188 +
4189 +/* This function is intentionally _NOT_ defined as __exit, because 
4190 + * it is needed by the init function */
4191 +static void fini(void)
4192 +{
4193 +       int port;
4194 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4195 +               DEBUGP("unregistering port %d\n", ports[port]);
4196 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
4197 +       }
4198 +}
4199 +
4200 +module_init(init);
4201 +module_exit(fini);
4202 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
4203 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c  1970-01-01 01:00:00.000000000 +0100
4204 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c      2004-03-30 11:52:01.000000000 +0200
4205 @@ -0,0 +1,509 @@
4206 +/*
4207 + * RTSP extension for IP connection tracking
4208 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
4209 + * based on ip_conntrack_irc.c
4210 + *
4211 + *      This program is free software; you can redistribute it and/or
4212 + *      modify it under the terms of the GNU General Public License
4213 + *      as published by the Free Software Foundation; either version
4214 + *      2 of the License, or (at your option) any later version.
4215 + *
4216 + * Module load syntax:
4217 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
4218 + *                              max_outstanding=n setup_timeout=secs
4219 + *
4220 + * If no ports are specified, the default will be port 554.
4221 + *
4222 + * With max_outstanding you can define the maximum number of not yet
4223 + * answered SETUP requests per RTSP session (default 8).
4224 + * With setup_timeout you can specify how long the system waits for
4225 + * an expected data channel (default 300 seconds).
4226 + */
4227 +
4228 +#include <linux/config.h>
4229 +#include <linux/module.h>
4230 +#include <linux/netfilter.h>
4231 +#include <linux/ip.h>
4232 +#include <net/checksum.h>
4233 +#include <net/tcp.h>
4234 +
4235 +#include <linux/netfilter_ipv4/lockhelp.h>
4236 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4237 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
4238 +
4239 +#include <linux/ctype.h>
4240 +#define NF_NEED_STRNCASECMP
4241 +#define NF_NEED_STRTOU16
4242 +#define NF_NEED_STRTOU32
4243 +#define NF_NEED_NEXTLINE
4244 +#include <linux/netfilter_helpers.h>
4245 +#define NF_NEED_MIME_NEXTLINE
4246 +#include <linux/netfilter_mime.h>
4247 +
4248 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
4249 +
4250 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
4251 +#ifdef IP_NF_RTSP_DEBUG
4252 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args)
4253 +#else
4254 +#define DEBUGP(args...)
4255 +#endif
4256 +
4257 +#define MAX_PORTS 8
4258 +static int ports[MAX_PORTS];
4259 +static int num_ports = 0;
4260 +static int max_outstanding = 8;
4261 +static unsigned int setup_timeout = 300;
4262 +
4263 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
4264 +MODULE_DESCRIPTION("RTSP connection tracking module");
4265 +MODULE_LICENSE("GPL");
4266 +#ifdef MODULE_PARM
4267 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4268 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
4269 +MODULE_PARM(max_outstanding, "i");
4270 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
4271 +MODULE_PARM(setup_timeout, "i");
4272 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
4273 +#endif
4274 +
4275 +DECLARE_LOCK(ip_rtsp_lock);
4276 +struct module* ip_conntrack_rtsp = THIS_MODULE;
4277 +
4278 +/*
4279 + * Max mappings we will allow for one RTSP connection (for RTP, the number
4280 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
4281 + * ports so keep this reasonably high.  If this is too low, you will see a
4282 + * lot of "no free client map entries" messages.
4283 + */
4284 +#define MAX_PORT_MAPS 16
4285 +
4286 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
4287 +
4288 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
4289 +
4290 +/*
4291 + * Parse an RTSP packet.
4292 + *
4293 + * Returns zero if parsing failed.
4294 + *
4295 + * Parameters:
4296 + *  IN      ptcp        tcp data pointer
4297 + *  IN      tcplen      tcp data len
4298 + *  IN/OUT  ptcpoff     points to current tcp offset
4299 + *  OUT     phdrsoff    set to offset of rtsp headers
4300 + *  OUT     phdrslen    set to length of rtsp headers
4301 + *  OUT     pcseqoff    set to offset of CSeq header
4302 + *  OUT     pcseqlen    set to length of CSeq header
4303 + */
4304 +static int
4305 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
4306 +                   uint* phdrsoff, uint* phdrslen,
4307 +                   uint* pcseqoff, uint* pcseqlen)
4308 +{
4309 +    uint    entitylen = 0;
4310 +    uint    lineoff;
4311 +    uint    linelen;
4312 +
4313 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
4314 +    {
4315 +        return 0;
4316 +    }
4317 +
4318 +    *phdrsoff = *ptcpoff;
4319 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
4320 +    {
4321 +        if (linelen == 0)
4322 +        {
4323 +            if (entitylen > 0)
4324 +            {
4325 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
4326 +            }
4327 +            break;
4328 +        }
4329 +        if (lineoff+linelen > tcplen)
4330 +        {
4331 +            INFOP("!! overrun !!\n");
4332 +            break;
4333 +        }
4334 +
4335 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
4336 +        {
4337 +            *pcseqoff = lineoff;
4338 +            *pcseqlen = linelen;
4339 +        }
4340 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
4341 +        {
4342 +            uint off = lineoff+15;
4343 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
4344 +            nf_strtou32(ptcp+off, &entitylen);
4345 +        }
4346 +    }
4347 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
4348 +
4349 +    return 1;
4350 +}
4351 +
4352 +/*
4353 + * Find lo/hi client ports (if any) in transport header
4354 + * In:
4355 + *   ptcp, tcplen = packet
4356 + *   tranoff, tranlen = buffer to search
4357 + *
4358 + * Out:
4359 + *   pport_lo, pport_hi = lo/hi ports (host endian)
4360 + *
4361 + * Returns nonzero if any client ports found
4362 + *
4363 + * Note: it is valid (and expected) for the client to request multiple
4364 + * transports, so we need to parse the entire line.
4365 + */
4366 +static int
4367 +rtsp_parse_transport(char* ptran, uint tranlen,
4368 +                     struct ip_ct_rtsp_expect* prtspexp)
4369 +{
4370 +    int     rc = 0;
4371 +    uint    off = 0;
4372 +
4373 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
4374 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
4375 +    {
4376 +        INFOP("sanity check failed\n");
4377 +        return 0;
4378 +    }
4379 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
4380 +    off += 10;
4381 +    SKIP_WSPACE(ptran, tranlen, off);
4382 +
4383 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
4384 +    while (off < tranlen)
4385 +    {
4386 +        const char* pparamend;
4387 +        uint        nextparamoff;
4388 +
4389 +        pparamend = memchr(ptran+off, ',', tranlen-off);
4390 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
4391 +        nextparamoff = pparamend-ptran;
4392 +
4393 +        while (off < nextparamoff)
4394 +        {
4395 +            const char* pfieldend;
4396 +            uint        nextfieldoff;
4397 +
4398 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
4399 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
4400 +
4401 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
4402 +            {
4403 +                u_int16_t   port;
4404 +                uint        numlen;
4405 +
4406 +                off += 12;
4407 +                numlen = nf_strtou16(ptran+off, &port);
4408 +                off += numlen;
4409 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
4410 +                {
4411 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
4412 +                }
4413 +                else
4414 +                {
4415 +                    prtspexp->loport = prtspexp->hiport = port;
4416 +                    if (ptran[off] == '-')
4417 +                    {
4418 +                        off++;
4419 +                        numlen = nf_strtou16(ptran+off, &port);
4420 +                        off += numlen;
4421 +                        prtspexp->pbtype = pb_range;
4422 +                        prtspexp->hiport = port;
4423 +
4424 +                        // If we have a range, assume rtp:
4425 +                        // loport must be even, hiport must be loport+1
4426 +                        if ((prtspexp->loport & 0x0001) != 0 ||
4427 +                            prtspexp->hiport != prtspexp->loport+1)
4428 +                        {
4429 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
4430 +                                   prtspexp->loport, prtspexp->hiport);
4431 +                            prtspexp->loport &= 0xfffe;
4432 +                            prtspexp->hiport = prtspexp->loport+1;
4433 +                        }
4434 +                    }
4435 +                    else if (ptran[off] == '/')
4436 +                    {
4437 +                        off++;
4438 +                        numlen = nf_strtou16(ptran+off, &port);
4439 +                        off += numlen;
4440 +                        prtspexp->pbtype = pb_discon;
4441 +                        prtspexp->hiport = port;
4442 +                    }
4443 +                    rc = 1;
4444 +                }
4445 +            }
4446 +
4447 +            /*
4448 +             * Note we don't look for the destination parameter here.
4449 +             * If we are using NAT, the NAT module will handle it.  If not,
4450 +             * and the client is sending packets elsewhere, the expectation
4451 +             * will quietly time out.
4452 +             */
4453 +
4454 +            off = nextfieldoff;
4455 +        }
4456 +
4457 +        off = nextparamoff;
4458 +    }
4459 +
4460 +    return rc;
4461 +}
4462 +
4463 +/*** conntrack functions ***/
4464 +
4465 +/* outbound packet: client->server */
4466 +static int
4467 +help_out(const struct iphdr* iph, size_t pktlen,
4468 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
4469 +{
4470 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
4471 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
4472 +    uint    tcplen = pktlen - iph->ihl * 4;
4473 +    char*   pdata = (char*)tcph + tcph->doff * 4;
4474 +    uint    datalen = tcplen - tcph->doff * 4;
4475 +    uint    dataoff = 0;
4476 +
4477 +    struct ip_conntrack_expect exp;
4478 +
4479 +    while (dataoff < datalen)
4480 +    {
4481 +        uint    cmdoff = dataoff;
4482 +        uint    hdrsoff = 0;
4483 +        uint    hdrslen = 0;
4484 +        uint    cseqoff = 0;
4485 +        uint    cseqlen = 0;
4486 +        uint    lineoff = 0;
4487 +        uint    linelen = 0;
4488 +        uint    off;
4489 +        int     rc;
4490 +
4491 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
4492 +                                &hdrsoff, &hdrslen,
4493 +                                &cseqoff, &cseqlen))
4494 +        {
4495 +            break;      /* not a valid message */
4496 +        }
4497 +
4498 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
4499 +        {
4500 +            continue;   /* not a SETUP message */
4501 +        }
4502 +        DEBUGP("found a setup message\n");
4503 +
4504 +        memset(&exp, 0, sizeof(exp));
4505 +
4506 +        off = 0;
4507 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
4508 +                                &lineoff, &linelen))
4509 +        {
4510 +            if (linelen == 0)
4511 +            {
4512 +                break;
4513 +            }
4514 +            if (off > hdrsoff+hdrslen)
4515 +            {
4516 +                INFOP("!! overrun !!");
4517 +                break;
4518 +            }
4519 +
4520 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
4521 +            {
4522 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
4523 +                                     &exp.help.exp_rtsp_info);
4524 +            }
4525 +        }
4526 +
4527 +        if (exp.help.exp_rtsp_info.loport == 0)
4528 +        {
4529 +            DEBUGP("no udp transports found\n");
4530 +            continue;   /* no udp transports found */
4531 +        }
4532 +
4533 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
4534 +              (int)exp.help.exp_rtsp_info.pbtype,
4535 +              exp.help.exp_rtsp_info.loport,
4536 +              exp.help.exp_rtsp_info.hiport);
4537 +
4538 +        LOCK_BH(&ip_rtsp_lock);
4539 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
4540 +        exp.help.exp_rtsp_info.len = hdrslen;
4541 +
4542 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4543 +        exp.mask.src.ip  = 0xffffffff;
4544 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
4545 +        exp.mask.dst.ip  = 0xffffffff;
4546 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
4547 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
4548 +        exp.tuple.dst.protonum = IPPROTO_UDP;
4549 +        exp.mask.dst.protonum  = 0xffff;
4550 +
4551 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4552 +                NIPQUAD(exp.tuple.src.ip),
4553 +                ntohs(exp.tuple.src.u.tcp.port),
4554 +                NIPQUAD(exp.tuple.dst.ip),
4555 +                ntohs(exp.tuple.dst.u.tcp.port));
4556 +
4557 +        /* pass the request off to the nat helper */
4558 +        rc = ip_conntrack_expect_related(ct, &exp);
4559 +        UNLOCK_BH(&ip_rtsp_lock);
4560 +        if (rc == 0)
4561 +        {
4562 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
4563 +        }
4564 +        else
4565 +        {
4566 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
4567 +        }
4568 +    }
4569 +
4570 +    return NF_ACCEPT;
4571 +}
4572 +
4573 +/* inbound packet: server->client */
4574 +static int
4575 +help_in(const struct iphdr* iph, size_t pktlen,
4576 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
4577 +{
4578 +    return NF_ACCEPT;
4579 +}
4580 +
4581 +static int
4582 +help(const struct iphdr* iph, size_t pktlen,
4583 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
4584 +{
4585 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4586 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
4587 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
4588 +
4589 +    /* Until there's been traffic both ways, don't look in packets. */
4590 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
4591 +    {
4592 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
4593 +        return NF_ACCEPT;
4594 +    }
4595 +
4596 +    /* Not whole TCP header? */
4597 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
4598 +    {
4599 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
4600 +        return NF_ACCEPT;
4601 +    }
4602 +
4603 +    /* Checksum invalid?  Ignore. */
4604 +    /* FIXME: Source route IP option packets --RR */
4605 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4606 +                     csum_partial((char*)tcph, tcplen, 0)))
4607 +    {
4608 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4609 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
4610 +        return NF_ACCEPT;
4611 +    }
4612 +
4613 +    switch (CTINFO2DIR(ctinfo))
4614 +    {
4615 +    case IP_CT_DIR_ORIGINAL:
4616 +        help_out(iph, pktlen, ct, ctinfo);
4617 +        break;
4618 +    case IP_CT_DIR_REPLY:
4619 +        help_in(iph, pktlen, ct, ctinfo);
4620 +        break;
4621 +    default:
4622 +        /* oops */
4623 +    }
4624 +
4625 +    return NF_ACCEPT;
4626 +}
4627 +
4628 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
4629 +static char rtsp_names[MAX_PORTS][10];
4630 +
4631 +/* This function is intentionally _NOT_ defined as __exit */
4632 +static void
4633 +fini(void)
4634 +{
4635 +    int i;
4636 +    for (i = 0; i < num_ports; i++)
4637 +    {
4638 +        DEBUGP("unregistering port %d\n", ports[i]);
4639 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
4640 +    }
4641 +}
4642 +
4643 +static int __init
4644 +init(void)
4645 +{
4646 +    int i, ret;
4647 +    struct ip_conntrack_helper *hlpr;
4648 +    char *tmpname;
4649 +
4650 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
4651 +
4652 +    if (max_outstanding < 1)
4653 +    {
4654 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
4655 +        return -EBUSY;
4656 +    }
4657 +    if (setup_timeout < 0)
4658 +    {
4659 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
4660 +        return -EBUSY;
4661 +    }
4662 +
4663 +    /* If no port given, default to standard rtsp port */
4664 +    if (ports[0] == 0)
4665 +    {
4666 +        ports[0] = RTSP_PORT;
4667 +    }
4668 +
4669 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
4670 +    {
4671 +        hlpr = &rtsp_helpers[i];
4672 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
4673 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
4674 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
4675 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
4676 +        hlpr->mask.dst.protonum = 0xFFFF;
4677 +        hlpr->max_expected = max_outstanding;
4678 +        hlpr->timeout = setup_timeout;
4679 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
4680 +        hlpr->me = ip_conntrack_rtsp;
4681 +        hlpr->help = help;
4682 +
4683 +        tmpname = &rtsp_names[i][0];
4684 +        if (ports[i] == RTSP_PORT)
4685 +        {
4686 +            sprintf(tmpname, "rtsp");
4687 +        }
4688 +        else
4689 +        {
4690 +            sprintf(tmpname, "rtsp-%d", i);
4691 +        }
4692 +        hlpr->name = tmpname;
4693 +
4694 +        DEBUGP("port #%d: %d\n", i, ports[i]);
4695 +
4696 +        ret = ip_conntrack_helper_register(hlpr);
4697 +
4698 +        if (ret)
4699 +        {
4700 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
4701 +            fini();
4702 +            return -EBUSY;
4703 +        }
4704 +        num_ports++;
4705 +    }
4706 +    return 0;
4707 +}
4708 +
4709 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4710 +EXPORT_SYMBOL(ip_rtsp_lock);
4711 +#endif
4712 +
4713 +module_init(init);
4714 +module_exit(fini);
4715 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
4716 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-03-30 11:31:19.000000000 +0200
4717 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-03-30 11:51:26.000000000 +0200
4718 @@ -110,6 +110,9 @@
4719                 len += sprintf(buffer + len, "[ASSURED] ");
4720         len += sprintf(buffer + len, "use=%u ",
4721                        atomic_read(&conntrack->ct_general.use));
4722 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
4723 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
4724 +#endif
4725         len += sprintf(buffer + len, "\n");
4726  
4727         return len;
4728 @@ -569,13 +572,20 @@
4729         return ret;
4730  }
4731  
4732 -/* FIXME: Allow NULL functions and sub in pointers to generic for
4733 -   them. --RR */
4734 +/**
4735 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
4736 + * @proto: structure describing this layer 4 protocol helper
4737 + *
4738 + * This function is called by layer 4 protocol helpers to register 
4739 + * themselves with the conntrack core.
4740 + */
4741  int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
4742  {
4743         int ret = 0;
4744         struct list_head *i;
4745  
4746 +       /* FIXME: Allow NULL functions and sub in pointers to generic for
4747 +          them. --RR */
4748         WRITE_LOCK(&ip_conntrack_lock);
4749         list_for_each(i, &protocol_list) {
4750                 if (((struct ip_conntrack_protocol *)i)->proto
4751 @@ -592,12 +602,20 @@
4752         return ret;
4753  }
4754  
4755 +/**
4756 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
4757 + * @proto: structure describing this layer 4 protocol helper
4758 + *
4759 + * This function is called byh layer 4 protocol helpers to unregister
4760 + * themselvers from the conntrack core.  Please note that all conntrack
4761 + * entries for this protocol are deleted from the conntrack hash table.
4762 + */
4763  void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
4764  {
4765         WRITE_LOCK(&ip_conntrack_lock);
4766  
4767 -       /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
4768 -        * helper. So this should be enough - HW */
4769 +       /* ip_ct_find_proto() returns proto_generic in case there is no
4770 +        * protocol helper. So this should be enough - HW */
4771         LIST_DELETE(&protocol_list, proto);
4772         WRITE_UNLOCK(&ip_conntrack_lock);
4773         
4774 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
4775 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c  1970-01-01 01:00:00.000000000 +0100
4776 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_conntrack_talk.c      2004-03-30 11:53:01.000000000 +0200
4777 @@ -0,0 +1,360 @@
4778 +/* 
4779 + * talk extension for IP connection tracking. 
4780 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4781 + *
4782 + *      This program is free software; you can redistribute it and/or
4783 + *      modify it under the terms of the GNU General Public License
4784 + *      as published by the Free Software Foundation; either version
4785 + *      2 of the License, or (at your option) any later version.
4786 + **
4787 + *     Module load syntax:
4788 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
4789 + *
4790 + *             talk=[0|1]      disable|enable old talk support
4791 + *            ntalk=[0|1]      disable|enable ntalk support
4792 + *           ntalk2=[0|1]      disable|enable ntalk2 support
4793 + *
4794 + *     The default is talk=1 ntalk=1 ntalk2=1
4795 + *
4796 + *     The helper does not support simultaneous talk requests.
4797 + **
4798 + *
4799 + *             ASCII art on talk protocols
4800 + *     
4801 + *     
4802 + *     caller server               callee server
4803 + *             |     \           /
4804 + *             |       \       /
4805 + *             |         \   /
4806 + *             |           /  
4807 + *             |         /   \
4808 + *           2 |     1 /       \ 3
4809 + *     caller client  ----------- callee client
4810 + *                              4
4811 + *
4812 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
4813 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
4814 + *     3. callee client <-> caller server: LOOK_UP invitation
4815 + *     4. callee client <-> caller client: talk data channel
4816 + *
4817 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
4818 + *      draft-hunter-talk-00.txt
4819 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
4820 + */
4821 +#include <linux/config.h>
4822 +#include <linux/module.h>
4823 +#include <linux/netfilter.h>
4824 +#include <linux/ip.h>
4825 +#include <net/checksum.h>
4826 +#include <net/udp.h>
4827 +
4828 +#include <linux/netfilter_ipv4/lockhelp.h>
4829 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4830 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
4831 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4832 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
4833 +
4834 +/* Default all talk protocols are supported */
4835 +static int talk = 1;
4836 +static int ntalk = 1;
4837 +static int ntalk2 = 1;
4838 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
4839 +MODULE_DESCRIPTION("talk connection tracking module");
4840 +MODULE_LICENSE("GPL");
4841 +#ifdef MODULE_PARM
4842 +MODULE_PARM(talk, "i");
4843 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
4844 +MODULE_PARM(ntalk, "i");
4845 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
4846 +MODULE_PARM(ntalk2, "i");
4847 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
4848 +#endif
4849 +
4850 +DECLARE_LOCK(ip_talk_lock);
4851 +struct module *ip_conntrack_talk = THIS_MODULE;
4852 +
4853 +#if 0
4854 +#define DEBUGP printk
4855 +#else
4856 +#define DEBUGP(format, args...)
4857 +#endif
4858 +
4859 +static int talk_expect(struct ip_conntrack *ct);
4860 +static int ntalk_expect(struct ip_conntrack *ct);
4861 +
4862 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
4863 +
4864 +static int talk_help_response(const struct iphdr *iph, size_t len,
4865 +                             struct ip_conntrack *ct,
4866 +                             enum ip_conntrack_info ctinfo,
4867 +                             int talk_port,
4868 +                             u_char mode,
4869 +                             u_char type,
4870 +                             u_char answer,
4871 +                             struct talk_addr *addr)
4872 +{
4873 +       int dir = CTINFO2DIR(ctinfo);
4874 +       struct ip_conntrack_expect expect, *exp = &expect;
4875 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
4876 +
4877 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
4878 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
4879 +               type, answer);
4880 +
4881 +       if (!(answer == SUCCESS && type == mode))
4882 +               return NF_ACCEPT;
4883 +       
4884 +       memset(&expect, 0, sizeof(expect));
4885 +       
4886 +       if (type == ANNOUNCE) {
4887 +
4888 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
4889 +
4890 +               /* update the talk info */
4891 +               LOCK_BH(&ip_talk_lock);
4892 +               exp_talk_info->port = htons(talk_port);
4893 +
4894 +               /* expect callee client -> caller server message */
4895 +               exp->tuple = ((struct ip_conntrack_tuple)
4896 +                       { { ct->tuplehash[dir].tuple.src.ip,
4897 +                           { 0 } },
4898 +                         { ct->tuplehash[dir].tuple.dst.ip,
4899 +                           { .tcp = { htons(talk_port) } },
4900 +                           IPPROTO_UDP }});
4901 +               exp->mask = ((struct ip_conntrack_tuple)
4902 +                       { { 0xFFFFFFFF, { 0 } },
4903 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4904 +               
4905 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
4906 +
4907 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
4908 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
4909 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
4910 +
4911 +               /* Ignore failure; should only happen with NAT */
4912 +               ip_conntrack_expect_related(ct, &expect);
4913 +               UNLOCK_BH(&ip_talk_lock);
4914 +       }
4915 +       if (type == LOOK_UP) {
4916 +
4917 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
4918 +
4919 +               /* update the talk info */
4920 +               LOCK_BH(&ip_talk_lock);
4921 +               exp_talk_info->port = addr->ta_port;
4922 +
4923 +               /* expect callee client -> caller client connection */
4924 +               exp->tuple = ((struct ip_conntrack_tuple)
4925 +                       { { ct->tuplehash[!dir].tuple.src.ip,
4926 +                           { 0 } },
4927 +                         { addr->ta_addr,
4928 +                           { addr->ta_port },
4929 +                           IPPROTO_TCP }});
4930 +               exp->mask = ((struct ip_conntrack_tuple)
4931 +                       { { 0xFFFFFFFF, { 0 } },
4932 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
4933 +               
4934 +               exp->expectfn = NULL;
4935 +               
4936 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
4937 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
4938 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
4939 +
4940 +               /* Ignore failure; should only happen with NAT */
4941 +               ip_conntrack_expect_related(ct, &expect);
4942 +               UNLOCK_BH(&ip_talk_lock);
4943 +       }
4944 +                   
4945 +       return NF_ACCEPT;
4946 +}
4947 +
4948 +/* FIXME: This should be in userspace.  Later. */
4949 +static int talk_help(const struct iphdr *iph, size_t len,
4950 +                    struct ip_conntrack *ct,
4951 +                    enum ip_conntrack_info ctinfo,
4952 +                    int talk_port,
4953 +                    u_char mode)
4954 +{
4955 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
4956 +       const char *data = (const char *)udph + sizeof(struct udphdr);
4957 +       int dir = CTINFO2DIR(ctinfo);
4958 +       size_t udplen;
4959 +
4960 +       DEBUGP("ip_ct_talk_help: help entered\n");
4961 +
4962 +       /* Until there's been traffic both ways, don't look in packets. */
4963 +       if (ctinfo != IP_CT_ESTABLISHED
4964 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4965 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
4966 +               return NF_ACCEPT;
4967 +       }
4968 +
4969 +       /* Not whole UDP header? */
4970 +       udplen = len - iph->ihl * 4;
4971 +       if (udplen < sizeof(struct udphdr)) {
4972 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
4973 +               return NF_ACCEPT;
4974 +       }
4975 +
4976 +       /* Checksum invalid?  Ignore. */
4977 +       /* FIXME: Source route IP option packets --RR */
4978 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4979 +                             csum_partial((char *)udph, udplen, 0))) {
4980 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4981 +                      udph, udplen, NIPQUAD(iph->saddr),
4982 +                      NIPQUAD(iph->daddr));
4983 +               return NF_ACCEPT;
4984 +       }
4985 +       
4986 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4987 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
4988 +
4989 +       if (dir == IP_CT_DIR_ORIGINAL)
4990 +               return NF_ACCEPT;
4991 +               
4992 +       if (talk_port == TALK_PORT
4993 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
4994 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
4995 +                                         ((struct talk_response *)data)->type, 
4996 +                                         ((struct talk_response *)data)->answer,
4997 +                                         &(((struct talk_response *)data)->addr));
4998 +       else if (talk_port == NTALK_PORT
4999 +                 && ntalk
5000 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5001 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5002 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5003 +                                         ((struct ntalk_response *)data)->type, 
5004 +                                         ((struct ntalk_response *)data)->answer,
5005 +                                         &(((struct ntalk_response *)data)->addr));
5006 +       else if (talk_port == NTALK_PORT
5007 +                && ntalk2
5008 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5009 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5010 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5011 +                                         ((struct ntalk2_response *)data)->type, 
5012 +                                         ((struct ntalk2_response *)data)->answer,
5013 +                                         &(((struct ntalk2_response *)data)->addr));
5014 +       else {
5015 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
5016 +                      (unsigned)udplen - sizeof(struct udphdr), 
5017 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5018 +               return NF_ACCEPT;
5019 +       }
5020 +}
5021 +
5022 +static int lookup_help(const struct iphdr *iph, size_t len,
5023 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5024 +{
5025 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5026 +}
5027 +
5028 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
5029 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5030 +{
5031 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5032 +}
5033 +
5034 +static struct ip_conntrack_helper lookup_helpers[2] = 
5035 +       { { { NULL, NULL },
5036 +           "talk",                                     /* name */
5037 +           0,                                          /* flags */
5038 +           NULL,                                       /* module */
5039 +           1,                                          /* max_expected */
5040 +           240,                                        /* timeout */
5041 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
5042 +             { 0, { 0 }, IPPROTO_UDP } },
5043 +           { { 0, { 0xFFFF } },                        /* mask */
5044 +             { 0, { 0 }, 0xFFFF } },
5045 +           lookup_help },                              /* helper */
5046 +          { { NULL, NULL },
5047 +            "ntalk",                                   /* name */
5048 +           0,                                          /* flags */
5049 +           NULL,                                       /* module */
5050 +           1,                                          /* max_expected */
5051 +           240,                                        /* timeout */
5052 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
5053 +             { 0, { 0 }, IPPROTO_UDP } },
5054 +           { { 0, { 0xFFFF } },                        /* mask */
5055 +             { 0, { 0 }, 0xFFFF } },
5056 +           lookup_nhelp }                              /* helper */
5057 +        };
5058 +
5059 +static int talk_expect(struct ip_conntrack *ct)
5060 +{
5061 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5062 +       WRITE_LOCK(&ip_conntrack_lock);
5063 +       ct->helper = &lookup_helpers[0];
5064 +       WRITE_UNLOCK(&ip_conntrack_lock);
5065 +        
5066 +       return NF_ACCEPT;       /* unused */
5067 +}
5068 +
5069 +static int ntalk_expect(struct ip_conntrack *ct)
5070 +{
5071 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5072 +       WRITE_LOCK(&ip_conntrack_lock);
5073 +       ct->helper = &lookup_helpers[1];
5074 +       WRITE_UNLOCK(&ip_conntrack_lock);
5075 +        
5076 +       return NF_ACCEPT;       /* unused */
5077 +}
5078 +
5079 +static int help(const struct iphdr *iph, size_t len,
5080 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5081 +{
5082 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5083 +}
5084 +
5085 +static int nhelp(const struct iphdr *iph, size_t len,
5086 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5087 +{
5088 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5089 +}
5090 +
5091 +static struct ip_conntrack_helper talk_helpers[2] = 
5092 +       { { { NULL, NULL },
5093 +           "talk",                                     /* name */
5094 +           0,                                          /* flags */
5095 +           THIS_MODULE,                                /* module */
5096 +           1,                                          /* max_expected */
5097 +           240,                                        /* timeout */
5098 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
5099 +             { 0, { 0 }, IPPROTO_UDP } },
5100 +           { { 0, { 0xFFFF } },                        /* mask */
5101 +             { 0, { 0 }, 0xFFFF } },
5102 +           help },                                     /* helper */
5103 +          { { NULL, NULL },
5104 +           "ntalk",                                    /* name */
5105 +           0,                                          /* flags */
5106 +           THIS_MODULE,                                /* module */
5107 +           1,                                          /* max_expected */
5108 +           240,                                        /* timeout */
5109 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
5110 +             { 0, { 0 }, IPPROTO_UDP } },
5111 +           { { 0, { 0xFFFF } },                        /* mask */
5112 +             { 0, { 0 }, 0xFFFF } },
5113 +           nhelp }                                     /* helper */
5114 +       };
5115 +
5116 +static int __init init(void)
5117 +{
5118 +       if (talk > 0)
5119 +               ip_conntrack_helper_register(&talk_helpers[0]);
5120 +       if (ntalk > 0 || ntalk2 > 0)
5121 +               ip_conntrack_helper_register(&talk_helpers[1]);
5122 +               
5123 +       return 0;
5124 +}
5125 +
5126 +static void __exit fini(void)
5127 +{
5128 +       if (talk > 0)
5129 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
5130 +       if (ntalk > 0 || ntalk2 > 0)
5131 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
5132 +}
5133 +
5134 +EXPORT_SYMBOL(ip_talk_lock);
5135 +
5136 +module_init(init);
5137 +module_exit(fini);
5138 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_core.c
5139 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_core.c        2004-03-30 11:31:19.000000000 +0200
5140 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_core.c    2004-03-30 11:51:26.000000000 +0200
5141 @@ -96,9 +96,16 @@
5142         WRITE_UNLOCK(&ip_nat_lock);
5143  }
5144  
5145 -/* We do checksum mangling, so if they were wrong before they're still
5146 - * wrong.  Also works for incomplete packets (eg. ICMP dest
5147 - * unreachables.) */
5148 +/**
5149 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
5150 + * @oldvalinv: bit-inverted old value of 32bit word
5151 + * @newval: new value of 32bit word
5152 + * @oldcheck: old checksum value
5153 + *
5154 + * This function implements incremental checksum mangling, so if a checksum
5155 + * was wrong it will still be wrong after mangling.  Also works for incomplete
5156 + * packets (eg. ICMP dest unreachables).  Return value is the new checksum.
5157 + */
5158  u_int16_t
5159  ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
5160  {
5161 @@ -124,7 +131,14 @@
5162         return i;
5163  }
5164  
5165 -/* Is this tuple already taken? (not by us) */
5166 +/**
5167 + * ip_nat_used_tuple - Is this tuple already in use?
5168 + * @tuple: tuple to be used for this check
5169 + * @ignored_conntrack: conntrack excluded from this check
5170 + *
5171 + * This function checks for the reply (inverted) tuple in the conntrack
5172 + * hash.  This is necessarry with NAT, since there is no fixed mapping.
5173 + */
5174  int
5175  ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
5176                   const struct ip_conntrack *ignored_conntrack)
5177 @@ -515,6 +529,19 @@
5178  #endif
5179  };
5180  
5181 +/**
5182 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
5183 + * @conntrack: conntrack on which we operate
5184 + * @mr: address/port range which is valid for this NAT mapping
5185 + * @hooknum: hook at which this NAT mapping applies
5186 + *
5187 + * This function is called by NAT targets (SNAT,DNAT,...) and by
5188 + * the NAT application helper modules.  It is called for the NEW packet
5189 + * of a connection in order to specify which NAT mappings shall apply to
5190 + * this connection at a given hook.
5191 + *
5192 + * Note: The reply mappings are created automagically by this function. 
5193 + */
5194  unsigned int
5195  ip_nat_setup_info(struct ip_conntrack *conntrack,
5196                   const struct ip_nat_multi_range *mr,
5197 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c
5198 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c     1970-01-01 01:00:00.000000000 +0100
5199 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c 2004-03-30 11:50:58.000000000 +0200
5200 @@ -0,0 +1,289 @@
5201 +/* CuSeeMe extension for UDP NAT alteration.
5202 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5203 + * based on ip_masq_cuseeme.c in 2.2 kernels
5204 + *
5205 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
5206 + *
5207 + *      This program is free software; you can redistribute it and/or
5208 + *      modify it under the terms of the GNU General Public License
5209 + *      as published by the Free Software Foundation; either version
5210 + *      2 of the License, or (at your option) any later version.
5211 + *
5212 + *      Module load syntax:
5213 + *      insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
5214 + *
5215 + *      Please give the ports of the CuSeeMe traffic you want to track.
5216 + *      If you don't specify ports, the default will be UDP port 7648.
5217 + *
5218 + *      CuSeeMe Protocol Documentation:
5219 + *      http://cu-seeme.net/squeek/tech/contents.html
5220 + *
5221 + */
5222 +
5223 +#include <linux/module.h>
5224 +#include <linux/netfilter_ipv4.h>
5225 +#include <linux/ip.h>
5226 +#include <linux/udp.h>
5227 +
5228 +#include <linux/netfilter.h>
5229 +#include <linux/netfilter_ipv4/ip_tables.h>
5230 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5231 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
5232 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5233 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5234 +
5235 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5236 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
5237 +MODULE_LICENSE("GPL");
5238 +
5239 +#define MAX_PORTS 8
5240 +
5241 +static int ports[MAX_PORTS];
5242 +static int ports_c = 0;
5243 +#ifdef MODULE_PARM
5244 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
5245 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
5246 +#endif
5247 +
5248 +#if 0
5249 +#define DEBUGP printk
5250 +#else
5251 +#define DEBUGP(format, args...)
5252 +#endif
5253 +
5254 +/* process packet from client->reflector, possibly manipulate client IP in payload */
5255 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
5256 +                             struct ip_nat_info *info,
5257 +                             enum ip_conntrack_info ctinfo,
5258 +                             struct sk_buff **pskb,
5259 +                             char *data,
5260 +                             unsigned int datalen)
5261 +{
5262 +       char new_port_ip[6];
5263 +       struct cu_header *cu_head=(struct cu_header *)data;
5264 +       
5265 +       DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n", 
5266 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5267 +               
5268 +       /* At least check that the data at offset 10 is the client's port and IP address */
5269 +       if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
5270 +           (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
5271 +               DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n", 
5272 +                      NIPQUAD(cu_head->addr),
5273 +                      ntohs(cu_head->port),
5274 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5275 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
5276 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
5277 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5278 +               /* at offset 10, replace 6 bytes containing port + IP address */
5279 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5280 +                                        10, 6, (char *)(new_port_ip), 6);
5281 +       } else 
5282 +               DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5283 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5284 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
5285 +                      NIPQUAD(cu_head->addr),
5286 +                      ntohs(cu_head->port));
5287 +}
5288 +
5289 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
5290 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
5291 +                             struct ip_nat_info *info,
5292 +                             enum ip_conntrack_info ctinfo,
5293 +                             struct sk_buff **pskb,
5294 +                             char *data,
5295 +                             unsigned int datalen)
5296 +{
5297 +       char new_port_ip[6];
5298 +       struct cu_header *cu_head = (struct cu_header *)data;
5299 +       struct oc_header *oc_head = (struct oc_header *)data; 
5300 +       struct client_info *ci; 
5301 +       int i, off;
5302 +
5303 +       
5304 +       DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n", 
5305 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5306 +               
5307 +       /* Check if we're really dealing with the client's port + IP address before rewriting */
5308 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
5309 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
5310 +               DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
5311 +                      NIPQUAD(cu_head->dest_addr),
5312 +                      ntohs(cu_head->dest_port),
5313 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5314 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
5315 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
5316 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5317 +               /* at offset 2, replace 6 bytes containing port + IP address */
5318 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5319 +                                        2, 6, (char *)(new_port_ip), 6);
5320 +       } else 
5321 +               DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5322 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5323 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
5324 +                      NIPQUAD(cu_head->dest_addr),
5325 +                      ntohs(cu_head->dest_port));
5326 +       
5327 +       /* Check if we're really dealing with the server's port + IP address before rewriting. 
5328 +          In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
5329 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
5330 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
5331 +               DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
5332 +                      NIPQUAD(cu_head->addr),
5333 +                      ntohs(cu_head->port),
5334 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
5335 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
5336 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
5337 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5338 +               /* at offset 10, replace 6 bytes containing port + IP address */
5339 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5340 +                                        10, 6, (char *)(new_port_ip), 6);
5341 +       } else 
5342 +               /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
5343 +                  is not that important so we're not logging this unless we're debugging */
5344 +               DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5345 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
5346 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
5347 +                      NIPQUAD(cu_head->addr),
5348 +                      ntohs(cu_head->port));
5349 +       
5350 +       /* Spin through client_info structs until we find our own */
5351 +       if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
5352 +               DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
5353 +               for(i=0, off=sizeof(struct oc_header);
5354 +                   (i < oc_head->client_count && 
5355 +                   off+sizeof(struct client_info) <= datalen); 
5356 +                   i++) {
5357 +                       ci=(struct client_info *)(data+off);
5358 +                       DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n", 
5359 +                              NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
5360 +                              (unsigned int)((void *)&(ci->address) - (void *)cu_head));
5361 +                       if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
5362 +                               /* mangle this IP address */
5363 +                               DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
5364 +                                      NIPQUAD(ci->address), 
5365 +                                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5366 +                                      (unsigned int)((void *)&(ci->address) - (void *)cu_head));
5367 +                               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5368 +                                                        (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4, 
5369 +                                                        (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
5370 +                               break;
5371 +                       } else 
5372 +                               off+=sizeof(struct client_info);
5373 +               }
5374 +       } else
5375 +               DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n", 
5376 +                      ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
5377 +}
5378 +
5379 +static unsigned int 
5380 +cuseeme_nat_help(struct ip_conntrack *ct,
5381 +                 struct ip_conntrack_expect *exp,
5382 +                 struct ip_nat_info *info,
5383 +                 enum ip_conntrack_info ctinfo,
5384 +                 unsigned int hooknum,
5385 +                 struct sk_buff **pskb)
5386 +{
5387 +       struct iphdr *iph = (*pskb)->nh.iph;
5388 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5389 +       int dir = CTINFO2DIR(ctinfo);
5390 +       unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
5391 +       char *data = (char *) &udph[1];
5392 +       
5393 +       DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
5394 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5395 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5396 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5397 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
5398 +             );
5399 +       
5400 +       /* Only mangle things once: original direction in POST_ROUTING
5401 +          and reply direction on PRE_ROUTING. */
5402 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5403 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5404 +               DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
5405 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5406 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5407 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5408 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
5409 +               return NF_ACCEPT;
5410 +       }
5411 +       
5412 +       if(datalen < sizeof(struct cu_header)) {
5413 +               /* packet too small */
5414 +               if (net_ratelimit())
5415 +                       printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n", 
5416 +                              datalen, sizeof(struct cu_header));
5417 +               return NF_ACCEPT;
5418 +       }
5419 +
5420 +
5421 +       /* In the debugging output, "outgoing" is from client to server, and
5422 +          "incoming" is from server to client */
5423 +       if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) 
5424 +               cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
5425 +       else 
5426 +               cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
5427 +
5428 +       return NF_ACCEPT;
5429 +}
5430 +
5431 +static struct ip_nat_helper cuseeme[MAX_PORTS];
5432 +static char cuseeme_names[MAX_PORTS][14];  /* cuseeme-65535 */
5433 +
5434 +static void fini(void)
5435 +{
5436 +       int i;
5437 +       
5438 +       for (i = 0 ; i < ports_c; i++) {
5439 +               DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
5440 +                      ip_nat_helper_unregister(&cuseeme[i]);
5441 +       }
5442 +}
5443 +
5444 +static int __init init(void)
5445 +{
5446 +       int i, ret = 0;
5447 +       char *tmpname;
5448 +
5449 +       if (!ports[0])
5450 +               ports[0] = CUSEEME_PORT;
5451 +               
5452 +       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5453 +               memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
5454 +
5455 +               cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
5456 +               cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
5457 +               cuseeme[i].mask.dst.protonum = 0xFFFF;
5458 +               cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
5459 +               cuseeme[i].help = cuseeme_nat_help;
5460 +               cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE + 
5461 +                                  IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
5462 +                                                             is stricly needed... */
5463 +               cuseeme[i].me = THIS_MODULE;
5464 +               cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
5465 +                       
5466 +               tmpname = &cuseeme_names[i][0];
5467 +               if (ports[i] == CUSEEME_PORT)
5468 +                       sprintf(tmpname, "cuseeme");
5469 +               else
5470 +                       sprintf(tmpname, "cuseeme-%d", ports[i]);
5471 +               cuseeme[i].name = tmpname;
5472 +                       
5473 +               DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
5474 +                      ports[i], cuseeme[i].name);
5475 +               ret = ip_nat_helper_register(&cuseeme[i]);
5476 +                       
5477 +               if (ret) {
5478 +                       printk("ip_nat_cuseeme: unable to register helper for port %d\n",
5479 +                              ports[i]);
5480 +                       fini();
5481 +                       return ret;
5482 +               }
5483 +               ports_c++;
5484 +       }
5485 +       return ret;
5486 +}
5487 +       
5488 +module_init(init);
5489 +module_exit(fini);
5490 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_h323.c
5491 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_h323.c        1970-01-01 01:00:00.000000000 +0100
5492 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_h323.c    2004-03-30 11:51:04.000000000 +0200
5493 @@ -0,0 +1,419 @@
5494 +/* 
5495 + * H.323 'brute force' extension for NAT alteration. 
5496 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5497 + *
5498 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
5499 + * (http://www.coritel.it/projects/sofia/nat.html)
5500 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
5501 + * the unregistered helpers to the conntrack entries.
5502 + */
5503 +
5504 +
5505 +#include <linux/module.h>
5506 +#include <linux/netfilter.h>
5507 +#include <linux/ip.h>
5508 +#include <net/checksum.h>
5509 +#include <net/tcp.h>
5510 +
5511 +#include <linux/netfilter_ipv4/lockhelp.h>
5512 +#include <linux/netfilter_ipv4/ip_nat.h>
5513 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5514 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5515 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
5516 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5517 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
5518 +
5519 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5520 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
5521 +MODULE_LICENSE("GPL");
5522 +
5523 +DECLARE_LOCK_EXTERN(ip_h323_lock);
5524 +struct module *ip_nat_h323 = THIS_MODULE;
5525 +
5526 +#if 0
5527 +#define DEBUGP printk
5528 +#else
5529 +#define DEBUGP(format, args...)
5530 +#endif
5531 +
5532 +/* FIXME: Time out? --RR */
5533 +
5534 +static unsigned int 
5535 +h225_nat_expected(struct sk_buff **pskb,
5536 +                 unsigned int hooknum,
5537 +                 struct ip_conntrack *ct,
5538 +                 struct ip_nat_info *info);
5539 +
5540 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5541 +                                 struct ip_conntrack_expect *exp,
5542 +                                 struct ip_nat_info *info,
5543 +                                 enum ip_conntrack_info ctinfo,
5544 +                                 unsigned int hooknum,
5545 +                                 struct sk_buff **pskb);
5546 +                 
5547 +static struct ip_nat_helper h245 = 
5548 +       { { NULL, NULL },
5549 +          "H.245",                             /* name */
5550 +         0,                                    /* flags */
5551 +         NULL,                                 /* module */
5552 +         { { 0, { 0 } },                       /* tuple */
5553 +           { 0, { 0 }, IPPROTO_TCP } },
5554 +         { { 0, { 0xFFFF } },                  /* mask */
5555 +           { 0, { 0 }, 0xFFFF } },
5556 +         h225_nat_help,                        /* helper */
5557 +         h225_nat_expected                     /* expectfn */
5558 +       };
5559 +
5560 +static unsigned int
5561 +h225_nat_expected(struct sk_buff **pskb,
5562 +                 unsigned int hooknum,
5563 +                 struct ip_conntrack *ct,
5564 +                 struct ip_nat_info *info)
5565 +{
5566 +       struct ip_nat_multi_range mr;
5567 +       u_int32_t newdstip, newsrcip, newip;
5568 +       u_int16_t port;
5569 +       struct ip_ct_h225_expect *exp_info;
5570 +       struct ip_ct_h225_master *master_info;
5571 +       struct ip_conntrack *master = master_ct(ct);
5572 +       unsigned int is_h225, ret;
5573 +       
5574 +       IP_NF_ASSERT(info);
5575 +       IP_NF_ASSERT(master);
5576 +
5577 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
5578 +
5579 +       DEBUGP("h225_nat_expected: We have a connection!\n");
5580 +       master_info = &ct->master->expectant->help.ct_h225_info;
5581 +       exp_info = &ct->master->help.exp_h225_info;
5582 +
5583 +       LOCK_BH(&ip_h323_lock);
5584 +
5585 +       DEBUGP("master: ");
5586 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5587 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
5588 +       DEBUGP("conntrack: ");
5589 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5590 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
5591 +               /* Make connection go to the client. */
5592 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5593 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5594 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
5595 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
5596 +       } else {
5597 +               /* Make the connection go to the server */
5598 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
5599 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5600 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
5601 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
5602 +       }
5603 +       port = exp_info->port;
5604 +       is_h225 = master_info->is_h225 == H225_PORT;
5605 +       UNLOCK_BH(&ip_h323_lock);
5606 +       
5607 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
5608 +               newip = newsrcip;
5609 +       else
5610 +               newip = newdstip;
5611 +
5612 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
5613 +
5614 +       mr.rangesize = 1;
5615 +       /* We don't want to manip the per-protocol, just the IPs... */
5616 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
5617 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
5618 +
5619 +       /* ... unless we're doing a MANIP_DST, in which case, make
5620 +          sure we map to the correct port */
5621 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
5622 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
5623 +               mr.range[0].min = mr.range[0].max
5624 +                       = ((union ip_conntrack_manip_proto)
5625 +                               { .tcp = { port } });
5626 +       }
5627 +
5628 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
5629 +       
5630 +       if (is_h225) {
5631 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
5632 +               /* NAT expectfn called with ip_nat_lock write-locked */
5633 +               info->helper = &h245;
5634 +       }
5635 +       return ret;
5636 +}
5637 +
5638 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
5639 +                                    struct sk_buff **pskb,
5640 +                                    enum ip_conntrack_info ctinfo)
5641 +{
5642 +       struct iphdr *iph = (*pskb)->nh.iph;
5643 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
5644 +       char *data = (char *) tcph + tcph->doff * 4;
5645 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
5646 +       u_int32_t datalen = tcplen - tcph->doff*4;
5647 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
5648 +       u_int32_t newip;
5649 +       u_int16_t port;
5650 +       int i;
5651 +
5652 +       MUST_BE_LOCKED(&ip_h323_lock);
5653 +
5654 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
5655 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5656 +                       ? "yes" : "no",
5657 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5658 +                       ? "yes" : "no");
5659 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
5660 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
5661 +               return 1;
5662 +
5663 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
5664 +               info->offset[IP_CT_DIR_ORIGINAL], 
5665 +               info->offset[IP_CT_DIR_REPLY],
5666 +               tcplen);
5667 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5668 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5669 +
5670 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
5671 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
5672 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
5673 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
5674 +               if (!between(info->seq[i], ntohl(tcph->seq), 
5675 +                            ntohl(tcph->seq) + datalen))
5676 +                       continue;
5677 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
5678 +                            ntohl(tcph->seq) + datalen)) {
5679 +                       /* Partial retransmisison. It's a cracker being funky. */
5680 +                       if (net_ratelimit()) {
5681 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
5682 +                                    info->seq[i],
5683 +                                    ntohl(tcph->seq),
5684 +                                    ntohl(tcph->seq) + datalen);
5685 +                       }
5686 +                       return 0;
5687 +               }
5688 +
5689 +               /* Change address inside packet to match way we're mapping
5690 +                  this connection. */
5691 +               if (i == IP_CT_DIR_ORIGINAL) {
5692 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
5693 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
5694 +               } else {
5695 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
5696 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
5697 +               }
5698 +
5699 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
5700 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
5701 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
5702 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
5703 +
5704 +               /* Modify the packet */
5705 +               *(u_int32_t *)(data + info->offset[i]) = newip;
5706 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
5707 +       
5708 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
5709 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
5710 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
5711 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
5712 +       }
5713 +
5714 +       /* fix checksum information */
5715 +
5716 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
5717 +                                    datalen, 0);
5718 +
5719 +       tcph->check = 0;
5720 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5721 +                                  csum_partial((char *)tcph, tcph->doff*4,
5722 +                                          (*pskb)->csum));
5723 +       ip_send_check(iph);
5724 +
5725 +       return 1;
5726 +}
5727 +
5728 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
5729 +                          struct ip_conntrack *ct,
5730 +                          struct sk_buff **pskb,
5731 +                          enum ip_conntrack_info ctinfo,
5732 +                          struct ip_conntrack_expect *expect)
5733 +{
5734 +       u_int32_t newip;
5735 +       u_int16_t port;
5736 +       struct ip_conntrack_tuple newtuple;
5737 +       struct iphdr *iph = (*pskb)->nh.iph;
5738 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
5739 +       char *data = (char *) tcph + tcph->doff * 4;
5740 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
5741 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
5742 +       int is_h225;
5743 +
5744 +       MUST_BE_LOCKED(&ip_h323_lock);
5745 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
5746 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5747 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5748 +
5749 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
5750 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
5751 +               /* Partial retransmisison. It's a cracker being funky. */
5752 +               if (net_ratelimit()) {
5753 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
5754 +                            expect->seq,
5755 +                            ntohl(tcph->seq),
5756 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
5757 +               }
5758 +               return 0;
5759 +       }
5760 +
5761 +       /* Change address inside packet to match way we're mapping
5762 +          this connection. */
5763 +       if (info->dir == IP_CT_DIR_REPLY) {
5764 +               /* Must be where client thinks server is */
5765 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5766 +               /* Expect something from client->server */
5767 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5768 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
5769 +       } else {
5770 +               /* Must be where server thinks client is */
5771 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5772 +               /* Expect something from server->client */
5773 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
5774 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5775 +       }
5776 +
5777 +       is_h225 = (master_info->is_h225 == H225_PORT);
5778 +
5779 +       if (is_h225) {
5780 +               newtuple.dst.protonum = IPPROTO_TCP;
5781 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
5782 +       } else {
5783 +               newtuple.dst.protonum = IPPROTO_UDP;
5784 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
5785 +       }
5786 +       
5787 +       /* Try to get same port: if not, try to change it. */
5788 +       for (port = ntohs(info->port); port != 0; port++) {
5789 +               if (is_h225)
5790 +                       newtuple.dst.u.tcp.port = htons(port);
5791 +               else
5792 +                       newtuple.dst.u.udp.port = htons(port);
5793 +
5794 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
5795 +                       break;
5796 +       }
5797 +       if (port == 0) {
5798 +               DEBUGP("h323_data_fixup: no free port found!\n");
5799 +               return 0;
5800 +       }
5801 +
5802 +       port = htons(port);
5803 +
5804 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
5805 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
5806 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
5807 +
5808 +       /* Modify the packet */
5809 +       *(u_int32_t *)(data + info->offset) = newip;
5810 +       *(u_int16_t *)(data + info->offset + 4) = port;
5811 +       
5812 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
5813 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
5814 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
5815 +
5816 +       /* fix checksum information  */
5817 +       /* FIXME: usually repeated multiple times in the case of H.245! */
5818 +
5819 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
5820 +                                    tcplen - tcph->doff*4, 0);
5821 +
5822 +       tcph->check = 0;
5823 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5824 +                                  csum_partial((char *)tcph, tcph->doff*4,
5825 +                                          (*pskb)->csum));
5826 +       ip_send_check(iph);
5827 +
5828 +       return 1;
5829 +}
5830 +
5831 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5832 +                                 struct ip_conntrack_expect *exp,
5833 +                                 struct ip_nat_info *info,
5834 +                                 enum ip_conntrack_info ctinfo,
5835 +                                 unsigned int hooknum,
5836 +                                 struct sk_buff **pskb)
5837 +{
5838 +       int dir;
5839 +       struct ip_ct_h225_expect *exp_info;
5840 +       
5841 +       /* Only mangle things once: original direction in POST_ROUTING
5842 +          and reply direction on PRE_ROUTING. */
5843 +       dir = CTINFO2DIR(ctinfo);
5844 +       DEBUGP("nat_h323: dir %s at hook %s\n",
5845 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5846 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5847 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5848 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5849 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
5850 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
5851 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
5852 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
5853 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
5854 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
5855 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
5856 +               return NF_ACCEPT;
5857 +       }
5858 +
5859 +       if (!exp) {
5860 +               LOCK_BH(&ip_h323_lock);
5861 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
5862 +                       UNLOCK_BH(&ip_h323_lock);
5863 +                       return NF_DROP;
5864 +               }
5865 +               UNLOCK_BH(&ip_h323_lock);
5866 +               return NF_ACCEPT;
5867 +       }
5868 +               
5869 +       exp_info = &exp->help.exp_h225_info;
5870 +
5871 +       LOCK_BH(&ip_h323_lock);
5872 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
5873 +               UNLOCK_BH(&ip_h323_lock);
5874 +               return NF_DROP;
5875 +       }
5876 +       UNLOCK_BH(&ip_h323_lock);
5877 +
5878 +       return NF_ACCEPT;
5879 +}
5880 +
5881 +static struct ip_nat_helper h225 = 
5882 +       { { NULL, NULL },
5883 +         "H.225",                                      /* name */
5884 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
5885 +         THIS_MODULE,                                  /* module */
5886 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
5887 +           { 0, { 0 }, IPPROTO_TCP } },
5888 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
5889 +           { 0, { 0 }, 0xFFFF } },
5890 +         h225_nat_help,                                /* helper */
5891 +         h225_nat_expected                             /* expectfn */
5892 +       };
5893 +
5894 +static int __init init(void)
5895 +{
5896 +       int ret;
5897 +       
5898 +       ret = ip_nat_helper_register(&h225);
5899 +
5900 +       if (ret != 0)
5901 +               printk("ip_nat_h323: cannot initialize the module!\n");
5902 +
5903 +       return ret;
5904 +}
5905 +
5906 +static void __exit fini(void)
5907 +{
5908 +       ip_nat_helper_unregister(&h225);
5909 +}
5910 +
5911 +module_init(init);
5912 +module_exit(fini);
5913 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_helper.c
5914 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_helper.c      2004-03-30 05:25:34.000000000 +0200
5915 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_helper.c  2004-03-30 11:51:26.000000000 +0200
5916 @@ -150,9 +150,19 @@
5917         return 1;
5918  }
5919  
5920 -/* Generic function for mangling variable-length address changes inside
5921 - * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
5922 - * command in FTP).
5923 +/**
5924 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
5925 + * @skb: pointer to skb of packet on which we operate
5926 + * @ct: conntrack of the connection to which this packet belongs
5927 + * @ctinfo: conntrack_info of the connection to which this packet belongs
5928 + * @match_offset: offset in bytes where to-be-manipulated part starts
5929 + * @match_len: lenght of the to-be-manipulated part
5930 + * @rep_buffer: pointer to buffer containing replacement
5931 + * @rep_len: length of replacement
5932 + *
5933 + * Generic function for mangling fixed and variable-length changes inside
5934 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command 
5935 + * in FTP).
5936   *
5937   * Takes care about all the nasty sequence number changes, checksumming,
5938   * skb enlargement, ...
5939 @@ -198,16 +208,27 @@
5940         return 1;
5941  }
5942                         
5943 -/* Generic function for mangling variable-length address changes inside
5944 - * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
5945 - * command in the Amanda protocol)
5946 +/**
5947 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
5948 + * @skb: pointer to skb of packet on which we operate
5949 + * @ct: conntrack of the connection to which this packet belongs
5950 + * @ctinfo: conntrack_info of the connection to which this packet belongs
5951 + * @match_offset: offset in bytes where to-be-manipulated part starts
5952 + * @match_len: lenght of the to-be-manipulated part
5953 + * @rep_buffer: pointer to buffer containing replacement
5954 + * @rep_len: length of replacement
5955 + *
5956 + * Generic function for mangling fixed and variable-length changes inside
5957 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
5958 + * commad in the Amanda protocol)
5959   *
5960   * Takes care about all the nasty sequence number changes, checksumming,
5961   * skb enlargement, ...
5962   *
5963 - * XXX - This function could be merged with ip_nat_mangle_tcp_packet which
5964 - *       should be fairly easy to do.
5965 - */
5966 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
5967 + *
5968 + * */
5969 +
5970  int 
5971  ip_nat_mangle_udp_packet(struct sk_buff **pskb,
5972                          struct ip_conntrack *ct,
5973 @@ -405,6 +426,13 @@
5974         return ip_ct_tuple_mask_cmp(tuple, &helper->tuple, &helper->mask);
5975  }
5976  
5977 +/**
5978 + * ip_nat_helper_register - Register NAT application helper
5979 + * @me: structure describing the helper
5980 + *
5981 + * This function is called by NAT application helpers to register
5982 + * themselves with the NAT core.
5983 + */
5984  int ip_nat_helper_register(struct ip_nat_helper *me)
5985  {
5986         int ret = 0;
5987 @@ -431,6 +459,13 @@
5988         return ret;
5989  }
5990  
5991 +/**
5992 + * ip_nat_helper_unregister - Unregister NAT application helper
5993 + * @me: structure describing the helper
5994 + *
5995 + * This function is called by NAT application helpers to unregister
5996 + * themselves from the NAT core.
5997 + */
5998  void ip_nat_helper_unregister(struct ip_nat_helper *me)
5999  {
6000         WRITE_LOCK(&ip_nat_lock);
6001 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_mms.c
6002 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6003 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_mms.c     2004-03-30 11:51:24.000000000 +0200
6004 @@ -0,0 +1,350 @@
6005 +/* MMS extension for TCP NAT alteration.
6006 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6007 + * based on ip_nat_ftp.c and ip_nat_irc.c
6008 + *
6009 + * ip_nat_mms.c v0.3 2002-09-22
6010 + *
6011 + *      This program is free software; you can redistribute it and/or
6012 + *      modify it under the terms of the GNU General Public License
6013 + *      as published by the Free Software Foundation; either version
6014 + *      2 of the License, or (at your option) any later version.
6015 + *
6016 + *      Module load syntax:
6017 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6018 + *
6019 + *      Please give the ports of all MMS servers You wish to connect to.
6020 + *      If you don't specify ports, the default will be TCP port 1755.
6021 + *
6022 + *      More info on MMS protocol, firewalls and NAT:
6023 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6024 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6025 + *
6026 + *      The SDP project people are reverse-engineering MMS:
6027 + *      http://get.to/sdp
6028 + */
6029 +
6030 +/* FIXME: issue with UDP & fragmentation with this URL: 
6031 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
6032 +   may be related to out-of-order first packets:
6033 +   basically the expectation is set up correctly, then the server sends
6034 +   a first UDP packet which is fragmented plus arrives out-of-order.
6035 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
6036 +   an ICMP unreachable back to the server */
6037 +
6038 +#include <linux/module.h>
6039 +#include <linux/netfilter_ipv4.h>
6040 +#include <linux/ip.h>
6041 +#include <linux/tcp.h>
6042 +#include <net/tcp.h>
6043 +#include <linux/netfilter_ipv4/ip_nat.h>
6044 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6045 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6046 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6047 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6048 +
6049 +#if 0 
6050 +#define DEBUGP printk
6051 +#define DUMP_BYTES(address, counter)                                \
6052 +({                                                                  \
6053 +       int temp_counter;                                           \
6054 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6055 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
6056 +       };                                                          \
6057 +       DEBUGP("\n");                                               \
6058 +})
6059 +#else
6060 +#define DEBUGP(format, args...)
6061 +#define DUMP_BYTES(address, counter)
6062 +#endif
6063 +
6064 +#define MAX_PORTS 8
6065 +static int ports[MAX_PORTS];
6066 +static int ports_c = 0;
6067 +
6068 +#ifdef MODULE_PARM
6069 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6070 +#endif
6071 +
6072 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6073 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6074 +MODULE_LICENSE("GPL");
6075 +
6076 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6077 +
6078 +/* FIXME: Time out? --RR */
6079 +
6080 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6081 +                          struct ip_conntrack *ct,
6082 +                          struct sk_buff **pskb,
6083 +                          enum ip_conntrack_info ctinfo,
6084 +                          struct ip_conntrack_expect *expect)
6085 +{
6086 +       u_int32_t newip;
6087 +       struct ip_conntrack_tuple t;
6088 +       struct iphdr *iph = (*pskb)->nh.iph;
6089 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6090 +       char *data = (char *)tcph + tcph->doff * 4;
6091 +       int i, j, k, port;
6092 +       u_int16_t mms_proto;
6093 +
6094 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6095 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6096 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6097 +
6098 +       int zero_padding;
6099 +
6100 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6101 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6102 +       char proto_string[6];
6103 +       
6104 +       MUST_BE_LOCKED(&ip_mms_lock);
6105 +
6106 +       /* what was the protocol again ? */
6107 +       mms_proto = expect->tuple.dst.protonum;
6108 +       sprintf(proto_string, "%u", mms_proto);
6109 +       
6110 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6111 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6112 +              mms_proto == IPPROTO_UDP ? "UDP"
6113 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6114 +       
6115 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6116 +
6117 +       /* Alter conntrack's expectations. */
6118 +       t = expect->tuple;
6119 +       t.dst.ip = newip;
6120 +       for (port = ct_mms_info->port; port != 0; port++) {
6121 +               t.dst.u.tcp.port = htons(port);
6122 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
6123 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6124 +                       break;
6125 +               }
6126 +       }
6127 +       
6128 +       if(port == 0)
6129 +               return 0;
6130 +
6131 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6132 +               NIPQUAD(newip),
6133 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6134 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6135 +               port);
6136 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6137 +       
6138 +       memset(unicode_buffer, 0, sizeof(char)*75);
6139 +
6140 +       for (i=0; i<strlen(buffer); ++i)
6141 +               *(unicode_buffer+i*2)=*(buffer+i);
6142 +       
6143 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6144 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6145 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6146 +       
6147 +       /* add end of packet to it */
6148 +       for (j=0; j<ct_mms_info->padding; ++j) {
6149 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
6150 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6151 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6152 +       }
6153 +
6154 +       /* pad with zeroes at the end ? see explanation of weird math below */
6155 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6156 +       for (k=0; k<zero_padding; ++k)
6157 +               *(unicode_buffer+i*2+j+k)= (char)0;
6158 +       
6159 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6160 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6161 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6162 +       
6163 +       /* explanation, before I forget what I did:
6164 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6165 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
6166 +          but note that things may have to be padded with zeroes to align by 8 
6167 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
6168 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6169 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
6170 +       *mms_messageLength = *mms_chunkLenLV*8;
6171 +       
6172 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6173 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6174 +       
6175 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
6176 +                                expect->seq - ntohl(tcph->seq),
6177 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6178 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6179 +       DUMP_BYTES(unicode_buffer, 60);
6180 +       
6181 +       return 1;
6182 +}
6183 +
6184 +static unsigned int
6185 +mms_nat_expected(struct sk_buff **pskb,
6186 +                 unsigned int hooknum,
6187 +                 struct ip_conntrack *ct,
6188 +                 struct ip_nat_info *info)
6189 +{
6190 +       struct ip_nat_multi_range mr;
6191 +       u_int32_t newdstip, newsrcip, newip;
6192 +
6193 +       struct ip_conntrack *master = master_ct(ct);
6194 +
6195 +       IP_NF_ASSERT(info);
6196 +       IP_NF_ASSERT(master);
6197 +
6198 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6199 +
6200 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6201 +
6202 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6203 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6204 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6205 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6206 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6207 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6208 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
6209 +
6210 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6211 +               newip = newsrcip;
6212 +       else
6213 +               newip = newdstip;
6214 +
6215 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6216 +
6217 +       mr.rangesize = 1;
6218 +       /* We don't want to manip the per-protocol, just the IPs. */
6219 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6220 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6221 +
6222 +       return ip_nat_setup_info(ct, &mr, hooknum);
6223 +}
6224 +
6225 +
6226 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6227 +                        struct ip_conntrack_expect *exp,
6228 +                        struct ip_nat_info *info,
6229 +                        enum ip_conntrack_info ctinfo,
6230 +                        unsigned int hooknum,
6231 +                        struct sk_buff **pskb)
6232 +{
6233 +       struct iphdr *iph = (*pskb)->nh.iph;
6234 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6235 +       unsigned int datalen;
6236 +       int dir;
6237 +       struct ip_ct_mms_expect *ct_mms_info;
6238 +
6239 +       if (!exp)
6240 +               DEBUGP("ip_nat_mms: no exp!!");
6241 +
6242 +       ct_mms_info = &exp->help.exp_mms_info;
6243 +       
6244 +       /* Only mangle things once: original direction in POST_ROUTING
6245 +          and reply direction on PRE_ROUTING. */
6246 +       dir = CTINFO2DIR(ctinfo);
6247 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6248 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6249 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6250 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6251 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6252 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6253 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6254 +               return NF_ACCEPT;
6255 +       }
6256 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6257 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6258 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6259 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6260 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6261 +       
6262 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6263 +       
6264 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6265 +              exp->seq + ct_mms_info->len,
6266 +              ntohl(tcph->seq),
6267 +              ntohl(tcph->seq) + datalen);
6268 +       
6269 +       LOCK_BH(&ip_mms_lock);
6270 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
6271 +       if (between(exp->seq + ct_mms_info->len,
6272 +           ntohl(tcph->seq),
6273 +           ntohl(tcph->seq) + datalen)) {
6274 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6275 +                       UNLOCK_BH(&ip_mms_lock);
6276 +                       return NF_DROP;
6277 +               }
6278 +       } else {
6279 +               /* Half a match?  This means a partial retransmisison.
6280 +                  It's a cracker being funky. */
6281 +               if (net_ratelimit()) {
6282 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6283 +                              exp->seq, ct_mms_info->len,
6284 +                              ntohl(tcph->seq),
6285 +                              ntohl(tcph->seq) + datalen);
6286 +               }
6287 +               UNLOCK_BH(&ip_mms_lock);
6288 +               return NF_DROP;
6289 +       }
6290 +       UNLOCK_BH(&ip_mms_lock);
6291 +       
6292 +       return NF_ACCEPT;
6293 +}
6294 +
6295 +static struct ip_nat_helper mms[MAX_PORTS];
6296 +static char mms_names[MAX_PORTS][10];
6297 +
6298 +/* Not __exit: called from init() */
6299 +static void fini(void)
6300 +{
6301 +       int i;
6302 +
6303 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6304 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6305 +               ip_nat_helper_unregister(&mms[i]);
6306 +       }
6307 +}
6308 +
6309 +static int __init init(void)
6310 +{
6311 +       int i, ret = 0;
6312 +       char *tmpname;
6313 +
6314 +       if (ports[0] == 0)
6315 +               ports[0] = MMS_PORT;
6316 +
6317 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6318 +
6319 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6320 +
6321 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
6322 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6323 +               mms[i].mask.dst.protonum = 0xFFFF;
6324 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
6325 +               mms[i].help = mms_nat_help;
6326 +               mms[i].me = THIS_MODULE;
6327 +               mms[i].flags = 0;
6328 +               mms[i].expect = mms_nat_expected;
6329 +
6330 +               tmpname = &mms_names[i][0];
6331 +               if (ports[i] == MMS_PORT)
6332 +                       sprintf(tmpname, "mms");
6333 +               else
6334 +                       sprintf(tmpname, "mms-%d", i);
6335 +               mms[i].name = tmpname;
6336 +
6337 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
6338 +                               ports[i]);
6339 +               ret = ip_nat_helper_register(&mms[i]);
6340 +
6341 +               if (ret) {
6342 +                       printk("ip_nat_mms: error registering "
6343 +                              "helper for port %d\n", ports[i]);
6344 +                       fini();
6345 +                       return ret;
6346 +               }
6347 +               ports_c++;
6348 +       }
6349 +
6350 +       return ret;
6351 +}
6352 +
6353 +module_init(init);
6354 +module_exit(fini);
6355 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_quake3.c
6356 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c      1970-01-01 01:00:00.000000000 +0100
6357 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_quake3.c  2004-03-30 11:51:52.000000000 +0200
6358 @@ -0,0 +1,249 @@
6359 +/* Quake3 extension for UDP NAT alteration.
6360 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6361 + * based on ip_nat_ftp.c and ip_nat_tftp.c
6362 + *
6363 + * ip_nat_quake3.c v0.0.3 2002-08-31
6364 + *
6365 + *      This program is free software; you can redistribute it and/or
6366 + *      modify it under the terms of the GNU General Public License
6367 + *      as published by the Free Software Foundation; either version
6368 + *      2 of the License, or (at your option) any later version.
6369 + *
6370 + *      Module load syntax:
6371 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6372 + *
6373 + *      please give the ports of all Quake3 master servers You wish to
6374 + *      connect to. If you don't specify ports, the default will be UDP
6375 + *      port 27950.
6376 + *
6377 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6378 + *
6379 + *      Notes: 
6380 + *      - If you're one of those people who would try anything to lower
6381 + *        latency while playing Quake (and who isn't :-) ), you may want to
6382 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
6383 + *        outgoing UDP traffic.
6384 + *        This will make ip_conntrack_quake3 add the necessary expectations,
6385 + *        but there will be no overhead for client->server UDP streams. If
6386 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6387 + *        hook for every packet in the client->server UDP stream.
6388 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6389 + *        The IP addresses in the master connection payload (=IP addresses
6390 + *        of Quake servers) have no relation with the master server so
6391 + *        DNAT'ing the master connection to a server should not change the
6392 + *        expected connections.
6393 + *      - Not tested due to lack of equipment:
6394 + *        - multiple Quake3 clients behind one MASQUERADE gateway
6395 + *        - what if Quake3 client is running on router too
6396 + */
6397 +
6398 +#include <linux/module.h>
6399 +#include <linux/netfilter_ipv4.h>
6400 +#include <linux/ip.h>
6401 +#include <linux/udp.h>
6402 +
6403 +#include <linux/netfilter.h>
6404 +#include <linux/netfilter_ipv4/ip_tables.h>
6405 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6406 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6407 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6408 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6409 +
6410 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6411 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6412 +MODULE_LICENSE("GPL");
6413 +
6414 +#define MAX_PORTS 8
6415 +
6416 +static int ports[MAX_PORTS];
6417 +static int ports_c = 0;
6418 +#ifdef MODULE_PARM
6419 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
6420 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
6421 +#endif
6422 +
6423 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
6424 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
6425 +#if 0 
6426 +#define DEBUGP printk
6427 +#else
6428 +#define DEBUGP(format, args...)
6429 +#endif
6430 +
6431 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
6432 +
6433 +static unsigned int 
6434 +quake3_nat_help(struct ip_conntrack *ct,
6435 +                struct ip_conntrack_expect *exp,
6436 +                struct ip_nat_info *info,
6437 +                enum ip_conntrack_info ctinfo,
6438 +                unsigned int hooknum,
6439 +                struct sk_buff **pskb)
6440 +{
6441 +       struct iphdr *iph = (*pskb)->nh.iph;
6442 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
6443 +       struct ip_conntrack_tuple repl;
6444 +       int dir = CTINFO2DIR(ctinfo);
6445 +       int i;
6446 +       
6447 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
6448 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6449 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6450 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6451 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6452 +             );
6453 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6454 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6455 +       
6456 +       /* Only mangle things once: original direction in POST_ROUTING
6457 +          and reply direction on PRE_ROUTING. */
6458 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6459 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6460 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
6461 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6462 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6463 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6464 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6465 +               return NF_ACCEPT;
6466 +       }
6467 +
6468 +       if (!exp) {
6469 +               DEBUGP("no conntrack expectation to modify\n");
6470 +               return NF_ACCEPT;
6471 +       }
6472 +
6473 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
6474 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
6475 +                   i+6 < ntohs(udph->len);
6476 +                   i+=7) {
6477 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
6478 +                              i, ntohs(udph->len),
6479 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
6480 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
6481 +                       
6482 +                       memset(&repl, 0, sizeof(repl));
6483 +
6484 +                       repl.dst.protonum = IPPROTO_UDP;
6485 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6486 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
6487 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
6488 +                       
6489 +                       ip_conntrack_change_expect(exp, &repl);
6490 +               }
6491 +       }
6492 +       return NF_ACCEPT;
6493 +}
6494 +
6495 +static unsigned int 
6496 +quake3_nat_expected(struct sk_buff **pskb,
6497 +                    unsigned int hooknum,
6498 +                    struct ip_conntrack *ct, 
6499 +                    struct ip_nat_info *info) 
6500 +{
6501 +       const struct ip_conntrack *master = ct->master->expectant;
6502 +       struct ip_nat_multi_range mr;
6503 +       u_int32_t newsrcip, newdstip, newip;
6504 +#if 0 
6505 +       const struct ip_conntrack_tuple *repl =
6506 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
6507 +       struct iphdr *iph = (*pskb)->nh.iph;
6508 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
6509 +#endif
6510 +
6511 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
6512 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6513 +
6514 +       IP_NF_ASSERT(info);
6515 +       IP_NF_ASSERT(master);
6516 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6517 +       
6518 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6519 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6520 +       
6521 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
6522 +               newip = newsrcip;
6523 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6524 +                      "newsrc: %u.%u.%u.%u\n",
6525 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6526 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6527 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6528 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6529 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6530 +                      NIPQUAD(newip));
6531 +               
6532 +       } else {
6533 +               newip = newdstip;
6534 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6535 +                      "newdst: %u.%u.%u.%u\n",
6536 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6537 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6538 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6539 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6540 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6541 +                      NIPQUAD(newip));
6542 +       }
6543 +       
6544 +       mr.rangesize = 1;
6545 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6546 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
6547 +
6548 +       return ip_nat_setup_info(ct,&mr,hooknum);
6549 +}
6550 +
6551 +static struct ip_nat_helper quake3[MAX_PORTS];
6552 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
6553 +
6554 +static void fini(void)
6555 +{
6556 +       int i;
6557 +       
6558 +       for (i = 0 ; i < ports_c; i++) {
6559 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
6560 +                      ip_nat_helper_unregister(&quake3[i]);
6561 +       }
6562 +}
6563 +
6564 +static int __init init(void)
6565 +       {
6566 +               int i, ret = 0;
6567 +               char *tmpname;
6568 +
6569 +               if (!ports[0])
6570 +                       ports[0] = QUAKE3_MASTER_PORT;
6571 +               
6572 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6573 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
6574 +
6575 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
6576 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
6577 +                       quake3[i].mask.dst.protonum = 0xFFFF;
6578 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
6579 +                       quake3[i].help = quake3_nat_help;
6580 +                       quake3[i].flags = 0;
6581 +                       quake3[i].me = THIS_MODULE;
6582 +                       quake3[i].expect = quake3_nat_expected;
6583 +                       
6584 +                       tmpname = &quake3_names[i][0];
6585 +                       if (ports[i] == QUAKE3_MASTER_PORT)
6586 +                               sprintf(tmpname, "quake3");
6587 +                       else
6588 +                               sprintf(tmpname, "quake3-%d", i);
6589 +                       quake3[i].name = tmpname;
6590 +                       
6591 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
6592 +                              ports[i], quake3[i].name);
6593 +                       ret = ip_nat_helper_register(&quake3[i]);
6594 +                       
6595 +                       if (ret) {
6596 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
6597 +                                      ports[i]);
6598 +                               fini();
6599 +                               return ret;
6600 +                       }
6601 +                       ports_c++;
6602 +               }
6603 +               return ret;
6604 +       }
6605 +       
6606 +module_init(init);
6607 +module_exit(fini);
6608 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
6609 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c        1970-01-01 01:00:00.000000000 +0100
6610 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_rtsp.c    2004-03-30 11:52:01.000000000 +0200
6611 @@ -0,0 +1,625 @@
6612 +/*
6613 + * RTSP extension for TCP NAT alteration
6614 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6615 + * based on ip_nat_irc.c
6616 + *
6617 + *      This program is free software; you can redistribute it and/or
6618 + *      modify it under the terms of the GNU General Public License
6619 + *      as published by the Free Software Foundation; either version
6620 + *      2 of the License, or (at your option) any later version.
6621 + *
6622 + * Module load syntax:
6623 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6624 + *                           stunaddr=<address>
6625 + *                           destaction=[auto|strip|none]
6626 + *
6627 + * If no ports are specified, the default will be port 554 only.
6628 + *
6629 + * stunaddr specifies the address used to detect that a client is using STUN.
6630 + * If this address is seen in the destination parameter, it is assumed that
6631 + * the client has already punched a UDP hole in the firewall, so we don't
6632 + * mangle the client_port.  If none is specified, it is autodetected.  It
6633 + * only needs to be set if you have multiple levels of NAT.  It should be
6634 + * set to the external address that the STUN clients detect.  Note that in
6635 + * this case, it will not be possible for clients to use UDP with servers
6636 + * between the NATs.
6637 + *
6638 + * If no destaction is specified, auto is used.
6639 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
6640 + *   destaction=strip: always strip destination parameter (not recommended).
6641 + *   destaction=none:  do not touch destination parameter (not recommended).
6642 + */
6643 +
6644 +#include <linux/module.h>
6645 +#include <linux/netfilter_ipv4.h>
6646 +#include <linux/ip.h>
6647 +#include <linux/tcp.h>
6648 +#include <linux/kernel.h>
6649 +#include <net/tcp.h>
6650 +#include <linux/netfilter_ipv4/ip_nat.h>
6651 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6652 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6653 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6654 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6655 +
6656 +#include <linux/inet.h>
6657 +#include <linux/ctype.h>
6658 +#define NF_NEED_STRNCASECMP
6659 +#define NF_NEED_STRTOU16
6660 +#include <linux/netfilter_helpers.h>
6661 +#define NF_NEED_MIME_NEXTLINE
6662 +#include <linux/netfilter_mime.h>
6663 +
6664 +#define INFOP(args...) printk(KERN_INFO __FILE__ ":" __FUNCTION__ ":" args)
6665 +#ifdef IP_NF_RTSP_DEBUG
6666 +#define DEBUGP(args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ ":" args);
6667 +#else
6668 +#define DEBUGP(args...)
6669 +#endif
6670 +
6671 +#define MAX_PORTS       8
6672 +#define DSTACT_AUTO     0
6673 +#define DSTACT_STRIP    1
6674 +#define DSTACT_NONE     2
6675 +
6676 +static int      ports[MAX_PORTS];
6677 +static char*    stunaddr = NULL;
6678 +static char*    destaction = NULL;
6679 +
6680 +static int       num_ports = 0;
6681 +static u_int32_t extip = 0;
6682 +static int       dstact = 0;
6683 +
6684 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
6685 +MODULE_DESCRIPTION("RTSP network address translation module");
6686 +MODULE_LICENSE("GPL");
6687 +#ifdef MODULE_PARM
6688 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6689 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
6690 +MODULE_PARM(stunaddr, "s");
6691 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
6692 +MODULE_PARM(destaction, "s");
6693 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
6694 +#endif
6695 +
6696 +/* protects rtsp part of conntracks */
6697 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
6698 +
6699 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
6700 +
6701 +/*** helper functions ***/
6702 +
6703 +static void
6704 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
6705 +{
6706 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
6707 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
6708 +
6709 +    *pptcpdata = (char*)tcph + tcph->doff*4;
6710 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
6711 +}
6712 +
6713 +/*** nat functions ***/
6714 +
6715 +/*
6716 + * Mangle the "Transport:" header:
6717 + *   - Replace all occurences of "client_port=<spec>"
6718 + *   - Handle destination parameter
6719 + *
6720 + * In:
6721 + *   ct, ctinfo = conntrack context
6722 + *   pskb       = packet
6723 + *   tranoff    = Transport header offset from TCP data
6724 + *   tranlen    = Transport header length (incl. CRLF)
6725 + *   rport_lo   = replacement low  port (host endian)
6726 + *   rport_hi   = replacement high port (host endian)
6727 + *
6728 + * Returns packet size difference.
6729 + *
6730 + * Assumes that a complete transport header is present, ending with CR or LF
6731 + */
6732 +static int
6733 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
6734 +                 struct ip_conntrack_expect* exp,
6735 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
6736 +{
6737 +    char*       ptcp;
6738 +    uint        tcplen;
6739 +    char*       ptran;
6740 +    char        rbuf1[16];      /* Replacement buffer (one port) */
6741 +    uint        rbuf1len;       /* Replacement len (one port) */
6742 +    char        rbufa[16];      /* Replacement buffer (all ports) */
6743 +    uint        rbufalen;       /* Replacement len (all ports) */
6744 +    u_int32_t   newip;
6745 +    u_int16_t   loport, hiport;
6746 +    uint        off = 0;
6747 +    uint        diff;           /* Number of bytes we removed */
6748 +
6749 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
6750 +    struct ip_conntrack_tuple t;
6751 +
6752 +    char    szextaddr[15+1];
6753 +    uint    extaddrlen;
6754 +    int     is_stun;
6755 +
6756 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
6757 +    ptran = ptcp+tranoff;
6758 +
6759 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
6760 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
6761 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
6762 +    {
6763 +        INFOP("sanity check failed\n");
6764 +        return 0;
6765 +    }
6766 +    off += 10;
6767 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
6768 +
6769 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6770 +    t = exp->tuple;
6771 +    t.dst.ip = newip;
6772 +
6773 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
6774 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
6775 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
6776 +
6777 +    rbuf1len = rbufalen = 0;
6778 +    switch (prtspexp->pbtype)
6779 +    {
6780 +    case pb_single:
6781 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
6782 +        {
6783 +            t.dst.u.udp.port = htons(loport);
6784 +            if (ip_conntrack_change_expect(exp, &t) == 0)
6785 +            {
6786 +                DEBUGP("using port %hu\n", loport);
6787 +                break;
6788 +            }
6789 +        }
6790 +        if (loport != 0)
6791 +        {
6792 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
6793 +            rbufalen = sprintf(rbufa, "%hu", loport);
6794 +        }
6795 +        break;
6796 +    case pb_range:
6797 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
6798 +        {
6799 +            t.dst.u.udp.port = htons(loport);
6800 +            if (ip_conntrack_change_expect(exp, &t) == 0)
6801 +            {
6802 +                hiport = loport + ~exp->mask.dst.u.udp.port;
6803 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
6804 +                break;
6805 +            }
6806 +        }
6807 +        if (loport != 0)
6808 +        {
6809 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
6810 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
6811 +        }
6812 +        break;
6813 +    case pb_discon:
6814 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
6815 +        {
6816 +            t.dst.u.udp.port = htons(loport);
6817 +            if (ip_conntrack_change_expect(exp, &t) == 0)
6818 +            {
6819 +                DEBUGP("using port %hu (1 of 2)\n", loport);
6820 +                break;
6821 +            }
6822 +        }
6823 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
6824 +        {
6825 +            t.dst.u.udp.port = htons(hiport);
6826 +            if (ip_conntrack_change_expect(exp, &t) == 0)
6827 +            {
6828 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
6829 +                break;
6830 +            }
6831 +        }
6832 +        if (loport != 0 && hiport != 0)
6833 +        {
6834 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
6835 +            if (hiport == loport+1)
6836 +            {
6837 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
6838 +            }
6839 +            else
6840 +            {
6841 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
6842 +            }
6843 +        }
6844 +        break;
6845 +    default:
6846 +        /* oops */
6847 +    }
6848 +
6849 +    if (rbuf1len == 0)
6850 +    {
6851 +        return 0;   /* cannot get replacement port(s) */
6852 +    }
6853 +
6854 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
6855 +    while (off < tranlen)
6856 +    {
6857 +        uint        saveoff;
6858 +        const char* pparamend;
6859 +        uint        nextparamoff;
6860 +
6861 +        pparamend = memchr(ptran+off, ',', tranlen-off);
6862 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
6863 +        nextparamoff = pparamend-ptcp;
6864 +
6865 +        /*
6866 +         * We pass over each param twice.  On the first pass, we look for a
6867 +         * destination= field.  It is handled by the security policy.  If it
6868 +         * is present, allowed, and equal to our external address, we assume
6869 +         * that STUN is being used and we leave the client_port= field alone.
6870 +         */
6871 +        is_stun = 0;
6872 +        saveoff = off;
6873 +        while (off < nextparamoff)
6874 +        {
6875 +            const char* pfieldend;
6876 +            uint        nextfieldoff;
6877 +
6878 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6879 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6880 +
6881 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
6882 +            {
6883 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
6884 +                {
6885 +                    is_stun = 1;
6886 +                }
6887 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
6888 +                {
6889 +                    diff = nextfieldoff-off;
6890 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6891 +                                                         off, diff, NULL, 0))
6892 +                    {
6893 +                        /* mangle failed, all we can do is bail */
6894 +                        return 0;
6895 +                    }
6896 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
6897 +                    ptran = ptcp+tranoff;
6898 +                    tranlen -= diff;
6899 +                    nextparamoff -= diff;
6900 +                    nextfieldoff -= diff;
6901 +                }
6902 +            }
6903 +
6904 +            off = nextfieldoff;
6905 +        }
6906 +        if (is_stun)
6907 +        {
6908 +            continue;
6909 +        }
6910 +        off = saveoff;
6911 +        while (off < nextparamoff)
6912 +        {
6913 +            const char* pfieldend;
6914 +            uint        nextfieldoff;
6915 +
6916 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
6917 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
6918 +
6919 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
6920 +            {
6921 +                u_int16_t   port;
6922 +                uint        numlen;
6923 +                uint        origoff;
6924 +                uint        origlen;
6925 +                char*       rbuf    = rbuf1;
6926 +                uint        rbuflen = rbuf1len;
6927 +
6928 +                off += 12;
6929 +                origoff = (ptran-ptcp)+off;
6930 +                origlen = 0;
6931 +                numlen = nf_strtou16(ptran+off, &port);
6932 +                off += numlen;
6933 +                origlen += numlen;
6934 +                if (port != prtspexp->loport)
6935 +                {
6936 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
6937 +                }
6938 +                else
6939 +                {
6940 +                    if (ptran[off] == '-' || ptran[off] == '/')
6941 +                    {
6942 +                        off++;
6943 +                        origlen++;
6944 +                        numlen = nf_strtou16(ptran+off, &port);
6945 +                        off += numlen;
6946 +                        origlen += numlen;
6947 +                        rbuf = rbufa;
6948 +                        rbuflen = rbufalen;
6949 +                    }
6950 +
6951 +                    /*
6952 +                     * note we cannot just memcpy() if the sizes are the same.
6953 +                     * the mangle function does skb resizing, checks for a
6954 +                     * cloned skb, and updates the checksums.
6955 +                     *
6956 +                     * parameter 4 below is offset from start of tcp data.
6957 +                     */
6958 +                    diff = origlen-rbuflen;
6959 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
6960 +                                              origoff, origlen, rbuf, rbuflen))
6961 +                    {
6962 +                        /* mangle failed, all we can do is bail */
6963 +                        return 0;
6964 +                    }
6965 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
6966 +                    ptran = ptcp+tranoff;
6967 +                    tranlen -= diff;
6968 +                    nextparamoff -= diff;
6969 +                    nextfieldoff -= diff;
6970 +                }
6971 +            }
6972 +
6973 +            off = nextfieldoff;
6974 +        }
6975 +
6976 +        off = nextparamoff;
6977 +    }
6978 +
6979 +    return 1;
6980 +}
6981 +
6982 +static unsigned int
6983 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
6984 +{
6985 +    struct ip_nat_multi_range mr;
6986 +    u_int32_t newdstip, newsrcip, newip;
6987 +
6988 +    struct ip_conntrack *master = master_ct(ct);
6989 +
6990 +    IP_NF_ASSERT(info);
6991 +    IP_NF_ASSERT(master);
6992 +
6993 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6994 +
6995 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6996 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6997 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
6998 +
6999 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7000 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7001 +
7002 +    mr.rangesize = 1;
7003 +    /* We don't want to manip the per-protocol, just the IPs. */
7004 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7005 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
7006 +
7007 +    return ip_nat_setup_info(ct, &mr, hooknum);
7008 +}
7009 +
7010 +static uint
7011 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7012 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7013 +{
7014 +    char*   ptcp;
7015 +    uint    tcplen;
7016 +    uint    hdrsoff;
7017 +    uint    hdrslen;
7018 +    uint    lineoff;
7019 +    uint    linelen;
7020 +    uint    off;
7021 +
7022 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7023 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7024 +
7025 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7026 +
7027 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7028 +
7029 +    hdrsoff = exp->seq - ntohl(tcph->seq);
7030 +    hdrslen = prtspexp->len;
7031 +    off = hdrsoff;
7032 +
7033 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7034 +    {
7035 +        if (linelen == 0)
7036 +        {
7037 +            break;
7038 +        }
7039 +        if (off > hdrsoff+hdrslen)
7040 +        {
7041 +            INFOP("!! overrun !!");
7042 +            break;
7043 +        }
7044 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7045 +
7046 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7047 +        {
7048 +            uint oldtcplen = tcplen;
7049 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7050 +            {
7051 +                break;
7052 +            }
7053 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7054 +            hdrslen -= (oldtcplen-tcplen);
7055 +            off -= (oldtcplen-tcplen);
7056 +            lineoff -= (oldtcplen-tcplen);
7057 +            linelen -= (oldtcplen-tcplen);
7058 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7059 +        }
7060 +    }
7061 +
7062 +    return NF_ACCEPT;
7063 +}
7064 +
7065 +static uint
7066 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7067 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7068 +{
7069 +    /* XXX: unmangle */
7070 +    return NF_ACCEPT;
7071 +}
7072 +
7073 +static uint
7074 +help(struct ip_conntrack* ct,
7075 +     struct ip_conntrack_expect* exp,
7076 +     struct ip_nat_info* info,
7077 +     enum ip_conntrack_info ctinfo,
7078 +     unsigned int hooknum,
7079 +     struct sk_buff** pskb)
7080 +{
7081 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
7082 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7083 +    uint datalen;
7084 +    int dir;
7085 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
7086 +    int rc = NF_ACCEPT;
7087 +
7088 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7089 +    {
7090 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7091 +        return NF_ACCEPT;
7092 +    }
7093 +
7094 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
7095 +
7096 +    /*
7097 +     * Only mangle things once: original direction in POST_ROUTING
7098 +     * and reply direction on PRE_ROUTING.
7099 +     */
7100 +    dir = CTINFO2DIR(ctinfo);
7101 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7102 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7103 +    {
7104 +        DEBUGP("Not touching dir %s at hook %s\n",
7105 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7106 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7107 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7108 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7109 +        return NF_ACCEPT;
7110 +    }
7111 +    DEBUGP("got beyond not touching\n");
7112 +
7113 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7114 +
7115 +    LOCK_BH(&ip_rtsp_lock);
7116 +    /* Ensure the packet contains all of the marked data */
7117 +    if (!between(exp->seq + ct_rtsp_info->len,
7118 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7119 +    {
7120 +        /* Partial retransmission?  Probably a hacker. */
7121 +        if (net_ratelimit())
7122 +        {
7123 +            INFOP("partial packet %u/%u in %u/%u\n",
7124 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7125 +        }
7126 +        UNLOCK_BH(&ip_rtsp_lock);
7127 +        return NF_DROP;
7128 +    }
7129 +
7130 +    switch (dir)
7131 +    {
7132 +    case IP_CT_DIR_ORIGINAL:
7133 +        rc = help_out(ct, ctinfo, exp, pskb);
7134 +        break;
7135 +    case IP_CT_DIR_REPLY:
7136 +        rc = help_in(ct, ctinfo, exp, pskb);
7137 +        break;
7138 +    default:
7139 +        /* oops */
7140 +    }
7141 +    UNLOCK_BH(&ip_rtsp_lock);
7142 +
7143 +    return rc;
7144 +}
7145 +
7146 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7147 +static char rtsp_names[MAX_PORTS][10];
7148 +
7149 +/* This function is intentionally _NOT_ defined as  __exit */
7150 +static void
7151 +fini(void)
7152 +{
7153 +    int i;
7154 +
7155 +    for (i = 0; i < num_ports; i++)
7156 +    {
7157 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
7158 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7159 +    }
7160 +}
7161 +
7162 +static int __init
7163 +init(void)
7164 +{
7165 +    int ret = 0;
7166 +    int i;
7167 +    struct ip_nat_helper* hlpr;
7168 +    char* tmpname;
7169 +
7170 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7171 +
7172 +    if (ports[0] == 0)
7173 +    {
7174 +        ports[0] = RTSP_PORT;
7175 +    }
7176 +
7177 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7178 +    {
7179 +        hlpr = &ip_nat_rtsp_helpers[i];
7180 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
7181 +
7182 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
7183 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7184 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
7185 +        hlpr->mask.dst.protonum = 0xFFFF;
7186 +        hlpr->help = help;
7187 +        hlpr->flags = 0;
7188 +        hlpr->me = THIS_MODULE;
7189 +        hlpr->expect = expected;
7190 +
7191 +        tmpname = &rtsp_names[i][0];
7192 +        if (ports[i] == RTSP_PORT)
7193 +        {
7194 +                sprintf(tmpname, "rtsp");
7195 +        }
7196 +        else
7197 +        {
7198 +                sprintf(tmpname, "rtsp-%d", i);
7199 +        }
7200 +        hlpr->name = tmpname;
7201 +
7202 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7203 +        ret = ip_nat_helper_register(hlpr);
7204 +
7205 +        if (ret)
7206 +        {
7207 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7208 +            fini();
7209 +            return 1;
7210 +        }
7211 +        num_ports++;
7212 +    }
7213 +    if (stunaddr != NULL)
7214 +    {
7215 +        extip = in_aton(stunaddr);
7216 +    }
7217 +    if (destaction != NULL)
7218 +    {
7219 +        if (strcmp(destaction, "auto") == 0)
7220 +        {
7221 +            dstact = DSTACT_AUTO;
7222 +        }
7223 +        if (strcmp(destaction, "strip") == 0)
7224 +        {
7225 +            dstact = DSTACT_STRIP;
7226 +        }
7227 +        if (strcmp(destaction, "none") == 0)
7228 +        {
7229 +            dstact = DSTACT_NONE;
7230 +        }
7231 +    }
7232 +    return ret;
7233 +}
7234 +
7235 +module_init(init);
7236 +module_exit(fini);
7237 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_standalone.c
7238 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c  2004-03-30 05:27:01.000000000 +0200
7239 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_standalone.c      2004-03-30 11:51:26.000000000 +0200
7240 @@ -266,7 +266,13 @@
7241  };
7242  #endif
7243  
7244 -/* Protocol registration. */
7245 +/**
7246 + * ip_nat_protocol_register - Register a layer 4 protocol helper
7247 + * @proto: structure describing this helper
7248 + * 
7249 + * This function is called by NAT layer 4 protocol helpers to register
7250 + * themselvers with the NAT core.
7251 + */
7252  int ip_nat_protocol_register(struct ip_nat_protocol *proto)
7253  {
7254         int ret = 0;
7255 @@ -287,9 +293,16 @@
7256         return ret;
7257  }
7258  
7259 -/* Noone stores the protocol anywhere; simply delete it. */
7260 +/**
7261 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
7262 + * @proto: structure describing the helper
7263 + *
7264 + * This function is called by NAT layer 4 protocol helpers to
7265 + * unregister themselves from the NAT core.
7266 + */
7267  void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
7268  {
7269 +       /* Noone stores the protocol anywhere; simply delete it. */
7270         WRITE_LOCK(&ip_nat_lock);
7271         LIST_DELETE(&protos, proto);
7272         WRITE_UNLOCK(&ip_nat_lock);
7273 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_talk.c
7274 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_nat_talk.c        1970-01-01 01:00:00.000000000 +0100
7275 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_nat_talk.c    2004-03-30 11:53:01.000000000 +0200
7276 @@ -0,0 +1,473 @@
7277 +/* 
7278 + * talk extension for UDP NAT alteration. 
7279 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7280 + *
7281 + *      This program is free software; you can redistribute it and/or
7282 + *      modify it under the terms of the GNU General Public License
7283 + *      as published by the Free Software Foundation; either version
7284 + *      2 of the License, or (at your option) any later version.
7285 + **
7286 + *     Module load syntax:
7287 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7288 + *
7289 + *             talk=[0|1]      disable|enable old talk support
7290 + *            ntalk=[0|1]      disable|enable ntalk support
7291 + *           ntalk2=[0|1]      disable|enable ntalk2 support
7292 + *
7293 + *     The default is talk=1 ntalk=1 ntalk2=1
7294 + *
7295 + *  
7296 + */
7297 +#include <linux/module.h>
7298 +#include <linux/netfilter_ipv4.h>
7299 +#include <linux/ip.h>
7300 +#include <linux/udp.h>
7301 +#include <linux/kernel.h>
7302 +#include <net/tcp.h>
7303 +#include <net/udp.h>
7304 +
7305 +#include <linux/netfilter_ipv4/ip_nat.h>
7306 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7307 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7308 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7309 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7310 +
7311 +/* Default all talk protocols are supported */
7312 +static int talk   = 1;
7313 +static int ntalk  = 1;
7314 +static int ntalk2 = 1;
7315 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7316 +MODULE_DESCRIPTION("talk network address translation module");
7317 +#ifdef MODULE_PARM
7318 +MODULE_PARM(talk, "i");
7319 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7320 +MODULE_PARM(ntalk, "i");
7321 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7322 +MODULE_PARM(ntalk2, "i");
7323 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7324 +#endif
7325 +
7326 +#if 0
7327 +#define DEBUGP printk
7328 +#define IP_NAT_TALK_DEBUG
7329 +#else
7330 +#define DEBUGP(format, args...)
7331 +#endif
7332 +
7333 +/* FIXME: Time out? --RR */
7334 +
7335 +static int
7336 +mangle_packet(struct sk_buff **pskb,
7337 +             struct ip_conntrack *ct,
7338 +             u_int32_t newip,
7339 +             u_int16_t port,
7340 +             struct talk_addr *addr,
7341 +             struct talk_addr *ctl_addr)
7342 +{
7343 +       struct iphdr *iph = (*pskb)->nh.iph;
7344 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7345 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
7346 +
7347 +       /* Fortunately talk sends a structure with the address and
7348 +          port in it. The size of the packet won't change. */
7349 +
7350 +       if (ctl_addr == NULL) {
7351 +               /* response */
7352 +               if (addr->ta_addr == INADDR_ANY)
7353 +                       return 1;
7354 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
7355 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7356 +                      NIPQUAD(newip), ntohs(port));
7357 +               addr->ta_addr = newip;
7358 +               addr->ta_port = port;
7359 +       } else {
7360 +               /* message */
7361 +               if (addr->ta_addr != INADDR_ANY) {
7362 +                       /* Change address inside packet to match way we're mapping
7363 +                          this connection. */
7364 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
7365 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7366 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
7367 +                              ntohs(addr->ta_port));
7368 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7369 +               }
7370 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
7371 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7372 +                      NIPQUAD(newip), ntohs(port));
7373 +               ctl_addr->ta_addr = newip;
7374 +               ctl_addr->ta_port = port;
7375 +       }
7376 +
7377 +       /* Fix checksums */
7378 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
7379 +       udph->check = 0;
7380 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7381 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
7382 +               
7383 +       ip_send_check(iph);
7384 +       return 1;
7385 +}
7386 +
7387 +static int talk_help_msg(struct ip_conntrack *ct,
7388 +                        struct sk_buff **pskb,
7389 +                        u_char type,
7390 +                        struct talk_addr *addr,
7391 +                        struct talk_addr *ctl_addr)
7392 +{
7393 +       u_int32_t newip;
7394 +       u_int16_t port;
7395 +       
7396 +       unsigned int verdict = NF_ACCEPT;
7397 +
7398 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
7399 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7400 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7401 +               type);
7402 +
7403 +       /* Change address inside packet to match way we're mapping
7404 +          this connection. */
7405 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7406 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7407 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
7408 +               NIPQUAD(newip), ntohs(port));
7409 +
7410 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
7411 +               verdict = NF_DROP;
7412 +
7413 +       return verdict;
7414 +}
7415 +
7416 +static int talk_help_response(struct ip_conntrack *ct,
7417 +                             struct ip_conntrack_expect *exp,
7418 +                             struct sk_buff **pskb,
7419 +                             u_char type,
7420 +                             u_char answer,
7421 +                             struct talk_addr *addr)
7422 +{
7423 +       u_int32_t newip;
7424 +       u_int16_t port;
7425 +       struct ip_conntrack_tuple t;
7426 +       struct ip_ct_talk_expect *ct_talk_info;
7427 +
7428 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
7429 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7430 +               type, answer);
7431 +       
7432 +       LOCK_BH(&ip_talk_lock);
7433 +       ct_talk_info = &exp->help.exp_talk_info;
7434 +
7435 +       if (!(answer == SUCCESS 
7436 +             && (type == LOOK_UP || type == ANNOUNCE)
7437 +             && exp != NULL)) {
7438 +               UNLOCK_BH(&ip_talk_lock);
7439 +               return NF_ACCEPT;
7440 +       }
7441 +               
7442 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
7443 +               ntohs(ct_talk_info->port), 
7444 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
7445 +
7446 +       /* Change address inside packet to match way we're mapping
7447 +          this connection. */
7448 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
7449 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
7450 +       /* We can read expect here without conntrack lock, since it's
7451 +          only set in ip_conntrack_talk , with ip_talk_lock held
7452 +          writable */ 
7453 +       t = exp->tuple;
7454 +       t.dst.ip = newip;
7455 +
7456 +       /* Try to get same port: if not, try to change it. */
7457 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
7458 +               if (type == LOOK_UP)
7459 +                       t.dst.u.tcp.port = htons(port);
7460 +               else
7461 +                       t.dst.u.udp.port = htons(port);
7462 +
7463 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
7464 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
7465 +                       break;
7466 +               }
7467 +       }
7468 +       UNLOCK_BH(&ip_talk_lock);
7469 +
7470 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
7471 +               return NF_DROP;
7472 +       
7473 +       return NF_ACCEPT;
7474 +}
7475 +
7476 +static unsigned int talk_help(struct ip_conntrack *ct,
7477 +                             struct ip_conntrack_expect *exp,
7478 +                             struct ip_nat_info *info,
7479 +                             enum ip_conntrack_info ctinfo,
7480 +                             unsigned int hooknum,
7481 +                             struct sk_buff **pskb,
7482 +                             int talk_port)
7483 +{
7484 +       struct iphdr *iph = (*pskb)->nh.iph;
7485 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7486 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
7487 +       char *data = (char *)udph + sizeof(struct udphdr);
7488 +       int dir;
7489 +
7490 +       /* Only mangle things once: original direction in POST_ROUTING
7491 +          and reply direction on PRE_ROUTING. */
7492 +       dir = CTINFO2DIR(ctinfo);
7493 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7494 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7495 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
7496 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7497 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7498 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7499 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7500 +               return NF_ACCEPT;
7501 +       }
7502 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
7503 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7504 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7505 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7506 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7507 +              NIPQUAD(iph->saddr), ntohs(udph->source),
7508 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
7509 +              talk_port);
7510 +
7511 +       /* Because conntrack does not drop packets, checking must be repeated here... */
7512 +       if (talk_port == TALK_PORT) {
7513 +               if (dir == IP_CT_DIR_ORIGINAL
7514 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
7515 +                       return talk_help_msg(ct, pskb,
7516 +                                            ((struct talk_msg *)data)->type, 
7517 +                                            &(((struct talk_msg *)data)->addr),
7518 +                                            &(((struct talk_msg *)data)->ctl_addr));
7519 +               else if (dir == IP_CT_DIR_REPLY
7520 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7521 +                       return talk_help_response(ct, exp, pskb,
7522 +                                                 ((struct talk_response *)data)->type, 
7523 +                                                 ((struct talk_response *)data)->answer,
7524 +                                                 &(((struct talk_response *)data)->addr));
7525 +               else {  
7526 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
7527 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
7528 +                              (unsigned)udplen - sizeof(struct udphdr), 
7529 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
7530 +                       return NF_DROP;
7531 +               }
7532 +       } else {
7533 +               if (dir == IP_CT_DIR_ORIGINAL) {
7534 +                       if (ntalk
7535 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
7536 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
7537 +                               return talk_help_msg(ct, pskb,
7538 +                                                    ((struct ntalk_msg *)data)->type, 
7539 +                                                    &(((struct ntalk_msg *)data)->addr),
7540 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
7541 +                       else if (ntalk2
7542 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
7543 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
7544 +                                && udplen == sizeof(struct udphdr) 
7545 +                                             + sizeof(struct ntalk2_msg) 
7546 +                                             + ((struct ntalk2_msg *)data)->extended)
7547 +                               return talk_help_msg(ct, pskb,
7548 +                                                    ((struct ntalk2_msg *)data)->type, 
7549 +                                                    &(((struct ntalk2_msg *)data)->addr),
7550 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
7551 +                       else {
7552 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
7553 +                                      (unsigned)udplen - sizeof(struct udphdr), 
7554 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
7555 +                               return NF_DROP;
7556 +                       }
7557 +               } else {
7558 +                       if (ntalk
7559 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
7560 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
7561 +                               return talk_help_response(ct, exp, pskb,
7562 +                                                         ((struct ntalk_response *)data)->type, 
7563 +                                                         ((struct ntalk_response *)data)->answer,
7564 +                                                         &(((struct ntalk_response *)data)->addr));
7565 +                       else if (ntalk2
7566 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
7567 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
7568 +                               return talk_help_response(ct, exp, pskb,
7569 +                                                         ((struct ntalk2_response *)data)->type, 
7570 +                                                         ((struct ntalk2_response *)data)->answer,
7571 +                                                         &(((struct ntalk2_response *)data)->addr));
7572 +                       else {
7573 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
7574 +                                      (unsigned)udplen - sizeof(struct udphdr), 
7575 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
7576 +                               return NF_DROP;
7577 +                       }
7578 +               }
7579 +       }
7580 +}
7581 +
7582 +static unsigned int help(struct ip_conntrack *ct,
7583 +                        struct ip_conntrack_expect *exp,
7584 +                        struct ip_nat_info *info,
7585 +                        enum ip_conntrack_info ctinfo,
7586 +                        unsigned int hooknum,
7587 +                        struct sk_buff **pskb)
7588 +{
7589 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
7590 +}
7591 +
7592 +static unsigned int nhelp(struct ip_conntrack *ct,
7593 +                         struct ip_conntrack_expect *exp,
7594 +                         struct ip_nat_info *info,
7595 +                         enum ip_conntrack_info ctinfo,
7596 +                         unsigned int hooknum,
7597 +                         struct sk_buff **pskb)
7598 +{
7599 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
7600 +}
7601 +
7602 +static unsigned int
7603 +talk_nat_expected(struct sk_buff **pskb,
7604 +                 unsigned int hooknum,
7605 +                 struct ip_conntrack *ct,
7606 +                 struct ip_nat_info *info);
7607 +
7608 +static struct ip_nat_helper talk_helpers[2] = 
7609 +       { { { NULL, NULL },
7610 +            "talk",                                    /* name */
7611 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
7612 +            THIS_MODULE,                               /* module */
7613 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
7614 +              { 0, { 0 }, IPPROTO_UDP } },
7615 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
7616 +              { 0, { 0 }, 0xFFFF } },
7617 +            help,                                      /* helper */
7618 +            talk_nat_expected },                       /* expectfn */
7619 +         { { NULL, NULL },
7620 +            "ntalk",                                   /* name */
7621 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
7622 +            THIS_MODULE,                                       /* module */
7623 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
7624 +              { 0, { 0 }, IPPROTO_UDP } },
7625 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
7626 +              { 0, { 0 }, 0xFFFF } },
7627 +            nhelp,                                     /* helper */
7628 +            talk_nat_expected }                                /* expectfn */
7629 +       };
7630 +          
7631 +static unsigned int
7632 +talk_nat_expected(struct sk_buff **pskb,
7633 +                 unsigned int hooknum,
7634 +                 struct ip_conntrack *ct,
7635 +                 struct ip_nat_info *info)
7636 +{
7637 +       struct ip_nat_multi_range mr;
7638 +       u_int32_t newdstip, newsrcip, newip;
7639 +       u_int16_t port;
7640 +       unsigned int ret;
7641 +       
7642 +       struct ip_conntrack *master = master_ct(ct);
7643 +
7644 +       IP_NF_ASSERT(info);
7645 +       IP_NF_ASSERT(master);
7646 +
7647 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
7648 +
7649 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
7650 +
7651 +       LOCK_BH(&ip_talk_lock);
7652 +       port = ct->master->help.exp_talk_info.port;
7653 +       UNLOCK_BH(&ip_talk_lock);
7654 +
7655 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
7656 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7657 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7658 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7659 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7660 +              ct, master);
7661 +
7662 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
7663 +               /* Callee client -> caller server */
7664 +#ifdef IP_NAT_TALK_DEBUG
7665 +               struct iphdr *iph = (*pskb)->nh.iph;
7666 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
7667 +
7668 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7669 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
7670 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
7671 +#endif
7672 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7673 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7674 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
7675 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
7676 +       } else {
7677 +               /* Callee client -> caller client */
7678 +#ifdef IP_NAT_TALK_DEBUG
7679 +               struct iphdr *iph = (*pskb)->nh.iph;
7680 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
7681 +
7682 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
7683 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
7684 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
7685 +#endif
7686 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
7687 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7688 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
7689 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
7690 +       }
7691 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7692 +               newip = newsrcip;
7693 +       else
7694 +               newip = newdstip;
7695 +
7696 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
7697 +
7698 +       mr.rangesize = 1;
7699 +       /* We don't want to manip the per-protocol, just the IPs... */
7700 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7701 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
7702 +       
7703 +       /* ... unless we're doing a MANIP_DST, in which case, make
7704 +          sure we map to the correct port */
7705 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
7706 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
7707 +               mr.range[0].min = mr.range[0].max
7708 +                       = ((union ip_conntrack_manip_proto)
7709 +                               { .udp = { port } });
7710 +       }
7711 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
7712 +
7713 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
7714 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
7715 +               /* NAT expectfn called with ip_nat_lock write-locked */
7716 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
7717 +       }
7718 +       return ret;
7719 +}
7720 +
7721 +static int __init init(void)
7722 +{
7723 +       int ret = 0;
7724 +
7725 +       if (talk > 0) {
7726 +               ret = ip_nat_helper_register(&talk_helpers[0]);
7727 +
7728 +               if (ret != 0)
7729 +                       return ret;
7730 +       }
7731 +       if (ntalk > 0 || ntalk2 > 0) {
7732 +               ret = ip_nat_helper_register(&talk_helpers[1]);
7733 +
7734 +               if (ret != 0 && talk > 0)
7735 +                       ip_nat_helper_unregister(&talk_helpers[0]);
7736 +       }
7737 +       return ret;
7738 +}
7739 +
7740 +static void __exit fini(void)
7741 +{
7742 +       if (talk > 0)
7743 +               ip_nat_helper_unregister(&talk_helpers[0]);
7744 +       if (ntalk > 0 || ntalk2 > 0)
7745 +               ip_nat_helper_unregister(&talk_helpers[1]);
7746 +}
7747 +
7748 +module_init(init);
7749 +module_exit(fini);
7750 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.5-rc3/net/ipv4/netfilter/ip_tables.c
7751 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ip_tables.c  2004-03-30 11:31:19.000000000 +0200
7752 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ip_tables.c      2004-03-30 11:51:11.000000000 +0200
7753 @@ -8,6 +8,10 @@
7754   * it under the terms of the GNU General Public License version 2 as
7755   * published by the Free Software Foundation.
7756   *
7757 + *  6 Mar 2002 Robert Olsson <robban@robtex.com>
7758 + * 17 Apr 2003 Chris  Wilson <chris@netservers.co.uk>
7759 + *     - mark_source_chains speedup for complex chains
7760 + *
7761   * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
7762   *     - increase module usage count as soon as we have rules inside
7763   *       a table
7764 @@ -498,6 +502,9 @@
7765  {
7766         unsigned int hook;
7767  
7768 +       /* keep track of where we have been: */
7769 +       unsigned char *been = vmalloc(newinfo->size);
7770 +
7771         /* No recursion; use packet counter to save back ptrs (reset
7772            to 0 as we leave), and comefrom to save source hook bitmask */
7773         for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
7774 @@ -510,6 +517,7 @@
7775  
7776                 /* Set initial back pointer. */
7777                 e->counters.pcnt = pos;
7778 +               memset(been, 0, newinfo->size);
7779  
7780                 for (;;) {
7781                         struct ipt_standard_target *t
7782 @@ -518,6 +526,7 @@
7783                         if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
7784                                 printk("iptables: loop hook %u pos %u %08X.\n",
7785                                        hook, pos, e->comefrom);
7786 +                               vfree(been);
7787                                 return 0;
7788                         }
7789                         e->comefrom
7790 @@ -565,10 +574,14 @@
7791                         } else {
7792                                 int newpos = t->verdict;
7793  
7794 -                               if (strcmp(t->target.u.user.name,
7795 +                               if ( (pos < 0 || pos >= newinfo->size
7796 +                                     || !been[pos]) 
7797 +                                   && strcmp(t->target.u.user.name,
7798                                            IPT_STANDARD_TARGET) == 0
7799                                     && newpos >= 0) {
7800                                         /* This a jump; chase it. */
7801 +                                       if (pos >= 0 && pos < newinfo->size)
7802 +                                               been[pos]++;
7803                                         duprintf("Jump rule %u -> %u\n",
7804                                                  pos, newpos);
7805                                 } else {
7806 @@ -584,6 +597,7 @@
7807                 next:
7808                 duprintf("Finished chain %u\n", hook);
7809         }
7810 +       vfree(been);
7811         return 1;
7812  }
7813  
7814 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
7815 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c       1970-01-01 01:00:00.000000000 +0100
7816 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_CONNMARK.c   2004-03-30 11:48:14.000000000 +0200
7817 @@ -0,0 +1,118 @@
7818 +/* This kernel module is used to modify the connection mark values, or
7819 + * to optionally restore the skb nfmark from the connection mark
7820 + *
7821 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
7822 + * by Henrik Nordstrom <hno@marasystems.com>
7823 + *
7824 + * This program is free software; you can redistribute it and/or modify
7825 + * it under the terms of the GNU General Public License as published by
7826 + * the Free Software Foundation; either version 2 of the License, or
7827 + * (at your option) any later version.
7828 + *
7829 + * This program is distributed in the hope that it will be useful,
7830 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7831 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7832 + * GNU General Public License for more details.
7833 + *
7834 + * You should have received a copy of the GNU General Public License
7835 + * along with this program; if not, write to the Free Software
7836 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
7837 + */
7838 +#include <linux/module.h>
7839 +#include <linux/skbuff.h>
7840 +#include <linux/ip.h>
7841 +#include <net/checksum.h>
7842 +
7843 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
7844 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
7845 +MODULE_LICENSE("GPL");
7846 +
7847 +#include <linux/netfilter_ipv4/ip_tables.h>
7848 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
7849 +#include <linux/netfilter_ipv4/ip_conntrack.h>
7850 +
7851 +static unsigned int
7852 +target(struct sk_buff **pskb,
7853 +       const struct net_device *in,
7854 +       const struct net_device *out,
7855 +       unsigned int hooknum,
7856 +       const void *targinfo,
7857 +       void *userinfo)
7858 +{
7859 +       const struct ipt_connmark_target_info *markinfo = targinfo;
7860 +       unsigned long diff;
7861 +       unsigned long nfmark;
7862 +       unsigned long newmark;
7863 +
7864 +       enum ip_conntrack_info ctinfo;
7865 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
7866 +       if (ct) {
7867 +           switch(markinfo->mode) {
7868 +           case IPT_CONNMARK_SET:
7869 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
7870 +               if (newmark != ct->mark)
7871 +                   ct->mark = newmark;
7872 +               break;
7873 +           case IPT_CONNMARK_SAVE:
7874 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
7875 +               if (ct->mark != newmark)
7876 +                   ct->mark = newmark;
7877 +               break;
7878 +           case IPT_CONNMARK_RESTORE:
7879 +               nfmark = (*pskb)->nfmark;
7880 +               diff = (ct->mark ^ nfmark & markinfo->mask);
7881 +               if (diff != 0) {
7882 +                   (*pskb)->nfmark = nfmark ^ diff;
7883 +                   (*pskb)->nfcache |= NFC_ALTERED;
7884 +               }
7885 +               break;
7886 +           }
7887 +       }
7888 +
7889 +       return IPT_CONTINUE;
7890 +}
7891 +
7892 +static int
7893 +checkentry(const char *tablename,
7894 +          const struct ipt_entry *e,
7895 +          void *targinfo,
7896 +          unsigned int targinfosize,
7897 +          unsigned int hook_mask)
7898 +{
7899 +       struct ipt_connmark_target_info *matchinfo = targinfo;
7900 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
7901 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
7902 +                      targinfosize,
7903 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
7904 +               return 0;
7905 +       }
7906 +
7907 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
7908 +           if (strcmp(tablename, "mangle") != 0) {
7909 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
7910 +                   return 0;
7911 +           }
7912 +       }
7913 +
7914 +       return 1;
7915 +}
7916 +
7917 +static struct ipt_target ipt_connmark_reg = {
7918 +       .name = "CONNMARK",
7919 +       .target = &target,
7920 +       .checkentry = &checkentry,
7921 +       .me = THIS_MODULE
7922 +};
7923 +
7924 +static int __init init(void)
7925 +{
7926 +       return ipt_register_target(&ipt_connmark_reg);
7927 +}
7928 +
7929 +static void __exit fini(void)
7930 +{
7931 +       ipt_unregister_target(&ipt_connmark_reg);
7932 +}
7933 +
7934 +module_init(init);
7935 +module_exit(fini);
7936 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_IPMARK.c
7937 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
7938 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_IPMARK.c     2004-03-30 11:48:25.000000000 +0200
7939 @@ -0,0 +1,81 @@
7940 +/* This is a module which is used for setting the NFMARK field of an skb. */
7941 +#include <linux/module.h>
7942 +#include <linux/skbuff.h>
7943 +#include <linux/ip.h>
7944 +#include <net/checksum.h>
7945 +
7946 +#include <linux/netfilter_ipv4/ip_tables.h>
7947 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
7948 +
7949 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
7950 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
7951 +MODULE_LICENSE("GPL");
7952 +
7953 +static unsigned int
7954 +target(struct sk_buff **pskb,
7955 +       const struct net_device *in,
7956 +       const struct net_device *out,
7957 +       unsigned int hooknum,
7958 +       const void *targinfo,
7959 +       void *userinfo)
7960 +{
7961 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
7962 +       struct iphdr *iph = (*pskb)->nh.iph;
7963 +       unsigned long mark;
7964 +
7965 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
7966 +               mark = (unsigned long) ntohl(iph->saddr);
7967 +       else
7968 +               mark = (unsigned long) ntohl(iph->daddr);
7969 +
7970 +       mark &= ipmarkinfo->andmask;
7971 +       mark |= ipmarkinfo->ormask;
7972 +       
7973 +       if ((*pskb)->nfmark != mark) {
7974 +               (*pskb)->nfmark = mark;
7975 +               (*pskb)->nfcache |= NFC_ALTERED;
7976 +       }
7977 +       return IPT_CONTINUE;
7978 +}
7979 +
7980 +static int
7981 +checkentry(const char *tablename,
7982 +          const struct ipt_entry *e,
7983 +           void *targinfo,
7984 +           unsigned int targinfosize,
7985 +           unsigned int hook_mask)
7986 +{
7987 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
7988 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
7989 +                      targinfosize,
7990 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
7991 +               return 0;
7992 +       }
7993 +
7994 +       if (strcmp(tablename, "mangle") != 0) {
7995 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
7996 +               return 0;
7997 +       }
7998 +
7999 +       return 1;
8000 +}
8001 +
8002 +static struct ipt_target ipt_ipmark_reg = { 
8003 +       .name = "IPMARK",
8004 +       .target = target,
8005 +       .checkentry = checkentry,
8006 +       .me = THIS_MODULE
8007 +};
8008 +
8009 +static int __init init(void)
8010 +{
8011 +       return ipt_register_target(&ipt_ipmark_reg);
8012 +}
8013 +
8014 +static void __exit fini(void)
8015 +{
8016 +       ipt_unregister_target(&ipt_ipmark_reg);
8017 +}
8018 +
8019 +module_init(init);
8020 +module_exit(fini);
8021 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_ROUTE.c
8022 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c  1970-01-01 01:00:00.000000000 +0100
8023 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_ROUTE.c      2004-03-30 11:48:31.000000000 +0200
8024 @@ -0,0 +1,369 @@
8025 +/*
8026 + * This implements the ROUTE target, which enables you to setup unusual
8027 + * routes not supported by the standard kernel routing table.
8028 + *
8029 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
8030 + *
8031 + * v 1.8 2003/07/25
8032 + *
8033 + * This software is distributed under GNU GPL v2, 1991
8034 + */
8035 +
8036 +#include <linux/module.h>
8037 +#include <linux/skbuff.h>
8038 +#include <linux/ip.h>
8039 +#include <linux/netfilter_ipv4/ip_tables.h>
8040 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
8041 +#include <linux/netdevice.h>
8042 +#include <linux/route.h>
8043 +#include <net/ip.h>
8044 +#include <net/route.h>
8045 +#include <net/icmp.h>
8046 +
8047 +#if 0
8048 +#define DEBUGP printk
8049 +#else
8050 +#define DEBUGP(format, args...)
8051 +#endif
8052 +
8053 +MODULE_LICENSE("GPL");
8054 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
8055 +
8056 +/* Try to route the packet according to the routing keys specified in
8057 + * route_info. Keys are :
8058 + *  - ifindex : 
8059 + *      0 if no oif preferred, 
8060 + *      otherwise set to the index of the desired oif
8061 + *  - route_info->gw :
8062 + *      0 if no gateway specified,
8063 + *      otherwise set to the next host to which the pkt must be routed
8064 + * If success, skb->dev is the output device to which the packet must 
8065 + * be sent and skb->dst is not NULL
8066 + *
8067 + * RETURN: -1 if an error occured
8068 + *          1 if the packet was succesfully routed to the 
8069 + *            destination desired
8070 + *          0 if the kernel routing table could not route the packet
8071 + *            according to the keys specified
8072 + */
8073 +static int route(struct sk_buff *skb,
8074 +                unsigned int ifindex,
8075 +                const struct ipt_route_target_info *route_info)
8076 +{
8077 +       int err;
8078 +       struct rtable *rt;
8079 +       struct iphdr *iph = skb->nh.iph;
8080 +       struct rt_key key = { 
8081 +               dst:iph->daddr,
8082 +               src:0,
8083 +               oif:ifindex, 
8084 +               tos:RT_TOS(iph->tos) 
8085 +       };
8086 +       
8087 +       /* The destination address may be overloaded by the target */
8088 +       if (route_info->gw)
8089 +               key.dst = route_info->gw;
8090 +       
8091 +       /* Trying to route the packet using the standard routing table. */
8092 +       if ((err = ip_route_output_key(&rt, &key))) {
8093 +               if (net_ratelimit()) 
8094 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
8095 +               return -1;
8096 +       }
8097 +       
8098 +       /* Drop old route. */
8099 +       dst_release(skb->dst);
8100 +       skb->dst = NULL;
8101 +
8102 +       /* Success if no oif specified or if the oif correspond to the 
8103 +        * one desired */
8104 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
8105 +               skb->dst = &rt->u.dst;
8106 +               skb->dev = skb->dst->dev;
8107 +               return 1;
8108 +       }
8109 +       
8110 +       /* The interface selected by the routing table is not the one
8111 +        * specified by the user. This may happen because the dst address
8112 +        * is one of our own addresses.
8113 +        */
8114 +       if (net_ratelimit()) 
8115 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
8116 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
8117 +       
8118 +       return 0;
8119 +}
8120 +
8121 +
8122 +/* Stolen from ip_finish_output2
8123 + * PRE : skb->dev is set to the device we are leaving by
8124 + *       skb->dst is not NULL
8125 + * POST: the packet is sent with the link layer header pushed
8126 + *       the packet is destroyed
8127 + */
8128 +static void ip_direct_send(struct sk_buff *skb)
8129 +{
8130 +       struct dst_entry *dst = skb->dst;
8131 +       struct hh_cache *hh = dst->hh;
8132 +
8133 +       if (hh) {
8134 +               read_lock_bh(&hh->hh_lock);
8135 +               memcpy(skb->data - 16, hh->hh_data, 16);
8136 +               read_unlock_bh(&hh->hh_lock);
8137 +               skb_push(skb, hh->hh_len);
8138 +               hh->hh_output(skb);
8139 +       } else if (dst->neighbour)
8140 +               dst->neighbour->output(skb);
8141 +       else {
8142 +               if (net_ratelimit())
8143 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
8144 +               kfree_skb(skb);
8145 +       }
8146 +}
8147 +
8148 +
8149 +/* PRE : skb->dev is set to the device we are leaving by
8150 + * POST: - the packet is directly sent to the skb->dev device, without 
8151 + *         pushing the link layer header.
8152 + *       - the packet is destroyed
8153 + */
8154 +static inline int dev_direct_send(struct sk_buff *skb)
8155 +{
8156 +       return dev_queue_xmit(skb);
8157 +}
8158 +
8159 +
8160 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
8161 +                             struct sk_buff *skb) 
8162 +{
8163 +       unsigned int ifindex = 0;
8164 +       struct net_device *dev_out = NULL;
8165 +
8166 +       /* The user set the interface name to use.
8167 +        * Getting the current interface index.
8168 +        */
8169 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
8170 +               ifindex = dev_out->ifindex;
8171 +       } else {
8172 +               /* Unknown interface name : packet dropped */
8173 +               if (net_ratelimit()) 
8174 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
8175 +               return NF_DROP;
8176 +       }
8177 +
8178 +       /* Trying the standard way of routing packets */
8179 +       switch (route(skb, ifindex, route_info)) {
8180 +       case 1:
8181 +               dev_put(dev_out);
8182 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
8183 +                       return IPT_CONTINUE;
8184 +
8185 +               ip_direct_send(skb);
8186 +               return NF_STOLEN;
8187 +
8188 +       case 0:
8189 +               /* Failed to send to oif. Trying the hard way */
8190 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
8191 +                       return NF_DROP;
8192 +
8193 +               if (net_ratelimit()) 
8194 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
8195 +                              ifindex);
8196 +
8197 +               /* We have to force the use of an interface.
8198 +                * This interface must be a tunnel interface since
8199 +                * otherwise we can't guess the hw address for
8200 +                * the packet. For a tunnel interface, no hw address
8201 +                * is needed.
8202 +                */
8203 +               if ((dev_out->type != ARPHRD_TUNNEL)
8204 +                   && (dev_out->type != ARPHRD_IPGRE)) {
8205 +                       if (net_ratelimit()) 
8206 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
8207 +                       dev_put(dev_out);
8208 +                       return NF_DROP;
8209 +               }
8210 +       
8211 +               /* Send the packet. This will also free skb
8212 +                * Do not go through the POST_ROUTING hook because 
8213 +                * skb->dst is not set and because it will probably
8214 +                * get confused by the destination IP address.
8215 +                */
8216 +               skb->dev = dev_out;
8217 +               dev_direct_send(skb);
8218 +               dev_put(dev_out);
8219 +               return NF_STOLEN;
8220 +               
8221 +       default:
8222 +               /* Unexpected error */
8223 +               dev_put(dev_out);
8224 +               return NF_DROP;
8225 +       }
8226 +}
8227 +
8228 +
8229 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
8230 +                             struct sk_buff *skb) 
8231 +{
8232 +       struct net_device *dev_out = NULL;
8233 +       unsigned int ifindex = 0;
8234 +
8235 +       /* Getting the current interface index. */
8236 +       if ((dev_out = dev_get_by_name(route_info->iif)))
8237 +               ifindex = dev_out->ifindex;
8238 +       else {
8239 +               /* Unknown interface name : packet dropped */
8240 +               if (net_ratelimit()) 
8241 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
8242 +               return NF_DROP;
8243 +       }
8244 +
8245 +       skb->dev = dev_out;
8246 +       dst_release(skb->dst);
8247 +       skb->dst = NULL;
8248 +               
8249 +       netif_rx(skb);
8250 +
8251 +       return NF_STOLEN;
8252 +}
8253 +
8254 +
8255 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
8256 +                            struct sk_buff *skb) 
8257 +{
8258 +       if (route(skb, 0, route_info)!=1)
8259 +               return NF_DROP;
8260 +
8261 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
8262 +               return IPT_CONTINUE;
8263 +
8264 +       ip_direct_send(skb);
8265 +       return NF_STOLEN;
8266 +}
8267 +
8268 +
8269 +static unsigned int ipt_route_target(struct sk_buff **pskb,
8270 +                                    const struct net_device *in,
8271 +                                    const struct net_device *out,
8272 +                                    unsigned int hooknum,
8273 +                                    const void *targinfo,
8274 +                                    void *userinfo)
8275 +{
8276 +       const struct ipt_route_target_info *route_info = targinfo;
8277 +       struct sk_buff *skb = *pskb;
8278 +
8279 +       /* If we are at PREROUTING or INPUT hook
8280 +        * the TTL isn't decreased by the IP stack
8281 +        */
8282 +       if (hooknum == NF_IP_PRE_ROUTING ||
8283 +           hooknum == NF_IP_LOCAL_IN) {
8284 +
8285 +               struct iphdr *iph = skb->nh.iph;
8286 +
8287 +               if (iph->ttl <= 1) {
8288 +                       struct rtable *rt;
8289 +
8290 +                       if (ip_route_output(&rt, iph->saddr, iph->daddr,
8291 +                                           RT_TOS(iph->tos) | RTO_CONN,
8292 +                                           0)) {
8293 +                               return NF_DROP;
8294 +                       }
8295 +
8296 +                       if (skb->dev == rt->u.dst.dev) {
8297 +                               /* Drop old route. */
8298 +                               dst_release(skb->dst);
8299 +                               skb->dst = &rt->u.dst;
8300 +
8301 +                               /* this will traverse normal stack, and 
8302 +                                * thus call conntrack on the icmp packet */
8303 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
8304 +                                         ICMP_EXC_TTL, 0);
8305 +                       }
8306 +
8307 +                       return NF_DROP;
8308 +               }
8309 +
8310 +               ip_decrease_ttl(iph);
8311 +       }
8312 +
8313 +       /* Tell conntrack to forget this packet since it may get confused 
8314 +        * when a packet is leaving with dst address == our address.
8315 +        * Good idea ? Dunno. Need advice.
8316 +        */
8317 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
8318 +               nf_conntrack_put(skb->nfct);
8319 +               skb->nfct = NULL;
8320 +               skb->nfcache = 0;
8321 +#ifdef CONFIG_NETFILTER_DEBUG
8322 +               skb->nf_debug = 0;
8323 +#endif
8324 +       }
8325 +
8326 +       if (route_info->oif[0]) 
8327 +               return route_oif(route_info, *pskb);
8328 +       
8329 +       if (route_info->iif[0]) 
8330 +               return route_iif(route_info, *pskb);
8331 +
8332 +       if (route_info->gw) 
8333 +               return route_gw(route_info, *pskb);
8334 +
8335 +       if (net_ratelimit()) 
8336 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
8337 +
8338 +       return IPT_CONTINUE;
8339 +}
8340 +
8341 +
8342 +static int ipt_route_checkentry(const char *tablename,
8343 +                               const struct ipt_entry *e,
8344 +                               void *targinfo,
8345 +                               unsigned int targinfosize,
8346 +                               unsigned int hook_mask)
8347 +{
8348 +       if (strcmp(tablename, "mangle") != 0) {
8349 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
8350 +                      tablename);
8351 +               return 0;
8352 +       }
8353 +
8354 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
8355 +                           | (1 << NF_IP_LOCAL_IN)
8356 +                           | (1 << NF_IP_FORWARD)
8357 +                           | (1 << NF_IP_LOCAL_OUT)
8358 +                           | (1 << NF_IP_POST_ROUTING))) {
8359 +               printk("ipt_ROUTE: bad hook\n");
8360 +               return 0;
8361 +       }
8362 +
8363 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
8364 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
8365 +                      targinfosize,
8366 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
8367 +               return 0;
8368 +       }
8369 +
8370 +       return 1;
8371 +}
8372 +
8373 +
8374 +static struct ipt_target ipt_route_reg = { 
8375 +       .name = "ROUTE",
8376 +       .target = ipt_route_target,
8377 +       .checkentry = ipt_route_checkentry,
8378 +       .me = THIS_MODULE,
8379 +};
8380 +
8381 +static int __init init(void)
8382 +{
8383 +       return ipt_register_target(&ipt_route_reg);
8384 +}
8385 +
8386 +
8387 +static void __exit fini(void)
8388 +{
8389 +       ipt_unregister_target(&ipt_route_reg);
8390 +}
8391 +
8392 +module_init(init);
8393 +module_exit(fini);
8394 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TARPIT.c
8395 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
8396 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TARPIT.c     2004-03-30 11:50:27.000000000 +0200
8397 @@ -0,0 +1,287 @@
8398 +/* 
8399 + * Kernel module to capture and hold incoming TCP connections using 
8400 + * no local per-connection resources.
8401 + * 
8402 + * Based on ipt_REJECT.c and offering functionality similar to 
8403 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
8404 + * 
8405 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
8406 + * 
8407 + * This program is free software; you can redistribute it and/or modify
8408 + * it under the terms of the GNU General Public License as published by
8409 + * the Free Software Foundation; either version 2 of the License, or
8410 + * (at your option) any later version.
8411 + *
8412 + * This program is distributed in the hope that it will be useful,
8413 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8414 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8415 + * GNU General Public License for more details.
8416 + *
8417 + * You should have received a copy of the GNU General Public License
8418 + * along with this program; if not, write to the Free Software
8419 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8420 + * 
8421 + * Goal:
8422 + * - Allow incoming TCP connections to be established.
8423 + * - Passing data should result in the connection being switched to the 
8424 + *   persist state (0 byte window), in which the remote side stops sending 
8425 + *   data and asks to continue every 60 seconds.
8426 + * - Attempts to shut down the connection should be ignored completely, so 
8427 + *   the remote side ends up having to time it out.
8428 + *
8429 + * This means:
8430 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
8431 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
8432 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
8433 + */
8434 +
8435 +#include <linux/config.h>
8436 +#include <linux/module.h>
8437 +#include <linux/skbuff.h>
8438 +#include <linux/ip.h>
8439 +#include <net/ip.h>
8440 +#include <net/tcp.h>
8441 +#include <net/icmp.h>
8442 +struct in_device;
8443 +#include <net/route.h>
8444 +#include <linux/random.h>
8445 +#include <linux/netfilter_ipv4/ip_tables.h>
8446 +
8447 +#if 0
8448 +#define DEBUGP printk
8449 +#else
8450 +#define DEBUGP(format, args...)
8451 +#endif
8452 +
8453 +MODULE_LICENSE("GPL");
8454 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
8455 +
8456 +/* Stolen from ip_finish_output2 */
8457 +static int ip_direct_send(struct sk_buff *skb)
8458 +{
8459 +       struct dst_entry *dst = skb->dst;
8460 +       struct hh_cache *hh = dst->hh;
8461 +
8462 +       if (hh) {    
8463 +               read_lock_bh(&hh->hh_lock);
8464 +               memcpy(skb->data - 16, hh->hh_data, 16);
8465 +                read_unlock_bh(&hh->hh_lock);
8466 +                skb_push(skb, hh->hh_len);
8467 +                return hh->hh_output(skb);
8468 +        } else if (dst->neighbour)
8469 +                return dst->neighbour->output(skb);
8470 +
8471 +       if (net_ratelimit())
8472 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
8473 +        kfree_skb(skb);
8474 +        return -EINVAL;
8475 +}
8476 +
8477 +
8478 +/* Send reply */
8479 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
8480 +{
8481 +       struct sk_buff *nskb;
8482 +       struct rtable *nrt;
8483 +       struct tcphdr *otcph, *ntcph;
8484 +       unsigned int otcplen;
8485 +       u_int16_t tmp;
8486 +
8487 +       /* A truncated TCP header isn't going to be useful */
8488 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
8489 +               return;
8490 +
8491 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
8492 +                                  + oskb->nh.iph->ihl);
8493 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
8494 +
8495 +       /* No replies for RST or FIN */
8496 +       if (otcph->rst || otcph->fin)
8497 +               return;
8498 +
8499 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
8500 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
8501 +               return;
8502 +
8503 +       /* Check checksum. */
8504 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
8505 +                        oskb->nh.iph->daddr,
8506 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
8507 +               return;
8508 +
8509 +       /* Copy skb (even if skb is about to be dropped, we can't just
8510 +           clone it because there may be other things, such as tcpdump,
8511 +           interested in it) */
8512 +       nskb = skb_copy(oskb, GFP_ATOMIC);
8513 +       if (!nskb)
8514 +               return;
8515 +
8516 +       /* This packet will not be the same as the other: clear nf fields */
8517 +       nf_conntrack_put(nskb->nfct);
8518 +       nskb->nfct = NULL;
8519 +       nskb->nfcache = 0;
8520 +#ifdef CONFIG_NETFILTER_DEBUG
8521 +       nskb->nf_debug = 0;
8522 +#endif
8523 +
8524 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
8525 +
8526 +       /* Truncate to length (no data) */
8527 +       ntcph->doff = sizeof(struct tcphdr)/4;
8528 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
8529 +       nskb->nh.iph->tot_len = htons(nskb->len);
8530 +
8531 +       /* Swap source and dest */
8532 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
8533 +       tmp = ntcph->source;
8534 +       ntcph->source = ntcph->dest;
8535 +       ntcph->dest = tmp;
8536 +
8537 +       /* Use supplied sequence number or make a new one */
8538 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
8539 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
8540 +                                                       nskb->nh.iph->daddr, 
8541 +                                                       ntcph->source, 
8542 +                                                       ntcph->dest));
8543 +
8544 +       /* Our SYN-ACKs must have a >0 window */
8545 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
8546 +
8547 +       ntcph->urg_ptr = 0;
8548 +
8549 +       /* Reset flags */
8550 +       ((u_int8_t *)ntcph)[13] = 0;
8551 +
8552 +       if (otcph->syn && otcph->ack) {
8553 +               ntcph->rst = 1;
8554 +               ntcph->ack_seq = 0;
8555 +       } else {
8556 +               ntcph->syn = otcph->syn;
8557 +               ntcph->ack = 1;
8558 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
8559 +       }
8560 +
8561 +       /* Adjust TCP checksum */
8562 +       ntcph->check = 0;
8563 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
8564 +                                  nskb->nh.iph->saddr,
8565 +                                  nskb->nh.iph->daddr,
8566 +                                  csum_partial((char *)ntcph,
8567 +                                               sizeof(struct tcphdr), 0));
8568 +
8569 +       /* Adjust IP TTL */
8570 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
8571 +
8572 +       /* Set DF, id = 0 */
8573 +       nskb->nh.iph->frag_off = htons(IP_DF);
8574 +       nskb->nh.iph->id = 0;
8575 +
8576 +       /* Adjust IP checksum */
8577 +       nskb->nh.iph->check = 0;
8578 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
8579 +                                          nskb->nh.iph->ihl);
8580 +
8581 +       if (ip_route_output(&nrt, nskb->nh.iph->daddr, 
8582 +                           local ? nskb->nh.iph->saddr : 0,
8583 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN, 
8584 +                           0) != 0)
8585 +               goto free_nskb;
8586 +
8587 +       dst_release(nskb->dst);
8588 +       nskb->dst = &nrt->u.dst;
8589 +
8590 +       /* "Never happens" */
8591 +       if (nskb->len > nskb->dst->pmtu)
8592 +               goto free_nskb;
8593 +
8594 +       ip_direct_send (nskb);
8595 +
8596 +       return;
8597 +
8598 + free_nskb:
8599 +       kfree_skb(nskb);
8600 +}
8601 +
8602 +
8603 +static unsigned int tarpit(struct sk_buff **pskb,
8604 +                          const struct net_device *in,
8605 +                          const struct net_device *out,
8606 +                          unsigned int hooknum,
8607 +                          const void *targinfo,
8608 +                          void *userinfo)
8609 +{
8610 +       struct sk_buff *skb = *pskb;
8611 +       struct rtable *rt = (struct rtable*)skb->dst;
8612 +
8613 +       /* Do we have an input route cache entry? */
8614 +       if (!rt)
8615 +               return NF_DROP;
8616 +
8617 +        /* No replies to physical multicast/broadcast */
8618 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
8619 +               return NF_DROP;
8620 +
8621 +        /* Now check at the protocol level */
8622 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
8623 +                return NF_DROP;
8624 +
8625 +       /* Our naive response construction doesn't deal with IP
8626 +           options, and probably shouldn't try. */
8627 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
8628 +               return NF_DROP;
8629 +
8630 +        /* We aren't interested in fragments */
8631 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
8632 +                return NF_DROP;
8633 +
8634 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
8635 +
8636 +       return NF_DROP;
8637 +}
8638 +
8639 +
8640 +static int check(const char *tablename,
8641 +                const struct ipt_entry *e,
8642 +                void *targinfo,
8643 +                unsigned int targinfosize,
8644 +                unsigned int hook_mask)
8645 +{
8646 +       /* Only allow these for input/forward packet filtering. */
8647 +       if (strcmp(tablename, "filter") != 0) {
8648 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
8649 +               return 0;
8650 +       }
8651 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
8652 +                           | (1 << NF_IP_FORWARD))) != 0) {
8653 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
8654 +               return 0;
8655 +       }
8656 +
8657 +       /* Must specify that it's a TCP packet */
8658 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
8659 +               DEBUGP("TARPIT: not valid for non-tcp\n");
8660 +               return 0;
8661 +       }
8662 +
8663 +       return 1;
8664 +}
8665 +
8666 +static struct ipt_target ipt_tarpit_reg = { 
8667 +       .name = "TARPIT",
8668 +       .target = tarpit,
8669 +       .checkentry = check,
8670 +       .me = THIS_MODULE
8671 +};
8672 +
8673 +static int __init init(void)
8674 +{
8675 +       return ipt_register_target(&ipt_tarpit_reg);
8676 +}
8677 +
8678 +static void __exit fini(void)
8679 +{
8680 +       ipt_unregister_target(&ipt_tarpit_reg);
8681 +}
8682 +
8683 +module_init(init);
8684 +module_exit(fini);
8685 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TCPLAG.c
8686 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_TCPLAG.c 1970-01-01 01:00:00.000000000 +0100
8687 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_TCPLAG.c     2004-03-30 11:50:30.000000000 +0200
8688 @@ -0,0 +1,697 @@
8689 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
8690 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
8691 + *
8692 + * This program is free software; you can redistribute it and/or modify
8693 + * it under the terms of the GNU General Public License as published by
8694 + * the Free Software Foundation; either version 2 of the License, or
8695 + * (at your option) any later version.
8696 + *
8697 + * This program is distributed in the hope that it will be useful,
8698 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8699 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8700 + * GNU General Public License for more details.
8701 + *
8702 + * You should have received a copy of the GNU General Public License
8703 + * along with this program; if not, write to the Free Software
8704 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
8705 + */
8706 +
8707 +/*
8708 + * This collects packets and attempts to make them into pairs
8709 + * based on its own knowledge of how typical network conversations
8710 + * operate. Once it has a pair, it logs the time between them.
8711 + */
8712 +#include <linux/module.h>
8713 +#include <linux/skbuff.h>
8714 +#include <linux/ip.h>
8715 +#include <linux/spinlock.h>
8716 +#include <net/icmp.h>
8717 +#include <net/udp.h>
8718 +#include <net/tcp.h>
8719 +#include <linux/netfilter_ipv4/ip_tables.h>
8720 +
8721 +#include <net/route.h>
8722 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
8723 +
8724 +#if 0
8725 +#define DEBUGP printk
8726 +#else
8727 +#define DEBUGP(format, args...)
8728 +#endif
8729 +
8730 +/*
8731 + * We need one spinlock for the hash table.
8732 + */
8733 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
8734 +
8735 +typedef struct timeval timeval_T;
8736 +
8737 +/*
8738 + * Linked lists of events in the connection,
8739 + * these store the SEQ numbers and the newest is always
8740 + * at the start of the linked list, then they get older
8741 + * down to the end of the linked list (this is not perfect
8742 + * if packets get out of order but we don't worry about fine
8743 + * details like that).
8744 + *
8745 + * Matching any event wipes out that event and also all other
8746 + * events down the chain (i.e. all older events).
8747 + * This keeps the linked list as short as possible.
8748 + */
8749 +typedef struct tcplag_event_S
8750 +{
8751 +       struct tcplag_event_S *next;
8752 +       u16 source_port;
8753 +       u16 dest_port;
8754 +       u32 expected_ACK;
8755 +       struct timeval stamp;
8756 +} tcplag_event_T;
8757 +
8758 +/*
8759 + * This stores the connection statistics
8760 + * We define connections more loosely than TCP/IP does,
8761 + * because we only consider the two hosts, not the ports
8762 + * Also, we list the host-pairs in low,high order which
8763 + * means that we don't care who originated the connection.
8764 + */
8765 +typedef struct tcplag_hash_S
8766 +{
8767 +       u32 low_ip;
8768 +       u32 high_ip;
8769 +       struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
8770 +       struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
8771 +       tcplag_event_T *h_ACK_list;     /* Try to match ACK packets coming from h in this list */
8772 +       tcplag_event_T *l_ACK_list;     /* Try to match ACK packets coming from l in this list */
8773 +       time_t stamp;                   /* When this bucket got added to the table */
8774 +       u16 count_l_SEQ_h_ACK;          /* Increment for each event */
8775 +       u16 count_h_SEQ_l_ACK;          /* Increment for each event */
8776 +} tcplag_hash_T;
8777 +
8778 +static tcplag_hash_T **hashtab = 0;
8779 +static u32 hashsize = 0;
8780 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
8781 +static u32 reaper_ix = 0;
8782 +
8783 +static void divide_down( timeval_T *T, int c )
8784 +{
8785 +       int remainder;
8786 +
8787 +       T->tv_usec /= c;
8788 +       remainder = T->tv_sec % c; /* Only works properly with positive numbers */
8789 +       remainder *= 1000000;
8790 +       T->tv_usec == remainder;
8791 +       T->tv_sec /= c;
8792 +}
8793 +
8794 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
8795 +{
8796 +       register long x;
8797 +
8798 +       x = tv1->tv_sec - tv2->tv_sec;
8799 +       if( x ) return( x );
8800 +       x = tv1->tv_usec - tv2->tv_usec;
8801 +       return( x );
8802 +}
8803 +
8804 +void sprint_timeval( char *buf, timeval_T *tv )
8805 +{
8806 +       if( tv->tv_sec )
8807 +               sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
8808 +       else
8809 +               sprintf( buf, "%lu", tv->tv_usec );
8810 +}
8811 +
8812 +/*
8813 + * This generates the log messages through printk()
8814 + *
8815 + * There is really no particular interest in the port numbers at this stage,
8816 + * they are only useful for matching up the request with the reply.
8817 + * The IP numbers are useful because some sites may be slower than others
8818 + * or may travel different routes, etc (OK, in theory changing the port number
8819 + * could also change the route but I don't like that sort of theory).
8820 + *
8821 + * The tags are:
8822 + *
8823 + * LIP=          The IP number of the side with the lowest lag
8824 + * RIP=          The IP number of the side with the highest lag
8825 + * LLAG=         The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
8826 + * RLAG=         The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
8827 + */
8828 +static void output( tcplag_hash_T *H, int level, const char *prefix )
8829 +{
8830 +       struct timeval ltm, rtm;
8831 +       u32 local_ip, remote_ip;
8832 +       char r_buf[ 20 ], l_buf[ 20 ];
8833 +/*
8834 + * We can't make sense of a connection that only passes data one way,
8835 + * In principle, at least the SYN and FIN should go both ways so we
8836 + * should get a few hits for every connection.
8837 + */
8838 +       if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
8839 +/*
8840 + * Calculate average times by dividing down
8841 + */
8842 +       divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
8843 +       divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
8844 +/*
8845 + * Sort these two by the lag so the the local is always the short lag
8846 + */
8847 +       if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
8848 +       {
8849 +               local_ip    = H->low_ip;
8850 +               remote_ip   = H->high_ip;
8851 +               rtm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
8852 +               rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
8853 +               ltm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
8854 +               ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
8855 +       }
8856 +       else
8857 +       {
8858 +               local_ip    = H->high_ip;
8859 +               remote_ip   = H->low_ip;
8860 +               ltm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
8861 +               ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
8862 +               rtm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
8863 +               rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
8864 +       }
8865 +/*
8866 + * Don't use a spinlock on the output,
8867 + * it is not guaranteed safe because some OTHER printk could
8868 + * split our log message so we want only one single printk.
8869 + *
8870 + * We use sprintf() to partially pre-digest the output
8871 + *
8872 + * Actually, neither this not the main netfilter LOG target is
8873 + * really safe from printk() overlap, basically syslog cannot
8874 + * be regarded as a guaranteed data output channel. It is good
8875 + * enough for most purposes.
8876 + */
8877 +       sprint_timeval( l_buf, &ltm );
8878 +       sprint_timeval( r_buf, &rtm );
8879 +       printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
8880 +                       level & 7, prefix,
8881 +                       NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
8882 +                       l_buf, r_buf );
8883 +}
8884 +
8885 +/*
8886 + * The reaper rolls through the hash table looking for old.
8887 + * Log entries are only generated at the reaping time
8888 + * (which means all log entries are out-of-date)
8889 + */
8890 +static void reaper( time_t now, int level, const char *prefix )
8891 +{
8892 +       int i;
8893 +
8894 +       now -= max_seconds;
8895 +       if( !hashsize ) return;
8896 +       if( !hashtab ) return;
8897 +       for( i = 0; i < 10; i++ )
8898 +       {
8899 +               if( ++reaper_ix >= hashsize ) reaper_ix = 0; 
8900 +
8901 +//             DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
8902 +
8903 +               if( hashtab[ reaper_ix ])
8904 +               {
8905 +                       tcplag_hash_T *found = 0;
8906 +
8907 +                       spin_lock_bh( &hash_lock );
8908 +                       if( hashtab[ reaper_ix ])
8909 +                       {
8910 +                               if( now > hashtab[ reaper_ix ]->stamp )
8911 +                               {
8912 +                                       DEBUGP( KERN_WARNING "reaper found expired entry\n" );
8913 +                                       found = hashtab[ reaper_ix ];
8914 +                                       hashtab[ reaper_ix ] = 0;
8915 +                               }
8916 +                       }
8917 +                       spin_unlock_bh( &hash_lock );
8918 +
8919 +                       if( found )
8920 +                       {
8921 +                               output( found, level, prefix );
8922 +                               kfree( found );
8923 +                       }
8924 +               }
8925 +       }
8926 +}
8927 +
8928 +/*
8929 + * Convert the connection characteristics into a number
8930 + * (not including the timestamp) FIXME: this is a sucky hash function
8931 + */
8932 +static u32 make_hash( tcplag_hash_T *connection )
8933 +{
8934 +       register u32 r;
8935 +
8936 +       r = connection->low_ip;
8937 +       r += connection->high_ip;
8938 +       return( r );
8939 +}
8940 +
8941 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
8942 +{
8943 +       int x;
8944 +
8945 +       x = con1->low_ip - con2->low_ip; if( x ) return( x );
8946 +       x = con1->high_ip - con2->high_ip;
8947 +       return( x );
8948 +}
8949 +
8950 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
8951 +{
8952 +       int x;
8953 +
8954 +       DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
8955 +       x = ev1->expected_ACK - ev2->expected_ACK;
8956 +       if( x ) return( x );
8957 +       DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
8958 +       x = ev1->source_port - ev2->source_port;
8959 +       if( x ) return( x );
8960 +       DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
8961 +       x = ev1->dest_port - ev2->dest_port;
8962 +       return( x );
8963 +}
8964 +
8965 +/*
8966 + * Go to the hash table and either find an existing connection that
8967 + * matches correctly or inject a new connection into the table.
8968 + * Once the connection is OK, chain the event onto the linked list.
8969 + */
8970 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
8971 +{
8972 +       u32 h, i;
8973 +
8974 +       if( !event ) return; /* Just to be safe */
8975 +       if( !hashsize ) return;
8976 +       if( !hashtab ) return;
8977 +
8978 +       h = make_hash( connection );
8979 +       h %= hashsize;
8980 +
8981 +       DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
8982 +
8983 +       spin_lock_bh( &hash_lock );
8984 +       for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
8985 +       {
8986 +               tcplag_hash_T *co_new = 0;
8987 +/*
8988 + * Consider existing entry
8989 + */
8990 +               if( hashtab[ h ])
8991 +               {
8992 +                       if( compare_connections( hashtab[ h ], connection )) continue;
8993 +                       co_new = hashtab[ h ];
8994 +                       DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
8995 +                       goto add_link;
8996 +               }
8997 +/*
8998 + * Use empty slot for new entry
8999 + */
9000 +               if( !hashtab[ h ])
9001 +               {
9002 +                       co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
9003 +                       memset( co_new, 0, sizeof( tcplag_hash_T ));
9004 +                       co_new->low_ip = connection->low_ip;
9005 +                       co_new->high_ip = connection->high_ip;
9006 +                       co_new->stamp = event->stamp.tv_sec;
9007 +                       hashtab[ h ] = co_new;
9008 +                       DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
9009 + add_link:
9010 +                       {
9011 +                               tcplag_event_T *ev_new;
9012 +
9013 +                               ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
9014 +                               memcpy( ev_new, event, sizeof( tcplag_event_T ));
9015 +                               if( direction )
9016 +                               {
9017 +                                       ev_new->next = co_new->h_ACK_list;
9018 +                                       co_new->h_ACK_list = ev_new;
9019 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
9020 +                               }
9021 +                               else
9022 +                               {
9023 +                                       ev_new->next = co_new->l_ACK_list;
9024 +                                       co_new->l_ACK_list = ev_new;
9025 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
9026 +                               }
9027 +                       }
9028 +                       goto done;
9029 +               }
9030 +       }
9031 + done:
9032 +       spin_unlock_bh( &hash_lock );
9033 +}
9034 +
9035 +/*
9036 + * Search the hash table for a matching connection,
9037 + * if we can't find one of those then we are stuffed.
9038 + *
9039 + * Once a connection has been found, scan along the list for
9040 + * a matching SEQ number and if that is found then calculate
9041 + * the lag, update the counters and cut the chain at the
9042 + * point where the matching SEQ is found.
9043 + */
9044 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
9045 +{
9046 +       u32 h, i;
9047 +
9048 +       if( !event ) return( 0 );
9049 +       if( !hashsize ) return( 0 );
9050 +       if( !hashtab ) return( 0 );
9051 +       h = make_hash( connection );
9052 +       h %= hashsize;
9053 +
9054 +       DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
9055 +
9056 +       for( i = 0; i < hashsize; i++ )
9057 +       {
9058 +               tcplag_hash_T *found = 0;
9059 +
9060 +               if( !hashtab[ h ]) return( 0 );
9061 +
9062 +               spin_lock_bh( &hash_lock );
9063 +               if( hashtab[ h ])
9064 +               {
9065 +                       if( !compare_connections( hashtab[ h ], connection ))
9066 +                       {
9067 +                               tcplag_event_T *ev, **evroot;
9068 +                               timeval_T *tv;
9069 +                               u16 *cn;
9070 +
9071 +                               found = hashtab[ h ];
9072 +                               if( direction )
9073 +                               {
9074 +                                       evroot = &found->h_ACK_list;
9075 +                                       tv = &found->lag_l_SEQ_h_ACK;
9076 +                                       cn = &found->count_l_SEQ_h_ACK;
9077 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
9078 +                               }
9079 +                               else
9080 +                               {
9081 +                                       evroot = &found->l_ACK_list;
9082 +                                       tv = &found->lag_h_SEQ_l_ACK;
9083 +                                       cn = &found->count_h_SEQ_l_ACK;
9084 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
9085 +                               }
9086 +                               for( ev = *evroot; ev; ev = ev->next )
9087 +                               {
9088 +                                       if( !compare_events( ev, event ))
9089 +                                       {
9090 +/*
9091 + * Calculate the lag (in two parts) and add that to the collection
9092 + */
9093 +                                               event->stamp.tv_sec -= ev->stamp.tv_sec;
9094 +                                               event->stamp.tv_usec -= ev->stamp.tv_usec;
9095 +                                               if( event->stamp.tv_usec < 0 )
9096 +                                               {
9097 +                                                       event->stamp.tv_usec += 1000000;
9098 +                                                       event->stamp.tv_sec++;
9099 +                                               }
9100 +                                               if( event->stamp.tv_sec < 0 )
9101 +                                               {
9102 +                                                       DEBUGP( KERN_WARNING "Negative lag detected\n" );
9103 +                                               }
9104 +                                               else
9105 +                                               {
9106 +                                                       tv->tv_sec += event->stamp.tv_sec;
9107 +                                                       tv->tv_usec += event->stamp.tv_usec;
9108 +                                                       ++*cn;
9109 +                                                       DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
9110 +                                                                       " (accumulator is up to %lu.%06lu, %u events)\n",
9111 +                                                                       event->stamp.tv_sec,
9112 +                                                                       event->stamp.tv_usec,
9113 +                                                                       tv->tv_sec, tv->tv_usec, *cn );
9114 +                                               }
9115 +/*
9116 + * Truncate the linked list.
9117 + *
9118 + * Visit each event in the list and return the memory to the pool.
9119 + *
9120 + * If a host is making multiple connections to the same remote host
9121 + * then this truncation will result in some requests not being
9122 + * monitored. Statistically we will still get some reasonable number
9123 + * of measurements and multiple simultaneous connections between host
9124 + * pairs don't happen all that often.
9125 + */
9126 +                                               *evroot = 0;
9127 +                                               while( ev )
9128 +                                               {
9129 +                                                       tcplag_event_T *ev_next = ev->next;
9130 +                                                       DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
9131 +                                                       kfree( ev );
9132 +                                                       ev = ev_next;
9133 +                                               }
9134 +/*
9135 + * TODO: overflow limit for *cn, force premature output() if necessary
9136 + * (and drop this connection from the hash table)
9137 + */
9138 +                                               break;
9139 +                                       }
9140 +                               }
9141 +                               goto done;
9142 +                       }
9143 +               }
9144 + done:
9145 +               spin_unlock_bh( &hash_lock );
9146 +
9147 +               if( found ) return( 1 );
9148 +               if( ++h >= hashsize ) h = 0;
9149 +       }       
9150 +       return( 0 );
9151 +}
9152 +
9153 +/*
9154 + * Here is our target data:
9155 + *
9156 + * pskb      --  The packet itself (see linux/skbuff.h for breakdown)
9157 + *
9158 + * hooknum   --
9159 + *
9160 + * in        --  The device that this packet came in on
9161 + *               (depending on the chain this may or may not exist)
9162 + *
9163 + * out       --  The device that this packet is just about to go
9164 + *               out onto (again existance depends on the chain)
9165 + *
9166 + * targinfo  --  Our private data (handed through from iptables command util)
9167 + *
9168 + * userinfo  --  Some more data
9169 + *
9170 + */
9171 +
9172 +static unsigned int target( struct sk_buff **pskb,
9173 +                                                       unsigned int hooknum,
9174 +                                                       const struct net_device *in,
9175 +                                                       const struct net_device *out,
9176 +                                                       const void *targinfo,
9177 +                                                       void *userinfo )
9178 +{
9179 +       struct iphdr *iph = ( *pskb )->nh.iph;
9180 +       const struct ipt_tcplag *el = targinfo;
9181 +       tcplag_hash_T connection;
9182 +       tcplag_event_T event;
9183 +       int direction;
9184 +/*
9185 + * We know we are dealing with IP here
9186 + * Fill in all the obvious fields
9187 + */
9188 +       if( iph->saddr > iph->daddr )
9189 +       {
9190 +               direction = 0;
9191 +               connection.high_ip = iph->saddr;
9192 +               connection.low_ip = iph->daddr;
9193 +       }
9194 +       else
9195 +       {
9196 +               direction = 1;
9197 +               connection.low_ip = iph->saddr;
9198 +               connection.high_ip = iph->daddr;
9199 +       }
9200 +       do_gettimeofday( &event.stamp );
9201 +/*
9202 + * Do a bit of cleaning
9203 + */
9204 +       reaper( event.stamp.tv_sec, el->level, el->prefix );
9205 +
9206 +       DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
9207 +                       event.stamp.tv_sec,
9208 +                       event.stamp.tv_usec,
9209 +                       in ? in->name : "none", out ? out->name : "none" );
9210 +/*
9211 + * Now start looking at the details
9212 + *
9213 + * First step is to identify this packet to see if it is 
9214 + * the sort of packet that we are interested in.
9215 + * Don't hold any locks while we are doing this because often
9216 + * we will just let the packet go without any further consideration.
9217 + */
9218 +       switch( iph->protocol )
9219 +       {
9220 +               case IPPROTO_TCP:
9221 +               {
9222 +                       struct tcphdr *tcp;
9223 +
9224 +                       if( ntohs( iph->frag_off ) & IP_OFFSET )
9225 +                       {
9226 +                               DEBUGP( KERN_WARNING "ignoring fragment\n" );
9227 +                               break;
9228 +                       }
9229 +                       tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
9230 +                       event.source_port = ntohs( tcp->source );
9231 +                       event.dest_port = ntohs( tcp->dest );
9232 +/*
9233 + * Every packet should have a valid SEQ number so use this to
9234 + * generate an ACK number. This works along the formula:
9235 + * -- Start with the SEQ number
9236 + * -- For SYN or FIN add 1 to that number
9237 + * -- For data packet, add the data length to that number
9238 + */
9239 +
9240 +/*
9241 + * Data length requires a bit of fiddling around
9242 + */
9243 +                       {
9244 +                               unsigned int data_len;
9245 +                               if( tcp->syn || tcp->fin )
9246 +                               {
9247 +                                       data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
9248 +                               }
9249 +                               else
9250 +                               {
9251 +                                       data_len = ntohs( iph->tot_len );
9252 +                                       data_len -= 4 * iph->ihl;  /* Subtract away IP header & options */
9253 +                                       data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
9254 +                               }
9255 +                               
9256 +                               DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
9257 +
9258 +                               if( data_len ) /* Only track events that demand an ACK */
9259 +                               {
9260 +                                       event.expected_ACK = ntohl( tcp->seq ) + data_len;
9261 +                                       hash_insert( &connection, &event, direction );
9262 +                               }
9263 +                               else
9264 +                               {
9265 +                                       DEBUGP( "Don't bother to insert this, ACK not required\n" );
9266 +                               }
9267 +                       }
9268 +
9269 +                       if( tcp->ack )
9270 +                       {
9271 +/*
9272 + * Now we consider the matching of an existing event.
9273 + * Reverse the port numbers and change the ACK number to the actual ACK number
9274 + * Note that the direction is reversed because the reply will be going
9275 + * the opposite way to the request.
9276 + */
9277 +                               event.expected_ACK = ntohl( tcp->ack_seq );
9278 +                               event.dest_port = ntohs( tcp->source );
9279 +                               event.source_port = ntohs( tcp->dest );
9280 +                               request_complete( &connection, &event, !direction );
9281 +                       }
9282 +                       else
9283 +                       {
9284 +                               DEBUGP( "Don't bother to check this, ACK not valid\n" );
9285 +                       }
9286 +               }
9287 +       }
9288 +       return( IPT_CONTINUE );
9289 +}
9290 +
9291 +/*
9292 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
9293 + * return( 1 ) if the entry is suitable
9294 + *
9295 + * tablename     --  
9296 + *
9297 + * e             --  
9298 + *
9299 + * targinfo      --  Our private data block (handed to us from iptables plug-in)
9300 + *
9301 + * targinfosize  --  The size of our private data block
9302 + *
9303 + * hook_mask     --  
9304 + *
9305 + *
9306 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
9307 + * all possible flag combos make sense. All we check for is correct data size.
9308 + */
9309 +static int checkentry( const char *tablename,
9310 +                                          const struct ipt_entry *e,
9311 +                                          void *targinfo,
9312 +                                          unsigned int targinfosize,
9313 +                                          unsigned int hook_mask )
9314 +{
9315 +       const struct ipt_tcplag *el = targinfo;
9316 +
9317 +       if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
9318 +       {
9319 +               DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
9320 +                               IPT_ALIGN( sizeof( struct ipt_tcplag )));
9321 +               return( 0 );
9322 +       }
9323 +       if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
9324 +       return( 1 );
9325 +}
9326 +
9327 +static struct ipt_target reg =
9328 +{
9329 +       { 0, 0 },
9330 +       "TCPLAG",
9331 +       &target,
9332 +       &checkentry,
9333 +       0,
9334 +    THIS_MODULE
9335 +};
9336 +
9337 +static int __init init( void )
9338 +{
9339 +       if( ipt_register_target( &reg )) return( -EINVAL );
9340 +       hashsize = 123; /* should be configurable */
9341 +       hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
9342 +       memset( hashtab, 0, sizeof( void * ) * hashsize );
9343 +       return( 0 );
9344 +}
9345 +
9346 +/*
9347 + * This should not need locks (in theory)
9348 + * because it can only get punted after it is no longer
9349 + * chained into any of the netfilter lists.
9350 + */
9351 +static void __exit fini( void )
9352 +{
9353 +       int i;
9354 +
9355 +       ipt_unregister_target( &reg );
9356 +/*
9357 + * Put back kernel memory
9358 + */
9359 +       for( i = 0; i < hashsize; i++ )
9360 +       {
9361 +               tcplag_hash_T *p;
9362 +
9363 +               if(( p = hashtab[ i ]))
9364 +               {
9365 +                       tcplag_event_T *ev, *evn;
9366 +
9367 +                       hashtab[ i ] = 0;
9368 +                       for( ev = p->h_ACK_list; ev; ev = evn )
9369 +                       {
9370 +                               evn = ev->next;
9371 +                               kfree( ev );
9372 +                       }
9373 +                       for( ev = p->l_ACK_list; ev; ev = evn )
9374 +                       {
9375 +                               evn = ev->next;
9376 +                               kfree( ev );
9377 +                       }
9378 +                       kfree( p );
9379 +               }
9380 +       }
9381 +       kfree( hashtab );
9382 +}
9383 +
9384 +module_init(init);
9385 +module_exit(fini);
9386 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_XOR.c
9387 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_XOR.c    1970-01-01 01:00:00.000000000 +0100
9388 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_XOR.c        2004-03-30 11:50:41.000000000 +0200
9389 @@ -0,0 +1,117 @@
9390 +/* XOR target for IP tables
9391 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9392 + * Based on ipt_TTL.c
9393 + *
9394 + * Version 1.0
9395 + *
9396 + * This software is distributed under the terms of GNU GPL
9397 + */
9398 +
9399 +#include <linux/module.h>
9400 +#include <linux/skbuff.h>
9401 +#include <linux/ip.h>
9402 +#include <linux/tcp.h>
9403 +#include <linux/udp.h>
9404 +
9405 +#include <linux/netfilter_ipv4/ip_tables.h>
9406 +#include <linux/netfilter_ipv4/ipt_XOR.h>
9407 +
9408 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9409 +MODULE_DESCRIPTION("IP tables XOR module");
9410 +MODULE_LICENSE("GPL");
9411 +
9412 +static unsigned int 
9413 +ipt_xor_target(struct sk_buff **pskb, 
9414 +               const struct net_device *in, const struct net_device *out, 
9415 +               unsigned int hooknum, const void *targinfo, void *userinfo)
9416 +{
9417 +       struct ipt_XOR_info *info = (void *) targinfo;
9418 +       struct iphdr *iph;
9419 +       struct tcphdr *tcph;
9420 +       struct udphdr *udph;
9421 +       int i, j, k;
9422 +
9423 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
9424 +               return NF_DROP;
9425 +
9426 +       iph = (*pskb)->nh.iph;
9427 +  
9428 +       if (iph->protocol == IPPROTO_TCP) {
9429 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9430 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9431 +                       for (k=0; k<=info->block_size; k++) {
9432 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
9433 +                                               info->key[j];
9434 +                               i++;
9435 +                       }
9436 +                       j++;
9437 +                       if (info->key[j] == 0x00)
9438 +                               j = 0;
9439 +               }
9440 +       } else if (iph->protocol == IPPROTO_UDP) {
9441 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9442 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9443 +                       for (k=0; k<=info->block_size; k++) {
9444 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
9445 +                                               info->key[j];
9446 +                               i++;
9447 +                       }
9448 +                       j++;
9449 +                       if (info->key[j] == 0x00)
9450 +                               j = 0;
9451 +               }
9452 +       }
9453 +  
9454 +       return IPT_CONTINUE;
9455 +}
9456 +
9457 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9458 +               void *targinfo, unsigned int targinfosize, 
9459 +               unsigned int hook_mask)
9460 +{
9461 +       struct ipt_XOR_info *info = targinfo;
9462 +
9463 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9464 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
9465 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9466 +               return 0;
9467 +       }       
9468 +
9469 +       if (strcmp(tablename, "mangle")) {
9470 +               printk(KERN_WARNING "XOR: can only be called from"
9471 +                               "\"mangle\" table, not \"%s\"\n", tablename);
9472 +               return 0; 
9473 +       }
9474 +
9475 +       if (!strcmp(info->key, "")) {
9476 +               printk(KERN_WARNING "XOR: You must specify a key");
9477 +               return 0;
9478 +       }
9479 +
9480 +       if (info->block_size == 0) {
9481 +               printk(KERN_WARNING "XOR: You must specify a block-size");
9482 +               return 0;
9483 +       }
9484 +
9485 +       return 1;
9486 +}
9487 +
9488 +static struct ipt_target ipt_XOR = { 
9489 +       .name = "XOR",
9490 +       .target = ipt_xor_target, 
9491 +       .checkentry = ipt_xor_checkentry,
9492 +       .me = THIS_MODULE,
9493 +};
9494 +
9495 +static int __init init(void)
9496 +{
9497 +       return ipt_register_target(&ipt_XOR);
9498 +}
9499 +
9500 +static void __exit fini(void)
9501 +{
9502 +       ipt_unregister_target(&ipt_XOR);
9503 +}
9504 +
9505 +module_init(init);
9506 +module_exit(fini);
9507 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_addrtype.c
9508 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_addrtype.c       1970-01-01 01:00:00.000000000 +0100
9509 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_addrtype.c   2004-03-30 11:50:44.000000000 +0200
9510 @@ -0,0 +1,68 @@
9511 +/*
9512 + *  iptables module to match inet_addr_type() of an ip.
9513 + */
9514 +
9515 +#include <linux/module.h>
9516 +#include <linux/skbuff.h>
9517 +#include <linux/netdevice.h>
9518 +#include <net/route.h>
9519 +
9520 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
9521 +#include <linux/netfilter_ipv4/ip_tables.h>
9522 +
9523 +MODULE_LICENSE("GPL");
9524 +
9525 +static inline int match_type(u_int32_t addr, u_int16_t mask)
9526 +{
9527 +       return !!(mask & (1 << inet_addr_type(addr)));
9528 +}
9529 +
9530 +static int match(const struct sk_buff *skb, const struct net_device *in,
9531 +                const struct net_device *out, const void *matchinfo,
9532 +                int offset, int *hotdrop)
9533 +{
9534 +       const struct ipt_addrtype_info *info = matchinfo;
9535 +       const struct iphdr *iph = skb->nh.iph;
9536 +       int ret = 1;
9537 +
9538 +       if (info->source)
9539 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
9540 +       if (info->dest)
9541 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9542 +       
9543 +       return ret;
9544 +}
9545 +
9546 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9547 +                     void *matchinfo, unsigned int matchsize,
9548 +                     unsigned int hook_mask)
9549 +{
9550 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9551 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9552 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9553 +               return 0;
9554 +       }
9555 +
9556 +       return 1;
9557 +}
9558 +
9559 +static struct ipt_match addrtype_match = { 
9560 +       .name = "addrtype",
9561 +       .match = match,
9562 +       .checkentry = checkentry,
9563 +       .me = THIS_MODULE
9564 +};
9565 +
9566 +static int __init init(void)
9567 +{
9568 +       return ipt_register_match(&addrtype_match);
9569 +}
9570 +
9571 +static void __exit fini(void)
9572 +{
9573 +       ipt_unregister_match(&addrtype_match);
9574 +
9575 +}
9576 +
9577 +module_init(init);
9578 +module_exit(fini);
9579 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_condition.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_condition.c
9580 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_condition.c      1970-01-01 01:00:00.000000000 +0100
9581 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_condition.c  2004-03-30 11:50:47.000000000 +0200
9582 @@ -0,0 +1,256 @@
9583 +/*-------------------------------------------*\
9584 +|          Netfilter Condition Module         |
9585 +|                                             |
9586 +|  Description: This module allows firewall   |
9587 +|    rules to match using condition variables |
9588 +|    stored in /proc files.                   |
9589 +|                                             |
9590 +|  Author: Stephane Ouellette     2002-10-22  |
9591 +|          <ouellettes@videotron.ca>          |
9592 +|                                             |
9593 +|  History:                                   |
9594 +|    2003-02-10  Second version with improved |
9595 +|                locking and simplified code. |
9596 +|                                             |
9597 +|  This software is distributed under the     |
9598 +|  terms of the GNU GPL.                      |
9599 +\*-------------------------------------------*/
9600 +
9601 +#include<linux/module.h>
9602 +#include<linux/proc_fs.h>
9603 +#include<linux/spinlock.h>
9604 +#include<linux/string.h>
9605 +#include<asm/atomic.h>
9606 +#include<linux/netfilter_ipv4/ip_tables.h>
9607 +#include<linux/netfilter_ipv4/ipt_condition.h>
9608 +
9609 +
9610 +#ifndef CONFIG_PROC_FS
9611 +#error  "Proc file system support is required for this module"
9612 +#endif
9613 +
9614 +
9615 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
9616 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
9617 +MODULE_LICENSE("GPL");
9618 +
9619 +
9620 +struct condition_variable {
9621 +       struct condition_variable *next;
9622 +       struct proc_dir_entry *status_proc;
9623 +       atomic_t refcount;
9624 +        int enabled;   /* TRUE == 1, FALSE == 0 */
9625 +};
9626 +
9627 +
9628 +static rwlock_t list_lock;
9629 +static struct condition_variable *head = NULL;
9630 +static struct proc_dir_entry *proc_net_condition = NULL;
9631 +
9632 +
9633 +static int
9634 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
9635 +                       int length, int *eof, void *data)
9636 +{
9637 +       struct condition_variable *var =
9638 +           (struct condition_variable *) data;
9639 +
9640 +       if (offset == 0) {
9641 +               *start = buffer;
9642 +               buffer[0] = (var->enabled) ? '1' : '0';
9643 +               buffer[1] = '\n';
9644 +               return 2;
9645 +       }
9646 +
9647 +       *eof = 1;
9648 +       return 0;
9649 +}
9650 +
9651 +
9652 +static int
9653 +ipt_condition_write_info(struct file *file, const char *buffer,
9654 +                        unsigned long length, void *data)
9655 +{
9656 +       struct condition_variable *var =
9657 +           (struct condition_variable *) data;
9658 +
9659 +       if (length) {
9660 +               /* Match only on the first character */
9661 +               switch (buffer[0]) {
9662 +               case '0':
9663 +                       var->enabled = 0;
9664 +                       break;
9665 +               case '1':
9666 +                       var->enabled = 1;
9667 +               }
9668 +       }
9669 +
9670 +       return (int) length;
9671 +}
9672 +
9673 +
9674 +static int
9675 +match(const struct sk_buff *skb, const struct net_device *in,
9676 +      const struct net_device *out, const void *matchinfo, int offset,
9677 +      const void *hdr, u_int16_t datalen, int *hotdrop)
9678 +{
9679 +       const struct condition_info *info =
9680 +           (const struct condition_info *) matchinfo;
9681 +       struct condition_variable *var;
9682 +       int condition_status = 0;
9683 +
9684 +       read_lock(&list_lock);
9685 +
9686 +       for (var = head; var; var = var->next) {
9687 +               if (strcmp(info->name, var->status_proc->name) == 0) {
9688 +                       condition_status = var->enabled;
9689 +                       break;
9690 +               }
9691 +       }
9692 +
9693 +       read_unlock(&list_lock);
9694 +
9695 +       return condition_status ^ info->invert;
9696 +}
9697 +
9698 +
9699 +
9700 +static int
9701 +checkentry(const char *tablename, const struct ipt_ip *ip,
9702 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
9703 +{
9704 +       struct condition_info *info = (struct condition_info *) matchinfo;
9705 +       struct condition_variable *var, *newvar;
9706 +
9707 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
9708 +               return 0;
9709 +
9710 +       /* The first step is to check if the condition variable already exists. */
9711 +       /* Here, a read lock is sufficient because we won't change the list */
9712 +       read_lock(&list_lock);
9713 +
9714 +       for (var = head; var; var = var->next) {
9715 +               if (strcmp(info->name, var->status_proc->name) == 0) {
9716 +                       atomic_inc(&var->refcount);
9717 +                       read_unlock(&list_lock);
9718 +                       return 1;
9719 +               }
9720 +       }
9721 +
9722 +       read_unlock(&list_lock);
9723 +
9724 +       /* At this point, we need to allocate a new condition variable */
9725 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
9726 +
9727 +       if (!newvar)
9728 +               return -ENOMEM;
9729 +
9730 +       /* Create the condition variable's proc file entry */
9731 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
9732 +
9733 +       if (!newvar->status_proc) {
9734 +         /*
9735 +          * There are two possibilities:
9736 +          *  1- Another condition variable with the same name has been created, which is valid.
9737 +          *  2- There was a memory allocation error.
9738 +          */
9739 +               kfree(newvar);
9740 +               read_lock(&list_lock);
9741 +
9742 +               for (var = head; var; var = var->next) {
9743 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
9744 +                               atomic_inc(&var->refcount);
9745 +                               read_unlock(&list_lock);
9746 +                               return 1;
9747 +                       }
9748 +               }
9749 +
9750 +               read_unlock(&list_lock);
9751 +               return -ENOMEM;
9752 +       }
9753 +
9754 +       atomic_set(&newvar->refcount, 1);
9755 +       newvar->enabled = 0;
9756 +       newvar->status_proc->owner = THIS_MODULE;
9757 +       newvar->status_proc->data = newvar;
9758 +       wmb();
9759 +       newvar->status_proc->read_proc = ipt_condition_read_info;
9760 +       newvar->status_proc->write_proc = ipt_condition_write_info;
9761 +
9762 +       write_lock(&list_lock);
9763 +
9764 +       newvar->next = head;
9765 +       head = newvar;
9766 +
9767 +       write_unlock(&list_lock);
9768 +
9769 +       return 1;
9770 +}
9771 +
9772 +
9773 +static void
9774 +destroy(void *matchinfo, unsigned int matchsize)
9775 +{
9776 +       struct condition_info *info = (struct condition_info *) matchinfo;
9777 +       struct condition_variable *var, *prev = NULL;
9778 +
9779 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
9780 +               return;
9781 +
9782 +       write_lock(&list_lock);
9783 +
9784 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
9785 +            prev = var, var = var->next);
9786 +
9787 +       if (var && atomic_dec_and_test(&var->refcount)) {
9788 +               if (prev)
9789 +                       prev->next = var->next;
9790 +               else
9791 +                       head = var->next;
9792 +
9793 +               write_unlock(&list_lock);
9794 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
9795 +               kfree(var);
9796 +       } else
9797 +               write_unlock(&list_lock);
9798 +}
9799 +
9800 +
9801 +static struct ipt_match condition_match = {
9802 +       .name = "condition",
9803 +       .match = &match,
9804 +       .checkentry = &checkentry,
9805 +       .destroy = &destroy,
9806 +       .me = THIS_MODULE
9807 +};
9808 +
9809 +
9810 +static int __init
9811 +init(void)
9812 +{
9813 +       int errorcode;
9814 +
9815 +       rwlock_init(&list_lock);
9816 +       proc_net_condition = proc_mkdir("ipt_condition", proc_net);
9817 +
9818 +       if (proc_net_condition) {
9819 +               errorcode = ipt_register_match(&condition_match);
9820 +
9821 +               if (errorcode)
9822 +                       remove_proc_entry("ipt_condition", proc_net);
9823 +       } else
9824 +               errorcode = -EACCES;
9825 +
9826 +       return errorcode;
9827 +}
9828 +
9829 +
9830 +static void __exit
9831 +fini(void)
9832 +{
9833 +       ipt_unregister_match(&condition_match);
9834 +       remove_proc_entry("ipt_condition", proc_net);
9835 +}
9836 +
9837 +module_init(init);
9838 +module_exit(fini);
9839 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_connmark.c
9840 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_connmark.c       1970-01-01 01:00:00.000000000 +0100
9841 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_connmark.c   2004-03-30 11:48:14.000000000 +0200
9842 @@ -0,0 +1,81 @@
9843 +/* This kernel module matches connection mark values set by the
9844 + * CONNMARK target
9845 + *
9846 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9847 + * by Henrik Nordstrom <hno@marasystems.com>
9848 + *
9849 + * This program is free software; you can redistribute it and/or modify
9850 + * it under the terms of the GNU General Public License as published by
9851 + * the Free Software Foundation; either version 2 of the License, or
9852 + * (at your option) any later version.
9853 + *
9854 + * This program is distributed in the hope that it will be useful,
9855 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9856 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9857 + * GNU General Public License for more details.
9858 + *
9859 + * You should have received a copy of the GNU General Public License
9860 + * along with this program; if not, write to the Free Software
9861 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
9862 + */
9863 +
9864 +#include <linux/module.h>
9865 +#include <linux/skbuff.h>
9866 +
9867 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9868 +MODULE_DESCRIPTION("IP tables connmark match module");
9869 +MODULE_LICENSE("GPL");
9870 +
9871 +#include <linux/netfilter_ipv4/ip_tables.h>
9872 +#include <linux/netfilter_ipv4/ipt_connmark.h>
9873 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9874 +
9875 +static int
9876 +match(const struct sk_buff *skb,
9877 +      const struct net_device *in,
9878 +      const struct net_device *out,
9879 +      const void *matchinfo,
9880 +      int offset,
9881 +      int *hotdrop)
9882 +{
9883 +       const struct ipt_connmark_info *info = matchinfo;
9884 +       enum ip_conntrack_info ctinfo;
9885 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
9886 +       if (!ct)
9887 +               return 0;
9888 +
9889 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
9890 +}
9891 +
9892 +static int
9893 +checkentry(const char *tablename,
9894 +          const struct ipt_ip *ip,
9895 +          void *matchinfo,
9896 +          unsigned int matchsize,
9897 +          unsigned int hook_mask)
9898 +{
9899 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
9900 +               return 0;
9901 +
9902 +       return 1;
9903 +}
9904 +
9905 +static struct ipt_match connmark_match = {
9906 +       .name = "connmark",
9907 +       .match = &match,
9908 +       .checkentry = &checkentry,
9909 +       .me = THIS_MODULE
9910 +};
9911 +
9912 +static int __init init(void)
9913 +{
9914 +       return ipt_register_match(&connmark_match);
9915 +}
9916 +
9917 +static void __exit fini(void)
9918 +{
9919 +       ipt_unregister_match(&connmark_match);
9920 +}
9921 +
9922 +module_init(init);
9923 +module_exit(fini);
9924 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_helper.c
9925 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-03-30 11:31:19.000000000 +0200
9926 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_helper.c     2004-03-30 11:51:07.000000000 +0200
9927 @@ -71,8 +71,11 @@
9928         DEBUGP("master's name = %s , info->name = %s\n", 
9929                 exp->expectant->helper->name, info->name);
9930  
9931 -       ret ^= !strncmp(exp->expectant->helper->name, info->name, 
9932 -                       strlen(exp->expectant->helper->name));
9933 +       if (info->name[0] == '\0')
9934 +               ret ^= 1;
9935 +       else
9936 +               ret ^= !strncmp(exp->expectant->helper->name, info->name, 
9937 +                               strlen(exp->expectant->helper->name));
9938  out_unlock:
9939         READ_UNLOCK(&ip_conntrack_lock);
9940         return ret;
9941 @@ -92,10 +95,6 @@
9942         if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
9943                 return 0;
9944  
9945 -       /* verify that we actually should match anything */
9946 -       if ( strlen(info->name) == 0 )
9947 -               return 0;
9948 -       
9949         return 1;
9950  }
9951  
9952 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_owner.c
9953 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_owner.c  2004-03-30 05:27:17.000000000 +0200
9954 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_owner.c      2004-03-30 11:51:33.000000000 +0200
9955 @@ -6,12 +6,19 @@
9956   * This program is free software; you can redistribute it and/or modify
9957   * it under the terms of the GNU General Public License version 2 as
9958   * published by the Free Software Foundation.
9959 + *
9960 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
9961   */
9962  
9963  #include <linux/module.h>
9964  #include <linux/skbuff.h>
9965  #include <linux/file.h>
9966 +#include <linux/ip.h>
9967 +#include <linux/tcp.h>
9968 +#include <linux/udp.h>
9969  #include <net/sock.h>
9970 +#include <net/tcp.h>
9971 +#include <net/udp.h>
9972  
9973  #include <linux/netfilter_ipv4/ipt_owner.h>
9974  #include <linux/netfilter_ipv4/ip_tables.h>
9975 @@ -21,7 +28,7 @@
9976  MODULE_DESCRIPTION("iptables owner match");
9977  
9978  static int
9979 -match_comm(const struct sk_buff *skb, const char *comm)
9980 +match_comm(const struct sock *sk, const char *comm)
9981  {
9982         struct task_struct *g, *p;
9983         struct files_struct *files;
9984 @@ -38,7 +45,7 @@
9985                         spin_lock(&files->file_lock);
9986                         for (i=0; i < files->max_fds; i++) {
9987                                 if (fcheck_files(files, i) ==
9988 -                                   skb->sk->sk_socket->file) {
9989 +                                   sk->sk_socket->file) {
9990                                         spin_unlock(&files->file_lock);
9991                                         task_unlock(p);
9992                                         read_unlock(&tasklist_lock);
9993 @@ -54,7 +61,7 @@
9994  }
9995  
9996  static int
9997 -match_pid(const struct sk_buff *skb, pid_t pid)
9998 +match_pid(const struct sock *sk, pid_t pid)
9999  {
10000         struct task_struct *p;
10001         struct files_struct *files;
10002 @@ -70,7 +77,7 @@
10003                 spin_lock(&files->file_lock);
10004                 for (i=0; i < files->max_fds; i++) {
10005                         if (fcheck_files(files, i) ==
10006 -                           skb->sk->sk_socket->file) {
10007 +                           sk->sk_socket->file) {
10008                                 spin_unlock(&files->file_lock);
10009                                 task_unlock(p);
10010                                 read_unlock(&tasklist_lock);
10011 @@ -86,10 +93,10 @@
10012  }
10013  
10014  static int
10015 -match_sid(const struct sk_buff *skb, pid_t sid)
10016 +match_sid(const struct sock *sk, pid_t sid)
10017  {
10018         struct task_struct *g, *p;
10019 -       struct file *file = skb->sk->sk_socket->file;
10020 +       struct file *file = sk->sk_socket->file;
10021         int i, found=0;
10022  
10023         read_lock(&tasklist_lock);
10024 @@ -129,41 +136,71 @@
10025        int *hotdrop)
10026  {
10027         const struct ipt_owner_info *info = matchinfo;
10028 +       struct iphdr *iph = skb->nh.iph;
10029 +       struct sock *sk = NULL;
10030 +       int ret = 0;
10031 +
10032 +       if (out) {
10033 +               sk = skb->sk;
10034 +       } else {
10035 +               if (iph->protocol == IPPROTO_TCP) {
10036 +                       struct tcphdr *tcph =
10037 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
10038 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
10039 +                                          iph->daddr, tcph->dest,
10040 +                                          skb->dev->ifindex);
10041 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
10042 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
10043 +                               return ret;
10044 +                       }
10045 +               } else if (iph->protocol == IPPROTO_UDP) {
10046 +                       struct udphdr *udph =
10047 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
10048 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
10049 +                                          udph->dest, skb->dev->ifindex);
10050 +               }
10051 +       }
10052  
10053 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
10054 -               return 0;
10055 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
10056 +               goto out;
10057  
10058         if(info->match & IPT_OWNER_UID) {
10059 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
10060 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
10061                     !!(info->invert & IPT_OWNER_UID))
10062 -                       return 0;
10063 +                       goto out;
10064         }
10065  
10066         if(info->match & IPT_OWNER_GID) {
10067 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
10068 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
10069                     !!(info->invert & IPT_OWNER_GID))
10070 -                       return 0;
10071 +                       goto out;
10072         }
10073  
10074         if(info->match & IPT_OWNER_PID) {
10075 -               if (!match_pid(skb, info->pid) ^
10076 +               if (!match_pid(sk, info->pid) ^
10077                     !!(info->invert & IPT_OWNER_PID))
10078 -                       return 0;
10079 +                       goto out;
10080         }
10081  
10082         if(info->match & IPT_OWNER_SID) {
10083 -               if (!match_sid(skb, info->sid) ^
10084 +               if (!match_sid(sk, info->sid) ^
10085                     !!(info->invert & IPT_OWNER_SID))
10086 -                       return 0;
10087 +                       goto out;
10088         }
10089  
10090         if(info->match & IPT_OWNER_COMM) {
10091 -               if (!match_comm(skb, info->comm) ^
10092 +               if (!match_comm(sk, info->comm) ^
10093                     !!(info->invert & IPT_OWNER_COMM))
10094 -                       return 0;
10095 +                       goto out;
10096         }
10097  
10098 -       return 1;
10099 +       ret = 1;
10100 +
10101 +out:
10102 +       if (in && sk)
10103 +               sock_put(sk);
10104 +
10105 +       return ret;
10106  }
10107  
10108  static int
10109 @@ -173,11 +210,19 @@
10110             unsigned int matchsize,
10111             unsigned int hook_mask)
10112  {
10113 -        if (hook_mask
10114 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
10115 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
10116 -                return 0;
10117 -        }
10118 +       if (hook_mask
10119 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
10120 +           (1 << NF_IP_LOCAL_IN))) {
10121 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
10122 +                      "or POST_ROUTING.\n");
10123 +               return 0;
10124 +       }
10125 +
10126 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
10127 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
10128 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
10129 +               return 0;
10130 +       }
10131  
10132         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
10133                 printk("Matchsize %u != %Zu\n", matchsize,
10134 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_policy.c
10135 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
10136 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_policy.c     2004-03-30 11:51:40.000000000 +0200
10137 @@ -0,0 +1,176 @@
10138 +/* IP tables module for matching IPsec policy
10139 + *
10140 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
10141 + *
10142 + * This program is free software; you can redistribute it and/or modify
10143 + * it under the terms of the GNU General Public License version 2 as
10144 + * published by the Free Software Foundation.
10145 + */
10146 +
10147 +#include <linux/kernel.h>
10148 +#include <linux/config.h>
10149 +#include <linux/module.h>
10150 +#include <linux/skbuff.h>
10151 +#include <linux/init.h>
10152 +#include <net/xfrm.h>
10153 +
10154 +#include <linux/netfilter_ipv4.h>
10155 +#include <linux/netfilter_ipv4/ipt_policy.h>
10156 +#include <linux/netfilter_ipv4/ip_tables.h>
10157 +
10158 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
10159 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
10160 +MODULE_LICENSE("GPL");
10161 +
10162 +
10163 +static inline int
10164 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
10165 +{
10166 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
10167 +
10168 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
10169 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
10170 +           MISMATCH(proto, x->id.proto) ||
10171 +           MISMATCH(mode, x->props.mode) ||
10172 +           MISMATCH(spi, x->id.spi) ||
10173 +           MISMATCH(reqid, x->props.reqid))
10174 +               return 0;
10175 +       return 1;
10176 +}
10177 +
10178 +static int
10179 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
10180 +{
10181 +       const struct ipt_policy_elem *e;
10182 +       struct sec_path *sp = skb->sp;
10183 +       int strict = info->flags & POLICY_MATCH_STRICT;
10184 +       int i, pos;
10185 +
10186 +       if (sp == NULL)
10187 +               return -1;
10188 +       if (strict && info->len != sp->len)
10189 +               return 0;
10190 +
10191 +       for (i = sp->len - 1; i >= 0; i--) {
10192 +               pos = strict ? i - sp->len + 1 : 0;
10193 +               if (pos >= info->len)
10194 +                       return 0;
10195 +               e = &info->pol[pos];
10196 +
10197 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
10198 +                       if (!strict)
10199 +                               return 1;
10200 +               } else if (strict)
10201 +                       return 0;
10202 +       }
10203 +
10204 +       return strict ? 1 : 0;
10205 +}
10206 +
10207 +static int
10208 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
10209 +{
10210 +       const struct ipt_policy_elem *e;
10211 +       struct dst_entry *dst = skb->dst;
10212 +       int strict = info->flags & POLICY_MATCH_STRICT;
10213 +       int i, pos;
10214 +
10215 +       if (dst->xfrm == NULL)
10216 +               return -1;
10217 +
10218 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
10219 +               pos = strict ? i : 0;
10220 +               if (pos >= info->len)
10221 +                       return 0;
10222 +               e = &info->pol[pos];
10223 +
10224 +               if (match_xfrm_state(dst->xfrm, e)) {
10225 +                       if (!strict)
10226 +                               return 1;
10227 +               } else if (strict)
10228 +                       return 0;
10229 +       }
10230 +
10231 +       return strict ? 1 : 0;
10232 +}
10233 +
10234 +static int match(const struct sk_buff *skb,
10235 +                 const struct net_device *in,
10236 +                 const struct net_device *out,
10237 +                 const void *matchinfo, int offset, int *hotdrop)
10238 +{
10239 +       const struct ipt_policy_info *info = matchinfo;
10240 +       int ret;
10241 +
10242 +       if (info->flags & POLICY_MATCH_IN)
10243 +               ret = match_policy_in(skb, info);
10244 +       else
10245 +               ret = match_policy_out(skb, info);
10246 +
10247 +       if (ret < 0) {
10248 +               if (info->flags & POLICY_MATCH_NONE)
10249 +                       ret = 1;
10250 +               else
10251 +                       ret = 0;
10252 +       } else if (info->flags & POLICY_MATCH_NONE)
10253 +               ret = 0;
10254 +
10255 +       return ret;
10256 +}
10257 +
10258 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
10259 +                      void *matchinfo, unsigned int matchsize,
10260 +                      unsigned int hook_mask)
10261 +{
10262 +       struct ipt_policy_info *info = matchinfo;
10263 +
10264 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
10265 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
10266 +                      matchsize, IPT_ALIGN(sizeof(*info)));
10267 +               return 0;
10268 +       }
10269 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
10270 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
10271 +                               "outgoing policy selected\n");
10272 +               return 0;
10273 +       }
10274 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
10275 +           && info->flags & POLICY_MATCH_OUT) {
10276 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
10277 +                               "PRE_ROUTING and INPUT\n");
10278 +               return 0;
10279 +       }
10280 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
10281 +           && info->flags & POLICY_MATCH_IN) {
10282 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
10283 +                               "POST_ROUTING and OUTPUT\n");
10284 +               return 0;
10285 +       }
10286 +       if (info->len > POLICY_MAX_ELEM) {
10287 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
10288 +               return 0;
10289 +       }
10290 +
10291 +       return 1;
10292 +}
10293 +
10294 +static struct ipt_match policy_match =
10295 +{
10296 +       .name           = "policy",
10297 +       .match          = match,
10298 +       .checkentry     = checkentry,
10299 +       .me             = THIS_MODULE,
10300 +};
10301 +
10302 +static int __init init(void)
10303 +{
10304 +       return ipt_register_match(&policy_match);
10305 +}
10306 +
10307 +static void __exit fini(void)
10308 +{
10309 +       ipt_unregister_match(&policy_match);
10310 +}
10311 +
10312 +module_init(init);
10313 +module_exit(fini);
10314 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_rpc.c
10315 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_rpc.c    1970-01-01 01:00:00.000000000 +0100
10316 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_rpc.c        2004-03-30 11:51:55.000000000 +0200
10317 @@ -0,0 +1,428 @@
10318 +/* RPC extension for IP connection matching, Version 2.2
10319 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
10320 + *     - original rpc tracking module
10321 + *     - "recent" connection handling for kernel 2.3+ netfilter
10322 + *
10323 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
10324 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
10325 + *
10326 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
10327 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
10328 + *     - extended matching to support filtering on procedures
10329 + *
10330 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
10331 + *
10332 + *     This program is free software; you can redistribute it and/or
10333 + *     modify it under the terms of the GNU General Public License
10334 + *     as published by the Free Software Foundation; either version
10335 + *     2 of the License, or (at your option) any later version.
10336 + **
10337 + *     Module load syntax:
10338 + *     insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
10339 + *
10340 + *     Please give the ports of all RPC servers you wish to connect to.
10341 + *     If you don't specify ports, the default will be port 111.
10342 + **
10343 + *     Note to all:
10344 + *
10345 + *     RPCs should not be exposed to the internet - ask the Pentagon;
10346 + *
10347 + *       "The unidentified crackers pleaded guilty in July to charges
10348 + *        of juvenile delinquency stemming from a string of Pentagon
10349 + *        network intrusions in February.
10350 + *
10351 + *        The youths, going by the names TooShort and Makaveli, used
10352 + *        a common server security hole to break in, according to
10353 + *        Dane Jasper, owner of the California Internet service
10354 + *        provider, Sonic. They used the hole, known as the 'statd'
10355 + *        exploit, to attempt more than 800 break-ins, Jasper said."
10356 + *
10357 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
10358 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
10359 + **
10360 + */
10361 +
10362 +#include <linux/module.h>
10363 +#include <linux/skbuff.h>
10364 +#include <linux/list.h>
10365 +#include <linux/udp.h>
10366 +#include <linux/tcp.h>
10367 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10368 +#include <linux/netfilter_ipv4/ip_tables.h>
10369 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
10370 +#include <linux/netfilter_ipv4/lockhelp.h>
10371 +#include <linux/netfilter_ipv4/ipt_rpc.h>
10372 +
10373 +#define MAX_PORTS 8
10374 +static int ports[MAX_PORTS];
10375 +static int ports_n_c = 0;
10376 +
10377 +#ifdef MODULE_PARM
10378 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
10379 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
10380 +#endif
10381 +
10382 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
10383 +MODULE_DESCRIPTION("RPC connection matching module");
10384 +MODULE_LICENSE("GPL");
10385 +
10386 +#if 0
10387 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
10388 +                                       format, ## args)
10389 +#else
10390 +#define DEBUGP(format, args...)
10391 +#endif
10392 +
10393 +EXPORT_NO_SYMBOLS;
10394 +
10395 +/* vars from ip_conntrack_rpc_tcp */
10396 +extern struct list_head request_p_list_tcp;
10397 +extern struct module *ip_conntrack_rpc_tcp;
10398 +
10399 +/* vars from ip_conntrack_rpc_udp */
10400 +extern struct list_head request_p_list_udp;
10401 +extern struct module *ip_conntrack_rpc_udp;
10402 +
10403 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
10404 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
10405 +
10406 +#define ASSERT_READ_LOCK(x)                                    \
10407 +do {                                                           \
10408 +       if (x == &request_p_list_udp)                           \
10409 +               MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);        \
10410 +       else if (x == &request_p_list_tcp)                      \
10411 +               MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);        \
10412 +} while (0)
10413 +
10414 +#define ASSERT_WRITE_LOCK(x)                                   \
10415 +do {                                                           \
10416 +       if (x == &request_p_list_udp)                           \
10417 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);       \
10418 +       else if (x == &request_p_list_tcp)                      \
10419 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);       \
10420 +} while (0)
10421 +
10422 +#include <linux/netfilter_ipv4/listhelp.h>
10423 +
10424 +const int IPT_RPC_CHAR_LEN = 11;
10425 +
10426 +
10427 +static int k_atoi(char *string)
10428 +{
10429 +       unsigned int result = 0;
10430 +       int maxoctet = IPT_RPC_CHAR_LEN;
10431 +
10432 +       for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
10433 +               if (*string < 0)
10434 +                       return(0);
10435 +               if (*string == 0)
10436 +                       break;
10437 +               if (*string < 48 || *string > 57) {
10438 +                       return(0);
10439 +               }
10440 +               result = result * 10 + ( *string - 48 );
10441 +       }
10442 +       return(result);
10443 +}
10444 +
10445 +
10446 +static int match_rpcs(char *c_procs, int i_procs, int proc)
10447 +{
10448 +       int   proc_ctr;
10449 +       char *proc_ptr;
10450 +       unsigned int proc_num;
10451 +
10452 +       DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
10453 +
10454 +       if (i_procs == -1)
10455 +               return 1;
10456 +
10457 +       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
10458 +
10459 +               proc_ptr = c_procs;
10460 +               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
10461 +               proc_num = k_atoi(proc_ptr);
10462 +
10463 +               if (proc_num == proc)
10464 +                       return 1;
10465 +       }
10466 +
10467 +       return 0;
10468 +}
10469 +
10470 +
10471 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
10472 +                       int *hotdrop, int dir, struct ip_conntrack *ct,
10473 +                       int offset, struct list_head request_p_list)
10474 +{
10475 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
10476 +       struct request_p *req_p;
10477 +       u_int32_t xid;
10478 +
10479 +
10480 +       /* Get XID */
10481 +       xid = *data;
10482 +
10483 +       /* This does sanity checking on RPC payloads,
10484 +        * and permits only the RPC "get port" (3)
10485 +        * in authorised procedures in client
10486 +        * communications with the portmapper.
10487 +        */
10488 +
10489 +       data += 5;
10490 +
10491 +       /* Get RPC requestor */
10492 +       if (IXDR_GET_INT32(data) != 3) {
10493 +               DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
10494 +               if(rpcinfo->strict == 1)
10495 +                       *hotdrop = 1;
10496 +               return 0;
10497 +       }
10498 +       DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
10499 +
10500 +       data++;
10501 +
10502 +       /* Jump Credentials and Verfifier */
10503 +       data = data + IXDR_GET_INT32(data) + 2;
10504 +       data = data + IXDR_GET_INT32(data) + 2;
10505 +
10506 +       /* Get RPC procedure */
10507 +       if (match_rpcs((char *)&rpcinfo->c_procs,
10508 +           rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
10509 +               DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
10510 +                       (unsigned int)IXDR_GET_INT32(data));
10511 +
10512 +               /* If the RPC conntrack half entry already exists .. */
10513 +
10514 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
10515 +                       case IPPROTO_UDP:
10516 +                               WRITE_LOCK(&ipct_rpc_udp_lock);
10517 +                       case IPPROTO_TCP:
10518 +                               WRITE_LOCK(&ipct_rpc_tcp_lock);
10519 +               }
10520 +               req_p = LIST_FIND(&request_p_list, request_p_cmp,
10521 +                                 struct request_p *, xid,
10522 +                                 ct->tuplehash[dir].tuple.src.ip,
10523 +                                 ct->tuplehash[dir].tuple.src.u.all);
10524 +
10525 +               if (req_p) {
10526 +                       DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10527 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
10528 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10529 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
10530 +
10531 +                       /* .. remove it */
10532 +                       if (del_timer(&req_p->timeout))
10533 +                               req_p->timeout.expires = 0;
10534 +
10535 +                               LIST_DELETE(&request_p_list, req_p);
10536 +                       DEBUGP("RPC req_p removed. [done]\n");
10537 +
10538 +               } else {
10539 +                       DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10540 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
10541 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10542 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
10543 +
10544 +               }
10545 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
10546 +                       case IPPROTO_UDP:
10547 +                               WRITE_UNLOCK(&ipct_rpc_udp_lock);
10548 +                       case IPPROTO_TCP:
10549 +                               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
10550 +               }
10551 +
10552 +               if(rpcinfo->strict == 1)
10553 +                       *hotdrop = 1;
10554 +               return 0;
10555 +       }
10556 +
10557 +       DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
10558 +               (unsigned int)IXDR_GET_INT32(data));
10559 +       return (1 && (!offset));
10560 +}
10561 +
10562 +
10563 +static int match(const struct sk_buff *skb, const struct net_device *in,
10564 +                const struct net_device *out, const void *matchinfo,
10565 +                int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
10566 +{
10567 +       struct ip_conntrack *ct;
10568 +       enum ip_conntrack_info ctinfo;
10569 +       const u_int32_t *data;
10570 +       enum ip_conntrack_dir dir;
10571 +       const struct tcphdr *tcp;
10572 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
10573 +       int port, portsok;
10574 +       int tval;
10575 +
10576 +
10577 +       DEBUGP("new packet to evaluate ..\n");
10578 +
10579 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10580 +       if (!ct) {
10581 +               DEBUGP("no ct available [skip]\n");
10582 +               return 0;
10583 +       }
10584 +
10585 +       DEBUGP("ct detected. [cont]\n");
10586 +       dir = CTINFO2DIR(ctinfo);
10587 +
10588 +       /* we only want the client to server packets for matching */
10589 +       if (dir != IP_CT_DIR_ORIGINAL)
10590 +               return 0;
10591 +
10592 +       /* This does sanity checking on UDP or TCP packets,
10593 +        * like their respective modules.
10594 +        */
10595 +
10596 +       switch (ct->tuplehash[0].tuple.dst.protonum) {
10597 +
10598 +               case IPPROTO_UDP:
10599 +                       DEBUGP("PROTO_UDP [cont]\n");
10600 +                       if (offset == 0 && datalen < sizeof(struct udphdr)) {
10601 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
10602 +                               return 0;
10603 +                       }
10604 +
10605 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
10606 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10607 +                                       portsok++;
10608 +                                       break;
10609 +                               }
10610 +                       }
10611 +                       if (portsok == 0) {
10612 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10613 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10614 +                               return 0;
10615 +                       }
10616 +
10617 +                       if ((datalen - sizeof(struct udphdr)) != 56) {
10618 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
10619 +                               if (rpcinfo->strict == 1)
10620 +                                       *hotdrop = 1;
10621 +                               return 0;
10622 +                       }
10623 +                       DEBUGP("packet length is correct. [cont]\n");
10624 +
10625 +                       /* Get to the data */
10626 +                       data = (const u_int32_t *)hdr + 2;
10627 +
10628 +                       /* Check the RPC data */
10629 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
10630 +                                               dir, ct, offset,
10631 +                                               request_p_list_udp);
10632 +
10633 +                       return tval;
10634 +                       
10635 +               
10636 +               case IPPROTO_TCP:
10637 +                       DEBUGP("PROTO_TCP [cont]\n");
10638 +                       if (offset == 0 && datalen < sizeof(struct tcphdr)) {
10639 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
10640 +                               return 0;
10641 +                       }
10642 +       
10643 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
10644 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10645 +                                       portsok++;
10646 +                                       break;
10647 +                               }
10648 +                       }
10649 +                       if (portsok == 0) {
10650 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10651 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10652 +                               return 0;
10653 +                       }
10654 +
10655 +                       tcp = hdr;
10656 +                       if (datalen == (tcp->doff * 4)) {
10657 +                               DEBUGP("packet does not contain any data. [match]\n");
10658 +                               return (1 && (!offset));
10659 +                       }
10660 +
10661 +                       /* Tests if packet len is ok */
10662 +                       if ((datalen - (tcp->doff * 4)) != 60) {
10663 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
10664 +                               if(rpcinfo->strict == 1)
10665 +                                       *hotdrop = 1;
10666 +                               return 0;
10667 +                       }
10668 +                       DEBUGP("packet length is correct. [cont]\n");
10669 +
10670 +                       /* Get to the data */
10671 +                       data = (const u_int32_t *)tcp + tcp->doff + 1;  
10672 +
10673 +                       /* Check the RPC data */
10674 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
10675 +                                               dir, ct, offset,
10676 +                                               request_p_list_tcp);
10677 +
10678 +                       return tval;
10679 +
10680 +       }
10681 +
10682 +       DEBUGP("transport protocol=%u, is not supported [skip]\n",
10683 +               ct->tuplehash[0].tuple.dst.protonum);
10684 +       return 0;
10685 +}
10686 +
10687 +
10688 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
10689 +                  unsigned int matchsize, unsigned int hook_mask)
10690 +{
10691 +       if (hook_mask
10692 +           & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
10693 +               | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
10694 +               printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
10695 +               return 0;
10696 +       }
10697 +
10698 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
10699 +               return 0;
10700 +
10701 +       return 1;
10702 +}
10703 +
10704 +
10705 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
10706 +                                       &match, &checkentry, NULL,
10707 +                                       THIS_MODULE };
10708 +
10709 +
10710 +static int __init init(void)
10711 +{
10712 +       int port;
10713 +
10714 +       DEBUGP("incrementing usage counts\n");
10715 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
10716 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
10717 +
10718 +       /* If no port given, default to standard RPC port */
10719 +       if (ports[0] == 0)
10720 +               ports[0] = RPC_PORT;
10721 +
10722 +       DEBUGP("registering match [%s] for;\n", rpc_match.name);
10723 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
10724 +               DEBUGP("  port %i (UDP|TCP);\n", ports[port]);
10725 +               ports_n_c++;
10726 +       }
10727 +       
10728 +       return ipt_register_match(&rpc_match);
10729 +}
10730 +
10731 +
10732 +static void fini(void)
10733 +{
10734 +       DEBUGP("unregistering match\n");
10735 +       ipt_unregister_match(&rpc_match);
10736 +
10737 +       DEBUGP("decrementing usage counts\n");
10738 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
10739 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
10740 +}
10741 +
10742 +
10743 +module_init(init);
10744 +module_exit(fini);
10745 +
10746 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.5-rc3/net/ipv4/netfilter/ipt_string.c
10747 --- linux-2.6.5-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
10748 +++ linux-2.6.5-rc3/net/ipv4/netfilter/ipt_string.c     2004-03-30 11:52:56.000000000 +0200
10749 @@ -0,0 +1,218 @@
10750 +/* Kernel module to match a string into a packet.
10751 + *
10752 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
10753 + * 
10754 + * ChangeLog
10755 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
10756 + *             Fixed SMP re-entrancy problem using per-cpu data areas
10757 + *             for the skip/shift tables.
10758 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10759 + *             Fixed kernel panic, due to overrunning boyer moore string
10760 + *             tables. Also slightly tweaked heuristic for deciding what
10761 + *             search algo to use.
10762 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10763 + *             Implemented Boyer Moore Sublinear search algorithm
10764 + *             alongside the existing linear search based on memcmp().
10765 + *             Also a quick check to decide which method to use on a per
10766 + *             packet basis.
10767 + */
10768 +
10769 +#include <linux/smp.h>
10770 +#include <linux/module.h>
10771 +#include <linux/skbuff.h>
10772 +#include <linux/file.h>
10773 +#include <net/sock.h>
10774 +
10775 +#include <linux/netfilter_ipv4/ip_tables.h>
10776 +#include <linux/netfilter_ipv4/ipt_string.h>
10777 +
10778 +MODULE_LICENSE("GPL");
10779 +
10780 +struct string_per_cpu {
10781 +       int *skip;
10782 +       int *shift;
10783 +       int *len;
10784 +};
10785 +
10786 +struct string_per_cpu *bm_string_data=NULL;
10787 +
10788 +/* Boyer Moore Sublinear string search - VERY FAST */
10789 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
10790 +{
10791 +       int M1, right_end, sk, sh;  
10792 +       int ended, j, i;
10793 +
10794 +       int *skip, *shift, *len;
10795 +       
10796 +       /* use data suitable for this CPU */
10797 +       shift=bm_string_data[smp_processor_id()].shift;
10798 +       skip=bm_string_data[smp_processor_id()].skip;
10799 +       len=bm_string_data[smp_processor_id()].len;
10800 +       
10801 +       /* Setup skip/shift tables */
10802 +       M1 = right_end = needle_len-1;
10803 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
10804 +       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
10805 +
10806 +       for (i = 1; i < needle_len; i++) {   
10807 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
10808 +               len[i] = j;  
10809 +       }  
10810 +
10811 +       shift[0] = 1;  
10812 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
10813 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
10814 +       ended = 0;  
10815 +       
10816 +       for (i = 0; i < needle_len; i++) {  
10817 +               if (len[i] == M1 - i) ended = i;  
10818 +               if (ended) shift[i] = ended;  
10819 +       }  
10820 +
10821 +       /* Do the search*/  
10822 +       while (right_end < haystack_len)
10823 +       {
10824 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
10825 +               if (i == needle_len) {
10826 +                       return haystack+(right_end - M1);
10827 +               }
10828 +               
10829 +               sk = skip[haystack[right_end - i]];  
10830 +               sh = shift[i];
10831 +               right_end = max(right_end - i + sk, right_end + sh);  
10832 +       }
10833 +
10834 +       return NULL;
10835 +}  
10836 +
10837 +/* Linear string search based on memcmp() */
10838 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
10839 +{
10840 +       char *k = haystack + (haystack_len-needle_len);
10841 +       char *t = haystack;
10842 +       
10843 +       while ( t <= k ) {
10844 +               if (memcmp(t, needle, needle_len) == 0)
10845 +                       return t;
10846 +               t++;
10847 +       }
10848 +
10849 +       return NULL;
10850 +}
10851 +
10852 +
10853 +static int
10854 +match(const struct sk_buff *skb,
10855 +      const struct net_device *in,
10856 +      const struct net_device *out,
10857 +      const void *matchinfo,
10858 +      int offset,
10859 +      const void *hdr,
10860 +      u_int16_t datalen,
10861 +      int *hotdrop)
10862 +{
10863 +       const struct ipt_string_info *info = matchinfo;
10864 +       struct iphdr *ip = skb->nh.iph;
10865 +       int hlen, nlen;
10866 +       char *needle, *haystack;
10867 +       proc_ipt_search search=search_linear;
10868 +
10869 +       if ( !ip ) return 0;
10870 +
10871 +       /* get lenghts, and validate them */
10872 +       nlen=info->len;
10873 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
10874 +       if ( nlen > hlen ) return 0;
10875 +
10876 +       needle=(char *)&info->string;
10877 +       haystack=(char *)ip+(ip->ihl*4);
10878 +
10879 +       /* The sublinear search comes in to its own
10880 +        * on the larger packets */
10881 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
10882 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
10883 +               if ( hlen < BM_MAX_HLEN ) {
10884 +                       search=search_sublinear;
10885 +               }else{
10886 +                       if (net_ratelimit())
10887 +                               printk(KERN_INFO "ipt_string: Packet too big "
10888 +                                       "to attempt sublinear string search "
10889 +                                       "(%d bytes)\n", hlen );
10890 +               }
10891 +       }
10892 +       
10893 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
10894 +}
10895 +
10896 +static int
10897 +checkentry(const char *tablename,
10898 +           const struct ipt_ip *ip,
10899 +           void *matchinfo,
10900 +           unsigned int matchsize,
10901 +           unsigned int hook_mask)
10902 +{
10903 +
10904 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
10905 +               return 0;
10906 +
10907 +       return 1;
10908 +}
10909 +
10910 +void string_freeup_data(void)
10911 +{
10912 +       int c;
10913 +       
10914 +       if ( bm_string_data ) {
10915 +               for(c=0; c<smp_num_cpus; c++) {
10916 +                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
10917 +                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
10918 +                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
10919 +               }
10920 +               kfree(bm_string_data);
10921 +       }
10922 +}
10923 +
10924 +static struct ipt_match string_match
10925 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
10926 +
10927 +static int __init init(void)
10928 +{
10929 +       int c;
10930 +       size_t tlen;
10931 +       size_t alen;
10932 +
10933 +       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
10934 +       alen=sizeof(int)*BM_MAX_HLEN;
10935 +       
10936 +       /* allocate array of structures */
10937 +       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
10938 +               return 0;
10939 +       }
10940 +       
10941 +       memset(bm_string_data, 0, tlen);
10942 +       
10943 +       /* allocate our skip/shift tables */
10944 +       for(c=0; c<smp_num_cpus; c++) {
10945 +               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
10946 +                       goto alloc_fail;
10947 +               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
10948 +                       goto alloc_fail;
10949 +               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
10950 +                       goto alloc_fail;
10951 +       }
10952 +       
10953 +       return ipt_register_match(&string_match);
10954 +
10955 +alloc_fail:
10956 +       string_freeup_data();
10957 +       return 0;
10958 +}
10959 +
10960 +static void __exit fini(void)
10961 +{
10962 +       ipt_unregister_match(&string_match);
10963 +       string_freeup_data();
10964 +}
10965 +
10966 +module_init(init);
10967 +module_exit(fini);
10968 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.5-rc3/net/ipv4/tcp_ipv4.c
10969 --- linux-2.6.5-rc3.org/net/ipv4/tcp_ipv4.c     2004-03-30 05:26:01.000000000 +0200
10970 +++ linux-2.6.5-rc3/net/ipv4/tcp_ipv4.c 2004-03-30 11:51:33.000000000 +0200
10971 @@ -2667,6 +2667,7 @@
10972  EXPORT_SYMBOL(tcp_v4_connect);
10973  EXPORT_SYMBOL(tcp_v4_do_rcv);
10974  EXPORT_SYMBOL(tcp_v4_lookup_listener);
10975 +EXPORT_SYMBOL(tcp_v4_lookup);
10976  EXPORT_SYMBOL(tcp_v4_rebuild_header);
10977  EXPORT_SYMBOL(tcp_v4_remember_stamp);
10978  EXPORT_SYMBOL(tcp_v4_send_check);
10979 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv4/udp.c linux-2.6.5-rc3/net/ipv4/udp.c
10980 --- linux-2.6.5-rc3.org/net/ipv4/udp.c  2004-03-30 05:25:34.000000000 +0200
10981 +++ linux-2.6.5-rc3/net/ipv4/udp.c      2004-03-30 11:51:33.000000000 +0200
10982 @@ -1543,6 +1543,7 @@
10983  EXPORT_SYMBOL(udp_port_rover);
10984  EXPORT_SYMBOL(udp_prot);
10985  EXPORT_SYMBOL(udp_sendmsg);
10986 +EXPORT_SYMBOL(udp_v4_lookup);
10987  
10988  #ifdef CONFIG_PROC_FS
10989  EXPORT_SYMBOL(udp_proc_register);
10990 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.5-rc3/net/ipv6/netfilter/Kconfig
10991 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/Kconfig      2004-03-30 11:31:19.000000000 +0200
10992 +++ linux-2.6.5-rc3/net/ipv6/netfilter/Kconfig  2004-03-30 11:50:47.000000000 +0200
10993 @@ -255,5 +255,15 @@
10994           <file:Documentation/modules.txt>.  If unsure, say `N'.
10995           help
10996  
10997 +config IP6_NF_TARGET_ROUTE
10998 +       tristate '    ROUTE target support'
10999 +       depends on IP6_NF_MANGLE
11000 +         help
11001 +
11002 +config IP6_NF_MATCH_CONDITION
11003 +       tristate  'condition match support'
11004 +       depends on IP6_NF_IPTABLES
11005 +         help
11006 +
11007  endmenu
11008  
11009 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.5-rc3/net/ipv6/netfilter/Makefile
11010 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/Makefile     2004-03-30 11:31:19.000000000 +0200
11011 +++ linux-2.6.5-rc3/net/ipv6/netfilter/Makefile 2004-03-30 11:50:47.000000000 +0200
11012 @@ -5,6 +5,7 @@
11013  # Link order matters here.
11014  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
11015  obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
11016 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
11017  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
11018  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
11019  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
11020 @@ -20,6 +21,7 @@
11021  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
11022  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
11023  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
11024 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
11025  obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
11026  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
11027  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
11028 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_ROUTE.c
11029 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
11030 +++ linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_ROUTE.c     2004-03-30 11:48:31.000000000 +0200
11031 @@ -0,0 +1,289 @@
11032 +/*
11033 + * This implements the ROUTE v6 target, which enables you to setup unusual
11034 + * routes not supported by the standard kernel routing table.
11035 + *
11036 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
11037 + *
11038 + * v 1.0 2003/08/05
11039 + *
11040 + * This software is distributed under GNU GPL v2, 1991
11041 + */
11042 +
11043 +#include <linux/module.h>
11044 +#include <linux/skbuff.h>
11045 +#include <linux/ipv6.h>
11046 +#include <linux/netfilter_ipv6/ip6_tables.h>
11047 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
11048 +#include <linux/netdevice.h>
11049 +#include <net/ipv6.h>
11050 +#include <net/ndisc.h>
11051 +#include <net/ip6_route.h>
11052 +#include <linux/icmpv6.h>
11053 +
11054 +#if 1
11055 +#define DEBUGP printk
11056 +#else
11057 +#define DEBUGP(format, args...)
11058 +#endif
11059 +
11060 +#define NIP6(addr) \
11061 +       ntohs((addr).s6_addr16[0]), \
11062 +       ntohs((addr).s6_addr16[1]), \
11063 +       ntohs((addr).s6_addr16[2]), \
11064 +       ntohs((addr).s6_addr16[3]), \
11065 +       ntohs((addr).s6_addr16[4]), \
11066 +       ntohs((addr).s6_addr16[5]), \
11067 +       ntohs((addr).s6_addr16[6]), \
11068 +       ntohs((addr).s6_addr16[7])
11069 +
11070 +/* Route the packet according to the routing keys specified in
11071 + * route_info. Keys are :
11072 + *  - ifindex : 
11073 + *      0 if no oif preferred, 
11074 + *      otherwise set to the index of the desired oif
11075 + *  - route_info->gw :
11076 + *      0 if no gateway specified,
11077 + *      otherwise set to the next host to which the pkt must be routed
11078 + * If success, skb->dev is the output device to which the packet must 
11079 + * be sent and skb->dst is not NULL
11080 + *
11081 + * RETURN:  1 if the packet was succesfully routed to the 
11082 + *            destination desired
11083 + *          0 if the kernel routing table could not route the packet
11084 + *            according to the keys specified
11085 + */
11086 +static int 
11087 +route6(struct sk_buff *skb,
11088 +       unsigned int ifindex,
11089 +       const struct ip6t_route_target_info *route_info)
11090 +{
11091 +       struct rt6_info *rt = NULL;
11092 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
11093 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
11094 +
11095 +       DEBUGP("ip6t_ROUTE: called with: ");
11096 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
11097 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
11098 +       DEBUGP("OUT=%s\n", route_info->oif);
11099 +       
11100 +       if (ipv6_addr_any(gw))
11101 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
11102 +       else
11103 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
11104 +
11105 +       if (!rt)
11106 +               goto no_route;
11107 +
11108 +       DEBUGP("ip6t_ROUTE: routing gives: ");
11109 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
11110 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
11111 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
11112 +
11113 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
11114 +               goto wrong_route;
11115 +       
11116 +       if (!rt->rt6i_nexthop) {
11117 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
11118 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
11119 +       }
11120 +
11121 +       /* Drop old route. */
11122 +       dst_release(skb->dst);
11123 +       skb->dst = &rt->u.dst;
11124 +       skb->dev = rt->rt6i_dev;
11125 +       return 1;
11126 +
11127 + wrong_route:
11128 +       dst_release(&rt->u.dst);
11129 + no_route:
11130 +       if (!net_ratelimit())
11131 +               return 0;
11132 +
11133 +       printk("ip6t_ROUTE: no explicit route found ");
11134 +       if (ifindex)
11135 +               printk("via interface %s ", route_info->oif);
11136 +       if (!ipv6_addr_any(gw))
11137 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
11138 +       printk("\n");
11139 +       return 0;
11140 +}
11141 +
11142 +
11143 +/* Stolen from ip6_output_finish
11144 + * PRE : skb->dev is set to the device we are leaving by
11145 + *       skb->dst is not NULL
11146 + * POST: the packet is sent with the link layer header pushed
11147 + *       the packet is destroyed
11148 + */
11149 +static void ip_direct_send(struct sk_buff *skb)
11150 +{
11151 +       struct dst_entry *dst = skb->dst;
11152 +       struct hh_cache *hh = dst->hh;
11153 +
11154 +       if (hh) {
11155 +               read_lock_bh(&hh->hh_lock);
11156 +               memcpy(skb->data - 16, hh->hh_data, 16);
11157 +               read_unlock_bh(&hh->hh_lock);
11158 +               skb_push(skb, hh->hh_len);
11159 +               hh->hh_output(skb);
11160 +       } else if (dst->neighbour)
11161 +               dst->neighbour->output(skb);
11162 +       else {
11163 +               if (net_ratelimit())
11164 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
11165 +               kfree_skb(skb);
11166 +       }
11167 +}
11168 +
11169 +
11170 +static unsigned int 
11171 +route6_oif(const struct ip6t_route_target_info *route_info,
11172 +          struct sk_buff *skb) 
11173 +{
11174 +       unsigned int ifindex = 0;
11175 +       struct net_device *dev_out = NULL;
11176 +
11177 +       /* The user set the interface name to use.
11178 +        * Getting the current interface index.
11179 +        */
11180 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
11181 +               ifindex = dev_out->ifindex;
11182 +       } else {
11183 +               /* Unknown interface name : packet dropped */
11184 +               if (net_ratelimit()) 
11185 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
11186 +
11187 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
11188 +                       return IP6T_CONTINUE;
11189 +               else
11190 +                       return NF_DROP;
11191 +       }
11192 +
11193 +       /* Trying the standard way of routing packets */
11194 +       if (route6(skb, ifindex, route_info)) {
11195 +               dev_put(dev_out);
11196 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
11197 +                       return IP6T_CONTINUE;
11198 +               
11199 +               ip_direct_send(skb);
11200 +               return NF_STOLEN;
11201 +       } else 
11202 +               return NF_DROP;
11203 +}
11204 +
11205 +
11206 +static unsigned int 
11207 +route6_gw(const struct ip6t_route_target_info *route_info,
11208 +         struct sk_buff *skb) 
11209 +{
11210 +       if (route6(skb, 0, route_info)) {
11211 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
11212 +                       return IP6T_CONTINUE;
11213 +
11214 +               ip_direct_send(skb);
11215 +               return NF_STOLEN;
11216 +       } else
11217 +               return NF_DROP;
11218 +}
11219 +
11220 +
11221 +static unsigned int 
11222 +ip6t_route_target(struct sk_buff **pskb,
11223 +                 unsigned int hooknum,
11224 +                 const struct net_device *in,
11225 +                 const struct net_device *out,
11226 +                 const void *targinfo,
11227 +                 void *userinfo)
11228 +{
11229 +       const struct ip6t_route_target_info *route_info = targinfo;
11230 +       struct sk_buff *skb = *pskb;
11231 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
11232 +
11233 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
11234 +               goto do_it;
11235 +
11236 +       /* If we are at PREROUTING or INPUT hook
11237 +        * the TTL isn't decreased by the IP stack
11238 +        */
11239 +       if (hooknum == NF_IP6_PRE_ROUTING ||
11240 +           hooknum == NF_IP6_LOCAL_IN) {
11241 +
11242 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
11243 +
11244 +               if (ipv6h->hop_limit <= 1) {
11245 +                       /* Force OUTPUT device used as source address */
11246 +                       skb->dev = skb->dst->dev;
11247 +
11248 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
11249 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
11250 +
11251 +                       return NF_DROP;
11252 +               }
11253 +
11254 +               ipv6h->hop_limit--;
11255 +       }
11256 +
11257 +
11258 + do_it:
11259 +       if (route_info->oif[0]) 
11260 +               return route6_oif(route_info, *pskb);
11261 +       
11262 +       if (!ipv6_addr_any(gw))
11263 +               return route6_gw(route_info, *pskb);
11264 +
11265 +       if (net_ratelimit()) 
11266 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
11267 +
11268 +       return IP6T_CONTINUE;
11269 +}
11270 +
11271 +
11272 +static int 
11273 +ip6t_route_checkentry(const char *tablename,
11274 +                     const struct ip6t_entry *e,
11275 +                     void *targinfo,
11276 +                     unsigned int targinfosize,
11277 +                     unsigned int hook_mask)
11278 +{
11279 +       if (strcmp(tablename, "mangle") != 0) {
11280 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
11281 +               return 0;
11282 +       }
11283 +
11284 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
11285 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
11286 +                      targinfosize,
11287 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
11288 +               return 0;
11289 +       }
11290 +
11291 +       return 1;
11292 +}
11293 +
11294 +
11295 +static struct ip6t_target ip6t_route_reg = {
11296 +       .name       = "ROUTE",
11297 +       .target     = ip6t_route_target,
11298 +       .checkentry = ip6t_route_checkentry,
11299 +       .me         = THIS_MODULE
11300 +};
11301 +
11302 +
11303 +static int __init init(void)
11304 +{
11305 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
11306 +       if (ip6t_register_target(&ip6t_route_reg))
11307 +               return -EINVAL;
11308 +
11309 +       return 0;
11310 +}
11311 +
11312 +
11313 +static void __exit fini(void)
11314 +{
11315 +       ip6t_unregister_target(&ip6t_route_reg);
11316 +}
11317 +
11318 +module_init(init);
11319 +module_exit(fini);
11320 +MODULE_LICENSE("GPL");
11321 diff -Nur --exclude '*.orig' linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_condition.c linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_condition.c
11322 --- linux-2.6.5-rc3.org/net/ipv6/netfilter/ip6t_condition.c     1970-01-01 01:00:00.000000000 +0100
11323 +++ linux-2.6.5-rc3/net/ipv6/netfilter/ip6t_condition.c 2004-03-30 11:50:47.000000000 +0200
11324 @@ -0,0 +1,254 @@
11325 +/*-------------------------------------------*\
11326 +|    Netfilter Condition Module for IPv6      |
11327 +|                                             |
11328 +|  Description: This module allows firewall   |
11329 +|    rules to match using condition variables |
11330 +|    stored in /proc files.                   |
11331 +|                                             |
11332 +|  Author: Stephane Ouellette     2003-02-10  |
11333 +|          <ouellettes@videotron.ca>          |
11334 +|                                             |
11335 +|  This software is distributed under the     |
11336 +|  terms of the GNU GPL.                      |
11337 +\*-------------------------------------------*/
11338 +
11339 +#include<linux/module.h>
11340 +#include<linux/proc_fs.h>
11341 +#include<linux/spinlock.h>
11342 +#include<linux/string.h>
11343 +#include<asm/atomic.h>
11344 +#include<linux/netfilter_ipv6/ip6_tables.h>
11345 +#include<linux/netfilter_ipv6/ip6t_condition.h>
11346 +
11347 +
11348 +#ifndef CONFIG_PROC_FS
11349 +#error  "Proc file system support is required for this module"
11350 +#endif
11351 +
11352 +
11353 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
11354 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
11355 +MODULE_LICENSE("GPL");
11356 +
11357 +
11358 +struct condition_variable {
11359 +       struct condition_variable *next;
11360 +       struct proc_dir_entry *status_proc;
11361 +       atomic_t refcount;
11362 +        int enabled; /* TRUE == 1, FALSE == 0 */
11363 +};
11364 +
11365 +
11366 +static rwlock_t list_lock;
11367 +static struct condition_variable *head = NULL;
11368 +static struct proc_dir_entry *proc_net_condition = NULL;
11369 +
11370 +
11371 +static int
11372 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
11373 +                       int length, int *eof, void *data)
11374 +{
11375 +       struct condition_variable *var =
11376 +           (struct condition_variable *) data;
11377 +
11378 +       if (offset == 0) {
11379 +               *start = buffer;
11380 +               buffer[0] = (var->enabled) ? '1' : '0';
11381 +               buffer[1] = '\n';
11382 +               return 2;
11383 +       }
11384 +
11385 +       *eof = 1;
11386 +       return 0;
11387 +}
11388 +
11389 +
11390 +static int
11391 +ipt_condition_write_info(struct file *file, const char *buffer,
11392 +                        unsigned long length, void *data)
11393 +{
11394 +       struct condition_variable *var =
11395 +           (struct condition_variable *) data;
11396 +
11397 +       if (length) {
11398 +               /* Match only on the first character */
11399 +               switch (buffer[0]) {
11400 +               case '0':
11401 +                       var->enabled = 0;
11402 +                       break;
11403 +               case '1':
11404 +                       var->enabled = 1;
11405 +               }
11406 +       }
11407 +
11408 +       return (int) length;
11409 +}
11410 +
11411 +
11412 +static int
11413 +match(const struct sk_buff *skb, const struct net_device *in,
11414 +      const struct net_device *out, const void *matchinfo, int offset,
11415 +      const void *hdr, u_int16_t datalen, int *hotdrop)
11416 +{
11417 +       const struct condition6_info *info =
11418 +           (const struct condition6_info *) matchinfo;
11419 +       struct condition_variable *var;
11420 +       int condition_status = 0;
11421 +
11422 +       read_lock(&list_lock);
11423 +
11424 +       for (var = head; var; var = var->next) {
11425 +               if (strcmp(info->name, var->status_proc->name) == 0) {
11426 +                       condition_status = var->enabled;
11427 +                       break;
11428 +               }
11429 +       }
11430 +
11431 +       read_unlock(&list_lock);
11432 +
11433 +       return condition_status ^ info->invert;
11434 +}
11435 +
11436 +
11437 +
11438 +static int
11439 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
11440 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
11441 +{
11442 +       struct condition6_info *info =
11443 +           (struct condition6_info *) matchinfo;
11444 +       struct condition_variable *var, *newvar;
11445 +
11446 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
11447 +               return 0;
11448 +
11449 +       /* The first step is to check if the condition variable already exists. */
11450 +       /* Here, a read lock is sufficient because we won't change the list */
11451 +       read_lock(&list_lock);
11452 +
11453 +       for (var = head; var; var = var->next) {
11454 +               if (strcmp(info->name, var->status_proc->name) == 0) {
11455 +                       atomic_inc(&var->refcount);
11456 +                       read_unlock(&list_lock);
11457 +                       return 1;
11458 +               }
11459 +       }
11460 +
11461 +       read_unlock(&list_lock);
11462 +
11463 +       /* At this point, we need to allocate a new condition variable */
11464 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
11465 +
11466 +       if (!newvar)
11467 +               return -ENOMEM;
11468 +
11469 +       /* Create the condition variable's proc file entry */
11470 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
11471 +
11472 +       if (!newvar->status_proc) {
11473 +         /*
11474 +          * There are two possibilities:
11475 +          *  1- Another condition variable with the same name has been created, which is valid.
11476 +          *  2- There was a memory allocation error.
11477 +          */
11478 +               kfree(newvar);
11479 +               read_lock(&list_lock);
11480 +
11481 +               for (var = head; var; var = var->next) {
11482 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
11483 +                               atomic_inc(&var->refcount);
11484 +                               read_unlock(&list_lock);
11485 +                               return 1;
11486 +                       }
11487 +               }
11488 +
11489 +               read_unlock(&list_lock);
11490 +               return -ENOMEM;
11491 +       }
11492 +
11493 +       atomic_set(&newvar->refcount, 1);
11494 +       newvar->enabled = 0;
11495 +       newvar->status_proc->owner = THIS_MODULE;
11496 +       newvar->status_proc->data = newvar;
11497 +       wmb();
11498 +       newvar->status_proc->read_proc = ipt_condition_read_info;
11499 +       newvar->status_proc->write_proc = ipt_condition_write_info;
11500 +
11501 +       write_lock(&list_lock);
11502 +
11503 +       newvar->next = head;
11504 +       head = newvar;
11505 +
11506 +       write_unlock(&list_lock);
11507 +
11508 +       return 1;
11509 +}
11510 +
11511 +
11512 +static void
11513 +destroy(void *matchinfo, unsigned int matchsize)
11514 +{
11515 +       struct condition6_info *info =
11516 +           (struct condition6_info *) matchinfo;
11517 +       struct condition_variable *var, *prev = NULL;
11518 +
11519 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
11520 +               return;
11521 +
11522 +       write_lock(&list_lock);
11523 +
11524 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
11525 +            prev = var, var = var->next);
11526 +
11527 +       if (var && atomic_dec_and_test(&var->refcount)) {
11528 +               if (prev)
11529 +                       prev->next = var->next;
11530 +               else
11531 +                       head = var->next;
11532 +
11533 +               write_unlock(&list_lock);
11534 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
11535 +               kfree(var);
11536 +       } else
11537 +               write_unlock(&list_lock);
11538 +}
11539 +
11540 +
11541 +static struct ip6t_match condition_match = {
11542 +       .name = "condition",
11543 +       .match = &match,
11544 +       .checkentry = &checkentry,
11545 +       .destroy = &destroy,
11546 +       .me = THIS_MODULE
11547 +};
11548 +
11549 +
11550 +static int __init
11551 +init(void)
11552 +{
11553 +       int errorcode;
11554 +
11555 +       rwlock_init(&list_lock);
11556 +       proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
11557 +
11558 +       if (proc_net_condition) {
11559 +               errorcode = ipt_register_match(&condition_match);
11560 +
11561 +               if (errorcode)
11562 +                       remove_proc_entry("ip6t_condition", proc_net);
11563 +       } else
11564 +               errorcode = -EACCES;
11565 +
11566 +       return errorcode;
11567 +}
11568 +
11569 +
11570 +static void __exit
11571 +fini(void)
11572 +{
11573 +       ipt_unregister_match(&condition_match);
11574 +       remove_proc_entry("ip6t_condition", proc_net);
11575 +}
11576 +
11577 +module_init(init);
11578 +module_exit(fini);
This page took 0.992712 seconds and 3 git commands to generate.