]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.6-rc3-patch-o-matic-ng-extra-20040429.patch
- obsolete
[packages/kernel.git] / 2.6.6-rc3-patch-o-matic-ng-extra-20040429.patch
1 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter.h linux-2.6.6-rc3/include/linux/netfilter.h
2 --- linux-2.6.6-rc3.org/include/linux/netfilter.h       2004-04-28 03:35:48.000000000 +0200
3 +++ linux-2.6.6-rc3/include/linux/netfilter.h   2004-04-29 11:18:06.000000000 +0200
4 @@ -23,6 +23,7 @@
5     <= 0x2000 is used for protocol-flags. */
6  #define NFC_UNKNOWN 0x4000
7  #define NFC_ALTERED 0x8000
8 +#define NFC_TRACE   0x10000
9  
10  #ifdef __KERNEL__
11  #include <linux/config.h>
12 @@ -137,12 +138,14 @@
13  /* This is gross, but inline doesn't cut it for avoiding the function
14     call in fast path: gcc doesn't inline (needs value tracking?). --RR */
15  #ifdef CONFIG_NETFILTER_DEBUG
16 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
17 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
18 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
19 +(!(cond)                                                               \
20 + ? (okfn)(skb)                                                                 \
21 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
22  #define NF_HOOK_THRESH nf_hook_slow
23  #else
24 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
25 -(list_empty(&nf_hooks[(pf)][(hook)])                                   \
26 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
27 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)])                                \
28   ? (okfn)(skb)                                                         \
29   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
30  #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)     \
31 @@ -150,6 +153,8 @@
32   ? (okfn)(skb)                                                         \
33   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
34  #endif
35 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
36 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
37  
38  int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
39                  struct net_device *indev, struct net_device *outdev,
40 @@ -182,7 +187,24 @@
41  
42  #else /* !CONFIG_NETFILTER */
43  #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
44 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
45  #endif /*CONFIG_NETFILTER*/
46  
47 +#ifdef CONFIG_XFRM
48 +#ifdef CONFIG_IP_NF_NAT_NEEDED
49 +struct flowi;
50 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
51 +
52 +static inline void
53 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
54 +{
55 +       if (family == AF_INET)
56 +               nf_nat_decode_session4(skb, fl);
57 +}
58 +#else /* CONFIG_IP_NF_NAT_NEEDED */
59 +#define nf_nat_decode_session(skb,fl,family)
60 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
61 +#endif /* CONFIG_XFRM */
62 +
63  #endif /*__KERNEL__*/
64  #endif /*__LINUX_NETFILTER_H*/
65 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h linux-2.6.6-rc3/include/linux/netfilter_helpers.h
66 --- linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h       1970-01-01 01:00:00.000000000 +0100
67 +++ linux-2.6.6-rc3/include/linux/netfilter_helpers.h   2004-04-29 11:20:13.000000000 +0200
68 @@ -0,0 +1,133 @@
69 +/*
70 + * Helpers for netfiler modules.  This file provides implementations for basic
71 + * functions such as strncasecmp(), etc.
72 + *
73 + * gcc will warn for defined but unused functions, so we only include the
74 + * functions requested.  The following macros are used:
75 + *   NF_NEED_STRNCASECMP        nf_strncasecmp()
76 + *   NF_NEED_STRTOU16           nf_strtou16()
77 + *   NF_NEED_STRTOU32           nf_strtou32()
78 + */
79 +#ifndef _NETFILTER_HELPERS_H
80 +#define _NETFILTER_HELPERS_H
81 +
82 +/* Only include these functions for kernel code. */
83 +#ifdef __KERNEL__
84 +
85 +#include <linux/ctype.h>
86 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
87 +
88 +/*
89 + * The standard strncasecmp()
90 + */
91 +#ifdef NF_NEED_STRNCASECMP
92 +static int
93 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
94 +{
95 +    if (s1 == NULL || s2 == NULL)
96 +    {
97 +        if (s1 == NULL && s2 == NULL)
98 +        {
99 +            return 0;
100 +        }
101 +        return (s1 == NULL) ? -1 : 1;
102 +    }
103 +    while (len > 0 && tolower(*s1) == tolower(*s2))
104 +    {
105 +        len--;
106 +        s1++;
107 +        s2++;
108 +    }
109 +    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
110 +}
111 +#endif /* NF_NEED_STRNCASECMP */
112 +
113 +/*
114 + * Parse a string containing a 16-bit unsigned integer.
115 + * Returns the number of chars used, or zero if no number is found.
116 + */
117 +#ifdef NF_NEED_STRTOU16
118 +static int
119 +nf_strtou16(const char* pbuf, u_int16_t* pval)
120 +{
121 +    int n = 0;
122 +
123 +    *pval = 0;
124 +    while (isdigit(pbuf[n]))
125 +    {
126 +        *pval = (*pval * 10) + (pbuf[n] - '0');
127 +        n++;
128 +    }
129 +
130 +    return n;
131 +}
132 +#endif /* NF_NEED_STRTOU16 */
133 +
134 +/*
135 + * Parse a string containing a 32-bit unsigned integer.
136 + * Returns the number of chars used, or zero if no number is found.
137 + */
138 +#ifdef NF_NEED_STRTOU32
139 +static int
140 +nf_strtou32(const char* pbuf, u_int32_t* pval)
141 +{
142 +    int n = 0;
143 +
144 +    *pval = 0;
145 +    while (pbuf[n] >= '0' && pbuf[n] <= '9')
146 +    {
147 +        *pval = (*pval * 10) + (pbuf[n] - '0');
148 +        n++;
149 +    }
150 +
151 +    return n;
152 +}
153 +#endif /* NF_NEED_STRTOU32 */
154 +
155 +/*
156 + * Given a buffer and length, advance to the next line and mark the current
157 + * line.
158 + */
159 +#ifdef NF_NEED_NEXTLINE
160 +static int
161 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
162 +{
163 +    uint    off = *poff;
164 +    uint    physlen = 0;
165 +
166 +    if (off >= len)
167 +    {
168 +        return 0;
169 +    }
170 +
171 +    while (p[off] != '\n')
172 +    {
173 +        if (len-off <= 1)
174 +        {
175 +            return 0;
176 +        }
177 +
178 +        physlen++;
179 +        off++;
180 +    }
181 +
182 +    /* if we saw a crlf, physlen needs adjusted */
183 +    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
184 +    {
185 +        physlen--;
186 +    }
187 +
188 +    /* advance past the newline */
189 +    off++;
190 +
191 +    *plineoff = *poff;
192 +    *plinelen = physlen;
193 +    *poff = off;
194 +
195 +    return 1;
196 +}
197 +#endif /* NF_NEED_NEXTLINE */
198 +
199 +#endif /* __KERNEL__ */
200 +
201 +#endif /* _NETFILTER_HELPERS_H */
202 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
203 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h     2004-04-28 03:36:37.000000000 +0200
204 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-29 11:21:43.000000000 +0200
205 @@ -51,10 +51,12 @@
206  
207  #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
208  #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
209 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
210  
211  /* per conntrack: protocol private data */
212  union ip_conntrack_proto {
213         /* insert conntrack proto private data here */
214 +       struct ip_ct_sctp sctp;
215         struct ip_ct_tcp tcp;
216         struct ip_ct_icmp icmp;
217  };
218 @@ -64,6 +66,11 @@
219  };
220  
221  /* Add protocol helper include file here */
222 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
223 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
224 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
225 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
226 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
227  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
228  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
229  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
230 @@ -71,6 +78,11 @@
231  /* per expectation: application helper private data */
232  union ip_conntrack_expect_help {
233         /* insert conntrack helper private data (expect) here */
234 +       struct ip_ct_talk_expect exp_talk_info;
235 +       struct ip_ct_rtsp_expect exp_rtsp_info;
236 +       struct ip_ct_rsh_expect exp_rsh_info;
237 +       struct ip_ct_mms_expect exp_mms_info;
238 +       struct ip_ct_h225_expect exp_h225_info;
239         struct ip_ct_amanda_expect exp_amanda_info;
240         struct ip_ct_ftp_expect exp_ftp_info;
241         struct ip_ct_irc_expect exp_irc_info;
242 @@ -85,6 +97,11 @@
243  /* per conntrack: application helper private data */
244  union ip_conntrack_help {
245         /* insert conntrack helper private data (master) here */
246 +       struct ip_ct_talk_master ct_talk_info;
247 +       struct ip_ct_rtsp_master ct_rtsp_info;
248 +       struct ip_ct_rsh_master ct_rsh_info;
249 +       struct ip_ct_mms_master ct_mms_info;
250 +       struct ip_ct_h225_master ct_h225_info;
251         struct ip_ct_ftp_master ct_ftp_info;
252         struct ip_ct_irc_master ct_irc_info;
253  };
254 @@ -207,6 +224,10 @@
255         } nat;
256  #endif /* CONFIG_IP_NF_NAT_NEEDED */
257  
258 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
259 +       unsigned long mark;
260 +#endif
261 +
262  };
263  
264  /* get master conntrack via master expectation */
265 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
266 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h     1970-01-01 01:00:00.000000000 +0100
267 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h 2004-04-29 11:17:55.000000000 +0200
268 @@ -0,0 +1,70 @@
269 +#ifndef _IP_CT_CUSEEME
270 +#define _IP_CT_CUSEEME
271 +
272 +#define CUSEEME_PORT 7648
273 +
274 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
275 +
276 +#pragma pack(1)
277 +/* CuSeeMe data header */
278 +struct cu_header {
279 +       u_int16_t       dest_family;
280 +       u_int16_t       dest_port;
281 +       u_int32_t       dest_addr;
282 +       int16_t         family;
283 +       u_int16_t       port;
284 +       u_int32_t       addr;
285 +       u_int32_t       seq;
286 +       u_int16_t       msg;
287 +       u_int16_t       data_type;
288 +                               /* possible values:
289 +                                * 1    small video
290 +                                * 2    big video
291 +                                * 3    audio
292 +                                * 100  acknowledge connectivity when there
293 +                                *      is nothing else to send
294 +                                * 101  OpenContinue packet
295 +                                * 104  display a text message and 
296 +                                *      disconnect (used by reflector to
297 +                                *      kick clients off)
298 +                                * 105  display a text message (welcome
299 +                                *      message from reflector)
300 +                                * 106  exchanged among reflectors for
301 +                                *      reflector interoperation
302 +                                * 107  carry aux stream data when there is
303 +                                *      no video to piggy-back on
304 +                                * 108  obsolete (used in Mac alpha version)
305 +                                * 109  obsolete (used in Mac alpha version)
306 +                                * 110  used for data rate control
307 +                                * 111  used for data rate control
308 +                                * 256  aux data control messages
309 +                                * 257  aux data packets
310 +                                * */
311 +       u_int16_t       packet_len;
312 +};
313 +
314 +/* Open Continue Header */
315 +struct oc_header {
316 +       struct cu_header        cu_head;
317 +       u_int16_t       client_count; /* Number of client info structs */
318 +       u_int32_t       seq_no;
319 +       char            user_name[20];
320 +       char            stuff[4];     /* Flags, version stuff, etc */
321 +};
322 +
323 +/* Client info structures */
324 +struct client_info {
325 +       u_int32_t       address;      /* Client address */
326 +       char            stuff[8];     /* Flags, pruning bitfield, packet counts, etc */
327 +};
328 +#pragma pack()
329 +
330 +/* This structure is per expected connection */
331 +struct ip_ct_cuseeme_expect {
332 +};
333 +
334 +/* This structure exists only once per master */
335 +struct ip_ct_cuseeme_master {
336 +};
337 +
338 +#endif /* _IP_CT_CUSEEME */
339 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
340 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h        1970-01-01 01:00:00.000000000 +0100
341 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h    2004-04-29 11:18:00.000000000 +0200
342 @@ -0,0 +1,31 @@
343 +#ifndef _IP_CONNTRACK_H323_H
344 +#define _IP_CONNTRACK_H323_H
345 +/* H.323 connection tracking. */
346 +
347 +#ifdef __KERNEL__
348 +/* Protects H.323 related data */
349 +#include <linux/netfilter_ipv4/lockhelp.h>
350 +DECLARE_LOCK_EXTERN(ip_h323_lock);
351 +#endif
352 +
353 +/* Default H.225 port */
354 +#define H225_PORT      1720
355 +
356 +/* This structure is per expected connection */
357 +struct ip_ct_h225_expect {
358 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
359 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
360 +       unsigned int offset;            /* offset of the address in the payload */
361 +};
362 +
363 +/* This structure exists only once per master */
364 +struct ip_ct_h225_master {
365 +       int is_h225;                            /* H.225 or H.245 connection */
366 +#ifdef CONFIG_IP_NF_NAT_NEEDED
367 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
368 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
369 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
370 +#endif
371 +};
372 +
373 +#endif /* _IP_CONNTRACK_H323_H */
374 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
375 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
376 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h     2004-04-29 11:19:01.000000000 +0200
377 @@ -0,0 +1,31 @@
378 +#ifndef _IP_CONNTRACK_MMS_H
379 +#define _IP_CONNTRACK_MMS_H
380 +/* MMS tracking. */
381 +
382 +#ifdef __KERNEL__
383 +#include <linux/netfilter_ipv4/lockhelp.h>
384 +
385 +DECLARE_LOCK_EXTERN(ip_mms_lock);
386 +
387 +#define MMS_PORT                         1755
388 +#define MMS_SRV_MSG_ID                   196610
389 +
390 +#define MMS_SRV_MSG_OFFSET               36
391 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
392 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
393 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
394 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
395 +#endif
396 +
397 +/* This structure is per expected connection */
398 +struct ip_ct_mms_expect {
399 +       u_int32_t len;
400 +       u_int32_t padding;
401 +       u_int16_t port;
402 +};
403 +
404 +/* This structure exists only once per master */
405 +struct ip_ct_mms_master {
406 +};
407 +
408 +#endif /* _IP_CONNTRACK_MMS_H */
409 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
410 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h      1970-01-01 01:00:00.000000000 +0100
411 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h  2004-04-29 11:19:53.000000000 +0200
412 @@ -0,0 +1,21 @@
413 +#ifndef _IP_CT_QUAKE3
414 +#define _IP_CT_QUAKE3
415 +
416 +/* Don't confuse with 27960, often used as the Server Port */
417 +#define QUAKE3_MASTER_PORT 27950
418 +
419 +struct quake3_search {
420 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
421 +       const char *pattern;
422 +       size_t plen;
423 +}; 
424 +
425 +/* This structure is per expected connection */
426 +struct ip_ct_quake3_expect {
427 +};
428 +
429 +/* This structure exists only once per master */
430 +struct ip_ct_quake3_master {
431 +};
432 +
433 +#endif /* _IP_CT_QUAKE3 */
434 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
435 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h 1970-01-01 01:00:00.000000000 +0100
436 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rpc.h     2004-04-29 11:20:02.000000000 +0200
437 @@ -0,0 +1,68 @@
438 +/* RPC extension for IP connection tracking, Version 2.2
439 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
440 + *     - original rpc tracking module
441 + *     - "recent" connection handling for kernel 2.3+ netfilter
442 + *
443 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
444 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
445 + *
446 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
447 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
448 + *     - extended matching to support filtering on procedures
449 + *
450 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
451 + *
452 + *     This program is free software; you can redistribute it and/or
453 + *     modify it under the terms of the GNU General Public License
454 + *     as published by the Free Software Foundation; either version
455 + *     2 of the License, or (at your option) any later version.
456 + **
457 + */
458 +
459 +#include <asm/param.h>
460 +#include <linux/sched.h>
461 +#include <linux/timer.h>
462 +#include <linux/stddef.h>
463 +#include <linux/list.h>
464 +
465 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
466 +
467 +#ifndef _IP_CONNTRACK_RPC_H
468 +#define _IP_CONNTRACK_RPC_H
469 +
470 +#define RPC_PORT       111
471 +
472 +
473 +/* Datum in RPC packets are encoded in XDR */
474 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
475 +
476 +/* Fast timeout, to deny DoS atacks */
477 +#define EXP (60 * HZ)
478 +
479 +/* Normal timeouts */
480 +#define EXPIRES (180 * HZ)
481 +
482 +/* For future conections RPC, using client's cache bindings
483 + * I'll use ip_conntrack_lock to lock these lists      */
484 +
485 +/* This identifies each request and stores protocol */
486 +struct request_p {
487 +       struct list_head list;
488 +
489 +       u_int32_t xid;   
490 +       u_int32_t ip;
491 +       u_int16_t port;
492 +       
493 +       /* Protocol */
494 +       u_int16_t proto;
495 +
496 +       struct timer_list timeout;
497 +};
498 +
499 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
500 +                               u_int32_t ip, u_int32_t port) {
501 +       return (p->xid == xid && p->ip == ip && p->port);
502 +
503 +}
504 +
505 +#endif /* _IP_CONNTRACK_RPC_H */
506 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
507 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
508 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h     2004-04-29 11:20:06.000000000 +0200
509 @@ -0,0 +1,35 @@
510 +/* RSH extension for IP connection tracking, Version 1.0
511 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
512 + * based on HW's ip_conntrack_irc.c     
513 + *
514 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
515 + *
516 + *      This program is free software; you can redistribute it and/or
517 + *      modify it under the terms of the GNU General Public License
518 + *      as published by the Free Software Foundation; either version
519 + *      2 of the License, or (at your option) any later version.
520 + */
521 +#ifndef _IP_CONNTRACK_RSH_H
522 +#define _IP_CONNTRACK_RSH_H
523 +
524 +#ifdef __KERNEL__
525 +#include <linux/netfilter_ipv4/lockhelp.h>
526 +
527 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
528 +#endif
529 +
530 +
531 +#define RSH_PORT       514
532 +
533 +/* This structure is per expected connection */
534 +struct ip_ct_rsh_expect
535 +{
536 +       u_int16_t port;
537 +};
538 +
539 +/* This structure exists only once per master */
540 +struct ip_ct_rsh_master {
541 +};
542 +
543 +#endif /* _IP_CONNTRACK_RSH_H */
544 +
545 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
546 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h        1970-01-01 01:00:00.000000000 +0100
547 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h    2004-04-29 11:20:13.000000000 +0200
548 @@ -0,0 +1,68 @@
549 +/*
550 + * RTSP extension for IP connection tracking.
551 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
552 + * based on ip_conntrack_irc.h
553 + *
554 + *      This program is free software; you can redistribute it and/or
555 + *      modify it under the terms of the GNU General Public License
556 + *      as published by the Free Software Foundation; either version
557 + *      2 of the License, or (at your option) any later version.
558 + */
559 +#ifndef _IP_CONNTRACK_RTSP_H
560 +#define _IP_CONNTRACK_RTSP_H
561 +
562 +/* #define IP_NF_RTSP_DEBUG */
563 +#define IP_NF_RTSP_VERSION "0.01"
564 +
565 +/* port block types */
566 +typedef enum {
567 +    pb_single,  /* client_port=x */
568 +    pb_range,   /* client_port=x-y */
569 +    pb_discon   /* client_port=x/y (rtspbis) */
570 +} portblock_t;
571 +
572 +/* We record seq number and length of rtsp headers here, all in host order. */
573 +
574 +/*
575 + * This structure is per expected connection.  It is a member of struct
576 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
577 + * there and we are expected to only store the length of the data which
578 + * needs replaced.  If a packet contains multiple RTSP messages, we create
579 + * one expected connection per message.
580 + *
581 + * We use these variables to mark the entire header block.  This may seem
582 + * like overkill, but the nature of RTSP requires it.  A header may appear
583 + * multiple times in a message.  We must treat two Transport headers the
584 + * same as one Transport header with two entries.
585 + */
586 +struct ip_ct_rtsp_expect
587 +{
588 +    u_int32_t   len;        /* length of header block */
589 +    portblock_t pbtype;     /* Type of port block that was requested */
590 +    u_int16_t   loport;     /* Port that was requested, low or first */
591 +    u_int16_t   hiport;     /* Port that was requested, high or second */
592 +#if 0
593 +    uint        method;     /* RTSP method */
594 +    uint        cseq;       /* CSeq from request */
595 +#endif
596 +};
597 +
598 +/* This structure exists only once per master */
599 +struct ip_ct_rtsp_master
600 +{
601 +    /* Empty (?) */
602 +};
603 +
604 +
605 +#ifdef __KERNEL__
606 +
607 +#include <linux/netfilter_ipv4/lockhelp.h>
608 +
609 +#define RTSP_PORT   554
610 +
611 +/* Protects rtsp part of conntracks */
612 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
613 +
614 +#endif /* __KERNEL__ */
615 +
616 +#endif /* _IP_CONNTRACK_RTSP_H */
617 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
618 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h        1970-01-01 01:00:00.000000000 +0100
619 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h    2004-04-29 11:20:17.000000000 +0200
620 @@ -0,0 +1,25 @@
621 +#ifndef _IP_CONNTRACK_SCTP_H
622 +#define _IP_CONNTRACK_SCTP_H
623 +/* SCTP tracking. */
624 +
625 +enum sctp_conntrack {
626 +       SCTP_CONNTRACK_NONE,
627 +       SCTP_CONNTRACK_CLOSED,
628 +       SCTP_CONNTRACK_COOKIE_WAIT,
629 +       SCTP_CONNTRACK_COOKIE_ECHOED,
630 +       SCTP_CONNTRACK_ESTABLISHED,
631 +       SCTP_CONNTRACK_SHUTDOWN_SENT,
632 +       SCTP_CONNTRACK_SHUTDOWN_RECD,
633 +       SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
634 +       SCTP_CONNTRACK_MAX
635 +};
636 +
637 +struct ip_ct_sctp
638 +{
639 +       enum sctp_conntrack state;
640 +
641 +       u_int32_t vtag[IP_CT_DIR_MAX];
642 +       u_int32_t ttag[IP_CT_DIR_MAX];
643 +};
644 +
645 +#endif /* _IP_CONNTRACK_SCTP_H */
646 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
647 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h        1970-01-01 01:00:00.000000000 +0100
648 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h    2004-04-29 11:21:43.000000000 +0200
649 @@ -0,0 +1,152 @@
650 +#ifndef _IP_CONNTRACK_TALK_H
651 +#define _IP_CONNTRACK_TALK_H
652 +/* TALK tracking. */
653 +
654 +#ifdef __KERNEL__
655 +#include <linux/in.h>
656 +#include <linux/netfilter_ipv4/lockhelp.h>
657 +
658 +/* Protects talk part of conntracks */
659 +DECLARE_LOCK_EXTERN(ip_talk_lock);
660 +#endif
661 +
662 +
663 +#define TALK_PORT      517
664 +#define NTALK_PORT     518
665 +
666 +/* talk structures and constants from <protocols/talkd.h> */
667 +
668 +/*
669 + * 4.3BSD struct sockaddr
670 + */
671 +struct talk_addr {
672 +       u_int16_t ta_family;
673 +       u_int16_t ta_port;
674 +       u_int32_t ta_addr;
675 +       u_int32_t ta_junk1;
676 +       u_int32_t ta_junk2;
677 +};
678 +
679 +#define        TALK_OLD_NSIZE  9
680 +#define        TALK_NSIZE      12
681 +#define        TALK_TTY_NSIZE  16
682 +
683 +/*
684 + * Client->server request message formats.
685 + */
686 +struct talk_msg {
687 +       u_char  type;           /* request type, see below */
688 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
689 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
690 +       u_char  pad;
691 +       u_int32_t id_num;       /* message id */
692 +       int32_t pid;            /* caller's process id */
693 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
694 +       struct  talk_addr addr;         /* old (4.3) style */
695 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
696 +};
697 +
698 +struct ntalk_msg {
699 +       u_char  vers;           /* protocol version */
700 +       u_char  type;           /* request type, see below */
701 +       u_char  answer;         /* not used */
702 +       u_char  pad;
703 +       u_int32_t id_num;       /* message id */
704 +       struct  talk_addr addr;         /* old (4.3) style */
705 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
706 +       int32_t pid;            /* caller's process id */
707 +       char    l_name[TALK_NSIZE];/* caller's name */
708 +       char    r_name[TALK_NSIZE];/* callee's name */
709 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
710 +};
711 +
712 +struct ntalk2_msg {
713 +       u_char  vers;           /* talk protocol version    */
714 +       u_char  type;           /* request type             */
715 +       u_char  answer;         /*  */
716 +       u_char  extended;       /* !0 if additional parts   */
717 +       u_int32_t id_num;       /* message id number (dels) */
718 +       struct  talk_addr addr;         /* target address   */
719 +       struct  talk_addr ctl_addr;     /* reply to address */
720 +       int32_t pid;            /* caller's process id */
721 +       char    l_name[TALK_NSIZE];  /* caller's name */
722 +       char    r_name[TALK_NSIZE];  /* callee's name */
723 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
724 +};
725 +
726 +/*
727 + * Server->client response message formats.
728 + */
729 +struct talk_response {
730 +       u_char  type;           /* type of request message, see below */
731 +       u_char  answer;         /* response to request message, see below */
732 +       u_char  pad[2];
733 +       u_int32_t id_num;       /* message id */
734 +       struct  talk_addr addr; /* address for establishing conversation */
735 +};
736 +
737 +struct ntalk_response {
738 +       u_char  vers;           /* protocol version */
739 +       u_char  type;           /* type of request message, see below */
740 +       u_char  answer;         /* response to request message, see below */
741 +       u_char  pad;
742 +       u_int32_t id_num;       /* message id */
743 +       struct  talk_addr addr; /* address for establishing conversation */
744 +};
745 +
746 +struct ntalk2_response {
747 +       u_char  vers;           /* protocol version         */
748 +       u_char  type;           /* type of request message  */
749 +       u_char  answer;         /* response to request      */
750 +       u_char  rvers;          /* Version of answering vers*/
751 +       u_int32_t id_num;       /* message id number        */
752 +       struct  talk_addr addr; /* address for connection   */
753 +       /* This is at the end to compatiblize this with NTALK version.   */
754 +       char    r_name[TALK_NSIZE]; /* callee's name            */
755 +};
756 +
757 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
758 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
759 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
760 +
761 +#define        TALK_VERSION    0               /* protocol versions */
762 +#define        NTALK_VERSION   1
763 +#define        NTALK2_VERSION  2
764 +
765 +/* message type values */
766 +#define LEAVE_INVITE   0       /* leave invitation with server */
767 +#define LOOK_UP                1       /* check for invitation by callee */
768 +#define DELETE         2       /* delete invitation by caller */
769 +#define ANNOUNCE       3       /* announce invitation by caller */
770 +/* NTALK2 */
771 +#define REPLY_QUERY    4       /* request reply data from local daemon */
772 +
773 +/* answer values */
774 +#define SUCCESS                0       /* operation completed properly */
775 +#define NOT_HERE       1       /* callee not logged in */
776 +#define FAILED         2       /* operation failed for unexplained reason */
777 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
778 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
779 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
780 +#define        BADVERSION      6       /* request has invalid protocol version */
781 +#define        BADADDR         7       /* request has invalid addr value */
782 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
783 +/* NTALK2 */
784 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
785 +#define TRY_HERE       10      /* Not on this machine, try this      */
786 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
787 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
788 +
789 +/* We don't really need much for talk */
790 +struct ip_ct_talk_expect
791 +{
792 +       /* Port that was to be used */
793 +       u_int16_t port;
794 +};
795 +
796 +/* This structure exists only once per master */
797 +struct ip_ct_talk_master
798 +{
799 +};
800 +
801 +#endif /* _IP_CONNTRACK_TALK_H */
802 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
803 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h       2004-04-28 03:36:22.000000000 +0200
804 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h   2004-04-29 11:20:17.000000000 +0200
805 @@ -25,6 +25,9 @@
806         struct {
807                 u_int16_t id;
808         } icmp;
809 +       struct {
810 +               u_int16_t port;
811 +       } sctp;
812  };
813  
814  /* The manipulable part of the tuple. */
815 @@ -55,6 +58,9 @@
816                         struct {
817                                 u_int8_t type, code;
818                         } icmp;
819 +                       struct {
820 +                               u_int16_t port;
821 +                       } sctp;
822                 } u;
823  
824                 /* The protocol. */
825 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h
826 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h        2004-04-28 03:35:48.000000000 +0200
827 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h    2004-04-29 11:17:15.000000000 +0200
828 @@ -134,6 +134,12 @@
829         /* Back pointer */
830         unsigned int comefrom;
831  
832 +       /* Name of the chain */
833 +       char *chainname;
834 +       
835 +       /* Rule number in the chain. */
836 +       u_int32_t rulenum;
837 +
838         /* Packet and byte counters. */
839         struct ipt_counters counters;
840  
841 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
842 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h     1970-01-01 01:00:00.000000000 +0100
843 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-29 11:10:59.000000000 +0200
844 @@ -0,0 +1,25 @@
845 +#ifndef _IPT_CONNMARK_H_target
846 +#define _IPT_CONNMARK_H_target
847 +
848 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
849 + * by Henrik Nordstrom <hno@marasystems.com>
850 + *
851 + * This program is free software; you can redistribute it and/or modify
852 + * it under the terms of the GNU General Public License as published by
853 + * the Free Software Foundation; either version 2 of the License, or
854 + * (at your option) any later version.
855 + */
856 +
857 +enum {
858 +       IPT_CONNMARK_SET = 0,
859 +       IPT_CONNMARK_SAVE,
860 +       IPT_CONNMARK_RESTORE
861 +};
862 +
863 +struct ipt_connmark_target_info {
864 +       unsigned long mark;
865 +       unsigned long mask;
866 +       u_int8_t mode;
867 +};
868 +
869 +#endif /*_IPT_CONNMARK_H_target*/
870 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
871 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h       1970-01-01 01:00:00.000000000 +0100
872 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h   2004-04-29 11:17:03.000000000 +0200
873 @@ -0,0 +1,13 @@
874 +#ifndef _IPT_IPMARK_H_target
875 +#define _IPT_IPMARK_H_target
876 +
877 +struct ipt_ipmark_target_info {
878 +       unsigned long andmask;
879 +       unsigned long ormask;
880 +       unsigned int addr;
881 +};
882 +
883 +#define IPT_IPMARK_SRC    0
884 +#define IPT_IPMARK_DST    1
885 +
886 +#endif /*_IPT_IPMARK_H_target*/
887 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
888 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h  1970-01-01 01:00:00.000000000 +0100
889 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h      2004-04-29 11:17:18.000000000 +0200
890 @@ -0,0 +1,9 @@
891 +#ifndef _IPT_XOR_H
892 +#define _IPT_XOR_H
893 +
894 +struct ipt_XOR_info {
895 +       char            key[30];
896 +       u_int8_t        block_size;
897 +};
898 +
899 +#endif /* _IPT_XOR_H */
900 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
901 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h     1970-01-01 01:00:00.000000000 +0100
902 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-29 11:17:23.000000000 +0200
903 @@ -0,0 +1,11 @@
904 +#ifndef _IPT_ADDRTYPE_H
905 +#define _IPT_ADDRTYPE_H
906 +
907 +struct ipt_addrtype_info {
908 +       u_int16_t       source;         /* source-type mask */
909 +       u_int16_t       dest;           /* dest-type mask */
910 +       int             invert_source;
911 +       int             invert_dest;
912 +};
913 +
914 +#endif
915 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
916 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h     1970-01-01 01:00:00.000000000 +0100
917 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-29 11:10:59.000000000 +0200
918 @@ -0,0 +1,18 @@
919 +#ifndef _IPT_CONNMARK_H
920 +#define _IPT_CONNMARK_H
921 +
922 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
923 + * by Henrik Nordstrom <hno@marasystems.com>
924 + *
925 + * This program is free software; you can redistribute it and/or modify
926 + * it under the terms of the GNU General Public License as published by
927 + * the Free Software Foundation; either version 2 of the License, or
928 + * (at your option) any later version.
929 + */
930 +
931 +struct ipt_connmark_info {
932 +       unsigned long mark, mask;
933 +       u_int8_t invert;
934 +};
935 +
936 +#endif /*_IPT_CONNMARK_H*/
937 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h
938 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h       1970-01-01 01:00:00.000000000 +0100
939 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h   2004-04-29 11:19:41.000000000 +0200
940 @@ -0,0 +1,52 @@
941 +#ifndef _IPT_POLICY_H
942 +#define _IPT_POLICY_H
943 +
944 +#define POLICY_MAX_ELEM        4
945 +
946 +enum ipt_policy_flags
947 +{
948 +       POLICY_MATCH_IN         = 0x1,
949 +       POLICY_MATCH_OUT        = 0x2,
950 +       POLICY_MATCH_NONE       = 0x4,
951 +       POLICY_MATCH_STRICT     = 0x8,
952 +};
953 +
954 +enum ipt_policy_modes
955 +{
956 +       POLICY_MODE_TRANSPORT,
957 +       POLICY_MODE_TUNNEL
958 +};
959 +
960 +struct ipt_policy_spec
961 +{
962 +       u_int8_t        saddr:1,
963 +                       daddr:1,
964 +                       proto:1,
965 +                       mode:1,
966 +                       spi:1,
967 +                       reqid:1;
968 +};
969 +
970 +struct ipt_policy_elem
971 +{
972 +       u_int32_t       saddr;
973 +       u_int32_t       smask;
974 +       u_int32_t       daddr;
975 +       u_int32_t       dmask;
976 +       u_int32_t       spi;
977 +       u_int32_t       reqid;
978 +       u_int8_t        proto;
979 +       u_int8_t        mode;
980 +
981 +       struct ipt_policy_spec  match;
982 +       struct ipt_policy_spec  invert;
983 +};
984 +
985 +struct ipt_policy_info
986 +{
987 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
988 +       u_int16_t flags;
989 +       u_int16_t len;
990 +};
991 +
992 +#endif /* _IPT_POLICY_H */
993 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_rpc.h
994 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_rpc.h  1970-01-01 01:00:00.000000000 +0100
995 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_rpc.h      2004-04-29 11:20:02.000000000 +0200
996 @@ -0,0 +1,35 @@
997 +/* RPC extension for IP netfilter matching, Version 2.2
998 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
999 + *     - original rpc tracking module
1000 + *     - "recent" connection handling for kernel 2.3+ netfilter
1001 + *
1002 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1003 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1004 + *
1005 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1006 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
1007 + *     - extended matching to support filtering on procedures
1008 + *
1009 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
1010 + *
1011 + *     This program is free software; you can redistribute it and/or
1012 + *     modify it under the terms of the GNU General Public License
1013 + *     as published by the Free Software Foundation; either version
1014 + *     2 of the License, or (at your option) any later version.
1015 + **
1016 + */
1017 +
1018 +#ifndef _IPT_RPC_H
1019 +#define _IPT_RPC_H
1020 +
1021 +struct ipt_rpc_data;
1022 +
1023 +struct ipt_rpc_info {
1024 +       int inverse;
1025 +       int strict;
1026 +       const char c_procs[1408];
1027 +       int i_procs;
1028 +       struct ipt_rpc_data *data;
1029 +};
1030 +
1031 +#endif /* _IPT_RPC_H */
1032 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h
1033 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h       1970-01-01 01:00:00.000000000 +0100
1034 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h   2004-04-29 11:21:38.000000000 +0200
1035 @@ -0,0 +1,21 @@
1036 +#ifndef _IPT_STRING_H
1037 +#define _IPT_STRING_H
1038 +
1039 +/* *** PERFORMANCE TWEAK ***
1040 + * Packet size and search string threshold,
1041 + * above which sublinear searches is used. */
1042 +#define IPT_STRING_HAYSTACK_THRESH     100
1043 +#define IPT_STRING_NEEDLE_THRESH       20
1044 +
1045 +#define BM_MAX_NLEN 256
1046 +#define BM_MAX_HLEN 1024
1047 +
1048 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1049 +
1050 +struct ipt_string_info {
1051 +    char string[BM_MAX_NLEN];
1052 +    u_int16_t invert;
1053 +    u_int16_t len;
1054 +};
1055 +
1056 +#endif /* _IPT_STRING_H */
1057 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc3/include/linux/netfilter_ipv4.h
1058 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h  2004-04-28 03:36:31.000000000 +0200
1059 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4.h      2004-04-29 11:18:03.000000000 +0200
1060 @@ -7,6 +7,8 @@
1061  
1062  #include <linux/config.h>
1063  #include <linux/netfilter.h>
1064 +#include <linux/netdevice.h>
1065 +#include <net/protocol.h>
1066  
1067  /* IP Cache bits. */
1068  /* Src IP address. */
1069 @@ -85,6 +87,58 @@
1070     Returns true or false. */
1071  extern int skb_ip_make_writable(struct sk_buff **pskb,
1072                                 unsigned int writable_len);
1073 +
1074 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1075 +#include <net/route.h>
1076 +#include <net/xfrm.h>
1077 +
1078 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1079 +{
1080 +       return !skb->sp || skb->sp->decap_done;
1081 +}
1082 +
1083 +static inline int
1084 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1085 +{
1086 +       return skb->sp && !skb->sp->decap_done
1087 +              && (!ipprot || !ipprot->xfrm_prot);
1088 +}
1089 +
1090 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1091 +{
1092 +       return skb->sp && !skb->sp->decap_done
1093 +              && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1094 +}
1095 +
1096 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1097 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1098 +#else /* CONFIG_XFRM */
1099 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1100 +{
1101 +       return 1;
1102 +}
1103 +
1104 +static inline int
1105 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1106 +{
1107 +       return 0;
1108 +}
1109 +
1110 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1111 +{
1112 +       return 0;
1113 +}
1114 +
1115 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1116 +{
1117 +       return 0;
1118 +}
1119 +
1120 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1121 +{
1122 +       return 0; 
1123 +}
1124 +#endif /* CONFIG_XFRM */
1125  #endif /*__KERNEL__*/
1126  
1127  #endif /*__LINUX_IP_NETFILTER_H*/
1128 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h
1129 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h       2004-04-28 03:36:37.000000000 +0200
1130 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h   2004-04-29 11:17:15.000000000 +0200
1131 @@ -140,6 +140,12 @@
1132         /* Back pointer */
1133         unsigned int comefrom;
1134  
1135 +       /* Name of the chain */
1136 +       char *chainname;
1137 +       
1138 +       /* Rule number in the chain. */
1139 +       u_int32_t rulenum;
1140 +
1141         /* Packet and byte counters. */
1142         struct ip6t_counters counters;
1143  
1144 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h
1145 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h       2004-04-28 03:36:03.000000000 +0200
1146 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h   2004-04-29 11:19:40.000000000 +0200
1147 @@ -6,12 +6,14 @@
1148  #define IP6T_OWNER_GID 0x02
1149  #define IP6T_OWNER_PID 0x04
1150  #define IP6T_OWNER_SID 0x08
1151 +#define IP6T_OWNER_COMM 0x10
1152  
1153  struct ip6t_owner_info {
1154      uid_t uid;
1155      gid_t gid;
1156      pid_t pid;
1157      pid_t sid;
1158 +    char comm[16];
1159      u_int8_t match, invert;    /* flags */
1160  };
1161  
1162 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h
1163 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h      1970-01-01 01:00:00.000000000 +0100
1164 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h  2004-04-29 11:19:41.000000000 +0200
1165 @@ -0,0 +1,52 @@
1166 +#ifndef _IP6T_POLICY_H\r
1167 +#define _IP6T_POLICY_H\r
1168 +\r
1169 +#define POLICY_MAX_ELEM        4\r
1170 +\r
1171 +enum ip6t_policy_flags\r
1172 +{\r
1173 +       POLICY_MATCH_IN         = 0x1,\r
1174 +       POLICY_MATCH_OUT        = 0x2,\r
1175 +       POLICY_MATCH_NONE       = 0x4,\r
1176 +       POLICY_MATCH_STRICT     = 0x8,\r
1177 +};\r
1178 +\r
1179 +enum ip6t_policy_modes\r
1180 +{\r
1181 +       POLICY_MODE_TRANSPORT,\r
1182 +       POLICY_MODE_TUNNEL\r
1183 +};\r
1184 +\r
1185 +struct ip6t_policy_spec\r
1186 +{\r
1187 +       u_int8_t        saddr:1,\r
1188 +                       daddr:1,\r
1189 +                       proto:1,\r
1190 +                       mode:1,\r
1191 +                       spi:1,\r
1192 +                       reqid:1;\r
1193 +};\r
1194 +\r
1195 +struct ip6t_policy_elem\r
1196 +{\r
1197 +       struct in6_addr saddr;\r
1198 +       struct in6_addr smask;\r
1199 +       struct in6_addr daddr;\r
1200 +       struct in6_addr dmask;\r
1201 +       u_int32_t       spi;\r
1202 +       u_int32_t       reqid;\r
1203 +       u_int8_t        proto;\r
1204 +       u_int8_t        mode;\r
1205 +\r
1206 +       struct ip6t_policy_spec match;\r
1207 +       struct ip6t_policy_spec invert;\r
1208 +};\r
1209 +\r
1210 +struct ip6t_policy_info\r
1211 +{\r
1212 +       struct ip6t_policy_elem pol[POLICY_MAX_ELEM];\r
1213 +       u_int16_t flags;\r
1214 +       u_int16_t len;\r
1215 +};\r
1216 +\r
1217 +#endif /* _IP6T_POLICY_H */\r
1218 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/linux/netfilter_mime.h linux-2.6.6-rc3/include/linux/netfilter_mime.h
1219 --- linux-2.6.6-rc3.org/include/linux/netfilter_mime.h  1970-01-01 01:00:00.000000000 +0100
1220 +++ linux-2.6.6-rc3/include/linux/netfilter_mime.h      2004-04-29 11:20:13.000000000 +0200
1221 @@ -0,0 +1,89 @@
1222 +/*
1223 + * MIME functions for netfilter modules.  This file provides implementations
1224 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
1225 + * HTTP, RTSP, SIP, etc.
1226 + *
1227 + * gcc will warn for defined but unused functions, so we only include the
1228 + * functions requested.  The following macros are used:
1229 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
1230 + */
1231 +#ifndef _NETFILTER_MIME_H
1232 +#define _NETFILTER_MIME_H
1233 +
1234 +/* Only include these functions for kernel code. */
1235 +#ifdef __KERNEL__
1236 +
1237 +#include <linux/ctype.h>
1238 +
1239 +/*
1240 + * Given a buffer and length, advance to the next line and mark the current
1241 + * line.  If the current line is empty, *plinelen will be set to zero.  If
1242 + * not, it will be set to the actual line length (including CRLF).
1243 + *
1244 + * 'line' in this context means logical line (includes LWS continuations).
1245 + * Returns 1 on success, 0 on failure.
1246 + */
1247 +#ifdef NF_NEED_MIME_NEXTLINE
1248 +static int
1249 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1250 +{
1251 +    uint    off = *poff;
1252 +    uint    physlen = 0;
1253 +    int     is_first_line = 1;
1254 +
1255 +    if (off >= len)
1256 +    {
1257 +        return 0;
1258 +    }
1259 +
1260 +    do
1261 +    {
1262 +        while (p[off] != '\n')
1263 +        {
1264 +            if (len-off <= 1)
1265 +            {
1266 +                return 0;
1267 +            }
1268 +
1269 +            physlen++;
1270 +            off++;
1271 +        }
1272 +
1273 +        /* if we saw a crlf, physlen needs adjusted */
1274 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1275 +        {
1276 +            physlen--;
1277 +        }
1278 +
1279 +        /* advance past the newline */
1280 +        off++;
1281 +
1282 +        /* check for an empty line */
1283 +        if (physlen == 0)
1284 +        {
1285 +            break;
1286 +        }
1287 +
1288 +        /* check for colon on the first physical line */
1289 +        if (is_first_line)
1290 +        {
1291 +            is_first_line = 0;
1292 +            if (memchr(p+(*poff), ':', physlen) == NULL)
1293 +            {
1294 +                return 0;
1295 +            }
1296 +        }
1297 +    }
1298 +    while (p[off] == ' ' || p[off] == '\t');
1299 +
1300 +    *plineoff = *poff;
1301 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
1302 +    *poff = off;
1303 +
1304 +    return 1;
1305 +}
1306 +#endif /* NF_NEED_MIME_NEXTLINE */
1307 +
1308 +#endif /* __KERNEL__ */
1309 +
1310 +#endif /* _NETFILTER_MIME_H */
1311 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/ip.h linux-2.6.6-rc3/include/net/ip.h
1312 --- linux-2.6.6-rc3.org/include/net/ip.h        2004-04-28 03:36:16.000000000 +0200
1313 +++ linux-2.6.6-rc3/include/net/ip.h    2004-04-29 11:18:02.000000000 +0200
1314 @@ -30,6 +30,8 @@
1315  #include <linux/netdevice.h>
1316  #include <linux/inetdevice.h>
1317  #include <linux/in_route.h>
1318 +#include <linux/netfilter.h>
1319 +#include <linux/netfilter_ipv4.h>
1320  #include <net/route.h>
1321  #include <net/arp.h>
1322  
1323 @@ -48,6 +50,7 @@
1324  #define IPSKB_TRANSLATED       2
1325  #define IPSKB_FORWARDED                4
1326  #define IPSKB_XFRM_TUNNEL_SIZE 8
1327 +#define IPSKB_XFRM_TRANSFORMED 16
1328  };
1329  
1330  struct ipcm_cookie
1331 @@ -212,6 +215,12 @@
1332                 __ip_select_ident(iph, dst, more);
1333  }
1334  
1335 +extern inline int ip_dst_output(struct sk_buff *skb)
1336 +{
1337 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1338 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1339 +}
1340 +
1341  /*
1342   *     Map a multicast IP onto multicast MAC for type ethernet.
1343   */
1344 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/protocol.h linux-2.6.6-rc3/include/net/protocol.h
1345 --- linux-2.6.6-rc3.org/include/net/protocol.h  2004-04-28 03:35:44.000000000 +0200
1346 +++ linux-2.6.6-rc3/include/net/protocol.h      2004-04-29 11:18:03.000000000 +0200
1347 @@ -39,6 +39,7 @@
1348         int                     (*handler)(struct sk_buff *skb);
1349         void                    (*err_handler)(struct sk_buff *skb, u32 info);
1350         int                     no_policy;
1351 +       int                     xfrm_prot;
1352  };
1353  
1354  #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
1355 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/tcp.h linux-2.6.6-rc3/include/net/tcp.h
1356 --- linux-2.6.6-rc3.org/include/net/tcp.h       2004-04-29 11:24:38.000000000 +0200
1357 +++ linux-2.6.6-rc3/include/net/tcp.h   2004-04-29 11:19:32.000000000 +0200
1358 @@ -162,6 +162,7 @@
1359  extern void tcp_bucket_unlock(struct sock *sk);
1360  extern int tcp_port_rover;
1361  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
1362 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
1363  
1364  /* These are AF independent. */
1365  static __inline__ int tcp_bhashfn(__u16 lport)
1366 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/udp.h linux-2.6.6-rc3/include/net/udp.h
1367 --- linux-2.6.6-rc3.org/include/net/udp.h       2004-04-28 03:36:29.000000000 +0200
1368 +++ linux-2.6.6-rc3/include/net/udp.h   2004-04-29 11:19:32.000000000 +0200
1369 @@ -74,6 +74,8 @@
1370  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
1371  extern int     udp_disconnect(struct sock *sk, int flags);
1372  
1373 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
1374 +
1375  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
1376  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
1377  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
1378 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/include/net/xfrm.h linux-2.6.6-rc3/include/net/xfrm.h
1379 --- linux-2.6.6-rc3.org/include/net/xfrm.h      2004-04-28 03:36:31.000000000 +0200
1380 +++ linux-2.6.6-rc3/include/net/xfrm.h  2004-04-29 11:18:03.000000000 +0200
1381 @@ -540,6 +540,9 @@
1382  {
1383         atomic_t                refcnt;
1384         int                     len;
1385 +#ifdef CONFIG_NETFILTER
1386 +       int                     decap_done;
1387 +#endif
1388         struct sec_decap_state  x[XFRM_MAX_DEPTH];
1389  };
1390  
1391 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/core/netfilter.c linux-2.6.6-rc3/net/core/netfilter.c
1392 --- linux-2.6.6-rc3.org/net/core/netfilter.c    2004-04-28 03:35:46.000000000 +0200
1393 +++ linux-2.6.6-rc3/net/core/netfilter.c        2004-04-29 11:18:06.000000000 +0200
1394 @@ -27,6 +27,8 @@
1395  #include <linux/icmp.h>
1396  #include <net/sock.h>
1397  #include <net/route.h>
1398 +#include <net/xfrm.h>
1399 +#include <net/ip.h>
1400  #include <linux/ip.h>
1401  
1402  /* In this code, we can be waiting indefinitely for userspace to
1403 @@ -638,7 +640,6 @@
1404  #ifdef CONFIG_IP_ROUTE_FWMARK
1405                 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
1406  #endif
1407 -               fl.proto = iph->protocol;
1408                 if (ip_route_output_key(&rt, &fl) != 0)
1409                         return -1;
1410  
1411 @@ -665,6 +666,20 @@
1412         if ((*pskb)->dst->error)
1413                 return -1;
1414  
1415 +#ifdef CONFIG_XFRM
1416 +       if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
1417 +               struct xfrm_policy_afinfo *afinfo;
1418 +
1419 +               afinfo = xfrm_policy_get_afinfo(AF_INET);
1420 +               if (afinfo != NULL) {
1421 +                       afinfo->decode_session(*pskb, &fl);
1422 +                       xfrm_policy_put_afinfo(afinfo);
1423 +                       if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
1424 +                               return -1;
1425 +               }
1426 +       }
1427 +#endif
1428 +
1429         /* Change in oif may mean change in hh_len. */
1430         hh_len = (*pskb)->dst->dev->hard_header_len;
1431         if (skb_headroom(*pskb) < hh_len) {
1432 @@ -682,6 +697,71 @@
1433         return 0;
1434  }
1435  
1436 +#ifdef CONFIG_XFRM
1437 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1438 +{
1439 +       skb->sp->decap_done = 1;
1440 +       dst_release(skb->dst);
1441 +       skb->dst = NULL;
1442 +       nf_reset(skb);
1443 +       return netif_rx(skb);
1444 +}
1445 +
1446 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
1447 +{
1448 +       __skb_push(skb, skb->data - skb->nh.raw);
1449 +       /* Fix header len and checksum if last xfrm was transport mode */
1450 +       if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
1451 +               skb->nh.iph->tot_len = htons(skb->len);
1452 +               ip_send_check(skb->nh.iph);
1453 +       }
1454 +       return nf_rcv_postxfrm_nonlocal(skb);
1455 +}
1456 +
1457 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1458 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1459 +#include <linux/netfilter_ipv4/ip_nat.h>
1460 +
1461 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
1462 +{
1463 +       struct ip_conntrack *ct;
1464 +       struct ip_conntrack_tuple *t;
1465 +       struct ip_nat_info_manip *m;
1466 +       unsigned int i;
1467 +
1468 +       if (skb->nfct == NULL)
1469 +               return;
1470 +       ct = (struct ip_conntrack *)skb->nfct->master;
1471 +
1472 +       for (i = 0; i < ct->nat.info.num_manips; i++) {
1473 +               m = &ct->nat.info.manips[i];
1474 +               t = &ct->tuplehash[m->direction].tuple;
1475 +
1476 +               switch (m->hooknum) {
1477 +               case NF_IP_PRE_ROUTING:
1478 +                       if (m->maniptype != IP_NAT_MANIP_DST)
1479 +                               break;
1480 +                       fl->fl4_dst = t->dst.ip;
1481 +                       if (t->dst.protonum == IPPROTO_TCP ||
1482 +                           t->dst.protonum == IPPROTO_UDP)
1483 +                               fl->fl_ip_dport = t->dst.u.tcp.port;
1484 +                       break;
1485 +#ifdef CONFIG_IP_NF_NAT_LOCAL
1486 +               case NF_IP_LOCAL_IN:
1487 +                       if (m->maniptype != IP_NAT_MANIP_SRC)
1488 +                               break;
1489 +                       fl->fl4_src = t->src.ip;
1490 +                       if (t->dst.protonum == IPPROTO_TCP ||
1491 +                           t->dst.protonum == IPPROTO_UDP)
1492 +                               fl->fl_ip_sport = t->src.u.tcp.port;
1493 +                       break;
1494 +#endif
1495 +               }
1496 +       }
1497 +}
1498 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
1499 +#endif
1500 +
1501  int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
1502  {
1503         struct sk_buff *nskb;
1504 @@ -839,3 +919,4 @@
1505  EXPORT_SYMBOL(nf_unregister_hook);
1506  EXPORT_SYMBOL(nf_unregister_queue_handler);
1507  EXPORT_SYMBOL(nf_unregister_sockopt);
1508 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
1509 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ah4.c linux-2.6.6-rc3/net/ipv4/ah4.c
1510 --- linux-2.6.6-rc3.org/net/ipv4/ah4.c  2004-04-28 03:36:34.000000000 +0200
1511 +++ linux-2.6.6-rc3/net/ipv4/ah4.c      2004-04-29 11:18:03.000000000 +0200
1512 @@ -145,6 +145,7 @@
1513                 err = -EHOSTUNREACH;
1514                 goto error_nolock;
1515         }
1516 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1517         return NET_XMIT_BYPASS;
1518  
1519  error:
1520 @@ -343,6 +344,7 @@
1521         .handler        =       xfrm4_rcv,
1522         .err_handler    =       ah4_err,
1523         .no_policy      =       1,
1524 +       .xfrm_prot      =       1,
1525  };
1526  
1527  static int __init ah4_init(void)
1528 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/esp4.c linux-2.6.6-rc3/net/ipv4/esp4.c
1529 --- linux-2.6.6-rc3.org/net/ipv4/esp4.c 2004-04-28 03:36:01.000000000 +0200
1530 +++ linux-2.6.6-rc3/net/ipv4/esp4.c     2004-04-29 11:18:03.000000000 +0200
1531 @@ -216,6 +216,7 @@
1532                 err = -EHOSTUNREACH;
1533                 goto error_nolock;
1534         }
1535 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1536         return NET_XMIT_BYPASS;
1537  
1538  error:
1539 @@ -598,6 +599,7 @@
1540         .handler        =       xfrm4_rcv,
1541         .err_handler    =       esp4_err,
1542         .no_policy      =       1,
1543 +       .xfrm_prot      =       1,
1544  };
1545  
1546  static int __init esp4_init(void)
1547 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/igmp.c linux-2.6.6-rc3/net/ipv4/igmp.c
1548 --- linux-2.6.6-rc3.org/net/ipv4/igmp.c 2004-04-28 03:36:55.000000000 +0200
1549 +++ linux-2.6.6-rc3/net/ipv4/igmp.c     2004-04-29 11:18:02.000000000 +0200
1550 @@ -342,7 +342,7 @@
1551         pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
1552  
1553         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
1554 -                      dst_output);
1555 +                      ip_dst_output);
1556  }
1557  
1558  static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
1559 @@ -672,7 +672,7 @@
1560         ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
1561  
1562         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1563 -                      dst_output);
1564 +                      ip_dst_output);
1565  }
1566  
1567  static void igmp_gq_timer_expire(unsigned long data)
1568 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_forward.c linux-2.6.6-rc3/net/ipv4/ip_forward.c
1569 --- linux-2.6.6-rc3.org/net/ipv4/ip_forward.c   2004-04-28 03:34:59.000000000 +0200
1570 +++ linux-2.6.6-rc3/net/ipv4/ip_forward.c       2004-04-29 11:18:03.000000000 +0200
1571 @@ -51,7 +51,7 @@
1572         if (unlikely(opt->optlen))
1573                 ip_forward_options(skb);
1574  
1575 -       return dst_output(skb);
1576 +       return ip_dst_output(skb);
1577  }
1578  
1579  int ip_forward(struct sk_buff *skb)
1580 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
1581 --- linux-2.6.6-rc3.org/net/ipv4/ip_input.c     2004-04-29 11:24:39.000000000 +0200
1582 +++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-29 11:18:06.000000000 +0200
1583 @@ -206,10 +206,6 @@
1584  
1585         __skb_pull(skb, ihl);
1586  
1587 -       /* Free reference early: we don't need it any more, and it may
1588 -           hold ip_conntrack module loaded indefinitely. */
1589 -       nf_reset(skb);
1590 -
1591          /* Point into the IP datagram, just past the header. */
1592          skb->h.raw = skb->data;
1593  
1594 @@ -224,6 +220,13 @@
1595         resubmit:
1596                 hash = protocol & (MAX_INET_PROTOS - 1);
1597                 raw_sk = sk_head(&raw_v4_htable[hash]);
1598 +               ipprot = inet_protos[hash];
1599 +               smp_read_barrier_depends();
1600 +
1601 +               if (nf_xfrm_local_done(skb, ipprot)) {
1602 +                       nf_rcv_postxfrm_local(skb);
1603 +                       goto out;
1604 +               }
1605  
1606                 /* If there maybe a raw socket we must check - if not we
1607                  * don't care less
1608 @@ -231,14 +234,15 @@
1609                 if (raw_sk)
1610                         raw_v4_input(skb, skb->nh.iph, hash);
1611  
1612 -               if ((ipprot = inet_protos[hash]) != NULL) {
1613 +               if (ipprot != NULL) {
1614                         int ret;
1615  
1616 -                       smp_read_barrier_depends();
1617 -                       if (!ipprot->no_policy &&
1618 -                           !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1619 -                               kfree_skb(skb);
1620 -                               goto out;
1621 +                       if (!ipprot->no_policy) {
1622 +                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1623 +                                       kfree_skb(skb);
1624 +                                       goto out;
1625 +                               }
1626 +                               nf_reset(skb);
1627                         }
1628                         ret = ipprot->handler(skb);
1629                         if (ret < 0) {
1630 @@ -279,8 +283,8 @@
1631                         return 0;
1632         }
1633  
1634 -       return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1635 -                      ip_local_deliver_finish);
1636 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
1637 +                           ip_local_deliver_finish, nf_hook_input_cond(skb));
1638  }
1639  
1640  static inline int ip_rcv_finish(struct sk_buff *skb)
1641 @@ -297,6 +301,9 @@
1642                         goto drop; 
1643         }
1644  
1645 +       if (nf_xfrm_nonlocal_done(skb))
1646 +               return nf_rcv_postxfrm_nonlocal(skb);
1647 +
1648  #ifdef CONFIG_NET_CLS_ROUTE
1649         if (skb->dst->tclassid) {
1650                 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
1651 @@ -418,8 +425,8 @@
1652                 }
1653         }
1654  
1655 -       return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1656 -                      ip_rcv_finish);
1657 +       return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
1658 +                           ip_rcv_finish, nf_hook_input_cond(skb));
1659  
1660  inhdr_error:
1661         IP_INC_STATS_BH(IpInHdrErrors);
1662 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ip_output.c linux-2.6.6-rc3/net/ipv4/ip_output.c
1663 --- linux-2.6.6-rc3.org/net/ipv4/ip_output.c    2004-04-28 03:36:55.000000000 +0200
1664 +++ linux-2.6.6-rc3/net/ipv4/ip_output.c        2004-04-29 11:18:03.000000000 +0200
1665 @@ -123,6 +123,15 @@
1666         return ttl;
1667  }
1668  
1669 +#ifdef CONFIG_NETFILTER
1670 +/* out-of-line copy is only required with netfilter */
1671 +int ip_dst_output(struct sk_buff *skb)
1672 +{
1673 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
1674 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
1675 +}
1676 +#endif
1677 +
1678  /* 
1679   *             Add an ip header to a skbuff and send it out.
1680   *
1681 @@ -165,7 +174,7 @@
1682  
1683         /* Send it out. */
1684         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1685 -                      dst_output);
1686 +                      ip_dst_output);
1687  }
1688  
1689  static inline int ip_finish_output2(struct sk_buff *skb)
1690 @@ -283,7 +292,7 @@
1691                 return ip_finish_output(skb);
1692  }
1693  
1694 -int ip_output(struct sk_buff *skb)
1695 +static inline int ip_output2(struct sk_buff *skb)
1696  {
1697         IP_INC_STATS(IpOutRequests);
1698  
1699 @@ -294,6 +303,16 @@
1700                 return ip_finish_output(skb);
1701  }
1702  
1703 +int ip_output(struct sk_buff *skb)
1704 +{
1705 +       int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
1706 +
1707 +       if (transformed)
1708 +               nf_reset(skb);
1709 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
1710 +                           skb->dst->dev, ip_output2, transformed);
1711 +}
1712 +
1713  int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
1714  {
1715         struct sock *sk = skb->sk;
1716 @@ -387,7 +406,7 @@
1717         skb->priority = sk->sk_priority;
1718  
1719         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
1720 -                      dst_output);
1721 +                      ip_dst_output);
1722  
1723  no_route:
1724         IP_INC_STATS(IpOutNoRoutes);
1725 @@ -1177,7 +1196,7 @@
1726  
1727         /* Netfilter gets whole the not fragmented skb. */
1728         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
1729 -                     skb->dst->dev, dst_output);
1730 +                     skb->dst->dev, ip_dst_output);
1731         if (err) {
1732                 if (err > 0)
1733                         err = inet->recverr ? net_xmit_errno(err) : 0;
1734 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipcomp.c linux-2.6.6-rc3/net/ipv4/ipcomp.c
1735 --- linux-2.6.6-rc3.org/net/ipv4/ipcomp.c       2004-04-28 03:36:33.000000000 +0200
1736 +++ linux-2.6.6-rc3/net/ipv4/ipcomp.c   2004-04-29 11:18:03.000000000 +0200
1737 @@ -231,6 +231,7 @@
1738                 err = -EHOSTUNREACH;
1739                 goto error_nolock;
1740         }
1741 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
1742         err = NET_XMIT_BYPASS;
1743  
1744  out_exit:
1745 @@ -407,6 +408,7 @@
1746         .handler        =       xfrm4_rcv,
1747         .err_handler    =       ipcomp4_err,
1748         .no_policy      =       1,
1749 +       .xfrm_prot      =       1,
1750  };
1751  
1752  static int __init ipcomp4_init(void)
1753 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
1754 --- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-29 11:24:39.000000000 +0200
1755 +++ linux-2.6.6-rc3/net/ipv4/ipip.c     2004-04-29 11:18:03.000000000 +0200
1756 @@ -478,6 +478,11 @@
1757  
1758         read_lock(&ipip_lock);
1759         if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
1760 +               /* IPIP packets decapsulated by IPsec missed netfilter hooks */
1761 +               if (nf_xfrm_local_done(skb, NULL)) {
1762 +                       nf_rcv_postxfrm_local(skb);
1763 +                       return 0;
1764 +               }
1765                 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1766                         kfree_skb(skb);
1767                         return 0;
1768 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/ipmr.c linux-2.6.6-rc3/net/ipv4/ipmr.c
1769 --- linux-2.6.6-rc3.org/net/ipv4/ipmr.c 2004-04-28 03:35:47.000000000 +0200
1770 +++ linux-2.6.6-rc3/net/ipv4/ipmr.c     2004-04-29 11:18:03.000000000 +0200
1771 @@ -1120,7 +1120,7 @@
1772         if (unlikely(opt->optlen))
1773                 ip_forward_options(skb);
1774  
1775 -       return dst_output(skb);
1776 +       return ip_dst_output(skb);
1777  }
1778  
1779  /*
1780 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
1781 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig      2004-04-29 11:24:40.000000000 +0200
1782 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig  2004-04-29 11:21:43.000000000 +0200
1783 @@ -206,6 +206,11 @@
1784  
1785           To compile it as a module, choose M here.  If unsure, say N.
1786  
1787 +config IP_NF_MATCH_UNCLEAN
1788 +       tristate  'unclean match support (EXPERIMENTAL)'
1789 +       depends on EXPERIMENTAL && IP_NF_IPTABLES
1790 +         help
1791 +
1792  config IP_NF_MATCH_TTL
1793         tristate "TTL match support"
1794         depends on IP_NF_IPTABLES
1795 @@ -706,5 +711,149 @@
1796         depends on IP_NF_IPTABLES
1797           help
1798  
1799 +config IP_NF_CONNTRACK_MARK
1800 +       bool  'Connection mark tracking support'
1801 +config IP_NF_TARGET_CONNMARK
1802 +       tristate  'CONNMARK target support'
1803 +       depends on IP_NF_MANGLE
1804 +config IP_NF_MATCH_CONNMARK
1805 +       tristate  ' Connection mark match support'
1806 +       depends on IP_NF_IPTABLES
1807 +         help
1808 +
1809 +config IP_NF_TARGET_IPMARK
1810 +       tristate  'IPMARK target support'
1811 +       depends on IP_NF_MANGLE
1812 +         help
1813 +
1814 +config IP_NF_TARGET_TARPIT
1815 +       tristate 'TARPIT target support'
1816 +       depends on IP_NF_FILTER
1817 +         help
1818 +
1819 +config IP_NF_TARGET_TRACE
1820 +       tristate  'TRACE target support'
1821 +       depends on IP_NF_RAW
1822 +       help
1823 +         The TRACE target allows packets to be traced as those
1824 +         matches any subsequent rule in any table/rule. The matched
1825 +         rule and the packet is logged with the prefix
1826 +       
1827 +         TRACE: tablename/chainname/rulenum  
1828 +       
1829 +         If you want to compile it as a module, say M here and read
1830 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
1831 +         help
1832 +
1833 +config IP_NF_TARGET_XOR
1834 +       tristate  'XOR target support'
1835 +       depends on IP_NF_MANGLE
1836 +         help
1837 +
1838 +config IP_NF_MATCH_ADDRTYPE
1839 +       tristate  'address type match support'
1840 +       depends on IP_NF_IPTABLES
1841 +         help
1842 +
1843 +config IP_NF_NAT_CUSEEME
1844 +       tristate
1845 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1846 +       default IP_NF_NAT if IP_NF_CUSEEME=y
1847 +       default m if IP_NF_CUSEEME=m
1848 +
1849 +config IP_NF_CUSEEME
1850 +       tristate  'CuSeeMe protocol support'
1851 +       depends on IP_NF_CONNTRACK
1852 +         help
1853 +
1854 +config IP_NF_EGG
1855 +       tristate  'Eggdrop bot support'
1856 +       depends on IP_NF_CONNTRACK
1857 +         help
1858 +
1859 +config IP_NF_NAT_H323
1860 +       tristate
1861 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1862 +       default IP_NF_NAT if IP_NF_H323=y
1863 +       default m if IP_NF_H323=m
1864 +
1865 +config IP_NF_H323
1866 +       tristate  'H.323 (netmeeting) support'
1867 +       depends on IP_NF_CONNTRACK
1868 +         help
1869 +
1870 +config IP_NF_NAT_MMS
1871 +       tristate
1872 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1873 +       default IP_NF_NAT if IP_NF_MMS=y
1874 +       default m if IP_NF_MMS=m
1875 +
1876 +config IP_NF_MMS
1877 +       tristate  'MMS protocol support'
1878 +       depends on IP_NF_CONNTRACK
1879 +         help
1880 +
1881 +config IP_NF_MATCH_POLICY
1882 +       tristate "IPsec policy match support"
1883 +       depends on IP_NF_IPTABLES && XFRM
1884 +       help
1885 +         Policy matching allows you to match packets based on the
1886 +         IPsec policy that was used during decapsulation/will
1887 +         be used during encapsulation.
1888 +
1889 +         To compile it as a module, choose M here.  If unsure, say N.
1890 +         help
1891 +
1892 +config IP_NF_NAT_QUAKE3
1893 +       tristate
1894 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
1895 +       default IP_NF_NAT if IP_NF_QUAKE3=y
1896 +       default m if IP_NF_QUAKE3=m
1897 +
1898 +config IP_NF_QUAKE3
1899 +       tristate "Quake3 protocol support"
1900 +       depends on IP_NF_CONNTRACK
1901 +         help
1902 +
1903 +config IP_NF_MATCH_RPC
1904 +       tristate  'RPC match support'
1905 +       depends on IP_NF_CONNTRACK && IP_NF_IPTABLES
1906 +         help
1907 +
1908 +config IP_NF_RSH
1909 +       tristate  'RSH protocol support'
1910 +       depends on IP_NF_CONNTRACK
1911 +         help
1912 +
1913 +config IP_NF_NAT_RTSP
1914 +       tristate
1915 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1916 +       default IP_NF_NAT if IP_NF_RTSP=y
1917 +       default m if IP_NF_RTSP=m
1918 +config IP_NF_RTSP
1919 +       tristate  ' RTSP protocol support'
1920 +       depends on IP_NF_CONNTRACK
1921 +         help
1922 +
1923 +config IP_NF_CT_PROTO_SCTP
1924 +       tristate  'SCTP protocol connection tracking support'
1925 +       depends on IP_NF_CONNTRACK
1926 +         help
1927 +
1928 +config IP_NF_MATCH_STRING
1929 +       tristate  'String match support'
1930 +       depends on IP_NF_IPTABLES
1931 +         help
1932 +
1933 +config IP_NF_NAT_TALK
1934 +       tristate
1935 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
1936 +       default IP_NF_NAT if IP_NF_TALK=y
1937 +       default m if IP_NF_TALK=m
1938 +config IP_NF_TALK
1939 +       tristate  'talk protocol support'
1940 +       depends on IP_NF_CONNTRACK
1941 +         help
1942 +
1943  endmenu
1944  
1945 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
1946 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile     2004-04-29 11:24:40.000000000 +0200
1947 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-29 11:21:43.000000000 +0200
1948 @@ -19,17 +19,44 @@
1949  # connection tracking
1950  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
1951  
1952 +# talk protocol support
1953 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
1954 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
1955 +
1956 +
1957 +# SCTP protocol connection tracking
1958 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
1959
1960 +# H.323 support
1961 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
1962 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
1963 +
1964 +
1965  # connection tracking helpers
1966 +
1967 +# rtsp protocol support
1968 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
1969 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
1970 +
1971 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
1972 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
1973  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
1974  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
1975  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
1976 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
1977 +
1978 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
1979 +
1980  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
1981  
1982  # NAT helpers 
1983 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
1984  obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
1985  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
1986  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
1987  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
1988 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
1989 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
1990  
1991  # generic IP tables 
1992  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
1993 @@ -41,6 +83,8 @@
1994  obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
1995  
1996  # matches
1997 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
1998 +
1999  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
2000  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
2001  obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
2002 @@ -87,14 +132,19 @@
2003  obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
2004  
2005  
2006 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
2007 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
2008  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
2009  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
2010 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
2011  obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
2012  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
2013  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
2014 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
2015  obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
2016  
2017  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
2018 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
2019  
2020  # targets
2021  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
2022 @@ -102,6 +152,8 @@
2023  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
2024  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
2025  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
2026 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
2027 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
2028  obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
2029  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
2030  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
2031 @@ -110,11 +162,14 @@
2032  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
2033  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
2034  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
2035 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
2036 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
2037  obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
2038  obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
2039  obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
2040  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
2041  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
2042 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
2043  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
2044  
2045  # generic ARP tables
2046 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c
2047 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c  2004-04-29 11:24:39.000000000 +0200
2048 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c      2004-04-29 11:11:00.000000000 +0200
2049 @@ -718,6 +718,9 @@
2050                  __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
2051                  conntrack->master = expected;
2052                  expected->sibling = conntrack;
2053 +#if CONFIG_IP_NF_CONNTRACK_MARK
2054 +               conntrack->mark = expected->expectant->mark;
2055 +#endif
2056                  LIST_DELETE(&ip_conntrack_expect_list, expected);
2057                  expected->expectant->expecting--;
2058                  nf_conntrack_get(&master_ct(conntrack)->infos[0]);
2059 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
2060 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c   1970-01-01 01:00:00.000000000 +0100
2061 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c       2004-04-29 11:17:59.000000000 +0200
2062 @@ -0,0 +1,237 @@
2063 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
2064 + * based on ip_conntrack_irc.c 
2065 + *
2066 + *      This module only supports the share userfile-send command,
2067 + *      used by eggdrops to share it's userfile.
2068 + *
2069 + *      There are no support for NAT at the moment.
2070 + *
2071 + *      This program is free software; you can redistribute it and/or
2072 + *      modify it under the terms of the GNU General Public License
2073 + *      as published by the Free Software Foundation; either version
2074 + *      2 of the License, or (at your option) any later version.
2075 + *
2076 + *     Module load syntax:
2077 + *     
2078 + *     please give the ports of all Eggdrops You have running
2079 + *      on your system, the default port is 3333.
2080 + *
2081 + *      2001-04-19: Security update. IP addresses are now compared
2082 + *                  to prevent unauthorized "related" access.
2083 + *
2084 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
2085 + *                 Port to netfilter 'newnat' API.
2086 + */
2087 +
2088 +#include <linux/module.h>
2089 +#include <linux/netfilter.h>
2090 +#include <linux/ip.h>
2091 +#include <net/checksum.h>
2092 +#include <net/tcp.h>
2093 +
2094 +#include <linux/netfilter_ipv4/lockhelp.h>
2095 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2096 +
2097 +#define MAX_PORTS 8
2098 +static int ports[MAX_PORTS];
2099 +static int ports_c = 0;
2100 +static unsigned int egg_timeout = 300;
2101 +
2102 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
2103 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
2104 +MODULE_LICENSE("GPL");
2105 +#ifdef MODULE_PARM
2106 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2107 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
2108 +#endif
2109 +
2110 +DECLARE_LOCK(ip_egg_lock);
2111 +struct module *ip_conntrack_egg = THIS_MODULE;
2112 +
2113 +#if 0
2114 +#define DEBUGP printk
2115 +#else
2116 +#define DEBUGP(format, args...)
2117 +#endif
2118 +
2119 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
2120 +/* tries to get the ip_addr and port out of a eggdrop command
2121 +   return value: -1 on failure, 0 on success 
2122 +   data                pointer to first byte of DCC command data
2123 +   data_end    pointer to last byte of dcc command data
2124 +   ip          returns parsed ip of dcc command
2125 +   port                returns parsed port of dcc command */
2126 +{
2127 +       if (data > data_end)
2128 +               return -1;
2129 +       
2130 +       *ip = simple_strtoul(data, &data, 10);
2131 +
2132 +       /* skip blanks between ip and port */
2133 +       while (*data == ' ' && data < data_end)
2134 +               data++;
2135 +
2136 +       *port = simple_strtoul(data, &data, 10);
2137 +       return 0;
2138 +}
2139 +
2140 +
2141 +static int help(const struct iphdr *iph, size_t len,
2142 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
2143 +{
2144 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
2145 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
2146 +       char *data = (char *) tcph + tcph->doff * 4;
2147 +       char *data_limit;
2148 +       u_int32_t tcplen = len - iph->ihl * 4;
2149 +       u_int32_t datalen = tcplen - tcph->doff * 4;
2150 +       int dir = CTINFO2DIR(ctinfo);
2151 +       int bytes_scanned = 0;
2152 +       struct ip_conntrack_expect exp;
2153 +
2154 +       u_int32_t egg_ip;
2155 +       u_int16_t egg_port;
2156 +
2157 +       DEBUGP("entered\n");
2158 +
2159 +       /* If packet is coming from IRC server */
2160 +       if (dir != IP_CT_DIR_REPLY)
2161 +               return NF_ACCEPT;
2162 +
2163 +       /* Until there's been traffic both ways, don't look in packets. */
2164 +       if (ctinfo != IP_CT_ESTABLISHED
2165 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2166 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
2167 +               return NF_ACCEPT;
2168 +       }
2169 +
2170 +       /* Not whole TCP header? */
2171 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
2172 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
2173 +               return NF_ACCEPT;
2174 +       }
2175 +
2176 +       /* Checksum invalid?  Ignore. */
2177 +       /* FIXME: Source route IP option packets --RR */
2178 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2179 +                        csum_partial((char *) tcph, tcplen, 0))) {
2180 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
2181 +                       tcph, tcplen, NIPQUAD(iph->saddr),
2182 +                       NIPQUAD(iph->daddr));
2183 +               return NF_ACCEPT;
2184 +       }
2185 +
2186 +       data_limit = (char *) data + datalen;
2187 +       while (datalen > 5 && bytes_scanned < 128) {
2188 +               if (memcmp(data, "s us ", 5)) {
2189 +                       data++;
2190 +                       datalen--;
2191 +                       bytes_scanned++;
2192 +                       continue;
2193 +               }
2194 +
2195 +               data += 5;
2196 +
2197 +               DEBUGP("Userfile-share found in connection "
2198 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
2199 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
2200 +
2201 +               if (parse_command((char *) data, data_limit, &egg_ip,
2202 +                                 &egg_port)) {
2203 +                       DEBUGP("no data in userfile-share pkt\n");
2204 +                       return NF_ACCEPT;
2205 +               }
2206 +
2207 +               memset(&exp, 0, sizeof(exp));
2208 +
2209 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
2210 +                       if (net_ratelimit())
2211 +                               printk("Forged Eggdrop command from "
2212 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
2213 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
2214 +                                      HIPQUAD(egg_ip), egg_port);
2215 +                       return NF_ACCEPT;
2216 +               }
2217 +
2218 +               exp.tuple.src.ip = iph->daddr;
2219 +               exp.tuple.src.u.tcp.port = 0;
2220 +               exp.tuple.dst.ip = htonl(egg_ip);
2221 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
2222 +               exp.tuple.dst.protonum = IPPROTO_TCP;
2223 +
2224 +               exp.mask.dst.u.tcp.port = 0xffff;
2225 +               exp.mask.dst.protonum = 0xffff;
2226 +
2227 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
2228 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
2229 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
2230 +
2231 +               ip_conntrack_expect_related(ct, &exp);
2232 +               break;
2233 +       }
2234 +       return NF_ACCEPT;
2235 +}
2236 +
2237 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
2238 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
2239 +
2240 +static void deregister_helpers(void) {
2241 +       int i;
2242 +       
2243 +       for (i = 0; i < ports_c; i++) {
2244 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
2245 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
2246 +       }
2247 +}
2248 +
2249 +static int __init init(void)
2250 +{
2251 +       int i, ret;
2252 +       char *tmpname;
2253 +
2254 +       /* If no port given, default to standard eggdrop port */
2255 +       if (ports[0] == 0)
2256 +               ports[0] = 3333;
2257 +
2258 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2259 +               memset(&egg_helpers[i], 0,
2260 +                      sizeof(struct ip_conntrack_helper));
2261 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
2262 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
2263 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
2264 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
2265 +               egg_helpers[i].max_expected = 1;
2266 +               egg_helpers[i].timeout = egg_timeout;
2267 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2268 +               egg_helpers[i].me = THIS_MODULE;
2269 +               egg_helpers[i].help = help;
2270 +
2271 +               tmpname = &egg_names[i][0];
2272 +               if (ports[i] == 3333)
2273 +                       sprintf(tmpname, "eggdrop");
2274 +               else
2275 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
2276 +               egg_helpers[i].name = tmpname;
2277 +
2278 +               DEBUGP("port #%d: %d\n", i, ports[i]);
2279 +
2280 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
2281 +
2282 +               if (ret) {
2283 +                       printk("ip_conntrack_egg: ERROR registering helper "
2284 +                               "for port %d\n", ports[i]);
2285 +                       deregister_helpers();
2286 +                       return 1;
2287 +               }
2288 +               ports_c++;
2289 +       }
2290 +       return 0;
2291 +}
2292 +
2293 +static void __exit fini(void)
2294 +{
2295 +       deregister_helpers();
2296 +}
2297 +
2298 +module_init(init);
2299 +module_exit(fini);
2300 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
2301 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c  1970-01-01 01:00:00.000000000 +0100
2302 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c      2004-04-29 11:18:00.000000000 +0200
2303 @@ -0,0 +1,308 @@
2304 +/* 
2305 + * H.323 'brute force' extension for H.323 connection tracking. 
2306 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2307 + *
2308 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
2309 + * (http://www.coritel.it/projects/sofia/nat/)
2310 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
2311 + * the unregistered helpers to the conntrack entries.
2312 + */
2313 +
2314 +
2315 +#include <linux/module.h>
2316 +#include <linux/netfilter.h>
2317 +#include <linux/ip.h>
2318 +#include <net/checksum.h>
2319 +#include <net/tcp.h>
2320 +
2321 +#include <linux/netfilter_ipv4/lockhelp.h>
2322 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2323 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2324 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2325 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
2326 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
2327 +
2328 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
2329 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
2330 +MODULE_LICENSE("GPL");
2331 +
2332 +DECLARE_LOCK(ip_h323_lock);
2333 +struct module *ip_conntrack_h323 = THIS_MODULE;
2334 +
2335 +#if 0
2336 +#define DEBUGP printk
2337 +#else
2338 +#define DEBUGP(format, args...)
2339 +#endif
2340 +
2341 +/* FIXME: This should be in userspace.  Later. */
2342 +static int h245_help(const struct iphdr *iph, size_t len,
2343 +                    struct ip_conntrack *ct,
2344 +                    enum ip_conntrack_info ctinfo)
2345 +{
2346 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2347 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2348 +       unsigned char *data_limit;
2349 +       u_int32_t tcplen = len - iph->ihl * 4;
2350 +       u_int32_t datalen = tcplen - tcph->doff * 4;
2351 +       int dir = CTINFO2DIR(ctinfo);
2352 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2353 +       struct ip_conntrack_expect expect, *exp = &expect;
2354 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2355 +       u_int16_t data_port;
2356 +       u_int32_t data_ip;
2357 +       unsigned int i;
2358 +
2359 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2360 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
2361 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
2362 +
2363 +       /* Can't track connections formed before we registered */
2364 +       if (!info)
2365 +               return NF_ACCEPT;
2366 +               
2367 +       /* Until there's been traffic both ways, don't look in packets. */
2368 +       if (ctinfo != IP_CT_ESTABLISHED
2369 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2370 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
2371 +               return NF_ACCEPT;
2372 +       }
2373 +
2374 +       /* Not whole TCP header or too short packet? */
2375 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2376 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
2377 +               return NF_ACCEPT;
2378 +       }
2379 +
2380 +       /* Checksum invalid?  Ignore. */
2381 +       /* FIXME: Source route IP option packets --RR */
2382 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2383 +                             csum_partial((char *)tcph, tcplen, 0))) {
2384 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2385 +                      tcph, tcplen, NIPQUAD(iph->saddr),
2386 +                      NIPQUAD(iph->daddr));
2387 +               return NF_ACCEPT;
2388 +       }
2389 +
2390 +       data_limit = (unsigned char *) data + datalen;
2391 +       /* bytes: 0123   45
2392 +                 ipadrr port */
2393 +       for (i = 0; data < (data_limit - 5); data++, i++) {
2394 +               data_ip = *((u_int32_t *)data);
2395 +               if (data_ip == iph->saddr) {
2396 +                       data_port = *((u_int16_t *)(data + 4));
2397 +                       memset(&expect, 0, sizeof(expect));
2398 +                       /* update the H.225 info */
2399 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
2400 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2401 +                               NIPQUAD(iph->saddr), ntohs(data_port));
2402 +                       LOCK_BH(&ip_h323_lock);
2403 +                       info->is_h225 = H225_PORT + 1;
2404 +                       exp_info->port = data_port;
2405 +                       exp_info->dir = dir;
2406 +                       exp_info->offset = i;
2407 +
2408 +                       exp->seq = ntohl(tcph->seq) + i;
2409 +                   
2410 +                       exp->tuple = ((struct ip_conntrack_tuple)
2411 +                               { { ct->tuplehash[!dir].tuple.src.ip,
2412 +                                   { 0 } },
2413 +                                 { data_ip,
2414 +                                   { .tcp = { data_port } },
2415 +                                   IPPROTO_UDP }});
2416 +                       exp->mask = ((struct ip_conntrack_tuple)
2417 +                               { { 0xFFFFFFFF, { 0 } },
2418 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2419 +       
2420 +                       exp->expectfn = NULL;
2421 +                       
2422 +                       /* Ignore failure; should only happen with NAT */
2423 +                       ip_conntrack_expect_related(ct, exp);
2424 +
2425 +                       UNLOCK_BH(&ip_h323_lock);
2426 +               }
2427 +       }
2428 +
2429 +       return NF_ACCEPT;
2430 +
2431 +}
2432 +
2433 +/* H.245 helper is not registered! */
2434 +static struct ip_conntrack_helper h245 = 
2435 +       { { NULL, NULL },
2436 +          "H.245",                             /* name */
2437 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
2438 +          NULL,                                        /* module */
2439 +          8,                                   /* max_ expected */
2440 +          240,                                 /* timeout */
2441 +          { { 0, { 0 } },                      /* tuple */
2442 +            { 0, { 0 }, IPPROTO_TCP } },
2443 +          { { 0, { 0xFFFF } },                 /* mask */
2444 +            { 0, { 0 }, 0xFFFF } },
2445 +          h245_help                            /* helper */
2446 +       };
2447 +
2448 +static int h225_expect(struct ip_conntrack *ct)
2449 +{
2450 +       WRITE_LOCK(&ip_conntrack_lock);
2451 +       ct->helper = &h245;
2452 +       DEBUGP("h225_expect: helper for %p added\n", ct);
2453 +       WRITE_UNLOCK(&ip_conntrack_lock);
2454 +       
2455 +       return NF_ACCEPT;       /* unused */
2456 +}
2457 +
2458 +/* FIXME: This should be in userspace.  Later. */
2459 +static int h225_help(const struct iphdr *iph, size_t len,
2460 +                    struct ip_conntrack *ct,
2461 +                    enum ip_conntrack_info ctinfo)
2462 +{
2463 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2464 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
2465 +       unsigned char *data_limit;
2466 +       u_int32_t tcplen = len - iph->ihl * 4;
2467 +       u_int32_t datalen = tcplen - tcph->doff * 4;
2468 +       int dir = CTINFO2DIR(ctinfo);
2469 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
2470 +       struct ip_conntrack_expect expect, *exp = &expect;
2471 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
2472 +       u_int16_t data_port;
2473 +       u_int32_t data_ip;
2474 +       unsigned int i;
2475 +       
2476 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
2477 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
2478 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
2479 +
2480 +       /* Can't track connections formed before we registered */
2481 +       if (!info)
2482 +               return NF_ACCEPT;
2483 +
2484 +       /* Until there's been traffic both ways, don't look in packets. */
2485 +       if (ctinfo != IP_CT_ESTABLISHED
2486 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
2487 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
2488 +               return NF_ACCEPT;
2489 +       }
2490 +
2491 +       /* Not whole TCP header or too short packet? */
2492 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
2493 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
2494 +               return NF_ACCEPT;
2495 +       }
2496 +
2497 +       /* Checksum invalid?  Ignore. */
2498 +       /* FIXME: Source route IP option packets --RR */
2499 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2500 +                             csum_partial((char *)tcph, tcplen, 0))) {
2501 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2502 +                      tcph, tcplen, NIPQUAD(iph->saddr),
2503 +                      NIPQUAD(iph->daddr));
2504 +               return NF_ACCEPT;
2505 +       }
2506 +       
2507 +       data_limit = (unsigned char *) data + datalen;
2508 +       /* bytes: 0123   45
2509 +                 ipadrr port */
2510 +       for (i = 0; data < (data_limit - 5); data++, i++) {
2511 +               data_ip = *((u_int32_t *)data);
2512 +               if (data_ip == iph->saddr) {
2513 +                       data_port = *((u_int16_t *)(data + 4));
2514 +                       if (data_port == tcph->source) {
2515 +                               /* Signal address */
2516 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
2517 +                                       NIPQUAD(iph->saddr));
2518 +                               /* Update the H.225 info so that NAT can mangle the address/port
2519 +                                  even when we have no expected connection! */
2520 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2521 +                               LOCK_BH(&ip_h323_lock);
2522 +                               info->dir = dir;
2523 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
2524 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
2525 +                               UNLOCK_BH(&ip_h323_lock);
2526 +#endif
2527 +                       } else {
2528 +                               memset(&expect, 0, sizeof(expect));
2529 +
2530 +                               /* update the H.225 info */
2531 +                               LOCK_BH(&ip_h323_lock);
2532 +                               info->is_h225 = H225_PORT;
2533 +                               exp_info->port = data_port;
2534 +                               exp_info->dir = dir;
2535 +                               exp_info->offset = i;
2536 +
2537 +                               exp->seq = ntohl(tcph->seq) + i;
2538 +
2539 +                               exp->tuple = ((struct ip_conntrack_tuple)
2540 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
2541 +                                           { 0 } },
2542 +                                         { data_ip,
2543 +                                           { .tcp = { data_port } },
2544 +                                           IPPROTO_TCP }});
2545 +                               exp->mask = ((struct ip_conntrack_tuple)
2546 +                                       { { 0xFFFFFFFF, { 0 } },
2547 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2548 +       
2549 +                               exp->expectfn = h225_expect;
2550 +                               
2551 +                               /* Ignore failure */
2552 +                               ip_conntrack_expect_related(ct, exp);
2553 +
2554 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
2555 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2556 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
2557 +
2558 +                               UNLOCK_BH(&ip_h323_lock);
2559 +                       }  
2560 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2561 +               } else if (data_ip == iph->daddr) {
2562 +                       data_port = *((u_int16_t *)(data + 4));
2563 +                       if (data_port == tcph->dest) {
2564 +                               /* Signal address */
2565 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
2566 +                                       NIPQUAD(iph->daddr));
2567 +                               /* Update the H.225 info so that NAT can mangle the address/port
2568 +                                  even when we have no expected connection! */
2569 +                               LOCK_BH(&ip_h323_lock);
2570 +                               info->dir = dir;
2571 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
2572 +                               info->offset[IP_CT_DIR_REPLY] = i;
2573 +                               UNLOCK_BH(&ip_h323_lock);
2574 +                       }
2575 +#endif
2576 +               }
2577 +       }
2578 +
2579 +       return NF_ACCEPT;
2580 +
2581 +}
2582 +
2583 +static struct ip_conntrack_helper h225 = 
2584 +       { { NULL, NULL },
2585 +         "H.225",                                      /* name */
2586 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
2587 +         THIS_MODULE,                                  /* module */
2588 +         2,                                            /* max_expected */
2589 +         240,                                          /* timeout */
2590 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
2591 +           { 0, { 0 }, IPPROTO_TCP } },
2592 +         { { 0, { 0xFFFF } },                          /* mask */
2593 +           { 0, { 0 }, 0xFFFF } },
2594 +         h225_help                                     /* helper */
2595 +       };
2596 +
2597 +static int __init init(void)
2598 +{
2599 +       return ip_conntrack_helper_register(&h225);
2600 +}
2601 +
2602 +static void __exit fini(void)
2603 +{
2604 +       /* Unregister H.225 helper */   
2605 +       ip_conntrack_helper_unregister(&h225);
2606 +}
2607 +
2608 +EXPORT_SYMBOL(ip_h323_lock);
2609 +
2610 +module_init(init);
2611 +module_exit(fini);
2612 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
2613 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c   1970-01-01 01:00:00.000000000 +0100
2614 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c       2004-04-29 11:19:01.000000000 +0200
2615 @@ -0,0 +1,308 @@
2616 +/* MMS extension for IP connection tracking
2617 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
2618 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
2619 + *
2620 + * ip_conntrack_mms.c v0.3 2002-09-22
2621 + *
2622 + *      This program is free software; you can redistribute it and/or
2623 + *      modify it under the terms of the GNU General Public License
2624 + *      as published by the Free Software Foundation; either version
2625 + *      2 of the License, or (at your option) any later version.
2626 + *
2627 + *      Module load syntax:
2628 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
2629 + *
2630 + *      Please give the ports of all MMS servers You wish to connect to.
2631 + *      If you don't specify ports, the default will be TCP port 1755.
2632 + *
2633 + *      More info on MMS protocol, firewalls and NAT:
2634 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
2635 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
2636 + *
2637 + *      The SDP project people are reverse-engineering MMS:
2638 + *      http://get.to/sdp
2639 + */
2640 +
2641 +#include <linux/config.h>
2642 +#include <linux/module.h>
2643 +#include <linux/netfilter.h>
2644 +#include <linux/ip.h>
2645 +#include <linux/ctype.h>
2646 +#include <net/checksum.h>
2647 +#include <net/tcp.h>
2648 +
2649 +#include <linux/netfilter_ipv4/lockhelp.h>
2650 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
2651 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
2652 +
2653 +DECLARE_LOCK(ip_mms_lock);
2654 +struct module *ip_conntrack_mms = THIS_MODULE;
2655 +
2656 +#define MAX_PORTS 8
2657 +static int ports[MAX_PORTS];
2658 +static int ports_c;
2659 +#ifdef MODULE_PARM
2660 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
2661 +#endif
2662 +
2663 +#if 0 
2664 +#define DEBUGP printk
2665 +#else
2666 +#define DEBUGP(format, args...)
2667 +#endif
2668 +
2669 +EXPORT_SYMBOL(ip_mms_lock);
2670 +
2671 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
2672 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
2673 +MODULE_LICENSE("GPL");
2674 +
2675 +/* #define isdigit(c) (c >= '0' && c <= '9') */
2676 +
2677 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
2678 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
2679 +{
2680 +       int i;
2681 +       for (i = 0; i < unicode_size; ++i) {
2682 +               string[i] = (char)(unicode[i]);
2683 +       }
2684 +       string[unicode_size] = 0x00;
2685 +}
2686 +
2687 +__inline static int atoi(char *s) 
2688 +{
2689 +       int i=0;
2690 +       while (isdigit(*s)) {
2691 +               i = i*10 + *(s++) - '0';
2692 +       }
2693 +       return i;
2694 +}
2695 +
2696 +/* convert ip address string like "192.168.0.10" to unsigned int */
2697 +__inline static u_int32_t asciiiptoi(char *s)
2698 +{
2699 +       unsigned int i, j, k;
2700 +
2701 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
2702 +               i+=atoi(s);
2703 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
2704 +                       ;
2705 +       }
2706 +       i+=atoi(s);
2707 +       return ntohl(i);
2708 +}
2709 +
2710 +int parse_mms(const char *data, 
2711 +             const unsigned int datalen,
2712 +             u_int32_t *mms_ip,
2713 +             u_int16_t *mms_proto,
2714 +             u_int16_t *mms_port,
2715 +             char **mms_string_b,
2716 +             char **mms_string_e,
2717 +             char **mms_padding_e)
2718 +{
2719 +       int unicode_size, i;
2720 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
2721 +       char getlengthstring[28];
2722 +       
2723 +       for(unicode_size=0; 
2724 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
2725 +           unicode_size++)
2726 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
2727 +                       return -1; /* out of bounds - incomplete packet */
2728 +       
2729 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
2730 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
2731 +       
2732 +       /* IP address ? */
2733 +       *mms_ip = asciiiptoi(tempstring+2);
2734 +       
2735 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
2736 +               
2737 +       /* protocol ? */
2738 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
2739 +               *mms_proto = IPPROTO_TCP;
2740 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
2741 +               *mms_proto = IPPROTO_UDP;
2742 +
2743 +       /* port ? */
2744 +       *mms_port = atoi(tempstring+7+i);
2745 +
2746 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
2747 +          unicode string, one to the end of the string, and one to the end 
2748 +          of the packet, since we must keep track of the number of bytes 
2749 +          between end of the unicode string and the end of packet (padding) */
2750 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
2751 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
2752 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
2753 +       return 0;
2754 +}
2755 +
2756 +
2757 +/* FIXME: This should be in userspace.  Later. */
2758 +static int help(const struct iphdr *iph, size_t len,
2759 +               struct ip_conntrack *ct,
2760 +               enum ip_conntrack_info ctinfo)
2761 +{
2762 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
2763 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
2764 +       const char *data = (const char *)tcph + tcph->doff * 4;
2765 +       unsigned int tcplen = len - iph->ihl * 4;
2766 +       unsigned int datalen = tcplen - tcph->doff * 4;
2767 +       int dir = CTINFO2DIR(ctinfo);
2768 +       struct ip_conntrack_expect expect, *exp = &expect; 
2769 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
2770 +       
2771 +       u_int32_t mms_ip;
2772 +       u_int16_t mms_proto;
2773 +       char mms_proto_string[8];
2774 +       u_int16_t mms_port;
2775 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
2776 +            
2777 +       /* Until there's been traffic both ways, don't look in packets. */
2778 +       if (ctinfo != IP_CT_ESTABLISHED
2779 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
2780 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
2781 +               return NF_ACCEPT;
2782 +       }
2783 +
2784 +       /* Not whole TCP header? */
2785 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
2786 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
2787 +               return NF_ACCEPT;
2788 +       }
2789 +
2790 +       /* Checksum invalid?  Ignore. */
2791 +       /* FIXME: Source route IP option packets --RR */
2792 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
2793 +           csum_partial((char *)tcph, tcplen, 0))) {
2794 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
2795 +                      tcph, tcplen, NIPQUAD(iph->saddr),
2796 +                      NIPQUAD(iph->daddr));
2797 +               return NF_ACCEPT;
2798 +       }
2799 +       
2800 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
2801 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
2802 +          the client has already sent a packet to the server with the server's hostname 
2803 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
2804 +          server will break the connection if this doesn't correspond to its own host 
2805 +          header. The client can also connect to an IP address; if it's the server's IP
2806 +          address, it will not break the connection. When doing DNAT on a connection 
2807 +          where the client uses a server's IP address, the nat module should detect
2808 +          this and change this string accordingly to the DNATed address. This should
2809 +          probably be done by checking for an IP address, then storing it as a member
2810 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
2811 +          */
2812 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
2813 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
2814 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
2815 +                      (u8)*(data+36), (u8)*(data+37), 
2816 +                      (u8)*(data+38), (u8)*(data+39),
2817 +                      datalen);
2818 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
2819 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
2820 +                       if(net_ratelimit())
2821 +                               /* FIXME: more verbose debugging ? */
2822 +                               printk(KERN_WARNING
2823 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
2824 +
2825 +               memset(&expect, 0, sizeof(expect));
2826 +
2827 +               sprintf(mms_proto_string, "(%u)", mms_proto);
2828 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
2829 +                      mms_proto == IPPROTO_TCP ? "TCP"
2830 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
2831 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
2832 +                      NIPQUAD(mms_ip),
2833 +                      mms_port);
2834 +               
2835 +               /* it's possible that the client will just ask the server to tunnel
2836 +                  the stream over the same TCP session (from port 1755): there's 
2837 +                  shouldn't be a need to add an expectation in that case, but it
2838 +                  makes NAT packet mangling so much easier */
2839 +               LOCK_BH(&ip_mms_lock);
2840 +
2841 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
2842 +               
2843 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
2844 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
2845 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
2846 +               exp_mms_info->port    = mms_port;
2847 +               
2848 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
2849 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
2850 +               
2851 +               exp->tuple = ((struct ip_conntrack_tuple)
2852 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
2853 +                             { mms_ip,
2854 +                               { .tcp = { (__u16) ntohs(mms_port) } },
2855 +                               mms_proto } }
2856 +                            );
2857 +               exp->mask  = ((struct ip_conntrack_tuple)
2858 +                            { { 0xFFFFFFFF, { 0 } },
2859 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
2860 +               exp->expectfn = NULL;
2861 +               ip_conntrack_expect_related(ct, &expect);
2862 +               UNLOCK_BH(&ip_mms_lock);
2863 +       }
2864 +
2865 +       return NF_ACCEPT;
2866 +}
2867 +
2868 +static struct ip_conntrack_helper mms[MAX_PORTS];
2869 +static char mms_names[MAX_PORTS][10];
2870 +
2871 +/* Not __exit: called from init() */
2872 +static void fini(void)
2873 +{
2874 +       int i;
2875 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2876 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
2877 +                               ports[i]);
2878 +               ip_conntrack_helper_unregister(&mms[i]);
2879 +       }
2880 +}
2881 +
2882 +static int __init init(void)
2883 +{
2884 +       int i, ret;
2885 +       char *tmpname;
2886 +
2887 +       if (ports[0] == 0)
2888 +               ports[0] = MMS_PORT;
2889 +
2890 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
2891 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
2892 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
2893 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
2894 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
2895 +               mms[i].mask.dst.protonum = 0xFFFF;
2896 +               mms[i].max_expected = 1;
2897 +               mms[i].timeout = 0;
2898 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
2899 +               mms[i].me = THIS_MODULE;
2900 +               mms[i].help = help;
2901 +
2902 +               tmpname = &mms_names[i][0];
2903 +               if (ports[i] == MMS_PORT)
2904 +                       sprintf(tmpname, "mms");
2905 +               else
2906 +                       sprintf(tmpname, "mms-%d", ports[i]);
2907 +               mms[i].name = tmpname;
2908 +
2909 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
2910 +                               ports[i]);
2911 +               ret = ip_conntrack_helper_register(&mms[i]);
2912 +
2913 +               if (ret) {
2914 +                       fini();
2915 +                       return ret;
2916 +               }
2917 +               ports_c++;
2918 +       }
2919 +       return 0;
2920 +}
2921 +
2922 +module_init(init);
2923 +module_exit(fini);
2924 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
2925 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c    1970-01-01 01:00:00.000000000 +0100
2926 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c        2004-04-29 11:20:17.000000000 +0200
2927 @@ -0,0 +1,529 @@
2928 +/*
2929 + * Connection tracking protocol helper module for SCTP.
2930 + * 
2931 + * SCTP is defined in RFC 2960. References to various sections in this code 
2932 + * are to this RFC.
2933 + * 
2934 + * This program is free software; you can redistribute it and/or modify
2935 + * it under the terms of the GNU General Public License version 2 as
2936 + * published by the Free Software Foundation.
2937 + */
2938 +
2939 +#include <linux/types.h>
2940 +#include <linux/sched.h>
2941 +#include <linux/timer.h>
2942 +#include <linux/netfilter.h>
2943 +#include <linux/module.h>
2944 +#include <linux/in.h>
2945 +#include <linux/ip.h>
2946 +#include <linux/sctp.h>
2947 +#include <linux/string.h>
2948 +
2949 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2950 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
2951 +#include <linux/netfilter_ipv4/lockhelp.h>
2952 +
2953 +#if 0
2954 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
2955 +#else
2956 +#define DEBUGP(format, args...)
2957 +#endif
2958 +
2959 +/* Protects conntrack->proto.sctp */
2960 +static DECLARE_RWLOCK(sctp_lock);
2961 +
2962 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
2963 +   closely.  They're more complex. --RR 
2964 +
2965 +   And so for me for SCTP :D -Kiran */
2966 +
2967 +static const char *sctp_conntrack_names[] = {
2968 +       "NONE",
2969 +       "CLOSED",
2970 +       "COOKIE_WAIT",
2971 +       "COOKIE_ECHOED",
2972 +       "ESTABLISHED",
2973 +       "SHUTDOWN_SENT",
2974 +       "SHUTDOWN_RECD",
2975 +       "SHUTDOWN_ACK_SENT",
2976 +};
2977 +
2978 +#define SECS  * HZ
2979 +#define MINS  * 60 SECS
2980 +#define HOURS * 60 MINS
2981 +#define DAYS  * 24 HOURS
2982 +
2983 +unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
2984 +unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
2985 +unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
2986 +unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
2987 +unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
2988 +unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
2989 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
2990 +
2991 +static unsigned long * sctp_timeouts[]
2992 += { 0,                                     /* SCTP_CONNTRACK_NONE  */
2993 +    &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
2994 +    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
2995 +    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
2996 +    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
2997 +    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
2998 +    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
2999 +    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
3000 + };
3001 +
3002 +#define sNO SCTP_CONNTRACK_NONE
3003 +#define        sCL SCTP_CONNTRACK_CLOSED
3004 +#define        sCW SCTP_CONNTRACK_COOKIE_WAIT
3005 +#define        sCE SCTP_CONNTRACK_COOKIE_ECHOED
3006 +#define        sES SCTP_CONNTRACK_ESTABLISHED
3007 +#define        sSS SCTP_CONNTRACK_SHUTDOWN_SENT
3008 +#define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
3009 +#define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
3010 +#define        sIV SCTP_CONNTRACK_MAX
3011 +
3012 +/* 
3013 +       These are the descriptions of the states:
3014 +
3015 +NOTE: These state names are tantalizingly similar to the states of an 
3016 +SCTP endpoint. But the interpretation of the states is a little different,
3017 +considering that these are the states of the connection and not of an end 
3018 +point. Please note the subtleties. -Kiran
3019 +
3020 +NONE              - Nothing so far.
3021 +COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
3022 +                    an INIT_ACK chunk in the reply direction.
3023 +COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
3024 +ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
3025 +SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
3026 +SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
3027 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
3028 +                    to that of the SHUTDOWN chunk.
3029 +CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
3030 +                    the SHUTDOWN chunk. Connection is closed.
3031 +*/
3032 +
3033 +/* TODO
3034 + - I have assumed that the first INIT is in the original direction. 
3035 + This messes things when an INIT comes in the reply direction in CLOSED
3036 + state.
3037 + - Check the error type in the reply dir before transitioning from 
3038 +cookie echoed to closed.
3039 + - Sec 5.2.4 of RFC 2960
3040 + - Multi Homing support.
3041 +*/
3042 +
3043 +/* SCTP conntrack state transitions */
3044 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
3045 +       {
3046 +/*     ORIGINAL        */
3047 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
3048 +/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
3049 +/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
3050 +/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
3051 +/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
3052 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
3053 +/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
3054 +/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
3055 +/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
3056 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
3057 +       },
3058 +       {
3059 +/*     REPLY   */
3060 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
3061 +/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
3062 +/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
3063 +/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
3064 +/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
3065 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
3066 +/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
3067 +/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
3068 +/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
3069 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
3070 +       }
3071 +};
3072 +
3073 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
3074 +                            unsigned int dataoff,
3075 +                            struct ip_conntrack_tuple *tuple)
3076 +{
3077 +       sctp_sctphdr_t hdr;
3078 +
3079 +       DEBUGP(__FUNCTION__);
3080 +       DEBUGP("\n");
3081 +
3082 +       /* Actually only need first 8 bytes. */
3083 +       if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
3084 +               return 0;
3085 +
3086 +       tuple->src.u.sctp.port = hdr.source;
3087 +       tuple->dst.u.sctp.port = hdr.dest;
3088 +
3089 +       return 1;
3090 +}
3091 +
3092 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
3093 +                            const struct ip_conntrack_tuple *orig)
3094 +{
3095 +       DEBUGP(__FUNCTION__);
3096 +       DEBUGP("\n");
3097 +
3098 +       tuple->src.u.sctp.port = orig->dst.u.sctp.port;
3099 +       tuple->dst.u.sctp.port = orig->src.u.sctp.port;
3100 +       return 1;
3101 +}
3102 +
3103 +/* Print out the per-protocol part of the tuple. */
3104 +static unsigned int sctp_print_tuple(char *buffer,
3105 +                                    const struct ip_conntrack_tuple *tuple)
3106 +{
3107 +       DEBUGP(__FUNCTION__);
3108 +       DEBUGP("\n");
3109 +
3110 +       return sprintf(buffer, "sport=%hu dport=%hu ",
3111 +                      ntohs(tuple->src.u.sctp.port),
3112 +                      ntohs(tuple->dst.u.sctp.port));
3113 +}
3114 +
3115 +/* Print out the private part of the conntrack. */
3116 +static unsigned int sctp_print_conntrack(char *buffer,
3117 +                                        const struct ip_conntrack *conntrack)
3118 +{
3119 +       enum sctp_conntrack state;
3120 +
3121 +       DEBUGP(__FUNCTION__);
3122 +       DEBUGP("\n");
3123 +
3124 +       READ_LOCK(&sctp_lock);
3125 +       state = conntrack->proto.sctp.state;
3126 +       READ_UNLOCK(&sctp_lock);
3127 +
3128 +       return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
3129 +}
3130 +
3131 +#define for_each_sctp_chunk(skb, sch, offset, count)   \
3132 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0;       \
3133 +       offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch));    \
3134 +       offset += (htons(sch.length) + 3) & ~3, count++)
3135 +
3136 +/* Some validity checks to make sure the chunks are fine */
3137 +static int do_basic_checks(struct ip_conntrack *conntrack,
3138 +                          const struct sk_buff *skb,
3139 +                          char *map)
3140 +{
3141 +       u_int32_t offset, count;
3142 +       sctp_chunkhdr_t sch;
3143 +       int flag;
3144 +
3145 +       DEBUGP(__FUNCTION__);
3146 +       DEBUGP("\n");
3147 +
3148 +       flag = 0;
3149 +
3150 +       for_each_sctp_chunk (skb, sch, offset, count) {
3151 +               DEBUGP("Chunk Num: %d  Type: %d\n", count, sch.type);
3152 +
3153 +               if (sch.type == SCTP_CID_INIT 
3154 +                       || sch.type == SCTP_CID_INIT_ACK
3155 +                       || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3156 +                       flag = 1;
3157 +               }
3158 +
3159 +               /* Cookie Ack/Echo chunks not the first OR 
3160 +                  Init / Init Ack / Shutdown compl chunks not the only chunks */
3161 +               if ((sch.type == SCTP_CID_COOKIE_ACK 
3162 +                       || sch.type == SCTP_CID_COOKIE_ECHO
3163 +                       || flag)
3164 +                    && count !=0 ) {
3165 +                       DEBUGP("Basic checks failed\n");
3166 +                       return 1;
3167 +               }
3168 +
3169 +               if (map) {
3170 +                       set_bit (sch.type, (void *)map);
3171 +               }
3172 +       }
3173 +
3174 +       DEBUGP("Basic checks passed\n");
3175 +       return 0;
3176 +}
3177 +
3178 +static int new_state(enum ip_conntrack_dir dir,
3179 +                    enum sctp_conntrack cur_state,
3180 +                    int chunk_type)
3181 +{
3182 +       int i;
3183 +
3184 +       DEBUGP(__FUNCTION__);
3185 +       DEBUGP("\n");
3186 +
3187 +       DEBUGP("Chunk type: %d\n", chunk_type);
3188 +
3189 +       switch (chunk_type) {
3190 +               case SCTP_CID_INIT: 
3191 +                       DEBUGP("SCTP_CID_INIT\n");
3192 +                       i = 0; break;
3193 +               case SCTP_CID_INIT_ACK: 
3194 +                       DEBUGP("SCTP_CID_INIT_ACK\n");
3195 +                       i = 1; break;
3196 +               case SCTP_CID_ABORT: 
3197 +                       DEBUGP("SCTP_CID_ABORT\n");
3198 +                       i = 2; break;
3199 +               case SCTP_CID_SHUTDOWN: 
3200 +                       DEBUGP("SCTP_CID_SHUTDOWN\n");
3201 +                       i = 3; break;
3202 +               case SCTP_CID_SHUTDOWN_ACK: 
3203 +                       DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
3204 +                       i = 4; break;
3205 +               case SCTP_CID_ERROR: 
3206 +                       DEBUGP("SCTP_CID_ERROR\n");
3207 +                       i = 5; break;
3208 +               case SCTP_CID_COOKIE_ECHO: 
3209 +                       DEBUGP("SCTP_CID_COOKIE_ECHO\n");
3210 +                       i = 6; break;
3211 +               case SCTP_CID_COOKIE_ACK: 
3212 +                       DEBUGP("SCTP_CID_COOKIE_ACK\n");
3213 +                       i = 7; break;
3214 +               case SCTP_CID_SHUTDOWN_COMPLETE: 
3215 +                       DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
3216 +                       i = 8; break;
3217 +               default:
3218 +                       /* Other chunks like DATA, SACK, HEARTBEAT and
3219 +                       its ACK do not cause a change in state */
3220 +                       DEBUGP("Unknown chunk type, Will stay in %s\n", 
3221 +                                               sctp_conntrack_names[cur_state]);
3222 +                       return cur_state;
3223 +       }
3224 +
3225 +       DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
3226 +                       dir, sctp_conntrack_names[cur_state], chunk_type,
3227 +                       sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
3228 +
3229 +       return sctp_conntracks[dir][i][cur_state];
3230 +}
3231 +
3232 +/* Returns verdict for packet, or -1 for invalid. */
3233 +static int sctp_packet(struct ip_conntrack *conntrack,
3234 +                      const struct sk_buff *skb,
3235 +                      enum ip_conntrack_info ctinfo)
3236 +{
3237 +       enum sctp_conntrack newconntrack, oldsctpstate;
3238 +       sctp_sctphdr_t sctph;
3239 +       sctp_chunkhdr_t sch;
3240 +       u_int32_t offset, count;
3241 +       char map[256 / sizeof (char)] = {0};
3242 +
3243 +       DEBUGP(__FUNCTION__);
3244 +       DEBUGP("\n");
3245 +
3246 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3247 +               return -1;
3248 +
3249 +       if (do_basic_checks(conntrack, skb, map) != 0)
3250 +               return -1;
3251 +
3252 +       /* Check the verification tag (Sec 8.5) */
3253 +       if (!test_bit(SCTP_CID_INIT, (void *)map)
3254 +               && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
3255 +               && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
3256 +               && !test_bit(SCTP_CID_ABORT, (void *)map)
3257 +               && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
3258 +               && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3259 +               DEBUGP("Verification tag check failed\n");
3260 +               return -1;
3261 +       }
3262 +
3263 +       oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
3264 +       for_each_sctp_chunk (skb, sch, offset, count) {
3265 +               WRITE_LOCK(&sctp_lock);
3266 +
3267 +               /* Special cases of Verification tag check (Sec 8.5.1) */
3268 +               if (sch.type == SCTP_CID_INIT) {
3269 +                       /* Sec 8.5.1 (A) */
3270 +                       if (sctph.vtag != 0) {
3271 +                               WRITE_UNLOCK(&sctp_lock);
3272 +                               return -1;
3273 +                       }
3274 +               } else if (sch.type == SCTP_CID_ABORT) {
3275 +                       /* Sec 8.5.1 (B) */
3276 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3277 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
3278 +                                                       [1 - CTINFO2DIR(ctinfo)])) {
3279 +                               WRITE_UNLOCK(&sctp_lock);
3280 +                               return -1;
3281 +                       }
3282 +               } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
3283 +                       /* Sec 8.5.1 (C) */
3284 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
3285 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
3286 +                                                       [1 - CTINFO2DIR(ctinfo)] 
3287 +                                       && (sch.flags & 1))) {
3288 +                               WRITE_UNLOCK(&sctp_lock);
3289 +                               return -1;
3290 +                       }
3291 +               } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
3292 +                       /* Sec 8.5.1 (D) */
3293 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
3294 +                               WRITE_UNLOCK(&sctp_lock);
3295 +                               return -1;
3296 +                       }
3297 +               }
3298 +
3299 +               oldsctpstate = conntrack->proto.sctp.state;
3300 +               newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
3301 +
3302 +               /* Invalid */
3303 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
3304 +                       DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
3305 +                              CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
3306 +                       WRITE_UNLOCK(&sctp_lock);
3307 +                       return -1;
3308 +               }
3309 +
3310 +               /* If it is an INIT or an INIT ACK note down the vtag */
3311 +               if (sch.type == SCTP_CID_INIT 
3312 +                       || sch.type == SCTP_CID_INIT_ACK) {
3313 +                       sctp_inithdr_t inithdr;
3314 +
3315 +                       if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
3316 +                               &inithdr, sizeof(inithdr)) != 0) {
3317 +                                       WRITE_UNLOCK(&sctp_lock);
3318 +                                       return -1;
3319 +                       }
3320 +                       DEBUGP("Setting vtag %x for dir %d\n", 
3321 +                                       inithdr.init_tag, CTINFO2DIR(ctinfo));
3322 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
3323 +               }
3324 +
3325 +               conntrack->proto.sctp.state = newconntrack;
3326 +               WRITE_UNLOCK(&sctp_lock);
3327 +       }
3328 +
3329 +       ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
3330 +
3331 +       if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
3332 +               && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
3333 +               && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
3334 +               DEBUGP("Setting assured bit\n");
3335 +               set_bit(IPS_ASSURED_BIT, &conntrack->status);
3336 +       }
3337 +
3338 +       return NF_ACCEPT;
3339 +}
3340 +
3341 +/* Called when a new connection for this protocol found. */
3342 +static int sctp_new(struct ip_conntrack *conntrack, 
3343 +                   const struct sk_buff *skb)
3344 +{
3345 +       enum sctp_conntrack newconntrack;
3346 +       sctp_sctphdr_t sctph;
3347 +       sctp_chunkhdr_t sch;
3348 +       u_int32_t offset, count;
3349 +       char map[256 / sizeof (char)] = {0};
3350 +
3351 +       DEBUGP(__FUNCTION__);
3352 +       DEBUGP("\n");
3353 +
3354 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
3355 +               return -1;
3356 +
3357 +       if (do_basic_checks(conntrack, skb, map) != 0)
3358 +               return -1;
3359 +
3360 +       /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
3361 +       if ((test_bit (SCTP_CID_ABORT, (void *)map))
3362 +               || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
3363 +               || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
3364 +               return -1;
3365 +       }
3366 +
3367 +       newconntrack = SCTP_CONNTRACK_MAX;
3368 +       for_each_sctp_chunk (skb, sch, offset, count) {
3369 +               /* Don't need lock here: this conntrack not in circulation yet */
3370 +               newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
3371 +                                               SCTP_CONNTRACK_NONE, sch.type);
3372 +
3373 +               /* Invalid: delete conntrack */
3374 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
3375 +                       DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
3376 +                       return 0;
3377 +               }
3378 +
3379 +               /* Copy the vtag into the state info */
3380 +               if (sch.type == SCTP_CID_INIT) {
3381 +                       if (sctph.vtag == 0) {
3382 +                               sctp_inithdr_t inithdr;
3383 +
3384 +                               if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t), 
3385 +                                       &inithdr, sizeof(inithdr)) != 0) {
3386 +                                               return -1;
3387 +                               }
3388 +
3389 +                               DEBUGP("Setting vtag %x for new conn\n", 
3390 +                                       inithdr.init_tag);
3391 +
3392 +                               conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
3393 +                                                               inithdr.init_tag;
3394 +                       } else {
3395 +                               /* Sec 8.5.1 (A) */
3396 +                               return -1;
3397 +                       }
3398 +               }
3399 +               /* If it is a shutdown ack OOTB packet, we expect a return
3400 +                  shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
3401 +               else {
3402 +                       DEBUGP("Setting vtag %x for new conn OOTB\n", 
3403 +                               sctph.vtag);
3404 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
3405 +               }
3406 +
3407 +               conntrack->proto.sctp.state = newconntrack;
3408 +       }
3409 +
3410 +       return 1;
3411 +}
3412 +
3413 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
3414 +                               const struct sk_buff *skb)
3415 +{
3416 +       /* To be implemented */
3417 +       return 0;
3418 +}
3419 +
3420 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
3421 +       .list            = { NULL, NULL }, 
3422 +       .proto           = IPPROTO_SCTP, 
3423 +       .name            = "sctp",
3424 +       .pkt_to_tuple    = sctp_pkt_to_tuple, 
3425 +       .invert_tuple    = sctp_invert_tuple, 
3426 +       .print_tuple     = sctp_print_tuple, 
3427 +       .print_conntrack = sctp_print_conntrack,
3428 +       .packet          = sctp_packet, 
3429 +       .new             = sctp_new, 
3430 +       .destroy         = NULL, 
3431 +       .exp_matches_pkt = sctp_exp_matches_pkt, 
3432 +       .me              = THIS_MODULE 
3433 +};
3434 +
3435 +int __init init(void)
3436 +{
3437 +       int ret;
3438 +
3439 +       ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
3440 +       DEBUGP("SCTP conntrack module loading %s\n", 
3441 +                                       ret ? "failed": "succeeded");
3442 +       return ret;
3443 +}
3444 +
3445 +void __exit fini(void)
3446 +{
3447 +       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
3448 +       DEBUGP("SCTP conntrack module unloaded\n");
3449 +}
3450 +
3451 +module_init(init);
3452 +module_exit(fini);
3453 +
3454 +MODULE_LICENSE("GPL");
3455 +MODULE_AUTHOR("Kiran Kumar Immidi");
3456 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
3457 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
3458 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c        1970-01-01 01:00:00.000000000 +0100
3459 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c    2004-04-29 11:19:53.000000000 +0200
3460 @@ -0,0 +1,156 @@
3461 +/* Quake3 extension for IP connection tracking
3462 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3463 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
3464 + *
3465 + * ip_conntrack_quake3.c v0.04 2002-08-31
3466 + *
3467 + *      This program is free software; you can redistribute it and/or
3468 + *      modify it under the terms of the GNU General Public License
3469 + *      as published by the Free Software Foundation; either version
3470 + *      2 of the License, or (at your option) any later version.
3471 + *
3472 + *      Module load syntax:
3473 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
3474 + *
3475 + *      please give the ports of all Quake3 master servers You wish to 
3476 + *      connect to. If you don't specify ports, the default will be UDP 
3477 + *      port 27950.
3478 + *
3479 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
3480 + */
3481 +
3482 +#include <linux/module.h>
3483 +#include <linux/ip.h>
3484 +#include <linux/udp.h>
3485 +
3486 +#include <linux/netfilter.h>
3487 +#include <linux/netfilter_ipv4/ip_tables.h>
3488 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3489 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
3490 +
3491 +struct module *ip_conntrack_quake3 = THIS_MODULE;
3492 +
3493 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3494 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
3495 +MODULE_LICENSE("GPL");
3496 +
3497 +#define MAX_PORTS 8
3498 +static int ports[MAX_PORTS];
3499 +static int ports_c = 0;
3500 +#ifdef MODULE_PARM
3501 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3502 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
3503 +#endif
3504 +
3505 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
3506 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
3507 +#if 0 
3508 +#define DEBUGP printk
3509 +#else
3510 +#define DEBUGP(format, args...)
3511 +#endif
3512 +
3513 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
3514 +
3515 +static int quake3_help(const struct iphdr *iph, size_t len,
3516 +       struct ip_conntrack *ct,
3517 +       enum ip_conntrack_info ctinfo)
3518 +{
3519 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
3520 +       int dir = CTINFO2DIR(ctinfo);
3521 +       struct ip_conntrack_expect exp;
3522 +       int i;
3523 +       
3524 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
3525 +       if (ctinfo != IP_CT_ESTABLISHED
3526 +           && ctinfo != IP_CT_IS_REPLY) {
3527 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
3528 +               return NF_ACCEPT;
3529 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
3530 +       
3531 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
3532 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
3533 +                   i+6 < ntohs(udph->len);
3534 +                   i+=7) {
3535 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
3536 +                              i, ntohs(udph->len),
3537 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
3538 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
3539 +
3540 +                       memset(&exp, 0, sizeof(exp));
3541 +
3542 +                       exp.tuple = ((struct ip_conntrack_tuple)
3543 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3544 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
3545 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
3546 +                                        IPPROTO_UDP } }
3547 +                                   );
3548 +                       exp.mask  = ((struct ip_conntrack_tuple)
3549 +                                    { { 0xFFFFFFFF, { 0 } },
3550 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
3551 +                       exp.expectfn = NULL;
3552 +
3553 +                       ip_conntrack_expect_related(ct, &exp);
3554 +               }
3555 +
3556 +       }
3557 +       
3558 +       return(NF_ACCEPT);
3559 +}
3560 +
3561 +static struct ip_conntrack_helper quake3[MAX_PORTS];
3562 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
3563 +
3564 +static void fini(void)
3565 +{
3566 +       int i;
3567 +
3568 +       for(i = 0 ; (i < ports_c); i++) {
3569 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
3570 +                                       ports[i]);
3571 +               ip_conntrack_helper_unregister(&quake3[i]);
3572 +       } 
3573 +}
3574 +
3575 +static int __init init(void)
3576 +{
3577 +       int i, ret;
3578 +       char *tmpname;
3579 +
3580 +       if(!ports[0])
3581 +               ports[0]=QUAKE3_MASTER_PORT;
3582 +
3583 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
3584 +               /* Create helper structure */
3585 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
3586 +
3587 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
3588 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
3589 +               quake3[i].mask.dst.protonum = 0xFFFF;
3590 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
3591 +               quake3[i].help = quake3_help;
3592 +               quake3[i].me = THIS_MODULE;
3593 +
3594 +               tmpname = &quake3_names[i][0];
3595 +               if (ports[i] == QUAKE3_MASTER_PORT)
3596 +                       sprintf(tmpname, "quake3");
3597 +               else
3598 +                       sprintf(tmpname, "quake3-%d", i);
3599 +               quake3[i].name = tmpname;
3600 +               
3601 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
3602 +                      ports[i]);
3603 +
3604 +               ret=ip_conntrack_helper_register(&quake3[i]);
3605 +               if(ret) {
3606 +                       fini();
3607 +                       return(ret);
3608 +               }
3609 +               ports_c++;
3610 +       }
3611 +
3612 +       return(0);
3613 +}
3614 +
3615 +module_init(init);
3616 +module_exit(fini);
3617 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
3618 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c       1970-01-01 01:00:00.000000000 +0100
3619 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c   2004-04-29 11:20:02.000000000 +0200
3620 @@ -0,0 +1,508 @@
3621 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
3622 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3623 + *     - original rpc tracking module
3624 + *     - "recent" connection handling for kernel 2.3+ netfilter
3625 + *
3626 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3627 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3628 + *
3629 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3630 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
3631 + *     - extended matching to support filtering on procedures
3632 + *
3633 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
3634 + *
3635 + *     This program is free software; you can redistribute it and/or
3636 + *     modify it under the terms of the GNU General Public License
3637 + *     as published by the Free Software Foundation; either version
3638 + *     2 of the License, or (at your option) any later version.
3639 + **
3640 + *     Module load syntax:
3641 + *     insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
3642 + *
3643 + *     Please give the ports of all RPC servers you wish to connect to.
3644 + *     If you don't specify ports, the default will be port 111.
3645 + **
3646 + *     Note to all:
3647 + *
3648 + *     RPCs should not be exposed to the internet - ask the Pentagon;
3649 + *
3650 + *       "The unidentified crackers pleaded guilty in July to charges
3651 + *        of juvenile delinquency stemming from a string of Pentagon
3652 + *        network intrusions in February.
3653 + *
3654 + *        The youths, going by the names TooShort and Makaveli, used
3655 + *        a common server security hole to break in, according to
3656 + *        Dane Jasper, owner of the California Internet service
3657 + *        provider, Sonic. They used the hole, known as the 'statd'
3658 + *        exploit, to attempt more than 800 break-ins, Jasper said."
3659 + *
3660 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
3661 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
3662 + **
3663 + */
3664 +
3665 +#include <linux/module.h>
3666 +#include <linux/netfilter.h>
3667 +#include <linux/ip.h>
3668 +#include <net/checksum.h>
3669 +#include <net/tcp.h>
3670 +
3671 +#include <asm/param.h>
3672 +#include <linux/sched.h>
3673 +#include <linux/timer.h>
3674 +#include <linux/stddef.h>
3675 +#include <linux/list.h>
3676 +
3677 +#include <linux/netfilter_ipv4/lockhelp.h>
3678 +#include <linux/netfilter_ipv4/ip_tables.h>
3679 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3680 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
3681 +
3682 +#define MAX_PORTS 8
3683 +static int ports[MAX_PORTS];
3684 +static int ports_n_c = 0;
3685 +
3686 +#ifdef MODULE_PARM
3687 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3688 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
3689 +#endif
3690 +
3691 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
3692 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
3693 +MODULE_LICENSE("GPL");
3694 +
3695 +#if 0
3696 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
3697 +                                       format, ## args)
3698 +#else
3699 +#define DEBUGP(format, args...)
3700 +#endif
3701 +
3702 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
3703 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
3704 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
3705 +#include <linux/netfilter_ipv4/listhelp.h>
3706 +
3707 +/* For future conections RPC, using client's cache bindings
3708 + * I'll use ip_conntrack_lock to lock these lists         */
3709 +
3710 +LIST_HEAD(request_p_list_tcp);
3711 +
3712 +
3713 +static void delete_request_p(unsigned long request_p_ul) 
3714 +{
3715 +       struct request_p *p = (void *)request_p_ul;
3716 +       
3717 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3718 +       LIST_DELETE(&request_p_list_tcp, p);
3719 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3720 +       kfree(p);
3721 +       return;
3722 +}
3723 +
3724 +
3725 +static void req_cl(struct request_p * r)
3726 +{
3727 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3728 +       del_timer(&r->timeout);
3729 +       LIST_DELETE(&request_p_list_tcp, r);
3730 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3731 +       kfree(r);
3732 +       return;
3733 +}
3734 +
3735 +
3736 +static void clean_request(struct list_head *list)
3737 +{
3738 +       struct list_head *first = list->prev;
3739 +       struct list_head *temp = list->next;
3740 +       struct list_head *aux;
3741 +
3742 +       if (list_empty(list))
3743 +               return;
3744 +
3745 +       while (first != temp) {
3746 +               aux = temp->next;
3747 +               req_cl((struct request_p *)temp);
3748 +               temp = aux;     
3749 +       }
3750 +       req_cl((struct request_p *)temp);
3751 +       return;
3752 +}
3753 +
3754 +
3755 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
3756 +                    u_int16_t port)
3757 +{
3758 +       struct request_p *req_p;
3759 +       
3760 +       /* Verifies if entry already exists */
3761 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3762 +       req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3763 +               struct request_p *, xid, ip, port);
3764 +
3765 +       if (req_p) {
3766 +               /* Refresh timeout */
3767 +               if (del_timer(&req_p->timeout)) {
3768 +                       req_p->timeout.expires = jiffies + EXP;
3769 +                       add_timer(&req_p->timeout);     
3770 +               } 
3771 +               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3772 +               return; 
3773 +
3774 +       }
3775 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
3776 +       
3777 +       /* Allocate new request_p */
3778 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
3779 +       if (!req_p) {
3780 +               DEBUGP("can't allocate request_p\n");
3781 +               return;                 
3782 +       }
3783 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
3784 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
3785 +                       NULL }}); 
3786 +      
3787 +       /* Initialize timer */
3788 +       init_timer(&req_p->timeout);
3789 +       req_p->timeout.function = delete_request_p;
3790 +       add_timer(&req_p->timeout); 
3791 +
3792 +       /* Put in list */
3793 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
3794 +       list_prepend(&request_p_list_tcp, req_p);
3795 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
3796 +       return; 
3797 +
3798 +}
3799 +
3800 +
3801 +static int check_rpc_packet(const u_int32_t *data,
3802 +                       int dir, struct ip_conntrack *ct,
3803 +                       struct list_head request_p_list)
3804 +{
3805 +       struct request_p *req_p;
3806 +       u_int32_t xid;
3807 +       struct ip_conntrack_expect expect, *exp = &expect;
3808 +
3809 +        /* Translstion's buffer for XDR */
3810 +        u_int16_t port_buf;
3811 +
3812 +
3813 +       /* Get XID */
3814 +       xid = *data;
3815 +
3816 +       /* This does sanity checking on RPC payloads,
3817 +        * and permits only the RPC "get port" (3)
3818 +        * in authorised procedures in client
3819 +        * communications with the portmapper.
3820 +        */
3821 +
3822 +       /* perform direction dependant RPC work */
3823 +       if (dir == IP_CT_DIR_ORIGINAL) {
3824 +
3825 +               data += 5;
3826 +
3827 +               /* Get RPC requestor */
3828 +               if (IXDR_GET_INT32(data) != 3) {
3829 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
3830 +                       return NF_ACCEPT;
3831 +               }
3832 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
3833 +
3834 +               data++;
3835 +
3836 +               /* Jump Credentials and Verfifier */
3837 +               data += IXDR_GET_INT32(data) + 2;
3838 +               data += IXDR_GET_INT32(data) + 2;
3839 +
3840 +               /* Get RPC procedure */
3841 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
3842 +                       (unsigned int)IXDR_GET_INT32(data));
3843 +
3844 +               /* Get RPC protocol and store against client parameters */
3845 +               data = data + 2;
3846 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
3847 +                               ct->tuplehash[dir].tuple.src.u.all);
3848 +
3849 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
3850 +                       xid, IXDR_GET_INT32(data),
3851 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3852 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
3853 +
3854 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
3855 +                       (unsigned int)IXDR_GET_INT32(data));
3856 +
3857 +       } else {
3858 +
3859 +               /* Check for returning packet's stored counterpart */
3860 +               req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
3861 +                                 struct request_p *, xid,
3862 +                                 ct->tuplehash[!dir].tuple.src.ip,
3863 +                                 ct->tuplehash[!dir].tuple.src.u.all);
3864 +
3865 +               /* Drop unexpected packets */
3866 +               if (!req_p) {
3867 +                       DEBUGP("packet is not expected. [skip]\n");
3868 +                       return NF_ACCEPT;
3869 +               }
3870 +
3871 +               /* Verifies if packet is really an RPC reply packet */
3872 +               data = data++;
3873 +               if (IXDR_GET_INT32(data) != 1) {
3874 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
3875 +                       return NF_ACCEPT;
3876 +               }
3877 +
3878 +               /* Is status accept? */
3879 +               data++;
3880 +               if (IXDR_GET_INT32(data)) {
3881 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
3882 +                       return NF_ACCEPT;
3883 +               }
3884 +
3885 +               /* Get Verifier length. Jump verifier */
3886 +               data++;
3887 +               data = data + IXDR_GET_INT32(data) + 2;
3888 +
3889 +               /* Is accpet status "success"? */
3890 +               if (IXDR_GET_INT32(data)) {
3891 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
3892 +                       return NF_ACCEPT;
3893 +               }
3894 +
3895 +               /* Get server port number */      
3896 +               data++;
3897 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
3898 +
3899 +               /* If a packet has made it this far then it deserves an
3900 +                * expectation ...  if port == 0, then this service is 
3901 +                * not going to be registered.
3902 +                */
3903 +               if (port_buf) {
3904 +                       DEBUGP("port found: %u\n", port_buf);
3905 +
3906 +                       memset(&expect, 0, sizeof(expect));
3907 +
3908 +                       /* Watch out, Radioactive-Man! */
3909 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
3910 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
3911 +                       exp->mask.src.ip = 0xffffffff;
3912 +                       exp->mask.dst.ip = 0xffffffff;
3913 +
3914 +                       switch (req_p->proto) {
3915 +                               case IPPROTO_UDP:
3916 +                                       exp->tuple.src.u.udp.port = 0;
3917 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
3918 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
3919 +                                       exp->mask.src.u.udp.port = 0;
3920 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
3921 +                                       exp->mask.dst.protonum = 0xffff;
3922 +                                       break;
3923 +
3924 +                               case IPPROTO_TCP:
3925 +                                       exp->tuple.src.u.tcp.port = 0;
3926 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
3927 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
3928 +                                       exp->mask.src.u.tcp.port = 0;
3929 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
3930 +                                       exp->mask.dst.protonum = 0xffff;
3931 +                                       break;
3932 +                       }
3933 +                       exp->expectfn = NULL;
3934 +
3935 +                       ip_conntrack_expect_related(ct, &expect);
3936 +
3937 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
3938 +                               NIPQUAD(exp->tuple.src.ip),
3939 +                               NIPQUAD(exp->tuple.dst.ip),
3940 +                               port_buf, req_p->proto);
3941 +
3942 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
3943 +                               NIPQUAD(exp->mask.src.ip),
3944 +                               NIPQUAD(exp->mask.dst.ip),
3945 +                               exp->mask.dst.protonum);
3946 +
3947 +               }
3948 +
3949 +               req_cl(req_p);
3950 +
3951 +               DEBUGP("packet evaluated. [expect]\n");
3952 +               return NF_ACCEPT;
3953 +       }
3954 +
3955 +       return NF_ACCEPT;
3956 +
3957 +}
3958 +
3959 +
3960 +/* RPC TCP helper */
3961 +static int help(const struct iphdr *iph, size_t len,
3962 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3963 +{
3964 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3965 +       const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
3966 +       size_t tcplen = len - iph->ihl * 4;
3967 +
3968 +       int dir = CTINFO2DIR(ctinfo);
3969 +       int crp_ret;
3970 +
3971 +
3972 +       DEBUGP("new packet to evaluate ..\n");
3973 +
3974 +       /* This works for packets like handshake packets, ignore */
3975 +       if (len == ((tcph->doff + iph->ihl) * 4)) {
3976 +               DEBUGP("packet has no data (may still be handshaking). [skip]\n");
3977 +               return NF_ACCEPT;
3978 +       }
3979 +
3980 +       /* Until there's been traffic both ways, don't look in packets. */
3981 +       if (ctinfo != IP_CT_ESTABLISHED
3982 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3983 +               DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
3984 +               DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
3985 +               DEBUGP("packet is not yet part of a two way stream. [skip]\n");
3986 +               return NF_ACCEPT;
3987 +       }
3988 +
3989 +       /* Not whole TCP header? */
3990 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3991 +               DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
3992 +               DEBUGP("packet does not contain a complete TCP header. [skip]\n");
3993 +               return NF_ACCEPT;
3994 +       }
3995 +
3996 +       /* FIXME: Source route IP option packets --RR */
3997 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3998 +                        csum_partial((char *) tcph, tcplen, 0))) {
3999 +               DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4000 +                    tcph, tcplen, NIPQUAD(iph->saddr),
4001 +                    NIPQUAD(iph->daddr));
4002 +               DEBUGP("[note: failure to get past this error may indicate source routing]\n");
4003 +               DEBUGP("packet contains a bad checksum. [skip]\n");
4004 +               return NF_ACCEPT;
4005 +       }
4006 +
4007 +       /* perform direction dependant protocol work */
4008 +       if (dir == IP_CT_DIR_ORIGINAL) {
4009 +
4010 +               DEBUGP("packet is from the initiator. [cont]\n");
4011 +
4012 +               /* Tests if packet len is ok */
4013 +               if ((tcplen - (tcph->doff * 4)) != 60) {
4014 +                       DEBUGP("packet length is not correct. [skip]\n");
4015 +                       return NF_ACCEPT;
4016 +               }
4017 +
4018 +       } else {
4019 +
4020 +               DEBUGP("packet is from the receiver. [cont]\n");
4021 +
4022 +               /* Tests if packet len is ok */
4023 +               if ((tcplen - (tcph->doff * 4)) != 32) {
4024 +                       DEBUGP("packet length is not correct. [skip]\n");
4025 +                       return NF_ACCEPT;
4026 +               }
4027 +       }
4028 +
4029 +       /* Get to the data */
4030 +       data++;
4031 +
4032 +       /* Check the RPC data */
4033 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
4034 +
4035 +       return crp_ret;
4036 +
4037 +}
4038 +
4039 +
4040 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
4041 +
4042 +static void fini(void);
4043 +
4044 +
4045 +static int __init init(void)
4046 +{
4047 +       int port, ret;
4048 +       static char name[10];
4049 +
4050 +
4051 +       /* If no port given, default to standard RPC port */
4052 +       if (ports[0] == 0)
4053 +               ports[0] = RPC_PORT;
4054 +
4055 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4056 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4057 +
4058 +                if (ports[port] == RPC_PORT)
4059 +                        sprintf(name, "rpc");
4060 +                else
4061 +                        sprintf(name, "rpc-%d", port);
4062 +
4063 +               rpc_helpers[port].name = name;
4064 +               rpc_helpers[port].me = THIS_MODULE;
4065 +               rpc_helpers[port].max_expected = 1;
4066 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4067 +               rpc_helpers[port].timeout = 0;
4068 +
4069 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4070 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
4071 +
4072 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
4073 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
4074 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
4075 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
4076 +
4077 +               rpc_helpers[port].help = help;
4078 +
4079 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4080 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4081 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
4082 +                       ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
4083 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
4084 +                       ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
4085 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4086 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
4087 +                       ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
4088 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
4089 +                       ntohs(rpc_helpers[port].mask.src.u.tcp.port));
4090 +
4091 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4092 +
4093 +               if (ret) {
4094 +                       printk("ERROR registering port %d\n",
4095 +                               ports[port]);
4096 +                       fini();
4097 +                       return -EBUSY;
4098 +               }
4099 +               ports_n_c++;
4100 +       }
4101 +       return 0;
4102 +}
4103 +
4104 +
4105 +/* This function is intentionally _NOT_ defined as __exit, because 
4106 + * it is needed by the init function */
4107 +static void fini(void)
4108 +{
4109 +       int port;
4110 +
4111 +       DEBUGP("cleaning request list\n");
4112 +       clean_request(&request_p_list_tcp);
4113 +
4114 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4115 +               DEBUGP("unregistering port %d\n", ports[port]);
4116 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
4117 +       }
4118 +}
4119 +
4120 +
4121 +module_init(init);
4122 +module_exit(fini);
4123 +
4124 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
4125 +EXPORT_SYMBOL(request_p_list_tcp);
4126 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
4127 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
4128 +
4129 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
4130 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c       1970-01-01 01:00:00.000000000 +0100
4131 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rpc_udp.c   2004-04-29 11:20:02.000000000 +0200
4132 @@ -0,0 +1,503 @@
4133 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
4134 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
4135 + *     - original rpc tracking module
4136 + *     - "recent" connection handling for kernel 2.3+ netfilter
4137 + *
4138 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
4139 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
4140 + *
4141 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4142 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
4143 + *     - extended matching to support filtering on procedures
4144 + *
4145 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
4146 + *
4147 + *     This program is free software; you can redistribute it and/or
4148 + *     modify it under the terms of the GNU General Public License
4149 + *     as published by the Free Software Foundation; either version
4150 + *     2 of the License, or (at your option) any later version.
4151 + **
4152 + *     Module load syntax:
4153 + *     insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
4154 + *
4155 + *     Please give the ports of all RPC servers you wish to connect to.
4156 + *     If you don't specify ports, the default will be port 111.
4157 + **
4158 + *     Note to all:
4159 + *
4160 + *     RPCs should not be exposed to the internet - ask the Pentagon;
4161 + *
4162 + *       "The unidentified crackers pleaded guilty in July to charges
4163 + *        of juvenile delinquency stemming from a string of Pentagon
4164 + *        network intrusions in February.
4165 + *
4166 + *        The youths, going by the names TooShort and Makaveli, used
4167 + *        a common server security hole to break in, according to
4168 + *        Dane Jasper, owner of the California Internet service
4169 + *        provider, Sonic. They used the hole, known as the 'statd'
4170 + *        exploit, to attempt more than 800 break-ins, Jasper said."
4171 + *
4172 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
4173 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
4174 + **
4175 + */
4176 +
4177 +#include <linux/module.h>
4178 +#include <linux/netfilter.h>
4179 +#include <linux/ip.h>
4180 +#include <net/checksum.h>
4181 +#include <net/udp.h>
4182 +
4183 +#include <asm/param.h>
4184 +#include <linux/sched.h>
4185 +#include <linux/timer.h>
4186 +#include <linux/stddef.h>
4187 +#include <linux/list.h>
4188 +
4189 +#include <linux/netfilter_ipv4/lockhelp.h>
4190 +#include <linux/netfilter_ipv4/ip_tables.h>
4191 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4192 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
4193 +
4194 +#define MAX_PORTS 8
4195 +static int ports[MAX_PORTS];
4196 +static int ports_n_c = 0;
4197 +
4198 +#ifdef MODULE_PARM
4199 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4200 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
4201 +#endif
4202 +
4203 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
4204 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
4205 +MODULE_LICENSE("GPL");
4206 +
4207 +#if 0
4208 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
4209 +                                       format, ## args)
4210 +#else
4211 +#define DEBUGP(format, args...)
4212 +#endif
4213 +
4214 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
4215 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
4216 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
4217 +#include <linux/netfilter_ipv4/listhelp.h>
4218 +
4219 +/* For future conections RPC, using client's cache bindings
4220 + * I'll use ip_conntrack_lock to lock these lists           */
4221 +
4222 +LIST_HEAD(request_p_list_udp);
4223 +
4224 +
4225 +static void delete_request_p(unsigned long request_p_ul)
4226 +{
4227 +       struct request_p *p = (void *)request_p_ul;
4228 +       
4229 +       WRITE_LOCK(&ipct_rpc_udp_lock);
4230 +       LIST_DELETE(&request_p_list_udp, p);
4231 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
4232 +       kfree(p);
4233 +       return;
4234 +}
4235 +
4236 +
4237 +static void req_cl(struct request_p * r)
4238 +{
4239 +       WRITE_LOCK(&ipct_rpc_udp_lock);
4240 +       del_timer(&r->timeout);
4241 +       LIST_DELETE(&request_p_list_udp, r);
4242 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
4243 +       kfree(r);
4244 +       return;
4245 +}
4246 +
4247 +
4248 +static void clean_request(struct list_head *list)
4249 +{
4250 +       struct list_head *first = list->prev;
4251 +       struct list_head *temp = list->next;
4252 +       struct list_head *aux;
4253 +
4254 +       if (list_empty(list))
4255 +               return;
4256 +
4257 +       while (first != temp) {
4258 +               aux = temp->next;
4259 +               req_cl((struct request_p *)temp);
4260 +               temp = aux;     
4261 +       }
4262 +       req_cl((struct request_p *)temp);
4263 +       return;
4264 +}
4265 +
4266 +
4267 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
4268 +                    u_int16_t port)
4269 +{
4270 +       struct request_p *req_p;
4271 +        
4272 +       /* Verifies if entry already exists */
4273 +       WRITE_LOCK(&ipct_rpc_udp_lock);
4274 +       req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4275 +               struct request_p *, xid, ip, port);
4276 +
4277 +       if (req_p) {
4278 +               /* Refresh timeout */
4279 +               if (del_timer(&req_p->timeout)) {
4280 +                       req_p->timeout.expires = jiffies + EXP;
4281 +                       add_timer(&req_p->timeout);     
4282 +               } 
4283 +               WRITE_UNLOCK(&ipct_rpc_udp_lock);
4284 +               return; 
4285 +
4286 +       }
4287 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
4288 +       
4289 +       /* Allocate new request_p */
4290 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
4291 +       if (!req_p) {
4292 +               DEBUGP("can't allocate request_p\n");
4293 +               return;                 
4294 +       }
4295 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
4296 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
4297 +                       NULL }}); 
4298 +      
4299 +       /* Initialize timer */
4300 +       init_timer(&req_p->timeout);
4301 +       req_p->timeout.function = delete_request_p;
4302 +       add_timer(&req_p->timeout); 
4303 +
4304 +       /* Put in list */
4305 +       WRITE_LOCK(&ipct_rpc_udp_lock);
4306 +       list_prepend(&request_p_list_udp, req_p);
4307 +       WRITE_UNLOCK(&ipct_rpc_udp_lock); 
4308 +       return; 
4309 +
4310 +}
4311 +
4312 +
4313 +static int check_rpc_packet(const u_int32_t *data,
4314 +                       int dir, struct ip_conntrack *ct,
4315 +                       struct list_head request_p_list)
4316 +{
4317 +       struct request_p *req_p;
4318 +       u_int32_t xid;
4319 +       struct ip_conntrack_expect expect, *exp = &expect;
4320 +
4321 +       /* Translstion's buffer for XDR */
4322 +       u_int16_t port_buf;
4323 +
4324 +
4325 +       /* Get XID */
4326 +       xid = *data;
4327 +
4328 +       /* This does sanity checking on RPC payloads,
4329 +        * and permits only the RPC "get port" (3)
4330 +        * in authorised procedures in client
4331 +        * communications with the portmapper.
4332 +        */
4333 +
4334 +       /* perform direction dependant RPC work */
4335 +       if (dir == IP_CT_DIR_ORIGINAL) {
4336 +
4337 +               data += 5;
4338 +
4339 +               /* Get RPC requestor */
4340 +               if (IXDR_GET_INT32(data) != 3) {
4341 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
4342 +                       return NF_ACCEPT;
4343 +               }
4344 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
4345 +
4346 +               data++;
4347 +
4348 +               /* Jump Credentials and Verfifier */
4349 +               data = data + IXDR_GET_INT32(data) + 2;
4350 +               data = data + IXDR_GET_INT32(data) + 2;
4351 +
4352 +               /* Get RPC procedure */
4353 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
4354 +                       (unsigned int)IXDR_GET_INT32(data));
4355 +
4356 +               /* Get RPC protocol and store against client parameters */
4357 +               data = data + 2;
4358 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
4359 +                               ct->tuplehash[dir].tuple.src.u.all);
4360 +
4361 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
4362 +                       xid, IXDR_GET_INT32(data),
4363 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
4364 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
4365 +
4366 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
4367 +                       (unsigned int)IXDR_GET_INT32(data));
4368 +
4369 +       } else {
4370 +
4371 +               /* Check for returning packet's stored counterpart */
4372 +               req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
4373 +                                 struct request_p *, xid,
4374 +                                 ct->tuplehash[!dir].tuple.src.ip,
4375 +                                 ct->tuplehash[!dir].tuple.src.u.all);
4376 +
4377 +               /* Drop unexpected packets */
4378 +               if (!req_p) {
4379 +                       DEBUGP("packet is not expected. [skip]\n");
4380 +                       return NF_ACCEPT;
4381 +               }
4382 +
4383 +               /* Verifies if packet is really an RPC reply packet */
4384 +               data = data++;
4385 +               if (IXDR_GET_INT32(data) != 1) {
4386 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
4387 +                       return NF_ACCEPT;
4388 +               }
4389 +
4390 +               /* Is status accept? */
4391 +               data++;
4392 +               if (IXDR_GET_INT32(data)) {
4393 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
4394 +                       return NF_ACCEPT;
4395 +               }
4396 +
4397 +               /* Get Verifier length. Jump verifier */
4398 +               data++;
4399 +               data = data + IXDR_GET_INT32(data) + 2;
4400 +
4401 +               /* Is accpet status "success"? */
4402 +               if (IXDR_GET_INT32(data)) {
4403 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
4404 +                       return NF_ACCEPT;
4405 +               }
4406 +
4407 +               /* Get server port number */      
4408 +               data++;
4409 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
4410 +
4411 +               /* If a packet has made it this far then it deserves an
4412 +                * expectation ...  if port == 0, then this service is 
4413 +                * not going to be registered.
4414 +                */
4415 +               if (port_buf) {
4416 +                       DEBUGP("port found: %u\n", port_buf);
4417 +
4418 +                       memset(&expect, 0, sizeof(expect));
4419 +
4420 +                       /* Watch out, Radioactive-Man! */
4421 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4422 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4423 +                       exp->mask.src.ip = 0xffffffff;
4424 +                       exp->mask.dst.ip = 0xffffffff;
4425 +
4426 +                       switch (req_p->proto) {
4427 +                               case IPPROTO_UDP:
4428 +                                       exp->tuple.src.u.udp.port = 0;
4429 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
4430 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
4431 +                                       exp->mask.src.u.udp.port = 0;
4432 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
4433 +                                       exp->mask.dst.protonum = 0xffff;
4434 +                                       break;
4435 +
4436 +                               case IPPROTO_TCP:
4437 +                                       exp->tuple.src.u.tcp.port = 0;
4438 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
4439 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
4440 +                                       exp->mask.src.u.tcp.port = 0;
4441 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
4442 +                                       exp->mask.dst.protonum = 0xffff;
4443 +                                       break;
4444 +                       }
4445 +                       exp->expectfn = NULL;
4446 +
4447 +                       ip_conntrack_expect_related(ct, &expect);
4448 +
4449 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
4450 +                               NIPQUAD(exp->tuple.src.ip),
4451 +                               NIPQUAD(exp->tuple.dst.ip),
4452 +                               port_buf, req_p->proto);
4453 +
4454 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
4455 +                               NIPQUAD(exp->mask.src.ip),
4456 +                               NIPQUAD(exp->mask.dst.ip),
4457 +                               exp->mask.dst.protonum);
4458 +
4459 +               }
4460 +
4461 +               req_cl(req_p);
4462 +
4463 +               DEBUGP("packet evaluated. [expect]\n");
4464 +               return NF_ACCEPT;
4465 +       }
4466 +
4467 +       return NF_ACCEPT;
4468 +
4469 +}
4470 +
4471 +
4472 +/* RPC UDP helper */
4473 +static int help(const struct iphdr *iph, size_t len,
4474 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4475 +{
4476 +       struct udphdr *udph = (void *) iph + iph->ihl * 4;
4477 +       const u_int32_t *data = (const u_int32_t *)udph + 2;
4478 +       size_t udplen = len - iph->ihl * 4;
4479 +       int dir = CTINFO2DIR(ctinfo);
4480 +       int crp_ret;
4481 +
4482 +       /* Checksum */
4483 +       const u_int16_t *chsm = (const u_int16_t *)udph + 3;
4484 +
4485 +
4486 +       DEBUGP("new packet to evaluate ..\n");
4487 +
4488 +       /* Not whole UDP header? */
4489 +       if (udplen < sizeof(struct udphdr)) {
4490 +               DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
4491 +               DEBUGP("packet does not contain a complete UDP header. [skip]\n");
4492 +               return NF_ACCEPT;
4493 +       }
4494 +
4495 +       /* FIXME: Source route IP option packets --RR */
4496 +       if (*chsm) {
4497 +               if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
4498 +                   csum_partial((char *)udph, udplen, 0))) {
4499 +                       DEBUGP("[note: failure to get past this error may indicate source routing]\n");
4500 +                       DEBUGP("packet contains a bad checksum. [skip]\n");
4501 +                       return NF_ACCEPT;
4502 +                  } 
4503 +       }
4504 +
4505 +       /* perform direction dependant protocol work */
4506 +       if (dir == IP_CT_DIR_ORIGINAL) {
4507 +
4508 +               DEBUGP("packet is from the initiator. [cont]\n");
4509 +
4510 +               /* Tests if packet len is ok */
4511 +               if ((udplen - sizeof(struct udphdr)) != 56) {
4512 +                       DEBUGP("packet length is not correct. [skip]\n");
4513 +                       return NF_ACCEPT;
4514 +               }
4515 +
4516 +       } else {
4517 +
4518 +               DEBUGP("packet is from the receiver. [cont]\n");
4519 +
4520 +               /* Until there's been traffic both ways, don't look in packets. */
4521 +               if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4522 +                       DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
4523 +                       DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
4524 +                       DEBUGP("packet is not yet part of a two way stream. [skip]\n");
4525 +                       return NF_ACCEPT;
4526 +               }
4527 +
4528 +               /* Tests if packet len is ok */
4529 +                       if ((udplen - sizeof(struct udphdr)) != 28) {
4530 +                       DEBUGP("packet length is not correct. [skip]\n");
4531 +                       return NF_ACCEPT;
4532 +               }
4533 +
4534 +       }
4535 +
4536 +       /* Get to the data */
4537 +       /* udp *data == *correct */
4538 +
4539 +       /* Check the RPC data */
4540 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
4541 +
4542 +       return crp_ret;
4543 +
4544 +}
4545 +
4546 +
4547 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
4548 +
4549 +static void fini(void);
4550 +
4551 +
4552 +static int __init init(void)
4553 +{
4554 +       int port, ret;
4555 +       static char name[10];
4556 +
4557 +
4558 +       /* If no port given, default to standard RPC port */
4559 +       if (ports[0] == 0)
4560 +               ports[0] = RPC_PORT;
4561 +
4562 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4563 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4564 +
4565 +                if (ports[port] == RPC_PORT)
4566 +                        sprintf(name, "rpc");
4567 +                else
4568 +                        sprintf(name, "rpc-%d", port);
4569 +
4570 +               rpc_helpers[port].name = name;
4571 +               rpc_helpers[port].me = THIS_MODULE;
4572 +               rpc_helpers[port].max_expected = 1;
4573 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4574 +               rpc_helpers[port].timeout = 0;
4575 +
4576 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
4577 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
4578 +
4579 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
4580 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
4581 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
4582 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
4583 +
4584 +               rpc_helpers[port].help = help;
4585 +
4586 +               DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
4587 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4588 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
4589 +                       ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
4590 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
4591 +                       ntohs(rpc_helpers[port].tuple.src.u.udp.port));
4592 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4593 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
4594 +                       ntohs(rpc_helpers[port].mask.dst.u.udp.port),
4595 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
4596 +                       ntohs(rpc_helpers[port].mask.src.u.udp.port));
4597 +
4598 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
4599 +
4600 +               if (ret) {
4601 +                       printk("ERROR registering port %d\n",
4602 +                               ports[port]);
4603 +                       fini();
4604 +                       return -EBUSY;
4605 +               }
4606 +               ports_n_c++;
4607 +       }
4608 +       return 0;
4609 +}
4610 +
4611 +
4612 +/* This function is intentionally _NOT_ defined as __exit, because 
4613 + * it is needed by the init function */
4614 +static void fini(void)
4615 +{
4616 +       int port;
4617 +
4618 +       DEBUGP("cleaning request list\n");
4619 +       clean_request(&request_p_list_udp);
4620 +
4621 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
4622 +               DEBUGP("unregistering port %d\n", ports[port]);
4623 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
4624 +       }
4625 +}
4626 +
4627 +
4628 +module_init(init);
4629 +module_exit(fini);
4630 +
4631 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
4632 +EXPORT_SYMBOL(request_p_list_udp);
4633 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
4634 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
4635 +
4636 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
4637 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c   1970-01-01 01:00:00.000000000 +0100
4638 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c       2004-04-29 11:20:06.000000000 +0200
4639 @@ -0,0 +1,331 @@
4640 +/* RSH extension for IP connection tracking, Version 1.0
4641 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4642 + * based on HW's ip_conntrack_irc.c    
4643 + *
4644 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
4645 + *
4646 + *      This program is free software; you can redistribute it and/or
4647 + *      modify it under the terms of the GNU General Public License
4648 + *      as published by the Free Software Foundation; either version
4649 + *      2 of the License, or (at your option) any later version.
4650 + **
4651 + *     Module load syntax:
4652 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
4653 + *     
4654 + *     please give the ports of all RSH servers You wish to connect to.
4655 + *     If You don't specify ports, the default will be port 514
4656 + **
4657 + *      Note to all:
4658 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
4659 + *        unfortunately I babysit some sysadmins that won't migrate
4660 + *       their legacy crap, in our second tier.
4661 + */
4662 +
4663 +
4664 +/*
4665 + *  Some docco ripped from the net to teach me all there is to know about
4666 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
4667 + *  this module).
4668 + *
4669 + *  I have no idea what "unix rshd man pages" these guys have .. but that
4670 + *  is some pretty detailed docco!
4671 + **
4672 + *
4673 + *  4. Of the rsh protocol.
4674 + *  -----------------------
4675 + * 
4676 + *   The rshd listens on TCP port #514. The following info is from the unix
4677 + *   rshd man pages :
4678 + * 
4679 + *   "Service Request Protocol
4680 + * 
4681 + *    When the rshd daemon receives a service request, it initiates the
4682 + *    following protocol:
4683 + * 
4684 + *     1. The rshd daemon checks the source port number for the request.
4685 + *        If the port number is not in the range 0 through 1023, the rshd daemon
4686 + *        terminates the connection.
4687 + * 
4688 + *     2. The rshd daemon reads characters from the socket up to a null byte.
4689 + *        The string read is interpreted as an ASCII number (base 10). If this
4690 + *        number is nonzero, the rshd daemon interprets it as the port number
4691 + *        of a secondary stream to be used as standard error. A second connection
4692 + *        is created to the specified port on the client host. The source port
4693 + *        on the local host is in the range 0 through 1023.
4694 + * 
4695 + *     3. The rshd daemon uses the source address of the initial connection
4696 + *        request to determine the name of the client host. If the name cannot
4697 + *        be determined, the rshd daemon uses the dotted decimal representation
4698 + *        of the client host's address.
4699 + * 
4700 + *     4. The rshd daemon retrieves the following information from the initial
4701 + *        socket:
4702 + * 
4703 + *         * A null-terminated string of at most 16 bytes interpreted as
4704 + *           the user name of the user on the client host.
4705 + * 
4706 + *         * A null-terminated string of at most 16 bytes interpreted as
4707 + *           the user name to be used on the local server host.
4708 + * 
4709 + *         * Another null-terminated string interpreted as a command line
4710 + *           to be passed to a shell on the local server host.
4711 + * 
4712 + *     5. The rshd daemon attempts to validate the user using the following steps:
4713 + * 
4714 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
4715 + *            file and tries to switch to the home directory (using the chdir
4716 + *            subroutine). If either the lookup or the directory change fails,
4717 + *            the rshd daemon terminates the connection.
4718 + * 
4719 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
4720 + *            the /etc/hosts.equiv file to see if the name of the client
4721 + *            workstation is listed. If the client workstation is listed as an
4722 + *            equivalent host, the rshd daemon validates the user.
4723 + * 
4724 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4725 + *            authenticate the user by checking the .rhosts file.
4726 + * 
4727 + *         d. If either the $HOME/.rhosts authentication fails or the
4728 + *            client host is not an equivalent host, the rshd daemon
4729 + *            terminates the connection.
4730 + * 
4731 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
4732 + *        on the initial connection and passes the command line to the user's
4733 + *        local login shell. The shell then inherits the network connections
4734 + *        established by the rshd daemon."
4735 + * 
4736 + */
4737 +
4738 +
4739 +#include <linux/module.h>
4740 +#include <linux/netfilter.h>
4741 +#include <linux/ip.h>
4742 +#include <net/checksum.h>
4743 +#include <net/tcp.h>
4744 +
4745 +#include <linux/netfilter_ipv4/lockhelp.h>
4746 +#include <linux/netfilter_ipv4/ip_tables.h>
4747 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4748 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4749 +
4750 +#define MAX_PORTS 8
4751 +static int ports[MAX_PORTS];
4752 +static int ports_n_c = 0;
4753 +
4754 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4755 +MODULE_DESCRIPTION("RSH connection tracking module");
4756 +MODULE_LICENSE("GPL");
4757 +#ifdef MODULE_PARM
4758 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4759 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4760 +#endif
4761 +
4762 +DECLARE_LOCK(ip_rsh_lock);
4763 +struct module *ip_conntrack_rsh = THIS_MODULE;
4764 +
4765 +#if 0
4766 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4767 +                                       format, ## args)
4768 +#else
4769 +#define DEBUGP(format, args...)
4770 +#endif
4771 +
4772 +
4773 +
4774 +/* FIXME: This should be in userspace.  Later. */
4775 +static int help(const struct iphdr *iph, size_t len,
4776 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4777 +{
4778 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4779 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4780 +       const char *data = (const char *) tcph + tcph->doff * 4;
4781 +       u_int32_t tcplen = len - iph->ihl * 4;
4782 +       int dir = CTINFO2DIR(ctinfo);
4783 +        struct ip_conntrack_expect expect, *exp = &expect;
4784 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4785 +       u_int16_t port;
4786 +       int maxoctet;
4787 +
4788 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
4789 +        *  original array size used in rshd/glibc) -- is there a
4790 +        *  vulnerability in rshd.c in the looped port *= 10?
4791 +        */
4792 +
4793 +
4794 +       DEBUGP("entered\n");
4795 +
4796 +       /* bail if packet is not from RSH client */
4797 +       if (dir == IP_CT_DIR_REPLY)
4798 +               return NF_ACCEPT;
4799 +
4800 +       /* Until there's been traffic both ways, don't look in packets. */
4801 +       if (ctinfo != IP_CT_ESTABLISHED
4802 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4803 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
4804 +               return NF_ACCEPT;
4805 +       }
4806 +
4807 +       /* Not whole TCP header? */
4808 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4809 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4810 +               return NF_ACCEPT;
4811 +       }
4812 +
4813 +       /* Checksum invalid?  Ignore. */
4814 +       /* FIXME: Source route IP option packets --RR */
4815 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4816 +                        csum_partial((char *) tcph, tcplen, 0))) {
4817 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4818 +                    tcph, tcplen, NIPQUAD(iph->saddr),
4819 +                    NIPQUAD(iph->daddr));
4820 +               return NF_ACCEPT;
4821 +       }
4822 +
4823 +       /* find the rsh stderr port */
4824 +       maxoctet = 4;
4825 +       port = 0;
4826 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4827 +               if (*data < 0)
4828 +                       return(1);
4829 +               if (*data == 0)
4830 +                       break;
4831 +               if (*data < 48 || *data > 57) {
4832 +                       DEBUGP("these aren't the packets you're looking for ..\n");
4833 +                       return NF_ACCEPT;
4834 +               }
4835 +               port = port * 10 + ( *data - 48 );
4836 +       }
4837 +
4838 +       /* dont relate sessions that try to expose the client */
4839 +       DEBUGP("found port %u\n", port);
4840 +       if (port > 1023) {
4841 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
4842 +               return NF_ACCEPT;
4843 +       }
4844 +
4845 +
4846 +       LOCK_BH(&ip_rsh_lock);
4847 +
4848 +       /*  new(,related) connection is;
4849 +        *          reply + dst (uint)port + src port (0:1023)
4850 +        */
4851 +       memset(&expect, 0, sizeof(expect));
4852 +
4853 +       /*  save some discovered data, in case someone ever wants to write
4854 +        *  a NAT module for this bastard ..
4855 +        */
4856 +       exp_rsh_info->port = port;
4857 +
4858 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4859 +
4860 +
4861 +       /* Watch out, Radioactive-Man! */
4862 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4863 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4864 +       exp->tuple.src.u.tcp.port = 0;
4865 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4866 +       exp->tuple.dst.protonum = IPPROTO_TCP;
4867 +
4868 +       exp->mask.src.ip = 0xffffffff;
4869 +       exp->mask.dst.ip = 0xffffffff;
4870 +
4871 +       exp->mask.src.u.tcp.port = htons(0xfc00);
4872 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
4873 +       exp->mask.dst.protonum = 0xffff;
4874 +
4875 +       exp->expectfn = NULL;
4876 +
4877 +       ip_conntrack_expect_related(ct, &expect);
4878 +
4879 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4880 +               NIPQUAD(exp->tuple.src.ip),
4881 +               ntohs(exp->tuple.src.u.tcp.port),
4882 +               NIPQUAD(exp->tuple.dst.ip),
4883 +               ntohs(exp->tuple.dst.u.tcp.port));
4884 +
4885 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4886 +               NIPQUAD(exp->mask.src.ip),
4887 +               ntohs(exp->mask.src.u.tcp.port),
4888 +               NIPQUAD(exp->mask.dst.ip),
4889 +               ntohs(exp->mask.dst.u.tcp.port));
4890 +       UNLOCK_BH(&ip_rsh_lock);
4891 +
4892 +       return NF_ACCEPT;
4893 +}
4894 +
4895 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4896 +
4897 +static void fini(void);
4898 +
4899 +static int __init init(void)
4900 +{
4901 +       int port, ret;
4902 +       static char name[10];
4903 +
4904 +
4905 +       /* If no port given, default to standard RSH port */
4906 +       if (ports[0] == 0)
4907 +               ports[0] = RSH_PORT;
4908 +
4909 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4910 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4911 +
4912 +                if (ports[port] == RSH_PORT)
4913 +                        sprintf(name, "rsh");
4914 +                else
4915 +                        sprintf(name, "rsh-%d", port);
4916 +
4917 +               rsh_helpers[port].name = name;
4918 +               rsh_helpers[port].me = THIS_MODULE;
4919 +               rsh_helpers[port].max_expected = 1;
4920 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4921 +               rsh_helpers[port].timeout = 0;
4922 +
4923 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4924 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
4925 +
4926 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
4927 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4928 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4929 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4930 +
4931 +               rsh_helpers[port].help = help;
4932 +
4933 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4934 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4935 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
4936 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4937 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4938 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4939 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4940 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
4941 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4942 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
4943 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4944 +
4945 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4946 +
4947 +               if (ret) {
4948 +                       printk("ERROR registering port %d\n",
4949 +                               ports[port]);
4950 +                       fini();
4951 +                       return -EBUSY;
4952 +               }
4953 +               ports_n_c++;
4954 +       }
4955 +       return 0;
4956 +}
4957 +
4958 +/* This function is intentionally _NOT_ defined as __exit, because 
4959 + * it is needed by the init function */
4960 +static void fini(void)
4961 +{
4962 +       int port;
4963 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4964 +               DEBUGP("unregistering port %d\n", ports[port]);
4965 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
4966 +       }
4967 +}
4968 +
4969 +module_init(init);
4970 +module_exit(fini);
4971 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
4972 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c  1970-01-01 01:00:00.000000000 +0100
4973 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c      2004-04-29 11:20:13.000000000 +0200
4974 @@ -0,0 +1,507 @@
4975 +/*
4976 + * RTSP extension for IP connection tracking
4977 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
4978 + * based on ip_conntrack_irc.c
4979 + *
4980 + *      This program is free software; you can redistribute it and/or
4981 + *      modify it under the terms of the GNU General Public License
4982 + *      as published by the Free Software Foundation; either version
4983 + *      2 of the License, or (at your option) any later version.
4984 + *
4985 + * Module load syntax:
4986 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
4987 + *                              max_outstanding=n setup_timeout=secs
4988 + *
4989 + * If no ports are specified, the default will be port 554.
4990 + *
4991 + * With max_outstanding you can define the maximum number of not yet
4992 + * answered SETUP requests per RTSP session (default 8).
4993 + * With setup_timeout you can specify how long the system waits for
4994 + * an expected data channel (default 300 seconds).
4995 + */
4996 +
4997 +#include <linux/config.h>
4998 +#include <linux/module.h>
4999 +#include <linux/netfilter.h>
5000 +#include <linux/ip.h>
5001 +#include <net/checksum.h>
5002 +#include <net/tcp.h>
5003 +
5004 +#include <linux/netfilter_ipv4/lockhelp.h>
5005 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5006 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5007 +
5008 +#include <linux/ctype.h>
5009 +#define NF_NEED_STRNCASECMP
5010 +#define NF_NEED_STRTOU16
5011 +#define NF_NEED_STRTOU32
5012 +#define NF_NEED_NEXTLINE
5013 +#include <linux/netfilter_helpers.h>
5014 +#define NF_NEED_MIME_NEXTLINE
5015 +#include <linux/netfilter_mime.h>
5016 +
5017 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5018 +
5019 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5020 +#ifdef IP_NF_RTSP_DEBUG
5021 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5022 +#else
5023 +#define DEBUGP(fmt, args...)
5024 +#endif
5025 +
5026 +#define MAX_PORTS 8
5027 +static int ports[MAX_PORTS];
5028 +static int num_ports = 0;
5029 +static int max_outstanding = 8;
5030 +static unsigned int setup_timeout = 300;
5031 +
5032 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5033 +MODULE_DESCRIPTION("RTSP connection tracking module");
5034 +MODULE_LICENSE("GPL");
5035 +#ifdef MODULE_PARM
5036 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5037 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5038 +MODULE_PARM(max_outstanding, "i");
5039 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5040 +MODULE_PARM(setup_timeout, "i");
5041 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5042 +#endif
5043 +
5044 +DECLARE_LOCK(ip_rtsp_lock);
5045 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5046 +
5047 +/*
5048 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5049 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
5050 + * ports so keep this reasonably high.  If this is too low, you will see a
5051 + * lot of "no free client map entries" messages.
5052 + */
5053 +#define MAX_PORT_MAPS 16
5054 +
5055 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5056 +
5057 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5058 +
5059 +/*
5060 + * Parse an RTSP packet.
5061 + *
5062 + * Returns zero if parsing failed.
5063 + *
5064 + * Parameters:
5065 + *  IN      ptcp        tcp data pointer
5066 + *  IN      tcplen      tcp data len
5067 + *  IN/OUT  ptcpoff     points to current tcp offset
5068 + *  OUT     phdrsoff    set to offset of rtsp headers
5069 + *  OUT     phdrslen    set to length of rtsp headers
5070 + *  OUT     pcseqoff    set to offset of CSeq header
5071 + *  OUT     pcseqlen    set to length of CSeq header
5072 + */
5073 +static int
5074 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5075 +                   uint* phdrsoff, uint* phdrslen,
5076 +                   uint* pcseqoff, uint* pcseqlen)
5077 +{
5078 +    uint    entitylen = 0;
5079 +    uint    lineoff;
5080 +    uint    linelen;
5081 +
5082 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5083 +    {
5084 +        return 0;
5085 +    }
5086 +
5087 +    *phdrsoff = *ptcpoff;
5088 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5089 +    {
5090 +        if (linelen == 0)
5091 +        {
5092 +            if (entitylen > 0)
5093 +            {
5094 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5095 +            }
5096 +            break;
5097 +        }
5098 +        if (lineoff+linelen > tcplen)
5099 +        {
5100 +            INFOP("!! overrun !!\n");
5101 +            break;
5102 +        }
5103 +
5104 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5105 +        {
5106 +            *pcseqoff = lineoff;
5107 +            *pcseqlen = linelen;
5108 +        }
5109 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5110 +        {
5111 +            uint off = lineoff+15;
5112 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
5113 +            nf_strtou32(ptcp+off, &entitylen);
5114 +        }
5115 +    }
5116 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
5117 +
5118 +    return 1;
5119 +}
5120 +
5121 +/*
5122 + * Find lo/hi client ports (if any) in transport header
5123 + * In:
5124 + *   ptcp, tcplen = packet
5125 + *   tranoff, tranlen = buffer to search
5126 + *
5127 + * Out:
5128 + *   pport_lo, pport_hi = lo/hi ports (host endian)
5129 + *
5130 + * Returns nonzero if any client ports found
5131 + *
5132 + * Note: it is valid (and expected) for the client to request multiple
5133 + * transports, so we need to parse the entire line.
5134 + */
5135 +static int
5136 +rtsp_parse_transport(char* ptran, uint tranlen,
5137 +                     struct ip_ct_rtsp_expect* prtspexp)
5138 +{
5139 +    int     rc = 0;
5140 +    uint    off = 0;
5141 +
5142 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5143 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
5144 +    {
5145 +        INFOP("sanity check failed\n");
5146 +        return 0;
5147 +    }
5148 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5149 +    off += 10;
5150 +    SKIP_WSPACE(ptran, tranlen, off);
5151 +
5152 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
5153 +    while (off < tranlen)
5154 +    {
5155 +        const char* pparamend;
5156 +        uint        nextparamoff;
5157 +
5158 +        pparamend = memchr(ptran+off, ',', tranlen-off);
5159 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5160 +        nextparamoff = pparamend-ptran;
5161 +
5162 +        while (off < nextparamoff)
5163 +        {
5164 +            const char* pfieldend;
5165 +            uint        nextfieldoff;
5166 +
5167 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5168 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5169 +
5170 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
5171 +            {
5172 +                u_int16_t   port;
5173 +                uint        numlen;
5174 +
5175 +                off += 12;
5176 +                numlen = nf_strtou16(ptran+off, &port);
5177 +                off += numlen;
5178 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
5179 +                {
5180 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
5181 +                }
5182 +                else
5183 +                {
5184 +                    prtspexp->loport = prtspexp->hiport = port;
5185 +                    if (ptran[off] == '-')
5186 +                    {
5187 +                        off++;
5188 +                        numlen = nf_strtou16(ptran+off, &port);
5189 +                        off += numlen;
5190 +                        prtspexp->pbtype = pb_range;
5191 +                        prtspexp->hiport = port;
5192 +
5193 +                        // If we have a range, assume rtp:
5194 +                        // loport must be even, hiport must be loport+1
5195 +                        if ((prtspexp->loport & 0x0001) != 0 ||
5196 +                            prtspexp->hiport != prtspexp->loport+1)
5197 +                        {
5198 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
5199 +                                   prtspexp->loport, prtspexp->hiport);
5200 +                            prtspexp->loport &= 0xfffe;
5201 +                            prtspexp->hiport = prtspexp->loport+1;
5202 +                        }
5203 +                    }
5204 +                    else if (ptran[off] == '/')
5205 +                    {
5206 +                        off++;
5207 +                        numlen = nf_strtou16(ptran+off, &port);
5208 +                        off += numlen;
5209 +                        prtspexp->pbtype = pb_discon;
5210 +                        prtspexp->hiport = port;
5211 +                    }
5212 +                    rc = 1;
5213 +                }
5214 +            }
5215 +
5216 +            /*
5217 +             * Note we don't look for the destination parameter here.
5218 +             * If we are using NAT, the NAT module will handle it.  If not,
5219 +             * and the client is sending packets elsewhere, the expectation
5220 +             * will quietly time out.
5221 +             */
5222 +
5223 +            off = nextfieldoff;
5224 +        }
5225 +
5226 +        off = nextparamoff;
5227 +    }
5228 +
5229 +    return rc;
5230 +}
5231 +
5232 +/*** conntrack functions ***/
5233 +
5234 +/* outbound packet: client->server */
5235 +static int
5236 +help_out(const struct iphdr* iph, size_t pktlen,
5237 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5238 +{
5239 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
5240 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
5241 +    uint    tcplen = pktlen - iph->ihl * 4;
5242 +    char*   pdata = (char*)tcph + tcph->doff * 4;
5243 +    uint    datalen = tcplen - tcph->doff * 4;
5244 +    uint    dataoff = 0;
5245 +
5246 +    struct ip_conntrack_expect exp;
5247 +
5248 +    while (dataoff < datalen)
5249 +    {
5250 +        uint    cmdoff = dataoff;
5251 +        uint    hdrsoff = 0;
5252 +        uint    hdrslen = 0;
5253 +        uint    cseqoff = 0;
5254 +        uint    cseqlen = 0;
5255 +        uint    lineoff = 0;
5256 +        uint    linelen = 0;
5257 +        uint    off;
5258 +        int     rc;
5259 +
5260 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
5261 +                                &hdrsoff, &hdrslen,
5262 +                                &cseqoff, &cseqlen))
5263 +        {
5264 +            break;      /* not a valid message */
5265 +        }
5266 +
5267 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5268 +        {
5269 +            continue;   /* not a SETUP message */
5270 +        }
5271 +        DEBUGP("found a setup message\n");
5272 +
5273 +        memset(&exp, 0, sizeof(exp));
5274 +
5275 +        off = 0;
5276 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5277 +                                &lineoff, &linelen))
5278 +        {
5279 +            if (linelen == 0)
5280 +            {
5281 +                break;
5282 +            }
5283 +            if (off > hdrsoff+hdrslen)
5284 +            {
5285 +                INFOP("!! overrun !!");
5286 +                break;
5287 +            }
5288 +
5289 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5290 +            {
5291 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5292 +                                     &exp.help.exp_rtsp_info);
5293 +            }
5294 +        }
5295 +
5296 +        if (exp.help.exp_rtsp_info.loport == 0)
5297 +        {
5298 +            DEBUGP("no udp transports found\n");
5299 +            continue;   /* no udp transports found */
5300 +        }
5301 +
5302 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5303 +              (int)exp.help.exp_rtsp_info.pbtype,
5304 +              exp.help.exp_rtsp_info.loport,
5305 +              exp.help.exp_rtsp_info.hiport);
5306 +
5307 +        LOCK_BH(&ip_rtsp_lock);
5308 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5309 +        exp.help.exp_rtsp_info.len = hdrslen;
5310 +
5311 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5312 +        exp.mask.src.ip  = 0xffffffff;
5313 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5314 +        exp.mask.dst.ip  = 0xffffffff;
5315 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5316 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5317 +        exp.tuple.dst.protonum = IPPROTO_UDP;
5318 +        exp.mask.dst.protonum  = 0xffff;
5319 +
5320 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5321 +                NIPQUAD(exp.tuple.src.ip),
5322 +                ntohs(exp.tuple.src.u.tcp.port),
5323 +                NIPQUAD(exp.tuple.dst.ip),
5324 +                ntohs(exp.tuple.dst.u.tcp.port));
5325 +
5326 +        /* pass the request off to the nat helper */
5327 +        rc = ip_conntrack_expect_related(ct, &exp);
5328 +        UNLOCK_BH(&ip_rtsp_lock);
5329 +        if (rc == 0)
5330 +        {
5331 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
5332 +        }
5333 +        else
5334 +        {
5335 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5336 +        }
5337 +    }
5338 +
5339 +    return NF_ACCEPT;
5340 +}
5341 +
5342 +/* inbound packet: server->client */
5343 +static int
5344 +help_in(const struct iphdr* iph, size_t pktlen,
5345 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5346 +{
5347 +    return NF_ACCEPT;
5348 +}
5349 +
5350 +static int
5351 +help(const struct iphdr* iph, size_t pktlen,
5352 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5353 +{
5354 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5355 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5356 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
5357 +
5358 +    /* Until there's been traffic both ways, don't look in packets. */
5359 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5360 +    {
5361 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
5362 +        return NF_ACCEPT;
5363 +    }
5364 +
5365 +    /* Not whole TCP header? */
5366 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5367 +    {
5368 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5369 +        return NF_ACCEPT;
5370 +    }
5371 +
5372 +    /* Checksum invalid?  Ignore. */
5373 +    /* FIXME: Source route IP option packets --RR */
5374 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5375 +                     csum_partial((char*)tcph, tcplen, 0)))
5376 +    {
5377 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5378 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5379 +        return NF_ACCEPT;
5380 +    }
5381 +
5382 +    switch (CTINFO2DIR(ctinfo))
5383 +    {
5384 +    case IP_CT_DIR_ORIGINAL:
5385 +        help_out(iph, pktlen, ct, ctinfo);
5386 +        break;
5387 +    case IP_CT_DIR_REPLY:
5388 +        help_in(iph, pktlen, ct, ctinfo);
5389 +        break;
5390 +    }
5391 +
5392 +    return NF_ACCEPT;
5393 +}
5394 +
5395 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5396 +static char rtsp_names[MAX_PORTS][10];
5397 +
5398 +/* This function is intentionally _NOT_ defined as __exit */
5399 +static void
5400 +fini(void)
5401 +{
5402 +    int i;
5403 +    for (i = 0; i < num_ports; i++)
5404 +    {
5405 +        DEBUGP("unregistering port %d\n", ports[i]);
5406 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5407 +    }
5408 +}
5409 +
5410 +static int __init
5411 +init(void)
5412 +{
5413 +    int i, ret;
5414 +    struct ip_conntrack_helper *hlpr;
5415 +    char *tmpname;
5416 +
5417 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5418 +
5419 +    if (max_outstanding < 1)
5420 +    {
5421 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5422 +        return -EBUSY;
5423 +    }
5424 +    if (setup_timeout < 0)
5425 +    {
5426 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5427 +        return -EBUSY;
5428 +    }
5429 +
5430 +    /* If no port given, default to standard rtsp port */
5431 +    if (ports[0] == 0)
5432 +    {
5433 +        ports[0] = RTSP_PORT;
5434 +    }
5435 +
5436 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5437 +    {
5438 +        hlpr = &rtsp_helpers[i];
5439 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5440 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5441 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
5442 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
5443 +        hlpr->mask.dst.protonum = 0xFFFF;
5444 +        hlpr->max_expected = max_outstanding;
5445 +        hlpr->timeout = setup_timeout;
5446 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5447 +        hlpr->me = ip_conntrack_rtsp;
5448 +        hlpr->help = help;
5449 +
5450 +        tmpname = &rtsp_names[i][0];
5451 +        if (ports[i] == RTSP_PORT)
5452 +        {
5453 +            sprintf(tmpname, "rtsp");
5454 +        }
5455 +        else
5456 +        {
5457 +            sprintf(tmpname, "rtsp-%d", i);
5458 +        }
5459 +        hlpr->name = tmpname;
5460 +
5461 +        DEBUGP("port #%d: %d\n", i, ports[i]);
5462 +
5463 +        ret = ip_conntrack_helper_register(hlpr);
5464 +
5465 +        if (ret)
5466 +        {
5467 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5468 +            fini();
5469 +            return -EBUSY;
5470 +        }
5471 +        num_ports++;
5472 +    }
5473 +    return 0;
5474 +}
5475 +
5476 +#ifdef CONFIG_IP_NF_NAT_NEEDED
5477 +EXPORT_SYMBOL(ip_rtsp_lock);
5478 +#endif
5479 +
5480 +module_init(init);
5481 +module_exit(fini);
5482 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
5483 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-04-28 03:35:45.000000000 +0200
5484 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-04-29 11:18:04.000000000 +0200
5485 @@ -110,6 +110,9 @@
5486                 len += sprintf(buffer + len, "[ASSURED] ");
5487         len += sprintf(buffer + len, "use=%u ",
5488                        atomic_read(&conntrack->ct_general.use));
5489 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5490 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5491 +#endif
5492         len += sprintf(buffer + len, "\n");
5493  
5494         return len;
5495 @@ -633,6 +636,7 @@
5496  EXPORT_SYMBOL(ip_conntrack_alter_reply);
5497  EXPORT_SYMBOL(ip_conntrack_destroyed);
5498  EXPORT_SYMBOL(ip_conntrack_get);
5499 +EXPORT_SYMBOL(__ip_conntrack_confirm);
5500  EXPORT_SYMBOL(need_ip_conntrack);
5501  EXPORT_SYMBOL(ip_conntrack_helper_register);
5502  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5503 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
5504 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c  1970-01-01 01:00:00.000000000 +0100
5505 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c      2004-04-29 11:21:43.000000000 +0200
5506 @@ -0,0 +1,360 @@
5507 +/* 
5508 + * talk extension for IP connection tracking. 
5509 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5510 + *
5511 + *      This program is free software; you can redistribute it and/or
5512 + *      modify it under the terms of the GNU General Public License
5513 + *      as published by the Free Software Foundation; either version
5514 + *      2 of the License, or (at your option) any later version.
5515 + **
5516 + *     Module load syntax:
5517 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5518 + *
5519 + *             talk=[0|1]      disable|enable old talk support
5520 + *            ntalk=[0|1]      disable|enable ntalk support
5521 + *           ntalk2=[0|1]      disable|enable ntalk2 support
5522 + *
5523 + *     The default is talk=1 ntalk=1 ntalk2=1
5524 + *
5525 + *     The helper does not support simultaneous talk requests.
5526 + **
5527 + *
5528 + *             ASCII art on talk protocols
5529 + *     
5530 + *     
5531 + *     caller server               callee server
5532 + *             |     \           /
5533 + *             |       \       /
5534 + *             |         \   /
5535 + *             |           /  
5536 + *             |         /   \
5537 + *           2 |     1 /       \ 3
5538 + *     caller client  ----------- callee client
5539 + *                              4
5540 + *
5541 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
5542 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5543 + *     3. callee client <-> caller server: LOOK_UP invitation
5544 + *     4. callee client <-> caller client: talk data channel
5545 + *
5546 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
5547 + *      draft-hunter-talk-00.txt
5548 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
5549 + */
5550 +#include <linux/config.h>
5551 +#include <linux/module.h>
5552 +#include <linux/netfilter.h>
5553 +#include <linux/ip.h>
5554 +#include <net/checksum.h>
5555 +#include <net/udp.h>
5556 +
5557 +#include <linux/netfilter_ipv4/lockhelp.h>
5558 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5559 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5560 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5561 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5562 +
5563 +/* Default all talk protocols are supported */
5564 +static int talk = 1;
5565 +static int ntalk = 1;
5566 +static int ntalk2 = 1;
5567 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5568 +MODULE_DESCRIPTION("talk connection tracking module");
5569 +MODULE_LICENSE("GPL");
5570 +#ifdef MODULE_PARM
5571 +MODULE_PARM(talk, "i");
5572 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5573 +MODULE_PARM(ntalk, "i");
5574 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5575 +MODULE_PARM(ntalk2, "i");
5576 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5577 +#endif
5578 +
5579 +DECLARE_LOCK(ip_talk_lock);
5580 +struct module *ip_conntrack_talk = THIS_MODULE;
5581 +
5582 +#if 0
5583 +#define DEBUGP printk
5584 +#else
5585 +#define DEBUGP(format, args...)
5586 +#endif
5587 +
5588 +static int talk_expect(struct ip_conntrack *ct);
5589 +static int ntalk_expect(struct ip_conntrack *ct);
5590 +
5591 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
5592 +
5593 +static int talk_help_response(const struct iphdr *iph, size_t len,
5594 +                             struct ip_conntrack *ct,
5595 +                             enum ip_conntrack_info ctinfo,
5596 +                             int talk_port,
5597 +                             u_char mode,
5598 +                             u_char type,
5599 +                             u_char answer,
5600 +                             struct talk_addr *addr)
5601 +{
5602 +       int dir = CTINFO2DIR(ctinfo);
5603 +       struct ip_conntrack_expect expect, *exp = &expect;
5604 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
5605 +
5606 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
5607 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5608 +               type, answer);
5609 +
5610 +       if (!(answer == SUCCESS && type == mode))
5611 +               return NF_ACCEPT;
5612 +       
5613 +       memset(&expect, 0, sizeof(expect));
5614 +       
5615 +       if (type == ANNOUNCE) {
5616 +
5617 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
5618 +
5619 +               /* update the talk info */
5620 +               LOCK_BH(&ip_talk_lock);
5621 +               exp_talk_info->port = htons(talk_port);
5622 +
5623 +               /* expect callee client -> caller server message */
5624 +               exp->tuple = ((struct ip_conntrack_tuple)
5625 +                       { { ct->tuplehash[dir].tuple.src.ip,
5626 +                           { 0 } },
5627 +                         { ct->tuplehash[dir].tuple.dst.ip,
5628 +                           { .tcp = { htons(talk_port) } },
5629 +                           IPPROTO_UDP }});
5630 +               exp->mask = ((struct ip_conntrack_tuple)
5631 +                       { { 0xFFFFFFFF, { 0 } },
5632 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
5633 +               
5634 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
5635 +
5636 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
5637 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
5638 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
5639 +
5640 +               /* Ignore failure; should only happen with NAT */
5641 +               ip_conntrack_expect_related(ct, &expect);
5642 +               UNLOCK_BH(&ip_talk_lock);
5643 +       }
5644 +       if (type == LOOK_UP) {
5645 +
5646 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
5647 +
5648 +               /* update the talk info */
5649 +               LOCK_BH(&ip_talk_lock);
5650 +               exp_talk_info->port = addr->ta_port;
5651 +
5652 +               /* expect callee client -> caller client connection */
5653 +               exp->tuple = ((struct ip_conntrack_tuple)
5654 +                       { { ct->tuplehash[!dir].tuple.src.ip,
5655 +                           { 0 } },
5656 +                         { addr->ta_addr,
5657 +                           { addr->ta_port },
5658 +                           IPPROTO_TCP }});
5659 +               exp->mask = ((struct ip_conntrack_tuple)
5660 +                       { { 0xFFFFFFFF, { 0 } },
5661 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5662 +               
5663 +               exp->expectfn = NULL;
5664 +               
5665 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
5666 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
5667 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
5668 +
5669 +               /* Ignore failure; should only happen with NAT */
5670 +               ip_conntrack_expect_related(ct, &expect);
5671 +               UNLOCK_BH(&ip_talk_lock);
5672 +       }
5673 +                   
5674 +       return NF_ACCEPT;
5675 +}
5676 +
5677 +/* FIXME: This should be in userspace.  Later. */
5678 +static int talk_help(const struct iphdr *iph, size_t len,
5679 +                    struct ip_conntrack *ct,
5680 +                    enum ip_conntrack_info ctinfo,
5681 +                    int talk_port,
5682 +                    u_char mode)
5683 +{
5684 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5685 +       const char *data = (const char *)udph + sizeof(struct udphdr);
5686 +       int dir = CTINFO2DIR(ctinfo);
5687 +       size_t udplen;
5688 +
5689 +       DEBUGP("ip_ct_talk_help: help entered\n");
5690 +
5691 +       /* Until there's been traffic both ways, don't look in packets. */
5692 +       if (ctinfo != IP_CT_ESTABLISHED
5693 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5694 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
5695 +               return NF_ACCEPT;
5696 +       }
5697 +
5698 +       /* Not whole UDP header? */
5699 +       udplen = len - iph->ihl * 4;
5700 +       if (udplen < sizeof(struct udphdr)) {
5701 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
5702 +               return NF_ACCEPT;
5703 +       }
5704 +
5705 +       /* Checksum invalid?  Ignore. */
5706 +       /* FIXME: Source route IP option packets --RR */
5707 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5708 +                             csum_partial((char *)udph, udplen, 0))) {
5709 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5710 +                      udph, udplen, NIPQUAD(iph->saddr),
5711 +                      NIPQUAD(iph->daddr));
5712 +               return NF_ACCEPT;
5713 +       }
5714 +       
5715 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5716 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
5717 +
5718 +       if (dir == IP_CT_DIR_ORIGINAL)
5719 +               return NF_ACCEPT;
5720 +               
5721 +       if (talk_port == TALK_PORT
5722 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
5723 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5724 +                                         ((struct talk_response *)data)->type, 
5725 +                                         ((struct talk_response *)data)->answer,
5726 +                                         &(((struct talk_response *)data)->addr));
5727 +       else if (talk_port == NTALK_PORT
5728 +                 && ntalk
5729 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5730 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5731 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5732 +                                         ((struct ntalk_response *)data)->type, 
5733 +                                         ((struct ntalk_response *)data)->answer,
5734 +                                         &(((struct ntalk_response *)data)->addr));
5735 +       else if (talk_port == NTALK_PORT
5736 +                && ntalk2
5737 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5738 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5739 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5740 +                                         ((struct ntalk2_response *)data)->type, 
5741 +                                         ((struct ntalk2_response *)data)->answer,
5742 +                                         &(((struct ntalk2_response *)data)->addr));
5743 +       else {
5744 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
5745 +                      (unsigned)udplen - sizeof(struct udphdr), 
5746 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5747 +               return NF_ACCEPT;
5748 +       }
5749 +}
5750 +
5751 +static int lookup_help(const struct iphdr *iph, size_t len,
5752 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5753 +{
5754 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5755 +}
5756 +
5757 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
5758 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5759 +{
5760 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5761 +}
5762 +
5763 +static struct ip_conntrack_helper lookup_helpers[2] = 
5764 +       { { { NULL, NULL },
5765 +           "talk",                                     /* name */
5766 +           0,                                          /* flags */
5767 +           NULL,                                       /* module */
5768 +           1,                                          /* max_expected */
5769 +           240,                                        /* timeout */
5770 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
5771 +             { 0, { 0 }, IPPROTO_UDP } },
5772 +           { { 0, { 0xFFFF } },                        /* mask */
5773 +             { 0, { 0 }, 0xFFFF } },
5774 +           lookup_help },                              /* helper */
5775 +          { { NULL, NULL },
5776 +            "ntalk",                                   /* name */
5777 +           0,                                          /* flags */
5778 +           NULL,                                       /* module */
5779 +           1,                                          /* max_expected */
5780 +           240,                                        /* timeout */
5781 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
5782 +             { 0, { 0 }, IPPROTO_UDP } },
5783 +           { { 0, { 0xFFFF } },                        /* mask */
5784 +             { 0, { 0 }, 0xFFFF } },
5785 +           lookup_nhelp }                              /* helper */
5786 +        };
5787 +
5788 +static int talk_expect(struct ip_conntrack *ct)
5789 +{
5790 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5791 +       WRITE_LOCK(&ip_conntrack_lock);
5792 +       ct->helper = &lookup_helpers[0];
5793 +       WRITE_UNLOCK(&ip_conntrack_lock);
5794 +        
5795 +       return NF_ACCEPT;       /* unused */
5796 +}
5797 +
5798 +static int ntalk_expect(struct ip_conntrack *ct)
5799 +{
5800 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5801 +       WRITE_LOCK(&ip_conntrack_lock);
5802 +       ct->helper = &lookup_helpers[1];
5803 +       WRITE_UNLOCK(&ip_conntrack_lock);
5804 +        
5805 +       return NF_ACCEPT;       /* unused */
5806 +}
5807 +
5808 +static int help(const struct iphdr *iph, size_t len,
5809 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5810 +{
5811 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5812 +}
5813 +
5814 +static int nhelp(const struct iphdr *iph, size_t len,
5815 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5816 +{
5817 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5818 +}
5819 +
5820 +static struct ip_conntrack_helper talk_helpers[2] = 
5821 +       { { { NULL, NULL },
5822 +           "talk",                                     /* name */
5823 +           0,                                          /* flags */
5824 +           THIS_MODULE,                                /* module */
5825 +           1,                                          /* max_expected */
5826 +           240,                                        /* timeout */
5827 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
5828 +             { 0, { 0 }, IPPROTO_UDP } },
5829 +           { { 0, { 0xFFFF } },                        /* mask */
5830 +             { 0, { 0 }, 0xFFFF } },
5831 +           help },                                     /* helper */
5832 +          { { NULL, NULL },
5833 +           "ntalk",                                    /* name */
5834 +           0,                                          /* flags */
5835 +           THIS_MODULE,                                /* module */
5836 +           1,                                          /* max_expected */
5837 +           240,                                        /* timeout */
5838 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
5839 +             { 0, { 0 }, IPPROTO_UDP } },
5840 +           { { 0, { 0xFFFF } },                        /* mask */
5841 +             { 0, { 0 }, 0xFFFF } },
5842 +           nhelp }                                     /* helper */
5843 +       };
5844 +
5845 +static int __init init(void)
5846 +{
5847 +       if (talk > 0)
5848 +               ip_conntrack_helper_register(&talk_helpers[0]);
5849 +       if (ntalk > 0 || ntalk2 > 0)
5850 +               ip_conntrack_helper_register(&talk_helpers[1]);
5851 +               
5852 +       return 0;
5853 +}
5854 +
5855 +static void __exit fini(void)
5856 +{
5857 +       if (talk > 0)
5858 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
5859 +       if (ntalk > 0 || ntalk2 > 0)
5860 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
5861 +}
5862 +
5863 +EXPORT_SYMBOL(ip_talk_lock);
5864 +
5865 +module_init(init);
5866 +module_exit(fini);
5867 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c
5868 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_cuseeme.c     1970-01-01 01:00:00.000000000 +0100
5869 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_cuseeme.c 2004-04-29 11:17:55.000000000 +0200
5870 @@ -0,0 +1,289 @@
5871 +/* CuSeeMe extension for UDP NAT alteration.
5872 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5873 + * based on ip_masq_cuseeme.c in 2.2 kernels
5874 + *
5875 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
5876 + *
5877 + *      This program is free software; you can redistribute it and/or
5878 + *      modify it under the terms of the GNU General Public License
5879 + *      as published by the Free Software Foundation; either version
5880 + *      2 of the License, or (at your option) any later version.
5881 + *
5882 + *      Module load syntax:
5883 + *      insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
5884 + *
5885 + *      Please give the ports of the CuSeeMe traffic you want to track.
5886 + *      If you don't specify ports, the default will be UDP port 7648.
5887 + *
5888 + *      CuSeeMe Protocol Documentation:
5889 + *      http://cu-seeme.net/squeek/tech/contents.html
5890 + *
5891 + */
5892 +
5893 +#include <linux/module.h>
5894 +#include <linux/netfilter_ipv4.h>
5895 +#include <linux/ip.h>
5896 +#include <linux/udp.h>
5897 +
5898 +#include <linux/netfilter.h>
5899 +#include <linux/netfilter_ipv4/ip_tables.h>
5900 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5901 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
5902 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5903 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5904 +
5905 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5906 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
5907 +MODULE_LICENSE("GPL");
5908 +
5909 +#define MAX_PORTS 8
5910 +
5911 +static int ports[MAX_PORTS];
5912 +static int ports_c = 0;
5913 +#ifdef MODULE_PARM
5914 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
5915 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
5916 +#endif
5917 +
5918 +#if 0
5919 +#define DEBUGP printk
5920 +#else
5921 +#define DEBUGP(format, args...)
5922 +#endif
5923 +
5924 +/* process packet from client->reflector, possibly manipulate client IP in payload */
5925 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
5926 +                             struct ip_nat_info *info,
5927 +                             enum ip_conntrack_info ctinfo,
5928 +                             struct sk_buff **pskb,
5929 +                             char *data,
5930 +                             unsigned int datalen)
5931 +{
5932 +       char new_port_ip[6];
5933 +       struct cu_header *cu_head=(struct cu_header *)data;
5934 +       
5935 +       DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n", 
5936 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5937 +               
5938 +       /* At least check that the data at offset 10 is the client's port and IP address */
5939 +       if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
5940 +           (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
5941 +               DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n", 
5942 +                      NIPQUAD(cu_head->addr),
5943 +                      ntohs(cu_head->port),
5944 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5945 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
5946 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
5947 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
5948 +               /* at offset 10, replace 6 bytes containing port + IP address */
5949 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5950 +                                        10, 6, (char *)(new_port_ip), 6);
5951 +       } else 
5952 +               DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5953 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5954 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
5955 +                      NIPQUAD(cu_head->addr),
5956 +                      ntohs(cu_head->port));
5957 +}
5958 +
5959 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
5960 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
5961 +                             struct ip_nat_info *info,
5962 +                             enum ip_conntrack_info ctinfo,
5963 +                             struct sk_buff **pskb,
5964 +                             char *data,
5965 +                             unsigned int datalen)
5966 +{
5967 +       char new_port_ip[6];
5968 +       struct cu_header *cu_head = (struct cu_header *)data;
5969 +       struct oc_header *oc_head = (struct oc_header *)data; 
5970 +       struct client_info *ci; 
5971 +       int i, off;
5972 +
5973 +       
5974 +       DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n", 
5975 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
5976 +               
5977 +       /* Check if we're really dealing with the client's port + IP address before rewriting */
5978 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
5979 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
5980 +               DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
5981 +                      NIPQUAD(cu_head->dest_addr),
5982 +                      ntohs(cu_head->dest_port),
5983 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5984 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
5985 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
5986 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
5987 +               /* at offset 2, replace 6 bytes containing port + IP address */
5988 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
5989 +                                        2, 6, (char *)(new_port_ip), 6);
5990 +       } else 
5991 +               DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
5992 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
5993 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
5994 +                      NIPQUAD(cu_head->dest_addr),
5995 +                      ntohs(cu_head->dest_port));
5996 +       
5997 +       /* Check if we're really dealing with the server's port + IP address before rewriting. 
5998 +          In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
5999 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
6000 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
6001 +               DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
6002 +                      NIPQUAD(cu_head->addr),
6003 +                      ntohs(cu_head->port),
6004 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
6005 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
6006 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
6007 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6008 +               /* at offset 10, replace 6 bytes containing port + IP address */
6009 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
6010 +                                        10, 6, (char *)(new_port_ip), 6);
6011 +       } else 
6012 +               /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
6013 +                  is not that important so we're not logging this unless we're debugging */
6014 +               DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
6015 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
6016 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
6017 +                      NIPQUAD(cu_head->addr),
6018 +                      ntohs(cu_head->port));
6019 +       
6020 +       /* Spin through client_info structs until we find our own */
6021 +       if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
6022 +               DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
6023 +               for(i=0, off=sizeof(struct oc_header);
6024 +                   (i < oc_head->client_count && 
6025 +                   off+sizeof(struct client_info) <= datalen); 
6026 +                   i++) {
6027 +                       ci=(struct client_info *)(data+off);
6028 +                       DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n", 
6029 +                              NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
6030 +                              (unsigned int)((void *)&(ci->address) - (void *)cu_head));
6031 +                       if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
6032 +                               /* mangle this IP address */
6033 +                               DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
6034 +                                      NIPQUAD(ci->address), 
6035 +                                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
6036 +                                      (unsigned int)((void *)&(ci->address) - (void *)cu_head));
6037 +                               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
6038 +                                                        (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4, 
6039 +                                                        (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
6040 +                               break;
6041 +                       } else 
6042 +                               off+=sizeof(struct client_info);
6043 +               }
6044 +       } else
6045 +               DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n", 
6046 +                      ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
6047 +}
6048 +
6049 +static unsigned int 
6050 +cuseeme_nat_help(struct ip_conntrack *ct,
6051 +                 struct ip_conntrack_expect *exp,
6052 +                 struct ip_nat_info *info,
6053 +                 enum ip_conntrack_info ctinfo,
6054 +                 unsigned int hooknum,
6055 +                 struct sk_buff **pskb)
6056 +{
6057 +       struct iphdr *iph = (*pskb)->nh.iph;
6058 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
6059 +       int dir = CTINFO2DIR(ctinfo);
6060 +       unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
6061 +       char *data = (char *) &udph[1];
6062 +       
6063 +       DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
6064 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6065 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6066 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6067 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6068 +             );
6069 +       
6070 +       /* Only mangle things once: original direction in POST_ROUTING
6071 +          and reply direction on PRE_ROUTING. */
6072 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6073 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6074 +               DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
6075 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6076 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6077 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6078 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6079 +               return NF_ACCEPT;
6080 +       }
6081 +       
6082 +       if(datalen < sizeof(struct cu_header)) {
6083 +               /* packet too small */
6084 +               if (net_ratelimit())
6085 +                       printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n", 
6086 +                              datalen, sizeof(struct cu_header));
6087 +               return NF_ACCEPT;
6088 +       }
6089 +
6090 +
6091 +       /* In the debugging output, "outgoing" is from client to server, and
6092 +          "incoming" is from server to client */
6093 +       if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) 
6094 +               cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
6095 +       else 
6096 +               cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
6097 +
6098 +       return NF_ACCEPT;
6099 +}
6100 +
6101 +static struct ip_nat_helper cuseeme[MAX_PORTS];
6102 +static char cuseeme_names[MAX_PORTS][14];  /* cuseeme-65535 */
6103 +
6104 +static void fini(void)
6105 +{
6106 +       int i;
6107 +       
6108 +       for (i = 0 ; i < ports_c; i++) {
6109 +               DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
6110 +                      ip_nat_helper_unregister(&cuseeme[i]);
6111 +       }
6112 +}
6113 +
6114 +static int __init init(void)
6115 +{
6116 +       int i, ret = 0;
6117 +       char *tmpname;
6118 +
6119 +       if (!ports[0])
6120 +               ports[0] = CUSEEME_PORT;
6121 +               
6122 +       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6123 +               memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
6124 +
6125 +               cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
6126 +               cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
6127 +               cuseeme[i].mask.dst.protonum = 0xFFFF;
6128 +               cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
6129 +               cuseeme[i].help = cuseeme_nat_help;
6130 +               cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE + 
6131 +                                  IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
6132 +                                                             is stricly needed... */
6133 +               cuseeme[i].me = THIS_MODULE;
6134 +               cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
6135 +                       
6136 +               tmpname = &cuseeme_names[i][0];
6137 +               if (ports[i] == CUSEEME_PORT)
6138 +                       sprintf(tmpname, "cuseeme");
6139 +               else
6140 +                       sprintf(tmpname, "cuseeme-%d", ports[i]);
6141 +               cuseeme[i].name = tmpname;
6142 +                       
6143 +               DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
6144 +                      ports[i], cuseeme[i].name);
6145 +               ret = ip_nat_helper_register(&cuseeme[i]);
6146 +                       
6147 +               if (ret) {
6148 +                       printk("ip_nat_cuseeme: unable to register helper for port %d\n",
6149 +                              ports[i]);
6150 +                       fini();
6151 +                       return ret;
6152 +               }
6153 +               ports_c++;
6154 +       }
6155 +       return ret;
6156 +}
6157 +       
6158 +module_init(init);
6159 +module_exit(fini);
6160 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c
6161 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c        1970-01-01 01:00:00.000000000 +0100
6162 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c    2004-04-29 11:18:00.000000000 +0200
6163 @@ -0,0 +1,419 @@
6164 +/* 
6165 + * H.323 'brute force' extension for NAT alteration. 
6166 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6167 + *
6168 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6169 + * (http://www.coritel.it/projects/sofia/nat.html)
6170 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6171 + * the unregistered helpers to the conntrack entries.
6172 + */
6173 +
6174 +
6175 +#include <linux/module.h>
6176 +#include <linux/netfilter.h>
6177 +#include <linux/ip.h>
6178 +#include <net/checksum.h>
6179 +#include <net/tcp.h>
6180 +
6181 +#include <linux/netfilter_ipv4/lockhelp.h>
6182 +#include <linux/netfilter_ipv4/ip_nat.h>
6183 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6184 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6185 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6186 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6187 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6188 +
6189 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6190 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6191 +MODULE_LICENSE("GPL");
6192 +
6193 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6194 +struct module *ip_nat_h323 = THIS_MODULE;
6195 +
6196 +#if 0
6197 +#define DEBUGP printk
6198 +#else
6199 +#define DEBUGP(format, args...)
6200 +#endif
6201 +
6202 +/* FIXME: Time out? --RR */
6203 +
6204 +static unsigned int 
6205 +h225_nat_expected(struct sk_buff **pskb,
6206 +                 unsigned int hooknum,
6207 +                 struct ip_conntrack *ct,
6208 +                 struct ip_nat_info *info);
6209 +
6210 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6211 +                                 struct ip_conntrack_expect *exp,
6212 +                                 struct ip_nat_info *info,
6213 +                                 enum ip_conntrack_info ctinfo,
6214 +                                 unsigned int hooknum,
6215 +                                 struct sk_buff **pskb);
6216 +                 
6217 +static struct ip_nat_helper h245 = 
6218 +       { { NULL, NULL },
6219 +          "H.245",                             /* name */
6220 +         0,                                    /* flags */
6221 +         NULL,                                 /* module */
6222 +         { { 0, { 0 } },                       /* tuple */
6223 +           { 0, { 0 }, IPPROTO_TCP } },
6224 +         { { 0, { 0xFFFF } },                  /* mask */
6225 +           { 0, { 0 }, 0xFFFF } },
6226 +         h225_nat_help,                        /* helper */
6227 +         h225_nat_expected                     /* expectfn */
6228 +       };
6229 +
6230 +static unsigned int
6231 +h225_nat_expected(struct sk_buff **pskb,
6232 +                 unsigned int hooknum,
6233 +                 struct ip_conntrack *ct,
6234 +                 struct ip_nat_info *info)
6235 +{
6236 +       struct ip_nat_multi_range mr;
6237 +       u_int32_t newdstip, newsrcip, newip;
6238 +       u_int16_t port;
6239 +       struct ip_ct_h225_expect *exp_info;
6240 +       struct ip_ct_h225_master *master_info;
6241 +       struct ip_conntrack *master = master_ct(ct);
6242 +       unsigned int is_h225, ret;
6243 +       
6244 +       IP_NF_ASSERT(info);
6245 +       IP_NF_ASSERT(master);
6246 +
6247 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6248 +
6249 +       DEBUGP("h225_nat_expected: We have a connection!\n");
6250 +       master_info = &ct->master->expectant->help.ct_h225_info;
6251 +       exp_info = &ct->master->help.exp_h225_info;
6252 +
6253 +       LOCK_BH(&ip_h323_lock);
6254 +
6255 +       DEBUGP("master: ");
6256 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6257 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6258 +       DEBUGP("conntrack: ");
6259 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6260 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6261 +               /* Make connection go to the client. */
6262 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6263 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6264 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6265 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6266 +       } else {
6267 +               /* Make the connection go to the server */
6268 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6269 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6270 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6271 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6272 +       }
6273 +       port = exp_info->port;
6274 +       is_h225 = master_info->is_h225 == H225_PORT;
6275 +       UNLOCK_BH(&ip_h323_lock);
6276 +       
6277 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6278 +               newip = newsrcip;
6279 +       else
6280 +               newip = newdstip;
6281 +
6282 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6283 +
6284 +       mr.rangesize = 1;
6285 +       /* We don't want to manip the per-protocol, just the IPs... */
6286 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6287 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6288 +
6289 +       /* ... unless we're doing a MANIP_DST, in which case, make
6290 +          sure we map to the correct port */
6291 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6292 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6293 +               mr.range[0].min = mr.range[0].max
6294 +                       = ((union ip_conntrack_manip_proto)
6295 +                               { .tcp = { port } });
6296 +       }
6297 +
6298 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
6299 +       
6300 +       if (is_h225) {
6301 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6302 +               /* NAT expectfn called with ip_nat_lock write-locked */
6303 +               info->helper = &h245;
6304 +       }
6305 +       return ret;
6306 +}
6307 +
6308 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6309 +                                    struct sk_buff **pskb,
6310 +                                    enum ip_conntrack_info ctinfo)
6311 +{
6312 +       struct iphdr *iph = (*pskb)->nh.iph;
6313 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6314 +       char *data = (char *) tcph + tcph->doff * 4;
6315 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6316 +       u_int32_t datalen = tcplen - tcph->doff*4;
6317 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
6318 +       u_int32_t newip;
6319 +       u_int16_t port;
6320 +       int i;
6321 +
6322 +       MUST_BE_LOCKED(&ip_h323_lock);
6323 +
6324 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
6325 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6326 +                       ? "yes" : "no",
6327 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6328 +                       ? "yes" : "no");
6329 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6330 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6331 +               return 1;
6332 +
6333 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
6334 +               info->offset[IP_CT_DIR_ORIGINAL], 
6335 +               info->offset[IP_CT_DIR_REPLY],
6336 +               tcplen);
6337 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6338 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6339 +
6340 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
6341 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
6342 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6343 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6344 +               if (!between(info->seq[i], ntohl(tcph->seq), 
6345 +                            ntohl(tcph->seq) + datalen))
6346 +                       continue;
6347 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6348 +                            ntohl(tcph->seq) + datalen)) {
6349 +                       /* Partial retransmisison. It's a cracker being funky. */
6350 +                       if (net_ratelimit()) {
6351 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6352 +                                    info->seq[i],
6353 +                                    ntohl(tcph->seq),
6354 +                                    ntohl(tcph->seq) + datalen);
6355 +                       }
6356 +                       return 0;
6357 +               }
6358 +
6359 +               /* Change address inside packet to match way we're mapping
6360 +                  this connection. */
6361 +               if (i == IP_CT_DIR_ORIGINAL) {
6362 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6363 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6364 +               } else {
6365 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
6366 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6367 +               }
6368 +
6369 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
6370 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6371 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6372 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6373 +
6374 +               /* Modify the packet */
6375 +               *(u_int32_t *)(data + info->offset[i]) = newip;
6376 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
6377 +       
6378 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
6379 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6380 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6381 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6382 +       }
6383 +
6384 +       /* fix checksum information */
6385 +
6386 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6387 +                                    datalen, 0);
6388 +
6389 +       tcph->check = 0;
6390 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6391 +                                  csum_partial((char *)tcph, tcph->doff*4,
6392 +                                          (*pskb)->csum));
6393 +       ip_send_check(iph);
6394 +
6395 +       return 1;
6396 +}
6397 +
6398 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6399 +                          struct ip_conntrack *ct,
6400 +                          struct sk_buff **pskb,
6401 +                          enum ip_conntrack_info ctinfo,
6402 +                          struct ip_conntrack_expect *expect)
6403 +{
6404 +       u_int32_t newip;
6405 +       u_int16_t port;
6406 +       struct ip_conntrack_tuple newtuple;
6407 +       struct iphdr *iph = (*pskb)->nh.iph;
6408 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6409 +       char *data = (char *) tcph + tcph->doff * 4;
6410 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6411 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6412 +       int is_h225;
6413 +
6414 +       MUST_BE_LOCKED(&ip_h323_lock);
6415 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6416 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6417 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6418 +
6419 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
6420 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6421 +               /* Partial retransmisison. It's a cracker being funky. */
6422 +               if (net_ratelimit()) {
6423 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6424 +                            expect->seq,
6425 +                            ntohl(tcph->seq),
6426 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6427 +               }
6428 +               return 0;
6429 +       }
6430 +
6431 +       /* Change address inside packet to match way we're mapping
6432 +          this connection. */
6433 +       if (info->dir == IP_CT_DIR_REPLY) {
6434 +               /* Must be where client thinks server is */
6435 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6436 +               /* Expect something from client->server */
6437 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6438 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6439 +       } else {
6440 +               /* Must be where server thinks client is */
6441 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6442 +               /* Expect something from server->client */
6443 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6444 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6445 +       }
6446 +
6447 +       is_h225 = (master_info->is_h225 == H225_PORT);
6448 +
6449 +       if (is_h225) {
6450 +               newtuple.dst.protonum = IPPROTO_TCP;
6451 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6452 +       } else {
6453 +               newtuple.dst.protonum = IPPROTO_UDP;
6454 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6455 +       }
6456 +       
6457 +       /* Try to get same port: if not, try to change it. */
6458 +       for (port = ntohs(info->port); port != 0; port++) {
6459 +               if (is_h225)
6460 +                       newtuple.dst.u.tcp.port = htons(port);
6461 +               else
6462 +                       newtuple.dst.u.udp.port = htons(port);
6463 +
6464 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6465 +                       break;
6466 +       }
6467 +       if (port == 0) {
6468 +               DEBUGP("h323_data_fixup: no free port found!\n");
6469 +               return 0;
6470 +       }
6471 +
6472 +       port = htons(port);
6473 +
6474 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
6475 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6476 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6477 +
6478 +       /* Modify the packet */
6479 +       *(u_int32_t *)(data + info->offset) = newip;
6480 +       *(u_int16_t *)(data + info->offset + 4) = port;
6481 +       
6482 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
6483 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6484 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6485 +
6486 +       /* fix checksum information  */
6487 +       /* FIXME: usually repeated multiple times in the case of H.245! */
6488 +
6489 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6490 +                                    tcplen - tcph->doff*4, 0);
6491 +
6492 +       tcph->check = 0;
6493 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6494 +                                  csum_partial((char *)tcph, tcph->doff*4,
6495 +                                          (*pskb)->csum));
6496 +       ip_send_check(iph);
6497 +
6498 +       return 1;
6499 +}
6500 +
6501 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6502 +                                 struct ip_conntrack_expect *exp,
6503 +                                 struct ip_nat_info *info,
6504 +                                 enum ip_conntrack_info ctinfo,
6505 +                                 unsigned int hooknum,
6506 +                                 struct sk_buff **pskb)
6507 +{
6508 +       int dir;
6509 +       struct ip_ct_h225_expect *exp_info;
6510 +       
6511 +       /* Only mangle things once: original direction in POST_ROUTING
6512 +          and reply direction on PRE_ROUTING. */
6513 +       dir = CTINFO2DIR(ctinfo);
6514 +       DEBUGP("nat_h323: dir %s at hook %s\n",
6515 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6516 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6517 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6518 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6519 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6520 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6521 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6522 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6523 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6524 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6525 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6526 +               return NF_ACCEPT;
6527 +       }
6528 +
6529 +       if (!exp) {
6530 +               LOCK_BH(&ip_h323_lock);
6531 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6532 +                       UNLOCK_BH(&ip_h323_lock);
6533 +                       return NF_DROP;
6534 +               }
6535 +               UNLOCK_BH(&ip_h323_lock);
6536 +               return NF_ACCEPT;
6537 +       }
6538 +               
6539 +       exp_info = &exp->help.exp_h225_info;
6540 +
6541 +       LOCK_BH(&ip_h323_lock);
6542 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6543 +               UNLOCK_BH(&ip_h323_lock);
6544 +               return NF_DROP;
6545 +       }
6546 +       UNLOCK_BH(&ip_h323_lock);
6547 +
6548 +       return NF_ACCEPT;
6549 +}
6550 +
6551 +static struct ip_nat_helper h225 = 
6552 +       { { NULL, NULL },
6553 +         "H.225",                                      /* name */
6554 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
6555 +         THIS_MODULE,                                  /* module */
6556 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
6557 +           { 0, { 0 }, IPPROTO_TCP } },
6558 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
6559 +           { 0, { 0 }, 0xFFFF } },
6560 +         h225_nat_help,                                /* helper */
6561 +         h225_nat_expected                             /* expectfn */
6562 +       };
6563 +
6564 +static int __init init(void)
6565 +{
6566 +       int ret;
6567 +       
6568 +       ret = ip_nat_helper_register(&h225);
6569 +
6570 +       if (ret != 0)
6571 +               printk("ip_nat_h323: cannot initialize the module!\n");
6572 +
6573 +       return ret;
6574 +}
6575 +
6576 +static void __exit fini(void)
6577 +{
6578 +       ip_nat_helper_unregister(&h225);
6579 +}
6580 +
6581 +module_init(init);
6582 +module_exit(fini);
6583 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c
6584 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6585 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c     2004-04-29 11:19:01.000000000 +0200
6586 @@ -0,0 +1,350 @@
6587 +/* MMS extension for TCP NAT alteration.
6588 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6589 + * based on ip_nat_ftp.c and ip_nat_irc.c
6590 + *
6591 + * ip_nat_mms.c v0.3 2002-09-22
6592 + *
6593 + *      This program is free software; you can redistribute it and/or
6594 + *      modify it under the terms of the GNU General Public License
6595 + *      as published by the Free Software Foundation; either version
6596 + *      2 of the License, or (at your option) any later version.
6597 + *
6598 + *      Module load syntax:
6599 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6600 + *
6601 + *      Please give the ports of all MMS servers You wish to connect to.
6602 + *      If you don't specify ports, the default will be TCP port 1755.
6603 + *
6604 + *      More info on MMS protocol, firewalls and NAT:
6605 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6606 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6607 + *
6608 + *      The SDP project people are reverse-engineering MMS:
6609 + *      http://get.to/sdp
6610 + */
6611 +
6612 +/* FIXME: issue with UDP & fragmentation with this URL: 
6613 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
6614 +   may be related to out-of-order first packets:
6615 +   basically the expectation is set up correctly, then the server sends
6616 +   a first UDP packet which is fragmented plus arrives out-of-order.
6617 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
6618 +   an ICMP unreachable back to the server */
6619 +
6620 +#include <linux/module.h>
6621 +#include <linux/netfilter_ipv4.h>
6622 +#include <linux/ip.h>
6623 +#include <linux/tcp.h>
6624 +#include <net/tcp.h>
6625 +#include <linux/netfilter_ipv4/ip_nat.h>
6626 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6627 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6628 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6629 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6630 +
6631 +#if 0 
6632 +#define DEBUGP printk
6633 +#define DUMP_BYTES(address, counter)                                \
6634 +({                                                                  \
6635 +       int temp_counter;                                           \
6636 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6637 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
6638 +       };                                                          \
6639 +       DEBUGP("\n");                                               \
6640 +})
6641 +#else
6642 +#define DEBUGP(format, args...)
6643 +#define DUMP_BYTES(address, counter)
6644 +#endif
6645 +
6646 +#define MAX_PORTS 8
6647 +static int ports[MAX_PORTS];
6648 +static int ports_c = 0;
6649 +
6650 +#ifdef MODULE_PARM
6651 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6652 +#endif
6653 +
6654 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6655 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6656 +MODULE_LICENSE("GPL");
6657 +
6658 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6659 +
6660 +/* FIXME: Time out? --RR */
6661 +
6662 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6663 +                          struct ip_conntrack *ct,
6664 +                          struct sk_buff **pskb,
6665 +                          enum ip_conntrack_info ctinfo,
6666 +                          struct ip_conntrack_expect *expect)
6667 +{
6668 +       u_int32_t newip;
6669 +       struct ip_conntrack_tuple t;
6670 +       struct iphdr *iph = (*pskb)->nh.iph;
6671 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6672 +       char *data = (char *)tcph + tcph->doff * 4;
6673 +       int i, j, k, port;
6674 +       u_int16_t mms_proto;
6675 +
6676 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6677 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6678 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6679 +
6680 +       int zero_padding;
6681 +
6682 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6683 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6684 +       char proto_string[6];
6685 +       
6686 +       MUST_BE_LOCKED(&ip_mms_lock);
6687 +
6688 +       /* what was the protocol again ? */
6689 +       mms_proto = expect->tuple.dst.protonum;
6690 +       sprintf(proto_string, "%u", mms_proto);
6691 +       
6692 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6693 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6694 +              mms_proto == IPPROTO_UDP ? "UDP"
6695 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6696 +       
6697 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6698 +
6699 +       /* Alter conntrack's expectations. */
6700 +       t = expect->tuple;
6701 +       t.dst.ip = newip;
6702 +       for (port = ct_mms_info->port; port != 0; port++) {
6703 +               t.dst.u.tcp.port = htons(port);
6704 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
6705 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6706 +                       break;
6707 +               }
6708 +       }
6709 +       
6710 +       if(port == 0)
6711 +               return 0;
6712 +
6713 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6714 +               NIPQUAD(newip),
6715 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6716 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6717 +               port);
6718 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6719 +       
6720 +       memset(unicode_buffer, 0, sizeof(char)*75);
6721 +
6722 +       for (i=0; i<strlen(buffer); ++i)
6723 +               *(unicode_buffer+i*2)=*(buffer+i);
6724 +       
6725 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6726 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6727 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6728 +       
6729 +       /* add end of packet to it */
6730 +       for (j=0; j<ct_mms_info->padding; ++j) {
6731 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
6732 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6733 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6734 +       }
6735 +
6736 +       /* pad with zeroes at the end ? see explanation of weird math below */
6737 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6738 +       for (k=0; k<zero_padding; ++k)
6739 +               *(unicode_buffer+i*2+j+k)= (char)0;
6740 +       
6741 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6742 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6743 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6744 +       
6745 +       /* explanation, before I forget what I did:
6746 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6747 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
6748 +          but note that things may have to be padded with zeroes to align by 8 
6749 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
6750 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6751 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
6752 +       *mms_messageLength = *mms_chunkLenLV*8;
6753 +       
6754 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6755 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6756 +       
6757 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
6758 +                                expect->seq - ntohl(tcph->seq),
6759 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6760 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6761 +       DUMP_BYTES(unicode_buffer, 60);
6762 +       
6763 +       return 1;
6764 +}
6765 +
6766 +static unsigned int
6767 +mms_nat_expected(struct sk_buff **pskb,
6768 +                 unsigned int hooknum,
6769 +                 struct ip_conntrack *ct,
6770 +                 struct ip_nat_info *info)
6771 +{
6772 +       struct ip_nat_multi_range mr;
6773 +       u_int32_t newdstip, newsrcip, newip;
6774 +
6775 +       struct ip_conntrack *master = master_ct(ct);
6776 +
6777 +       IP_NF_ASSERT(info);
6778 +       IP_NF_ASSERT(master);
6779 +
6780 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6781 +
6782 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6783 +
6784 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6785 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6786 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6787 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6788 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6789 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6790 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
6791 +
6792 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6793 +               newip = newsrcip;
6794 +       else
6795 +               newip = newdstip;
6796 +
6797 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6798 +
6799 +       mr.rangesize = 1;
6800 +       /* We don't want to manip the per-protocol, just the IPs. */
6801 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6802 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6803 +
6804 +       return ip_nat_setup_info(ct, &mr, hooknum);
6805 +}
6806 +
6807 +
6808 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6809 +                        struct ip_conntrack_expect *exp,
6810 +                        struct ip_nat_info *info,
6811 +                        enum ip_conntrack_info ctinfo,
6812 +                        unsigned int hooknum,
6813 +                        struct sk_buff **pskb)
6814 +{
6815 +       struct iphdr *iph = (*pskb)->nh.iph;
6816 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6817 +       unsigned int datalen;
6818 +       int dir;
6819 +       struct ip_ct_mms_expect *ct_mms_info;
6820 +
6821 +       if (!exp)
6822 +               DEBUGP("ip_nat_mms: no exp!!");
6823 +
6824 +       ct_mms_info = &exp->help.exp_mms_info;
6825 +       
6826 +       /* Only mangle things once: original direction in POST_ROUTING
6827 +          and reply direction on PRE_ROUTING. */
6828 +       dir = CTINFO2DIR(ctinfo);
6829 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6830 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6831 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6832 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6833 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6834 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6835 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6836 +               return NF_ACCEPT;
6837 +       }
6838 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6839 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6840 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6841 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6842 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6843 +       
6844 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6845 +       
6846 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6847 +              exp->seq + ct_mms_info->len,
6848 +              ntohl(tcph->seq),
6849 +              ntohl(tcph->seq) + datalen);
6850 +       
6851 +       LOCK_BH(&ip_mms_lock);
6852 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
6853 +       if (between(exp->seq + ct_mms_info->len,
6854 +           ntohl(tcph->seq),
6855 +           ntohl(tcph->seq) + datalen)) {
6856 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6857 +                       UNLOCK_BH(&ip_mms_lock);
6858 +                       return NF_DROP;
6859 +               }
6860 +       } else {
6861 +               /* Half a match?  This means a partial retransmisison.
6862 +                  It's a cracker being funky. */
6863 +               if (net_ratelimit()) {
6864 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6865 +                              exp->seq, ct_mms_info->len,
6866 +                              ntohl(tcph->seq),
6867 +                              ntohl(tcph->seq) + datalen);
6868 +               }
6869 +               UNLOCK_BH(&ip_mms_lock);
6870 +               return NF_DROP;
6871 +       }
6872 +       UNLOCK_BH(&ip_mms_lock);
6873 +       
6874 +       return NF_ACCEPT;
6875 +}
6876 +
6877 +static struct ip_nat_helper mms[MAX_PORTS];
6878 +static char mms_names[MAX_PORTS][10];
6879 +
6880 +/* Not __exit: called from init() */
6881 +static void fini(void)
6882 +{
6883 +       int i;
6884 +
6885 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6886 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6887 +               ip_nat_helper_unregister(&mms[i]);
6888 +       }
6889 +}
6890 +
6891 +static int __init init(void)
6892 +{
6893 +       int i, ret = 0;
6894 +       char *tmpname;
6895 +
6896 +       if (ports[0] == 0)
6897 +               ports[0] = MMS_PORT;
6898 +
6899 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6900 +
6901 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6902 +
6903 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
6904 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6905 +               mms[i].mask.dst.protonum = 0xFFFF;
6906 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
6907 +               mms[i].help = mms_nat_help;
6908 +               mms[i].me = THIS_MODULE;
6909 +               mms[i].flags = 0;
6910 +               mms[i].expect = mms_nat_expected;
6911 +
6912 +               tmpname = &mms_names[i][0];
6913 +               if (ports[i] == MMS_PORT)
6914 +                       sprintf(tmpname, "mms");
6915 +               else
6916 +                       sprintf(tmpname, "mms-%d", i);
6917 +               mms[i].name = tmpname;
6918 +
6919 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
6920 +                               ports[i]);
6921 +               ret = ip_nat_helper_register(&mms[i]);
6922 +
6923 +               if (ret) {
6924 +                       printk("ip_nat_mms: error registering "
6925 +                              "helper for port %d\n", ports[i]);
6926 +                       fini();
6927 +                       return ret;
6928 +               }
6929 +               ports_c++;
6930 +       }
6931 +
6932 +       return ret;
6933 +}
6934 +
6935 +module_init(init);
6936 +module_exit(fini);
6937 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c
6938 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c      1970-01-01 01:00:00.000000000 +0100
6939 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c  2004-04-29 11:19:53.000000000 +0200
6940 @@ -0,0 +1,249 @@
6941 +/* Quake3 extension for UDP NAT alteration.
6942 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6943 + * based on ip_nat_ftp.c and ip_nat_tftp.c
6944 + *
6945 + * ip_nat_quake3.c v0.0.3 2002-08-31
6946 + *
6947 + *      This program is free software; you can redistribute it and/or
6948 + *      modify it under the terms of the GNU General Public License
6949 + *      as published by the Free Software Foundation; either version
6950 + *      2 of the License, or (at your option) any later version.
6951 + *
6952 + *      Module load syntax:
6953 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6954 + *
6955 + *      please give the ports of all Quake3 master servers You wish to
6956 + *      connect to. If you don't specify ports, the default will be UDP
6957 + *      port 27950.
6958 + *
6959 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6960 + *
6961 + *      Notes: 
6962 + *      - If you're one of those people who would try anything to lower
6963 + *        latency while playing Quake (and who isn't :-) ), you may want to
6964 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
6965 + *        outgoing UDP traffic.
6966 + *        This will make ip_conntrack_quake3 add the necessary expectations,
6967 + *        but there will be no overhead for client->server UDP streams. If
6968 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6969 + *        hook for every packet in the client->server UDP stream.
6970 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6971 + *        The IP addresses in the master connection payload (=IP addresses
6972 + *        of Quake servers) have no relation with the master server so
6973 + *        DNAT'ing the master connection to a server should not change the
6974 + *        expected connections.
6975 + *      - Not tested due to lack of equipment:
6976 + *        - multiple Quake3 clients behind one MASQUERADE gateway
6977 + *        - what if Quake3 client is running on router too
6978 + */
6979 +
6980 +#include <linux/module.h>
6981 +#include <linux/netfilter_ipv4.h>
6982 +#include <linux/ip.h>
6983 +#include <linux/udp.h>
6984 +
6985 +#include <linux/netfilter.h>
6986 +#include <linux/netfilter_ipv4/ip_tables.h>
6987 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6988 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6989 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6990 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6991 +
6992 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6993 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6994 +MODULE_LICENSE("GPL");
6995 +
6996 +#define MAX_PORTS 8
6997 +
6998 +static int ports[MAX_PORTS];
6999 +static int ports_c = 0;
7000 +#ifdef MODULE_PARM
7001 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7002 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7003 +#endif
7004 +
7005 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7006 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7007 +#if 0 
7008 +#define DEBUGP printk
7009 +#else
7010 +#define DEBUGP(format, args...)
7011 +#endif
7012 +
7013 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7014 +
7015 +static unsigned int 
7016 +quake3_nat_help(struct ip_conntrack *ct,
7017 +                struct ip_conntrack_expect *exp,
7018 +                struct ip_nat_info *info,
7019 +                enum ip_conntrack_info ctinfo,
7020 +                unsigned int hooknum,
7021 +                struct sk_buff **pskb)
7022 +{
7023 +       struct iphdr *iph = (*pskb)->nh.iph;
7024 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7025 +       struct ip_conntrack_tuple repl;
7026 +       int dir = CTINFO2DIR(ctinfo);
7027 +       int i;
7028 +       
7029 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7030 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7031 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7032 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7033 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7034 +             );
7035 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7036 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7037 +       
7038 +       /* Only mangle things once: original direction in POST_ROUTING
7039 +          and reply direction on PRE_ROUTING. */
7040 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7041 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7042 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7043 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7044 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7045 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7046 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7047 +               return NF_ACCEPT;
7048 +       }
7049 +
7050 +       if (!exp) {
7051 +               DEBUGP("no conntrack expectation to modify\n");
7052 +               return NF_ACCEPT;
7053 +       }
7054 +
7055 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7056 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7057 +                   i+6 < ntohs(udph->len);
7058 +                   i+=7) {
7059 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
7060 +                              i, ntohs(udph->len),
7061 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7062 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7063 +                       
7064 +                       memset(&repl, 0, sizeof(repl));
7065 +
7066 +                       repl.dst.protonum = IPPROTO_UDP;
7067 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7068 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7069 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
7070 +                       
7071 +                       ip_conntrack_change_expect(exp, &repl);
7072 +               }
7073 +       }
7074 +       return NF_ACCEPT;
7075 +}
7076 +
7077 +static unsigned int 
7078 +quake3_nat_expected(struct sk_buff **pskb,
7079 +                    unsigned int hooknum,
7080 +                    struct ip_conntrack *ct, 
7081 +                    struct ip_nat_info *info) 
7082 +{
7083 +       const struct ip_conntrack *master = ct->master->expectant;
7084 +       struct ip_nat_multi_range mr;
7085 +       u_int32_t newsrcip, newdstip, newip;
7086 +#if 0 
7087 +       const struct ip_conntrack_tuple *repl =
7088 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7089 +       struct iphdr *iph = (*pskb)->nh.iph;
7090 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
7091 +#endif
7092 +
7093 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7094 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7095 +
7096 +       IP_NF_ASSERT(info);
7097 +       IP_NF_ASSERT(master);
7098 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7099 +       
7100 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7101 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7102 +       
7103 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7104 +               newip = newsrcip;
7105 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7106 +                      "newsrc: %u.%u.%u.%u\n",
7107 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7108 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7109 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7110 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7111 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7112 +                      NIPQUAD(newip));
7113 +               
7114 +       } else {
7115 +               newip = newdstip;
7116 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7117 +                      "newdst: %u.%u.%u.%u\n",
7118 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7119 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7120 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7121 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7122 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7123 +                      NIPQUAD(newip));
7124 +       }
7125 +       
7126 +       mr.rangesize = 1;
7127 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7128 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
7129 +
7130 +       return ip_nat_setup_info(ct,&mr,hooknum);
7131 +}
7132 +
7133 +static struct ip_nat_helper quake3[MAX_PORTS];
7134 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
7135 +
7136 +static void fini(void)
7137 +{
7138 +       int i;
7139 +       
7140 +       for (i = 0 ; i < ports_c; i++) {
7141 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7142 +                      ip_nat_helper_unregister(&quake3[i]);
7143 +       }
7144 +}
7145 +
7146 +static int __init init(void)
7147 +       {
7148 +               int i, ret = 0;
7149 +               char *tmpname;
7150 +
7151 +               if (!ports[0])
7152 +                       ports[0] = QUAKE3_MASTER_PORT;
7153 +               
7154 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7155 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7156 +
7157 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7158 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7159 +                       quake3[i].mask.dst.protonum = 0xFFFF;
7160 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
7161 +                       quake3[i].help = quake3_nat_help;
7162 +                       quake3[i].flags = 0;
7163 +                       quake3[i].me = THIS_MODULE;
7164 +                       quake3[i].expect = quake3_nat_expected;
7165 +                       
7166 +                       tmpname = &quake3_names[i][0];
7167 +                       if (ports[i] == QUAKE3_MASTER_PORT)
7168 +                               sprintf(tmpname, "quake3");
7169 +                       else
7170 +                               sprintf(tmpname, "quake3-%d", i);
7171 +                       quake3[i].name = tmpname;
7172 +                       
7173 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7174 +                              ports[i], quake3[i].name);
7175 +                       ret = ip_nat_helper_register(&quake3[i]);
7176 +                       
7177 +                       if (ret) {
7178 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
7179 +                                      ports[i]);
7180 +                               fini();
7181 +                               return ret;
7182 +                       }
7183 +                       ports_c++;
7184 +               }
7185 +               return ret;
7186 +       }
7187 +       
7188 +module_init(init);
7189 +module_exit(fini);
7190 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
7191 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c        1970-01-01 01:00:00.000000000 +0100
7192 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c    2004-04-29 11:20:13.000000000 +0200
7193 @@ -0,0 +1,621 @@
7194 +/*
7195 + * RTSP extension for TCP NAT alteration
7196 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7197 + * based on ip_nat_irc.c
7198 + *
7199 + *      This program is free software; you can redistribute it and/or
7200 + *      modify it under the terms of the GNU General Public License
7201 + *      as published by the Free Software Foundation; either version
7202 + *      2 of the License, or (at your option) any later version.
7203 + *
7204 + * Module load syntax:
7205 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7206 + *                           stunaddr=<address>
7207 + *                           destaction=[auto|strip|none]
7208 + *
7209 + * If no ports are specified, the default will be port 554 only.
7210 + *
7211 + * stunaddr specifies the address used to detect that a client is using STUN.
7212 + * If this address is seen in the destination parameter, it is assumed that
7213 + * the client has already punched a UDP hole in the firewall, so we don't
7214 + * mangle the client_port.  If none is specified, it is autodetected.  It
7215 + * only needs to be set if you have multiple levels of NAT.  It should be
7216 + * set to the external address that the STUN clients detect.  Note that in
7217 + * this case, it will not be possible for clients to use UDP with servers
7218 + * between the NATs.
7219 + *
7220 + * If no destaction is specified, auto is used.
7221 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
7222 + *   destaction=strip: always strip destination parameter (not recommended).
7223 + *   destaction=none:  do not touch destination parameter (not recommended).
7224 + */
7225 +
7226 +#include <linux/module.h>
7227 +#include <linux/netfilter_ipv4.h>
7228 +#include <linux/ip.h>
7229 +#include <linux/tcp.h>
7230 +#include <linux/kernel.h>
7231 +#include <net/tcp.h>
7232 +#include <linux/netfilter_ipv4/ip_nat.h>
7233 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7234 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7235 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7236 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7237 +
7238 +#include <linux/inet.h>
7239 +#include <linux/ctype.h>
7240 +#define NF_NEED_STRNCASECMP
7241 +#define NF_NEED_STRTOU16
7242 +#include <linux/netfilter_helpers.h>
7243 +#define NF_NEED_MIME_NEXTLINE
7244 +#include <linux/netfilter_mime.h>
7245 +
7246 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7247 +#ifdef IP_NF_RTSP_DEBUG
7248 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7249 +#else
7250 +#define DEBUGP(fmt, args...)
7251 +#endif
7252 +
7253 +#define MAX_PORTS       8
7254 +#define DSTACT_AUTO     0
7255 +#define DSTACT_STRIP    1
7256 +#define DSTACT_NONE     2
7257 +
7258 +static int      ports[MAX_PORTS];
7259 +static char*    stunaddr = NULL;
7260 +static char*    destaction = NULL;
7261 +
7262 +static int       num_ports = 0;
7263 +static u_int32_t extip = 0;
7264 +static int       dstact = 0;
7265 +
7266 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7267 +MODULE_DESCRIPTION("RTSP network address translation module");
7268 +MODULE_LICENSE("GPL");
7269 +#ifdef MODULE_PARM
7270 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7271 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7272 +MODULE_PARM(stunaddr, "s");
7273 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7274 +MODULE_PARM(destaction, "s");
7275 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7276 +#endif
7277 +
7278 +/* protects rtsp part of conntracks */
7279 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7280 +
7281 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7282 +
7283 +/*** helper functions ***/
7284 +
7285 +static void
7286 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7287 +{
7288 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
7289 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7290 +
7291 +    *pptcpdata = (char*)tcph + tcph->doff*4;
7292 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7293 +}
7294 +
7295 +/*** nat functions ***/
7296 +
7297 +/*
7298 + * Mangle the "Transport:" header:
7299 + *   - Replace all occurences of "client_port=<spec>"
7300 + *   - Handle destination parameter
7301 + *
7302 + * In:
7303 + *   ct, ctinfo = conntrack context
7304 + *   pskb       = packet
7305 + *   tranoff    = Transport header offset from TCP data
7306 + *   tranlen    = Transport header length (incl. CRLF)
7307 + *   rport_lo   = replacement low  port (host endian)
7308 + *   rport_hi   = replacement high port (host endian)
7309 + *
7310 + * Returns packet size difference.
7311 + *
7312 + * Assumes that a complete transport header is present, ending with CR or LF
7313 + */
7314 +static int
7315 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7316 +                 struct ip_conntrack_expect* exp,
7317 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
7318 +{
7319 +    char*       ptcp;
7320 +    uint        tcplen;
7321 +    char*       ptran;
7322 +    char        rbuf1[16];      /* Replacement buffer (one port) */
7323 +    uint        rbuf1len;       /* Replacement len (one port) */
7324 +    char        rbufa[16];      /* Replacement buffer (all ports) */
7325 +    uint        rbufalen;       /* Replacement len (all ports) */
7326 +    u_int32_t   newip;
7327 +    u_int16_t   loport, hiport;
7328 +    uint        off = 0;
7329 +    uint        diff;           /* Number of bytes we removed */
7330 +
7331 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7332 +    struct ip_conntrack_tuple t;
7333 +
7334 +    char    szextaddr[15+1];
7335 +    uint    extaddrlen;
7336 +    int     is_stun;
7337 +
7338 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7339 +    ptran = ptcp+tranoff;
7340 +
7341 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7342 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7343 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
7344 +    {
7345 +        INFOP("sanity check failed\n");
7346 +        return 0;
7347 +    }
7348 +    off += 10;
7349 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7350 +
7351 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7352 +    t = exp->tuple;
7353 +    t.dst.ip = newip;
7354 +
7355 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7356 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7357 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7358 +
7359 +    rbuf1len = rbufalen = 0;
7360 +    switch (prtspexp->pbtype)
7361 +    {
7362 +    case pb_single:
7363 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7364 +        {
7365 +            t.dst.u.udp.port = htons(loport);
7366 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7367 +            {
7368 +                DEBUGP("using port %hu\n", loport);
7369 +                break;
7370 +            }
7371 +        }
7372 +        if (loport != 0)
7373 +        {
7374 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7375 +            rbufalen = sprintf(rbufa, "%hu", loport);
7376 +        }
7377 +        break;
7378 +    case pb_range:
7379 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7380 +        {
7381 +            t.dst.u.udp.port = htons(loport);
7382 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7383 +            {
7384 +                hiport = loport + ~exp->mask.dst.u.udp.port;
7385 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
7386 +                break;
7387 +            }
7388 +        }
7389 +        if (loport != 0)
7390 +        {
7391 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7392 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7393 +        }
7394 +        break;
7395 +    case pb_discon:
7396 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7397 +        {
7398 +            t.dst.u.udp.port = htons(loport);
7399 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7400 +            {
7401 +                DEBUGP("using port %hu (1 of 2)\n", loport);
7402 +                break;
7403 +            }
7404 +        }
7405 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7406 +        {
7407 +            t.dst.u.udp.port = htons(hiport);
7408 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7409 +            {
7410 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
7411 +                break;
7412 +            }
7413 +        }
7414 +        if (loport != 0 && hiport != 0)
7415 +        {
7416 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7417 +            if (hiport == loport+1)
7418 +            {
7419 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7420 +            }
7421 +            else
7422 +            {
7423 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7424 +            }
7425 +        }
7426 +        break;
7427 +    }
7428 +
7429 +    if (rbuf1len == 0)
7430 +    {
7431 +        return 0;   /* cannot get replacement port(s) */
7432 +    }
7433 +
7434 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
7435 +    while (off < tranlen)
7436 +    {
7437 +        uint        saveoff;
7438 +        const char* pparamend;
7439 +        uint        nextparamoff;
7440 +
7441 +        pparamend = memchr(ptran+off, ',', tranlen-off);
7442 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7443 +        nextparamoff = pparamend-ptcp;
7444 +
7445 +        /*
7446 +         * We pass over each param twice.  On the first pass, we look for a
7447 +         * destination= field.  It is handled by the security policy.  If it
7448 +         * is present, allowed, and equal to our external address, we assume
7449 +         * that STUN is being used and we leave the client_port= field alone.
7450 +         */
7451 +        is_stun = 0;
7452 +        saveoff = off;
7453 +        while (off < nextparamoff)
7454 +        {
7455 +            const char* pfieldend;
7456 +            uint        nextfieldoff;
7457 +
7458 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7459 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7460 +
7461 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7462 +            {
7463 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7464 +                {
7465 +                    is_stun = 1;
7466 +                }
7467 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7468 +                {
7469 +                    diff = nextfieldoff-off;
7470 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7471 +                                                         off, diff, NULL, 0))
7472 +                    {
7473 +                        /* mangle failed, all we can do is bail */
7474 +                        return 0;
7475 +                    }
7476 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7477 +                    ptran = ptcp+tranoff;
7478 +                    tranlen -= diff;
7479 +                    nextparamoff -= diff;
7480 +                    nextfieldoff -= diff;
7481 +                }
7482 +            }
7483 +
7484 +            off = nextfieldoff;
7485 +        }
7486 +        if (is_stun)
7487 +        {
7488 +            continue;
7489 +        }
7490 +        off = saveoff;
7491 +        while (off < nextparamoff)
7492 +        {
7493 +            const char* pfieldend;
7494 +            uint        nextfieldoff;
7495 +
7496 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7497 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7498 +
7499 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
7500 +            {
7501 +                u_int16_t   port;
7502 +                uint        numlen;
7503 +                uint        origoff;
7504 +                uint        origlen;
7505 +                char*       rbuf    = rbuf1;
7506 +                uint        rbuflen = rbuf1len;
7507 +
7508 +                off += 12;
7509 +                origoff = (ptran-ptcp)+off;
7510 +                origlen = 0;
7511 +                numlen = nf_strtou16(ptran+off, &port);
7512 +                off += numlen;
7513 +                origlen += numlen;
7514 +                if (port != prtspexp->loport)
7515 +                {
7516 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
7517 +                }
7518 +                else
7519 +                {
7520 +                    if (ptran[off] == '-' || ptran[off] == '/')
7521 +                    {
7522 +                        off++;
7523 +                        origlen++;
7524 +                        numlen = nf_strtou16(ptran+off, &port);
7525 +                        off += numlen;
7526 +                        origlen += numlen;
7527 +                        rbuf = rbufa;
7528 +                        rbuflen = rbufalen;
7529 +                    }
7530 +
7531 +                    /*
7532 +                     * note we cannot just memcpy() if the sizes are the same.
7533 +                     * the mangle function does skb resizing, checks for a
7534 +                     * cloned skb, and updates the checksums.
7535 +                     *
7536 +                     * parameter 4 below is offset from start of tcp data.
7537 +                     */
7538 +                    diff = origlen-rbuflen;
7539 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7540 +                                              origoff, origlen, rbuf, rbuflen))
7541 +                    {
7542 +                        /* mangle failed, all we can do is bail */
7543 +                        return 0;
7544 +                    }
7545 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7546 +                    ptran = ptcp+tranoff;
7547 +                    tranlen -= diff;
7548 +                    nextparamoff -= diff;
7549 +                    nextfieldoff -= diff;
7550 +                }
7551 +            }
7552 +
7553 +            off = nextfieldoff;
7554 +        }
7555 +
7556 +        off = nextparamoff;
7557 +    }
7558 +
7559 +    return 1;
7560 +}
7561 +
7562 +static unsigned int
7563 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7564 +{
7565 +    struct ip_nat_multi_range mr;
7566 +    u_int32_t newdstip, newsrcip, newip;
7567 +
7568 +    struct ip_conntrack *master = master_ct(ct);
7569 +
7570 +    IP_NF_ASSERT(info);
7571 +    IP_NF_ASSERT(master);
7572 +
7573 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7574 +
7575 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7576 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7577 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7578 +
7579 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7580 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7581 +
7582 +    mr.rangesize = 1;
7583 +    /* We don't want to manip the per-protocol, just the IPs. */
7584 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7585 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
7586 +
7587 +    return ip_nat_setup_info(ct, &mr, hooknum);
7588 +}
7589 +
7590 +static uint
7591 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7592 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7593 +{
7594 +    char*   ptcp;
7595 +    uint    tcplen;
7596 +    uint    hdrsoff;
7597 +    uint    hdrslen;
7598 +    uint    lineoff;
7599 +    uint    linelen;
7600 +    uint    off;
7601 +
7602 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7603 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7604 +
7605 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7606 +
7607 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7608 +
7609 +    hdrsoff = exp->seq - ntohl(tcph->seq);
7610 +    hdrslen = prtspexp->len;
7611 +    off = hdrsoff;
7612 +
7613 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7614 +    {
7615 +        if (linelen == 0)
7616 +        {
7617 +            break;
7618 +        }
7619 +        if (off > hdrsoff+hdrslen)
7620 +        {
7621 +            INFOP("!! overrun !!");
7622 +            break;
7623 +        }
7624 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7625 +
7626 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7627 +        {
7628 +            uint oldtcplen = tcplen;
7629 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7630 +            {
7631 +                break;
7632 +            }
7633 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7634 +            hdrslen -= (oldtcplen-tcplen);
7635 +            off -= (oldtcplen-tcplen);
7636 +            lineoff -= (oldtcplen-tcplen);
7637 +            linelen -= (oldtcplen-tcplen);
7638 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7639 +        }
7640 +    }
7641 +
7642 +    return NF_ACCEPT;
7643 +}
7644 +
7645 +static uint
7646 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7647 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7648 +{
7649 +    /* XXX: unmangle */
7650 +    return NF_ACCEPT;
7651 +}
7652 +
7653 +static uint
7654 +help(struct ip_conntrack* ct,
7655 +     struct ip_conntrack_expect* exp,
7656 +     struct ip_nat_info* info,
7657 +     enum ip_conntrack_info ctinfo,
7658 +     unsigned int hooknum,
7659 +     struct sk_buff** pskb)
7660 +{
7661 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
7662 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7663 +    uint datalen;
7664 +    int dir;
7665 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
7666 +    int rc = NF_ACCEPT;
7667 +
7668 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7669 +    {
7670 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7671 +        return NF_ACCEPT;
7672 +    }
7673 +
7674 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
7675 +
7676 +    /*
7677 +     * Only mangle things once: original direction in POST_ROUTING
7678 +     * and reply direction on PRE_ROUTING.
7679 +     */
7680 +    dir = CTINFO2DIR(ctinfo);
7681 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7682 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7683 +    {
7684 +        DEBUGP("Not touching dir %s at hook %s\n",
7685 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7686 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7687 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7688 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7689 +        return NF_ACCEPT;
7690 +    }
7691 +    DEBUGP("got beyond not touching\n");
7692 +
7693 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7694 +
7695 +    LOCK_BH(&ip_rtsp_lock);
7696 +    /* Ensure the packet contains all of the marked data */
7697 +    if (!between(exp->seq + ct_rtsp_info->len,
7698 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7699 +    {
7700 +        /* Partial retransmission?  Probably a hacker. */
7701 +        if (net_ratelimit())
7702 +        {
7703 +            INFOP("partial packet %u/%u in %u/%u\n",
7704 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7705 +        }
7706 +        UNLOCK_BH(&ip_rtsp_lock);
7707 +        return NF_DROP;
7708 +    }
7709 +
7710 +    switch (dir)
7711 +    {
7712 +    case IP_CT_DIR_ORIGINAL:
7713 +        rc = help_out(ct, ctinfo, exp, pskb);
7714 +        break;
7715 +    case IP_CT_DIR_REPLY:
7716 +        rc = help_in(ct, ctinfo, exp, pskb);
7717 +        break;
7718 +    }
7719 +    UNLOCK_BH(&ip_rtsp_lock);
7720 +
7721 +    return rc;
7722 +}
7723 +
7724 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7725 +static char rtsp_names[MAX_PORTS][10];
7726 +
7727 +/* This function is intentionally _NOT_ defined as  __exit */
7728 +static void
7729 +fini(void)
7730 +{
7731 +    int i;
7732 +
7733 +    for (i = 0; i < num_ports; i++)
7734 +    {
7735 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
7736 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7737 +    }
7738 +}
7739 +
7740 +static int __init
7741 +init(void)
7742 +{
7743 +    int ret = 0;
7744 +    int i;
7745 +    struct ip_nat_helper* hlpr;
7746 +    char* tmpname;
7747 +
7748 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7749 +
7750 +    if (ports[0] == 0)
7751 +    {
7752 +        ports[0] = RTSP_PORT;
7753 +    }
7754 +
7755 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7756 +    {
7757 +        hlpr = &ip_nat_rtsp_helpers[i];
7758 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
7759 +
7760 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
7761 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7762 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
7763 +        hlpr->mask.dst.protonum = 0xFFFF;
7764 +        hlpr->help = help;
7765 +        hlpr->flags = 0;
7766 +        hlpr->me = THIS_MODULE;
7767 +        hlpr->expect = expected;
7768 +
7769 +        tmpname = &rtsp_names[i][0];
7770 +        if (ports[i] == RTSP_PORT)
7771 +        {
7772 +                sprintf(tmpname, "rtsp");
7773 +        }
7774 +        else
7775 +        {
7776 +                sprintf(tmpname, "rtsp-%d", i);
7777 +        }
7778 +        hlpr->name = tmpname;
7779 +
7780 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7781 +        ret = ip_nat_helper_register(hlpr);
7782 +
7783 +        if (ret)
7784 +        {
7785 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7786 +            fini();
7787 +            return 1;
7788 +        }
7789 +        num_ports++;
7790 +    }
7791 +    if (stunaddr != NULL)
7792 +    {
7793 +        extip = in_aton(stunaddr);
7794 +    }
7795 +    if (destaction != NULL)
7796 +    {
7797 +        if (strcmp(destaction, "auto") == 0)
7798 +        {
7799 +            dstact = DSTACT_AUTO;
7800 +        }
7801 +        if (strcmp(destaction, "strip") == 0)
7802 +        {
7803 +            dstact = DSTACT_STRIP;
7804 +        }
7805 +        if (strcmp(destaction, "none") == 0)
7806 +        {
7807 +            dstact = DSTACT_NONE;
7808 +        }
7809 +    }
7810 +    return ret;
7811 +}
7812 +
7813 +module_init(init);
7814 +module_exit(fini);
7815 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c
7816 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c        2004-04-28 03:35:44.000000000 +0200
7817 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c    2004-04-29 11:17:15.000000000 +0200
7818 @@ -75,7 +75,7 @@
7819                 0,
7820                 sizeof(struct ipt_entry),
7821                 sizeof(struct ipt_standard),
7822 -               0, { 0, 0 }, { } },
7823 +               0, NULL, 0, { 0, 0 }, { } },
7824               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7825                 -NF_ACCEPT - 1 } },
7826             /* POST_ROUTING */
7827 @@ -83,7 +83,7 @@
7828                 0,
7829                 sizeof(struct ipt_entry),
7830                 sizeof(struct ipt_standard),
7831 -               0, { 0, 0 }, { } },
7832 +               0, NULL, 0, { 0, 0 }, { } },
7833               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7834                 -NF_ACCEPT - 1 } },
7835             /* LOCAL_OUT */
7836 @@ -91,7 +91,7 @@
7837                 0,
7838                 sizeof(struct ipt_entry),
7839                 sizeof(struct ipt_standard),
7840 -               0, { 0, 0 }, { } },
7841 +               0, NULL, 0, { 0, 0 }, { } },
7842               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7843                 -NF_ACCEPT - 1 } }
7844      },
7845 @@ -100,7 +100,7 @@
7846         0,
7847         sizeof(struct ipt_entry),
7848         sizeof(struct ipt_error),
7849 -       0, { 0, 0 }, { } },
7850 +       0, NULL, 0, { 0, 0 }, { } },
7851        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7852           { } },
7853         "ERROR"
7854 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c
7855 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c  2004-04-28 03:36:29.000000000 +0200
7856 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c      2004-04-29 11:18:04.000000000 +0200
7857 @@ -175,6 +175,45 @@
7858         return do_bindings(ct, ctinfo, info, hooknum, pskb);
7859  }
7860  
7861 +struct nat_route_key
7862 +{
7863 +       u_int32_t addr;
7864 +#ifdef CONFIG_XFRM
7865 +       u_int16_t port;
7866 +#endif
7867 +};
7868 +
7869 +static inline void
7870 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
7871 +{
7872 +       struct iphdr *iph = skb->nh.iph;
7873 +
7874 +       key->addr = which ? iph->daddr : iph->saddr;
7875 +#ifdef CONFIG_XFRM
7876 +       key->port = 0;
7877 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7878 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7879 +               key->port = ports[which];
7880 +       }
7881 +#endif
7882 +}
7883 +
7884 +static inline int
7885 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
7886 +{
7887 +       struct iphdr *iph = skb->nh.iph;
7888 +
7889 +       if (key->addr != (which ? iph->daddr : iph->saddr))
7890 +               return 1;
7891 +#ifdef CONFIG_XFRM
7892 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7893 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7894 +               if (key->port != ports[which])
7895 +                       return 1;
7896 +       }
7897 +#endif
7898 +}
7899 +
7900  static unsigned int
7901  ip_nat_out(unsigned int hooknum,
7902            struct sk_buff **pskb,
7903 @@ -182,6 +221,9 @@
7904            const struct net_device *out,
7905            int (*okfn)(struct sk_buff *))
7906  {
7907 +       struct nat_route_key key;
7908 +       unsigned int ret;
7909 +
7910         /* root is playing with raw sockets. */
7911         if ((*pskb)->len < sizeof(struct iphdr)
7912             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7913 @@ -204,7 +246,29 @@
7914                         return NF_STOLEN;
7915         }
7916  
7917 -       return ip_nat_fn(hooknum, pskb, in, out, okfn);
7918 +       nat_route_key_get(*pskb, &key, 0);
7919 +       ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7920 +
7921 +       if (ret != NF_DROP && ret != NF_STOLEN
7922 +           && nat_route_key_compare(*pskb, &key, 0)) {
7923 +               if (ip_route_me_harder(pskb) != 0)
7924 +                       ret = NF_DROP;
7925 +#ifdef CONFIG_XFRM
7926 +               /*
7927 +                * POST_ROUTING hook is called with fixed outfn, we need
7928 +                * to manually confirm the packet and direct it to the
7929 +                * transformers if a policy matches.
7930 +                */
7931 +               else if ((*pskb)->dst->xfrm != NULL) {
7932 +                       ret = ip_conntrack_confirm(*pskb);
7933 +                       if (ret != NF_DROP) {
7934 +                               dst_output(*pskb);
7935 +                               ret = NF_STOLEN;
7936 +                       }
7937 +               }
7938 +#endif
7939 +       }
7940 +       return ret;
7941  }
7942  
7943  #ifdef CONFIG_IP_NF_NAT_LOCAL
7944 @@ -215,7 +279,7 @@
7945                 const struct net_device *out,
7946                 int (*okfn)(struct sk_buff *))
7947  {
7948 -       u_int32_t saddr, daddr;
7949 +       struct nat_route_key key;
7950         unsigned int ret;
7951  
7952         /* root is playing with raw sockets. */
7953 @@ -223,14 +287,14 @@
7954             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7955                 return NF_ACCEPT;
7956  
7957 -       saddr = (*pskb)->nh.iph->saddr;
7958 -       daddr = (*pskb)->nh.iph->daddr;
7959 -
7960 +       nat_route_key_get(*pskb, &key, 1);
7961         ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7962 +
7963         if (ret != NF_DROP && ret != NF_STOLEN
7964 -           && ((*pskb)->nh.iph->saddr != saddr
7965 -               || (*pskb)->nh.iph->daddr != daddr))
7966 -               return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
7967 +           && nat_route_key_compare(*pskb, &key, 1)) {
7968 +               if (ip_route_me_harder(pskb) != 0)
7969 +                       ret = NF_DROP;
7970 +       }
7971         return ret;
7972  }
7973  #endif
7974 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c
7975 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c        1970-01-01 01:00:00.000000000 +0100
7976 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c    2004-04-29 11:21:43.000000000 +0200
7977 @@ -0,0 +1,473 @@
7978 +/* 
7979 + * talk extension for UDP NAT alteration. 
7980 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7981 + *
7982 + *      This program is free software; you can redistribute it and/or
7983 + *      modify it under the terms of the GNU General Public License
7984 + *      as published by the Free Software Foundation; either version
7985 + *      2 of the License, or (at your option) any later version.
7986 + **
7987 + *     Module load syntax:
7988 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7989 + *
7990 + *             talk=[0|1]      disable|enable old talk support
7991 + *            ntalk=[0|1]      disable|enable ntalk support
7992 + *           ntalk2=[0|1]      disable|enable ntalk2 support
7993 + *
7994 + *     The default is talk=1 ntalk=1 ntalk2=1
7995 + *
7996 + *  
7997 + */
7998 +#include <linux/module.h>
7999 +#include <linux/netfilter_ipv4.h>
8000 +#include <linux/ip.h>
8001 +#include <linux/udp.h>
8002 +#include <linux/kernel.h>
8003 +#include <net/tcp.h>
8004 +#include <net/udp.h>
8005 +
8006 +#include <linux/netfilter_ipv4/ip_nat.h>
8007 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8008 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8009 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8010 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8011 +
8012 +/* Default all talk protocols are supported */
8013 +static int talk   = 1;
8014 +static int ntalk  = 1;
8015 +static int ntalk2 = 1;
8016 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8017 +MODULE_DESCRIPTION("talk network address translation module");
8018 +#ifdef MODULE_PARM
8019 +MODULE_PARM(talk, "i");
8020 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8021 +MODULE_PARM(ntalk, "i");
8022 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8023 +MODULE_PARM(ntalk2, "i");
8024 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8025 +#endif
8026 +
8027 +#if 0
8028 +#define DEBUGP printk
8029 +#define IP_NAT_TALK_DEBUG
8030 +#else
8031 +#define DEBUGP(format, args...)
8032 +#endif
8033 +
8034 +/* FIXME: Time out? --RR */
8035 +
8036 +static int
8037 +mangle_packet(struct sk_buff **pskb,
8038 +             struct ip_conntrack *ct,
8039 +             u_int32_t newip,
8040 +             u_int16_t port,
8041 +             struct talk_addr *addr,
8042 +             struct talk_addr *ctl_addr)
8043 +{
8044 +       struct iphdr *iph = (*pskb)->nh.iph;
8045 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8046 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
8047 +
8048 +       /* Fortunately talk sends a structure with the address and
8049 +          port in it. The size of the packet won't change. */
8050 +
8051 +       if (ctl_addr == NULL) {
8052 +               /* response */
8053 +               if (addr->ta_addr == INADDR_ANY)
8054 +                       return 1;
8055 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8056 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8057 +                      NIPQUAD(newip), ntohs(port));
8058 +               addr->ta_addr = newip;
8059 +               addr->ta_port = port;
8060 +       } else {
8061 +               /* message */
8062 +               if (addr->ta_addr != INADDR_ANY) {
8063 +                       /* Change address inside packet to match way we're mapping
8064 +                          this connection. */
8065 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8066 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8067 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
8068 +                              ntohs(addr->ta_port));
8069 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8070 +               }
8071 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8072 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8073 +                      NIPQUAD(newip), ntohs(port));
8074 +               ctl_addr->ta_addr = newip;
8075 +               ctl_addr->ta_port = port;
8076 +       }
8077 +
8078 +       /* Fix checksums */
8079 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8080 +       udph->check = 0;
8081 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8082 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8083 +               
8084 +       ip_send_check(iph);
8085 +       return 1;
8086 +}
8087 +
8088 +static int talk_help_msg(struct ip_conntrack *ct,
8089 +                        struct sk_buff **pskb,
8090 +                        u_char type,
8091 +                        struct talk_addr *addr,
8092 +                        struct talk_addr *ctl_addr)
8093 +{
8094 +       u_int32_t newip;
8095 +       u_int16_t port;
8096 +       
8097 +       unsigned int verdict = NF_ACCEPT;
8098 +
8099 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8100 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8101 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8102 +               type);
8103 +
8104 +       /* Change address inside packet to match way we're mapping
8105 +          this connection. */
8106 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8107 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8108 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8109 +               NIPQUAD(newip), ntohs(port));
8110 +
8111 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8112 +               verdict = NF_DROP;
8113 +
8114 +       return verdict;
8115 +}
8116 +
8117 +static int talk_help_response(struct ip_conntrack *ct,
8118 +                             struct ip_conntrack_expect *exp,
8119 +                             struct sk_buff **pskb,
8120 +                             u_char type,
8121 +                             u_char answer,
8122 +                             struct talk_addr *addr)
8123 +{
8124 +       u_int32_t newip;
8125 +       u_int16_t port;
8126 +       struct ip_conntrack_tuple t;
8127 +       struct ip_ct_talk_expect *ct_talk_info;
8128 +
8129 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8130 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8131 +               type, answer);
8132 +       
8133 +       LOCK_BH(&ip_talk_lock);
8134 +       ct_talk_info = &exp->help.exp_talk_info;
8135 +
8136 +       if (!(answer == SUCCESS 
8137 +             && (type == LOOK_UP || type == ANNOUNCE)
8138 +             && exp != NULL)) {
8139 +               UNLOCK_BH(&ip_talk_lock);
8140 +               return NF_ACCEPT;
8141 +       }
8142 +               
8143 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
8144 +               ntohs(ct_talk_info->port), 
8145 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8146 +
8147 +       /* Change address inside packet to match way we're mapping
8148 +          this connection. */
8149 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
8150 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
8151 +       /* We can read expect here without conntrack lock, since it's
8152 +          only set in ip_conntrack_talk , with ip_talk_lock held
8153 +          writable */ 
8154 +       t = exp->tuple;
8155 +       t.dst.ip = newip;
8156 +
8157 +       /* Try to get same port: if not, try to change it. */
8158 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8159 +               if (type == LOOK_UP)
8160 +                       t.dst.u.tcp.port = htons(port);
8161 +               else
8162 +                       t.dst.u.udp.port = htons(port);
8163 +
8164 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
8165 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8166 +                       break;
8167 +               }
8168 +       }
8169 +       UNLOCK_BH(&ip_talk_lock);
8170 +
8171 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8172 +               return NF_DROP;
8173 +       
8174 +       return NF_ACCEPT;
8175 +}
8176 +
8177 +static unsigned int talk_help(struct ip_conntrack *ct,
8178 +                             struct ip_conntrack_expect *exp,
8179 +                             struct ip_nat_info *info,
8180 +                             enum ip_conntrack_info ctinfo,
8181 +                             unsigned int hooknum,
8182 +                             struct sk_buff **pskb,
8183 +                             int talk_port)
8184 +{
8185 +       struct iphdr *iph = (*pskb)->nh.iph;
8186 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8187 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8188 +       char *data = (char *)udph + sizeof(struct udphdr);
8189 +       int dir;
8190 +
8191 +       /* Only mangle things once: original direction in POST_ROUTING
8192 +          and reply direction on PRE_ROUTING. */
8193 +       dir = CTINFO2DIR(ctinfo);
8194 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8195 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8196 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8197 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8198 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8199 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8200 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8201 +               return NF_ACCEPT;
8202 +       }
8203 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8204 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8205 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8206 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8207 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8208 +              NIPQUAD(iph->saddr), ntohs(udph->source),
8209 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
8210 +              talk_port);
8211 +
8212 +       /* Because conntrack does not drop packets, checking must be repeated here... */
8213 +       if (talk_port == TALK_PORT) {
8214 +               if (dir == IP_CT_DIR_ORIGINAL
8215 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8216 +                       return talk_help_msg(ct, pskb,
8217 +                                            ((struct talk_msg *)data)->type, 
8218 +                                            &(((struct talk_msg *)data)->addr),
8219 +                                            &(((struct talk_msg *)data)->ctl_addr));
8220 +               else if (dir == IP_CT_DIR_REPLY
8221 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8222 +                       return talk_help_response(ct, exp, pskb,
8223 +                                                 ((struct talk_response *)data)->type, 
8224 +                                                 ((struct talk_response *)data)->answer,
8225 +                                                 &(((struct talk_response *)data)->addr));
8226 +               else {  
8227 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8228 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
8229 +                              (unsigned)udplen - sizeof(struct udphdr), 
8230 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8231 +                       return NF_DROP;
8232 +               }
8233 +       } else {
8234 +               if (dir == IP_CT_DIR_ORIGINAL) {
8235 +                       if (ntalk
8236 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8237 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8238 +                               return talk_help_msg(ct, pskb,
8239 +                                                    ((struct ntalk_msg *)data)->type, 
8240 +                                                    &(((struct ntalk_msg *)data)->addr),
8241 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
8242 +                       else if (ntalk2
8243 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8244 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8245 +                                && udplen == sizeof(struct udphdr) 
8246 +                                             + sizeof(struct ntalk2_msg) 
8247 +                                             + ((struct ntalk2_msg *)data)->extended)
8248 +                               return talk_help_msg(ct, pskb,
8249 +                                                    ((struct ntalk2_msg *)data)->type, 
8250 +                                                    &(((struct ntalk2_msg *)data)->addr),
8251 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
8252 +                       else {
8253 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
8254 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8255 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8256 +                               return NF_DROP;
8257 +                       }
8258 +               } else {
8259 +                       if (ntalk
8260 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8261 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8262 +                               return talk_help_response(ct, exp, pskb,
8263 +                                                         ((struct ntalk_response *)data)->type, 
8264 +                                                         ((struct ntalk_response *)data)->answer,
8265 +                                                         &(((struct ntalk_response *)data)->addr));
8266 +                       else if (ntalk2
8267 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8268 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8269 +                               return talk_help_response(ct, exp, pskb,
8270 +                                                         ((struct ntalk2_response *)data)->type, 
8271 +                                                         ((struct ntalk2_response *)data)->answer,
8272 +                                                         &(((struct ntalk2_response *)data)->addr));
8273 +                       else {
8274 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
8275 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8276 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8277 +                               return NF_DROP;
8278 +                       }
8279 +               }
8280 +       }
8281 +}
8282 +
8283 +static unsigned int help(struct ip_conntrack *ct,
8284 +                        struct ip_conntrack_expect *exp,
8285 +                        struct ip_nat_info *info,
8286 +                        enum ip_conntrack_info ctinfo,
8287 +                        unsigned int hooknum,
8288 +                        struct sk_buff **pskb)
8289 +{
8290 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8291 +}
8292 +
8293 +static unsigned int nhelp(struct ip_conntrack *ct,
8294 +                         struct ip_conntrack_expect *exp,
8295 +                         struct ip_nat_info *info,
8296 +                         enum ip_conntrack_info ctinfo,
8297 +                         unsigned int hooknum,
8298 +                         struct sk_buff **pskb)
8299 +{
8300 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8301 +}
8302 +
8303 +static unsigned int
8304 +talk_nat_expected(struct sk_buff **pskb,
8305 +                 unsigned int hooknum,
8306 +                 struct ip_conntrack *ct,
8307 +                 struct ip_nat_info *info);
8308 +
8309 +static struct ip_nat_helper talk_helpers[2] = 
8310 +       { { { NULL, NULL },
8311 +            "talk",                                    /* name */
8312 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8313 +            THIS_MODULE,                               /* module */
8314 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8315 +              { 0, { 0 }, IPPROTO_UDP } },
8316 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8317 +              { 0, { 0 }, 0xFFFF } },
8318 +            help,                                      /* helper */
8319 +            talk_nat_expected },                       /* expectfn */
8320 +         { { NULL, NULL },
8321 +            "ntalk",                                   /* name */
8322 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8323 +            THIS_MODULE,                                       /* module */
8324 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8325 +              { 0, { 0 }, IPPROTO_UDP } },
8326 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8327 +              { 0, { 0 }, 0xFFFF } },
8328 +            nhelp,                                     /* helper */
8329 +            talk_nat_expected }                                /* expectfn */
8330 +       };
8331 +          
8332 +static unsigned int
8333 +talk_nat_expected(struct sk_buff **pskb,
8334 +                 unsigned int hooknum,
8335 +                 struct ip_conntrack *ct,
8336 +                 struct ip_nat_info *info)
8337 +{
8338 +       struct ip_nat_multi_range mr;
8339 +       u_int32_t newdstip, newsrcip, newip;
8340 +       u_int16_t port;
8341 +       unsigned int ret;
8342 +       
8343 +       struct ip_conntrack *master = master_ct(ct);
8344 +
8345 +       IP_NF_ASSERT(info);
8346 +       IP_NF_ASSERT(master);
8347 +
8348 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8349 +
8350 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8351 +
8352 +       LOCK_BH(&ip_talk_lock);
8353 +       port = ct->master->help.exp_talk_info.port;
8354 +       UNLOCK_BH(&ip_talk_lock);
8355 +
8356 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8357 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8358 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8359 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8360 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8361 +              ct, master);
8362 +
8363 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8364 +               /* Callee client -> caller server */
8365 +#ifdef IP_NAT_TALK_DEBUG
8366 +               struct iphdr *iph = (*pskb)->nh.iph;
8367 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
8368 +
8369 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8370 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
8371 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
8372 +#endif
8373 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8374 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8375 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8376 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8377 +       } else {
8378 +               /* Callee client -> caller client */
8379 +#ifdef IP_NAT_TALK_DEBUG
8380 +               struct iphdr *iph = (*pskb)->nh.iph;
8381 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8382 +
8383 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8384 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
8385 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
8386 +#endif
8387 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8388 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8389 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8390 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8391 +       }
8392 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8393 +               newip = newsrcip;
8394 +       else
8395 +               newip = newdstip;
8396 +
8397 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8398 +
8399 +       mr.rangesize = 1;
8400 +       /* We don't want to manip the per-protocol, just the IPs... */
8401 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8402 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8403 +       
8404 +       /* ... unless we're doing a MANIP_DST, in which case, make
8405 +          sure we map to the correct port */
8406 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8407 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8408 +               mr.range[0].min = mr.range[0].max
8409 +                       = ((union ip_conntrack_manip_proto)
8410 +                               { .udp = { port } });
8411 +       }
8412 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
8413 +
8414 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8415 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8416 +               /* NAT expectfn called with ip_nat_lock write-locked */
8417 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
8418 +       }
8419 +       return ret;
8420 +}
8421 +
8422 +static int __init init(void)
8423 +{
8424 +       int ret = 0;
8425 +
8426 +       if (talk > 0) {
8427 +               ret = ip_nat_helper_register(&talk_helpers[0]);
8428 +
8429 +               if (ret != 0)
8430 +                       return ret;
8431 +       }
8432 +       if (ntalk > 0 || ntalk2 > 0) {
8433 +               ret = ip_nat_helper_register(&talk_helpers[1]);
8434 +
8435 +               if (ret != 0 && talk > 0)
8436 +                       ip_nat_helper_unregister(&talk_helpers[0]);
8437 +       }
8438 +       return ret;
8439 +}
8440 +
8441 +static void __exit fini(void)
8442 +{
8443 +       if (talk > 0)
8444 +               ip_nat_helper_unregister(&talk_helpers[0]);
8445 +       if (ntalk > 0 || ntalk2 > 0)
8446 +               ip_nat_helper_unregister(&talk_helpers[1]);
8447 +}
8448 +
8449 +module_init(init);
8450 +module_exit(fini);
8451 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c
8452 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c  2004-04-29 11:24:39.000000000 +0200
8453 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c      2004-04-29 11:17:15.000000000 +0200
8454 @@ -29,6 +29,14 @@
8455  
8456  #include <linux/netfilter_ipv4/ip_tables.h>
8457  
8458 +static const char *hooknames[] = { 
8459 +       [NF_IP_PRE_ROUTING] "PREROUTING",
8460 +       [NF_IP_LOCAL_IN] "INPUT",
8461 +       [NF_IP_FORWARD] "FORWARD",
8462 +       [NF_IP_LOCAL_OUT] "OUTPUT",
8463 +       [NF_IP_POST_ROUTING] "POSTROUTING",
8464 +};
8465 +
8466  MODULE_LICENSE("GPL");
8467  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8468  MODULE_DESCRIPTION("IPv4 packet filter");
8469 @@ -326,6 +334,12 @@
8470  
8471                         t = ipt_get_target(e);
8472                         IP_NF_ASSERT(t->u.kernel.target);
8473 +
8474 +                       /* The packet traced and the rule isn't an unconditional return/END. */
8475 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {       
8476 +                               nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8477 +                                             table->name, e->chainname, e->rulenum);
8478 +                       }
8479                         /* Standard target? */
8480                         if (!t->u.kernel.target->target) {
8481                                 int v;
8482 @@ -352,7 +366,6 @@
8483                                         /* set back pointer to next entry */
8484                                         back = next;
8485                                 }
8486 -
8487                                 e = get_entry(table_base, v);
8488                         } else {
8489                                 /* Targets which reenter must return
8490 @@ -478,6 +491,29 @@
8491         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8492  }
8493  
8494 +static inline int
8495 +find_error_target(struct ipt_entry *s, 
8496 +                 struct ipt_entry *e,
8497 +                 char **chainname)
8498 +{
8499 +       struct ipt_entry_target *t;
8500 +       static struct ipt_entry *found = NULL;
8501 +
8502 +       if (s == e) {
8503 +               if (!found)
8504 +                       return 0;
8505 +               t = ipt_get_target(found);
8506 +               if (strcmp(t->u.user.name, 
8507 +                          IPT_ERROR_TARGET) == 0) {
8508 +                       *chainname = t->data;
8509 +                       return 1;
8510 +               }
8511 +       } else
8512 +               found = s;
8513 +       
8514 +       return 0;
8515 +}
8516 +
8517  /* All zeroes == unconditional rule. */
8518  static inline int
8519  unconditional(const struct ipt_ip *ip)
8520 @@ -497,6 +533,8 @@
8521  mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
8522  {
8523         unsigned int hook;
8524 +       char *chainname = NULL;
8525 +       u_int32_t rulenum;
8526  
8527         /* No recursion; use packet counter to save back ptrs (reset
8528            to 0 as we leave), and comefrom to save source hook bitmask */
8529 @@ -510,6 +548,8 @@
8530  
8531                 /* Set initial back pointer. */
8532                 e->counters.pcnt = pos;
8533 +               rulenum = 1;
8534 +               chainname = (char *) hooknames[hook];
8535  
8536                 for (;;) {
8537                         struct ipt_standard_target *t
8538 @@ -522,6 +562,8 @@
8539                         }
8540                         e->comefrom
8541                                 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
8542 +                       e->rulenum = rulenum++;
8543 +                       e->chainname = chainname;
8544  
8545                         /* Unconditional return/END. */
8546                         if (e->target_offset == sizeof(struct ipt_entry)
8547 @@ -531,6 +573,10 @@
8548                             && unconditional(&e->ip)) {
8549                                 unsigned int oldpos, size;
8550  
8551 +                               /* Set unconditional rulenum to zero. */
8552 +                               e->rulenum = 0;
8553 +                               e->counters.bcnt = 0;
8554 +
8555                                 /* Return: backtrack through the last
8556                                    big jump. */
8557                                 do {
8558 @@ -556,6 +602,11 @@
8559                                                 (newinfo->entries + pos);
8560                                 } while (oldpos == pos + e->next_offset);
8561  
8562 +                               /* Restore chainname, rulenum. */
8563 +                               chainname = e->chainname;
8564 +                               rulenum = e->counters.bcnt;
8565 +                               e->counters.bcnt = 0;
8566 +
8567                                 /* Move along one */
8568                                 size = e->next_offset;
8569                                 e = (struct ipt_entry *)
8570 @@ -571,6 +622,17 @@
8571                                         /* This a jump; chase it. */
8572                                         duprintf("Jump rule %u -> %u\n",
8573                                                  pos, newpos);
8574 +                                       e->counters.bcnt = rulenum++;
8575 +                                       rulenum = 1;
8576 +                                       e = (struct ipt_entry *)
8577 +                                               (newinfo->entries + newpos);
8578 +                                       if (IPT_ENTRY_ITERATE(newinfo->entries,
8579 +                                                             newinfo->size,
8580 +                                                             find_error_target,
8581 +                                                             e, &chainname) == 0) {
8582 +                                               printk("ip_tables: table screwed up!\n");
8583 +                                               return 0;
8584 +                                       }
8585                                 } else {
8586                                         /* ... this is a fallthru */
8587                                         newpos = pos + e->next_offset;
8588 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
8589 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c       1970-01-01 01:00:00.000000000 +0100
8590 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c   2004-04-29 11:10:59.000000000 +0200
8591 @@ -0,0 +1,118 @@
8592 +/* This kernel module is used to modify the connection mark values, or
8593 + * to optionally restore the skb nfmark from the connection mark
8594 + *
8595 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8596 + * by Henrik Nordstrom <hno@marasystems.com>
8597 + *
8598 + * This program is free software; you can redistribute it and/or modify
8599 + * it under the terms of the GNU General Public License as published by
8600 + * the Free Software Foundation; either version 2 of the License, or
8601 + * (at your option) any later version.
8602 + *
8603 + * This program is distributed in the hope that it will be useful,
8604 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8605 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8606 + * GNU General Public License for more details.
8607 + *
8608 + * You should have received a copy of the GNU General Public License
8609 + * along with this program; if not, write to the Free Software
8610 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
8611 + */
8612 +#include <linux/module.h>
8613 +#include <linux/skbuff.h>
8614 +#include <linux/ip.h>
8615 +#include <net/checksum.h>
8616 +
8617 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8618 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
8619 +MODULE_LICENSE("GPL");
8620 +
8621 +#include <linux/netfilter_ipv4/ip_tables.h>
8622 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
8623 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8624 +
8625 +static unsigned int
8626 +target(struct sk_buff **pskb,
8627 +       const struct net_device *in,
8628 +       const struct net_device *out,
8629 +       unsigned int hooknum,
8630 +       const void *targinfo,
8631 +       void *userinfo)
8632 +{
8633 +       const struct ipt_connmark_target_info *markinfo = targinfo;
8634 +       unsigned long diff;
8635 +       unsigned long nfmark;
8636 +       unsigned long newmark;
8637 +
8638 +       enum ip_conntrack_info ctinfo;
8639 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
8640 +       if (ct) {
8641 +           switch(markinfo->mode) {
8642 +           case IPT_CONNMARK_SET:
8643 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
8644 +               if (newmark != ct->mark)
8645 +                   ct->mark = newmark;
8646 +               break;
8647 +           case IPT_CONNMARK_SAVE:
8648 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
8649 +               if (ct->mark != newmark)
8650 +                   ct->mark = newmark;
8651 +               break;
8652 +           case IPT_CONNMARK_RESTORE:
8653 +               nfmark = (*pskb)->nfmark;
8654 +               diff = (ct->mark ^ nfmark & markinfo->mask);
8655 +               if (diff != 0) {
8656 +                   (*pskb)->nfmark = nfmark ^ diff;
8657 +                   (*pskb)->nfcache |= NFC_ALTERED;
8658 +               }
8659 +               break;
8660 +           }
8661 +       }
8662 +
8663 +       return IPT_CONTINUE;
8664 +}
8665 +
8666 +static int
8667 +checkentry(const char *tablename,
8668 +          const struct ipt_entry *e,
8669 +          void *targinfo,
8670 +          unsigned int targinfosize,
8671 +          unsigned int hook_mask)
8672 +{
8673 +       struct ipt_connmark_target_info *matchinfo = targinfo;
8674 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
8675 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
8676 +                      targinfosize,
8677 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
8678 +               return 0;
8679 +       }
8680 +
8681 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
8682 +           if (strcmp(tablename, "mangle") != 0) {
8683 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8684 +                   return 0;
8685 +           }
8686 +       }
8687 +
8688 +       return 1;
8689 +}
8690 +
8691 +static struct ipt_target ipt_connmark_reg = {
8692 +       .name = "CONNMARK",
8693 +       .target = &target,
8694 +       .checkentry = &checkentry,
8695 +       .me = THIS_MODULE
8696 +};
8697 +
8698 +static int __init init(void)
8699 +{
8700 +       return ipt_register_target(&ipt_connmark_reg);
8701 +}
8702 +
8703 +static void __exit fini(void)
8704 +{
8705 +       ipt_unregister_target(&ipt_connmark_reg);
8706 +}
8707 +
8708 +module_init(init);
8709 +module_exit(fini);
8710 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c
8711 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
8712 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c     2004-04-29 11:17:03.000000000 +0200
8713 @@ -0,0 +1,81 @@
8714 +/* This is a module which is used for setting the NFMARK field of an skb. */
8715 +#include <linux/module.h>
8716 +#include <linux/skbuff.h>
8717 +#include <linux/ip.h>
8718 +#include <net/checksum.h>
8719 +
8720 +#include <linux/netfilter_ipv4/ip_tables.h>
8721 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
8722 +
8723 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
8724 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
8725 +MODULE_LICENSE("GPL");
8726 +
8727 +static unsigned int
8728 +target(struct sk_buff **pskb,
8729 +       const struct net_device *in,
8730 +       const struct net_device *out,
8731 +       unsigned int hooknum,
8732 +       const void *targinfo,
8733 +       void *userinfo)
8734 +{
8735 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
8736 +       struct iphdr *iph = (*pskb)->nh.iph;
8737 +       unsigned long mark;
8738 +
8739 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
8740 +               mark = (unsigned long) ntohl(iph->saddr);
8741 +       else
8742 +               mark = (unsigned long) ntohl(iph->daddr);
8743 +
8744 +       mark &= ipmarkinfo->andmask;
8745 +       mark |= ipmarkinfo->ormask;
8746 +       
8747 +       if ((*pskb)->nfmark != mark) {
8748 +               (*pskb)->nfmark = mark;
8749 +               (*pskb)->nfcache |= NFC_ALTERED;
8750 +       }
8751 +       return IPT_CONTINUE;
8752 +}
8753 +
8754 +static int
8755 +checkentry(const char *tablename,
8756 +          const struct ipt_entry *e,
8757 +           void *targinfo,
8758 +           unsigned int targinfosize,
8759 +           unsigned int hook_mask)
8760 +{
8761 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
8762 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
8763 +                      targinfosize,
8764 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
8765 +               return 0;
8766 +       }
8767 +
8768 +       if (strcmp(tablename, "mangle") != 0) {
8769 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8770 +               return 0;
8771 +       }
8772 +
8773 +       return 1;
8774 +}
8775 +
8776 +static struct ipt_target ipt_ipmark_reg = { 
8777 +       .name = "IPMARK",
8778 +       .target = target,
8779 +       .checkentry = checkentry,
8780 +       .me = THIS_MODULE
8781 +};
8782 +
8783 +static int __init init(void)
8784 +{
8785 +       return ipt_register_target(&ipt_ipmark_reg);
8786 +}
8787 +
8788 +static void __exit fini(void)
8789 +{
8790 +       ipt_unregister_target(&ipt_ipmark_reg);
8791 +}
8792 +
8793 +module_init(init);
8794 +module_exit(fini);
8795 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c
8796 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
8797 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c     2004-04-29 11:17:08.000000000 +0200
8798 @@ -0,0 +1,289 @@
8799 +/* 
8800 + * Kernel module to capture and hold incoming TCP connections using 
8801 + * no local per-connection resources.
8802 + * 
8803 + * Based on ipt_REJECT.c and offering functionality similar to 
8804 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
8805 + * 
8806 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
8807 + * 
8808 + * This program is free software; you can redistribute it and/or modify
8809 + * it under the terms of the GNU General Public License as published by
8810 + * the Free Software Foundation; either version 2 of the License, or
8811 + * (at your option) any later version.
8812 + *
8813 + * This program is distributed in the hope that it will be useful,
8814 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8815 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8816 + * GNU General Public License for more details.
8817 + *
8818 + * You should have received a copy of the GNU General Public License
8819 + * along with this program; if not, write to the Free Software
8820 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8821 + * 
8822 + * Goal:
8823 + * - Allow incoming TCP connections to be established.
8824 + * - Passing data should result in the connection being switched to the 
8825 + *   persist state (0 byte window), in which the remote side stops sending 
8826 + *   data and asks to continue every 60 seconds.
8827 + * - Attempts to shut down the connection should be ignored completely, so 
8828 + *   the remote side ends up having to time it out.
8829 + *
8830 + * This means:
8831 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
8832 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
8833 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
8834 + */
8835 +
8836 +#include <linux/config.h>
8837 +#include <linux/module.h>
8838 +#include <linux/skbuff.h>
8839 +#include <linux/ip.h>
8840 +#include <net/ip.h>
8841 +#include <net/tcp.h>
8842 +#include <net/icmp.h>
8843 +struct in_device;
8844 +#include <net/route.h>
8845 +#include <linux/random.h>
8846 +#include <linux/netfilter_ipv4/ip_tables.h>
8847 +
8848 +#if 0
8849 +#define DEBUGP printk
8850 +#else
8851 +#define DEBUGP(format, args...)
8852 +#endif
8853 +
8854 +MODULE_LICENSE("GPL");
8855 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
8856 +
8857 +/* Stolen from ip_finish_output2 */
8858 +static int ip_direct_send(struct sk_buff *skb)
8859 +{
8860 +       struct dst_entry *dst = skb->dst;
8861 +       struct hh_cache *hh = dst->hh;
8862 +
8863 +       if (hh) {    
8864 +               read_lock_bh(&hh->hh_lock);
8865 +               memcpy(skb->data - 16, hh->hh_data, 16);
8866 +                read_unlock_bh(&hh->hh_lock);
8867 +                skb_push(skb, hh->hh_len);
8868 +                return hh->hh_output(skb);
8869 +        } else if (dst->neighbour)
8870 +                return dst->neighbour->output(skb);
8871 +
8872 +       if (net_ratelimit())
8873 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
8874 +        kfree_skb(skb);
8875 +        return -EINVAL;
8876 +}
8877 +
8878 +
8879 +/* Send reply */
8880 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
8881 +{
8882 +       struct sk_buff *nskb;
8883 +       struct rtable *nrt;
8884 +       struct tcphdr *otcph, *ntcph;
8885 +       unsigned int otcplen;
8886 +       u_int16_t tmp;
8887 +       struct flowi fl = {};
8888 +
8889 +       /* A truncated TCP header isn't going to be useful */
8890 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
8891 +               return;
8892 +
8893 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
8894 +                                  + oskb->nh.iph->ihl);
8895 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
8896 +
8897 +       /* No replies for RST or FIN */
8898 +       if (otcph->rst || otcph->fin)
8899 +               return;
8900 +
8901 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
8902 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
8903 +               return;
8904 +
8905 +       /* Check checksum. */
8906 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
8907 +                        oskb->nh.iph->daddr,
8908 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
8909 +               return;
8910 +
8911 +       /* Copy skb (even if skb is about to be dropped, we can't just
8912 +           clone it because there may be other things, such as tcpdump,
8913 +           interested in it) */
8914 +       nskb = skb_copy(oskb, GFP_ATOMIC);
8915 +       if (!nskb)
8916 +               return;
8917 +
8918 +       /* This packet will not be the same as the other: clear nf fields */
8919 +       nf_conntrack_put(nskb->nfct);
8920 +       nskb->nfct = NULL;
8921 +       nskb->nfcache = 0;
8922 +#ifdef CONFIG_NETFILTER_DEBUG
8923 +       nskb->nf_debug = 0;
8924 +#endif
8925 +
8926 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
8927 +
8928 +       /* Truncate to length (no data) */
8929 +       ntcph->doff = sizeof(struct tcphdr)/4;
8930 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
8931 +       nskb->nh.iph->tot_len = htons(nskb->len);
8932 +
8933 +       /* Swap source and dest */
8934 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
8935 +       tmp = ntcph->source;
8936 +       ntcph->source = ntcph->dest;
8937 +       ntcph->dest = tmp;
8938 +
8939 +       /* Use supplied sequence number or make a new one */
8940 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
8941 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
8942 +                                                       nskb->nh.iph->daddr, 
8943 +                                                       ntcph->source, 
8944 +                                                       ntcph->dest));
8945 +
8946 +       /* Our SYN-ACKs must have a >0 window */
8947 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
8948 +
8949 +       ntcph->urg_ptr = 0;
8950 +
8951 +       /* Reset flags */
8952 +       ((u_int8_t *)ntcph)[13] = 0;
8953 +
8954 +       if (otcph->syn && otcph->ack) {
8955 +               ntcph->rst = 1;
8956 +               ntcph->ack_seq = 0;
8957 +       } else {
8958 +               ntcph->syn = otcph->syn;
8959 +               ntcph->ack = 1;
8960 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
8961 +       }
8962 +
8963 +       /* Adjust TCP checksum */
8964 +       ntcph->check = 0;
8965 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
8966 +                                  nskb->nh.iph->saddr,
8967 +                                  nskb->nh.iph->daddr,
8968 +                                  csum_partial((char *)ntcph,
8969 +                                               sizeof(struct tcphdr), 0));
8970 +
8971 +       /* Adjust IP TTL */
8972 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
8973 +
8974 +       /* Set DF, id = 0 */
8975 +       nskb->nh.iph->frag_off = htons(IP_DF);
8976 +       nskb->nh.iph->id = 0;
8977 +
8978 +       /* Adjust IP checksum */
8979 +       nskb->nh.iph->check = 0;
8980 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
8981 +                                          nskb->nh.iph->ihl);
8982 +
8983 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
8984 +       fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
8985 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
8986 +       fl.oif = 0;
8987 +       if (ip_route_output_key(&nrt, &fl) != 0)
8988 +               goto free_nskb;
8989 +
8990 +       dst_release(nskb->dst);
8991 +       nskb->dst = &nrt->u.dst;
8992 +
8993 +       /* "Never happens" */
8994 +       if (nskb->len > dst_pmtu(nskb->dst))
8995 +               goto free_nskb;
8996 +
8997 +       ip_direct_send (nskb);
8998 +
8999 +       return;
9000 +
9001 + free_nskb:
9002 +       kfree_skb(nskb);
9003 +}
9004 +
9005 +
9006 +static unsigned int tarpit(struct sk_buff **pskb,
9007 +                          const struct net_device *in,
9008 +                          const struct net_device *out,
9009 +                          unsigned int hooknum,
9010 +                          const void *targinfo,
9011 +                          void *userinfo)
9012 +{
9013 +       struct sk_buff *skb = *pskb;
9014 +       struct rtable *rt = (struct rtable*)skb->dst;
9015 +
9016 +       /* Do we have an input route cache entry? */
9017 +       if (!rt)
9018 +               return NF_DROP;
9019 +
9020 +        /* No replies to physical multicast/broadcast */
9021 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
9022 +               return NF_DROP;
9023 +
9024 +        /* Now check at the protocol level */
9025 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
9026 +                return NF_DROP;
9027 +
9028 +       /* Our naive response construction doesn't deal with IP
9029 +           options, and probably shouldn't try. */
9030 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
9031 +               return NF_DROP;
9032 +
9033 +        /* We aren't interested in fragments */
9034 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
9035 +                return NF_DROP;
9036 +
9037 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
9038 +
9039 +       return NF_DROP;
9040 +}
9041 +
9042 +
9043 +static int check(const char *tablename,
9044 +                const struct ipt_entry *e,
9045 +                void *targinfo,
9046 +                unsigned int targinfosize,
9047 +                unsigned int hook_mask)
9048 +{
9049 +       /* Only allow these for input/forward packet filtering. */
9050 +       if (strcmp(tablename, "filter") != 0) {
9051 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
9052 +               return 0;
9053 +       }
9054 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
9055 +                           | (1 << NF_IP_FORWARD))) != 0) {
9056 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
9057 +               return 0;
9058 +       }
9059 +
9060 +       /* Must specify that it's a TCP packet */
9061 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
9062 +               DEBUGP("TARPIT: not valid for non-tcp\n");
9063 +               return 0;
9064 +       }
9065 +
9066 +       return 1;
9067 +}
9068 +
9069 +static struct ipt_target ipt_tarpit_reg = { 
9070 +       .name = "TARPIT",
9071 +       .target = tarpit,
9072 +       .checkentry = check,
9073 +       .me = THIS_MODULE
9074 +};
9075 +
9076 +static int __init init(void)
9077 +{
9078 +       return ipt_register_target(&ipt_tarpit_reg);
9079 +}
9080 +
9081 +static void __exit fini(void)
9082 +{
9083 +       ipt_unregister_target(&ipt_tarpit_reg);
9084 +}
9085 +
9086 +module_init(init);
9087 +module_exit(fini);
9088 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c
9089 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c  1970-01-01 01:00:00.000000000 +0100
9090 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c      2004-04-29 11:17:15.000000000 +0200
9091 @@ -0,0 +1,64 @@
9092 +/* This is a module which is used for setting 
9093 + * the NFC_TRACE flag in the nfcache field of an skb. 
9094 + */
9095 +#include <linux/module.h>
9096 +#include <linux/skbuff.h>
9097 +
9098 +#include <linux/netfilter_ipv4/ip_tables.h>
9099 +
9100 +static unsigned int
9101 +target(struct sk_buff **pskb,
9102 +       const struct net_device *in,
9103 +       const struct net_device *out,
9104 +       unsigned int hooknum,
9105 +       const void *targinfo,
9106 +       void *userinfo)
9107 +{
9108 +       (*pskb)->nfcache |= NFC_TRACE;
9109 +       return IPT_CONTINUE;
9110 +}
9111 +
9112 +static int
9113 +checkentry(const char *tablename,
9114 +          const struct ipt_entry *e,
9115 +           void *targinfo,
9116 +           unsigned int targinfosize,
9117 +           unsigned int hook_mask)
9118 +{
9119 +       if (targinfosize != 0) {
9120 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
9121 +                      targinfosize);
9122 +               return 0;
9123 +       }
9124 +
9125 +       if (strcmp(tablename, "raw") != 0) {
9126 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
9127 +               return 0;
9128 +       }
9129 +
9130 +       return 1;
9131 +}
9132 +
9133 +static struct ipt_target ipt_trace_reg = { 
9134 +       .name = "TRACE", 
9135 +       .target = target, 
9136 +       .checkentry = checkentry, 
9137 +       .me = THIS_MODULE
9138 +};
9139 +
9140 +static int __init init(void)
9141 +{
9142 +       if (ipt_register_target(&ipt_trace_reg))
9143 +               return -EINVAL;
9144 +
9145 +       return 0;
9146 +}
9147 +
9148 +static void __exit fini(void)
9149 +{
9150 +       ipt_unregister_target(&ipt_trace_reg);
9151 +}
9152 +
9153 +module_init(init);
9154 +module_exit(fini);
9155 +MODULE_LICENSE("GPL");
9156 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c
9157 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c    1970-01-01 01:00:00.000000000 +0100
9158 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c        2004-04-29 11:17:18.000000000 +0200
9159 @@ -0,0 +1,117 @@
9160 +/* XOR target for IP tables
9161 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9162 + * Based on ipt_TTL.c
9163 + *
9164 + * Version 1.0
9165 + *
9166 + * This software is distributed under the terms of GNU GPL
9167 + */
9168 +
9169 +#include <linux/module.h>
9170 +#include <linux/skbuff.h>
9171 +#include <linux/ip.h>
9172 +#include <linux/tcp.h>
9173 +#include <linux/udp.h>
9174 +
9175 +#include <linux/netfilter_ipv4/ip_tables.h>
9176 +#include <linux/netfilter_ipv4/ipt_XOR.h>
9177 +
9178 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9179 +MODULE_DESCRIPTION("IP tables XOR module");
9180 +MODULE_LICENSE("GPL");
9181 +
9182 +static unsigned int 
9183 +ipt_xor_target(struct sk_buff **pskb, 
9184 +               const struct net_device *in, const struct net_device *out, 
9185 +               unsigned int hooknum, const void *targinfo, void *userinfo)
9186 +{
9187 +       struct ipt_XOR_info *info = (void *) targinfo;
9188 +       struct iphdr *iph;
9189 +       struct tcphdr *tcph;
9190 +       struct udphdr *udph;
9191 +       int i, j, k;
9192 +
9193 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
9194 +               return NF_DROP;
9195 +
9196 +       iph = (*pskb)->nh.iph;
9197 +  
9198 +       if (iph->protocol == IPPROTO_TCP) {
9199 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9200 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9201 +                       for (k=0; k<=info->block_size; k++) {
9202 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
9203 +                                               info->key[j];
9204 +                               i++;
9205 +                       }
9206 +                       j++;
9207 +                       if (info->key[j] == 0x00)
9208 +                               j = 0;
9209 +               }
9210 +       } else if (iph->protocol == IPPROTO_UDP) {
9211 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9212 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9213 +                       for (k=0; k<=info->block_size; k++) {
9214 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
9215 +                                               info->key[j];
9216 +                               i++;
9217 +                       }
9218 +                       j++;
9219 +                       if (info->key[j] == 0x00)
9220 +                               j = 0;
9221 +               }
9222 +       }
9223 +  
9224 +       return IPT_CONTINUE;
9225 +}
9226 +
9227 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9228 +               void *targinfo, unsigned int targinfosize, 
9229 +               unsigned int hook_mask)
9230 +{
9231 +       struct ipt_XOR_info *info = targinfo;
9232 +
9233 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9234 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
9235 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9236 +               return 0;
9237 +       }       
9238 +
9239 +       if (strcmp(tablename, "mangle")) {
9240 +               printk(KERN_WARNING "XOR: can only be called from"
9241 +                               "\"mangle\" table, not \"%s\"\n", tablename);
9242 +               return 0; 
9243 +       }
9244 +
9245 +       if (!strcmp(info->key, "")) {
9246 +               printk(KERN_WARNING "XOR: You must specify a key");
9247 +               return 0;
9248 +       }
9249 +
9250 +       if (info->block_size == 0) {
9251 +               printk(KERN_WARNING "XOR: You must specify a block-size");
9252 +               return 0;
9253 +       }
9254 +
9255 +       return 1;
9256 +}
9257 +
9258 +static struct ipt_target ipt_XOR = { 
9259 +       .name = "XOR",
9260 +       .target = ipt_xor_target, 
9261 +       .checkentry = ipt_xor_checkentry,
9262 +       .me = THIS_MODULE,
9263 +};
9264 +
9265 +static int __init init(void)
9266 +{
9267 +       return ipt_register_target(&ipt_XOR);
9268 +}
9269 +
9270 +static void __exit fini(void)
9271 +{
9272 +       ipt_unregister_target(&ipt_XOR);
9273 +}
9274 +
9275 +module_init(init);
9276 +module_exit(fini);
9277 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c
9278 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c       1970-01-01 01:00:00.000000000 +0100
9279 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c   2004-04-29 11:17:23.000000000 +0200
9280 @@ -0,0 +1,68 @@
9281 +/*
9282 + *  iptables module to match inet_addr_type() of an ip.
9283 + */
9284 +
9285 +#include <linux/module.h>
9286 +#include <linux/skbuff.h>
9287 +#include <linux/netdevice.h>
9288 +#include <net/route.h>
9289 +
9290 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
9291 +#include <linux/netfilter_ipv4/ip_tables.h>
9292 +
9293 +MODULE_LICENSE("GPL");
9294 +
9295 +static inline int match_type(u_int32_t addr, u_int16_t mask)
9296 +{
9297 +       return !!(mask & (1 << inet_addr_type(addr)));
9298 +}
9299 +
9300 +static int match(const struct sk_buff *skb, const struct net_device *in,
9301 +                const struct net_device *out, const void *matchinfo,
9302 +                int offset, int *hotdrop)
9303 +{
9304 +       const struct ipt_addrtype_info *info = matchinfo;
9305 +       const struct iphdr *iph = skb->nh.iph;
9306 +       int ret = 1;
9307 +
9308 +       if (info->source)
9309 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
9310 +       if (info->dest)
9311 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9312 +       
9313 +       return ret;
9314 +}
9315 +
9316 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9317 +                     void *matchinfo, unsigned int matchsize,
9318 +                     unsigned int hook_mask)
9319 +{
9320 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9321 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9322 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9323 +               return 0;
9324 +       }
9325 +
9326 +       return 1;
9327 +}
9328 +
9329 +static struct ipt_match addrtype_match = { 
9330 +       .name = "addrtype",
9331 +       .match = match,
9332 +       .checkentry = checkentry,
9333 +       .me = THIS_MODULE
9334 +};
9335 +
9336 +static int __init init(void)
9337 +{
9338 +       return ipt_register_match(&addrtype_match);
9339 +}
9340 +
9341 +static void __exit fini(void)
9342 +{
9343 +       ipt_unregister_match(&addrtype_match);
9344 +
9345 +}
9346 +
9347 +module_init(init);
9348 +module_exit(fini);
9349 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c
9350 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c       1970-01-01 01:00:00.000000000 +0100
9351 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c   2004-04-29 11:10:59.000000000 +0200
9352 @@ -0,0 +1,81 @@
9353 +/* This kernel module matches connection mark values set by the
9354 + * CONNMARK target
9355 + *
9356 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9357 + * by Henrik Nordstrom <hno@marasystems.com>
9358 + *
9359 + * This program is free software; you can redistribute it and/or modify
9360 + * it under the terms of the GNU General Public License as published by
9361 + * the Free Software Foundation; either version 2 of the License, or
9362 + * (at your option) any later version.
9363 + *
9364 + * This program is distributed in the hope that it will be useful,
9365 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9366 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9367 + * GNU General Public License for more details.
9368 + *
9369 + * You should have received a copy of the GNU General Public License
9370 + * along with this program; if not, write to the Free Software
9371 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
9372 + */
9373 +
9374 +#include <linux/module.h>
9375 +#include <linux/skbuff.h>
9376 +
9377 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9378 +MODULE_DESCRIPTION("IP tables connmark match module");
9379 +MODULE_LICENSE("GPL");
9380 +
9381 +#include <linux/netfilter_ipv4/ip_tables.h>
9382 +#include <linux/netfilter_ipv4/ipt_connmark.h>
9383 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9384 +
9385 +static int
9386 +match(const struct sk_buff *skb,
9387 +      const struct net_device *in,
9388 +      const struct net_device *out,
9389 +      const void *matchinfo,
9390 +      int offset,
9391 +      int *hotdrop)
9392 +{
9393 +       const struct ipt_connmark_info *info = matchinfo;
9394 +       enum ip_conntrack_info ctinfo;
9395 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
9396 +       if (!ct)
9397 +               return 0;
9398 +
9399 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
9400 +}
9401 +
9402 +static int
9403 +checkentry(const char *tablename,
9404 +          const struct ipt_ip *ip,
9405 +          void *matchinfo,
9406 +          unsigned int matchsize,
9407 +          unsigned int hook_mask)
9408 +{
9409 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
9410 +               return 0;
9411 +
9412 +       return 1;
9413 +}
9414 +
9415 +static struct ipt_match connmark_match = {
9416 +       .name = "connmark",
9417 +       .match = &match,
9418 +       .checkentry = &checkentry,
9419 +       .me = THIS_MODULE
9420 +};
9421 +
9422 +static int __init init(void)
9423 +{
9424 +       return ipt_register_match(&connmark_match);
9425 +}
9426 +
9427 +static void __exit fini(void)
9428 +{
9429 +       ipt_unregister_match(&connmark_match);
9430 +}
9431 +
9432 +module_init(init);
9433 +module_exit(fini);
9434 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c
9435 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-04-29 11:24:39.000000000 +0200
9436 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c     2004-04-29 11:18:37.000000000 +0200
9437 @@ -71,8 +71,11 @@
9438         DEBUGP("master's name = %s , info->name = %s\n", 
9439                 exp->expectant->helper->name, info->name);
9440  
9441 -       ret ^= !strncmp(exp->expectant->helper->name, info->name, 
9442 -                       strlen(exp->expectant->helper->name));
9443 +       if (info->name[0] == '\0')
9444 +               ret ^= 1;
9445 +       else
9446 +               ret ^= !strncmp(exp->expectant->helper->name, info->name, 
9447 +                               strlen(exp->expectant->helper->name));
9448  out_unlock:
9449         READ_UNLOCK(&ip_conntrack_lock);
9450         return ret;
9451 @@ -92,10 +95,6 @@
9452         if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
9453                 return 0;
9454  
9455 -       /* verify that we actually should match anything */
9456 -       if ( strlen(info->name) == 0 )
9457 -               return 0;
9458 -       
9459         return 1;
9460  }
9461  
9462 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c
9463 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c  2004-04-28 03:36:37.000000000 +0200
9464 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c      2004-04-29 11:19:32.000000000 +0200
9465 @@ -6,12 +6,19 @@
9466   * This program is free software; you can redistribute it and/or modify
9467   * it under the terms of the GNU General Public License version 2 as
9468   * published by the Free Software Foundation.
9469 + *
9470 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
9471   */
9472  
9473  #include <linux/module.h>
9474  #include <linux/skbuff.h>
9475  #include <linux/file.h>
9476 +#include <linux/ip.h>
9477 +#include <linux/tcp.h>
9478 +#include <linux/udp.h>
9479  #include <net/sock.h>
9480 +#include <net/tcp.h>
9481 +#include <net/udp.h>
9482  
9483  #include <linux/netfilter_ipv4/ipt_owner.h>
9484  #include <linux/netfilter_ipv4/ip_tables.h>
9485 @@ -21,7 +28,7 @@
9486  MODULE_DESCRIPTION("iptables owner match");
9487  
9488  static int
9489 -match_comm(const struct sk_buff *skb, const char *comm)
9490 +match_comm(const struct sock *sk, const char *comm)
9491  {
9492         struct task_struct *g, *p;
9493         struct files_struct *files;
9494 @@ -38,7 +45,7 @@
9495                         spin_lock(&files->file_lock);
9496                         for (i=0; i < files->max_fds; i++) {
9497                                 if (fcheck_files(files, i) ==
9498 -                                   skb->sk->sk_socket->file) {
9499 +                                   sk->sk_socket->file) {
9500                                         spin_unlock(&files->file_lock);
9501                                         task_unlock(p);
9502                                         read_unlock(&tasklist_lock);
9503 @@ -54,7 +61,7 @@
9504  }
9505  
9506  static int
9507 -match_pid(const struct sk_buff *skb, pid_t pid)
9508 +match_pid(const struct sock *sk, pid_t pid)
9509  {
9510         struct task_struct *p;
9511         struct files_struct *files;
9512 @@ -70,7 +77,7 @@
9513                 spin_lock(&files->file_lock);
9514                 for (i=0; i < files->max_fds; i++) {
9515                         if (fcheck_files(files, i) ==
9516 -                           skb->sk->sk_socket->file) {
9517 +                           sk->sk_socket->file) {
9518                                 spin_unlock(&files->file_lock);
9519                                 task_unlock(p);
9520                                 read_unlock(&tasklist_lock);
9521 @@ -86,10 +93,10 @@
9522  }
9523  
9524  static int
9525 -match_sid(const struct sk_buff *skb, pid_t sid)
9526 +match_sid(const struct sock *sk, pid_t sid)
9527  {
9528         struct task_struct *g, *p;
9529 -       struct file *file = skb->sk->sk_socket->file;
9530 +       struct file *file = sk->sk_socket->file;
9531         int i, found=0;
9532  
9533         read_lock(&tasklist_lock);
9534 @@ -129,41 +136,71 @@
9535        int *hotdrop)
9536  {
9537         const struct ipt_owner_info *info = matchinfo;
9538 +       struct iphdr *iph = skb->nh.iph;
9539 +       struct sock *sk = NULL;
9540 +       int ret = 0;
9541 +
9542 +       if (out) {
9543 +               sk = skb->sk;
9544 +       } else {
9545 +               if (iph->protocol == IPPROTO_TCP) {
9546 +                       struct tcphdr *tcph =
9547 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
9548 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
9549 +                                          iph->daddr, tcph->dest,
9550 +                                          skb->dev->ifindex);
9551 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
9552 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
9553 +                               return ret;
9554 +                       }
9555 +               } else if (iph->protocol == IPPROTO_UDP) {
9556 +                       struct udphdr *udph =
9557 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
9558 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
9559 +                                          udph->dest, skb->dev->ifindex);
9560 +               }
9561 +       }
9562  
9563 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
9564 -               return 0;
9565 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
9566 +               goto out;
9567  
9568         if(info->match & IPT_OWNER_UID) {
9569 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
9570 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
9571                     !!(info->invert & IPT_OWNER_UID))
9572 -                       return 0;
9573 +                       goto out;
9574         }
9575  
9576         if(info->match & IPT_OWNER_GID) {
9577 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
9578 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
9579                     !!(info->invert & IPT_OWNER_GID))
9580 -                       return 0;
9581 +                       goto out;
9582         }
9583  
9584         if(info->match & IPT_OWNER_PID) {
9585 -               if (!match_pid(skb, info->pid) ^
9586 +               if (!match_pid(sk, info->pid) ^
9587                     !!(info->invert & IPT_OWNER_PID))
9588 -                       return 0;
9589 +                       goto out;
9590         }
9591  
9592         if(info->match & IPT_OWNER_SID) {
9593 -               if (!match_sid(skb, info->sid) ^
9594 +               if (!match_sid(sk, info->sid) ^
9595                     !!(info->invert & IPT_OWNER_SID))
9596 -                       return 0;
9597 +                       goto out;
9598         }
9599  
9600         if(info->match & IPT_OWNER_COMM) {
9601 -               if (!match_comm(skb, info->comm) ^
9602 +               if (!match_comm(sk, info->comm) ^
9603                     !!(info->invert & IPT_OWNER_COMM))
9604 -                       return 0;
9605 +                       goto out;
9606         }
9607  
9608 -       return 1;
9609 +       ret = 1;
9610 +
9611 +out:
9612 +       if (in && sk)
9613 +               sock_put(sk);
9614 +
9615 +       return ret;
9616  }
9617  
9618  static int
9619 @@ -173,11 +210,19 @@
9620             unsigned int matchsize,
9621             unsigned int hook_mask)
9622  {
9623 -        if (hook_mask
9624 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
9625 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
9626 -                return 0;
9627 -        }
9628 +       if (hook_mask
9629 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
9630 +           (1 << NF_IP_LOCAL_IN))) {
9631 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
9632 +                      "or POST_ROUTING.\n");
9633 +               return 0;
9634 +       }
9635 +
9636 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
9637 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
9638 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
9639 +               return 0;
9640 +       }
9641  
9642         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
9643                 printk("Matchsize %u != %Zu\n", matchsize,
9644 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c
9645 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
9646 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c     2004-04-29 11:19:41.000000000 +0200
9647 @@ -0,0 +1,176 @@
9648 +/* IP tables module for matching IPsec policy
9649 + *
9650 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
9651 + *
9652 + * This program is free software; you can redistribute it and/or modify
9653 + * it under the terms of the GNU General Public License version 2 as
9654 + * published by the Free Software Foundation.
9655 + */
9656 +
9657 +#include <linux/kernel.h>
9658 +#include <linux/config.h>
9659 +#include <linux/module.h>
9660 +#include <linux/skbuff.h>
9661 +#include <linux/init.h>
9662 +#include <net/xfrm.h>
9663 +
9664 +#include <linux/netfilter_ipv4.h>
9665 +#include <linux/netfilter_ipv4/ipt_policy.h>
9666 +#include <linux/netfilter_ipv4/ip_tables.h>
9667 +
9668 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
9669 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
9670 +MODULE_LICENSE("GPL");
9671 +
9672 +
9673 +static inline int
9674 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
9675 +{
9676 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
9677 +
9678 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
9679 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
9680 +           MISMATCH(proto, x->id.proto) ||
9681 +           MISMATCH(mode, x->props.mode) ||
9682 +           MISMATCH(spi, x->id.spi) ||
9683 +           MISMATCH(reqid, x->props.reqid))
9684 +               return 0;
9685 +       return 1;
9686 +}
9687 +
9688 +static int
9689 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
9690 +{
9691 +       const struct ipt_policy_elem *e;
9692 +       struct sec_path *sp = skb->sp;
9693 +       int strict = info->flags & POLICY_MATCH_STRICT;
9694 +       int i, pos;
9695 +
9696 +       if (sp == NULL)
9697 +               return -1;
9698 +       if (strict && info->len != sp->len)
9699 +               return 0;
9700 +
9701 +       for (i = sp->len - 1; i >= 0; i--) {
9702 +               pos = strict ? i - sp->len + 1 : 0;
9703 +               if (pos >= info->len)
9704 +                       return 0;
9705 +               e = &info->pol[pos];
9706 +
9707 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
9708 +                       if (!strict)
9709 +                               return 1;
9710 +               } else if (strict)
9711 +                       return 0;
9712 +       }
9713 +
9714 +       return strict ? 1 : 0;
9715 +}
9716 +
9717 +static int
9718 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
9719 +{
9720 +       const struct ipt_policy_elem *e;
9721 +       struct dst_entry *dst = skb->dst;
9722 +       int strict = info->flags & POLICY_MATCH_STRICT;
9723 +       int i, pos;
9724 +
9725 +       if (dst->xfrm == NULL)
9726 +               return -1;
9727 +
9728 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
9729 +               pos = strict ? i : 0;
9730 +               if (pos >= info->len)
9731 +                       return 0;
9732 +               e = &info->pol[pos];
9733 +
9734 +               if (match_xfrm_state(dst->xfrm, e)) {
9735 +                       if (!strict)
9736 +                               return 1;
9737 +               } else if (strict)
9738 +                       return 0;
9739 +       }
9740 +
9741 +       return strict ? 1 : 0;
9742 +}
9743 +
9744 +static int match(const struct sk_buff *skb,
9745 +                 const struct net_device *in,
9746 +                 const struct net_device *out,
9747 +                 const void *matchinfo, int offset, int *hotdrop)
9748 +{
9749 +       const struct ipt_policy_info *info = matchinfo;
9750 +       int ret;
9751 +
9752 +       if (info->flags & POLICY_MATCH_IN)
9753 +               ret = match_policy_in(skb, info);
9754 +       else
9755 +               ret = match_policy_out(skb, info);
9756 +
9757 +       if (ret < 0) {
9758 +               if (info->flags & POLICY_MATCH_NONE)
9759 +                       ret = 1;
9760 +               else
9761 +                       ret = 0;
9762 +       } else if (info->flags & POLICY_MATCH_NONE)
9763 +               ret = 0;
9764 +
9765 +       return ret;
9766 +}
9767 +
9768 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9769 +                      void *matchinfo, unsigned int matchsize,
9770 +                      unsigned int hook_mask)
9771 +{
9772 +       struct ipt_policy_info *info = matchinfo;
9773 +
9774 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
9775 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
9776 +                      matchsize, IPT_ALIGN(sizeof(*info)));
9777 +               return 0;
9778 +       }
9779 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
9780 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
9781 +                               "outgoing policy selected\n");
9782 +               return 0;
9783 +       }
9784 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
9785 +           && info->flags & POLICY_MATCH_OUT) {
9786 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
9787 +                               "PRE_ROUTING and INPUT\n");
9788 +               return 0;
9789 +       }
9790 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
9791 +           && info->flags & POLICY_MATCH_IN) {
9792 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
9793 +                               "POST_ROUTING and OUTPUT\n");
9794 +               return 0;
9795 +       }
9796 +       if (info->len > POLICY_MAX_ELEM) {
9797 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
9798 +               return 0;
9799 +       }
9800 +
9801 +       return 1;
9802 +}
9803 +
9804 +static struct ipt_match policy_match =
9805 +{
9806 +       .name           = "policy",
9807 +       .match          = match,
9808 +       .checkentry     = checkentry,
9809 +       .me             = THIS_MODULE,
9810 +};
9811 +
9812 +static int __init init(void)
9813 +{
9814 +       return ipt_register_match(&policy_match);
9815 +}
9816 +
9817 +static void __exit fini(void)
9818 +{
9819 +       ipt_unregister_match(&policy_match);
9820 +}
9821 +
9822 +module_init(init);
9823 +module_exit(fini);
9824 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_rpc.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_rpc.c
9825 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_rpc.c    1970-01-01 01:00:00.000000000 +0100
9826 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_rpc.c        2004-04-29 11:20:02.000000000 +0200
9827 @@ -0,0 +1,428 @@
9828 +/* RPC extension for IP connection matching, Version 2.2
9829 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
9830 + *     - original rpc tracking module
9831 + *     - "recent" connection handling for kernel 2.3+ netfilter
9832 + *
9833 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
9834 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
9835 + *
9836 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
9837 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
9838 + *     - extended matching to support filtering on procedures
9839 + *
9840 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
9841 + *
9842 + *     This program is free software; you can redistribute it and/or
9843 + *     modify it under the terms of the GNU General Public License
9844 + *     as published by the Free Software Foundation; either version
9845 + *     2 of the License, or (at your option) any later version.
9846 + **
9847 + *     Module load syntax:
9848 + *     insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
9849 + *
9850 + *     Please give the ports of all RPC servers you wish to connect to.
9851 + *     If you don't specify ports, the default will be port 111.
9852 + **
9853 + *     Note to all:
9854 + *
9855 + *     RPCs should not be exposed to the internet - ask the Pentagon;
9856 + *
9857 + *       "The unidentified crackers pleaded guilty in July to charges
9858 + *        of juvenile delinquency stemming from a string of Pentagon
9859 + *        network intrusions in February.
9860 + *
9861 + *        The youths, going by the names TooShort and Makaveli, used
9862 + *        a common server security hole to break in, according to
9863 + *        Dane Jasper, owner of the California Internet service
9864 + *        provider, Sonic. They used the hole, known as the 'statd'
9865 + *        exploit, to attempt more than 800 break-ins, Jasper said."
9866 + *
9867 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
9868 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
9869 + **
9870 + */
9871 +
9872 +#include <linux/module.h>
9873 +#include <linux/skbuff.h>
9874 +#include <linux/list.h>
9875 +#include <linux/udp.h>
9876 +#include <linux/tcp.h>
9877 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9878 +#include <linux/netfilter_ipv4/ip_tables.h>
9879 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
9880 +#include <linux/netfilter_ipv4/lockhelp.h>
9881 +#include <linux/netfilter_ipv4/ipt_rpc.h>
9882 +
9883 +#define MAX_PORTS 8
9884 +static int ports[MAX_PORTS];
9885 +static int ports_n_c = 0;
9886 +
9887 +#ifdef MODULE_PARM
9888 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9889 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
9890 +#endif
9891 +
9892 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
9893 +MODULE_DESCRIPTION("RPC connection matching module");
9894 +MODULE_LICENSE("GPL");
9895 +
9896 +#if 0
9897 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
9898 +                                       format, ## args)
9899 +#else
9900 +#define DEBUGP(format, args...)
9901 +#endif
9902 +
9903 +EXPORT_NO_SYMBOLS;
9904 +
9905 +/* vars from ip_conntrack_rpc_tcp */
9906 +extern struct list_head request_p_list_tcp;
9907 +extern struct module *ip_conntrack_rpc_tcp;
9908 +
9909 +/* vars from ip_conntrack_rpc_udp */
9910 +extern struct list_head request_p_list_udp;
9911 +extern struct module *ip_conntrack_rpc_udp;
9912 +
9913 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
9914 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
9915 +
9916 +#define ASSERT_READ_LOCK(x)                                    \
9917 +do {                                                           \
9918 +       if (x == &request_p_list_udp)                           \
9919 +               MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);        \
9920 +       else if (x == &request_p_list_tcp)                      \
9921 +               MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);        \
9922 +} while (0)
9923 +
9924 +#define ASSERT_WRITE_LOCK(x)                                   \
9925 +do {                                                           \
9926 +       if (x == &request_p_list_udp)                           \
9927 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);       \
9928 +       else if (x == &request_p_list_tcp)                      \
9929 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);       \
9930 +} while (0)
9931 +
9932 +#include <linux/netfilter_ipv4/listhelp.h>
9933 +
9934 +const int IPT_RPC_CHAR_LEN = 11;
9935 +
9936 +
9937 +static int k_atoi(char *string)
9938 +{
9939 +       unsigned int result = 0;
9940 +       int maxoctet = IPT_RPC_CHAR_LEN;
9941 +
9942 +       for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
9943 +               if (*string < 0)
9944 +                       return(0);
9945 +               if (*string == 0)
9946 +                       break;
9947 +               if (*string < 48 || *string > 57) {
9948 +                       return(0);
9949 +               }
9950 +               result = result * 10 + ( *string - 48 );
9951 +       }
9952 +       return(result);
9953 +}
9954 +
9955 +
9956 +static int match_rpcs(char *c_procs, int i_procs, int proc)
9957 +{
9958 +       int   proc_ctr;
9959 +       char *proc_ptr;
9960 +       unsigned int proc_num;
9961 +
9962 +       DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
9963 +
9964 +       if (i_procs == -1)
9965 +               return 1;
9966 +
9967 +       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
9968 +
9969 +               proc_ptr = c_procs;
9970 +               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
9971 +               proc_num = k_atoi(proc_ptr);
9972 +
9973 +               if (proc_num == proc)
9974 +                       return 1;
9975 +       }
9976 +
9977 +       return 0;
9978 +}
9979 +
9980 +
9981 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
9982 +                       int *hotdrop, int dir, struct ip_conntrack *ct,
9983 +                       int offset, struct list_head request_p_list)
9984 +{
9985 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
9986 +       struct request_p *req_p;
9987 +       u_int32_t xid;
9988 +
9989 +
9990 +       /* Get XID */
9991 +       xid = *data;
9992 +
9993 +       /* This does sanity checking on RPC payloads,
9994 +        * and permits only the RPC "get port" (3)
9995 +        * in authorised procedures in client
9996 +        * communications with the portmapper.
9997 +        */
9998 +
9999 +       data += 5;
10000 +
10001 +       /* Get RPC requestor */
10002 +       if (IXDR_GET_INT32(data) != 3) {
10003 +               DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
10004 +               if(rpcinfo->strict == 1)
10005 +                       *hotdrop = 1;
10006 +               return 0;
10007 +       }
10008 +       DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
10009 +
10010 +       data++;
10011 +
10012 +       /* Jump Credentials and Verfifier */
10013 +       data = data + IXDR_GET_INT32(data) + 2;
10014 +       data = data + IXDR_GET_INT32(data) + 2;
10015 +
10016 +       /* Get RPC procedure */
10017 +       if (match_rpcs((char *)&rpcinfo->c_procs,
10018 +           rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
10019 +               DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
10020 +                       (unsigned int)IXDR_GET_INT32(data));
10021 +
10022 +               /* If the RPC conntrack half entry already exists .. */
10023 +
10024 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
10025 +                       case IPPROTO_UDP:
10026 +                               WRITE_LOCK(&ipct_rpc_udp_lock);
10027 +                       case IPPROTO_TCP:
10028 +                               WRITE_LOCK(&ipct_rpc_tcp_lock);
10029 +               }
10030 +               req_p = LIST_FIND(&request_p_list, request_p_cmp,
10031 +                                 struct request_p *, xid,
10032 +                                 ct->tuplehash[dir].tuple.src.ip,
10033 +                                 ct->tuplehash[dir].tuple.src.u.all);
10034 +
10035 +               if (req_p) {
10036 +                       DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10037 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
10038 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10039 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
10040 +
10041 +                       /* .. remove it */
10042 +                       if (del_timer(&req_p->timeout))
10043 +                               req_p->timeout.expires = 0;
10044 +
10045 +                               LIST_DELETE(&request_p_list, req_p);
10046 +                       DEBUGP("RPC req_p removed. [done]\n");
10047 +
10048 +               } else {
10049 +                       DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
10050 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
10051 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
10052 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
10053 +
10054 +               }
10055 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
10056 +                       case IPPROTO_UDP:
10057 +                               WRITE_UNLOCK(&ipct_rpc_udp_lock);
10058 +                       case IPPROTO_TCP:
10059 +                               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
10060 +               }
10061 +
10062 +               if(rpcinfo->strict == 1)
10063 +                       *hotdrop = 1;
10064 +               return 0;
10065 +       }
10066 +
10067 +       DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
10068 +               (unsigned int)IXDR_GET_INT32(data));
10069 +       return (1 && (!offset));
10070 +}
10071 +
10072 +
10073 +static int match(const struct sk_buff *skb, const struct net_device *in,
10074 +                const struct net_device *out, const void *matchinfo,
10075 +                int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
10076 +{
10077 +       struct ip_conntrack *ct;
10078 +       enum ip_conntrack_info ctinfo;
10079 +       const u_int32_t *data;
10080 +       enum ip_conntrack_dir dir;
10081 +       const struct tcphdr *tcp;
10082 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
10083 +       int port, portsok;
10084 +       int tval;
10085 +
10086 +
10087 +       DEBUGP("new packet to evaluate ..\n");
10088 +
10089 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10090 +       if (!ct) {
10091 +               DEBUGP("no ct available [skip]\n");
10092 +               return 0;
10093 +       }
10094 +
10095 +       DEBUGP("ct detected. [cont]\n");
10096 +       dir = CTINFO2DIR(ctinfo);
10097 +
10098 +       /* we only want the client to server packets for matching */
10099 +       if (dir != IP_CT_DIR_ORIGINAL)
10100 +               return 0;
10101 +
10102 +       /* This does sanity checking on UDP or TCP packets,
10103 +        * like their respective modules.
10104 +        */
10105 +
10106 +       switch (ct->tuplehash[0].tuple.dst.protonum) {
10107 +
10108 +               case IPPROTO_UDP:
10109 +                       DEBUGP("PROTO_UDP [cont]\n");
10110 +                       if (offset == 0 && datalen < sizeof(struct udphdr)) {
10111 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
10112 +                               return 0;
10113 +                       }
10114 +
10115 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
10116 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10117 +                                       portsok++;
10118 +                                       break;
10119 +                               }
10120 +                       }
10121 +                       if (portsok == 0) {
10122 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10123 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10124 +                               return 0;
10125 +                       }
10126 +
10127 +                       if ((datalen - sizeof(struct udphdr)) != 56) {
10128 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
10129 +                               if (rpcinfo->strict == 1)
10130 +                                       *hotdrop = 1;
10131 +                               return 0;
10132 +                       }
10133 +                       DEBUGP("packet length is correct. [cont]\n");
10134 +
10135 +                       /* Get to the data */
10136 +                       data = (const u_int32_t *)hdr + 2;
10137 +
10138 +                       /* Check the RPC data */
10139 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
10140 +                                               dir, ct, offset,
10141 +                                               request_p_list_udp);
10142 +
10143 +                       return tval;
10144 +                       
10145 +               
10146 +               case IPPROTO_TCP:
10147 +                       DEBUGP("PROTO_TCP [cont]\n");
10148 +                       if (offset == 0 && datalen < sizeof(struct tcphdr)) {
10149 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
10150 +                               return 0;
10151 +                       }
10152 +       
10153 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
10154 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
10155 +                                       portsok++;
10156 +                                       break;
10157 +                               }
10158 +                       }
10159 +                       if (portsok == 0) {
10160 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
10161 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
10162 +                               return 0;
10163 +                       }
10164 +
10165 +                       tcp = hdr;
10166 +                       if (datalen == (tcp->doff * 4)) {
10167 +                               DEBUGP("packet does not contain any data. [match]\n");
10168 +                               return (1 && (!offset));
10169 +                       }
10170 +
10171 +                       /* Tests if packet len is ok */
10172 +                       if ((datalen - (tcp->doff * 4)) != 60) {
10173 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
10174 +                               if(rpcinfo->strict == 1)
10175 +                                       *hotdrop = 1;
10176 +                               return 0;
10177 +                       }
10178 +                       DEBUGP("packet length is correct. [cont]\n");
10179 +
10180 +                       /* Get to the data */
10181 +                       data = (const u_int32_t *)tcp + tcp->doff + 1;  
10182 +
10183 +                       /* Check the RPC data */
10184 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
10185 +                                               dir, ct, offset,
10186 +                                               request_p_list_tcp);
10187 +
10188 +                       return tval;
10189 +
10190 +       }
10191 +
10192 +       DEBUGP("transport protocol=%u, is not supported [skip]\n",
10193 +               ct->tuplehash[0].tuple.dst.protonum);
10194 +       return 0;
10195 +}
10196 +
10197 +
10198 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
10199 +                  unsigned int matchsize, unsigned int hook_mask)
10200 +{
10201 +       if (hook_mask
10202 +           & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
10203 +               | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
10204 +               printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
10205 +               return 0;
10206 +       }
10207 +
10208 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
10209 +               return 0;
10210 +
10211 +       return 1;
10212 +}
10213 +
10214 +
10215 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
10216 +                                       &match, &checkentry, NULL,
10217 +                                       THIS_MODULE };
10218 +
10219 +
10220 +static int __init init(void)
10221 +{
10222 +       int port;
10223 +
10224 +       DEBUGP("incrementing usage counts\n");
10225 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
10226 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
10227 +
10228 +       /* If no port given, default to standard RPC port */
10229 +       if (ports[0] == 0)
10230 +               ports[0] = RPC_PORT;
10231 +
10232 +       DEBUGP("registering match [%s] for;\n", rpc_match.name);
10233 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
10234 +               DEBUGP("  port %i (UDP|TCP);\n", ports[port]);
10235 +               ports_n_c++;
10236 +       }
10237 +       
10238 +       return ipt_register_match(&rpc_match);
10239 +}
10240 +
10241 +
10242 +static void fini(void)
10243 +{
10244 +       DEBUGP("unregistering match\n");
10245 +       ipt_unregister_match(&rpc_match);
10246 +
10247 +       DEBUGP("decrementing usage counts\n");
10248 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
10249 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
10250 +}
10251 +
10252 +
10253 +module_init(init);
10254 +module_exit(fini);
10255 +
10256 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c
10257 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
10258 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c     2004-04-29 11:21:38.000000000 +0200
10259 @@ -0,0 +1,183 @@
10260 +/* Kernel module to match a string into a packet.
10261 + *
10262 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
10263 + * 
10264 + * ChangeLog
10265 + *     24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
10266 + *             Initial 2.6 port
10267 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
10268 + *             Fixed SMP re-entrancy problem using per-cpu data areas
10269 + *             for the skip/shift tables.
10270 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10271 + *             Fixed kernel panic, due to overrunning boyer moore string
10272 + *             tables. Also slightly tweaked heuristic for deciding what
10273 + *             search algo to use.
10274 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
10275 + *             Implemented Boyer Moore Sublinear search algorithm
10276 + *             alongside the existing linear search based on memcmp().
10277 + *             Also a quick check to decide which method to use on a per
10278 + *             packet basis.
10279 + */
10280 +
10281 +#include <linux/smp.h>
10282 +#include <linux/percpu.h>
10283 +#include <linux/module.h>
10284 +#include <linux/skbuff.h>
10285 +#include <linux/file.h>
10286 +#include <net/sock.h>
10287 +
10288 +#include <linux/netfilter_ipv4/ip_tables.h>
10289 +#include <linux/netfilter_ipv4/ipt_string.h>
10290 +
10291 +MODULE_LICENSE("GPL");
10292 +
10293 +struct string_per_cpu {
10294 +       int skip[BM_MAX_HLEN];
10295 +       int shift[BM_MAX_HLEN];
10296 +       int len[BM_MAX_HLEN];
10297 +};
10298 +
10299 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
10300 +
10301 +
10302 +/* Boyer Moore Sublinear string search - VERY FAST */
10303 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
10304 +{
10305 +       int M1, right_end, sk, sh;  
10306 +       int ended, j, i;
10307 +
10308 +       int *skip, *shift, *len;
10309 +       
10310 +       /* use data suitable for this CPU */
10311 +       shift=__get_cpu_var(bm_string_data).shift;
10312 +       skip=__get_cpu_var(bm_string_data).skip;
10313 +       len=__get_cpu_var(bm_string_data).len;
10314 +       
10315 +       /* Setup skip/shift tables */
10316 +       M1 = right_end = needle_len-1;
10317 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
10318 +       for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
10319 +
10320 +       for (i = 1; i < needle_len; i++) {   
10321 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
10322 +               len[i] = j;  
10323 +       }  
10324 +
10325 +       shift[0] = 1;  
10326 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
10327 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
10328 +       ended = 0;  
10329 +       
10330 +       for (i = 0; i < needle_len; i++) {  
10331 +               if (len[i] == M1 - i) ended = i;  
10332 +               if (ended) shift[i] = ended;  
10333 +       }  
10334 +
10335 +       /* Do the search*/  
10336 +       while (right_end < haystack_len)
10337 +       {
10338 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
10339 +               if (i == needle_len) {
10340 +                       return haystack+(right_end - M1);
10341 +               }
10342 +               
10343 +               sk = skip[(int)haystack[right_end - i]];  
10344 +               sh = shift[i];
10345 +               right_end = max(right_end - i + sk, right_end + sh);  
10346 +       }
10347 +
10348 +       return NULL;
10349 +}  
10350 +
10351 +/* Linear string search based on memcmp() */
10352 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
10353 +{
10354 +       char *k = haystack + (haystack_len-needle_len);
10355 +       char *t = haystack;
10356 +       
10357 +       while ( t <= k ) {
10358 +               if (memcmp(t, needle, needle_len) == 0)
10359 +                       return t;
10360 +               t++;
10361 +       }
10362 +
10363 +       return NULL;
10364 +}
10365 +
10366 +static int
10367 +match(const struct sk_buff *skb,
10368 +      const struct net_device *in,
10369 +      const struct net_device *out,
10370 +      const void *matchinfo,
10371 +      int offset,
10372 +      int *hotdrop)
10373 +{
10374 +       const struct ipt_string_info *info = matchinfo;
10375 +       struct iphdr *ip = skb->nh.iph;
10376 +       int hlen, nlen;
10377 +       char *needle, *haystack;
10378 +       proc_ipt_search search=search_linear;
10379 +
10380 +       if ( !ip ) return 0;
10381 +
10382 +       /* get lenghts, and validate them */
10383 +       nlen=info->len;
10384 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
10385 +       if ( nlen > hlen ) return 0;
10386 +
10387 +       needle=(char *)&info->string;
10388 +       haystack=(char *)ip+(ip->ihl*4);
10389 +
10390 +       /* The sublinear search comes in to its own
10391 +        * on the larger packets */
10392 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
10393 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
10394 +               if ( hlen < BM_MAX_HLEN ) {
10395 +                       search=search_sublinear;
10396 +               }else{
10397 +                       if (net_ratelimit())
10398 +                               printk(KERN_INFO "ipt_string: Packet too big "
10399 +                                       "to attempt sublinear string search "
10400 +                                       "(%d bytes)\n", hlen );
10401 +               }
10402 +       }
10403 +       
10404 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
10405 +}
10406 +
10407 +static int
10408 +checkentry(const char *tablename,
10409 +           const struct ipt_ip *ip,
10410 +           void *matchinfo,
10411 +           unsigned int matchsize,
10412 +           unsigned int hook_mask)
10413 +{
10414 +
10415 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
10416 +               return 0;
10417 +
10418 +       return 1;
10419 +}
10420 +
10421 +static struct ipt_match string_match = {
10422 +    .name = "string",
10423 +    .match = &match,
10424 +    .checkentry = &checkentry,
10425 +    .me = THIS_MODULE
10426 +};
10427 +
10428 +
10429 +static int __init init(void)
10430 +{
10431 +       return ipt_register_match(&string_match);
10432 +}
10433 +
10434 +static void __exit fini(void)
10435 +{
10436 +       ipt_unregister_match(&string_match);
10437 +}
10438 +
10439 +module_init(init);
10440 +module_exit(fini);
10441 +
10442 +
10443 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c
10444 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c        1970-01-01 01:00:00.000000000 +0100
10445 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c    2004-04-29 11:21:33.000000000 +0200
10446 @@ -0,0 +1,604 @@
10447 +/* Kernel module to match suspect packets. */
10448 +#include <linux/module.h>
10449 +#include <linux/skbuff.h>
10450 +#include <linux/ip.h>
10451 +#include <linux/udp.h>
10452 +#include <linux/tcp.h>
10453 +#include <linux/icmp.h>
10454 +#include <net/checksum.h>
10455 +
10456 +#include <linux/netfilter_ipv4/ip_tables.h>
10457 +
10458 +#define limpk(format, args...)                                          \
10459 +do {                                                                    \
10460 +       if (net_ratelimit())                                             \
10461 +               printk("ipt_unclean: %s" format,                         \
10462 +                      embedded ? "(embedded packet) " : "" , ## args);  \
10463 +} while(0)
10464 +
10465 +enum icmp_error_status
10466 +{
10467 +       ICMP_MAY_BE_ERROR,
10468 +       ICMP_IS_ERROR,
10469 +       ICMP_NOT_ERROR
10470 +};
10471 +
10472 +struct icmp_info
10473 +{
10474 +       size_t min_len, max_len;
10475 +       enum icmp_error_status err;
10476 +       u_int8_t min_code, max_code;
10477 +};
10478 +
10479 +static int
10480 +check_ip(struct iphdr *iph, size_t length, int embedded);
10481 +
10482 +/* ICMP-specific checks. */
10483 +static int
10484 +check_icmp(const struct icmphdr *icmph,
10485 +          u_int16_t datalen,
10486 +          unsigned int offset,
10487 +          int more_frags,
10488 +          int embedded)
10489 +{
10490 +       static struct icmp_info info[]
10491 +               = { [ICMP_ECHOREPLY]
10492 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10493 +                   [ICMP_DEST_UNREACH]
10494 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
10495 +                   [ICMP_SOURCE_QUENCH]
10496 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
10497 +                   [ICMP_REDIRECT]
10498 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
10499 +                   [ICMP_ECHO]
10500 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0  },
10501 +                   /* Router advertisement. */
10502 +                   [9]
10503 +                   = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
10504 +                   /* Router solicitation. */
10505 +                   [10]
10506 +                   = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
10507 +                   [ICMP_TIME_EXCEEDED]
10508 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1  },
10509 +                   [ICMP_PARAMETERPROB]
10510 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
10511 +                   [ICMP_TIMESTAMP]
10512 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10513 +                   [ICMP_TIMESTAMPREPLY]
10514 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
10515 +                   [ICMP_INFO_REQUEST]
10516 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10517 +                   [ICMP_INFO_REPLY]
10518 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
10519 +                   [ICMP_ADDRESS]
10520 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
10521 +                   [ICMP_ADDRESSREPLY]
10522 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
10523 +
10524 +       /* Can't do anything if it's a fragment. */
10525 +       if (offset)
10526 +               return 1;
10527 +
10528 +       /* Must cover type and code. */
10529 +       if (datalen < 2) {
10530 +               limpk("ICMP len=%u too short\n", datalen);
10531 +               return 0;
10532 +       }
10533 +
10534 +       /* If not embedded. */
10535 +       if (!embedded) {
10536 +               /* Bad checksum?  Don't print, just ignore. */
10537 +               if (!more_frags
10538 +                   && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
10539 +                       return 0;
10540 +
10541 +               /* CHECK: Truncated ICMP (even if first fragment). */
10542 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10543 +                   && info[icmph->type].min_len != 0
10544 +                   && datalen < info[icmph->type].min_len) {
10545 +                       limpk("ICMP type %u len %u too short\n",
10546 +                             icmph->type, datalen);
10547 +                       return 0;
10548 +               }
10549 +
10550 +               /* CHECK: Check within known error ICMPs. */
10551 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10552 +                   && info[icmph->type].err == ICMP_IS_ERROR) {
10553 +                       /* CHECK: Embedded packet must be at least
10554 +                          length of iph + 8 bytes. */
10555 +                       struct iphdr *inner = (void *)icmph + 8;
10556 +
10557 +                       /* datalen > 8 since all ICMP_IS_ERROR types
10558 +                           have min length > 8 */
10559 +                       if (datalen - 8 < sizeof(struct iphdr)) {
10560 +                               limpk("ICMP error internal way too short\n");
10561 +                               return 0;
10562 +                       }
10563 +                       if (datalen - 8 < inner->ihl*4 + 8) {
10564 +                               limpk("ICMP error internal too short\n");
10565 +                               return 0;
10566 +                       }
10567 +                       if (!check_ip(inner, datalen - 8, 1))
10568 +                               return 0;
10569 +               }
10570 +       } else {
10571 +               /* CHECK: Can't embed ICMP unless known non-error. */
10572 +               if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
10573 +                   || info[icmph->type].err != ICMP_NOT_ERROR) {
10574 +                       limpk("ICMP type %u not embeddable\n",
10575 +                             icmph->type);
10576 +                       return 0;
10577 +               }
10578 +       }
10579 +
10580 +       /* CHECK: Invalid ICMP codes. */
10581 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10582 +           && (icmph->code < info[icmph->type].min_code
10583 +               || icmph->code > info[icmph->type].max_code)) {
10584 +               limpk("ICMP type=%u code=%u\n",
10585 +                     icmph->type, icmph->code);
10586 +               return 0;
10587 +       }
10588 +
10589 +       /* CHECK: Above maximum length. */
10590 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
10591 +           && info[icmph->type].max_len != 0
10592 +           && datalen > info[icmph->type].max_len) {
10593 +               limpk("ICMP type=%u too long: %u bytes\n",
10594 +                     icmph->type, datalen);
10595 +               return 0;
10596 +       }
10597 +
10598 +       switch (icmph->type) {
10599 +       case ICMP_PARAMETERPROB: {
10600 +               /* CHECK: Problem param must be within error packet's
10601 +                * IP header. */
10602 +               struct iphdr *iph = (void *)icmph + 8;
10603 +               u_int32_t arg = ntohl(icmph->un.gateway);
10604 +
10605 +               if (icmph->code == 0) {
10606 +                       /* Code 0 means that upper 8 bits is pointer
10607 +                           to problem. */
10608 +                       if ((arg >> 24) >= iph->ihl*4) {
10609 +                               limpk("ICMP PARAMETERPROB ptr = %u\n",
10610 +                                     ntohl(icmph->un.gateway) >> 24);
10611 +                               return 0;
10612 +                       }
10613 +                       arg &= 0x00FFFFFF;
10614 +               }
10615 +
10616 +               /* CHECK: Rest must be zero. */
10617 +               if (arg) {
10618 +                       limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
10619 +                             arg);
10620 +                       return 0;
10621 +               }
10622 +               break;
10623 +       }
10624 +
10625 +       case ICMP_TIME_EXCEEDED:
10626 +       case ICMP_SOURCE_QUENCH:
10627 +               /* CHECK: Unused must be zero. */
10628 +               if (icmph->un.gateway != 0) {
10629 +                       limpk("ICMP type=%u unused = %u\n",
10630 +                             icmph->type, ntohl(icmph->un.gateway));
10631 +                       return 0;
10632 +               }
10633 +               break;
10634 +       }
10635 +
10636 +       return 1;
10637 +}
10638 +
10639 +/* UDP-specific checks. */
10640 +static int
10641 +check_udp(const struct iphdr *iph,
10642 +         const struct udphdr *udph,
10643 +         u_int16_t datalen,
10644 +         unsigned int offset,
10645 +         int more_frags,
10646 +         int embedded)
10647 +{
10648 +       /* Can't do anything if it's a fragment. */
10649 +       if (offset)
10650 +               return 1;
10651 +
10652 +       /* CHECK: Must cover UDP header. */
10653 +       if (datalen < sizeof(struct udphdr)) {
10654 +               limpk("UDP len=%u too short\n", datalen);
10655 +               return 0;
10656 +       }
10657 +
10658 +       /* Bad checksum?  Don't print, just say it's unclean. */
10659 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
10660 +       if (!more_frags && !embedded && udph->check
10661 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
10662 +                                csum_partial((char *)udph, datalen, 0)) != 0)
10663 +               return 0;
10664 +
10665 +       /* CHECK: Destination port can't be zero. */
10666 +       if (!udph->dest) {
10667 +               limpk("UDP zero destination port\n");
10668 +               return 0;
10669 +       }
10670 +
10671 +       if (!more_frags) {
10672 +               if (!embedded) {
10673 +                       /* CHECK: UDP length must match. */
10674 +                       if (ntohs(udph->len) != datalen) {
10675 +                               limpk("UDP len too short %u vs %u\n",
10676 +                                     ntohs(udph->len), datalen);
10677 +                               return 0;
10678 +                       }
10679 +               } else {
10680 +                       /* CHECK: UDP length be >= this truncated pkt. */
10681 +                       if (ntohs(udph->len) < datalen) {
10682 +                               limpk("UDP len too long %u vs %u\n",
10683 +                                     ntohs(udph->len), datalen);
10684 +                               return 0;
10685 +                       }
10686 +               }
10687 +       } else {
10688 +               /* CHECK: UDP length must be > this frag's length. */
10689 +               if (ntohs(udph->len) <= datalen) {
10690 +                       limpk("UDP fragment len too short %u vs %u\n",
10691 +                             ntohs(udph->len), datalen);
10692 +                       return 0;
10693 +               }
10694 +       }
10695 +
10696 +       return 1;
10697 +}
10698 +
10699 +#define        TH_FIN  0x01
10700 +#define        TH_SYN  0x02
10701 +#define        TH_RST  0x04
10702 +#define        TH_PUSH 0x08
10703 +#define        TH_ACK  0x10
10704 +#define        TH_URG  0x20
10705 +#define        TH_ECE  0x40
10706 +#define        TH_CWR  0x80
10707 +
10708 +/* table of valid flag combinations - ECE and CWR are always valid */
10709 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
10710 +{
10711 +       [TH_SYN]                        = 1,
10712 +       [TH_SYN|TH_ACK]                 = 1,
10713 +       [TH_RST]                        = 1,
10714 +       [TH_RST|TH_ACK]                 = 1,
10715 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
10716 +       [TH_FIN|TH_ACK]                 = 1,
10717 +       [TH_ACK]                        = 1,
10718 +       [TH_ACK|TH_PUSH]                = 1,
10719 +       [TH_ACK|TH_URG]                 = 1,
10720 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
10721 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
10722 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
10723 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
10724 +};
10725 +
10726 +/* TCP-specific checks. */
10727 +static int
10728 +check_tcp(const struct iphdr *iph,
10729 +         const struct tcphdr *tcph,
10730 +         u_int16_t datalen,
10731 +         unsigned int offset,
10732 +         int more_frags,
10733 +         int embedded)
10734 +{
10735 +       u_int8_t *opt = (u_int8_t *)tcph;
10736 +       u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
10737 +       u_int8_t tcpflags;
10738 +       int end_of_options = 0;
10739 +       size_t i;
10740 +
10741 +       /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
10742 +       /* In fact, this is caught below (offset < 516). */
10743 +
10744 +       /* Can't do anything if it's a fragment. */
10745 +       if (offset)
10746 +               return 1;
10747 +
10748 +       /* CHECK: Smaller than minimal TCP hdr. */
10749 +       if (datalen < sizeof(struct tcphdr)) {
10750 +               if (!embedded) {
10751 +                       limpk("Packet length %u < TCP header.\n", datalen);
10752 +                       return 0;
10753 +               }
10754 +               /* Must have ports available (datalen >= 8), from
10755 +                   check_icmp which set embedded = 1 */
10756 +               /* CHECK: TCP ports inside ICMP error */
10757 +               if (!tcph->source || !tcph->dest) {
10758 +                       limpk("Zero TCP ports %u/%u.\n",
10759 +                             htons(tcph->source), htons(tcph->dest));
10760 +                       return 0;
10761 +               }
10762 +               return 1;
10763 +       }
10764 +
10765 +       /* CHECK: Smaller than actual TCP hdr. */
10766 +       if (datalen < tcph->doff * 4) {
10767 +               if (!embedded) {
10768 +                       limpk("Packet length %u < actual TCP header.\n",
10769 +                             datalen);
10770 +                       return 0;
10771 +               } else
10772 +                       return 1;
10773 +       }
10774 +
10775 +       /* Bad checksum?  Don't print, just say it's unclean. */
10776 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
10777 +       if (!more_frags && !embedded
10778 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
10779 +                                csum_partial((char *)tcph, datalen, 0)) != 0)
10780 +               return 0;
10781 +
10782 +       /* CHECK: TCP ports non-zero */
10783 +       if (!tcph->source || !tcph->dest) {
10784 +               limpk("Zero TCP ports %u/%u.\n",
10785 +                     htons(tcph->source), htons(tcph->dest));
10786 +               return 0;
10787 +       }
10788 +
10789 +       /* CHECK: TCP reserved bits zero. */
10790 +       if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
10791 +               limpk("TCP reserved bits not zero\n");
10792 +               return 0;
10793 +       }
10794 +
10795 +       /* CHECK: TCP flags. */
10796 +       tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
10797 +       if (!tcp_valid_flags[tcpflags]) {
10798 +               limpk("TCP flags bad: %u\n", tcpflags);
10799 +               return 0;
10800 +       }
10801 +
10802 +       for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
10803 +               switch (opt[i]) {
10804 +               case 0:
10805 +                       end_of_options = 1;
10806 +                       i++;
10807 +                       break;
10808 +               case 1:
10809 +                       i++;
10810 +                       break;
10811 +               default:
10812 +                       /* CHECK: options after EOO. */
10813 +                       if (end_of_options) {
10814 +                               limpk("TCP option %u after end\n",
10815 +                                     opt[i]);
10816 +                               return 0;
10817 +                       }
10818 +                       /* CHECK: options at tail. */
10819 +                       else if (i+1 >= tcph->doff * 4) {
10820 +                               limpk("TCP option %u at tail\n",
10821 +                                     opt[i]);
10822 +                               return 0;
10823 +                       }
10824 +                       /* CHECK: zero-length options. */
10825 +                       else if (opt[i+1] == 0) {
10826 +                               limpk("TCP option %u 0 len\n",
10827 +                                     opt[i]);
10828 +                               return 0;
10829 +                       }
10830 +                       /* CHECK: oversize options. */
10831 +                       else if (&opt[i] + opt[i+1] > endhdr) {
10832 +                               limpk("TCP option %u at %Zu too long\n",
10833 +                                     (unsigned int) opt[i], i);
10834 +                               return 0;
10835 +                       }
10836 +                       /* Move to next option */
10837 +                       i += opt[i+1];
10838 +               }
10839 +       }
10840 +
10841 +       return 1;
10842 +}
10843 +
10844 +/* Returns 1 if ok */
10845 +/* Standard IP checks. */
10846 +static int
10847 +check_ip(struct iphdr *iph, size_t length, int embedded)
10848 +{
10849 +       u_int8_t *opt = (u_int8_t *)iph;
10850 +       u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
10851 +       int end_of_options = 0;
10852 +       void *protoh;
10853 +       size_t datalen;
10854 +       unsigned int i;
10855 +       unsigned int offset;
10856 +
10857 +       /* Should only happen for local outgoing raw-socket packets. */
10858 +       /* CHECK: length >= ip header. */
10859 +       if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
10860 +               limpk("Packet length %Zu < IP header.\n", length);
10861 +               return 0;
10862 +       }
10863 +
10864 +       offset = ntohs(iph->frag_off) & IP_OFFSET;
10865 +       protoh = (void *)iph + iph->ihl * 4;
10866 +       datalen = length - iph->ihl * 4;
10867 +
10868 +       /* CHECK: Embedded fragment. */
10869 +       if (embedded && offset) {
10870 +               limpk("Embedded fragment.\n");
10871 +               return 0;
10872 +       }
10873 +
10874 +       for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
10875 +               switch (opt[i]) {
10876 +               case 0:
10877 +                       end_of_options = 1;
10878 +                       i++;
10879 +                       break;
10880 +               case 1:
10881 +                       i++;
10882 +                       break;
10883 +               default:
10884 +                       /* CHECK: options after EOO. */
10885 +                       if (end_of_options) {
10886 +                               limpk("IP option %u after end\n",
10887 +                                     opt[i]);
10888 +                               return 0;
10889 +                       }
10890 +                       /* CHECK: options at tail. */
10891 +                       else if (i+1 >= iph->ihl * 4) {
10892 +                               limpk("IP option %u at tail\n",
10893 +                                     opt[i]);
10894 +                               return 0;
10895 +                       }
10896 +                       /* CHECK: zero-length or one-length options. */
10897 +                       else if (opt[i+1] < 2) {
10898 +                               limpk("IP option %u %u len\n",
10899 +                                     opt[i], opt[i+1]);
10900 +                               return 0;
10901 +                       }
10902 +                       /* CHECK: oversize options. */
10903 +                       else if (&opt[i] + opt[i+1] > endhdr) {
10904 +                               limpk("IP option %u at %u too long\n",
10905 +                                     opt[i], i);
10906 +                               return 0;
10907 +                       }
10908 +                       /* Move to next option */
10909 +                       i += opt[i+1];
10910 +               }
10911 +       }
10912 +
10913 +       /* Fragment checks. */
10914 +
10915 +       /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
10916 +       if ((ntohs(iph->frag_off) & IP_MF)
10917 +           && (ntohs(iph->tot_len) % 8) != 0) {
10918 +               limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
10919 +               return 0;
10920 +       }
10921 +
10922 +       /* CHECK: Oversize fragment a-la Ping of Death. */
10923 +       if (offset * 8 + datalen > 65535) {
10924 +               limpk("Oversize fragment to %u.\n", offset * 8);
10925 +               return 0;
10926 +       }
10927 +
10928 +       /* CHECK: DF set and offset or MF set. */
10929 +       if ((ntohs(iph->frag_off) & IP_DF)
10930 +           && (offset || (ntohs(iph->frag_off) & IP_MF))) {
10931 +               limpk("DF set and offset=%u, MF=%u.\n",
10932 +                     offset, ntohs(iph->frag_off) & IP_MF);
10933 +               return 0;
10934 +       }
10935 +
10936 +       /* CHECK: Zero-sized fragments. */
10937 +       if ((offset || (ntohs(iph->frag_off) & IP_MF))
10938 +           && datalen == 0) {
10939 +               limpk("Zero size fragment offset=%u\n", offset);
10940 +               return 0;
10941 +       }
10942 +
10943 +       /* Note: we can have even middle fragments smaller than this:
10944 +          consider a large packet passing through a 600MTU then
10945 +          576MTU link: this gives a fragment of 24 data bytes.  But
10946 +          everyone packs fragments largest first, hence a fragment
10947 +          can't START before 576 - MAX_IP_HEADER_LEN. */
10948 +
10949 +       /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
10950 +          down to 128 (576 taken from RFC 791: All hosts must be
10951 +          prepared to accept datagrams of up to 576 octets).  Use 128
10952 +          here. */
10953 +#define MIN_LIKELY_MTU 128
10954 +       /* CHECK: Min size of first frag = 128. */
10955 +       if ((ntohs(iph->frag_off) & IP_MF)
10956 +           && offset == 0
10957 +           && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
10958 +               limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
10959 +                     MIN_LIKELY_MTU);
10960 +               return 0;
10961 +       }
10962 +
10963 +       /* CHECK: Min offset of frag = 128 - IP hdr len. */
10964 +       if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
10965 +               limpk("Fragment starts at %u < %u\n", offset * 8,
10966 +                     MIN_LIKELY_MTU - iph->ihl * 4);
10967 +               return 0;
10968 +       }
10969 +
10970 +       /* CHECK: Protocol specification non-zero. */
10971 +       if (iph->protocol == 0) {
10972 +               limpk("Zero protocol\n");
10973 +               return 0;
10974 +       }
10975 +
10976 +       /* CHECK: Do not use what is unused.
10977 +        * First bit of fragmentation flags should be unused.
10978 +        * May be used by OS fingerprinting tools.
10979 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
10980 +        */
10981 +       if (ntohs(iph->frag_off)>>15) {
10982 +               limpk("IP unused bit set\n");
10983 +               return 0;
10984 +       }
10985 +
10986 +       /* Per-protocol checks. */
10987 +       switch (iph->protocol) {
10988 +       case IPPROTO_ICMP:
10989 +               return check_icmp(protoh, datalen, offset,
10990 +                                 (ntohs(iph->frag_off) & IP_MF),
10991 +                                 embedded);
10992 +
10993 +       case IPPROTO_UDP:
10994 +               return check_udp(iph, protoh, datalen, offset,
10995 +                                (ntohs(iph->frag_off) & IP_MF),
10996 +                                embedded);
10997 +
10998 +       case IPPROTO_TCP:
10999 +               return check_tcp(iph, protoh, datalen, offset,
11000 +                                (ntohs(iph->frag_off) & IP_MF),
11001 +                                embedded);
11002 +       default:
11003 +               /* Ignorance is bliss. */
11004 +               return 1;
11005 +       }
11006 +}
11007 +
11008 +static int
11009 +match(const struct sk_buff *skb,
11010 +      const struct net_device *in,
11011 +      const struct net_device *out,
11012 +      const void *matchinfo,
11013 +      int offset,
11014 +      const void *hdr,
11015 +      u_int16_t datalen,
11016 +      int *hotdrop)
11017 +{
11018 +       return !check_ip(skb->nh.iph, skb->len, 0);
11019 +}
11020 +
11021 +/* Called when user tries to insert an entry of this type. */
11022 +static int
11023 +checkentry(const char *tablename,
11024 +          const struct ipt_ip *ip,
11025 +          void *matchinfo,
11026 +          unsigned int matchsize,
11027 +          unsigned int hook_mask)
11028 +{
11029 +       if (matchsize != IPT_ALIGN(0))
11030 +               return 0;
11031 +
11032 +       return 1;
11033 +}
11034 +
11035 +static struct ipt_match unclean_match
11036 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
11037 +
11038 +static int __init init(void)
11039 +{
11040 +       return ipt_register_match(&unclean_match);
11041 +}
11042 +
11043 +static void __exit fini(void)
11044 +{
11045 +       ipt_unregister_match(&unclean_match);
11046 +}
11047 +
11048 +module_init(init);
11049 +module_exit(fini);
11050 +MODULE_LICENSE("GPL");
11051 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c
11052 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c     2004-04-28 03:35:43.000000000 +0200
11053 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c 2004-04-29 11:17:15.000000000 +0200
11054 @@ -59,7 +59,7 @@
11055                 0,
11056                 sizeof(struct ipt_entry),
11057                 sizeof(struct ipt_standard),
11058 -               0, { 0, 0 }, { } },
11059 +               0, NULL, 0, { 0, 0 }, { } },
11060               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11061                 -NF_ACCEPT - 1 } },
11062             /* FORWARD */
11063 @@ -67,7 +67,7 @@
11064                 0,
11065                 sizeof(struct ipt_entry),
11066                 sizeof(struct ipt_standard),
11067 -               0, { 0, 0 }, { } },
11068 +               0, NULL, 0, { 0, 0 }, { } },
11069               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11070                 -NF_ACCEPT - 1 } },
11071             /* LOCAL_OUT */
11072 @@ -75,7 +75,7 @@
11073                 0,
11074                 sizeof(struct ipt_entry),
11075                 sizeof(struct ipt_standard),
11076 -               0, { 0, 0 }, { } },
11077 +               0, NULL, 0, { 0, 0 }, { } },
11078               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11079                 -NF_ACCEPT - 1 } }
11080      },
11081 @@ -84,7 +84,7 @@
11082         0,
11083         sizeof(struct ipt_entry),
11084         sizeof(struct ipt_error),
11085 -       0, { 0, 0 }, { } },
11086 +       0, NULL, 0, { 0, 0 }, { } },
11087        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11088           { } },
11089         "ERROR"
11090 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c
11091 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c     2004-04-28 03:36:34.000000000 +0200
11092 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-04-29 11:17:15.000000000 +0200
11093 @@ -74,7 +74,7 @@
11094                 0,
11095                 sizeof(struct ipt_entry),
11096                 sizeof(struct ipt_standard),
11097 -               0, { 0, 0 }, { } },
11098 +               0, NULL, 0, { 0, 0 }, { } },
11099               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11100                 -NF_ACCEPT - 1 } },
11101             /* LOCAL_IN */
11102 @@ -82,7 +82,7 @@
11103                 0,
11104                 sizeof(struct ipt_entry),
11105                 sizeof(struct ipt_standard),
11106 -               0, { 0, 0 }, { } },
11107 +               0, NULL, 0, { 0, 0 }, { } },
11108               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11109                 -NF_ACCEPT - 1 } },
11110             /* FORWARD */
11111 @@ -90,7 +90,7 @@
11112                 0,
11113                 sizeof(struct ipt_entry),
11114                 sizeof(struct ipt_standard),
11115 -               0, { 0, 0 }, { } },
11116 +               0, NULL, 0, { 0, 0 }, { } },
11117               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11118                 -NF_ACCEPT - 1 } },
11119             /* LOCAL_OUT */
11120 @@ -98,7 +98,7 @@
11121                 0,
11122                 sizeof(struct ipt_entry),
11123                 sizeof(struct ipt_standard),
11124 -               0, { 0, 0 }, { } },
11125 +               0, NULL, 0, { 0, 0 }, { } },
11126               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11127                 -NF_ACCEPT - 1 } },
11128             /* POST_ROUTING */
11129 @@ -106,7 +106,7 @@
11130                 0,
11131                 sizeof(struct ipt_entry),
11132                 sizeof(struct ipt_standard),
11133 -               0, { 0, 0 }, { } },
11134 +               0, NULL, 0, { 0, 0 }, { } },
11135               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11136                 -NF_ACCEPT - 1 } },
11137      },
11138 @@ -115,7 +115,7 @@
11139         0,
11140         sizeof(struct ipt_entry),
11141         sizeof(struct ipt_error),
11142 -       0, { 0, 0 }, { } },
11143 +       0, NULL, 0, { 0, 0 }, { } },
11144        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11145           { } },
11146         "ERROR"
11147 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c
11148 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c        2004-04-28 03:36:36.000000000 +0200
11149 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c    2004-04-29 11:17:15.000000000 +0200
11150 @@ -46,7 +46,7 @@
11151                 0,
11152                 sizeof(struct ipt_entry),
11153                 sizeof(struct ipt_standard),
11154 -               0, { 0, 0 }, { } },
11155 +               0, NULL, 0, { 0, 0 }, { } },
11156               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11157                 -NF_ACCEPT - 1 } },
11158             /* LOCAL_OUT */
11159 @@ -54,7 +54,7 @@
11160                 0,
11161                 sizeof(struct ipt_entry),
11162                 sizeof(struct ipt_standard),
11163 -               0, { 0, 0 }, { } },
11164 +               0, NULL, 0, { 0, 0 }, { } },
11165               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
11166                 -NF_ACCEPT - 1 } }
11167      },
11168 @@ -63,7 +63,7 @@
11169         0,
11170         sizeof(struct ipt_entry),
11171         sizeof(struct ipt_error),
11172 -       0, { 0, 0 }, { } },
11173 +       0, NULL, 0, { 0, 0 }, { } },
11174        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
11175           { } },
11176         "ERROR"
11177 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/raw.c linux-2.6.6-rc3/net/ipv4/raw.c
11178 --- linux-2.6.6-rc3.org/net/ipv4/raw.c  2004-04-28 03:35:49.000000000 +0200
11179 +++ linux-2.6.6-rc3/net/ipv4/raw.c      2004-04-29 11:18:06.000000000 +0200
11180 @@ -249,6 +249,7 @@
11181                 kfree_skb(skb);
11182                 return NET_RX_DROP;
11183         }
11184 +       nf_reset(skb);
11185  
11186         skb_push(skb, skb->data - skb->nh.raw);
11187  
11188 @@ -307,7 +308,7 @@
11189         }
11190  
11191         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
11192 -                     dst_output);
11193 +                     ip_dst_output);
11194         if (err > 0)
11195                 err = inet->recverr ? net_xmit_errno(err) : 0;
11196         if (err)
11197 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c
11198 --- linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c     2004-04-28 03:35:40.000000000 +0200
11199 +++ linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c 2004-04-29 11:19:32.000000000 +0200
11200 @@ -1785,6 +1785,7 @@
11201  
11202         if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
11203                 goto discard_and_relse;
11204 +       nf_reset(skb);
11205  
11206         if (sk_filter(sk, skb, 0))
11207                 goto discard_and_relse;
11208 @@ -2670,6 +2671,7 @@
11209  EXPORT_SYMBOL(tcp_v4_connect);
11210  EXPORT_SYMBOL(tcp_v4_do_rcv);
11211  EXPORT_SYMBOL(tcp_v4_lookup_listener);
11212 +EXPORT_SYMBOL(tcp_v4_lookup);
11213  EXPORT_SYMBOL(tcp_v4_rebuild_header);
11214  EXPORT_SYMBOL(tcp_v4_remember_stamp);
11215  EXPORT_SYMBOL(tcp_v4_send_check);
11216 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/udp.c linux-2.6.6-rc3/net/ipv4/udp.c
11217 --- linux-2.6.6-rc3.org/net/ipv4/udp.c  2004-04-28 03:35:19.000000000 +0200
11218 +++ linux-2.6.6-rc3/net/ipv4/udp.c      2004-04-29 11:19:32.000000000 +0200
11219 @@ -1045,6 +1045,7 @@
11220                 kfree_skb(skb);
11221                 return -1;
11222         }
11223 +       nf_reset(skb);
11224  
11225         if (up->encap_type) {
11226                 /*
11227 @@ -1210,6 +1211,7 @@
11228  
11229         if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
11230                 goto drop;
11231 +       nf_reset(skb);
11232  
11233         /* No socket. Drop packet silently, if checksum is wrong */
11234         if (udp_checksum_complete(skb))
11235 @@ -1558,6 +1560,7 @@
11236  EXPORT_SYMBOL(udp_port_rover);
11237  EXPORT_SYMBOL(udp_prot);
11238  EXPORT_SYMBOL(udp_sendmsg);
11239 +EXPORT_SYMBOL(udp_v4_lookup);
11240  
11241  #ifdef CONFIG_PROC_FS
11242  EXPORT_SYMBOL(udp_proc_register);
11243 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c
11244 --- linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-04-28 03:35:08.000000000 +0200
11245 +++ linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c     2004-04-29 11:18:03.000000000 +0200
11246 @@ -76,6 +76,7 @@
11247                 err = -EHOSTUNREACH;
11248                 goto error_nolock;
11249         }
11250 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
11251         return NET_XMIT_BYPASS;
11252  
11253  error_nolock:
11254 @@ -170,6 +171,7 @@
11255         .handler        =       ipip_rcv,
11256         .err_handler    =       ipip_err,
11257         .no_policy      =       1,
11258 +       .xfrm_prot      =       1,
11259  };
11260  
11261  static int __init ipip_init(void)
11262 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig
11263 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig      2004-04-29 11:24:39.000000000 +0200
11264 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig  2004-04-29 11:19:41.000000000 +0200
11265 @@ -255,5 +255,29 @@
11266         depends on IP6_NF_IPTABLES
11267           help
11268  
11269 +config IP6_NF_TARGET_TRACE
11270 +       tristate  'TRACE target support'
11271 +       depends on IP6_NF_RAW
11272 +       help
11273 +         The TRACE target allows packets to be traced as those
11274 +         matches any subsequent rule in any table/rule. The matched
11275 +         rule and the packet is logged with the prefix
11276 +       
11277 +         TRACE: tablename/chainname/rulenum  
11278 +       
11279 +         If you want to compile it as a module, say M here and read
11280 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
11281 +         help
11282 +
11283 +config IP6_NF_MATCH_POLICY
11284 +       tristate "IPsec policy match support"
11285 +       depends on IP6_NF_IPTABLES && XFRM
11286 +       help
11287 +         Policy matching allows you to match packets based on the
11288 +         IPsec policy that was used during decapsulation/will
11289 +         be used during encapsulation.
11290 +
11291 +         To compile it as a module, choose M here.  If unsure, say N.
11292 +
11293  endmenu
11294  
11295 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc3/net/ipv6/netfilter/Makefile
11296 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile     2004-04-29 11:24:39.000000000 +0200
11297 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Makefile 2004-04-29 11:19:41.000000000 +0200
11298 @@ -29,4 +29,6 @@
11299  obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
11300  obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
11301  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
11302 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
11303  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
11304 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
11305 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c
11306 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-04-28 03:36:34.000000000 +0200
11307 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c     2004-04-29 11:17:15.000000000 +0200
11308 @@ -38,6 +38,14 @@
11309  #define IPV6_HDR_LEN   (sizeof(struct ipv6hdr))
11310  #define IPV6_OPTHDR_LEN        (sizeof(struct ipv6_opt_hdr))
11311  
11312 +static const char *hook6names[] = { 
11313 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
11314 +       [NF_IP6_LOCAL_IN] "INPUT",
11315 +       [NF_IP6_FORWARD] "FORWARD",
11316 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
11317 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
11318 +};
11319 +
11320  /*#define DEBUG_IP_FIREWALL*/
11321  /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
11322  /*#define DEBUG_IP_FIREWALL_USER*/
11323 @@ -408,6 +416,12 @@
11324  
11325                         t = ip6t_get_target(e);
11326                         IP_NF_ASSERT(t->u.kernel.target);
11327 +
11328 +                       /* The packet traced and the rule isn't an unconditional return/END. */
11329 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
11330 +                               nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
11331 +                                             table->name, e->chainname, e->rulenum);
11332 +                       }
11333                         /* Standard target? */
11334                         if (!t->u.kernel.target->target) {
11335                                 int v;
11336 @@ -561,6 +575,29 @@
11337         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
11338  }
11339  
11340 +static inline int
11341 +find_error_target(struct ip6t_entry *s, 
11342 +                 struct ip6t_entry *e,
11343 +                 char **chainname)
11344 +{
11345 +       struct ip6t_entry_target *t;
11346 +       static struct ip6t_entry *found = NULL;
11347 +
11348 +       if (s == e) {
11349 +               if (!found)
11350 +                       return 0;
11351 +               t = ip6t_get_target(found);
11352 +               if (strcmp(t->u.user.name, 
11353 +                          IP6T_ERROR_TARGET) == 0) {
11354 +                       *chainname = t->data;
11355 +                       return 1;
11356 +               }
11357 +       } else
11358 +               found = s;
11359 +       
11360 +       return 0;
11361 +}
11362 +
11363  /* All zeroes == unconditional rule. */
11364  static inline int
11365  unconditional(const struct ip6t_ip6 *ipv6)
11366 @@ -580,6 +617,8 @@
11367  mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
11368  {
11369         unsigned int hook;
11370 +       char *chainname = NULL;
11371 +       u_int32_t rulenum;
11372  
11373         /* No recursion; use packet counter to save back ptrs (reset
11374            to 0 as we leave), and comefrom to save source hook bitmask */
11375 @@ -593,6 +632,8 @@
11376  
11377                 /* Set initial back pointer. */
11378                 e->counters.pcnt = pos;
11379 +               rulenum = 1;
11380 +               chainname = (char *) hook6names[hook];
11381  
11382                 for (;;) {
11383                         struct ip6t_standard_target *t
11384 @@ -605,6 +646,8 @@
11385                         }
11386                         e->comefrom
11387                                 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
11388 +                       e->rulenum = rulenum++;
11389 +                       e->chainname = chainname;
11390  
11391                         /* Unconditional return/END. */
11392                         if (e->target_offset == sizeof(struct ip6t_entry)
11393 @@ -614,6 +657,10 @@
11394                             && unconditional(&e->ipv6)) {
11395                                 unsigned int oldpos, size;
11396  
11397 +                               /* Set unconditional rulenum to zero. */
11398 +                               e->rulenum = 0;
11399 +                               e->counters.bcnt = 0;
11400 +
11401                                 /* Return: backtrack through the last
11402                                    big jump. */
11403                                 do {
11404 @@ -639,6 +686,11 @@
11405                                                 (newinfo->entries + pos);
11406                                 } while (oldpos == pos + e->next_offset);
11407  
11408 +                               /* Restore chainname, rulenum. */
11409 +                               chainname = e->chainname;
11410 +                               rulenum = e->counters.bcnt;
11411 +                               e->counters.bcnt = 0;
11412 +
11413                                 /* Move along one */
11414                                 size = e->next_offset;
11415                                 e = (struct ip6t_entry *)
11416 @@ -654,6 +706,17 @@
11417                                         /* This a jump; chase it. */
11418                                         duprintf("Jump rule %u -> %u\n",
11419                                                  pos, newpos);
11420 +                                       e->counters.bcnt = rulenum++;
11421 +                                       rulenum = 1;
11422 +                                       e = (struct ip6t_entry *)
11423 +                                               (newinfo->entries + newpos);
11424 +                                       if (IP6T_ENTRY_ITERATE(newinfo->entries,
11425 +                                                              newinfo->size,
11426 +                                                              find_error_target,
11427 +                                                              e, &chainname) == 0) {
11428 +                                               printk("ip6_tables: table screwed up!\n");
11429 +                                               return 0;
11430 +                                       }
11431                                 } else {
11432                                         /* ... this is a fallthru */
11433                                         newpos = pos + e->next_offset;
11434 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c
11435 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
11436 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c     2004-04-29 11:17:15.000000000 +0200
11437 @@ -0,0 +1,65 @@
11438 +/* This is a module which is used for setting
11439 + * the NFC_TRACE flag in the nfcache field of an skb. 
11440 + */
11441 +#include <linux/module.h>
11442 +#include <linux/skbuff.h>
11443 +
11444 +#include <linux/netfilter_ipv6/ip6_tables.h>
11445 +
11446 +MODULE_LICENSE("GPL");
11447 +
11448 +static unsigned int
11449 +target(struct sk_buff **pskb,
11450 +       unsigned int hooknum,
11451 +       const struct net_device *in,
11452 +       const struct net_device *out,
11453 +       const void *targinfo,
11454 +       void *userinfo)
11455 +{
11456 +       (*pskb)->nfcache |= NFC_TRACE;
11457 +       return IP6T_CONTINUE;
11458 +}
11459 +
11460 +static int 
11461 +checkentry(const char *tablename,
11462 +                  const struct ip6t_entry *e,
11463 +           void *targinfo,
11464 +           unsigned int targinfosize,
11465 +           unsigned int hook_mask)
11466 +{
11467 +       if (targinfosize != 0) {
11468 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
11469 +                      targinfosize);
11470 +               return 0;
11471 +       }
11472 +
11473 +       if (strcmp(tablename, "raw") != 0) {
11474 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
11475 +               return 0;
11476 +       }
11477 +
11478 +       return 1;
11479 +}
11480 +
11481 +static struct ip6t_target ip6t_trace_reg = { 
11482 +       .name = "TRACE",
11483 +       .target = target, 
11484 +       .checkentry = checkentry, 
11485 +       .me = THIS_MODULE
11486 +};
11487 +
11488 +static int __init init(void)
11489 +{
11490 +       if (ip6t_register_target(&ip6t_trace_reg))
11491 +               return -EINVAL;
11492 +
11493 +       return 0;
11494 +}
11495 +
11496 +static void __exit fini(void)
11497 +{
11498 +       ip6t_unregister_target(&ip6t_trace_reg);
11499 +}
11500 +
11501 +module_init(init);
11502 +module_exit(fini);
11503 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c
11504 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-28 03:36:30.000000000 +0200
11505 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c     2004-04-29 11:19:40.000000000 +0200
11506 @@ -21,6 +21,39 @@
11507  MODULE_LICENSE("GPL");
11508  
11509  static int
11510 +match_comm(const struct sk_buff *skb, const char *comm)
11511 +{
11512 +       struct task_struct *p, *g;
11513 +       struct files_struct *files;
11514 +       int i;
11515 +
11516 +       read_lock(&tasklist_lock);
11517 +       do_each_thread(g, p) {
11518 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
11519 +                       continue;
11520 +
11521 +               task_lock(p);
11522 +               files = p->files;
11523 +               if(files) {
11524 +                       read_lock(&files->file_lock);
11525 +                       for (i=0; i < files->max_fds; i++) {
11526 +                               if (fcheck_files(files, i) ==
11527 +                                   skb->sk->sk_socket->file) {
11528 +                                       read_unlock(&files->file_lock);
11529 +                                       task_unlock(p);
11530 +                                       read_unlock(&tasklist_lock);
11531 +                                       return 1;
11532 +                               }
11533 +                       }
11534 +                       read_unlock(&files->file_lock);
11535 +               }
11536 +               task_unlock(p);
11537 +       } while_each_thread(g, p);
11538 +       read_unlock(&tasklist_lock);
11539 +       return 0;
11540 +}
11541 +
11542 +static int
11543  match_pid(const struct sk_buff *skb, pid_t pid)
11544  {
11545         struct task_struct *p;
11546 @@ -125,6 +158,12 @@
11547                         return 0;
11548         }
11549  
11550 +       if(info->match & IP6T_OWNER_COMM) {
11551 +               if (!match_comm(skb, info->comm) ^
11552 +                   !!(info->invert & IP6T_OWNER_COMM))
11553 +                       return 0;
11554 +       }
11555 +
11556         return 1;
11557  }
11558  
11559 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c
11560 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c        1970-01-01 01:00:00.000000000 +0100
11561 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c    2004-04-29 11:19:41.000000000 +0200
11562 @@ -0,0 +1,200 @@
11563 +/* IP tables module for matching IPsec policy\r
11564 + *\r
11565 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>\r
11566 + *\r
11567 + * This program is free software; you can redistribute it and/or modify\r
11568 + * it under the terms of the GNU General Public License version 2 as\r
11569 + * published by the Free Software Foundation.\r
11570 + */\r
11571 +\r
11572 +#include <linux/kernel.h>\r
11573 +#include <linux/config.h>\r
11574 +#include <linux/module.h>\r
11575 +#include <linux/skbuff.h>\r
11576 +#include <linux/init.h>\r
11577 +#include <net/xfrm.h>\r
11578 +\r
11579 +#include <linux/netfilter_ipv6.h>\r
11580 +#include <linux/netfilter_ipv6/ip6t_policy.h>\r
11581 +#include <linux/netfilter_ipv6/ip6_tables.h>\r
11582 +\r
11583 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");\r
11584 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");\r
11585 +MODULE_LICENSE("GPL");\r
11586 +\r
11587 +\r
11588 +static inline int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,\r
11589 +                                     struct in6_addr addr2)\r
11590 +{\r
11591 +       int i;\r
11592 +\r
11593 +       for (i = 0; i < 16; i++) {\r
11594 +               if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=\r
11595 +                   (addr2.s6_addr[i] & mask.s6_addr[i]))\r
11596 +                       return 1;\r
11597 +       }\r
11598 +       return 0;\r
11599 +}\r
11600 +\r
11601 +\r
11602 +static inline int\r
11603 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)\r
11604 +{\r
11605 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))\r
11606 +       \r
11607 +       struct in6_addr xfrm_saddr, xfrm_daddr;\r
11608 +       \r
11609 +       if ((e->match.saddr\r
11610 +            && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))\r
11611 +               ^ e->invert.saddr ) ||\r
11612 +           (e->match.daddr\r
11613 +            && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))\r
11614 +               ^ e->invert.daddr ) ||\r
11615 +           MISMATCH(proto, x->id.proto) ||\r
11616 +           MISMATCH(mode, x->props.mode) ||\r
11617 +           MISMATCH(spi, x->id.spi) ||\r
11618 +           MISMATCH(reqid, x->props.reqid))\r
11619 +               return 0;\r
11620 +       return 1;\r
11621 +}\r
11622 +\r
11623 +static int\r
11624 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
11625 +{\r
11626 +       const struct ip6t_policy_elem *e;\r
11627 +       struct sec_path *sp = skb->sp;\r
11628 +       int strict = info->flags & POLICY_MATCH_STRICT;\r
11629 +       int i, pos;\r
11630 +\r
11631 +       if (sp == NULL)\r
11632 +               return -1;\r
11633 +       if (strict && info->len != sp->len)\r
11634 +               return 0;\r
11635 +\r
11636 +       for (i = sp->len - 1; i >= 0; i--) {\r
11637 +               pos = strict ? i - sp->len + 1 : 0;\r
11638 +               if (pos >= info->len)\r
11639 +                       return 0;\r
11640 +               e = &info->pol[pos];\r
11641 +\r
11642 +               if (match_xfrm_state(sp->x[i].xvec, e)) {\r
11643 +                       if (!strict)\r
11644 +                               return 1;\r
11645 +               } else if (strict)\r
11646 +                       return 0;\r
11647 +       }\r
11648 +\r
11649 +       return strict ? 1 : 0;\r
11650 +}\r
11651 +\r
11652 +static int\r
11653 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
11654 +{\r
11655 +       const struct ip6t_policy_elem *e;\r
11656 +       struct dst_entry *dst = skb->dst;\r
11657 +       int strict = info->flags & POLICY_MATCH_STRICT;\r
11658 +       int i, pos;\r
11659 +\r
11660 +       if (dst->xfrm == NULL)\r
11661 +               return -1;\r
11662 +\r
11663 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {\r
11664 +               pos = strict ? i : 0;\r
11665 +               if (pos >= info->len)\r
11666 +                       return 0;\r
11667 +               e = &info->pol[pos];\r
11668 +\r
11669 +               if (match_xfrm_state(dst->xfrm, e)) {\r
11670 +                       if (!strict)\r
11671 +                               return 1;\r
11672 +               } else if (strict)\r
11673 +                       return 0;\r
11674 +       }\r
11675 +\r
11676 +       return strict ? 1 : 0;\r
11677 +}\r
11678 +\r
11679 +static int match(const struct sk_buff *skb,\r
11680 +                 const struct net_device *in,\r
11681 +                 const struct net_device *out,\r
11682 +                 const void *matchinfo,\r
11683 +                int offset,\r
11684 +                const void *hdr,\r
11685 +                u_int16_t datalen,\r
11686 +                int *hotdrop)\r
11687 +{\r
11688 +       const struct ip6t_policy_info *info = matchinfo;\r
11689 +       int ret;\r
11690 +\r
11691 +       if (info->flags & POLICY_MATCH_IN)\r
11692 +               ret = match_policy_in(skb, info);\r
11693 +       else\r
11694 +               ret = match_policy_out(skb, info);\r
11695 +\r
11696 +       if (ret < 0) {\r
11697 +               if (info->flags & POLICY_MATCH_NONE)\r
11698 +                       ret = 1;\r
11699 +               else\r
11700 +                       ret = 0;\r
11701 +       } else if (info->flags & POLICY_MATCH_NONE)\r
11702 +               ret = 0;\r
11703 +\r
11704 +       return ret;\r
11705 +}\r
11706 +\r
11707 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,\r
11708 +                      void *matchinfo, unsigned int matchsize,\r
11709 +                      unsigned int hook_mask)\r
11710 +{\r
11711 +       struct ip6t_policy_info *info = matchinfo;\r
11712 +\r
11713 +       if (matchsize != IP6T_ALIGN(sizeof(*info))) {\r
11714 +               printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",\r
11715 +                      matchsize, IP6T_ALIGN(sizeof(*info)));\r
11716 +               return 0;\r
11717 +       }\r
11718 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {\r
11719 +               printk(KERN_ERR "ip6t_policy: neither incoming nor "\r
11720 +                               "outgoing policy selected\n");\r
11721 +               return 0;\r
11722 +       }\r
11723 +       if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)\r
11724 +           && info->flags & POLICY_MATCH_OUT) {\r
11725 +               printk(KERN_ERR "ip6t_policy: output policy not valid in "\r
11726 +                               "PRE_ROUTING and INPUT\n");\r
11727 +               return 0;\r
11728 +       }\r
11729 +       if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)\r
11730 +           && info->flags & POLICY_MATCH_IN) {\r
11731 +               printk(KERN_ERR "ip6t_policy: input policy not valid in "\r
11732 +                               "POST_ROUTING and OUTPUT\n");\r
11733 +               return 0;\r
11734 +       }\r
11735 +       if (info->len > POLICY_MAX_ELEM) {\r
11736 +               printk(KERN_ERR "ip6t_policy: too many policy elements\n");\r
11737 +               return 0;\r
11738 +       }\r
11739 +\r
11740 +       return 1;\r
11741 +}\r
11742 +\r
11743 +static struct ip6t_match policy_match =\r
11744 +{\r
11745 +       .name           = "policy",\r
11746 +       .match          = match,\r
11747 +       .checkentry     = checkentry,\r
11748 +       .me             = THIS_MODULE,\r
11749 +};\r
11750 +\r
11751 +static int __init init(void)\r
11752 +{\r
11753 +       return ip6t_register_match(&policy_match);\r
11754 +}\r
11755 +\r
11756 +static void __exit fini(void)\r
11757 +{\r
11758 +       ip6t_unregister_match(&policy_match);\r
11759 +}\r
11760 +\r
11761 +module_init(init);\r
11762 +module_exit(fini);\r
11763 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c
11764 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c    2004-04-28 03:35:07.000000000 +0200
11765 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c        2004-04-29 11:17:15.000000000 +0200
11766 @@ -58,7 +58,7 @@
11767                 0,
11768                 sizeof(struct ip6t_entry),
11769                 sizeof(struct ip6t_standard),
11770 -               0, { 0, 0 }, { } },
11771 +               0, NULL, 0, { 0, 0 }, { } },
11772               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11773                 -NF_ACCEPT - 1 } },
11774             /* FORWARD */
11775 @@ -66,7 +66,7 @@
11776                 0,
11777                 sizeof(struct ip6t_entry),
11778                 sizeof(struct ip6t_standard),
11779 -               0, { 0, 0 }, { } },
11780 +               0, NULL, 0, { 0, 0 }, { } },
11781               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11782                 -NF_ACCEPT - 1 } },
11783             /* LOCAL_OUT */
11784 @@ -74,7 +74,7 @@
11785                 0,
11786                 sizeof(struct ip6t_entry),
11787                 sizeof(struct ip6t_standard),
11788 -               0, { 0, 0 }, { } },
11789 +               0, NULL, 0, { 0, 0 }, { } },
11790               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11791                 -NF_ACCEPT - 1 } }
11792      },
11793 @@ -83,7 +83,7 @@
11794         0,
11795         sizeof(struct ip6t_entry),
11796         sizeof(struct ip6t_error),
11797 -       0, { 0, 0 }, { } },
11798 +       0, NULL, 0, { 0, 0 }, { } },
11799        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11800           { } },
11801         "ERROR"
11802 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c
11803 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c    2004-04-28 03:35:43.000000000 +0200
11804 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c        2004-04-29 11:17:15.000000000 +0200
11805 @@ -73,7 +73,7 @@
11806                 0,
11807                 sizeof(struct ip6t_entry),
11808                 sizeof(struct ip6t_standard),
11809 -               0, { 0, 0 }, { } },
11810 +               0, NULL, 0, { 0, 0 }, { } },
11811               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11812                 -NF_ACCEPT - 1 } },
11813             /* LOCAL_IN */
11814 @@ -81,7 +81,7 @@
11815                 0,
11816                 sizeof(struct ip6t_entry),
11817                 sizeof(struct ip6t_standard),
11818 -               0, { 0, 0 }, { } },
11819 +               0, NULL, 0, { 0, 0 }, { } },
11820               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11821                 -NF_ACCEPT - 1 } },
11822             /* FORWARD */
11823 @@ -89,7 +89,7 @@
11824                 0,
11825                 sizeof(struct ip6t_entry),
11826                 sizeof(struct ip6t_standard),
11827 -               0, { 0, 0 }, { } },
11828 +               0, NULL, 0, { 0, 0 }, { } },
11829               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11830                 -NF_ACCEPT - 1 } },
11831             /* LOCAL_OUT */
11832 @@ -97,7 +97,7 @@
11833                 0,
11834                 sizeof(struct ip6t_entry),
11835                 sizeof(struct ip6t_standard),
11836 -               0, { 0, 0 }, { } },
11837 +               0, NULL, 0, { 0, 0 }, { } },
11838               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11839                 -NF_ACCEPT - 1 } },
11840             /* POST_ROUTING */
11841 @@ -105,7 +105,7 @@
11842                 0,
11843                 sizeof(struct ip6t_entry),
11844                 sizeof(struct ip6t_standard),
11845 -               0, { 0, 0 }, { } },
11846 +               0, NULL, 0, { 0, 0 }, { } },
11847               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11848                 -NF_ACCEPT - 1 } }
11849      },
11850 @@ -114,7 +114,7 @@
11851         0,
11852         sizeof(struct ip6t_entry),
11853         sizeof(struct ip6t_error),
11854 -       0, { 0, 0 }, { } },
11855 +       0, NULL, 0, { 0, 0 }, { } },
11856        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11857           { } },
11858         "ERROR"
11859 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c
11860 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c       2004-04-28 03:36:19.000000000 +0200
11861 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c   2004-04-29 11:17:15.000000000 +0200
11862 @@ -52,7 +52,7 @@
11863                 0,
11864                 sizeof(struct ip6t_entry),
11865                 sizeof(struct ip6t_standard),
11866 -               0, { 0, 0 }, { } },
11867 +               0, NULL, 0, { 0, 0 }, { } },
11868               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11869                 -NF_ACCEPT - 1 } },
11870             /* LOCAL_OUT */
11871 @@ -60,7 +60,7 @@
11872                 0,
11873                 sizeof(struct ip6t_entry),
11874                 sizeof(struct ip6t_standard),
11875 -               0, { 0, 0 }, { } },
11876 +               0, NULL, 0, { 0, 0 }, { } },
11877               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
11878                 -NF_ACCEPT - 1 } },
11879      },
11880 @@ -69,7 +69,7 @@
11881         0,
11882         sizeof(struct ip6t_entry),
11883         sizeof(struct ip6t_error),
11884 -       0, { 0, 0 }, { } },
11885 +       0, NULL, 0, { 0, 0 }, { } },
11886        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
11887           { } },
11888         "ERROR"
11889 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c linux-2.6.6-rc3/net/xfrm/xfrm_input.c
11890 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c   2004-04-28 03:35:05.000000000 +0200
11891 +++ linux-2.6.6-rc3/net/xfrm/xfrm_input.c       2004-04-29 11:18:03.000000000 +0200
11892 @@ -29,6 +29,9 @@
11893         if (!sp)
11894                 return NULL;
11895  
11896 +#ifdef CONFIG_NETFILTER
11897 +       sp->decap_done = 0;
11898 +#endif
11899         sp->len = 0;
11900         if (src) {
11901                 int i;
11902 diff -Nur --exclude '*.orig' linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc3/net/xfrm/xfrm_policy.c
11903 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c  2004-04-28 03:35:48.000000000 +0200
11904 +++ linux-2.6.6-rc3/net/xfrm/xfrm_policy.c      2004-04-29 11:18:06.000000000 +0200
11905 @@ -21,6 +21,7 @@
11906  #include <linux/workqueue.h>
11907  #include <linux/notifier.h>
11908  #include <linux/netdevice.h>
11909 +#include <linux/netfilter.h>
11910  #include <net/xfrm.h>
11911  #include <net/ip.h>
11912  
11913 @@ -908,6 +909,7 @@
11914  
11915         if (_decode_session(skb, &fl, family) < 0)
11916                 return 0;
11917 +       nf_nat_decode_session(skb, &fl, family);
11918  
11919         /* First, check used SA against their selectors. */
11920         if (skb->sp) {
This page took 0.963338 seconds and 3 git commands to generate.