]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.7-pom-ng-20040608.patch
- ported from linux-2.4.25-atmdd.patch
[packages/kernel.git] / 2.6.7-pom-ng-20040608.patch
1   Netfilter SNAP 20040608
2    included:
3    updates/01_iptables-1.2.10
4    updates/02_linux-2.6.4
5    updates/04_linux-2.6.6-helper_reassign
6    updates/05_linux-2.6.6-orphaned_expect
7    PENDING/expect-evict-order
8    PENDING/expect-slab-cache
9    PENDING/init_conntrack-optimize
10    PENDING/ipt_helper-invert-fix
11    PENDING/mangle-reroute
12    PENDING/nf-log
13    PENDING/nf_reset
14    PENDING/proc-no-internal-targets
15    PENDING/proc_net_conntrack-permissions
16    BASE/HOPLIMIT
17    BASE/IPV4OPTSSTRING
18    BASE/NETLINK                 // fix socket -> sk_socket
19    BASE/REJECT
20    BASE/TTL
21    BASE/connlimit
22    BASE/dstlimit
23    BASE/fuzzy
24    BASE/ipv4options
25    BASE/mport
26    BASE/nth
27    BASE/osf                     // fix socket -> sk_socket
28    BASE/pool                    // added EXPORT_SYMBOL(ip_pool_mod, ip_pool_match)
29    BASE/psd
30    BASE/quota
31    BASE/random
32    BASE/raw                     // removed linux-2.6.patch - included in kernel
33    BASE/realm
34    BASE/sctp
35    BASE/time
36    BASE/u32
37    EXTRA/CONNMARK
38    EXTRA/IPMARK
39    EXTRA/ROUTE
40    EXTRA/TARPIT
41    EXTRA/TRACE                  // ip_output.c fix
42    EXTRA/XOR
43    EXTRA/addrtype
44    EXTRA/eggdrop-conntrack
45    EXTRA/h323-conntrack-nat
46    EXTRA/ipsec-01-output-hooks  // fixed
47    EXTRA/ipsec-02-input-hooks
48    EXTRA/ipsec-03-policy-lookup
49    EXTRA/ipsec-04-policy-check
50    EXTRA/ipt_helper-any
51    EXTRA/mms-conntrack-nat
52    EXTRA/owner-socketlookup
53    EXTRA/ownercmd
54    EXTRA/policy
55    EXTRA/quake3-conntrack-nat
56    EXTRA/rsh
57    EXTRA/rtsp-conntrack
58    EXTRA/sctp-conntrack-nat
59    EXTRA/string                 // required unclean module - included - req fix
60    EXTRA/talk-conntrack-nat
61  
62 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter.h linux-2.6.7-rc3/include/linux/netfilter.h
63 --- linux-2.6.7-rc3.org/include/linux/netfilter.h       2004-06-07 21:14:24.000000000 +0200
64 +++ linux-2.6.7-rc3/include/linux/netfilter.h   2004-06-08 10:38:46.000000000 +0200
65 @@ -23,6 +23,7 @@
66     <= 0x2000 is used for protocol-flags. */
67  #define NFC_UNKNOWN 0x4000
68  #define NFC_ALTERED 0x8000
69 +#define NFC_TRACE   0x10000
70  
71  #ifdef __KERNEL__
72  #include <linux/config.h>
73 @@ -137,12 +138,14 @@
74  /* This is gross, but inline doesn't cut it for avoiding the function
75     call in fast path: gcc doesn't inline (needs value tracking?). --RR */
76  #ifdef CONFIG_NETFILTER_DEBUG
77 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
78 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
79 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
80 +(!(cond)                                                               \
81 + ? (okfn)(skb)                                                                 \
82 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
83  #define NF_HOOK_THRESH nf_hook_slow
84  #else
85 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
86 -(list_empty(&nf_hooks[(pf)][(hook)])                                   \
87 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
88 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)])                                \
89   ? (okfn)(skb)                                                         \
90   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
91  #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)     \
92 @@ -150,6 +153,8 @@
93   ? (okfn)(skb)                                                         \
94   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
95  #endif
96 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
97 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
98  
99  int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
100                  struct net_device *indev, struct net_device *outdev,
101 @@ -188,7 +193,24 @@
102  
103  #else /* !CONFIG_NETFILTER */
104  #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
105 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
106  #endif /*CONFIG_NETFILTER*/
107  
108 +#ifdef CONFIG_XFRM
109 +#ifdef CONFIG_IP_NF_NAT_NEEDED
110 +struct flowi;
111 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
112 +
113 +static inline void
114 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
115 +{
116 +       if (family == AF_INET)
117 +               nf_nat_decode_session4(skb, fl);
118 +}
119 +#else /* CONFIG_IP_NF_NAT_NEEDED */
120 +#define nf_nat_decode_session(skb,fl,family)
121 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
122 +#endif /* CONFIG_XFRM */
123 +
124  #endif /*__KERNEL__*/
125  #endif /*__LINUX_NETFILTER_H*/
126 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_helpers.h linux-2.6.7-rc3/include/linux/netfilter_helpers.h
127 --- linux-2.6.7-rc3.org/include/linux/netfilter_helpers.h       1970-01-01 01:00:00.000000000 +0100
128 +++ linux-2.6.7-rc3/include/linux/netfilter_helpers.h   2004-06-08 10:40:46.000000000 +0200
129 @@ -0,0 +1,133 @@
130 +/*
131 + * Helpers for netfiler modules.  This file provides implementations for basic
132 + * functions such as strncasecmp(), etc.
133 + *
134 + * gcc will warn for defined but unused functions, so we only include the
135 + * functions requested.  The following macros are used:
136 + *   NF_NEED_STRNCASECMP        nf_strncasecmp()
137 + *   NF_NEED_STRTOU16           nf_strtou16()
138 + *   NF_NEED_STRTOU32           nf_strtou32()
139 + */
140 +#ifndef _NETFILTER_HELPERS_H
141 +#define _NETFILTER_HELPERS_H
142 +
143 +/* Only include these functions for kernel code. */
144 +#ifdef __KERNEL__
145 +
146 +#include <linux/ctype.h>
147 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
148 +
149 +/*
150 + * The standard strncasecmp()
151 + */
152 +#ifdef NF_NEED_STRNCASECMP
153 +static int
154 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
155 +{
156 +    if (s1 == NULL || s2 == NULL)
157 +    {
158 +        if (s1 == NULL && s2 == NULL)
159 +        {
160 +            return 0;
161 +        }
162 +        return (s1 == NULL) ? -1 : 1;
163 +    }
164 +    while (len > 0 && tolower(*s1) == tolower(*s2))
165 +    {
166 +        len--;
167 +        s1++;
168 +        s2++;
169 +    }
170 +    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
171 +}
172 +#endif /* NF_NEED_STRNCASECMP */
173 +
174 +/*
175 + * Parse a string containing a 16-bit unsigned integer.
176 + * Returns the number of chars used, or zero if no number is found.
177 + */
178 +#ifdef NF_NEED_STRTOU16
179 +static int
180 +nf_strtou16(const char* pbuf, u_int16_t* pval)
181 +{
182 +    int n = 0;
183 +
184 +    *pval = 0;
185 +    while (isdigit(pbuf[n]))
186 +    {
187 +        *pval = (*pval * 10) + (pbuf[n] - '0');
188 +        n++;
189 +    }
190 +
191 +    return n;
192 +}
193 +#endif /* NF_NEED_STRTOU16 */
194 +
195 +/*
196 + * Parse a string containing a 32-bit unsigned integer.
197 + * Returns the number of chars used, or zero if no number is found.
198 + */
199 +#ifdef NF_NEED_STRTOU32
200 +static int
201 +nf_strtou32(const char* pbuf, u_int32_t* pval)
202 +{
203 +    int n = 0;
204 +
205 +    *pval = 0;
206 +    while (pbuf[n] >= '0' && pbuf[n] <= '9')
207 +    {
208 +        *pval = (*pval * 10) + (pbuf[n] - '0');
209 +        n++;
210 +    }
211 +
212 +    return n;
213 +}
214 +#endif /* NF_NEED_STRTOU32 */
215 +
216 +/*
217 + * Given a buffer and length, advance to the next line and mark the current
218 + * line.
219 + */
220 +#ifdef NF_NEED_NEXTLINE
221 +static int
222 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
223 +{
224 +    uint    off = *poff;
225 +    uint    physlen = 0;
226 +
227 +    if (off >= len)
228 +    {
229 +        return 0;
230 +    }
231 +
232 +    while (p[off] != '\n')
233 +    {
234 +        if (len-off <= 1)
235 +        {
236 +            return 0;
237 +        }
238 +
239 +        physlen++;
240 +        off++;
241 +    }
242 +
243 +    /* if we saw a crlf, physlen needs adjusted */
244 +    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
245 +    {
246 +        physlen--;
247 +    }
248 +
249 +    /* advance past the newline */
250 +    off++;
251 +
252 +    *plineoff = *poff;
253 +    *plinelen = physlen;
254 +    *poff = off;
255 +
256 +    return 1;
257 +}
258 +#endif /* NF_NEED_NEXTLINE */
259 +
260 +#endif /* __KERNEL__ */
261 +
262 +#endif /* _NETFILTER_HELPERS_H */
263 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
264 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h     2004-06-07 21:14:59.000000000 +0200
265 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-06-08 10:41:27.000000000 +0200
266 @@ -51,10 +51,12 @@
267  
268  #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
269  #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
270 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
271  
272  /* per conntrack: protocol private data */
273  union ip_conntrack_proto {
274         /* insert conntrack proto private data here */
275 +       struct ip_ct_sctp sctp;
276         struct ip_ct_tcp tcp;
277         struct ip_ct_icmp icmp;
278  };
279 @@ -64,6 +66,11 @@
280  };
281  
282  /* Add protocol helper include file here */
283 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
284 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
285 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
286 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
287 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
288  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
289  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
290  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
291 @@ -71,6 +78,11 @@
292  /* per expectation: application helper private data */
293  union ip_conntrack_expect_help {
294         /* insert conntrack helper private data (expect) here */
295 +       struct ip_ct_talk_expect exp_talk_info;
296 +       struct ip_ct_rtsp_expect exp_rtsp_info;
297 +       struct ip_ct_rsh_expect exp_rsh_info;
298 +       struct ip_ct_mms_expect exp_mms_info;
299 +       struct ip_ct_h225_expect exp_h225_info;
300         struct ip_ct_amanda_expect exp_amanda_info;
301         struct ip_ct_ftp_expect exp_ftp_info;
302         struct ip_ct_irc_expect exp_irc_info;
303 @@ -85,6 +97,11 @@
304  /* per conntrack: application helper private data */
305  union ip_conntrack_help {
306         /* insert conntrack helper private data (master) here */
307 +       struct ip_ct_talk_master ct_talk_info;
308 +       struct ip_ct_rtsp_master ct_rtsp_info;
309 +       struct ip_ct_rsh_master ct_rsh_info;
310 +       struct ip_ct_mms_master ct_mms_info;
311 +       struct ip_ct_h225_master ct_h225_info;
312         struct ip_ct_ftp_master ct_ftp_info;
313         struct ip_ct_irc_master ct_irc_info;
314  };
315 @@ -207,6 +224,10 @@
316         } nat;
317  #endif /* CONFIG_IP_NF_NAT_NEEDED */
318  
319 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
320 +       unsigned long mark;
321 +#endif
322 +
323  };
324  
325  /* get master conntrack via master expectation */
326 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
327 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h        1970-01-01 01:00:00.000000000 +0100
328 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h    2004-06-08 10:38:40.000000000 +0200
329 @@ -0,0 +1,31 @@
330 +#ifndef _IP_CONNTRACK_H323_H
331 +#define _IP_CONNTRACK_H323_H
332 +/* H.323 connection tracking. */
333 +
334 +#ifdef __KERNEL__
335 +/* Protects H.323 related data */
336 +#include <linux/netfilter_ipv4/lockhelp.h>
337 +DECLARE_LOCK_EXTERN(ip_h323_lock);
338 +#endif
339 +
340 +/* Default H.225 port */
341 +#define H225_PORT      1720
342 +
343 +/* This structure is per expected connection */
344 +struct ip_ct_h225_expect {
345 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
346 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
347 +       unsigned int offset;            /* offset of the address in the payload */
348 +};
349 +
350 +/* This structure exists only once per master */
351 +struct ip_ct_h225_master {
352 +       int is_h225;                            /* H.225 or H.245 connection */
353 +#ifdef CONFIG_IP_NF_NAT_NEEDED
354 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
355 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
356 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
357 +#endif
358 +};
359 +
360 +#endif /* _IP_CONNTRACK_H323_H */
361 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
362 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
363 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h     2004-06-08 10:39:44.000000000 +0200
364 @@ -0,0 +1,31 @@
365 +#ifndef _IP_CONNTRACK_MMS_H
366 +#define _IP_CONNTRACK_MMS_H
367 +/* MMS tracking. */
368 +
369 +#ifdef __KERNEL__
370 +#include <linux/netfilter_ipv4/lockhelp.h>
371 +
372 +DECLARE_LOCK_EXTERN(ip_mms_lock);
373 +
374 +#define MMS_PORT                         1755
375 +#define MMS_SRV_MSG_ID                   196610
376 +
377 +#define MMS_SRV_MSG_OFFSET               36
378 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
379 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
380 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
381 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
382 +#endif
383 +
384 +/* This structure is per expected connection */
385 +struct ip_ct_mms_expect {
386 +       u_int32_t len;
387 +       u_int32_t padding;
388 +       u_int16_t port;
389 +};
390 +
391 +/* This structure exists only once per master */
392 +struct ip_ct_mms_master {
393 +};
394 +
395 +#endif /* _IP_CONNTRACK_MMS_H */
396 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
397 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h      1970-01-01 01:00:00.000000000 +0100
398 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h  2004-06-08 10:40:36.000000000 +0200
399 @@ -0,0 +1,21 @@
400 +#ifndef _IP_CT_QUAKE3
401 +#define _IP_CT_QUAKE3
402 +
403 +/* Don't confuse with 27960, often used as the Server Port */
404 +#define QUAKE3_MASTER_PORT 27950
405 +
406 +struct quake3_search {
407 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
408 +       const char *pattern;
409 +       size_t plen;
410 +}; 
411 +
412 +/* This structure is per expected connection */
413 +struct ip_ct_quake3_expect {
414 +};
415 +
416 +/* This structure exists only once per master */
417 +struct ip_ct_quake3_master {
418 +};
419 +
420 +#endif /* _IP_CT_QUAKE3 */
421 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
422 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
423 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h     2004-06-08 10:40:43.000000000 +0200
424 @@ -0,0 +1,35 @@
425 +/* RSH extension for IP connection tracking, Version 1.0
426 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
427 + * based on HW's ip_conntrack_irc.c     
428 + *
429 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
430 + *
431 + *      This program is free software; you can redistribute it and/or
432 + *      modify it under the terms of the GNU General Public License
433 + *      as published by the Free Software Foundation; either version
434 + *      2 of the License, or (at your option) any later version.
435 + */
436 +#ifndef _IP_CONNTRACK_RSH_H
437 +#define _IP_CONNTRACK_RSH_H
438 +
439 +#ifdef __KERNEL__
440 +#include <linux/netfilter_ipv4/lockhelp.h>
441 +
442 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
443 +#endif
444 +
445 +
446 +#define RSH_PORT       514
447 +
448 +/* This structure is per expected connection */
449 +struct ip_ct_rsh_expect
450 +{
451 +       u_int16_t port;
452 +};
453 +
454 +/* This structure exists only once per master */
455 +struct ip_ct_rsh_master {
456 +};
457 +
458 +#endif /* _IP_CONNTRACK_RSH_H */
459 +
460 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
461 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h        1970-01-01 01:00:00.000000000 +0100
462 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h    2004-06-08 10:40:46.000000000 +0200
463 @@ -0,0 +1,68 @@
464 +/*
465 + * RTSP extension for IP connection tracking.
466 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
467 + * based on ip_conntrack_irc.h
468 + *
469 + *      This program is free software; you can redistribute it and/or
470 + *      modify it under the terms of the GNU General Public License
471 + *      as published by the Free Software Foundation; either version
472 + *      2 of the License, or (at your option) any later version.
473 + */
474 +#ifndef _IP_CONNTRACK_RTSP_H
475 +#define _IP_CONNTRACK_RTSP_H
476 +
477 +/* #define IP_NF_RTSP_DEBUG */
478 +#define IP_NF_RTSP_VERSION "0.01"
479 +
480 +/* port block types */
481 +typedef enum {
482 +    pb_single,  /* client_port=x */
483 +    pb_range,   /* client_port=x-y */
484 +    pb_discon   /* client_port=x/y (rtspbis) */
485 +} portblock_t;
486 +
487 +/* We record seq number and length of rtsp headers here, all in host order. */
488 +
489 +/*
490 + * This structure is per expected connection.  It is a member of struct
491 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
492 + * there and we are expected to only store the length of the data which
493 + * needs replaced.  If a packet contains multiple RTSP messages, we create
494 + * one expected connection per message.
495 + *
496 + * We use these variables to mark the entire header block.  This may seem
497 + * like overkill, but the nature of RTSP requires it.  A header may appear
498 + * multiple times in a message.  We must treat two Transport headers the
499 + * same as one Transport header with two entries.
500 + */
501 +struct ip_ct_rtsp_expect
502 +{
503 +    u_int32_t   len;        /* length of header block */
504 +    portblock_t pbtype;     /* Type of port block that was requested */
505 +    u_int16_t   loport;     /* Port that was requested, low or first */
506 +    u_int16_t   hiport;     /* Port that was requested, high or second */
507 +#if 0
508 +    uint        method;     /* RTSP method */
509 +    uint        cseq;       /* CSeq from request */
510 +#endif
511 +};
512 +
513 +/* This structure exists only once per master */
514 +struct ip_ct_rtsp_master
515 +{
516 +    /* Empty (?) */
517 +};
518 +
519 +
520 +#ifdef __KERNEL__
521 +
522 +#include <linux/netfilter_ipv4/lockhelp.h>
523 +
524 +#define RTSP_PORT   554
525 +
526 +/* Protects rtsp part of conntracks */
527 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
528 +
529 +#endif /* __KERNEL__ */
530 +
531 +#endif /* _IP_CONNTRACK_RTSP_H */
532 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
533 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h        1970-01-01 01:00:00.000000000 +0100
534 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h    2004-06-08 10:40:55.000000000 +0200
535 @@ -0,0 +1,25 @@
536 +#ifndef _IP_CONNTRACK_SCTP_H
537 +#define _IP_CONNTRACK_SCTP_H
538 +/* SCTP tracking. */
539 +
540 +enum sctp_conntrack {
541 +       SCTP_CONNTRACK_NONE,
542 +       SCTP_CONNTRACK_CLOSED,
543 +       SCTP_CONNTRACK_COOKIE_WAIT,
544 +       SCTP_CONNTRACK_COOKIE_ECHOED,
545 +       SCTP_CONNTRACK_ESTABLISHED,
546 +       SCTP_CONNTRACK_SHUTDOWN_SENT,
547 +       SCTP_CONNTRACK_SHUTDOWN_RECD,
548 +       SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
549 +       SCTP_CONNTRACK_MAX
550 +};
551 +
552 +struct ip_ct_sctp
553 +{
554 +       enum sctp_conntrack state;
555 +
556 +       u_int32_t vtag[IP_CT_DIR_MAX];
557 +       u_int32_t ttag[IP_CT_DIR_MAX];
558 +};
559 +
560 +#endif /* _IP_CONNTRACK_SCTP_H */
561 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
562 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h        1970-01-01 01:00:00.000000000 +0100
563 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h    2004-06-08 10:41:27.000000000 +0200
564 @@ -0,0 +1,152 @@
565 +#ifndef _IP_CONNTRACK_TALK_H
566 +#define _IP_CONNTRACK_TALK_H
567 +/* TALK tracking. */
568 +
569 +#ifdef __KERNEL__
570 +#include <linux/in.h>
571 +#include <linux/netfilter_ipv4/lockhelp.h>
572 +
573 +/* Protects talk part of conntracks */
574 +DECLARE_LOCK_EXTERN(ip_talk_lock);
575 +#endif
576 +
577 +
578 +#define TALK_PORT      517
579 +#define NTALK_PORT     518
580 +
581 +/* talk structures and constants from <protocols/talkd.h> */
582 +
583 +/*
584 + * 4.3BSD struct sockaddr
585 + */
586 +struct talk_addr {
587 +       u_int16_t ta_family;
588 +       u_int16_t ta_port;
589 +       u_int32_t ta_addr;
590 +       u_int32_t ta_junk1;
591 +       u_int32_t ta_junk2;
592 +};
593 +
594 +#define        TALK_OLD_NSIZE  9
595 +#define        TALK_NSIZE      12
596 +#define        TALK_TTY_NSIZE  16
597 +
598 +/*
599 + * Client->server request message formats.
600 + */
601 +struct talk_msg {
602 +       u_char  type;           /* request type, see below */
603 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
604 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
605 +       u_char  pad;
606 +       u_int32_t id_num;       /* message id */
607 +       int32_t pid;            /* caller's process id */
608 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
609 +       struct  talk_addr addr;         /* old (4.3) style */
610 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
611 +};
612 +
613 +struct ntalk_msg {
614 +       u_char  vers;           /* protocol version */
615 +       u_char  type;           /* request type, see below */
616 +       u_char  answer;         /* not used */
617 +       u_char  pad;
618 +       u_int32_t id_num;       /* message id */
619 +       struct  talk_addr addr;         /* old (4.3) style */
620 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
621 +       int32_t pid;            /* caller's process id */
622 +       char    l_name[TALK_NSIZE];/* caller's name */
623 +       char    r_name[TALK_NSIZE];/* callee's name */
624 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
625 +};
626 +
627 +struct ntalk2_msg {
628 +       u_char  vers;           /* talk protocol version    */
629 +       u_char  type;           /* request type             */
630 +       u_char  answer;         /*  */
631 +       u_char  extended;       /* !0 if additional parts   */
632 +       u_int32_t id_num;       /* message id number (dels) */
633 +       struct  talk_addr addr;         /* target address   */
634 +       struct  talk_addr ctl_addr;     /* reply to address */
635 +       int32_t pid;            /* caller's process id */
636 +       char    l_name[TALK_NSIZE];  /* caller's name */
637 +       char    r_name[TALK_NSIZE];  /* callee's name */
638 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
639 +};
640 +
641 +/*
642 + * Server->client response message formats.
643 + */
644 +struct talk_response {
645 +       u_char  type;           /* type of request message, see below */
646 +       u_char  answer;         /* response to request message, see below */
647 +       u_char  pad[2];
648 +       u_int32_t id_num;       /* message id */
649 +       struct  talk_addr addr; /* address for establishing conversation */
650 +};
651 +
652 +struct ntalk_response {
653 +       u_char  vers;           /* protocol version */
654 +       u_char  type;           /* type of request message, see below */
655 +       u_char  answer;         /* response to request message, see below */
656 +       u_char  pad;
657 +       u_int32_t id_num;       /* message id */
658 +       struct  talk_addr addr; /* address for establishing conversation */
659 +};
660 +
661 +struct ntalk2_response {
662 +       u_char  vers;           /* protocol version         */
663 +       u_char  type;           /* type of request message  */
664 +       u_char  answer;         /* response to request      */
665 +       u_char  rvers;          /* Version of answering vers*/
666 +       u_int32_t id_num;       /* message id number        */
667 +       struct  talk_addr addr; /* address for connection   */
668 +       /* This is at the end to compatiblize this with NTALK version.   */
669 +       char    r_name[TALK_NSIZE]; /* callee's name            */
670 +};
671 +
672 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
673 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
674 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
675 +
676 +#define        TALK_VERSION    0               /* protocol versions */
677 +#define        NTALK_VERSION   1
678 +#define        NTALK2_VERSION  2
679 +
680 +/* message type values */
681 +#define LEAVE_INVITE   0       /* leave invitation with server */
682 +#define LOOK_UP                1       /* check for invitation by callee */
683 +#define DELETE         2       /* delete invitation by caller */
684 +#define ANNOUNCE       3       /* announce invitation by caller */
685 +/* NTALK2 */
686 +#define REPLY_QUERY    4       /* request reply data from local daemon */
687 +
688 +/* answer values */
689 +#define SUCCESS                0       /* operation completed properly */
690 +#define NOT_HERE       1       /* callee not logged in */
691 +#define FAILED         2       /* operation failed for unexplained reason */
692 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
693 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
694 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
695 +#define        BADVERSION      6       /* request has invalid protocol version */
696 +#define        BADADDR         7       /* request has invalid addr value */
697 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
698 +/* NTALK2 */
699 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
700 +#define TRY_HERE       10      /* Not on this machine, try this      */
701 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
702 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
703 +
704 +/* We don't really need much for talk */
705 +struct ip_ct_talk_expect
706 +{
707 +       /* Port that was to be used */
708 +       u_int16_t port;
709 +};
710 +
711 +/* This structure exists only once per master */
712 +struct ip_ct_talk_master
713 +{
714 +};
715 +
716 +#endif /* _IP_CONNTRACK_TALK_H */
717 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
718 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h       2004-06-07 21:14:55.000000000 +0200
719 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h   2004-06-08 10:40:55.000000000 +0200
720 @@ -25,6 +25,9 @@
721         struct {
722                 u_int16_t id;
723         } icmp;
724 +       struct {
725 +               u_int16_t port;
726 +       } sctp;
727  };
728  
729  /* The manipulable part of the tuple. */
730 @@ -55,6 +58,9 @@
731                         struct {
732                                 u_int8_t type, code;
733                         } icmp;
734 +                       struct {
735 +                               u_int16_t port;
736 +                       } sctp;
737                 } u;
738  
739                 /* The protocol. */
740 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_pool.h
741 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_pool.h  1970-01-01 01:00:00.000000000 +0100
742 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_pool.h      2004-06-08 10:31:45.000000000 +0200
743 @@ -0,0 +1,64 @@
744 +#ifndef _IP_POOL_H
745 +#define _IP_POOL_H
746 +
747 +/***************************************************************************/
748 +/*  This program is free software; you can redistribute it and/or modify   */
749 +/*  it under the terms of the GNU General Public License as published by   */
750 +/*  the Free Software Foundation; either version 2 of the License, or     */
751 +/*  (at your option) any later version.                                           */
752 +/*                                                                        */
753 +/*  This program is distributed in the hope that it will be useful,       */
754 +/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
755 +/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
756 +/*  GNU General Public License for more details.                          */
757 +/*                                                                        */
758 +/*  You should have received a copy of the GNU General Public License     */
759 +/*  along with this program; if not, write to the Free Software                   */
760 +/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
761 +/***************************************************************************/
762 +
763 +/* A sockopt of such quality has hardly ever been seen before on the open
764 + * market!  This little beauty, hardly ever used: above 64, so it's
765 + * traditionally used for firewalling, not touched (even once!) by the
766 + * 2.0, 2.2 and 2.4 kernels!
767 + *
768 + * Comes with its own certificate of authenticity, valid anywhere in the
769 + * Free world!
770 + *
771 + * Rusty, 19.4.2000
772 + */
773 +#define SO_IP_POOL 81
774 +
775 +typedef int ip_pool_t;                 /* pool index */
776 +#define IP_POOL_NONE   ((ip_pool_t)-1)
777 +
778 +struct ip_pool_request {
779 +       int op;
780 +       ip_pool_t index;
781 +       u_int32_t addr;
782 +       u_int32_t addr2;
783 +};
784 +
785 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
786 +
787 +#define IP_POOL_BAD001         0x00000010
788 +
789 +#define IP_POOL_FLUSH          0x00000011      /* req.index, no arguments */
790 +#define IP_POOL_INIT           0x00000012      /* from addr to addr2 incl. */
791 +#define IP_POOL_DESTROY                0x00000013      /* req.index, no arguments */
792 +#define IP_POOL_ADD_ADDR       0x00000014      /* add addr to pool */
793 +#define IP_POOL_DEL_ADDR       0x00000015      /* del addr from pool */
794 +#define IP_POOL_HIGH_NR                0x00000016      /* result in req.index */
795 +#define IP_POOL_LOOKUP         0x00000017      /* result in addr and addr2 */
796 +#define IP_POOL_USAGE          0x00000018      /* result in addr */
797 +#define IP_POOL_TEST_ADDR      0x00000019      /* result (0/1) returned */
798 +
799 +#ifdef __KERNEL__
800 +
801 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
802 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
803 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
804 +
805 +#endif
806 +
807 +#endif /*_IP_POOL_H*/
808 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_tables.h
809 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ip_tables.h        2004-06-07 21:14:25.000000000 +0200
810 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ip_tables.h    2004-06-08 10:37:30.000000000 +0200
811 @@ -134,6 +134,12 @@
812         /* Back pointer */
813         unsigned int comefrom;
814  
815 +       /* Name of the chain */
816 +       char *chainname;
817 +       
818 +       /* Rule number in the chain. */
819 +       u_int32_t rulenum;
820 +
821         /* Packet and byte counters. */
822         struct ipt_counters counters;
823  
824 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
825 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h     1970-01-01 01:00:00.000000000 +0100
826 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-06-08 10:36:58.000000000 +0200
827 @@ -0,0 +1,25 @@
828 +#ifndef _IPT_CONNMARK_H_target
829 +#define _IPT_CONNMARK_H_target
830 +
831 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
832 + * by Henrik Nordstrom <hno@marasystems.com>
833 + *
834 + * This program is free software; you can redistribute it and/or modify
835 + * it under the terms of the GNU General Public License as published by
836 + * the Free Software Foundation; either version 2 of the License, or
837 + * (at your option) any later version.
838 + */
839 +
840 +enum {
841 +       IPT_CONNMARK_SET = 0,
842 +       IPT_CONNMARK_SAVE,
843 +       IPT_CONNMARK_RESTORE
844 +};
845 +
846 +struct ipt_connmark_target_info {
847 +       unsigned long mark;
848 +       unsigned long mask;
849 +       u_int8_t mode;
850 +};
851 +
852 +#endif /*_IPT_CONNMARK_H_target*/
853 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
854 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h       1970-01-01 01:00:00.000000000 +0100
855 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h   2004-06-08 10:37:02.000000000 +0200
856 @@ -0,0 +1,13 @@
857 +#ifndef _IPT_IPMARK_H_target
858 +#define _IPT_IPMARK_H_target
859 +
860 +struct ipt_ipmark_target_info {
861 +       unsigned long andmask;
862 +       unsigned long ormask;
863 +       unsigned int addr;
864 +};
865 +
866 +#define IPT_IPMARK_SRC    0
867 +#define IPT_IPMARK_DST    1
868 +
869 +#endif /*_IPT_IPMARK_H_target*/
870 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h
871 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h      1970-01-01 01:00:00.000000000 +0100
872 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h  2004-06-08 10:31:09.000000000 +0200
873 @@ -0,0 +1,27 @@
874 +#ifndef _IPT_FWMON_H
875 +#define _IPT_FWMON_H
876 +
877 +/* Bitmask macros */
878 +#define MASK(x,y) (x & y)
879 +#define MASK_SET(x,y) x |= y
880 +#define MASK_UNSET(x,y) x &= ~y
881 +
882 +#define USE_MARK       0x00000001
883 +#define USE_DROP       0x00000002
884 +#define USE_SIZE       0x00000004
885 +
886 +struct ipt_nldata
887 +{      
888 +       unsigned int flags;
889 +       unsigned int mark;
890 +       unsigned int size;
891 +};
892 +
893 +/* Old header */
894 +struct netlink_t {
895 +       unsigned int len;
896 +       unsigned int mark;
897 +       char iface[IFNAMSIZ];
898 +};
899 +
900 +#endif /*_IPT_FWMON_H*/
901 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h
902 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ROUTE.h        1970-01-01 01:00:00.000000000 +0100
903 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ROUTE.h    2004-06-08 10:37:08.000000000 +0200
904 @@ -0,0 +1,22 @@
905 +/* Header file for iptables ipt_ROUTE target
906 + *
907 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
908 + *
909 + * This software is distributed under GNU GPL v2, 1991
910 + */
911 +#ifndef _IPT_ROUTE_H_target
912 +#define _IPT_ROUTE_H_target
913 +
914 +#define IPT_ROUTE_IFNAMSIZ 16
915 +
916 +struct ipt_route_target_info {
917 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
918 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
919 +       u_int32_t gw;                           /* IP address of gateway */
920 +       u_int8_t  flags;
921 +};
922 +
923 +/* Values for "flags" field */
924 +#define IPT_ROUTE_CONTINUE        0x01
925 +
926 +#endif /*_IPT_ROUTE_H_target*/
927 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_TTL.h
928 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h  1970-01-01 01:00:00.000000000 +0100
929 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_TTL.h      2004-06-08 10:31:21.000000000 +0200
930 @@ -0,0 +1,21 @@
931 +/* TTL modification module for IP tables
932 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
933 +
934 +#ifndef _IPT_TTL_H
935 +#define _IPT_TTL_H
936 +
937 +enum {
938 +       IPT_TTL_SET = 0,
939 +       IPT_TTL_INC,
940 +       IPT_TTL_DEC
941 +};
942 +
943 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
944 +
945 +struct ipt_TTL_info {
946 +       u_int8_t        mode;
947 +       u_int8_t        ttl;
948 +};
949 +
950 +
951 +#endif
952 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
953 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h  1970-01-01 01:00:00.000000000 +0100
954 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_XOR.h      2004-06-08 10:37:54.000000000 +0200
955 @@ -0,0 +1,9 @@
956 +#ifndef _IPT_XOR_H
957 +#define _IPT_XOR_H
958 +
959 +struct ipt_XOR_info {
960 +       char            key[30];
961 +       u_int8_t        block_size;
962 +};
963 +
964 +#endif /* _IPT_XOR_H */
965 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
966 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h     1970-01-01 01:00:00.000000000 +0100
967 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-06-08 10:38:04.000000000 +0200
968 @@ -0,0 +1,11 @@
969 +#ifndef _IPT_ADDRTYPE_H
970 +#define _IPT_ADDRTYPE_H
971 +
972 +struct ipt_addrtype_info {
973 +       u_int16_t       source;         /* source-type mask */
974 +       u_int16_t       dest;           /* dest-type mask */
975 +       int             invert_source;
976 +       int             invert_dest;
977 +};
978 +
979 +#endif
980 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h
981 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h    1970-01-01 01:00:00.000000000 +0100
982 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h        2004-06-08 10:31:23.000000000 +0200
983 @@ -0,0 +1,12 @@
984 +#ifndef _IPT_CONNLIMIT_H
985 +#define _IPT_CONNLIMIT_H
986 +
987 +struct ipt_connlimit_data;
988 +
989 +struct ipt_connlimit_info {
990 +       int limit;
991 +       int inverse;
992 +       u_int32_t mask;
993 +       struct ipt_connlimit_data *data;
994 +};
995 +#endif /* _IPT_CONNLIMIT_H */
996 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
997 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h     1970-01-01 01:00:00.000000000 +0100
998 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-06-08 10:36:58.000000000 +0200
999 @@ -0,0 +1,18 @@
1000 +#ifndef _IPT_CONNMARK_H
1001 +#define _IPT_CONNMARK_H
1002 +
1003 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
1004 + * by Henrik Nordstrom <hno@marasystems.com>
1005 + *
1006 + * This program is free software; you can redistribute it and/or modify
1007 + * it under the terms of the GNU General Public License as published by
1008 + * the Free Software Foundation; either version 2 of the License, or
1009 + * (at your option) any later version.
1010 + */
1011 +
1012 +struct ipt_connmark_info {
1013 +       unsigned long mark, mask;
1014 +       u_int8_t invert;
1015 +};
1016 +
1017 +#endif /*_IPT_CONNMARK_H*/
1018 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h
1019 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h     1970-01-01 01:00:00.000000000 +0100
1020 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-06-08 10:31:34.000000000 +0200
1021 @@ -0,0 +1,39 @@
1022 +#ifndef _IPT_DSTLIMIT_H
1023 +#define _IPT_DSTLIMIT_H
1024 +
1025 +/* timings are in milliseconds. */
1026 +#define IPT_DSTLIMIT_SCALE 10000
1027 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
1028 +   seconds, or one every 59 hours. */
1029 +
1030 +/* details of this structure hidden by the implementation */
1031 +struct ipt_dstlimit_htable;
1032 +
1033 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
1034 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
1035 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
1036 +
1037 +struct dstlimit_cfg {
1038 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
1039 +       u_int32_t avg;    /* Average secs between packets * scale */
1040 +       u_int32_t burst;  /* Period multiplier for upper limit. */
1041 +
1042 +       /* user specified */
1043 +       u_int32_t size;         /* how many buckets */
1044 +       u_int32_t max;          /* max number of entries */
1045 +       u_int32_t gc_interval;  /* gc interval */
1046 +       u_int32_t expire;       /* when do entries expire? */
1047 +};
1048 +
1049 +struct ipt_dstlimit_info {
1050 +       char name [IFNAMSIZ];           /* name */
1051 +       struct dstlimit_cfg cfg;
1052 +       struct ipt_dstlimit_htable *hinfo;
1053 +
1054 +       /* Used internally by the kernel */
1055 +       union {
1056 +               void *ptr;
1057 +               struct ipt_dstlimit_info *master;
1058 +       } u;
1059 +};
1060 +#endif /*_IPT_DSTLIMIT_H*/
1061 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h
1062 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h        1970-01-01 01:00:00.000000000 +0100
1063 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h    2004-06-08 10:31:37.000000000 +0200
1064 @@ -0,0 +1,21 @@
1065 +#ifndef _IPT_FUZZY_H
1066 +#define _IPT_FUZZY_H
1067 +
1068 +#include <linux/param.h>
1069 +#include <linux/types.h>
1070 +
1071 +#define MAXFUZZYRATE 10000000
1072 +#define MINFUZZYRATE 3
1073 +
1074 +struct ipt_fuzzy_info {
1075 +       u_int32_t minimum_rate;
1076 +       u_int32_t maximum_rate;
1077 +       u_int32_t packets_total;
1078 +       u_int32_t bytes_total;
1079 +       u_int32_t previous_time;
1080 +       u_int32_t present_time;
1081 +       u_int32_t mean_rate;
1082 +       u_int8_t acceptance_rate;
1083 +};
1084 +
1085 +#endif /*_IPT_FUZZY_H*/
1086 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h
1087 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h  1970-01-01 01:00:00.000000000 +0100
1088 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h      2004-06-08 10:31:39.000000000 +0200
1089 @@ -0,0 +1,21 @@
1090 +#ifndef __ipt_ipv4options_h_included__
1091 +#define __ipt_ipv4options_h_included__
1092 +
1093 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
1094 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
1095 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
1096 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
1097 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
1098 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
1099 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
1100 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
1101 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1102 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
1103 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
1104 +
1105 +struct ipt_ipv4options_info {
1106 +       u_int16_t options;
1107 +};
1108 +
1109 +
1110 +#endif /* __ipt_ipv4options_h_included__ */
1111 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_mport.h
1112 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h        1970-01-01 01:00:00.000000000 +0100
1113 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_mport.h    2004-06-08 10:31:40.000000000 +0200
1114 @@ -0,0 +1,24 @@
1115 +#ifndef _IPT_MPORT_H
1116 +#define _IPT_MPORT_H
1117 +#include <linux/netfilter_ipv4/ip_tables.h>
1118 +
1119 +#define IPT_MPORT_SOURCE (1<<0)
1120 +#define IPT_MPORT_DESTINATION (1<<1)
1121 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1122 +
1123 +#define IPT_MULTI_PORTS        15
1124 +
1125 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1126 +/* every entry in ports[] except for the last one has one bit in pflags
1127 + * associated with it. If this bit is set, the port is the first port of
1128 + * a portrange, with the next entry being the last.
1129 + * End of list is marked with pflags bit set and port=65535.
1130 + * If 14 ports are used (last one does not have a pflag), the last port
1131 + * is repeated to fill the last entry in ports[] */
1132 +struct ipt_mport
1133 +{
1134 +       u_int8_t flags:2;                       /* Type of comparison */
1135 +       u_int16_t pflags:14;                    /* Port flags */
1136 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
1137 +};
1138 +#endif /*_IPT_MPORT_H*/
1139 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_nth.h
1140 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h  1970-01-01 01:00:00.000000000 +0100
1141 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_nth.h      2004-06-08 10:31:42.000000000 +0200
1142 @@ -0,0 +1,19 @@
1143 +#ifndef _IPT_NTH_H
1144 +#define _IPT_NTH_H
1145 +
1146 +#include <linux/param.h>
1147 +#include <linux/types.h>
1148 +
1149 +#ifndef IPT_NTH_NUM_COUNTERS
1150 +#define IPT_NTH_NUM_COUNTERS 16
1151 +#endif
1152 +
1153 +struct ipt_nth_info {
1154 +       u_int8_t every;
1155 +       u_int8_t not;
1156 +       u_int8_t startat;
1157 +       u_int8_t counter;
1158 +       u_int8_t packet;
1159 +};
1160 +
1161 +#endif /*_IPT_NTH_H*/
1162 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_osf.h
1163 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h  1970-01-01 01:00:00.000000000 +0100
1164 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_osf.h      2004-06-08 10:31:44.000000000 +0200
1165 @@ -0,0 +1,148 @@
1166 +/*
1167 + * ipt_osf.h
1168 + *
1169 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1170 + *
1171 + *
1172 + * This program is free software; you can redistribute it and/or modify
1173 + * it under the terms of the GNU General Public License as published by
1174 + * the Free Software Foundation; either version 2 of the License, or
1175 + * (at your option) any later version.
1176 + *
1177 + * This program is distributed in the hope that it will be useful,
1178 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1179 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1180 + * GNU General Public License for more details.
1181 + *
1182 + * You should have received a copy of the GNU General Public License
1183 + * along with this program; if not, write to the Free Software
1184 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1185 + */
1186 +
1187 +#ifndef _IPT_OSF_H
1188 +#define _IPT_OSF_H
1189 +
1190 +#define MAXGENRELEN            32
1191 +#define MAXDETLEN              64
1192 +
1193 +#define IPT_OSF_GENRE          1
1194 +#define        IPT_OSF_SMART           2
1195 +#define IPT_OSF_LOG            4
1196 +#define IPT_OSF_NETLINK                8
1197 +
1198 +#define IPT_OSF_LOGLEVEL_ALL   0
1199 +#define IPT_OSF_LOGLEVEL_FIRST 1
1200 +
1201 +#include <linux/list.h>
1202 +
1203 +#ifndef __KERNEL__
1204 +#include <netinet/ip.h>
1205 +#include <netinet/tcp.h>
1206 +
1207 +struct list_head
1208 +{
1209 +       struct list_head *prev, *next;
1210 +};
1211 +#endif
1212 +
1213 +struct ipt_osf_info
1214 +{
1215 +       char                    genre[MAXGENRELEN];
1216 +       int                     len;
1217 +       unsigned long           flags;
1218 +       int                     loglevel;
1219 +       int                     invert; /* UNSUPPORTED */
1220 +};
1221 +
1222 +struct osf_wc
1223 +{
1224 +       char                    wc;
1225 +       unsigned long           val;
1226 +};
1227 +
1228 +/* This struct represents IANA options
1229 + * http://www.iana.org/assignments/tcp-parameters
1230 + */
1231 +struct osf_opt
1232 +{
1233 +       unsigned char           kind;
1234 +       unsigned char           length;
1235 +       struct osf_wc           wc;
1236 +};
1237 +
1238 +struct osf_finger
1239 +{
1240 +       struct list_head        flist;
1241 +       struct osf_wc           wss;
1242 +       unsigned char           ttl;
1243 +       unsigned char           df;
1244 +       unsigned long           ss;
1245 +       unsigned char           genre[MAXGENRELEN];
1246 +       unsigned char           version[MAXGENRELEN], subtype[MAXGENRELEN];
1247 +       
1248 +       /* Not needed, but for consistency with original table from Michal Zalewski */
1249 +       unsigned char           details[MAXDETLEN]; 
1250 +
1251 +       int                     opt_num;
1252 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1253 +
1254 +};
1255 +
1256 +struct ipt_osf_nlmsg
1257 +{
1258 +       struct osf_finger       f;
1259 +       struct iphdr            ip;
1260 +       struct tcphdr           tcp;
1261 +};
1262 +
1263 +#ifdef __KERNEL__
1264 +
1265 +/* Defines for IANA option kinds */
1266 +
1267 +#define OSFOPT_EOL             0       /* End of options */
1268 +#define OSFOPT_NOP             1       /* NOP */
1269 +#define OSFOPT_MSS             2       /* Maximum segment size */
1270 +#define OSFOPT_WSO             3       /* Window scale option */
1271 +#define OSFOPT_SACKP           4       /* SACK permitted */
1272 +#define OSFOPT_SACK            5       /* SACK */
1273 +#define OSFOPT_ECHO            6       
1274 +#define OSFOPT_ECHOREPLY       7
1275 +#define OSFOPT_TS              8       /* Timestamp option */
1276 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
1277 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
1278 +/* Others are not used in current OSF */
1279 +
1280 +static struct osf_opt IANA_opts[] = 
1281 +{
1282 +       {0, 1,},
1283 +       {1, 1,},
1284 +       {2, 4,},
1285 +       {3, 3,},
1286 +       {4, 2,},
1287 +       {5, 1 ,}, /* SACK length is not defined */
1288 +       {6, 6,},
1289 +       {7, 6,},
1290 +       {8, 10,},
1291 +       {9, 2,},
1292 +       {10, 3,},
1293 +       {11, 1,}, /* CC: Suppose 1 */
1294 +       {12, 1,}, /* the same */
1295 +       {13, 1,}, /* and here too */
1296 +       {14, 3,},
1297 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1298 +       {16, 1,},
1299 +       {17, 1,},
1300 +       {18, 3,},
1301 +       {19, 18,},
1302 +       {20, 1,},
1303 +       {21, 1,},
1304 +       {22, 1,},
1305 +       {23, 1,},
1306 +       {24, 1,},
1307 +       {25, 1,},
1308 +       {26, 1,},
1309 +};
1310 +
1311 +#endif /* __KERNEL__ */
1312 +
1313 +#endif /* _IPT_OSF_H */
1314 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_policy.h
1315 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h       1970-01-01 01:00:00.000000000 +0100
1316 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_policy.h   2004-06-08 10:42:36.000000000 +0200
1317 @@ -0,0 +1,52 @@
1318 +#ifndef _IPT_POLICY_H
1319 +#define _IPT_POLICY_H
1320 +
1321 +#define POLICY_MAX_ELEM        4
1322 +
1323 +enum ipt_policy_flags
1324 +{
1325 +       POLICY_MATCH_IN         = 0x1,
1326 +       POLICY_MATCH_OUT        = 0x2,
1327 +       POLICY_MATCH_NONE       = 0x4,
1328 +       POLICY_MATCH_STRICT     = 0x8,
1329 +};
1330 +
1331 +enum ipt_policy_modes
1332 +{
1333 +       POLICY_MODE_TRANSPORT,
1334 +       POLICY_MODE_TUNNEL
1335 +};
1336 +
1337 +struct ipt_policy_spec
1338 +{
1339 +       u_int8_t        saddr:1,
1340 +                       daddr:1,
1341 +                       proto:1,
1342 +                       mode:1,
1343 +                       spi:1,
1344 +                       reqid:1;
1345 +};
1346 +
1347 +struct ipt_policy_elem
1348 +{
1349 +       u_int32_t       saddr;
1350 +       u_int32_t       smask;
1351 +       u_int32_t       daddr;
1352 +       u_int32_t       dmask;
1353 +       u_int32_t       spi;
1354 +       u_int32_t       reqid;
1355 +       u_int8_t        proto;
1356 +       u_int8_t        mode;
1357 +
1358 +       struct ipt_policy_spec  match;
1359 +       struct ipt_policy_spec  invert;
1360 +};
1361 +
1362 +struct ipt_policy_info
1363 +{
1364 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1365 +       u_int16_t flags;
1366 +       u_int16_t len;
1367 +};
1368 +
1369 +#endif /* _IPT_POLICY_H */
1370 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_pool.h
1371 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1372 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_pool.h     2004-06-08 10:31:45.000000000 +0200
1373 @@ -0,0 +1,25 @@
1374 +#ifndef _IPT_POOL_H
1375 +#define _IPT_POOL_H
1376 +
1377 +#include <linux/netfilter_ipv4/ip_pool.h>
1378 +
1379 +#define IPT_POOL_INV_SRC       0x00000001
1380 +#define IPT_POOL_INV_DST       0x00000002
1381 +#define IPT_POOL_DEL_SRC       0x00000004
1382 +#define IPT_POOL_DEL_DST       0x00000008
1383 +#define IPT_POOL_INV_MOD_SRC   0x00000010
1384 +#define IPT_POOL_INV_MOD_DST   0x00000020
1385 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
1386 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
1387 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
1388 +#define IPT_POOL_MOD_DST_DROP  0x00000200
1389 +
1390 +/* match info */
1391 +struct ipt_pool_info
1392 +{
1393 +       ip_pool_t src;
1394 +       ip_pool_t dst;
1395 +       unsigned flags;
1396 +};
1397 +
1398 +#endif /*_IPT_POOL_H*/
1399 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_psd.h
1400 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h  1970-01-01 01:00:00.000000000 +0100
1401 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_psd.h      2004-06-08 10:31:53.000000000 +0200
1402 @@ -0,0 +1,40 @@
1403 +#ifndef _IPT_PSD_H
1404 +#define _IPT_PSD_H
1405 +
1406 +#include <linux/param.h>
1407 +#include <linux/types.h>
1408 +
1409 +/*
1410 + * High port numbers have a lower weight to reduce the frequency of false
1411 + * positives, such as from passive mode FTP transfers.
1412 + */
1413 +#define PORT_WEIGHT_PRIV               3
1414 +#define PORT_WEIGHT_HIGH               1
1415 +
1416 +/*
1417 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1418 + * from the same source, with no longer than DELAY ticks between ports.
1419 + */
1420 +#define SCAN_MIN_COUNT                 7
1421 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1422 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
1423 +#define SCAN_DELAY_THRESHOLD           (300) /* old usage of HZ here was erroneously and broke under uml */
1424 +
1425 +/*
1426 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1427 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1428 + * HASH_MAX source addresses per the same hash value.
1429 + */
1430 +#define LIST_SIZE                      0x100
1431 +#define HASH_LOG                       9
1432 +#define HASH_SIZE                      (1 << HASH_LOG)
1433 +#define HASH_MAX                       0x10
1434 +
1435 +struct ipt_psd_info {
1436 +       unsigned int weight_threshold;
1437 +       unsigned int delay_threshold;
1438 +       unsigned short lo_ports_weight;
1439 +       unsigned short hi_ports_weight;
1440 +};
1441 +
1442 +#endif /*_IPT_PSD_H*/
1443 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_quota.h
1444 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h        1970-01-01 01:00:00.000000000 +0100
1445 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_quota.h    2004-06-08 10:31:54.000000000 +0200
1446 @@ -0,0 +1,11 @@
1447 +#ifndef _IPT_QUOTA_H
1448 +#define _IPT_QUOTA_H
1449 +
1450 +/* print debug info in both kernel/netfilter module & iptable library */
1451 +//#define DEBUG_IPT_QUOTA
1452 +
1453 +struct ipt_quota_info {
1454 +        u_int64_t quota;
1455 +};
1456 +
1457 +#endif /*_IPT_QUOTA_H*/
1458 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_random.h
1459 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_random.h       1970-01-01 01:00:00.000000000 +0100
1460 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_random.h   2004-06-08 10:31:56.000000000 +0200
1461 @@ -0,0 +1,11 @@
1462 +#ifndef _IPT_RAND_H
1463 +#define _IPT_RAND_H
1464 +
1465 +#include <linux/param.h>
1466 +#include <linux/types.h>
1467 +
1468 +struct ipt_rand_info {
1469 +       u_int8_t average;
1470 +};
1471 +
1472 +#endif /*_IPT_RAND_H*/
1473 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_realm.h
1474 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h        1970-01-01 01:00:00.000000000 +0100
1475 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_realm.h    2004-06-08 10:32:20.000000000 +0200
1476 @@ -0,0 +1,9 @@
1477 +#ifndef _IPT_REALM_H
1478 +#define _IPT_REALM_H
1479 +
1480 +struct ipt_realm_info {
1481 +       u_int32_t id;
1482 +       u_int32_t mask;
1483 +       u_int8_t invert;
1484 +};
1485 +#endif /*_IPT_REALM_H*/
1486 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_sctp.h
1487 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
1488 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_sctp.h     2004-06-08 10:32:21.000000000 +0200
1489 @@ -0,0 +1,107 @@
1490 +#ifndef _IPT_SCTP_H_
1491 +#define _IPT_SCTP_H_
1492 +
1493 +#define IPT_SCTP_SRC_PORTS             0x01
1494 +#define IPT_SCTP_DEST_PORTS            0x02
1495 +#define IPT_SCTP_CHUNK_TYPES           0x04
1496 +
1497 +#define IPT_SCTP_VALID_FLAGS           0x07
1498 +
1499 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1500 +
1501 +
1502 +struct ipt_sctp_flag_info {
1503 +       u_int8_t chunktype;
1504 +       u_int8_t flag;
1505 +       u_int8_t flag_mask;
1506 +};
1507 +
1508 +#define IPT_NUM_SCTP_FLAGS     4
1509 +
1510 +struct ipt_sctp_info {
1511 +       u_int16_t dpts[2];  /* Min, Max */
1512 +       u_int16_t spts[2];  /* Min, Max */
1513 +
1514 +       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
1515 +
1516 +#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
1517 +#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
1518 +#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
1519 +
1520 +       u_int32_t chunk_match_type;
1521 +       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1522 +       int flag_count;
1523 +
1524 +       u_int32_t flags;
1525 +       u_int32_t invflags;
1526 +};
1527 +
1528 +#define bytes(type) (sizeof(type) * 8)
1529 +
1530 +#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
1531 +       do {                                            \
1532 +               chunkmap[type / bytes(u_int32_t)] |=    \
1533 +                       1 << (type % bytes(u_int32_t)); \
1534 +       } while (0)
1535 +
1536 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
1537 +       do {                                                    \
1538 +               chunkmap[type / bytes(u_int32_t)] &=            \
1539 +                       ~(1 << (type % bytes(u_int32_t)));      \
1540 +       } while (0)
1541 +
1542 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
1543 +({                                                             \
1544 +       (chunkmap[type / bytes (u_int32_t)] &                   \
1545 +               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
1546 +})
1547 +
1548 +#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
1549 +       do {                                                    \
1550 +               int i;                                          \
1551 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1552 +                       chunkmap[i] = 0;                        \
1553 +       } while (0)
1554 +
1555 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
1556 +       do {                                                    \
1557 +               int i;                                          \
1558 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1559 +                       chunkmap[i] = ~0;                       \
1560 +       } while (0)
1561 +
1562 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
1563 +       do {                                                    \
1564 +               int i;                                          \
1565 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1566 +                       destmap[i] = srcmap[i];                 \
1567 +       } while (0)
1568 +
1569 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
1570 +({                                                     \
1571 +       int i;                                          \
1572 +       int flag = 1;                                   \
1573 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1574 +               if (chunkmap[i]) {                      \
1575 +                       flag = 0;                       \
1576 +                       break;                          \
1577 +               }                                       \
1578 +       }                                               \
1579 +        flag;                                          \
1580 +})
1581 +
1582 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
1583 +({                                                     \
1584 +       int i;                                          \
1585 +       int flag = 1;                                   \
1586 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1587 +               if (chunkmap[i] != ~0) {                \
1588 +                       flag = 0;                       \
1589 +                               break;                  \
1590 +               }                                       \
1591 +       }                                               \
1592 +        flag;                                          \
1593 +})
1594 +
1595 +#endif /* _IPT_SCTP_H_ */
1596 +
1597 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_string.h
1598 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_string.h       1970-01-01 01:00:00.000000000 +0100
1599 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_string.h   2004-06-08 10:41:24.000000000 +0200
1600 @@ -0,0 +1,21 @@
1601 +#ifndef _IPT_STRING_H
1602 +#define _IPT_STRING_H
1603 +
1604 +/* *** PERFORMANCE TWEAK ***
1605 + * Packet size and search string threshold,
1606 + * above which sublinear searches is used. */
1607 +#define IPT_STRING_HAYSTACK_THRESH     100
1608 +#define IPT_STRING_NEEDLE_THRESH       20
1609 +
1610 +#define BM_MAX_NLEN 256
1611 +#define BM_MAX_HLEN 1024
1612 +
1613 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1614 +
1615 +struct ipt_string_info {
1616 +    char string[BM_MAX_NLEN];
1617 +    u_int16_t invert;
1618 +    u_int16_t len;
1619 +};
1620 +
1621 +#endif /* _IPT_STRING_H */
1622 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_time.h
1623 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1624 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_time.h     2004-06-08 10:32:31.000000000 +0200
1625 @@ -0,0 +1,15 @@
1626 +#ifndef __ipt_time_h_included__
1627 +#define __ipt_time_h_included__
1628 +
1629 +
1630 +struct ipt_time_info {
1631 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
1632 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
1633 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
1634 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
1635 +       time_t    date_start;
1636 +       time_t    date_stop;
1637 +};
1638 +
1639 +
1640 +#endif /* __ipt_time_h_included__ */
1641 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_u32.h
1642 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h  1970-01-01 01:00:00.000000000 +0100
1643 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4/ipt_u32.h      2004-06-08 10:32:32.000000000 +0200
1644 @@ -0,0 +1,40 @@
1645 +#ifndef _IPT_U32_H
1646 +#define _IPT_U32_H
1647 +#include <linux/netfilter_ipv4/ip_tables.h>
1648 +
1649 +enum ipt_u32_ops
1650 +{
1651 +       IPT_U32_AND,
1652 +       IPT_U32_LEFTSH,
1653 +       IPT_U32_RIGHTSH,
1654 +       IPT_U32_AT
1655 +};
1656 +
1657 +struct ipt_u32_location_element
1658 +{
1659 +       u_int32_t number;
1660 +       u_int8_t nextop;
1661 +};
1662 +struct ipt_u32_value_element
1663 +{
1664 +       u_int32_t min;
1665 +       u_int32_t max;
1666 +};
1667 +/* *** any way to allow for an arbitrary number of elements?
1668 +   for now I settle for a limit of 10 of each */
1669 +#define U32MAXSIZE 10
1670 +struct ipt_u32_test
1671 +{
1672 +       u_int8_t nnums;
1673 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
1674 +       u_int8_t nvalues;
1675 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
1676 +};
1677 +
1678 +struct ipt_u32
1679 +{
1680 +       u_int8_t ntests;
1681 +       struct ipt_u32_test tests[U32MAXSIZE+1];
1682 +};
1683 +
1684 +#endif /*_IPT_U32_H*/
1685 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.7-rc3/include/linux/netfilter_ipv4.h
1686 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv4.h  2004-06-07 21:14:57.000000000 +0200
1687 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv4.h      2004-06-08 10:38:44.000000000 +0200
1688 @@ -7,6 +7,8 @@
1689  
1690  #include <linux/config.h>
1691  #include <linux/netfilter.h>
1692 +#include <linux/netdevice.h>
1693 +#include <net/protocol.h>
1694  
1695  /* IP Cache bits. */
1696  /* Src IP address. */
1697 @@ -85,6 +87,58 @@
1698     Returns true or false. */
1699  extern int skb_ip_make_writable(struct sk_buff **pskb,
1700                                 unsigned int writable_len);
1701 +
1702 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1703 +#include <net/route.h>
1704 +#include <net/xfrm.h>
1705 +
1706 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1707 +{
1708 +       return !skb->sp || skb->sp->decap_done;
1709 +}
1710 +
1711 +static inline int
1712 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1713 +{
1714 +       return skb->sp && !skb->sp->decap_done
1715 +              && (!ipprot || !ipprot->xfrm_prot);
1716 +}
1717 +
1718 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1719 +{
1720 +       return skb->sp && !skb->sp->decap_done
1721 +              && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1722 +}
1723 +
1724 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1725 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1726 +#else /* CONFIG_XFRM */
1727 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1728 +{
1729 +       return 1;
1730 +}
1731 +
1732 +static inline int
1733 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1734 +{
1735 +       return 0;
1736 +}
1737 +
1738 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1739 +{
1740 +       return 0;
1741 +}
1742 +
1743 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1744 +{
1745 +       return 0;
1746 +}
1747 +
1748 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1749 +{
1750 +       return 0; 
1751 +}
1752 +#endif /* CONFIG_XFRM */
1753  #endif /*__KERNEL__*/
1754  
1755  #endif /*__LINUX_IP_NETFILTER_H*/
1756 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6_tables.h
1757 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h       2004-06-07 21:15:11.000000000 +0200
1758 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6_tables.h   2004-06-08 10:37:30.000000000 +0200
1759 @@ -142,6 +142,12 @@
1760         /* Back pointer */
1761         unsigned int comefrom;
1762  
1763 +       /* Name of the chain */
1764 +       char *chainname;
1765 +       
1766 +       /* Rule number in the chain. */
1767 +       u_int32_t rulenum;
1768 +
1769         /* Packet and byte counters. */
1770         struct ip6t_counters counters;
1771  
1772 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_HL.h
1773 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h  1970-01-01 01:00:00.000000000 +0100
1774 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_HL.h      2004-06-08 10:31:03.000000000 +0200
1775 @@ -0,0 +1,22 @@
1776 +/* Hop Limit modification module for ip6tables
1777 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1778 + * Based on HW's TTL module */
1779 +
1780 +#ifndef _IP6T_HL_H
1781 +#define _IP6T_HL_H
1782 +
1783 +enum {
1784 +       IP6T_HL_SET = 0,
1785 +       IP6T_HL_INC,
1786 +       IP6T_HL_DEC
1787 +};
1788 +
1789 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
1790 +
1791 +struct ip6t_HL_info {
1792 +       u_int8_t        mode;
1793 +       u_int8_t        hop_limit;
1794 +};
1795 +
1796 +
1797 +#endif
1798 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h
1799 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-06-07 21:13:34.000000000 +0200
1800 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-06-08 10:31:20.000000000 +0200
1801 @@ -2,15 +2,17 @@
1802  #define _IP6T_REJECT_H
1803  
1804  enum ip6t_reject_with {
1805 -       IP6T_ICMP_NET_UNREACHABLE,
1806 -       IP6T_ICMP_HOST_UNREACHABLE,
1807 -       IP6T_ICMP_PROT_UNREACHABLE,
1808 -       IP6T_ICMP_PORT_UNREACHABLE,
1809 -       IP6T_ICMP_ECHOREPLY
1810 +       IP6T_ICMP6_NO_ROUTE,
1811 +       IP6T_ICMP6_ADM_PROHIBITED,
1812 +       IP6T_ICMP6_NOT_NEIGHBOUR,
1813 +       IP6T_ICMP6_ADDR_UNREACH,
1814 +       IP6T_ICMP6_PORT_UNREACH,
1815 +       IP6T_ICMP6_ECHOREPLY,
1816 +       IP6T_TCP_RESET
1817  };
1818  
1819  struct ip6t_reject_info {
1820         enum ip6t_reject_with with;      /* reject type */
1821  };
1822  
1823 -#endif /*_IPT_REJECT_H*/
1824 +#endif /*_IP6T_REJECT_H*/
1825 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h
1826 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h       1970-01-01 01:00:00.000000000 +0100
1827 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_ROUTE.h   2004-06-08 10:37:08.000000000 +0200
1828 @@ -0,0 +1,22 @@
1829 +/* Header file for iptables ip6t_ROUTE target
1830 + *
1831 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
1832 + *
1833 + * This software is distributed under GNU GPL v2, 1991
1834 + */
1835 +#ifndef _IPT_ROUTE_H_target
1836 +#define _IPT_ROUTE_H_target
1837 +
1838 +#define IP6T_ROUTE_IFNAMSIZ 16
1839 +
1840 +struct ip6t_route_target_info {
1841 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
1842 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
1843 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
1844 +       u_int8_t  flags;
1845 +};
1846 +
1847 +/* Values for "flags" field */
1848 +#define IP6T_ROUTE_CONTINUE        0x01
1849 +
1850 +#endif /*_IP6T_ROUTE_H_target*/
1851 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1852 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h       1970-01-01 01:00:00.000000000 +0100
1853 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h   2004-06-08 10:31:37.000000000 +0200
1854 @@ -0,0 +1,21 @@
1855 +#ifndef _IP6T_FUZZY_H
1856 +#define _IP6T_FUZZY_H
1857 +
1858 +#include <linux/param.h>
1859 +#include <linux/types.h>
1860 +
1861 +#define MAXFUZZYRATE 10000000
1862 +#define MINFUZZYRATE 3
1863 +
1864 +struct ip6t_fuzzy_info {
1865 +       u_int32_t minimum_rate;
1866 +       u_int32_t maximum_rate;
1867 +       u_int32_t packets_total;
1868 +       u_int32_t bytes_total;
1869 +       u_int32_t previous_time;
1870 +       u_int32_t present_time;
1871 +       u_int32_t mean_rate;
1872 +       u_int8_t acceptance_rate;
1873 +};
1874 +
1875 +#endif /*_IP6T_FUZZY_H*/
1876 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_nth.h
1877 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1878 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_nth.h     2004-06-08 10:31:42.000000000 +0200
1879 @@ -0,0 +1,19 @@
1880 +#ifndef _IP6T_NTH_H
1881 +#define _IP6T_NTH_H
1882 +
1883 +#include <linux/param.h>
1884 +#include <linux/types.h>
1885 +
1886 +#ifndef IP6T_NTH_NUM_COUNTERS
1887 +#define IP6T_NTH_NUM_COUNTERS 16
1888 +#endif
1889 +
1890 +struct ip6t_nth_info {
1891 +       u_int8_t every;
1892 +       u_int8_t not;
1893 +       u_int8_t startat;
1894 +       u_int8_t counter;
1895 +       u_int8_t packet;
1896 +};
1897 +
1898 +#endif /*_IP6T_NTH_H*/
1899 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_owner.h
1900 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h       2004-06-07 21:14:41.000000000 +0200
1901 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_owner.h   2004-06-08 10:40:01.000000000 +0200
1902 @@ -6,12 +6,14 @@
1903  #define IP6T_OWNER_GID 0x02
1904  #define IP6T_OWNER_PID 0x04
1905  #define IP6T_OWNER_SID 0x08
1906 +#define IP6T_OWNER_COMM 0x10
1907  
1908  struct ip6t_owner_info {
1909      uid_t uid;
1910      gid_t gid;
1911      pid_t pid;
1912      pid_t sid;
1913 +    char comm[16];
1914      u_int8_t match, invert;    /* flags */
1915  };
1916  
1917 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_policy.h
1918 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h      1970-01-01 01:00:00.000000000 +0100
1919 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_policy.h  2004-06-08 10:42:36.000000000 +0200
1920 @@ -0,0 +1,52 @@
1921 +#ifndef _IP6T_POLICY_H
1922 +#define _IP6T_POLICY_H
1923 +
1924 +#define POLICY_MAX_ELEM        4
1925 +
1926 +enum ip6t_policy_flags
1927 +{
1928 +       POLICY_MATCH_IN         = 0x1,
1929 +       POLICY_MATCH_OUT        = 0x2,
1930 +       POLICY_MATCH_NONE       = 0x4,
1931 +       POLICY_MATCH_STRICT     = 0x8,
1932 +};
1933 +
1934 +enum ip6t_policy_modes
1935 +{
1936 +       POLICY_MODE_TRANSPORT,
1937 +       POLICY_MODE_TUNNEL
1938 +};
1939 +
1940 +struct ip6t_policy_spec
1941 +{
1942 +       u_int8_t        saddr:1,
1943 +                       daddr:1,
1944 +                       proto:1,
1945 +                       mode:1,
1946 +                       spi:1,
1947 +                       reqid:1;
1948 +};
1949 +
1950 +struct ip6t_policy_elem
1951 +{
1952 +       struct in6_addr saddr;
1953 +       struct in6_addr smask;
1954 +       struct in6_addr daddr;
1955 +       struct in6_addr dmask;
1956 +       u_int32_t       spi;
1957 +       u_int32_t       reqid;
1958 +       u_int8_t        proto;
1959 +       u_int8_t        mode;
1960 +
1961 +       struct ip6t_policy_spec match;
1962 +       struct ip6t_policy_spec invert;
1963 +};
1964 +
1965 +struct ip6t_policy_info
1966 +{
1967 +       struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
1968 +       u_int16_t flags;
1969 +       u_int16_t len;
1970 +};
1971 +
1972 +#endif /* _IP6T_POLICY_H */
1973 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_random.h
1974 --- linux-2.6.7-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h      1970-01-01 01:00:00.000000000 +0100
1975 +++ linux-2.6.7-rc3/include/linux/netfilter_ipv6/ip6t_random.h  2004-06-08 10:31:56.000000000 +0200
1976 @@ -0,0 +1,11 @@
1977 +#ifndef _IP6T_RAND_H
1978 +#define _IP6T_RAND_H
1979 +
1980 +#include <linux/param.h>
1981 +#include <linux/types.h>
1982 +
1983 +struct ip6t_rand_info {
1984 +       u_int8_t average;
1985 +};
1986 +
1987 +#endif /*_IP6T_RAND_H*/
1988 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/netfilter_mime.h linux-2.6.7-rc3/include/linux/netfilter_mime.h
1989 --- linux-2.6.7-rc3.org/include/linux/netfilter_mime.h  1970-01-01 01:00:00.000000000 +0100
1990 +++ linux-2.6.7-rc3/include/linux/netfilter_mime.h      2004-06-08 10:40:46.000000000 +0200
1991 @@ -0,0 +1,89 @@
1992 +/*
1993 + * MIME functions for netfilter modules.  This file provides implementations
1994 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
1995 + * HTTP, RTSP, SIP, etc.
1996 + *
1997 + * gcc will warn for defined but unused functions, so we only include the
1998 + * functions requested.  The following macros are used:
1999 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
2000 + */
2001 +#ifndef _NETFILTER_MIME_H
2002 +#define _NETFILTER_MIME_H
2003 +
2004 +/* Only include these functions for kernel code. */
2005 +#ifdef __KERNEL__
2006 +
2007 +#include <linux/ctype.h>
2008 +
2009 +/*
2010 + * Given a buffer and length, advance to the next line and mark the current
2011 + * line.  If the current line is empty, *plinelen will be set to zero.  If
2012 + * not, it will be set to the actual line length (including CRLF).
2013 + *
2014 + * 'line' in this context means logical line (includes LWS continuations).
2015 + * Returns 1 on success, 0 on failure.
2016 + */
2017 +#ifdef NF_NEED_MIME_NEXTLINE
2018 +static int
2019 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
2020 +{
2021 +    uint    off = *poff;
2022 +    uint    physlen = 0;
2023 +    int     is_first_line = 1;
2024 +
2025 +    if (off >= len)
2026 +    {
2027 +        return 0;
2028 +    }
2029 +
2030 +    do
2031 +    {
2032 +        while (p[off] != '\n')
2033 +        {
2034 +            if (len-off <= 1)
2035 +            {
2036 +                return 0;
2037 +            }
2038 +
2039 +            physlen++;
2040 +            off++;
2041 +        }
2042 +
2043 +        /* if we saw a crlf, physlen needs adjusted */
2044 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
2045 +        {
2046 +            physlen--;
2047 +        }
2048 +
2049 +        /* advance past the newline */
2050 +        off++;
2051 +
2052 +        /* check for an empty line */
2053 +        if (physlen == 0)
2054 +        {
2055 +            break;
2056 +        }
2057 +
2058 +        /* check for colon on the first physical line */
2059 +        if (is_first_line)
2060 +        {
2061 +            is_first_line = 0;
2062 +            if (memchr(p+(*poff), ':', physlen) == NULL)
2063 +            {
2064 +                return 0;
2065 +            }
2066 +        }
2067 +    }
2068 +    while (p[off] == ' ' || p[off] == '\t');
2069 +
2070 +    *plineoff = *poff;
2071 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
2072 +    *poff = off;
2073 +
2074 +    return 1;
2075 +}
2076 +#endif /* NF_NEED_MIME_NEXTLINE */
2077 +
2078 +#endif /* __KERNEL__ */
2079 +
2080 +#endif /* _NETFILTER_MIME_H */
2081 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/linux/skbuff.h linux-2.6.7-rc3/include/linux/skbuff.h
2082 --- linux-2.6.7-rc3.org/include/linux/skbuff.h  2004-06-07 21:14:33.000000000 +0200
2083 +++ linux-2.6.7-rc3/include/linux/skbuff.h      2004-06-08 10:30:55.000000000 +0200
2084 @@ -1049,6 +1049,14 @@
2085         if (nfct)
2086                 atomic_inc(&nfct->master->use);
2087  }
2088 +static inline void nf_reset(struct sk_buff *skb)
2089 +{
2090 +       nf_conntrack_put(skb->nfct);
2091 +       skb->nfct = NULL;
2092 +#ifdef CONFIG_NETFILTER_DEBUG
2093 +       skb->nf_debug = 0;
2094 +#endif
2095 +}
2096  
2097  #ifdef CONFIG_BRIDGE_NETFILTER
2098  static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2099 @@ -1061,9 +1069,10 @@
2100         if (nf_bridge)
2101                 atomic_inc(&nf_bridge->use);
2102  }
2103 -#endif
2104 -
2105 -#endif
2106 +#endif /* CONFIG_BRIDGE_NETFILTER */
2107 +#else /* CONFIG_NETFILTER */
2108 +static inline void nf_reset(struct sk_buff *skb) {}
2109 +#endif /* CONFIG_NETFILTER */
2110  
2111  #endif /* __KERNEL__ */
2112  #endif /* _LINUX_SKBUFF_H */
2113 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/ip.h linux-2.6.7-rc3/include/net/ip.h
2114 --- linux-2.6.7-rc3.org/include/net/ip.h        2004-06-07 21:14:42.000000000 +0200
2115 +++ linux-2.6.7-rc3/include/net/ip.h    2004-06-08 10:38:43.000000000 +0200
2116 @@ -30,6 +30,8 @@
2117  #include <linux/netdevice.h>
2118  #include <linux/inetdevice.h>
2119  #include <linux/in_route.h>
2120 +#include <linux/netfilter.h>
2121 +#include <linux/netfilter_ipv4.h>
2122  #include <net/route.h>
2123  #include <net/arp.h>
2124  
2125 @@ -48,6 +50,7 @@
2126  #define IPSKB_TRANSLATED       2
2127  #define IPSKB_FORWARDED                4
2128  #define IPSKB_XFRM_TUNNEL_SIZE 8
2129 +#define IPSKB_XFRM_TRANSFORMED 16
2130  };
2131  
2132  struct ipcm_cookie
2133 @@ -212,6 +215,12 @@
2134                 __ip_select_ident(iph, dst, more);
2135  }
2136  
2137 +extern inline int ip_dst_output(struct sk_buff *skb)
2138 +{
2139 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2140 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2141 +}
2142 +
2143  /*
2144   *     Map a multicast IP onto multicast MAC for type ethernet.
2145   */
2146 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/protocol.h linux-2.6.7-rc3/include/net/protocol.h
2147 --- linux-2.6.7-rc3.org/include/net/protocol.h  2004-06-07 21:14:10.000000000 +0200
2148 +++ linux-2.6.7-rc3/include/net/protocol.h      2004-06-08 10:38:44.000000000 +0200
2149 @@ -39,6 +39,7 @@
2150         int                     (*handler)(struct sk_buff *skb);
2151         void                    (*err_handler)(struct sk_buff *skb, u32 info);
2152         int                     no_policy;
2153 +       int                     xfrm_prot;
2154  };
2155  
2156  #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2157 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/tcp.h linux-2.6.7-rc3/include/net/tcp.h
2158 --- linux-2.6.7-rc3.org/include/net/tcp.h       2004-06-07 21:13:39.000000000 +0200
2159 +++ linux-2.6.7-rc3/include/net/tcp.h   2004-06-08 10:39:56.000000000 +0200
2160 @@ -162,6 +162,7 @@
2161  extern void tcp_bucket_unlock(struct sock *sk);
2162  extern int tcp_port_rover;
2163  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2164 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2165  
2166  /* These are AF independent. */
2167  static __inline__ int tcp_bhashfn(__u16 lport)
2168 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/udp.h linux-2.6.7-rc3/include/net/udp.h
2169 --- linux-2.6.7-rc3.org/include/net/udp.h       2004-06-07 21:14:56.000000000 +0200
2170 +++ linux-2.6.7-rc3/include/net/udp.h   2004-06-08 10:39:56.000000000 +0200
2171 @@ -74,6 +74,8 @@
2172  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2173  extern int     udp_disconnect(struct sock *sk, int flags);
2174  
2175 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2176 +
2177  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2178  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
2179  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
2180 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/include/net/xfrm.h linux-2.6.7-rc3/include/net/xfrm.h
2181 --- linux-2.6.7-rc3.org/include/net/xfrm.h      2004-06-07 21:14:56.000000000 +0200
2182 +++ linux-2.6.7-rc3/include/net/xfrm.h  2004-06-08 10:38:44.000000000 +0200
2183 @@ -540,6 +540,9 @@
2184  {
2185         atomic_t                refcnt;
2186         int                     len;
2187 +#ifdef CONFIG_NETFILTER
2188 +       int                     decap_done;
2189 +#endif
2190         struct sec_decap_state  x[XFRM_MAX_DEPTH];
2191  };
2192  
2193 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/core/netfilter.c linux-2.6.7-rc3/net/core/netfilter.c
2194 --- linux-2.6.7-rc3.org/net/core/netfilter.c    2004-06-07 21:14:11.000000000 +0200
2195 +++ linux-2.6.7-rc3/net/core/netfilter.c        2004-06-08 10:38:46.000000000 +0200
2196 @@ -27,6 +27,8 @@
2197  #include <linux/icmp.h>
2198  #include <net/sock.h>
2199  #include <net/route.h>
2200 +#include <net/xfrm.h>
2201 +#include <net/ip.h>
2202  #include <linux/ip.h>
2203  
2204  /* In this code, we can be waiting indefinitely for userspace to
2205 @@ -630,7 +632,6 @@
2206  #ifdef CONFIG_IP_ROUTE_FWMARK
2207                 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2208  #endif
2209 -               fl.proto = iph->protocol;
2210                 if (ip_route_output_key(&rt, &fl) != 0)
2211                         return -1;
2212  
2213 @@ -657,6 +658,20 @@
2214         if ((*pskb)->dst->error)
2215                 return -1;
2216  
2217 +#ifdef CONFIG_XFRM
2218 +       if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2219 +               struct xfrm_policy_afinfo *afinfo;
2220 +
2221 +               afinfo = xfrm_policy_get_afinfo(AF_INET);
2222 +               if (afinfo != NULL) {
2223 +                       afinfo->decode_session(*pskb, &fl);
2224 +                       xfrm_policy_put_afinfo(afinfo);
2225 +                       if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2226 +                               return -1;
2227 +               }
2228 +       }
2229 +#endif
2230 +
2231         /* Change in oif may mean change in hh_len. */
2232         hh_len = (*pskb)->dst->dev->hard_header_len;
2233         if (skb_headroom(*pskb) < hh_len) {
2234 @@ -674,6 +689,71 @@
2235         return 0;
2236  }
2237  
2238 +#ifdef CONFIG_XFRM
2239 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2240 +{
2241 +       skb->sp->decap_done = 1;
2242 +       dst_release(skb->dst);
2243 +       skb->dst = NULL;
2244 +       nf_reset(skb);
2245 +       return netif_rx(skb);
2246 +}
2247 +
2248 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2249 +{
2250 +       __skb_push(skb, skb->data - skb->nh.raw);
2251 +       /* Fix header len and checksum if last xfrm was transport mode */
2252 +       if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2253 +               skb->nh.iph->tot_len = htons(skb->len);
2254 +               ip_send_check(skb->nh.iph);
2255 +       }
2256 +       return nf_rcv_postxfrm_nonlocal(skb);
2257 +}
2258 +
2259 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2260 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2261 +#include <linux/netfilter_ipv4/ip_nat.h>
2262 +
2263 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2264 +{
2265 +       struct ip_conntrack *ct;
2266 +       struct ip_conntrack_tuple *t;
2267 +       struct ip_nat_info_manip *m;
2268 +       unsigned int i;
2269 +
2270 +       if (skb->nfct == NULL)
2271 +               return;
2272 +       ct = (struct ip_conntrack *)skb->nfct->master;
2273 +
2274 +       for (i = 0; i < ct->nat.info.num_manips; i++) {
2275 +               m = &ct->nat.info.manips[i];
2276 +               t = &ct->tuplehash[m->direction].tuple;
2277 +
2278 +               switch (m->hooknum) {
2279 +               case NF_IP_PRE_ROUTING:
2280 +                       if (m->maniptype != IP_NAT_MANIP_DST)
2281 +                               break;
2282 +                       fl->fl4_dst = t->dst.ip;
2283 +                       if (t->dst.protonum == IPPROTO_TCP ||
2284 +                           t->dst.protonum == IPPROTO_UDP)
2285 +                               fl->fl_ip_dport = t->dst.u.tcp.port;
2286 +                       break;
2287 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2288 +               case NF_IP_LOCAL_IN:
2289 +                       if (m->maniptype != IP_NAT_MANIP_SRC)
2290 +                               break;
2291 +                       fl->fl4_src = t->src.ip;
2292 +                       if (t->dst.protonum == IPPROTO_TCP ||
2293 +                           t->dst.protonum == IPPROTO_UDP)
2294 +                               fl->fl_ip_sport = t->src.u.tcp.port;
2295 +                       break;
2296 +#endif
2297 +               }
2298 +       }
2299 +}
2300 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2301 +#endif
2302 +
2303  int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2304  {
2305         struct sk_buff *nskb;
2306 @@ -831,3 +911,4 @@
2307  EXPORT_SYMBOL(nf_unregister_hook);
2308  EXPORT_SYMBOL(nf_unregister_queue_handler);
2309  EXPORT_SYMBOL(nf_unregister_sockopt);
2310 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2311 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ah4.c linux-2.6.7-rc3/net/ipv4/ah4.c
2312 --- linux-2.6.7-rc3.org/net/ipv4/ah4.c  2004-06-07 21:14:58.000000000 +0200
2313 +++ linux-2.6.7-rc3/net/ipv4/ah4.c      2004-06-08 10:38:44.000000000 +0200
2314 @@ -146,6 +146,7 @@
2315                 err = -EHOSTUNREACH;
2316                 goto error_nolock;
2317         }
2318 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2319         return NET_XMIT_BYPASS;
2320  
2321  error:
2322 @@ -344,6 +345,7 @@
2323         .handler        =       xfrm4_rcv,
2324         .err_handler    =       ah4_err,
2325         .no_policy      =       1,
2326 +       .xfrm_prot      =       1,
2327  };
2328  
2329  static int __init ah4_init(void)
2330 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/esp4.c linux-2.6.7-rc3/net/ipv4/esp4.c
2331 --- linux-2.6.7-rc3.org/net/ipv4/esp4.c 2004-06-07 21:14:33.000000000 +0200
2332 +++ linux-2.6.7-rc3/net/ipv4/esp4.c     2004-06-08 10:38:44.000000000 +0200
2333 @@ -216,6 +216,7 @@
2334                 err = -EHOSTUNREACH;
2335                 goto error_nolock;
2336         }
2337 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2338         return NET_XMIT_BYPASS;
2339  
2340  error:
2341 @@ -598,6 +599,7 @@
2342         .handler        =       xfrm4_rcv,
2343         .err_handler    =       esp4_err,
2344         .no_policy      =       1,
2345 +       .xfrm_prot      =       1,
2346  };
2347  
2348  static int __init esp4_init(void)
2349 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/igmp.c linux-2.6.7-rc3/net/ipv4/igmp.c
2350 --- linux-2.6.7-rc3.org/net/ipv4/igmp.c 2004-06-07 21:15:12.000000000 +0200
2351 +++ linux-2.6.7-rc3/net/ipv4/igmp.c     2004-06-08 10:38:43.000000000 +0200
2352 @@ -343,7 +343,7 @@
2353         pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2354  
2355         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2356 -                      dst_output);
2357 +                      ip_dst_output);
2358  }
2359  
2360  static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2361 @@ -673,7 +673,7 @@
2362         ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2363  
2364         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2365 -                      dst_output);
2366 +                      ip_dst_output);
2367  }
2368  
2369  static void igmp_gq_timer_expire(unsigned long data)
2370 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_forward.c linux-2.6.7-rc3/net/ipv4/ip_forward.c
2371 --- linux-2.6.7-rc3.org/net/ipv4/ip_forward.c   2004-06-07 21:13:35.000000000 +0200
2372 +++ linux-2.6.7-rc3/net/ipv4/ip_forward.c       2004-06-08 10:38:43.000000000 +0200
2373 @@ -51,7 +51,7 @@
2374         if (unlikely(opt->optlen))
2375                 ip_forward_options(skb);
2376  
2377 -       return dst_output(skb);
2378 +       return ip_dst_output(skb);
2379  }
2380  
2381  int ip_forward(struct sk_buff *skb)
2382 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_gre.c linux-2.6.7-rc3/net/ipv4/ip_gre.c
2383 --- linux-2.6.7-rc3.org/net/ipv4/ip_gre.c       2004-06-07 21:14:55.000000000 +0200
2384 +++ linux-2.6.7-rc3/net/ipv4/ip_gre.c   2004-06-08 10:30:55.000000000 +0200
2385 @@ -643,13 +643,7 @@
2386                 skb->dev = tunnel->dev;
2387                 dst_release(skb->dst);
2388                 skb->dst = NULL;
2389 -#ifdef CONFIG_NETFILTER
2390 -               nf_conntrack_put(skb->nfct);
2391 -               skb->nfct = NULL;
2392 -#ifdef CONFIG_NETFILTER_DEBUG
2393 -               skb->nf_debug = 0;
2394 -#endif
2395 -#endif
2396 +               nf_reset(skb);
2397                 ipgre_ecn_decapsulate(iph, skb);
2398                 netif_rx(skb);
2399                 read_unlock(&ipgre_lock);
2400 @@ -877,13 +871,7 @@
2401                 }
2402         }
2403  
2404 -#ifdef CONFIG_NETFILTER
2405 -       nf_conntrack_put(skb->nfct);
2406 -       skb->nfct = NULL;
2407 -#ifdef CONFIG_NETFILTER_DEBUG
2408 -       skb->nf_debug = 0;
2409 -#endif
2410 -#endif
2411 +       nf_reset(skb);
2412  
2413         IPTUNNEL_XMIT();
2414         tunnel->recursion--;
2415 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_input.c linux-2.6.7-rc3/net/ipv4/ip_input.c
2416 --- linux-2.6.7-rc3.org/net/ipv4/ip_input.c     2004-06-07 21:13:37.000000000 +0200
2417 +++ linux-2.6.7-rc3/net/ipv4/ip_input.c 2004-06-08 10:38:46.000000000 +0200
2418 @@ -202,18 +202,10 @@
2419  
2420  #ifdef CONFIG_NETFILTER_DEBUG
2421         nf_debug_ip_local_deliver(skb);
2422 -       skb->nf_debug = 0;
2423  #endif /*CONFIG_NETFILTER_DEBUG*/
2424  
2425         __skb_pull(skb, ihl);
2426  
2427 -#ifdef CONFIG_NETFILTER
2428 -       /* Free reference early: we don't need it any more, and it may
2429 -           hold ip_conntrack module loaded indefinitely. */
2430 -       nf_conntrack_put(skb->nfct);
2431 -       skb->nfct = NULL;
2432 -#endif /*CONFIG_NETFILTER*/
2433 -
2434          /* Point into the IP datagram, just past the header. */
2435          skb->h.raw = skb->data;
2436  
2437 @@ -228,6 +220,13 @@
2438         resubmit:
2439                 hash = protocol & (MAX_INET_PROTOS - 1);
2440                 raw_sk = sk_head(&raw_v4_htable[hash]);
2441 +               ipprot = inet_protos[hash];
2442 +               smp_read_barrier_depends();
2443 +
2444 +               if (nf_xfrm_local_done(skb, ipprot)) {
2445 +                       nf_rcv_postxfrm_local(skb);
2446 +                       goto out;
2447 +               }
2448  
2449                 /* If there maybe a raw socket we must check - if not we
2450                  * don't care less
2451 @@ -235,14 +234,15 @@
2452                 if (raw_sk)
2453                         raw_v4_input(skb, skb->nh.iph, hash);
2454  
2455 -               if ((ipprot = inet_protos[hash]) != NULL) {
2456 +               if (ipprot != NULL) {
2457                         int ret;
2458  
2459 -                       smp_read_barrier_depends();
2460 -                       if (!ipprot->no_policy &&
2461 -                           !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2462 -                               kfree_skb(skb);
2463 -                               goto out;
2464 +                       if (!ipprot->no_policy) {
2465 +                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2466 +                                       kfree_skb(skb);
2467 +                                       goto out;
2468 +                               }
2469 +                               nf_reset(skb);
2470                         }
2471                         ret = ipprot->handler(skb);
2472                         if (ret < 0) {
2473 @@ -283,8 +283,8 @@
2474                         return 0;
2475         }
2476  
2477 -       return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2478 -                      ip_local_deliver_finish);
2479 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2480 +                           ip_local_deliver_finish, nf_hook_input_cond(skb));
2481  }
2482  
2483  static inline int ip_rcv_finish(struct sk_buff *skb)
2484 @@ -301,6 +301,9 @@
2485                         goto drop; 
2486         }
2487  
2488 +       if (nf_xfrm_nonlocal_done(skb))
2489 +               return nf_rcv_postxfrm_nonlocal(skb);
2490 +
2491  #ifdef CONFIG_NET_CLS_ROUTE
2492         if (skb->dst->tclassid) {
2493                 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2494 @@ -422,8 +425,8 @@
2495                 }
2496         }
2497  
2498 -       return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2499 -                      ip_rcv_finish);
2500 +       return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2501 +                           ip_rcv_finish, nf_hook_input_cond(skb));
2502  
2503  inhdr_error:
2504         IP_INC_STATS_BH(InHdrErrors);
2505 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ip_output.c linux-2.6.7-rc3/net/ipv4/ip_output.c
2506 --- linux-2.6.7-rc3.org/net/ipv4/ip_output.c    2004-06-07 21:15:12.000000000 +0200
2507 +++ linux-2.6.7-rc3/net/ipv4/ip_output.c        2004-06-08 10:38:43.000000000 +0200
2508 @@ -123,6 +123,15 @@
2509         return ttl;
2510  }
2511  
2512 +#ifdef CONFIG_NETFILTER
2513 +/* out-of-line copy is only required with netfilter */
2514 +int ip_dst_output(struct sk_buff *skb)
2515 +{
2516 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2517 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2518 +}
2519 +#endif
2520 +
2521  /* 
2522   *             Add an ip header to a skbuff and send it out.
2523   *
2524 @@ -165,7 +174,7 @@
2525  
2526         /* Send it out. */
2527         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2528 -                      dst_output);
2529 +                      ip_dst_output);
2530  }
2531  
2532  static inline int ip_finish_output2(struct sk_buff *skb)
2533 @@ -284,7 +293,7 @@
2534                 return ip_finish_output(skb);
2535  }
2536  
2537 -int ip_output(struct sk_buff **pskb)
2538 +static inline int ip_output2(struct sk_buff **pskb)
2539  {
2540         struct sk_buff *skb = *pskb;
2541  
2542 @@ -297,6 +306,16 @@
2543                 return ip_finish_output(skb);
2544  }
2545  
2546 +int ip_output(struct sk_buff *skb)
2547 +{
2548 +       int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2549 +
2550 +       if (transformed)
2551 +               nf_reset(skb);
2552 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2553 +                           skb->dst->dev, ip_output2, transformed);
2554 +}
2555 +
2556  int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2557  {
2558         struct sock *sk = skb->sk;
2559 @@ -390,7 +409,7 @@
2560         skb->priority = sk->sk_priority;
2561  
2562         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2563 -                      dst_output);
2564 +                      ip_dst_output);
2565  
2566  no_route:
2567         IP_INC_STATS(OutNoRoutes);
2568 @@ -1180,7 +1199,7 @@
2569  
2570         /* Netfilter gets whole the not fragmented skb. */
2571         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
2572 -                     skb->dst->dev, dst_output);
2573 +                     skb->dst->dev, ip_dst_output);
2574         if (err) {
2575                 if (err > 0)
2576                         err = inet->recverr ? net_xmit_errno(err) : 0;
2577 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ipcomp.c linux-2.6.7-rc3/net/ipv4/ipcomp.c
2578 --- linux-2.6.7-rc3.org/net/ipv4/ipcomp.c       2004-06-07 21:14:58.000000000 +0200
2579 +++ linux-2.6.7-rc3/net/ipv4/ipcomp.c   2004-06-08 10:38:44.000000000 +0200
2580 @@ -232,6 +232,7 @@
2581                 err = -EHOSTUNREACH;
2582                 goto error_nolock;
2583         }
2584 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2585         err = NET_XMIT_BYPASS;
2586  
2587  out_exit:
2588 @@ -409,6 +410,7 @@
2589         .handler        =       xfrm4_rcv,
2590         .err_handler    =       ipcomp4_err,
2591         .no_policy      =       1,
2592 +       .xfrm_prot      =       1,
2593  };
2594  
2595  static int __init ipcomp4_init(void)
2596 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ipip.c linux-2.6.7-rc3/net/ipv4/ipip.c
2597 --- linux-2.6.7-rc3.org/net/ipv4/ipip.c 2004-06-07 21:15:21.000000000 +0200
2598 +++ linux-2.6.7-rc3/net/ipv4/ipip.c     2004-06-08 10:38:44.000000000 +0200
2599 @@ -478,6 +478,11 @@
2600  
2601         read_lock(&ipip_lock);
2602         if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2603 +               /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2604 +               if (nf_xfrm_local_done(skb, NULL)) {
2605 +                       nf_rcv_postxfrm_local(skb);
2606 +                       return 0;
2607 +               }
2608                 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2609                         read_unlock(&ipip_lock);
2610                         kfree_skb(skb);
2611 @@ -497,13 +502,7 @@
2612                 skb->dev = tunnel->dev;
2613                 dst_release(skb->dst);
2614                 skb->dst = NULL;
2615 -#ifdef CONFIG_NETFILTER
2616 -               nf_conntrack_put(skb->nfct);
2617 -               skb->nfct = NULL;
2618 -#ifdef CONFIG_NETFILTER_DEBUG
2619 -               skb->nf_debug = 0;
2620 -#endif
2621 -#endif
2622 +               nf_reset(skb);
2623                 ipip_ecn_decapsulate(iph, skb);
2624                 netif_rx(skb);
2625                 read_unlock(&ipip_lock);
2626 @@ -648,13 +647,7 @@
2627         if ((iph->ttl = tiph->ttl) == 0)
2628                 iph->ttl        =       old_iph->ttl;
2629  
2630 -#ifdef CONFIG_NETFILTER
2631 -       nf_conntrack_put(skb->nfct);
2632 -       skb->nfct = NULL;
2633 -#ifdef CONFIG_NETFILTER_DEBUG
2634 -       skb->nf_debug = 0;
2635 -#endif
2636 -#endif
2637 +       nf_reset(skb);
2638  
2639         IPTUNNEL_XMIT();
2640         tunnel->recursion--;
2641 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/ipmr.c linux-2.6.7-rc3/net/ipv4/ipmr.c
2642 --- linux-2.6.7-rc3.org/net/ipv4/ipmr.c 2004-06-07 21:14:12.000000000 +0200
2643 +++ linux-2.6.7-rc3/net/ipv4/ipmr.c     2004-06-08 10:38:43.000000000 +0200
2644 @@ -1105,10 +1105,7 @@
2645         skb->h.ipiph = skb->nh.iph;
2646         skb->nh.iph = iph;
2647         memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
2648 -#ifdef CONFIG_NETFILTER
2649 -       nf_conntrack_put(skb->nfct);
2650 -       skb->nfct = NULL;
2651 -#endif
2652 +       nf_reset(skb);
2653  }
2654  
2655  static inline int ipmr_forward_finish(struct sk_buff *skb)
2656 @@ -1120,7 +1117,7 @@
2657         if (unlikely(opt->optlen))
2658                 ip_forward_options(skb);
2659  
2660 -       return dst_output(skb);
2661 +       return ip_dst_output(skb);
2662  }
2663  
2664  /*
2665 @@ -1461,10 +1458,7 @@
2666         skb->dst = NULL;
2667         ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
2668         ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
2669 -#ifdef CONFIG_NETFILTER
2670 -       nf_conntrack_put(skb->nfct);
2671 -       skb->nfct = NULL;
2672 -#endif
2673 +       nf_reset(skb);
2674         netif_rx(skb);
2675         dev_put(reg_dev);
2676         return 0;
2677 @@ -1520,10 +1514,7 @@
2678         ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len;
2679         ((struct net_device_stats*)reg_dev->priv)->rx_packets++;
2680         skb->dst = NULL;
2681 -#ifdef CONFIG_NETFILTER
2682 -       nf_conntrack_put(skb->nfct);
2683 -       skb->nfct = NULL;
2684 -#endif
2685 +       nf_reset(skb);
2686         netif_rx(skb);
2687         dev_put(reg_dev);
2688         return 0;
2689 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.7-rc3/net/ipv4/netfilter/Kconfig
2690 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/Kconfig      2004-06-07 21:14:56.000000000 +0200
2691 +++ linux-2.6.7-rc3/net/ipv4/netfilter/Kconfig  2004-06-08 10:42:36.000000000 +0200
2692 @@ -206,6 +206,11 @@
2693  
2694           To compile it as a module, choose M here.  If unsure, say N.
2695  
2696 +config IP_NF_MATCH_UNCLEAN
2697 +       tristate  'unclean match support (EXPERIMENTAL)'
2698 +       depends on EXPERIMENTAL && IP_NF_IPTABLES
2699 +         help
2700 +
2701  config IP_NF_MATCH_TTL
2702         tristate "TTL match support"
2703         depends on IP_NF_IPTABLES
2704 @@ -603,5 +608,492 @@
2705           <file:Documentation/modules.txt>.  If unsure, say `N'.
2706           help
2707  
2708 +config IP_NF_TARGET_IPV4OPTSSTRIP
2709 +       tristate  'IPV4OPTSSTRIP target support'
2710 +       depends on IP_NF_MANGLE
2711 +       help
2712 +         This option adds an IPV4OPTSSTRIP target.
2713 +         This target allows you to strip all IP options in a packet.
2714 +        
2715 +         If you want to compile it as a module, say M here and read
2716 +         Documentation/modules.txt.  If unsure, say `N'.
2717 +
2718 +config IP_NF_TARGET_NETLINK
2719 +       tristate  'NETLINK target support'
2720 +       depends on IP_NF_FILTER
2721 +       help
2722 +         The NETLINK target allows you to recieve packets in userspace via
2723 +         the kernel firewall netlink socket. Apps such as fwmon
2724 +         (http://firestorm.geek-ware.co.uk) can then recieve and dislpay
2725 +         these packets. This option is basically a re-implementation of the
2726 +         ipchains -o option.
2727 +
2728 +config IP_NF_TARGET_TTL
2729 +       tristate  'TTL target support'
2730 +       depends on IP_NF_MANGLE
2731 +       help
2732 +         This option adds a `TTL' target, which enables the user to set
2733 +         the TTL value or increment / decrement the TTL value by a given
2734 +         amount.
2735 +       
2736 +         If you want to compile it as a module, say M here and read
2737 +         Documentation/modules.txt.  If unsure, say `N'.
2738 +
2739 +config IP_NF_MATCH_CONNLIMIT
2740 +       tristate  'Connections/IP limit match support'
2741 +       depends on IP_NF_IPTABLES
2742 +       help
2743 +         This match allows you to restrict the number of parallel TCP
2744 +         connections to a server per client IP address (or address block).
2745 +       
2746 +         If you want to compile it as a module, say M here and read
2747 +         Documentation/modules.txt.  If unsure, say `N'.
2748 +
2749 +config IP_NF_MATCH_DSTLIMIT
2750 +       tristate  'dstlimit match support'
2751 +       depends on IP_NF_IPTABLES
2752 +
2753 +config IP_NF_MATCH_FUZZY
2754 +       tristate  'fuzzy match support'
2755 +       depends on IP_NF_IPTABLES
2756 +       help
2757 +         This option adds a `fuzzy' match, which allows you to match
2758 +         packets according to a fuzzy logic based law.
2759 +       
2760 +         If you want to compile it as a module, say M here and read
2761 +         Documentation/modules.txt.  If unsure, say `N'.
2762 +
2763 +config IP_NF_MATCH_IPV4OPTIONS
2764 +       tristate  'IPV4OPTIONS match support'
2765 +       depends on IP_NF_IPTABLES
2766 +       help
2767 +         This option adds a IPV4OPTIONS match.
2768 +         It allows you to filter options like source routing,
2769 +         record route, timestamp and router-altert.
2770 +       
2771 +         If you say Y here, try iptables -m ipv4options --help for more information.
2772 +        
2773 +         If you want to compile it as a module, say M here and read
2774 +         Documentation/modules.txt.  If unsure, say `N'.
2775 +
2776 +config IP_NF_MATCH_MPORT
2777 +       tristate  'Multiple port with ranges match support'
2778 +       depends on IP_NF_IPTABLES
2779 +       help
2780 +         This is an enhanced multiport match which supports port
2781 +         ranges as well as single ports.
2782 +       
2783 +         If you want to compile it as a module, say M here and read
2784 +         Documentation/modules.txt.  If unsure, say `N'.
2785 +
2786 +config IP_NF_MATCH_NTH
2787 +       tristate  'Nth match support'
2788 +       depends on IP_NF_IPTABLES
2789 +       help
2790 +         This option adds a `Nth' match, which allow you to make
2791 +         rules that match every Nth packet.  By default there are 
2792 +         16 different counters.
2793 +       
2794 +         [options]
2795 +          --every     Nth              Match every Nth packet
2796 +         [--counter]  num              Use counter 0-15 (default:0)
2797 +         [--start]    num              Initialize the counter at the number 'num'
2798 +                                       instead of 0. Must be between 0 and Nth-1
2799 +         [--packet]   num              Match on 'num' packet. Must be between 0
2800 +                                       and Nth-1.
2801 +       
2802 +                                       If --packet is used for a counter than
2803 +                                       there must be Nth number of --packet
2804 +                                       rules, covering all values between 0 and
2805 +                                       Nth-1 inclusively.
2806 +        
2807 +         If you want to compile it as a module, say M here and read
2808 +         Documentation/modules.txt.  If unsure, say `N'.
2809 +
2810 +config IP_NF_MATCH_OSF
2811 +       tristate  'OSF match support'
2812 +       depends on IP_NF_IPTABLES
2813 +       help
2814 +       
2815 +         The idea of passive OS fingerprint matching exists for quite a long time,
2816 +         but was created as extension fo OpenBSD pf only some weeks ago.
2817 +         Original idea was lurked in some OpenBSD mailing list (thanks
2818 +         grange@open...) and than adopted for Linux netfilter in form of this code.
2819 +       
2820 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
2821 +         his excellent p0f and than changed a bit for more convenience.
2822 +       
2823 +         This module compares some data(WS, MSS, options and it's order, ttl,
2824 +         df and others) from first SYN packet (actually from packets with SYN
2825 +         bit set) with hardcoded in fingers[] table ones.
2826 +       
2827 +         If you say Y here, try iptables -m osf --help for more information.
2828 +        
2829 +         If you want to compile it as a module, say M here and read
2830 +         Documentation/modules.txt.  If unsure, say `N'.
2831 +
2832 +config IP_POOL_STATISTICS
2833 +       bool  'enable statistics on pool usage'
2834 +       depends on IP_NF_POOL!=n
2835 +       help
2836 +         This option controls whether usage gathering code is compiled into the
2837 +         ip_pool module.  Disabling statistics may be substantially faster.
2838 +
2839 +config IP_NF_POOL
2840 +       tristate  'IP address pool support'
2841 +       depends on IP_NF_IPTABLES
2842 +       help
2843 +         Pool matching lets you use bitmaps with one bit per address from some
2844 +         range of IP addresses; the match depends on whether a checked source
2845 +         or destination address has its bit set in the pool.
2846 +       
2847 +         There is also a POOL netfilter target, which can be used to set or remove
2848 +         the addresses of a packet from a pool.
2849 +       
2850 +         To define and use pools, you need userlevel utilities: a patched iptables,
2851 +         and the program ippool(8), which defines the pools and their bounds.
2852 +         The current release of pool matching is ippool-0.0.2, and can be found
2853 +         in the archives of the netfilter mailing list at
2854 +         http://lists.samba.org/netfilter/.
2855 +       
2856 +         If you want to compile it as a module, say M here and read
2857 +         Documentation/modules.txt.  If unsure, say `N'.
2858 +
2859 +config IP_NF_MATCH_PSD
2860 +       tristate  'psd match support'
2861 +       depends on IP_NF_IPTABLES
2862 +       help
2863 +         This option adds a `psd' match, which allows you to create rules in
2864 +         any iptables table wich will detect TCP and UDP port scans.
2865 +        
2866 +         If you want to compile it as a module, say M here and read
2867 +         Documentation/modules.txt.  If unsure, say `N'.
2868 +
2869 +config IP_NF_MATCH_QUOTA
2870 +       tristate  'quota match support'
2871 +       depends on IP_NF_IPTABLES
2872 +       help
2873 +         This match implements network quotas.
2874 +       
2875 +         If you want to compile it as a module, say M here and read
2876 +         Documentation/modules.txt.  If unsure, say `N'.
2877 +       
2878 +
2879 +config IP_NF_MATCH_RANDOM
2880 +       tristate  'random match support'
2881 +       depends on IP_NF_IPTABLES
2882 +       help
2883 +         This option adds a `random' match,
2884 +         which allow you to match packets randomly
2885 +         following a given probability.
2886 +        
2887 +         If you want to compile it as a module, say M here and read
2888 +         Documentation/modules.txt.  If unsure, say `N'.
2889 +
2890 +config IP_NF_MATCH_REALM
2891 +       tristate  'realm match support'
2892 +       depends on IP_NF_IPTABLES && NET_CLS_ROUTE
2893 +       help
2894 +         This option adds a `realm' match, which allows you to use the realm
2895 +         key from the routing subsytem inside iptables.
2896 +       
2897 +         This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
2898 +         in tc world.
2899 +       
2900 +         If you want to compile it as a module, say M here and read
2901 +         Documentation/modules.txt.  If unsure, say `N'.
2902 +
2903 +config IP_NF_MATCH_SCTP
2904 +       tristate  'SCTP protocol match support'
2905 +       depends on IP_NF_IPTABLES
2906 +
2907 +config IP_NF_MATCH_TIME
2908 +       tristate  'TIME match support'
2909 +       depends on IP_NF_IPTABLES
2910 +       help
2911 +         This option adds a `time' match, which allows you
2912 +         to match based on the packet arrival time/date
2913 +         (arrival time/date at the machine which netfilter is running on) or
2914 +         departure time/date (for locally generated packets).
2915 +       
2916 +         If you say Y here, try iptables -m time --help for more information.
2917 +        
2918 +         If you want to compile it as a module, say M here and read
2919 +         Documentation/modules.txt.  If unsure, say `N'.
2920 +
2921 +config IP_NF_MATCH_U32
2922 +       tristate  'U32 match support'
2923 +       depends on IP_NF_IPTABLES
2924 +       help
2925 +         U32 allows you to extract quantities of up to 4 bytes from a packet,
2926 +         AND them with specified masks, shift them by specified amounts and
2927 +         test whether the results are in any of a set of specified ranges.
2928 +         The specification of what to extract is general enough to skip over
2929 +         headers with lengths stored in the packet, as in IP or TCP header
2930 +         lengths.
2931 +       
2932 +         Details and examples are in the kernel module source.
2933 +
2934 +config IP_NF_CONNTRACK_MARK
2935 +       bool  'Connection mark tracking support'
2936 +       help
2937 +         This option enables support for connection marks, used by the
2938 +         `CONNMARK' target and `connmark' match. Similar to the mark value
2939 +         of packets, but this mark value is kept in the conntrack session
2940 +         instead of the individual packets.
2941 +       
2942 +config IP_NF_TARGET_CONNMARK
2943 +       tristate  'CONNMARK target support'
2944 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
2945 +       help
2946 +         This option adds a `CONNMARK' target, which allows one to manipulate
2947 +         the connection mark value.  Similar to the MARK target, but
2948 +         affects the connection mark value rather than the packet mark value.
2949 +       
2950 +         If you want to compile it as a module, say M here and read
2951 +         Documentation/modules.txt.  The module will be called
2952 +         ipt_CONNMARK.o.  If unsure, say `N'.
2953 +       
2954 +config IP_NF_MATCH_CONNMARK
2955 +       tristate  ' Connection mark match support'
2956 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES
2957 +       help
2958 +         This option adds a `connmark' match, which allows you to match the
2959 +         connection mark value previously set for the session by `CONNMARK'. 
2960 +       
2961 +         If you want to compile it as a module, say M here and read
2962 +         Documentation/modules.txt.  The module will be called
2963 +         ipt_connmark.o.  If unsure, say `N'.
2964 +
2965 +config IP_NF_TARGET_IPMARK
2966 +       tristate  'IPMARK target support'
2967 +       depends on IP_NF_MANGLE
2968 +       help
2969 +         This option adds a `IPMARK' target, which allows you to create rules
2970 +         in the `mangle' table which alter the netfilter mark (nfmark) field
2971 +         basing on the source or destination ip address of the packet.
2972 +         This is very useful for very fast massive mangling and marking.
2973 +       
2974 +         If you want to compile it as a module, say M here and read
2975 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
2976 +
2977 +config IP_NF_TARGET_ROUTE
2978 +       tristate  'ROUTE target support'
2979 +       depends on IP_NF_MANGLE
2980 +       help
2981 +         This option adds a `ROUTE' target, which enables you to setup unusual
2982 +         routes. For example, the ROUTE lets you route a received packet through 
2983 +         an interface or towards a host, even if the regular destination of the 
2984 +         packet is the router itself. The ROUTE target is also able to change the 
2985 +         incoming interface of a packet.
2986 +       
2987 +         The target can be or not a final target. It has to be used inside the 
2988 +         mangle table.
2989 +         
2990 +         If you want to compile it as a module, say M here and read
2991 +         Documentation/modules.txt.  The module will be called ipt_ROUTE.o.
2992 +         If unsure, say `N'.
2993 +
2994 +config IP_NF_TARGET_TARPIT
2995 +       tristate 'TARPIT target support'
2996 +       depends on IP_NF_FILTER
2997 +       help
2998 +         Adds a TARPIT target to iptables, which captures and holds
2999 +         incoming TCP connections using no local per-connection resources.
3000 +         Connections are accepted, but immediately switched to the persist
3001 +         state (0 byte window), in which the remote side stops sending data
3002 +         and asks to continue every 60-240 seconds.  Attempts to close the
3003 +         connection are ignored, forcing the remote side to time out the
3004 +         connection in 12-24 minutes.
3005 +       
3006 +         This offers similar functionality to LaBrea
3007 +         <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
3008 +         hardware or IPs.  Any TCP port that you would normally DROP or REJECT
3009 +         can instead become a tarpit.
3010 +
3011 +config IP_NF_TARGET_TRACE
3012 +       tristate  'TRACE target support'
3013 +       depends on IP_NF_RAW
3014 +       help
3015 +         The TRACE target allows packets to be traced as those
3016 +         matches any subsequent rule in any table/rule. The matched
3017 +         rule and the packet is logged with the prefix
3018 +       
3019 +         TRACE: tablename/chainname/rulenum  
3020 +       
3021 +         If you want to compile it as a module, say M here and read
3022 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
3023 +
3024 +config IP_NF_TARGET_XOR
3025 +       tristate  'XOR target support'
3026 +       depends on IP_NF_MANGLE
3027 +       help
3028 +         This option adds a `XOR' target, which can encrypt TCP and 
3029 +         UDP traffic using a simple XOR encryption.
3030 +       
3031 +         If you want to compile it as a module, say M here and read
3032 +         Documentation/modules.txt.  If unsure, say `N'.
3033 +
3034 +config IP_NF_MATCH_ADDRTYPE
3035 +       tristate  'address type match support'
3036 +       depends on IP_NF_IPTABLES
3037 +       help
3038 +         This option allows you to match what routing thinks of an address,
3039 +         eg. UNICAST, LOCAL, BROADCAST, ...
3040 +       
3041 +         If you want to compile it as a module, say M here and read
3042 +         Documentation/modules.txt.  If unsure, say `N'.
3043 +
3044 +config IP_NF_EGG
3045 +       tristate  'Eggdrop bot support'
3046 +       depends on IP_NF_CONNTRACK
3047 +       help
3048 +         If you are running an eggdrop hub bot on this machine, then you
3049 +         may want to enable this feature. This enables eggdrop bots to share
3050 +         their user file to other eggdrop bots.
3051 +       
3052 +         If you want to compile it as a module, say M here and read
3053 +         Documentation/modules.txt.  If unsure, say `N'.
3054 +
3055 +config IP_NF_NAT_H323
3056 +       tristate
3057 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3058 +       default IP_NF_NAT if IP_NF_H323=y
3059 +       default m if IP_NF_H323=m
3060 +
3061 +config IP_NF_H323
3062 +       tristate  'H.323 (netmeeting) support'
3063 +       depends on IP_NF_CONNTRACK
3064 +       help
3065 +         H.323 is a standard signalling protocol used by teleconferencing
3066 +         softwares like netmeeting. With the ip_conntrack_h323 and
3067 +         the ip_nat_h323 modules you can support the protocol on a connection
3068 +         tracking/NATing firewall.
3069 +       
3070 +         If you want to compile it as a module, say 'M' here and read
3071 +         Documentation/modules.txt.  If unsure, say 'N'.
3072 +
3073 +config IP_NF_NAT_MMS
3074 +       tristate
3075 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3076 +       default IP_NF_NAT if IP_NF_MMS=y
3077 +       default m if IP_NF_MMS=m
3078 +
3079 +config IP_NF_MMS
3080 +       tristate  'MMS protocol support'
3081 +       depends on IP_NF_CONNTRACK
3082 +       help
3083 +         Tracking MMS (Microsoft Windows Media Services) connections
3084 +         could be problematic if random ports are used to send the
3085 +         streaming content. This option allows users to track streaming
3086 +         connections over random UDP or TCP ports.
3087 +       
3088 +         If you want to compile it as a module, say M here and read
3089 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
3090 +
3091 +config IP_NF_NAT_QUAKE3
3092 +       tristate
3093 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
3094 +       default IP_NF_NAT if IP_NF_QUAKE3=y
3095 +       default m if IP_NF_QUAKE3=m
3096 +
3097 +config IP_NF_QUAKE3
3098 +       tristate "Quake3 protocol support"
3099 +       depends on IP_NF_CONNTRACK
3100 +       help
3101 +         Quake III Arena  connection tracking helper. This module allows for a
3102 +         stricter firewall rulebase if one only allows traffic to a master
3103 +         server. Connections to Quake III server IP addresses and ports returned
3104 +         by the master server will be tracked automatically.
3105 +       
3106 +         If you want to compile it as a module, say M here and read
3107 +         <file:Documentation/modules.txt>.  If unsure, say `Y'.
3108 +
3109 +config IP_NF_RSH
3110 +       tristate  'RSH protocol support'
3111 +       depends on IP_NF_CONNTRACK
3112 +       help
3113 +         The RSH connection tracker is required if the dynamic
3114 +         stderr "Server to Client" connection is to occur during a
3115 +         normal RSH session.  This typically operates as follows;
3116 +       
3117 +           Client 0:1023 --> Server 514    (stream 1 - stdin/stdout)
3118 +           Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
3119 +       
3120 +         This connection tracker will identify new RSH sessions,
3121 +         extract the outbound session details, and notify netfilter
3122 +         of pending "related" sessions.
3123 +       
3124 +         Warning: This module could be dangerous. It is not "best
3125 +                  practice" to use RSH, use SSH in all instances.
3126 +                  (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
3127 +       
3128 +       
3129 +         If you want to compile it as a module, say M here and read
3130 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
3131 +
3132 +config IP_NF_NAT_RTSP
3133 +       tristate
3134 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3135 +       default IP_NF_NAT if IP_NF_RTSP=y
3136 +       default m if IP_NF_RTSP=m
3137 +
3138 +config IP_NF_RTSP
3139 +       tristate  ' RTSP protocol support'
3140 +       depends on IP_NF_CONNTRACK
3141 +       help
3142 +         Support the RTSP protocol.  This allows UDP transports to be setup
3143 +         properly, including RTP and RDT.
3144 +       
3145 +         If you want to compile it as a module, say 'M' here and read
3146 +         Documentation/modules.txt.  If unsure, say 'Y'.
3147 +
3148 +config IP_NF_CT_PROTO_SCTP
3149 +       tristate  'SCTP protocol connection tracking support'
3150 +       depends on IP_NF_CONNTRACK
3151 +
3152 +config IP_NF_MATCH_STRING
3153 +       tristate  'String match support'
3154 +       depends on IP_NF_IPTABLES
3155 +       help
3156 +         String matching alows you to match packets which contain a
3157 +         specified string of characters.
3158 +       
3159 +         If you want to compile it as a module, say M here and read
3160 +         Documentation/modules.txt.  If unsure, say `N'.
3161 +
3162 +config IP_NF_NAT_TALK
3163 +       tristate
3164 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
3165 +       default IP_NF_NAT if IP_NF_TALK=y
3166 +       default m if IP_NF_TALK=m
3167 +
3168 +config IP_NF_TALK
3169 +       tristate  'talk protocol support'
3170 +       depends on IP_NF_CONNTRACK
3171 +       help
3172 +         The talk protocols (both otalk/talk - or talk/ntalk, to confuse
3173 +         you by the different namings about which is old or which is new :-)
3174 +         use an additional channel to setup the talk session and a separated
3175 +         data channel for the actual conversation (like in FTP). Both the 
3176 +         initiating and the setup channels are over UDP, while the data channel 
3177 +         is over TCP, on a random port. The conntrack part of this extension
3178 +         will enable you to let in/out talk sessions easily by matching these
3179 +         connections as RELATED by the state match, while the NAT part helps
3180 +         you to let talk sessions trough a NAT machine.
3181 +       
3182 +         If you want to compile it as a module, say 'M' here and read
3183 +         Documentation/modules.txt.  If unsure, say 'N'.
3184 +
3185 +config IP_NF_MATCH_POLICY
3186 +       tristate "IPsec policy match support"
3187 +       depends on IP_NF_IPTABLES && XFRM
3188 +       help
3189 +         Policy matching allows you to match packets based on the
3190 +         IPsec policy that was used during decapsulation/will
3191 +         be used during encapsulation.
3192 +
3193 +         To compile it as a module, choose M here.  If unsure, say N.
3194 +
3195  endmenu
3196  
3197 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.7-rc3/net/ipv4/netfilter/Makefile
3198 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/Makefile     2004-06-07 21:14:01.000000000 +0200
3199 +++ linux-2.6.7-rc3/net/ipv4/netfilter/Makefile 2004-06-08 10:42:36.000000000 +0200
3200 @@ -19,10 +19,49 @@
3201  # connection tracking
3202  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
3203  
3204 +# talk protocol support
3205 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
3206 +ifdef CONFIG_IP_NF_TALK
3207 +       export-objs += ip_conntrack_talk.o
3208 +endif
3209 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
3210 +
3211 +
3212 +# SCTP protocol connection tracking
3213 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
3214
3215 +# H.323 support
3216 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
3217 +ifdef CONFIG_IP_NF_H323
3218 +       export-objs += ip_conntrack_h323.o
3219 +endif
3220 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
3221 +
3222 +
3223  # connection tracking helpers
3224 +
3225 +# rtsp protocol support
3226 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
3227 +ifdef CONFIG_IP_NF_NAT_RTSP
3228 +       export-objs += ip_conntrack_rtsp.o
3229 +endif
3230 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
3231 +
3232 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
3233 +ifdef CONFIG_IP_NF_NAT_QUAKE3
3234 +       export-objs += ip_conntrack_quake3.o
3235 +endif
3236 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
3237 +ifdef CONFIG_IP_NF_MMS
3238 +       export-objs += ip_conntrack_mms.o
3239 +endif
3240  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
3241  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
3242  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
3243 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
3244 +
3245 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
3246 +
3247  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
3248  
3249  # NAT helpers 
3250 @@ -30,6 +69,8 @@
3251  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
3252  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
3253  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
3254 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
3255 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
3256  
3257  # generic IP tables 
3258  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
3259 @@ -43,15 +84,39 @@
3260  # matches
3261  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
3262  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
3263 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
3264 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
3265 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
3266  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
3267 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
3268  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
3269  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
3270  
3271  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
3272  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
3273 +
3274 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
3275 +
3276  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
3277  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
3278  
3279 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
3280 +
3281 +
3282 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
3283 +
3284 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
3285 +
3286 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
3287 +
3288 +
3289 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
3290 +
3291 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
3292 +
3293 +
3294 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
3295 +
3296  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
3297  
3298  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
3299 @@ -60,28 +125,47 @@
3300  
3301  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
3302  
3303 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
3304 +
3305 +
3306 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
3307 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
3308  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
3309  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
3310 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
3311 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
3312  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
3313  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
3314 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
3315 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
3316  
3317  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
3318 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
3319  
3320  # targets
3321  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
3322 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
3323  obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
3324  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
3325  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
3326  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
3327 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
3328  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
3329  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
3330 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
3331  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
3332  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
3333  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
3334  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
3335  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
3336 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
3337 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
3338 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
3339 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
3340 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
3341  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
3342  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
3343 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
3344  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
3345  
3346  # generic ARP tables
3347 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_core.c
3348 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c  2004-06-07 21:13:34.000000000 +0200
3349 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_core.c      2004-06-08 10:36:58.000000000 +0200
3350 @@ -67,6 +67,7 @@
3351  static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
3352  struct list_head *ip_conntrack_hash;
3353  static kmem_cache_t *ip_conntrack_cachep;
3354 +static kmem_cache_t *ip_conntrack_expect_cachep;
3355  struct ip_conntrack ip_conntrack_untracked;
3356  
3357  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
3358 @@ -176,7 +177,7 @@
3359         IP_NF_ASSERT(atomic_read(&exp->use));
3360         IP_NF_ASSERT(!timer_pending(&exp->timeout));
3361  
3362 -       kfree(exp);
3363 +       kmem_cache_free(ip_conntrack_expect_cachep, exp);
3364  }
3365  
3366  
3367 @@ -324,8 +325,9 @@
3368                 ip_conntrack_destroyed(ct);
3369  
3370         WRITE_LOCK(&ip_conntrack_lock);
3371 -       /* Delete us from our own list to prevent corruption later */
3372 -       list_del(&ct->sibling_list);
3373 +       /* Make sure don't leave any orphaned expectations lying around */
3374 +       if (ct->expecting)
3375 +               remove_expectations(ct, 1);
3376  
3377         /* Delete our master expectation */
3378         if (ct->master) {
3379 @@ -335,7 +337,7 @@
3380                         list_del(&ct->master->expected_list);
3381                         master = ct->master->expectant;
3382                 }
3383 -               kfree(ct->master);
3384 +               kmem_cache_free(ip_conntrack_expect_cachep, ct->master);
3385         }
3386         WRITE_UNLOCK(&ip_conntrack_lock);
3387  
3388 @@ -692,25 +694,22 @@
3389                              struct ip_conntrack_expect *, tuple);
3390         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
3391  
3392 -       /* If master is not in hash table yet (ie. packet hasn't left
3393 -          this machine yet), how can other end know about expected?
3394 -          Hence these are not the droids you are looking for (if
3395 -          master ct never got confirmed, we'd hold a reference to it
3396 -          and weird things would happen to future packets). */
3397 -       if (expected && !is_confirmed(expected->expectant))
3398 -               expected = NULL;
3399 -
3400 -       /* Look up the conntrack helper for master connections only */
3401 -       if (!expected)
3402 -               conntrack->helper = ip_ct_find_helper(&repl_tuple);
3403 +       if (expected) {
3404 +               /* If master is not in hash table yet (ie. packet hasn't left
3405 +                  this machine yet), how can other end know about expected?
3406 +                  Hence these are not the droids you are looking for (if
3407 +                  master ct never got confirmed, we'd hold a reference to it
3408 +                  and weird things would happen to future packets). */
3409 +               if (!is_confirmed(expected->expectant)) {
3410 +                       conntrack->helper = ip_ct_find_helper(&repl_tuple);
3411 +                       goto end;
3412 +               }
3413  
3414 -       /* If the expectation is dying, then this is a loser. */
3415 -       if (expected
3416 -           && expected->expectant->helper->timeout
3417 -           && ! del_timer(&expected->timeout))
3418 -               expected = NULL;
3419 +               /* Expectation is dying... */
3420 +               if (expected->expectant->helper->timeout
3421 +                   && !del_timer(&expected->timeout))
3422 +                       goto end;       
3423  
3424 -       if (expected) {
3425                 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3426                         conntrack, expected);
3427                 /* Welcome, Mr. Bond.  We've been expecting you... */
3428 @@ -718,16 +717,28 @@
3429                 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3430                 conntrack->master = expected;
3431                 expected->sibling = conntrack;
3432 +#if CONFIG_IP_NF_CONNTRACK_MARK
3433 +               conntrack->mark = expected->expectant->mark;
3434 +#endif
3435                 LIST_DELETE(&ip_conntrack_expect_list, expected);
3436                 expected->expectant->expecting--;
3437                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3438 -       }
3439 -       atomic_inc(&ip_conntrack_count);
3440 +
3441 +               /* this is a braindead... --pablo */
3442 +               atomic_inc(&ip_conntrack_count);
3443 +               WRITE_UNLOCK(&ip_conntrack_lock);
3444 +
3445 +               if (expected->expectfn)
3446 +                       expected->expectfn(conntrack);
3447 +
3448 +               goto ret;
3449 +       } else 
3450 +               conntrack->helper = ip_ct_find_helper(&repl_tuple);
3451 +
3452 +end:   atomic_inc(&ip_conntrack_count);
3453         WRITE_UNLOCK(&ip_conntrack_lock);
3454  
3455 -       if (expected && expected->expectfn)
3456 -               expected->expectfn(conntrack);
3457 -       return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3458 +ret:   return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3459  }
3460  
3461  /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3462 @@ -923,9 +934,8 @@
3463  ip_conntrack_expect_alloc(void)
3464  {
3465         struct ip_conntrack_expect *new;
3466 -       
3467 -       new = (struct ip_conntrack_expect *)
3468 -               kmalloc(sizeof(struct ip_conntrack_expect), GFP_ATOMIC);
3469 +
3470 +       new = kmem_cache_alloc(ip_conntrack_expect_cachep, GFP_ATOMIC);
3471         if (!new) {
3472                 DEBUGP("expect_related: OOM allocating expect\n");
3473                 return NULL;
3474 @@ -933,6 +943,7 @@
3475  
3476         /* tuple_cmp compares whole union, we have to initialized cleanly */
3477         memset(new, 0, sizeof(struct ip_conntrack_expect));
3478 +       atomic_set(&new->use, 1);
3479  
3480         return new;
3481  }
3482 @@ -944,12 +955,10 @@
3483         DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
3484         new->expectant = related_to;
3485         new->sibling = NULL;
3486 -       atomic_set(&new->use, 1);
3487  
3488         /* add to expected list for this connection */
3489 -       list_add(&new->expected_list, &related_to->sibling_list);
3490 +       list_add_tail(&new->expected_list, &related_to->sibling_list);
3491         /* add to global list of expectations */
3492 -
3493         list_prepend(&ip_conntrack_expect_list, &new->list);
3494         /* add and start timer if required */
3495         if (related_to->helper->timeout) {
3496 @@ -998,12 +1007,12 @@
3497                 }
3498  
3499                 WRITE_UNLOCK(&ip_conntrack_lock);
3500 -               kfree(expect);
3501 +               /* This expectation is not inserted so no need to lock */
3502 +               kmem_cache_free(ip_conntrack_expect_cachep, expect);
3503                 return -EEXIST;
3504  
3505         } else if (related_to->helper->max_expected && 
3506                    related_to->expecting >= related_to->helper->max_expected) {
3507 -               struct list_head *cur_item;
3508                 /* old == NULL */
3509                 if (!(related_to->helper->flags & 
3510                       IP_CT_HELPER_F_REUSE_EXPECT)) {
3511 @@ -1017,7 +1026,7 @@
3512                                        related_to->helper->name,
3513                                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
3514                                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3515 -                       kfree(expect);
3516 +                       kmem_cache_free(ip_conntrack_expect_cachep, expect);
3517                         return -EPERM;
3518                 }
3519                 DEBUGP("ip_conntrack: max number of expected "
3520 @@ -1029,21 +1038,14 @@
3521                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3522   
3523                 /* choose the the oldest expectation to evict */
3524 -               list_for_each(cur_item, &related_to->sibling_list) { 
3525 -                       struct ip_conntrack_expect *cur;
3526 -
3527 -                       cur = list_entry(cur_item, 
3528 -                                        struct ip_conntrack_expect,
3529 -                                        expected_list);
3530 -                       if (cur->sibling == NULL) {
3531 -                               old = cur;
3532 +               list_for_each_entry(old, &related_to->sibling_list, 
3533 +                                                     expected_list)
3534 +                       if (old->sibling == NULL)
3535                                 break;
3536 -                       }
3537 -               }
3538  
3539 -               /* (!old) cannot happen, since related_to->expecting is the
3540 -                * number of unconfirmed expects */
3541 -               IP_NF_ASSERT(old);
3542 +               /* We cannot fail since related_to->expecting is the number
3543 +                * of unconfirmed expectations */
3544 +               IP_NF_ASSERT(old && old->sibling == NULL);
3545  
3546                 /* newnat14 does not reuse the real allocated memory
3547                  * structures but rather unexpects the old and
3548 @@ -1058,7 +1060,7 @@
3549                 WRITE_UNLOCK(&ip_conntrack_lock);
3550                 DEBUGP("expect_related: busy!\n");
3551  
3552 -               kfree(expect);
3553 +               kmem_cache_free(ip_conntrack_expect_cachep, expect);
3554                 return -EBUSY;
3555         }
3556  
3557 @@ -1127,10 +1129,8 @@
3558         DUMP_TUPLE(newreply);
3559  
3560         conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
3561 -       if (!conntrack->master)
3562 -               conntrack->helper = LIST_FIND(&helpers, helper_cmp,
3563 -                                             struct ip_conntrack_helper *,
3564 -                                             newreply);
3565 +       if (!conntrack->master && list_empty(&conntrack->sibling_list))
3566 +               conntrack->helper = ip_ct_find_helper(newreply);
3567         WRITE_UNLOCK(&ip_conntrack_lock);
3568  
3569         return 1;
3570 @@ -1379,6 +1379,7 @@
3571         }
3572  
3573         kmem_cache_destroy(ip_conntrack_cachep);
3574 +       kmem_cache_destroy(ip_conntrack_expect_cachep);
3575         vfree(ip_conntrack_hash);
3576         nf_unregister_sockopt(&so_getorigdst);
3577  }
3578 @@ -1431,6 +1432,15 @@
3579                 printk(KERN_ERR "Unable to create ip_conntrack slab cache\n");
3580                 goto err_free_hash;
3581         }
3582 +
3583 +       ip_conntrack_expect_cachep = kmem_cache_create("ip_conntrack_expect",
3584 +                                       sizeof(struct ip_conntrack_expect),
3585 +                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
3586 +       if (!ip_conntrack_expect_cachep) {
3587 +               printk(KERN_ERR "Unable to create ip_expect slab cache\n");
3588 +               goto err_free_conntrack_slab;
3589 +       }
3590 +
3591         /* Don't NEED lock here, but good form anyway. */
3592         WRITE_LOCK(&ip_conntrack_lock);
3593         /* Sew in builtin protocols. */
3594 @@ -1458,6 +1468,8 @@
3595  
3596         return ret;
3597  
3598 +err_free_conntrack_slab:
3599 +       kmem_cache_destroy(ip_conntrack_cachep);
3600  err_free_hash:
3601         vfree(ip_conntrack_hash);
3602  err_unreg_sockopt:
3603 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
3604 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c   1970-01-01 01:00:00.000000000 +0100
3605 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_egg.c       2004-06-08 10:38:25.000000000 +0200
3606 @@ -0,0 +1,237 @@
3607 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3608 + * based on ip_conntrack_irc.c 
3609 + *
3610 + *      This module only supports the share userfile-send command,
3611 + *      used by eggdrops to share it's userfile.
3612 + *
3613 + *      There are no support for NAT at the moment.
3614 + *
3615 + *      This program is free software; you can redistribute it and/or
3616 + *      modify it under the terms of the GNU General Public License
3617 + *      as published by the Free Software Foundation; either version
3618 + *      2 of the License, or (at your option) any later version.
3619 + *
3620 + *     Module load syntax:
3621 + *     
3622 + *     please give the ports of all Eggdrops You have running
3623 + *      on your system, the default port is 3333.
3624 + *
3625 + *      2001-04-19: Security update. IP addresses are now compared
3626 + *                  to prevent unauthorized "related" access.
3627 + *
3628 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
3629 + *                 Port to netfilter 'newnat' API.
3630 + */
3631 +
3632 +#include <linux/module.h>
3633 +#include <linux/netfilter.h>
3634 +#include <linux/ip.h>
3635 +#include <net/checksum.h>
3636 +#include <net/tcp.h>
3637 +
3638 +#include <linux/netfilter_ipv4/lockhelp.h>
3639 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3640 +
3641 +#define MAX_PORTS 8
3642 +static int ports[MAX_PORTS];
3643 +static int ports_c = 0;
3644 +static unsigned int egg_timeout = 300;
3645 +
3646 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3647 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3648 +MODULE_LICENSE("GPL");
3649 +#ifdef MODULE_PARM
3650 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3651 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3652 +#endif
3653 +
3654 +DECLARE_LOCK(ip_egg_lock);
3655 +struct module *ip_conntrack_egg = THIS_MODULE;
3656 +
3657 +#if 0
3658 +#define DEBUGP printk
3659 +#else
3660 +#define DEBUGP(format, args...)
3661 +#endif
3662 +
3663 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3664 +/* tries to get the ip_addr and port out of a eggdrop command
3665 +   return value: -1 on failure, 0 on success 
3666 +   data                pointer to first byte of DCC command data
3667 +   data_end    pointer to last byte of dcc command data
3668 +   ip          returns parsed ip of dcc command
3669 +   port                returns parsed port of dcc command */
3670 +{
3671 +       if (data > data_end)
3672 +               return -1;
3673 +       
3674 +       *ip = simple_strtoul(data, &data, 10);
3675 +
3676 +       /* skip blanks between ip and port */
3677 +       while (*data == ' ' && data < data_end)
3678 +               data++;
3679 +
3680 +       *port = simple_strtoul(data, &data, 10);
3681 +       return 0;
3682 +}
3683 +
3684 +
3685 +static int help(const struct iphdr *iph, size_t len,
3686 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3687 +{
3688 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3689 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3690 +       char *data = (char *) tcph + tcph->doff * 4;
3691 +       char *data_limit;
3692 +       u_int32_t tcplen = len - iph->ihl * 4;
3693 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3694 +       int dir = CTINFO2DIR(ctinfo);
3695 +       int bytes_scanned = 0;
3696 +       struct ip_conntrack_expect exp;
3697 +
3698 +       u_int32_t egg_ip;
3699 +       u_int16_t egg_port;
3700 +
3701 +       DEBUGP("entered\n");
3702 +
3703 +       /* If packet is coming from IRC server */
3704 +       if (dir != IP_CT_DIR_REPLY)
3705 +               return NF_ACCEPT;
3706 +
3707 +       /* Until there's been traffic both ways, don't look in packets. */
3708 +       if (ctinfo != IP_CT_ESTABLISHED
3709 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3710 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
3711 +               return NF_ACCEPT;
3712 +       }
3713 +
3714 +       /* Not whole TCP header? */
3715 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3716 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3717 +               return NF_ACCEPT;
3718 +       }
3719 +
3720 +       /* Checksum invalid?  Ignore. */
3721 +       /* FIXME: Source route IP option packets --RR */
3722 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3723 +                        csum_partial((char *) tcph, tcplen, 0))) {
3724 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3725 +                       tcph, tcplen, NIPQUAD(iph->saddr),
3726 +                       NIPQUAD(iph->daddr));
3727 +               return NF_ACCEPT;
3728 +       }
3729 +
3730 +       data_limit = (char *) data + datalen;
3731 +       while (datalen > 5 && bytes_scanned < 128) {
3732 +               if (memcmp(data, "s us ", 5)) {
3733 +                       data++;
3734 +                       datalen--;
3735 +                       bytes_scanned++;
3736 +                       continue;
3737 +               }
3738 +
3739 +               data += 5;
3740 +
3741 +               DEBUGP("Userfile-share found in connection "
3742 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3743 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3744 +
3745 +               if (parse_command((char *) data, data_limit, &egg_ip,
3746 +                                 &egg_port)) {
3747 +                       DEBUGP("no data in userfile-share pkt\n");
3748 +                       return NF_ACCEPT;
3749 +               }
3750 +
3751 +               memset(&exp, 0, sizeof(exp));
3752 +
3753 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3754 +                       if (net_ratelimit())
3755 +                               printk("Forged Eggdrop command from "
3756 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3757 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3758 +                                      HIPQUAD(egg_ip), egg_port);
3759 +                       return NF_ACCEPT;
3760 +               }
3761 +
3762 +               exp.tuple.src.ip = iph->daddr;
3763 +               exp.tuple.src.u.tcp.port = 0;
3764 +               exp.tuple.dst.ip = htonl(egg_ip);
3765 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
3766 +               exp.tuple.dst.protonum = IPPROTO_TCP;
3767 +
3768 +               exp.mask.dst.u.tcp.port = 0xffff;
3769 +               exp.mask.dst.protonum = 0xffff;
3770 +
3771 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3772 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3773 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3774 +
3775 +               ip_conntrack_expect_related(ct, &exp);
3776 +               break;
3777 +       }
3778 +       return NF_ACCEPT;
3779 +}
3780 +
3781 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3782 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3783 +
3784 +static void deregister_helpers(void) {
3785 +       int i;
3786 +       
3787 +       for (i = 0; i < ports_c; i++) {
3788 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
3789 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
3790 +       }
3791 +}
3792 +
3793 +static int __init init(void)
3794 +{
3795 +       int i, ret;
3796 +       char *tmpname;
3797 +
3798 +       /* If no port given, default to standard eggdrop port */
3799 +       if (ports[0] == 0)
3800 +               ports[0] = 3333;
3801 +
3802 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3803 +               memset(&egg_helpers[i], 0,
3804 +                      sizeof(struct ip_conntrack_helper));
3805 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3806 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3807 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3808 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
3809 +               egg_helpers[i].max_expected = 1;
3810 +               egg_helpers[i].timeout = egg_timeout;
3811 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3812 +               egg_helpers[i].me = THIS_MODULE;
3813 +               egg_helpers[i].help = help;
3814 +
3815 +               tmpname = &egg_names[i][0];
3816 +               if (ports[i] == 3333)
3817 +                       sprintf(tmpname, "eggdrop");
3818 +               else
3819 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
3820 +               egg_helpers[i].name = tmpname;
3821 +
3822 +               DEBUGP("port #%d: %d\n", i, ports[i]);
3823 +
3824 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
3825 +
3826 +               if (ret) {
3827 +                       printk("ip_conntrack_egg: ERROR registering helper "
3828 +                               "for port %d\n", ports[i]);
3829 +                       deregister_helpers();
3830 +                       return 1;
3831 +               }
3832 +               ports_c++;
3833 +       }
3834 +       return 0;
3835 +}
3836 +
3837 +static void __exit fini(void)
3838 +{
3839 +       deregister_helpers();
3840 +}
3841 +
3842 +module_init(init);
3843 +module_exit(fini);
3844 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
3845 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c  1970-01-01 01:00:00.000000000 +0100
3846 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_h323.c      2004-06-08 10:38:40.000000000 +0200
3847 @@ -0,0 +1,308 @@
3848 +/* 
3849 + * H.323 'brute force' extension for H.323 connection tracking. 
3850 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3851 + *
3852 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3853 + * (http://www.coritel.it/projects/sofia/nat/)
3854 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3855 + * the unregistered helpers to the conntrack entries.
3856 + */
3857 +
3858 +
3859 +#include <linux/module.h>
3860 +#include <linux/netfilter.h>
3861 +#include <linux/ip.h>
3862 +#include <net/checksum.h>
3863 +#include <net/tcp.h>
3864 +
3865 +#include <linux/netfilter_ipv4/lockhelp.h>
3866 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3867 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3868 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3869 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3870 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3871 +
3872 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3873 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3874 +MODULE_LICENSE("GPL");
3875 +
3876 +DECLARE_LOCK(ip_h323_lock);
3877 +struct module *ip_conntrack_h323 = THIS_MODULE;
3878 +
3879 +#if 0
3880 +#define DEBUGP printk
3881 +#else
3882 +#define DEBUGP(format, args...)
3883 +#endif
3884 +
3885 +/* FIXME: This should be in userspace.  Later. */
3886 +static int h245_help(const struct iphdr *iph, size_t len,
3887 +                    struct ip_conntrack *ct,
3888 +                    enum ip_conntrack_info ctinfo)
3889 +{
3890 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3891 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3892 +       unsigned char *data_limit;
3893 +       u_int32_t tcplen = len - iph->ihl * 4;
3894 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3895 +       int dir = CTINFO2DIR(ctinfo);
3896 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3897 +       struct ip_conntrack_expect expect, *exp = &expect;
3898 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3899 +       u_int16_t data_port;
3900 +       u_int32_t data_ip;
3901 +       unsigned int i;
3902 +
3903 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3904 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3905 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3906 +
3907 +       /* Can't track connections formed before we registered */
3908 +       if (!info)
3909 +               return NF_ACCEPT;
3910 +               
3911 +       /* Until there's been traffic both ways, don't look in packets. */
3912 +       if (ctinfo != IP_CT_ESTABLISHED
3913 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3914 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3915 +               return NF_ACCEPT;
3916 +       }
3917 +
3918 +       /* Not whole TCP header or too short packet? */
3919 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3920 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3921 +               return NF_ACCEPT;
3922 +       }
3923 +
3924 +       /* Checksum invalid?  Ignore. */
3925 +       /* FIXME: Source route IP option packets --RR */
3926 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3927 +                             csum_partial((char *)tcph, tcplen, 0))) {
3928 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3929 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3930 +                      NIPQUAD(iph->daddr));
3931 +               return NF_ACCEPT;
3932 +       }
3933 +
3934 +       data_limit = (unsigned char *) data + datalen;
3935 +       /* bytes: 0123   45
3936 +                 ipadrr port */
3937 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3938 +               data_ip = *((u_int32_t *)data);
3939 +               if (data_ip == iph->saddr) {
3940 +                       data_port = *((u_int16_t *)(data + 4));
3941 +                       memset(&expect, 0, sizeof(expect));
3942 +                       /* update the H.225 info */
3943 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3944 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3945 +                               NIPQUAD(iph->saddr), ntohs(data_port));
3946 +                       LOCK_BH(&ip_h323_lock);
3947 +                       info->is_h225 = H225_PORT + 1;
3948 +                       exp_info->port = data_port;
3949 +                       exp_info->dir = dir;
3950 +                       exp_info->offset = i;
3951 +
3952 +                       exp->seq = ntohl(tcph->seq) + i;
3953 +                   
3954 +                       exp->tuple = ((struct ip_conntrack_tuple)
3955 +                               { { ct->tuplehash[!dir].tuple.src.ip,
3956 +                                   { 0 } },
3957 +                                 { data_ip,
3958 +                                   { .tcp = { data_port } },
3959 +                                   IPPROTO_UDP }});
3960 +                       exp->mask = ((struct ip_conntrack_tuple)
3961 +                               { { 0xFFFFFFFF, { 0 } },
3962 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3963 +       
3964 +                       exp->expectfn = NULL;
3965 +                       
3966 +                       /* Ignore failure; should only happen with NAT */
3967 +                       ip_conntrack_expect_related(ct, exp);
3968 +
3969 +                       UNLOCK_BH(&ip_h323_lock);
3970 +               }
3971 +       }
3972 +
3973 +       return NF_ACCEPT;
3974 +
3975 +}
3976 +
3977 +/* H.245 helper is not registered! */
3978 +static struct ip_conntrack_helper h245 = 
3979 +       { { NULL, NULL },
3980 +          "H.245",                             /* name */
3981 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
3982 +          NULL,                                        /* module */
3983 +          8,                                   /* max_ expected */
3984 +          240,                                 /* timeout */
3985 +          { { 0, { 0 } },                      /* tuple */
3986 +            { 0, { 0 }, IPPROTO_TCP } },
3987 +          { { 0, { 0xFFFF } },                 /* mask */
3988 +            { 0, { 0 }, 0xFFFF } },
3989 +          h245_help                            /* helper */
3990 +       };
3991 +
3992 +static int h225_expect(struct ip_conntrack *ct)
3993 +{
3994 +       WRITE_LOCK(&ip_conntrack_lock);
3995 +       ct->helper = &h245;
3996 +       DEBUGP("h225_expect: helper for %p added\n", ct);
3997 +       WRITE_UNLOCK(&ip_conntrack_lock);
3998 +       
3999 +       return NF_ACCEPT;       /* unused */
4000 +}
4001 +
4002 +/* FIXME: This should be in userspace.  Later. */
4003 +static int h225_help(const struct iphdr *iph, size_t len,
4004 +                    struct ip_conntrack *ct,
4005 +                    enum ip_conntrack_info ctinfo)
4006 +{
4007 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4008 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
4009 +       unsigned char *data_limit;
4010 +       u_int32_t tcplen = len - iph->ihl * 4;
4011 +       u_int32_t datalen = tcplen - tcph->doff * 4;
4012 +       int dir = CTINFO2DIR(ctinfo);
4013 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
4014 +       struct ip_conntrack_expect expect, *exp = &expect;
4015 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
4016 +       u_int16_t data_port;
4017 +       u_int32_t data_ip;
4018 +       unsigned int i;
4019 +       
4020 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
4021 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
4022 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
4023 +
4024 +       /* Can't track connections formed before we registered */
4025 +       if (!info)
4026 +               return NF_ACCEPT;
4027 +
4028 +       /* Until there's been traffic both ways, don't look in packets. */
4029 +       if (ctinfo != IP_CT_ESTABLISHED
4030 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4031 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
4032 +               return NF_ACCEPT;
4033 +       }
4034 +
4035 +       /* Not whole TCP header or too short packet? */
4036 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
4037 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
4038 +               return NF_ACCEPT;
4039 +       }
4040 +
4041 +       /* Checksum invalid?  Ignore. */
4042 +       /* FIXME: Source route IP option packets --RR */
4043 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4044 +                             csum_partial((char *)tcph, tcplen, 0))) {
4045 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4046 +                      tcph, tcplen, NIPQUAD(iph->saddr),
4047 +                      NIPQUAD(iph->daddr));
4048 +               return NF_ACCEPT;
4049 +       }
4050 +       
4051 +       data_limit = (unsigned char *) data + datalen;
4052 +       /* bytes: 0123   45
4053 +                 ipadrr port */
4054 +       for (i = 0; data < (data_limit - 5); data++, i++) {
4055 +               data_ip = *((u_int32_t *)data);
4056 +               if (data_ip == iph->saddr) {
4057 +                       data_port = *((u_int16_t *)(data + 4));
4058 +                       if (data_port == tcph->source) {
4059 +                               /* Signal address */
4060 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
4061 +                                       NIPQUAD(iph->saddr));
4062 +                               /* Update the H.225 info so that NAT can mangle the address/port
4063 +                                  even when we have no expected connection! */
4064 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4065 +                               LOCK_BH(&ip_h323_lock);
4066 +                               info->dir = dir;
4067 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
4068 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
4069 +                               UNLOCK_BH(&ip_h323_lock);
4070 +#endif
4071 +                       } else {
4072 +                               memset(&expect, 0, sizeof(expect));
4073 +
4074 +                               /* update the H.225 info */
4075 +                               LOCK_BH(&ip_h323_lock);
4076 +                               info->is_h225 = H225_PORT;
4077 +                               exp_info->port = data_port;
4078 +                               exp_info->dir = dir;
4079 +                               exp_info->offset = i;
4080 +
4081 +                               exp->seq = ntohl(tcph->seq) + i;
4082 +
4083 +                               exp->tuple = ((struct ip_conntrack_tuple)
4084 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
4085 +                                           { 0 } },
4086 +                                         { data_ip,
4087 +                                           { .tcp = { data_port } },
4088 +                                           IPPROTO_TCP }});
4089 +                               exp->mask = ((struct ip_conntrack_tuple)
4090 +                                       { { 0xFFFFFFFF, { 0 } },
4091 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4092 +       
4093 +                               exp->expectfn = h225_expect;
4094 +                               
4095 +                               /* Ignore failure */
4096 +                               ip_conntrack_expect_related(ct, exp);
4097 +
4098 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
4099 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4100 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
4101 +
4102 +                               UNLOCK_BH(&ip_h323_lock);
4103 +                       }  
4104 +#ifdef CONFIG_IP_NF_NAT_NEEDED
4105 +               } else if (data_ip == iph->daddr) {
4106 +                       data_port = *((u_int16_t *)(data + 4));
4107 +                       if (data_port == tcph->dest) {
4108 +                               /* Signal address */
4109 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
4110 +                                       NIPQUAD(iph->daddr));
4111 +                               /* Update the H.225 info so that NAT can mangle the address/port
4112 +                                  even when we have no expected connection! */
4113 +                               LOCK_BH(&ip_h323_lock);
4114 +                               info->dir = dir;
4115 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
4116 +                               info->offset[IP_CT_DIR_REPLY] = i;
4117 +                               UNLOCK_BH(&ip_h323_lock);
4118 +                       }
4119 +#endif
4120 +               }
4121 +       }
4122 +
4123 +       return NF_ACCEPT;
4124 +
4125 +}
4126 +
4127 +static struct ip_conntrack_helper h225 = 
4128 +       { { NULL, NULL },
4129 +         "H.225",                                      /* name */
4130 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
4131 +         THIS_MODULE,                                  /* module */
4132 +         2,                                            /* max_expected */
4133 +         240,                                          /* timeout */
4134 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
4135 +           { 0, { 0 }, IPPROTO_TCP } },
4136 +         { { 0, { 0xFFFF } },                          /* mask */
4137 +           { 0, { 0 }, 0xFFFF } },
4138 +         h225_help                                     /* helper */
4139 +       };
4140 +
4141 +static int __init init(void)
4142 +{
4143 +       return ip_conntrack_helper_register(&h225);
4144 +}
4145 +
4146 +static void __exit fini(void)
4147 +{
4148 +       /* Unregister H.225 helper */   
4149 +       ip_conntrack_helper_unregister(&h225);
4150 +}
4151 +
4152 +EXPORT_SYMBOL(ip_h323_lock);
4153 +
4154 +module_init(init);
4155 +module_exit(fini);
4156 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
4157 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c   1970-01-01 01:00:00.000000000 +0100
4158 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_mms.c       2004-06-08 10:39:44.000000000 +0200
4159 @@ -0,0 +1,308 @@
4160 +/* MMS extension for IP connection tracking
4161 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4162 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
4163 + *
4164 + * ip_conntrack_mms.c v0.3 2002-09-22
4165 + *
4166 + *      This program is free software; you can redistribute it and/or
4167 + *      modify it under the terms of the GNU General Public License
4168 + *      as published by the Free Software Foundation; either version
4169 + *      2 of the License, or (at your option) any later version.
4170 + *
4171 + *      Module load syntax:
4172 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
4173 + *
4174 + *      Please give the ports of all MMS servers You wish to connect to.
4175 + *      If you don't specify ports, the default will be TCP port 1755.
4176 + *
4177 + *      More info on MMS protocol, firewalls and NAT:
4178 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
4179 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
4180 + *
4181 + *      The SDP project people are reverse-engineering MMS:
4182 + *      http://get.to/sdp
4183 + */
4184 +
4185 +#include <linux/config.h>
4186 +#include <linux/module.h>
4187 +#include <linux/netfilter.h>
4188 +#include <linux/ip.h>
4189 +#include <linux/ctype.h>
4190 +#include <net/checksum.h>
4191 +#include <net/tcp.h>
4192 +
4193 +#include <linux/netfilter_ipv4/lockhelp.h>
4194 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4195 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
4196 +
4197 +DECLARE_LOCK(ip_mms_lock);
4198 +struct module *ip_conntrack_mms = THIS_MODULE;
4199 +
4200 +#define MAX_PORTS 8
4201 +static int ports[MAX_PORTS];
4202 +static int ports_c;
4203 +#ifdef MODULE_PARM
4204 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4205 +#endif
4206 +
4207 +#if 0 
4208 +#define DEBUGP printk
4209 +#else
4210 +#define DEBUGP(format, args...)
4211 +#endif
4212 +
4213 +EXPORT_SYMBOL(ip_mms_lock);
4214 +
4215 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4216 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
4217 +MODULE_LICENSE("GPL");
4218 +
4219 +/* #define isdigit(c) (c >= '0' && c <= '9') */
4220 +
4221 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
4222 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
4223 +{
4224 +       int i;
4225 +       for (i = 0; i < unicode_size; ++i) {
4226 +               string[i] = (char)(unicode[i]);
4227 +       }
4228 +       string[unicode_size] = 0x00;
4229 +}
4230 +
4231 +__inline static int atoi(char *s) 
4232 +{
4233 +       int i=0;
4234 +       while (isdigit(*s)) {
4235 +               i = i*10 + *(s++) - '0';
4236 +       }
4237 +       return i;
4238 +}
4239 +
4240 +/* convert ip address string like "192.168.0.10" to unsigned int */
4241 +__inline static u_int32_t asciiiptoi(char *s)
4242 +{
4243 +       unsigned int i, j, k;
4244 +
4245 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
4246 +               i+=atoi(s);
4247 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
4248 +                       ;
4249 +       }
4250 +       i+=atoi(s);
4251 +       return ntohl(i);
4252 +}
4253 +
4254 +int parse_mms(const char *data, 
4255 +             const unsigned int datalen,
4256 +             u_int32_t *mms_ip,
4257 +             u_int16_t *mms_proto,
4258 +             u_int16_t *mms_port,
4259 +             char **mms_string_b,
4260 +             char **mms_string_e,
4261 +             char **mms_padding_e)
4262 +{
4263 +       int unicode_size, i;
4264 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
4265 +       char getlengthstring[28];
4266 +       
4267 +       for(unicode_size=0; 
4268 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
4269 +           unicode_size++)
4270 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
4271 +                       return -1; /* out of bounds - incomplete packet */
4272 +       
4273 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
4274 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
4275 +       
4276 +       /* IP address ? */
4277 +       *mms_ip = asciiiptoi(tempstring+2);
4278 +       
4279 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
4280 +               
4281 +       /* protocol ? */
4282 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
4283 +               *mms_proto = IPPROTO_TCP;
4284 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
4285 +               *mms_proto = IPPROTO_UDP;
4286 +
4287 +       /* port ? */
4288 +       *mms_port = atoi(tempstring+7+i);
4289 +
4290 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
4291 +          unicode string, one to the end of the string, and one to the end 
4292 +          of the packet, since we must keep track of the number of bytes 
4293 +          between end of the unicode string and the end of packet (padding) */
4294 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
4295 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
4296 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
4297 +       return 0;
4298 +}
4299 +
4300 +
4301 +/* FIXME: This should be in userspace.  Later. */
4302 +static int help(const struct iphdr *iph, size_t len,
4303 +               struct ip_conntrack *ct,
4304 +               enum ip_conntrack_info ctinfo)
4305 +{
4306 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
4307 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
4308 +       const char *data = (const char *)tcph + tcph->doff * 4;
4309 +       unsigned int tcplen = len - iph->ihl * 4;
4310 +       unsigned int datalen = tcplen - tcph->doff * 4;
4311 +       int dir = CTINFO2DIR(ctinfo);
4312 +       struct ip_conntrack_expect expect, *exp = &expect; 
4313 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
4314 +       
4315 +       u_int32_t mms_ip;
4316 +       u_int16_t mms_proto;
4317 +       char mms_proto_string[8];
4318 +       u_int16_t mms_port;
4319 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
4320 +            
4321 +       /* Until there's been traffic both ways, don't look in packets. */
4322 +       if (ctinfo != IP_CT_ESTABLISHED
4323 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
4324 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
4325 +               return NF_ACCEPT;
4326 +       }
4327 +
4328 +       /* Not whole TCP header? */
4329 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
4330 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
4331 +               return NF_ACCEPT;
4332 +       }
4333 +
4334 +       /* Checksum invalid?  Ignore. */
4335 +       /* FIXME: Source route IP option packets --RR */
4336 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4337 +           csum_partial((char *)tcph, tcplen, 0))) {
4338 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4339 +                      tcph, tcplen, NIPQUAD(iph->saddr),
4340 +                      NIPQUAD(iph->daddr));
4341 +               return NF_ACCEPT;
4342 +       }
4343 +       
4344 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
4345 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
4346 +          the client has already sent a packet to the server with the server's hostname 
4347 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
4348 +          server will break the connection if this doesn't correspond to its own host 
4349 +          header. The client can also connect to an IP address; if it's the server's IP
4350 +          address, it will not break the connection. When doing DNAT on a connection 
4351 +          where the client uses a server's IP address, the nat module should detect
4352 +          this and change this string accordingly to the DNATed address. This should
4353 +          probably be done by checking for an IP address, then storing it as a member
4354 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
4355 +          */
4356 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
4357 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
4358 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
4359 +                      (u8)*(data+36), (u8)*(data+37), 
4360 +                      (u8)*(data+38), (u8)*(data+39),
4361 +                      datalen);
4362 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
4363 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
4364 +                       if(net_ratelimit())
4365 +                               /* FIXME: more verbose debugging ? */
4366 +                               printk(KERN_WARNING
4367 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
4368 +
4369 +               memset(&expect, 0, sizeof(expect));
4370 +
4371 +               sprintf(mms_proto_string, "(%u)", mms_proto);
4372 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
4373 +                      mms_proto == IPPROTO_TCP ? "TCP"
4374 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
4375 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
4376 +                      NIPQUAD(mms_ip),
4377 +                      mms_port);
4378 +               
4379 +               /* it's possible that the client will just ask the server to tunnel
4380 +                  the stream over the same TCP session (from port 1755): there's 
4381 +                  shouldn't be a need to add an expectation in that case, but it
4382 +                  makes NAT packet mangling so much easier */
4383 +               LOCK_BH(&ip_mms_lock);
4384 +
4385 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
4386 +               
4387 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
4388 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
4389 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
4390 +               exp_mms_info->port    = mms_port;
4391 +               
4392 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
4393 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
4394 +               
4395 +               exp->tuple = ((struct ip_conntrack_tuple)
4396 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4397 +                             { mms_ip,
4398 +                               { .tcp = { (__u16) ntohs(mms_port) } },
4399 +                               mms_proto } }
4400 +                            );
4401 +               exp->mask  = ((struct ip_conntrack_tuple)
4402 +                            { { 0xFFFFFFFF, { 0 } },
4403 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
4404 +               exp->expectfn = NULL;
4405 +               ip_conntrack_expect_related(ct, &expect);
4406 +               UNLOCK_BH(&ip_mms_lock);
4407 +       }
4408 +
4409 +       return NF_ACCEPT;
4410 +}
4411 +
4412 +static struct ip_conntrack_helper mms[MAX_PORTS];
4413 +static char mms_names[MAX_PORTS][10];
4414 +
4415 +/* Not __exit: called from init() */
4416 +static void fini(void)
4417 +{
4418 +       int i;
4419 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4420 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
4421 +                               ports[i]);
4422 +               ip_conntrack_helper_unregister(&mms[i]);
4423 +       }
4424 +}
4425 +
4426 +static int __init init(void)
4427 +{
4428 +       int i, ret;
4429 +       char *tmpname;
4430 +
4431 +       if (ports[0] == 0)
4432 +               ports[0] = MMS_PORT;
4433 +
4434 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
4435 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
4436 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
4437 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
4438 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
4439 +               mms[i].mask.dst.protonum = 0xFFFF;
4440 +               mms[i].max_expected = 1;
4441 +               mms[i].timeout = 0;
4442 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4443 +               mms[i].me = THIS_MODULE;
4444 +               mms[i].help = help;
4445 +
4446 +               tmpname = &mms_names[i][0];
4447 +               if (ports[i] == MMS_PORT)
4448 +                       sprintf(tmpname, "mms");
4449 +               else
4450 +                       sprintf(tmpname, "mms-%d", ports[i]);
4451 +               mms[i].name = tmpname;
4452 +
4453 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
4454 +                               ports[i]);
4455 +               ret = ip_conntrack_helper_register(&mms[i]);
4456 +
4457 +               if (ret) {
4458 +                       fini();
4459 +                       return ret;
4460 +               }
4461 +               ports_c++;
4462 +       }
4463 +       return 0;
4464 +}
4465 +
4466 +module_init(init);
4467 +module_exit(fini);
4468 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
4469 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c    1970-01-01 01:00:00.000000000 +0100
4470 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c        2004-06-08 10:40:55.000000000 +0200
4471 @@ -0,0 +1,529 @@
4472 +/*
4473 + * Connection tracking protocol helper module for SCTP.
4474 + * 
4475 + * SCTP is defined in RFC 2960. References to various sections in this code 
4476 + * are to this RFC.
4477 + * 
4478 + * This program is free software; you can redistribute it and/or modify
4479 + * it under the terms of the GNU General Public License version 2 as
4480 + * published by the Free Software Foundation.
4481 + */
4482 +
4483 +#include <linux/types.h>
4484 +#include <linux/sched.h>
4485 +#include <linux/timer.h>
4486 +#include <linux/netfilter.h>
4487 +#include <linux/module.h>
4488 +#include <linux/in.h>
4489 +#include <linux/ip.h>
4490 +#include <linux/sctp.h>
4491 +#include <linux/string.h>
4492 +
4493 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4494 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4495 +#include <linux/netfilter_ipv4/lockhelp.h>
4496 +
4497 +#if 0
4498 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4499 +#else
4500 +#define DEBUGP(format, args...)
4501 +#endif
4502 +
4503 +/* Protects conntrack->proto.sctp */
4504 +static DECLARE_RWLOCK(sctp_lock);
4505 +
4506 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4507 +   closely.  They're more complex. --RR 
4508 +
4509 +   And so for me for SCTP :D -Kiran */
4510 +
4511 +static const char *sctp_conntrack_names[] = {
4512 +       "NONE",
4513 +       "CLOSED",
4514 +       "COOKIE_WAIT",
4515 +       "COOKIE_ECHOED",
4516 +       "ESTABLISHED",
4517 +       "SHUTDOWN_SENT",
4518 +       "SHUTDOWN_RECD",
4519 +       "SHUTDOWN_ACK_SENT",
4520 +};
4521 +
4522 +#define SECS  * HZ
4523 +#define MINS  * 60 SECS
4524 +#define HOURS * 60 MINS
4525 +#define DAYS  * 24 HOURS
4526 +
4527 +unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
4528 +unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
4529 +unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
4530 +unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
4531 +unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
4532 +unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
4533 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
4534 +
4535 +static unsigned long * sctp_timeouts[]
4536 += { 0,                                     /* SCTP_CONNTRACK_NONE  */
4537 +    &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
4538 +    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
4539 +    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
4540 +    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
4541 +    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4542 +    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4543 +    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4544 + };
4545 +
4546 +#define sNO SCTP_CONNTRACK_NONE
4547 +#define        sCL SCTP_CONNTRACK_CLOSED
4548 +#define        sCW SCTP_CONNTRACK_COOKIE_WAIT
4549 +#define        sCE SCTP_CONNTRACK_COOKIE_ECHOED
4550 +#define        sES SCTP_CONNTRACK_ESTABLISHED
4551 +#define        sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4552 +#define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4553 +#define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4554 +#define        sIV SCTP_CONNTRACK_MAX
4555 +
4556 +/* 
4557 +       These are the descriptions of the states:
4558 +
4559 +NOTE: These state names are tantalizingly similar to the states of an 
4560 +SCTP endpoint. But the interpretation of the states is a little different,
4561 +considering that these are the states of the connection and not of an end 
4562 +point. Please note the subtleties. -Kiran
4563 +
4564 +NONE              - Nothing so far.
4565 +COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
4566 +                    an INIT_ACK chunk in the reply direction.
4567 +COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
4568 +ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
4569 +SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
4570 +SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
4571 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4572 +                    to that of the SHUTDOWN chunk.
4573 +CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
4574 +                    the SHUTDOWN chunk. Connection is closed.
4575 +*/
4576 +
4577 +/* TODO
4578 + - I have assumed that the first INIT is in the original direction. 
4579 + This messes things when an INIT comes in the reply direction in CLOSED
4580 + state.
4581 + - Check the error type in the reply dir before transitioning from 
4582 +cookie echoed to closed.
4583 + - Sec 5.2.4 of RFC 2960
4584 + - Multi Homing support.
4585 +*/
4586 +
4587 +/* SCTP conntrack state transitions */
4588 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4589 +       {
4590 +/*     ORIGINAL        */
4591 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4592 +/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4593 +/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4594 +/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4595 +/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4596 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4597 +/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4598 +/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4599 +/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4600 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4601 +       },
4602 +       {
4603 +/*     REPLY   */
4604 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4605 +/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4606 +/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4607 +/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4608 +/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4609 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4610 +/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4611 +/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4612 +/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4613 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4614 +       }
4615 +};
4616 +
4617 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4618 +                            unsigned int dataoff,
4619 +                            struct ip_conntrack_tuple *tuple)
4620 +{
4621 +       sctp_sctphdr_t hdr;
4622 +
4623 +       DEBUGP(__FUNCTION__);
4624 +       DEBUGP("\n");
4625 +
4626 +       /* Actually only need first 8 bytes. */
4627 +       if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4628 +               return 0;
4629 +
4630 +       tuple->src.u.sctp.port = hdr.source;
4631 +       tuple->dst.u.sctp.port = hdr.dest;
4632 +
4633 +       return 1;
4634 +}
4635 +
4636 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4637 +                            const struct ip_conntrack_tuple *orig)
4638 +{
4639 +       DEBUGP(__FUNCTION__);
4640 +       DEBUGP("\n");
4641 +
4642 +       tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4643 +       tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4644 +       return 1;
4645 +}
4646 +
4647 +/* Print out the per-protocol part of the tuple. */
4648 +static unsigned int sctp_print_tuple(char *buffer,
4649 +                                    const struct ip_conntrack_tuple *tuple)
4650 +{
4651 +       DEBUGP(__FUNCTION__);
4652 +       DEBUGP("\n");
4653 +
4654 +       return sprintf(buffer, "sport=%hu dport=%hu ",
4655 +                      ntohs(tuple->src.u.sctp.port),
4656 +                      ntohs(tuple->dst.u.sctp.port));
4657 +}
4658 +
4659 +/* Print out the private part of the conntrack. */
4660 +static unsigned int sctp_print_conntrack(char *buffer,
4661 +                                        const struct ip_conntrack *conntrack)
4662 +{
4663 +       enum sctp_conntrack state;
4664 +
4665 +       DEBUGP(__FUNCTION__);
4666 +       DEBUGP("\n");
4667 +
4668 +       READ_LOCK(&sctp_lock);
4669 +       state = conntrack->proto.sctp.state;
4670 +       READ_UNLOCK(&sctp_lock);
4671 +
4672 +       return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4673 +}
4674 +
4675 +#define for_each_sctp_chunk(skb, sch, offset, count)   \
4676 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0;       \
4677 +       offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch));    \
4678 +       offset += (htons(sch.length) + 3) & ~3, count++)
4679 +
4680 +/* Some validity checks to make sure the chunks are fine */
4681 +static int do_basic_checks(struct ip_conntrack *conntrack,
4682 +                          const struct sk_buff *skb,
4683 +                          char *map)
4684 +{
4685 +       u_int32_t offset, count;
4686 +       sctp_chunkhdr_t sch;
4687 +       int flag;
4688 +
4689 +       DEBUGP(__FUNCTION__);
4690 +       DEBUGP("\n");
4691 +
4692 +       flag = 0;
4693 +
4694 +       for_each_sctp_chunk (skb, sch, offset, count) {
4695 +               DEBUGP("Chunk Num: %d  Type: %d\n", count, sch.type);
4696 +
4697 +               if (sch.type == SCTP_CID_INIT 
4698 +                       || sch.type == SCTP_CID_INIT_ACK
4699 +                       || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4700 +                       flag = 1;
4701 +               }
4702 +
4703 +               /* Cookie Ack/Echo chunks not the first OR 
4704 +                  Init / Init Ack / Shutdown compl chunks not the only chunks */
4705 +               if ((sch.type == SCTP_CID_COOKIE_ACK 
4706 +                       || sch.type == SCTP_CID_COOKIE_ECHO
4707 +                       || flag)
4708 +                    && count !=0 ) {
4709 +                       DEBUGP("Basic checks failed\n");
4710 +                       return 1;
4711 +               }
4712 +
4713 +               if (map) {
4714 +                       set_bit (sch.type, (void *)map);
4715 +               }
4716 +       }
4717 +
4718 +       DEBUGP("Basic checks passed\n");
4719 +       return 0;
4720 +}
4721 +
4722 +static int new_state(enum ip_conntrack_dir dir,
4723 +                    enum sctp_conntrack cur_state,
4724 +                    int chunk_type)
4725 +{
4726 +       int i;
4727 +
4728 +       DEBUGP(__FUNCTION__);
4729 +       DEBUGP("\n");
4730 +
4731 +       DEBUGP("Chunk type: %d\n", chunk_type);
4732 +
4733 +       switch (chunk_type) {
4734 +               case SCTP_CID_INIT: 
4735 +                       DEBUGP("SCTP_CID_INIT\n");
4736 +                       i = 0; break;
4737 +               case SCTP_CID_INIT_ACK: 
4738 +                       DEBUGP("SCTP_CID_INIT_ACK\n");
4739 +                       i = 1; break;
4740 +               case SCTP_CID_ABORT: 
4741 +                       DEBUGP("SCTP_CID_ABORT\n");
4742 +                       i = 2; break;
4743 +               case SCTP_CID_SHUTDOWN: 
4744 +                       DEBUGP("SCTP_CID_SHUTDOWN\n");
4745 +                       i = 3; break;
4746 +               case SCTP_CID_SHUTDOWN_ACK: 
4747 +                       DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4748 +                       i = 4; break;
4749 +               case SCTP_CID_ERROR: 
4750 +                       DEBUGP("SCTP_CID_ERROR\n");
4751 +                       i = 5; break;
4752 +               case SCTP_CID_COOKIE_ECHO: 
4753 +                       DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4754 +                       i = 6; break;
4755 +               case SCTP_CID_COOKIE_ACK: 
4756 +                       DEBUGP("SCTP_CID_COOKIE_ACK\n");
4757 +                       i = 7; break;
4758 +               case SCTP_CID_SHUTDOWN_COMPLETE: 
4759 +                       DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4760 +                       i = 8; break;
4761 +               default:
4762 +                       /* Other chunks like DATA, SACK, HEARTBEAT and
4763 +                       its ACK do not cause a change in state */
4764 +                       DEBUGP("Unknown chunk type, Will stay in %s\n", 
4765 +                                               sctp_conntrack_names[cur_state]);
4766 +                       return cur_state;
4767 +       }
4768 +
4769 +       DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
4770 +                       dir, sctp_conntrack_names[cur_state], chunk_type,
4771 +                       sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4772 +
4773 +       return sctp_conntracks[dir][i][cur_state];
4774 +}
4775 +
4776 +/* Returns verdict for packet, or -1 for invalid. */
4777 +static int sctp_packet(struct ip_conntrack *conntrack,
4778 +                      const struct sk_buff *skb,
4779 +                      enum ip_conntrack_info ctinfo)
4780 +{
4781 +       enum sctp_conntrack newconntrack, oldsctpstate;
4782 +       sctp_sctphdr_t sctph;
4783 +       sctp_chunkhdr_t sch;
4784 +       u_int32_t offset, count;
4785 +       char map[256 / sizeof (char)] = {0};
4786 +
4787 +       DEBUGP(__FUNCTION__);
4788 +       DEBUGP("\n");
4789 +
4790 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4791 +               return -1;
4792 +
4793 +       if (do_basic_checks(conntrack, skb, map) != 0)
4794 +               return -1;
4795 +
4796 +       /* Check the verification tag (Sec 8.5) */
4797 +       if (!test_bit(SCTP_CID_INIT, (void *)map)
4798 +               && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4799 +               && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4800 +               && !test_bit(SCTP_CID_ABORT, (void *)map)
4801 +               && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4802 +               && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4803 +               DEBUGP("Verification tag check failed\n");
4804 +               return -1;
4805 +       }
4806 +
4807 +       oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4808 +       for_each_sctp_chunk (skb, sch, offset, count) {
4809 +               WRITE_LOCK(&sctp_lock);
4810 +
4811 +               /* Special cases of Verification tag check (Sec 8.5.1) */
4812 +               if (sch.type == SCTP_CID_INIT) {
4813 +                       /* Sec 8.5.1 (A) */
4814 +                       if (sctph.vtag != 0) {
4815 +                               WRITE_UNLOCK(&sctp_lock);
4816 +                               return -1;
4817 +                       }
4818 +               } else if (sch.type == SCTP_CID_ABORT) {
4819 +                       /* Sec 8.5.1 (B) */
4820 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4821 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4822 +                                                       [1 - CTINFO2DIR(ctinfo)])) {
4823 +                               WRITE_UNLOCK(&sctp_lock);
4824 +                               return -1;
4825 +                       }
4826 +               } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4827 +                       /* Sec 8.5.1 (C) */
4828 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4829 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4830 +                                                       [1 - CTINFO2DIR(ctinfo)] 
4831 +                                       && (sch.flags & 1))) {
4832 +                               WRITE_UNLOCK(&sctp_lock);
4833 +                               return -1;
4834 +                       }
4835 +               } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4836 +                       /* Sec 8.5.1 (D) */
4837 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4838 +                               WRITE_UNLOCK(&sctp_lock);
4839 +                               return -1;
4840 +                       }
4841 +               }
4842 +
4843 +               oldsctpstate = conntrack->proto.sctp.state;
4844 +               newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4845 +
4846 +               /* Invalid */
4847 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4848 +                       DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4849 +                              CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4850 +                       WRITE_UNLOCK(&sctp_lock);
4851 +                       return -1;
4852 +               }
4853 +
4854 +               /* If it is an INIT or an INIT ACK note down the vtag */
4855 +               if (sch.type == SCTP_CID_INIT 
4856 +                       || sch.type == SCTP_CID_INIT_ACK) {
4857 +                       sctp_inithdr_t inithdr;
4858 +
4859 +                       if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4860 +                               &inithdr, sizeof(inithdr)) != 0) {
4861 +                                       WRITE_UNLOCK(&sctp_lock);
4862 +                                       return -1;
4863 +                       }
4864 +                       DEBUGP("Setting vtag %x for dir %d\n", 
4865 +                                       inithdr.init_tag, CTINFO2DIR(ctinfo));
4866 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4867 +               }
4868 +
4869 +               conntrack->proto.sctp.state = newconntrack;
4870 +               WRITE_UNLOCK(&sctp_lock);
4871 +       }
4872 +
4873 +       ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4874 +
4875 +       if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4876 +               && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4877 +               && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4878 +               DEBUGP("Setting assured bit\n");
4879 +               set_bit(IPS_ASSURED_BIT, &conntrack->status);
4880 +       }
4881 +
4882 +       return NF_ACCEPT;
4883 +}
4884 +
4885 +/* Called when a new connection for this protocol found. */
4886 +static int sctp_new(struct ip_conntrack *conntrack, 
4887 +                   const struct sk_buff *skb)
4888 +{
4889 +       enum sctp_conntrack newconntrack;
4890 +       sctp_sctphdr_t sctph;
4891 +       sctp_chunkhdr_t sch;
4892 +       u_int32_t offset, count;
4893 +       char map[256 / sizeof (char)] = {0};
4894 +
4895 +       DEBUGP(__FUNCTION__);
4896 +       DEBUGP("\n");
4897 +
4898 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4899 +               return -1;
4900 +
4901 +       if (do_basic_checks(conntrack, skb, map) != 0)
4902 +               return -1;
4903 +
4904 +       /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4905 +       if ((test_bit (SCTP_CID_ABORT, (void *)map))
4906 +               || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4907 +               || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4908 +               return -1;
4909 +       }
4910 +
4911 +       newconntrack = SCTP_CONNTRACK_MAX;
4912 +       for_each_sctp_chunk (skb, sch, offset, count) {
4913 +               /* Don't need lock here: this conntrack not in circulation yet */
4914 +               newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
4915 +                                               SCTP_CONNTRACK_NONE, sch.type);
4916 +
4917 +               /* Invalid: delete conntrack */
4918 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4919 +                       DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4920 +                       return 0;
4921 +               }
4922 +
4923 +               /* Copy the vtag into the state info */
4924 +               if (sch.type == SCTP_CID_INIT) {
4925 +                       if (sctph.vtag == 0) {
4926 +                               sctp_inithdr_t inithdr;
4927 +
4928 +                               if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t), 
4929 +                                       &inithdr, sizeof(inithdr)) != 0) {
4930 +                                               return -1;
4931 +                               }
4932 +
4933 +                               DEBUGP("Setting vtag %x for new conn\n", 
4934 +                                       inithdr.init_tag);
4935 +
4936 +                               conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
4937 +                                                               inithdr.init_tag;
4938 +                       } else {
4939 +                               /* Sec 8.5.1 (A) */
4940 +                               return -1;
4941 +                       }
4942 +               }
4943 +               /* If it is a shutdown ack OOTB packet, we expect a return
4944 +                  shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
4945 +               else {
4946 +                       DEBUGP("Setting vtag %x for new conn OOTB\n", 
4947 +                               sctph.vtag);
4948 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
4949 +               }
4950 +
4951 +               conntrack->proto.sctp.state = newconntrack;
4952 +       }
4953 +
4954 +       return 1;
4955 +}
4956 +
4957 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
4958 +                               const struct sk_buff *skb)
4959 +{
4960 +       /* To be implemented */
4961 +       return 0;
4962 +}
4963 +
4964 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
4965 +       .list            = { NULL, NULL }, 
4966 +       .proto           = IPPROTO_SCTP, 
4967 +       .name            = "sctp",
4968 +       .pkt_to_tuple    = sctp_pkt_to_tuple, 
4969 +       .invert_tuple    = sctp_invert_tuple, 
4970 +       .print_tuple     = sctp_print_tuple, 
4971 +       .print_conntrack = sctp_print_conntrack,
4972 +       .packet          = sctp_packet, 
4973 +       .new             = sctp_new, 
4974 +       .destroy         = NULL, 
4975 +       .exp_matches_pkt = sctp_exp_matches_pkt, 
4976 +       .me              = THIS_MODULE 
4977 +};
4978 +
4979 +int __init init(void)
4980 +{
4981 +       int ret;
4982 +
4983 +       ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
4984 +       DEBUGP("SCTP conntrack module loading %s\n", 
4985 +                                       ret ? "failed": "succeeded");
4986 +       return ret;
4987 +}
4988 +
4989 +void __exit fini(void)
4990 +{
4991 +       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
4992 +       DEBUGP("SCTP conntrack module unloaded\n");
4993 +}
4994 +
4995 +module_init(init);
4996 +module_exit(fini);
4997 +
4998 +MODULE_LICENSE("GPL");
4999 +MODULE_AUTHOR("Kiran Kumar Immidi");
5000 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
5001 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
5002 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c        1970-01-01 01:00:00.000000000 +0100
5003 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c    2004-06-08 10:40:36.000000000 +0200
5004 @@ -0,0 +1,156 @@
5005 +/* Quake3 extension for IP connection tracking
5006 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
5007 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
5008 + *
5009 + * ip_conntrack_quake3.c v0.04 2002-08-31
5010 + *
5011 + *      This program is free software; you can redistribute it and/or
5012 + *      modify it under the terms of the GNU General Public License
5013 + *      as published by the Free Software Foundation; either version
5014 + *      2 of the License, or (at your option) any later version.
5015 + *
5016 + *      Module load syntax:
5017 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
5018 + *
5019 + *      please give the ports of all Quake3 master servers You wish to 
5020 + *      connect to. If you don't specify ports, the default will be UDP 
5021 + *      port 27950.
5022 + *
5023 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
5024 + */
5025 +
5026 +#include <linux/module.h>
5027 +#include <linux/ip.h>
5028 +#include <linux/udp.h>
5029 +
5030 +#include <linux/netfilter.h>
5031 +#include <linux/netfilter_ipv4/ip_tables.h>
5032 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5033 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
5034 +
5035 +struct module *ip_conntrack_quake3 = THIS_MODULE;
5036 +
5037 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
5038 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
5039 +MODULE_LICENSE("GPL");
5040 +
5041 +#define MAX_PORTS 8
5042 +static int ports[MAX_PORTS];
5043 +static int ports_c = 0;
5044 +#ifdef MODULE_PARM
5045 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5046 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
5047 +#endif
5048 +
5049 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
5050 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
5051 +#if 0 
5052 +#define DEBUGP printk
5053 +#else
5054 +#define DEBUGP(format, args...)
5055 +#endif
5056 +
5057 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
5058 +
5059 +static int quake3_help(const struct iphdr *iph, size_t len,
5060 +       struct ip_conntrack *ct,
5061 +       enum ip_conntrack_info ctinfo)
5062 +{
5063 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5064 +       int dir = CTINFO2DIR(ctinfo);
5065 +       struct ip_conntrack_expect exp;
5066 +       int i;
5067 +       
5068 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
5069 +       if (ctinfo != IP_CT_ESTABLISHED
5070 +           && ctinfo != IP_CT_IS_REPLY) {
5071 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
5072 +               return NF_ACCEPT;
5073 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
5074 +       
5075 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
5076 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
5077 +                   i+6 < ntohs(udph->len);
5078 +                   i+=7) {
5079 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
5080 +                              i, ntohs(udph->len),
5081 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
5082 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
5083 +
5084 +                       memset(&exp, 0, sizeof(exp));
5085 +
5086 +                       exp.tuple = ((struct ip_conntrack_tuple)
5087 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
5088 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
5089 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
5090 +                                        IPPROTO_UDP } }
5091 +                                   );
5092 +                       exp.mask  = ((struct ip_conntrack_tuple)
5093 +                                    { { 0xFFFFFFFF, { 0 } },
5094 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
5095 +                       exp.expectfn = NULL;
5096 +
5097 +                       ip_conntrack_expect_related(ct, &exp);
5098 +               }
5099 +
5100 +       }
5101 +       
5102 +       return(NF_ACCEPT);
5103 +}
5104 +
5105 +static struct ip_conntrack_helper quake3[MAX_PORTS];
5106 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
5107 +
5108 +static void fini(void)
5109 +{
5110 +       int i;
5111 +
5112 +       for(i = 0 ; (i < ports_c); i++) {
5113 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
5114 +                                       ports[i]);
5115 +               ip_conntrack_helper_unregister(&quake3[i]);
5116 +       } 
5117 +}
5118 +
5119 +static int __init init(void)
5120 +{
5121 +       int i, ret;
5122 +       char *tmpname;
5123 +
5124 +       if(!ports[0])
5125 +               ports[0]=QUAKE3_MASTER_PORT;
5126 +
5127 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
5128 +               /* Create helper structure */
5129 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
5130 +
5131 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
5132 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
5133 +               quake3[i].mask.dst.protonum = 0xFFFF;
5134 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
5135 +               quake3[i].help = quake3_help;
5136 +               quake3[i].me = THIS_MODULE;
5137 +
5138 +               tmpname = &quake3_names[i][0];
5139 +               if (ports[i] == QUAKE3_MASTER_PORT)
5140 +                       sprintf(tmpname, "quake3");
5141 +               else
5142 +                       sprintf(tmpname, "quake3-%d", i);
5143 +               quake3[i].name = tmpname;
5144 +               
5145 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
5146 +                      ports[i]);
5147 +
5148 +               ret=ip_conntrack_helper_register(&quake3[i]);
5149 +               if(ret) {
5150 +                       fini();
5151 +                       return(ret);
5152 +               }
5153 +               ports_c++;
5154 +       }
5155 +
5156 +       return(0);
5157 +}
5158 +
5159 +module_init(init);
5160 +module_exit(fini);
5161 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
5162 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c   1970-01-01 01:00:00.000000000 +0100
5163 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c       2004-06-08 10:40:43.000000000 +0200
5164 @@ -0,0 +1,331 @@
5165 +/* RSH extension for IP connection tracking, Version 1.0
5166 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
5167 + * based on HW's ip_conntrack_irc.c    
5168 + *
5169 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
5170 + *
5171 + *      This program is free software; you can redistribute it and/or
5172 + *      modify it under the terms of the GNU General Public License
5173 + *      as published by the Free Software Foundation; either version
5174 + *      2 of the License, or (at your option) any later version.
5175 + **
5176 + *     Module load syntax:
5177 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
5178 + *     
5179 + *     please give the ports of all RSH servers You wish to connect to.
5180 + *     If You don't specify ports, the default will be port 514
5181 + **
5182 + *      Note to all:
5183 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
5184 + *        unfortunately I babysit some sysadmins that won't migrate
5185 + *       their legacy crap, in our second tier.
5186 + */
5187 +
5188 +
5189 +/*
5190 + *  Some docco ripped from the net to teach me all there is to know about
5191 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
5192 + *  this module).
5193 + *
5194 + *  I have no idea what "unix rshd man pages" these guys have .. but that
5195 + *  is some pretty detailed docco!
5196 + **
5197 + *
5198 + *  4. Of the rsh protocol.
5199 + *  -----------------------
5200 + * 
5201 + *   The rshd listens on TCP port #514. The following info is from the unix
5202 + *   rshd man pages :
5203 + * 
5204 + *   "Service Request Protocol
5205 + * 
5206 + *    When the rshd daemon receives a service request, it initiates the
5207 + *    following protocol:
5208 + * 
5209 + *     1. The rshd daemon checks the source port number for the request.
5210 + *        If the port number is not in the range 0 through 1023, the rshd daemon
5211 + *        terminates the connection.
5212 + * 
5213 + *     2. The rshd daemon reads characters from the socket up to a null byte.
5214 + *        The string read is interpreted as an ASCII number (base 10). If this
5215 + *        number is nonzero, the rshd daemon interprets it as the port number
5216 + *        of a secondary stream to be used as standard error. A second connection
5217 + *        is created to the specified port on the client host. The source port
5218 + *        on the local host is in the range 0 through 1023.
5219 + * 
5220 + *     3. The rshd daemon uses the source address of the initial connection
5221 + *        request to determine the name of the client host. If the name cannot
5222 + *        be determined, the rshd daemon uses the dotted decimal representation
5223 + *        of the client host's address.
5224 + * 
5225 + *     4. The rshd daemon retrieves the following information from the initial
5226 + *        socket:
5227 + * 
5228 + *         * A null-terminated string of at most 16 bytes interpreted as
5229 + *           the user name of the user on the client host.
5230 + * 
5231 + *         * A null-terminated string of at most 16 bytes interpreted as
5232 + *           the user name to be used on the local server host.
5233 + * 
5234 + *         * Another null-terminated string interpreted as a command line
5235 + *           to be passed to a shell on the local server host.
5236 + * 
5237 + *     5. The rshd daemon attempts to validate the user using the following steps:
5238 + * 
5239 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
5240 + *            file and tries to switch to the home directory (using the chdir
5241 + *            subroutine). If either the lookup or the directory change fails,
5242 + *            the rshd daemon terminates the connection.
5243 + * 
5244 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
5245 + *            the /etc/hosts.equiv file to see if the name of the client
5246 + *            workstation is listed. If the client workstation is listed as an
5247 + *            equivalent host, the rshd daemon validates the user.
5248 + * 
5249 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
5250 + *            authenticate the user by checking the .rhosts file.
5251 + * 
5252 + *         d. If either the $HOME/.rhosts authentication fails or the
5253 + *            client host is not an equivalent host, the rshd daemon
5254 + *            terminates the connection.
5255 + * 
5256 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
5257 + *        on the initial connection and passes the command line to the user's
5258 + *        local login shell. The shell then inherits the network connections
5259 + *        established by the rshd daemon."
5260 + * 
5261 + */
5262 +
5263 +
5264 +#include <linux/module.h>
5265 +#include <linux/netfilter.h>
5266 +#include <linux/ip.h>
5267 +#include <net/checksum.h>
5268 +#include <net/tcp.h>
5269 +
5270 +#include <linux/netfilter_ipv4/lockhelp.h>
5271 +#include <linux/netfilter_ipv4/ip_tables.h>
5272 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5273 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
5274 +
5275 +#define MAX_PORTS 8
5276 +static int ports[MAX_PORTS];
5277 +static int ports_n_c = 0;
5278 +
5279 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
5280 +MODULE_DESCRIPTION("RSH connection tracking module");
5281 +MODULE_LICENSE("GPL");
5282 +#ifdef MODULE_PARM
5283 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5284 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
5285 +#endif
5286 +
5287 +DECLARE_LOCK(ip_rsh_lock);
5288 +struct module *ip_conntrack_rsh = THIS_MODULE;
5289 +
5290 +#if 0
5291 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
5292 +                                       format, ## args)
5293 +#else
5294 +#define DEBUGP(format, args...)
5295 +#endif
5296 +
5297 +
5298 +
5299 +/* FIXME: This should be in userspace.  Later. */
5300 +static int help(const struct iphdr *iph, size_t len,
5301 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5302 +{
5303 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5304 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
5305 +       const char *data = (const char *) tcph + tcph->doff * 4;
5306 +       u_int32_t tcplen = len - iph->ihl * 4;
5307 +       int dir = CTINFO2DIR(ctinfo);
5308 +        struct ip_conntrack_expect expect, *exp = &expect;
5309 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
5310 +       u_int16_t port;
5311 +       int maxoctet;
5312 +
5313 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
5314 +        *  original array size used in rshd/glibc) -- is there a
5315 +        *  vulnerability in rshd.c in the looped port *= 10?
5316 +        */
5317 +
5318 +
5319 +       DEBUGP("entered\n");
5320 +
5321 +       /* bail if packet is not from RSH client */
5322 +       if (dir == IP_CT_DIR_REPLY)
5323 +               return NF_ACCEPT;
5324 +
5325 +       /* Until there's been traffic both ways, don't look in packets. */
5326 +       if (ctinfo != IP_CT_ESTABLISHED
5327 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5328 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
5329 +               return NF_ACCEPT;
5330 +       }
5331 +
5332 +       /* Not whole TCP header? */
5333 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
5334 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
5335 +               return NF_ACCEPT;
5336 +       }
5337 +
5338 +       /* Checksum invalid?  Ignore. */
5339 +       /* FIXME: Source route IP option packets --RR */
5340 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5341 +                        csum_partial((char *) tcph, tcplen, 0))) {
5342 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5343 +                    tcph, tcplen, NIPQUAD(iph->saddr),
5344 +                    NIPQUAD(iph->daddr));
5345 +               return NF_ACCEPT;
5346 +       }
5347 +
5348 +       /* find the rsh stderr port */
5349 +       maxoctet = 4;
5350 +       port = 0;
5351 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
5352 +               if (*data < 0)
5353 +                       return(1);
5354 +               if (*data == 0)
5355 +                       break;
5356 +               if (*data < 48 || *data > 57) {
5357 +                       DEBUGP("these aren't the packets you're looking for ..\n");
5358 +                       return NF_ACCEPT;
5359 +               }
5360 +               port = port * 10 + ( *data - 48 );
5361 +       }
5362 +
5363 +       /* dont relate sessions that try to expose the client */
5364 +       DEBUGP("found port %u\n", port);
5365 +       if (port > 1023) {
5366 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
5367 +               return NF_ACCEPT;
5368 +       }
5369 +
5370 +
5371 +       LOCK_BH(&ip_rsh_lock);
5372 +
5373 +       /*  new(,related) connection is;
5374 +        *          reply + dst (uint)port + src port (0:1023)
5375 +        */
5376 +       memset(&expect, 0, sizeof(expect));
5377 +
5378 +       /*  save some discovered data, in case someone ever wants to write
5379 +        *  a NAT module for this bastard ..
5380 +        */
5381 +       exp_rsh_info->port = port;
5382 +
5383 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
5384 +
5385 +
5386 +       /* Watch out, Radioactive-Man! */
5387 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5388 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
5389 +       exp->tuple.src.u.tcp.port = 0;
5390 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
5391 +       exp->tuple.dst.protonum = IPPROTO_TCP;
5392 +
5393 +       exp->mask.src.ip = 0xffffffff;
5394 +       exp->mask.dst.ip = 0xffffffff;
5395 +
5396 +       exp->mask.src.u.tcp.port = htons(0xfc00);
5397 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
5398 +       exp->mask.dst.protonum = 0xffff;
5399 +
5400 +       exp->expectfn = NULL;
5401 +
5402 +       ip_conntrack_expect_related(ct, &expect);
5403 +
5404 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5405 +               NIPQUAD(exp->tuple.src.ip),
5406 +               ntohs(exp->tuple.src.u.tcp.port),
5407 +               NIPQUAD(exp->tuple.dst.ip),
5408 +               ntohs(exp->tuple.dst.u.tcp.port));
5409 +
5410 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5411 +               NIPQUAD(exp->mask.src.ip),
5412 +               ntohs(exp->mask.src.u.tcp.port),
5413 +               NIPQUAD(exp->mask.dst.ip),
5414 +               ntohs(exp->mask.dst.u.tcp.port));
5415 +       UNLOCK_BH(&ip_rsh_lock);
5416 +
5417 +       return NF_ACCEPT;
5418 +}
5419 +
5420 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
5421 +
5422 +static void fini(void);
5423 +
5424 +static int __init init(void)
5425 +{
5426 +       int port, ret;
5427 +       static char name[10];
5428 +
5429 +
5430 +       /* If no port given, default to standard RSH port */
5431 +       if (ports[0] == 0)
5432 +               ports[0] = RSH_PORT;
5433 +
5434 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5435 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
5436 +
5437 +                if (ports[port] == RSH_PORT)
5438 +                        sprintf(name, "rsh");
5439 +                else
5440 +                        sprintf(name, "rsh-%d", port);
5441 +
5442 +               rsh_helpers[port].name = name;
5443 +               rsh_helpers[port].me = THIS_MODULE;
5444 +               rsh_helpers[port].max_expected = 1;
5445 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
5446 +               rsh_helpers[port].timeout = 0;
5447 +
5448 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
5449 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
5450 +
5451 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
5452 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
5453 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
5454 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
5455 +
5456 +               rsh_helpers[port].help = help;
5457 +
5458 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
5459 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5460 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
5461 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
5462 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
5463 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
5464 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5465 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
5466 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
5467 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
5468 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
5469 +
5470 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
5471 +
5472 +               if (ret) {
5473 +                       printk("ERROR registering port %d\n",
5474 +                               ports[port]);
5475 +                       fini();
5476 +                       return -EBUSY;
5477 +               }
5478 +               ports_n_c++;
5479 +       }
5480 +       return 0;
5481 +}
5482 +
5483 +/* This function is intentionally _NOT_ defined as __exit, because 
5484 + * it is needed by the init function */
5485 +static void fini(void)
5486 +{
5487 +       int port;
5488 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5489 +               DEBUGP("unregistering port %d\n", ports[port]);
5490 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
5491 +       }
5492 +}
5493 +
5494 +module_init(init);
5495 +module_exit(fini);
5496 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
5497 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c  1970-01-01 01:00:00.000000000 +0100
5498 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c      2004-06-08 10:40:46.000000000 +0200
5499 @@ -0,0 +1,507 @@
5500 +/*
5501 + * RTSP extension for IP connection tracking
5502 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5503 + * based on ip_conntrack_irc.c
5504 + *
5505 + *      This program is free software; you can redistribute it and/or
5506 + *      modify it under the terms of the GNU General Public License
5507 + *      as published by the Free Software Foundation; either version
5508 + *      2 of the License, or (at your option) any later version.
5509 + *
5510 + * Module load syntax:
5511 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5512 + *                              max_outstanding=n setup_timeout=secs
5513 + *
5514 + * If no ports are specified, the default will be port 554.
5515 + *
5516 + * With max_outstanding you can define the maximum number of not yet
5517 + * answered SETUP requests per RTSP session (default 8).
5518 + * With setup_timeout you can specify how long the system waits for
5519 + * an expected data channel (default 300 seconds).
5520 + */
5521 +
5522 +#include <linux/config.h>
5523 +#include <linux/module.h>
5524 +#include <linux/netfilter.h>
5525 +#include <linux/ip.h>
5526 +#include <net/checksum.h>
5527 +#include <net/tcp.h>
5528 +
5529 +#include <linux/netfilter_ipv4/lockhelp.h>
5530 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5531 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5532 +
5533 +#include <linux/ctype.h>
5534 +#define NF_NEED_STRNCASECMP
5535 +#define NF_NEED_STRTOU16
5536 +#define NF_NEED_STRTOU32
5537 +#define NF_NEED_NEXTLINE
5538 +#include <linux/netfilter_helpers.h>
5539 +#define NF_NEED_MIME_NEXTLINE
5540 +#include <linux/netfilter_mime.h>
5541 +
5542 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5543 +
5544 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5545 +#ifdef IP_NF_RTSP_DEBUG
5546 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
5547 +#else
5548 +#define DEBUGP(fmt, args...)
5549 +#endif
5550 +
5551 +#define MAX_PORTS 8
5552 +static int ports[MAX_PORTS];
5553 +static int num_ports = 0;
5554 +static int max_outstanding = 8;
5555 +static unsigned int setup_timeout = 300;
5556 +
5557 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5558 +MODULE_DESCRIPTION("RTSP connection tracking module");
5559 +MODULE_LICENSE("GPL");
5560 +#ifdef MODULE_PARM
5561 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5562 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5563 +MODULE_PARM(max_outstanding, "i");
5564 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5565 +MODULE_PARM(setup_timeout, "i");
5566 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5567 +#endif
5568 +
5569 +DECLARE_LOCK(ip_rtsp_lock);
5570 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5571 +
5572 +/*
5573 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5574 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
5575 + * ports so keep this reasonably high.  If this is too low, you will see a
5576 + * lot of "no free client map entries" messages.
5577 + */
5578 +#define MAX_PORT_MAPS 16
5579 +
5580 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5581 +
5582 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5583 +
5584 +/*
5585 + * Parse an RTSP packet.
5586 + *
5587 + * Returns zero if parsing failed.
5588 + *
5589 + * Parameters:
5590 + *  IN      ptcp        tcp data pointer
5591 + *  IN      tcplen      tcp data len
5592 + *  IN/OUT  ptcpoff     points to current tcp offset
5593 + *  OUT     phdrsoff    set to offset of rtsp headers
5594 + *  OUT     phdrslen    set to length of rtsp headers
5595 + *  OUT     pcseqoff    set to offset of CSeq header
5596 + *  OUT     pcseqlen    set to length of CSeq header
5597 + */
5598 +static int
5599 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5600 +                   uint* phdrsoff, uint* phdrslen,
5601 +                   uint* pcseqoff, uint* pcseqlen)
5602 +{
5603 +    uint    entitylen = 0;
5604 +    uint    lineoff;
5605 +    uint    linelen;
5606 +
5607 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5608 +    {
5609 +        return 0;
5610 +    }
5611 +
5612 +    *phdrsoff = *ptcpoff;
5613 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5614 +    {
5615 +        if (linelen == 0)
5616 +        {
5617 +            if (entitylen > 0)
5618 +            {
5619 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5620 +            }
5621 +            break;
5622 +        }
5623 +        if (lineoff+linelen > tcplen)
5624 +        {
5625 +            INFOP("!! overrun !!\n");
5626 +            break;
5627 +        }
5628 +
5629 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5630 +        {
5631 +            *pcseqoff = lineoff;
5632 +            *pcseqlen = linelen;
5633 +        }
5634 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5635 +        {
5636 +            uint off = lineoff+15;
5637 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
5638 +            nf_strtou32(ptcp+off, &entitylen);
5639 +        }
5640 +    }
5641 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
5642 +
5643 +    return 1;
5644 +}
5645 +
5646 +/*
5647 + * Find lo/hi client ports (if any) in transport header
5648 + * In:
5649 + *   ptcp, tcplen = packet
5650 + *   tranoff, tranlen = buffer to search
5651 + *
5652 + * Out:
5653 + *   pport_lo, pport_hi = lo/hi ports (host endian)
5654 + *
5655 + * Returns nonzero if any client ports found
5656 + *
5657 + * Note: it is valid (and expected) for the client to request multiple
5658 + * transports, so we need to parse the entire line.
5659 + */
5660 +static int
5661 +rtsp_parse_transport(char* ptran, uint tranlen,
5662 +                     struct ip_ct_rtsp_expect* prtspexp)
5663 +{
5664 +    int     rc = 0;
5665 +    uint    off = 0;
5666 +
5667 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5668 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
5669 +    {
5670 +        INFOP("sanity check failed\n");
5671 +        return 0;
5672 +    }
5673 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5674 +    off += 10;
5675 +    SKIP_WSPACE(ptran, tranlen, off);
5676 +
5677 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
5678 +    while (off < tranlen)
5679 +    {
5680 +        const char* pparamend;
5681 +        uint        nextparamoff;
5682 +
5683 +        pparamend = memchr(ptran+off, ',', tranlen-off);
5684 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5685 +        nextparamoff = pparamend-ptran;
5686 +
5687 +        while (off < nextparamoff)
5688 +        {
5689 +            const char* pfieldend;
5690 +            uint        nextfieldoff;
5691 +
5692 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5693 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5694 +
5695 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
5696 +            {
5697 +                u_int16_t   port;
5698 +                uint        numlen;
5699 +
5700 +                off += 12;
5701 +                numlen = nf_strtou16(ptran+off, &port);
5702 +                off += numlen;
5703 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
5704 +                {
5705 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
5706 +                }
5707 +                else
5708 +                {
5709 +                    prtspexp->loport = prtspexp->hiport = port;
5710 +                    if (ptran[off] == '-')
5711 +                    {
5712 +                        off++;
5713 +                        numlen = nf_strtou16(ptran+off, &port);
5714 +                        off += numlen;
5715 +                        prtspexp->pbtype = pb_range;
5716 +                        prtspexp->hiport = port;
5717 +
5718 +                        // If we have a range, assume rtp:
5719 +                        // loport must be even, hiport must be loport+1
5720 +                        if ((prtspexp->loport & 0x0001) != 0 ||
5721 +                            prtspexp->hiport != prtspexp->loport+1)
5722 +                        {
5723 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
5724 +                                   prtspexp->loport, prtspexp->hiport);
5725 +                            prtspexp->loport &= 0xfffe;
5726 +                            prtspexp->hiport = prtspexp->loport+1;
5727 +                        }
5728 +                    }
5729 +                    else if (ptran[off] == '/')
5730 +                    {
5731 +                        off++;
5732 +                        numlen = nf_strtou16(ptran+off, &port);
5733 +                        off += numlen;
5734 +                        prtspexp->pbtype = pb_discon;
5735 +                        prtspexp->hiport = port;
5736 +                    }
5737 +                    rc = 1;
5738 +                }
5739 +            }
5740 +
5741 +            /*
5742 +             * Note we don't look for the destination parameter here.
5743 +             * If we are using NAT, the NAT module will handle it.  If not,
5744 +             * and the client is sending packets elsewhere, the expectation
5745 +             * will quietly time out.
5746 +             */
5747 +
5748 +            off = nextfieldoff;
5749 +        }
5750 +
5751 +        off = nextparamoff;
5752 +    }
5753 +
5754 +    return rc;
5755 +}
5756 +
5757 +/*** conntrack functions ***/
5758 +
5759 +/* outbound packet: client->server */
5760 +static int
5761 +help_out(const struct iphdr* iph, size_t pktlen,
5762 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5763 +{
5764 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
5765 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
5766 +    uint    tcplen = pktlen - iph->ihl * 4;
5767 +    char*   pdata = (char*)tcph + tcph->doff * 4;
5768 +    uint    datalen = tcplen - tcph->doff * 4;
5769 +    uint    dataoff = 0;
5770 +
5771 +    struct ip_conntrack_expect exp;
5772 +
5773 +    while (dataoff < datalen)
5774 +    {
5775 +        uint    cmdoff = dataoff;
5776 +        uint    hdrsoff = 0;
5777 +        uint    hdrslen = 0;
5778 +        uint    cseqoff = 0;
5779 +        uint    cseqlen = 0;
5780 +        uint    lineoff = 0;
5781 +        uint    linelen = 0;
5782 +        uint    off;
5783 +        int     rc;
5784 +
5785 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
5786 +                                &hdrsoff, &hdrslen,
5787 +                                &cseqoff, &cseqlen))
5788 +        {
5789 +            break;      /* not a valid message */
5790 +        }
5791 +
5792 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5793 +        {
5794 +            continue;   /* not a SETUP message */
5795 +        }
5796 +        DEBUGP("found a setup message\n");
5797 +
5798 +        memset(&exp, 0, sizeof(exp));
5799 +
5800 +        off = 0;
5801 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5802 +                                &lineoff, &linelen))
5803 +        {
5804 +            if (linelen == 0)
5805 +            {
5806 +                break;
5807 +            }
5808 +            if (off > hdrsoff+hdrslen)
5809 +            {
5810 +                INFOP("!! overrun !!");
5811 +                break;
5812 +            }
5813 +
5814 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5815 +            {
5816 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5817 +                                     &exp.help.exp_rtsp_info);
5818 +            }
5819 +        }
5820 +
5821 +        if (exp.help.exp_rtsp_info.loport == 0)
5822 +        {
5823 +            DEBUGP("no udp transports found\n");
5824 +            continue;   /* no udp transports found */
5825 +        }
5826 +
5827 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5828 +              (int)exp.help.exp_rtsp_info.pbtype,
5829 +              exp.help.exp_rtsp_info.loport,
5830 +              exp.help.exp_rtsp_info.hiport);
5831 +
5832 +        LOCK_BH(&ip_rtsp_lock);
5833 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5834 +        exp.help.exp_rtsp_info.len = hdrslen;
5835 +
5836 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5837 +        exp.mask.src.ip  = 0xffffffff;
5838 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5839 +        exp.mask.dst.ip  = 0xffffffff;
5840 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5841 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5842 +        exp.tuple.dst.protonum = IPPROTO_UDP;
5843 +        exp.mask.dst.protonum  = 0xffff;
5844 +
5845 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5846 +                NIPQUAD(exp.tuple.src.ip),
5847 +                ntohs(exp.tuple.src.u.tcp.port),
5848 +                NIPQUAD(exp.tuple.dst.ip),
5849 +                ntohs(exp.tuple.dst.u.tcp.port));
5850 +
5851 +        /* pass the request off to the nat helper */
5852 +        rc = ip_conntrack_expect_related(ct, &exp);
5853 +        UNLOCK_BH(&ip_rtsp_lock);
5854 +        if (rc == 0)
5855 +        {
5856 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
5857 +        }
5858 +        else
5859 +        {
5860 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5861 +        }
5862 +    }
5863 +
5864 +    return NF_ACCEPT;
5865 +}
5866 +
5867 +/* inbound packet: server->client */
5868 +static int
5869 +help_in(const struct iphdr* iph, size_t pktlen,
5870 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5871 +{
5872 +    return NF_ACCEPT;
5873 +}
5874 +
5875 +static int
5876 +help(const struct iphdr* iph, size_t pktlen,
5877 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5878 +{
5879 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5880 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5881 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
5882 +
5883 +    /* Until there's been traffic both ways, don't look in packets. */
5884 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5885 +    {
5886 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
5887 +        return NF_ACCEPT;
5888 +    }
5889 +
5890 +    /* Not whole TCP header? */
5891 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5892 +    {
5893 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5894 +        return NF_ACCEPT;
5895 +    }
5896 +
5897 +    /* Checksum invalid?  Ignore. */
5898 +    /* FIXME: Source route IP option packets --RR */
5899 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5900 +                     csum_partial((char*)tcph, tcplen, 0)))
5901 +    {
5902 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5903 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5904 +        return NF_ACCEPT;
5905 +    }
5906 +
5907 +    switch (CTINFO2DIR(ctinfo))
5908 +    {
5909 +    case IP_CT_DIR_ORIGINAL:
5910 +        help_out(iph, pktlen, ct, ctinfo);
5911 +        break;
5912 +    case IP_CT_DIR_REPLY:
5913 +        help_in(iph, pktlen, ct, ctinfo);
5914 +        break;
5915 +    }
5916 +
5917 +    return NF_ACCEPT;
5918 +}
5919 +
5920 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5921 +static char rtsp_names[MAX_PORTS][10];
5922 +
5923 +/* This function is intentionally _NOT_ defined as __exit */
5924 +static void
5925 +fini(void)
5926 +{
5927 +    int i;
5928 +    for (i = 0; i < num_ports; i++)
5929 +    {
5930 +        DEBUGP("unregistering port %d\n", ports[i]);
5931 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5932 +    }
5933 +}
5934 +
5935 +static int __init
5936 +init(void)
5937 +{
5938 +    int i, ret;
5939 +    struct ip_conntrack_helper *hlpr;
5940 +    char *tmpname;
5941 +
5942 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5943 +
5944 +    if (max_outstanding < 1)
5945 +    {
5946 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5947 +        return -EBUSY;
5948 +    }
5949 +    if (setup_timeout < 0)
5950 +    {
5951 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5952 +        return -EBUSY;
5953 +    }
5954 +
5955 +    /* If no port given, default to standard rtsp port */
5956 +    if (ports[0] == 0)
5957 +    {
5958 +        ports[0] = RTSP_PORT;
5959 +    }
5960 +
5961 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5962 +    {
5963 +        hlpr = &rtsp_helpers[i];
5964 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5965 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5966 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
5967 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
5968 +        hlpr->mask.dst.protonum = 0xFFFF;
5969 +        hlpr->max_expected = max_outstanding;
5970 +        hlpr->timeout = setup_timeout;
5971 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5972 +        hlpr->me = ip_conntrack_rtsp;
5973 +        hlpr->help = help;
5974 +
5975 +        tmpname = &rtsp_names[i][0];
5976 +        if (ports[i] == RTSP_PORT)
5977 +        {
5978 +            sprintf(tmpname, "rtsp");
5979 +        }
5980 +        else
5981 +        {
5982 +            sprintf(tmpname, "rtsp-%d", i);
5983 +        }
5984 +        hlpr->name = tmpname;
5985 +
5986 +        DEBUGP("port #%d: %d\n", i, ports[i]);
5987 +
5988 +        ret = ip_conntrack_helper_register(hlpr);
5989 +
5990 +        if (ret)
5991 +        {
5992 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5993 +            fini();
5994 +            return -EBUSY;
5995 +        }
5996 +        num_ports++;
5997 +    }
5998 +    return 0;
5999 +}
6000 +
6001 +#ifdef CONFIG_IP_NF_NAT_NEEDED
6002 +EXPORT_SYMBOL(ip_rtsp_lock);
6003 +#endif
6004 +
6005 +module_init(init);
6006 +module_exit(fini);
6007 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
6008 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-06-07 21:14:11.000000000 +0200
6009 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-06-08 10:38:45.000000000 +0200
6010 @@ -110,6 +110,9 @@
6011                 len += sprintf(buffer + len, "[ASSURED] ");
6012         len += sprintf(buffer + len, "use=%u ",
6013                        atomic_read(&conntrack->ct_general.use));
6014 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
6015 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
6016 +#endif
6017         len += sprintf(buffer + len, "\n");
6018  
6019         return len;
6020 @@ -502,7 +505,7 @@
6021         if (ret < 0)
6022                 goto cleanup_nothing;
6023  
6024 -       proc = proc_net_create("ip_conntrack",0,list_conntracks);
6025 +       proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
6026         if (!proc) goto cleanup_init;
6027         proc->owner = THIS_MODULE;
6028  
6029 @@ -633,6 +636,7 @@
6030  EXPORT_SYMBOL(ip_conntrack_alter_reply);
6031  EXPORT_SYMBOL(ip_conntrack_destroyed);
6032  EXPORT_SYMBOL(ip_conntrack_get);
6033 +EXPORT_SYMBOL(__ip_conntrack_confirm);
6034  EXPORT_SYMBOL(need_ip_conntrack);
6035  EXPORT_SYMBOL(ip_conntrack_helper_register);
6036  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
6037 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
6038 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c  1970-01-01 01:00:00.000000000 +0100
6039 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_conntrack_talk.c      2004-06-08 10:41:27.000000000 +0200
6040 @@ -0,0 +1,360 @@
6041 +/* 
6042 + * talk extension for IP connection tracking. 
6043 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6044 + *
6045 + *      This program is free software; you can redistribute it and/or
6046 + *      modify it under the terms of the GNU General Public License
6047 + *      as published by the Free Software Foundation; either version
6048 + *      2 of the License, or (at your option) any later version.
6049 + **
6050 + *     Module load syntax:
6051 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
6052 + *
6053 + *             talk=[0|1]      disable|enable old talk support
6054 + *            ntalk=[0|1]      disable|enable ntalk support
6055 + *           ntalk2=[0|1]      disable|enable ntalk2 support
6056 + *
6057 + *     The default is talk=1 ntalk=1 ntalk2=1
6058 + *
6059 + *     The helper does not support simultaneous talk requests.
6060 + **
6061 + *
6062 + *             ASCII art on talk protocols
6063 + *     
6064 + *     
6065 + *     caller server               callee server
6066 + *             |     \           /
6067 + *             |       \       /
6068 + *             |         \   /
6069 + *             |           /  
6070 + *             |         /   \
6071 + *           2 |     1 /       \ 3
6072 + *     caller client  ----------- callee client
6073 + *                              4
6074 + *
6075 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
6076 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
6077 + *     3. callee client <-> caller server: LOOK_UP invitation
6078 + *     4. callee client <-> caller client: talk data channel
6079 + *
6080 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
6081 + *      draft-hunter-talk-00.txt
6082 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
6083 + */
6084 +#include <linux/config.h>
6085 +#include <linux/module.h>
6086 +#include <linux/netfilter.h>
6087 +#include <linux/ip.h>
6088 +#include <net/checksum.h>
6089 +#include <net/udp.h>
6090 +
6091 +#include <linux/netfilter_ipv4/lockhelp.h>
6092 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6093 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
6094 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6095 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
6096 +
6097 +/* Default all talk protocols are supported */
6098 +static int talk = 1;
6099 +static int ntalk = 1;
6100 +static int ntalk2 = 1;
6101 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6102 +MODULE_DESCRIPTION("talk connection tracking module");
6103 +MODULE_LICENSE("GPL");
6104 +#ifdef MODULE_PARM
6105 +MODULE_PARM(talk, "i");
6106 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
6107 +MODULE_PARM(ntalk, "i");
6108 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
6109 +MODULE_PARM(ntalk2, "i");
6110 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
6111 +#endif
6112 +
6113 +DECLARE_LOCK(ip_talk_lock);
6114 +struct module *ip_conntrack_talk = THIS_MODULE;
6115 +
6116 +#if 0
6117 +#define DEBUGP printk
6118 +#else
6119 +#define DEBUGP(format, args...)
6120 +#endif
6121 +
6122 +static int talk_expect(struct ip_conntrack *ct);
6123 +static int ntalk_expect(struct ip_conntrack *ct);
6124 +
6125 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
6126 +
6127 +static int talk_help_response(const struct iphdr *iph, size_t len,
6128 +                             struct ip_conntrack *ct,
6129 +                             enum ip_conntrack_info ctinfo,
6130 +                             int talk_port,
6131 +                             u_char mode,
6132 +                             u_char type,
6133 +                             u_char answer,
6134 +                             struct talk_addr *addr)
6135 +{
6136 +       int dir = CTINFO2DIR(ctinfo);
6137 +       struct ip_conntrack_expect expect, *exp = &expect;
6138 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
6139 +
6140 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
6141 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
6142 +               type, answer);
6143 +
6144 +       if (!(answer == SUCCESS && type == mode))
6145 +               return NF_ACCEPT;
6146 +       
6147 +       memset(&expect, 0, sizeof(expect));
6148 +       
6149 +       if (type == ANNOUNCE) {
6150 +
6151 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
6152 +
6153 +               /* update the talk info */
6154 +               LOCK_BH(&ip_talk_lock);
6155 +               exp_talk_info->port = htons(talk_port);
6156 +
6157 +               /* expect callee client -> caller server message */
6158 +               exp->tuple = ((struct ip_conntrack_tuple)
6159 +                       { { ct->tuplehash[dir].tuple.src.ip,
6160 +                           { 0 } },
6161 +                         { ct->tuplehash[dir].tuple.dst.ip,
6162 +                           { .tcp = { htons(talk_port) } },
6163 +                           IPPROTO_UDP }});
6164 +               exp->mask = ((struct ip_conntrack_tuple)
6165 +                       { { 0xFFFFFFFF, { 0 } },
6166 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6167 +               
6168 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
6169 +
6170 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
6171 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
6172 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
6173 +
6174 +               /* Ignore failure; should only happen with NAT */
6175 +               ip_conntrack_expect_related(ct, &expect);
6176 +               UNLOCK_BH(&ip_talk_lock);
6177 +       }
6178 +       if (type == LOOK_UP) {
6179 +
6180 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
6181 +
6182 +               /* update the talk info */
6183 +               LOCK_BH(&ip_talk_lock);
6184 +               exp_talk_info->port = addr->ta_port;
6185 +
6186 +               /* expect callee client -> caller client connection */
6187 +               exp->tuple = ((struct ip_conntrack_tuple)
6188 +                       { { ct->tuplehash[!dir].tuple.src.ip,
6189 +                           { 0 } },
6190 +                         { addr->ta_addr,
6191 +                           { addr->ta_port },
6192 +                           IPPROTO_TCP }});
6193 +               exp->mask = ((struct ip_conntrack_tuple)
6194 +                       { { 0xFFFFFFFF, { 0 } },
6195 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6196 +               
6197 +               exp->expectfn = NULL;
6198 +               
6199 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
6200 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
6201 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
6202 +
6203 +               /* Ignore failure; should only happen with NAT */
6204 +               ip_conntrack_expect_related(ct, &expect);
6205 +               UNLOCK_BH(&ip_talk_lock);
6206 +       }
6207 +                   
6208 +       return NF_ACCEPT;
6209 +}
6210 +
6211 +/* FIXME: This should be in userspace.  Later. */
6212 +static int talk_help(const struct iphdr *iph, size_t len,
6213 +                    struct ip_conntrack *ct,
6214 +                    enum ip_conntrack_info ctinfo,
6215 +                    int talk_port,
6216 +                    u_char mode)
6217 +{
6218 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
6219 +       const char *data = (const char *)udph + sizeof(struct udphdr);
6220 +       int dir = CTINFO2DIR(ctinfo);
6221 +       size_t udplen;
6222 +
6223 +       DEBUGP("ip_ct_talk_help: help entered\n");
6224 +
6225 +       /* Until there's been traffic both ways, don't look in packets. */
6226 +       if (ctinfo != IP_CT_ESTABLISHED
6227 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6228 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
6229 +               return NF_ACCEPT;
6230 +       }
6231 +
6232 +       /* Not whole UDP header? */
6233 +       udplen = len - iph->ihl * 4;
6234 +       if (udplen < sizeof(struct udphdr)) {
6235 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
6236 +               return NF_ACCEPT;
6237 +       }
6238 +
6239 +       /* Checksum invalid?  Ignore. */
6240 +       /* FIXME: Source route IP option packets --RR */
6241 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
6242 +                             csum_partial((char *)udph, udplen, 0))) {
6243 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6244 +                      udph, udplen, NIPQUAD(iph->saddr),
6245 +                      NIPQUAD(iph->daddr));
6246 +               return NF_ACCEPT;
6247 +       }
6248 +       
6249 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6250 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
6251 +
6252 +       if (dir == IP_CT_DIR_ORIGINAL)
6253 +               return NF_ACCEPT;
6254 +               
6255 +       if (talk_port == TALK_PORT
6256 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
6257 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6258 +                                         ((struct talk_response *)data)->type, 
6259 +                                         ((struct talk_response *)data)->answer,
6260 +                                         &(((struct talk_response *)data)->addr));
6261 +       else if (talk_port == NTALK_PORT
6262 +                 && ntalk
6263 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
6264 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
6265 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6266 +                                         ((struct ntalk_response *)data)->type, 
6267 +                                         ((struct ntalk_response *)data)->answer,
6268 +                                         &(((struct ntalk_response *)data)->addr));
6269 +       else if (talk_port == NTALK_PORT
6270 +                && ntalk2
6271 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
6272 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
6273 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
6274 +                                         ((struct ntalk2_response *)data)->type, 
6275 +                                         ((struct ntalk2_response *)data)->answer,
6276 +                                         &(((struct ntalk2_response *)data)->addr));
6277 +       else {
6278 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
6279 +                      (unsigned)udplen - sizeof(struct udphdr), 
6280 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
6281 +               return NF_ACCEPT;
6282 +       }
6283 +}
6284 +
6285 +static int lookup_help(const struct iphdr *iph, size_t len,
6286 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6287 +{
6288 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
6289 +}
6290 +
6291 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
6292 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6293 +{
6294 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
6295 +}
6296 +
6297 +static struct ip_conntrack_helper lookup_helpers[2] = 
6298 +       { { { NULL, NULL },
6299 +           "talk",                                     /* name */
6300 +           0,                                          /* flags */
6301 +           NULL,                                       /* module */
6302 +           1,                                          /* max_expected */
6303 +           240,                                        /* timeout */
6304 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
6305 +             { 0, { 0 }, IPPROTO_UDP } },
6306 +           { { 0, { 0xFFFF } },                        /* mask */
6307 +             { 0, { 0 }, 0xFFFF } },
6308 +           lookup_help },                              /* helper */
6309 +          { { NULL, NULL },
6310 +            "ntalk",                                   /* name */
6311 +           0,                                          /* flags */
6312 +           NULL,                                       /* module */
6313 +           1,                                          /* max_expected */
6314 +           240,                                        /* timeout */
6315 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
6316 +             { 0, { 0 }, IPPROTO_UDP } },
6317 +           { { 0, { 0xFFFF } },                        /* mask */
6318 +             { 0, { 0 }, 0xFFFF } },
6319 +           lookup_nhelp }                              /* helper */
6320 +        };
6321 +
6322 +static int talk_expect(struct ip_conntrack *ct)
6323 +{
6324 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
6325 +       WRITE_LOCK(&ip_conntrack_lock);
6326 +       ct->helper = &lookup_helpers[0];
6327 +       WRITE_UNLOCK(&ip_conntrack_lock);
6328 +        
6329 +       return NF_ACCEPT;       /* unused */
6330 +}
6331 +
6332 +static int ntalk_expect(struct ip_conntrack *ct)
6333 +{
6334 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
6335 +       WRITE_LOCK(&ip_conntrack_lock);
6336 +       ct->helper = &lookup_helpers[1];
6337 +       WRITE_UNLOCK(&ip_conntrack_lock);
6338 +        
6339 +       return NF_ACCEPT;       /* unused */
6340 +}
6341 +
6342 +static int help(const struct iphdr *iph, size_t len,
6343 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6344 +{
6345 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
6346 +}
6347 +
6348 +static int nhelp(const struct iphdr *iph, size_t len,
6349 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6350 +{
6351 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
6352 +}
6353 +
6354 +static struct ip_conntrack_helper talk_helpers[2] = 
6355 +       { { { NULL, NULL },
6356 +           "talk",                                     /* name */
6357 +           0,                                          /* flags */
6358 +           THIS_MODULE,                                /* module */
6359 +           1,                                          /* max_expected */
6360 +           240,                                        /* timeout */
6361 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
6362 +             { 0, { 0 }, IPPROTO_UDP } },
6363 +           { { 0, { 0xFFFF } },                        /* mask */
6364 +             { 0, { 0 }, 0xFFFF } },
6365 +           help },                                     /* helper */
6366 +          { { NULL, NULL },
6367 +           "ntalk",                                    /* name */
6368 +           0,                                          /* flags */
6369 +           THIS_MODULE,                                /* module */
6370 +           1,                                          /* max_expected */
6371 +           240,                                        /* timeout */
6372 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
6373 +             { 0, { 0 }, IPPROTO_UDP } },
6374 +           { { 0, { 0xFFFF } },                        /* mask */
6375 +             { 0, { 0 }, 0xFFFF } },
6376 +           nhelp }                                     /* helper */
6377 +       };
6378 +
6379 +static int __init init(void)
6380 +{
6381 +       if (talk > 0)
6382 +               ip_conntrack_helper_register(&talk_helpers[0]);
6383 +       if (ntalk > 0 || ntalk2 > 0)
6384 +               ip_conntrack_helper_register(&talk_helpers[1]);
6385 +               
6386 +       return 0;
6387 +}
6388 +
6389 +static void __exit fini(void)
6390 +{
6391 +       if (talk > 0)
6392 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
6393 +       if (ntalk > 0 || ntalk2 > 0)
6394 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
6395 +}
6396 +
6397 +EXPORT_SYMBOL(ip_talk_lock);
6398 +
6399 +module_init(init);
6400 +module_exit(fini);
6401 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_core.c
6402 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_core.c        2004-06-07 21:13:39.000000000 +0200
6403 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_core.c    2004-06-08 10:30:32.000000000 +0200
6404 @@ -816,7 +816,7 @@
6405  
6406                 /* Have to grab read lock before sibling_list traversal */
6407                 READ_LOCK(&ip_conntrack_lock);
6408 -               list_for_each(cur_item, &ct->sibling_list) { 
6409 +               list_for_each_prev(cur_item, &ct->sibling_list) { 
6410                         exp = list_entry(cur_item, struct ip_conntrack_expect, 
6411                                          expected_list);
6412                                          
6413 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_h323.c
6414 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_h323.c        1970-01-01 01:00:00.000000000 +0100
6415 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_h323.c    2004-06-08 10:38:40.000000000 +0200
6416 @@ -0,0 +1,419 @@
6417 +/* 
6418 + * H.323 'brute force' extension for NAT alteration. 
6419 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6420 + *
6421 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6422 + * (http://www.coritel.it/projects/sofia/nat.html)
6423 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6424 + * the unregistered helpers to the conntrack entries.
6425 + */
6426 +
6427 +
6428 +#include <linux/module.h>
6429 +#include <linux/netfilter.h>
6430 +#include <linux/ip.h>
6431 +#include <net/checksum.h>
6432 +#include <net/tcp.h>
6433 +
6434 +#include <linux/netfilter_ipv4/lockhelp.h>
6435 +#include <linux/netfilter_ipv4/ip_nat.h>
6436 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6437 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6438 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6439 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6440 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6441 +
6442 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6443 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6444 +MODULE_LICENSE("GPL");
6445 +
6446 +DECLARE_LOCK_EXTERN(ip_h323_lock);
6447 +struct module *ip_nat_h323 = THIS_MODULE;
6448 +
6449 +#if 0
6450 +#define DEBUGP printk
6451 +#else
6452 +#define DEBUGP(format, args...)
6453 +#endif
6454 +
6455 +/* FIXME: Time out? --RR */
6456 +
6457 +static unsigned int 
6458 +h225_nat_expected(struct sk_buff **pskb,
6459 +                 unsigned int hooknum,
6460 +                 struct ip_conntrack *ct,
6461 +                 struct ip_nat_info *info);
6462 +
6463 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6464 +                                 struct ip_conntrack_expect *exp,
6465 +                                 struct ip_nat_info *info,
6466 +                                 enum ip_conntrack_info ctinfo,
6467 +                                 unsigned int hooknum,
6468 +                                 struct sk_buff **pskb);
6469 +                 
6470 +static struct ip_nat_helper h245 = 
6471 +       { { NULL, NULL },
6472 +          "H.245",                             /* name */
6473 +         0,                                    /* flags */
6474 +         NULL,                                 /* module */
6475 +         { { 0, { 0 } },                       /* tuple */
6476 +           { 0, { 0 }, IPPROTO_TCP } },
6477 +         { { 0, { 0xFFFF } },                  /* mask */
6478 +           { 0, { 0 }, 0xFFFF } },
6479 +         h225_nat_help,                        /* helper */
6480 +         h225_nat_expected                     /* expectfn */
6481 +       };
6482 +
6483 +static unsigned int
6484 +h225_nat_expected(struct sk_buff **pskb,
6485 +                 unsigned int hooknum,
6486 +                 struct ip_conntrack *ct,
6487 +                 struct ip_nat_info *info)
6488 +{
6489 +       struct ip_nat_multi_range mr;
6490 +       u_int32_t newdstip, newsrcip, newip;
6491 +       u_int16_t port;
6492 +       struct ip_ct_h225_expect *exp_info;
6493 +       struct ip_ct_h225_master *master_info;
6494 +       struct ip_conntrack *master = master_ct(ct);
6495 +       unsigned int is_h225, ret;
6496 +       
6497 +       IP_NF_ASSERT(info);
6498 +       IP_NF_ASSERT(master);
6499 +
6500 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6501 +
6502 +       DEBUGP("h225_nat_expected: We have a connection!\n");
6503 +       master_info = &ct->master->expectant->help.ct_h225_info;
6504 +       exp_info = &ct->master->help.exp_h225_info;
6505 +
6506 +       LOCK_BH(&ip_h323_lock);
6507 +
6508 +       DEBUGP("master: ");
6509 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6510 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6511 +       DEBUGP("conntrack: ");
6512 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6513 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6514 +               /* Make connection go to the client. */
6515 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6516 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6517 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6518 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6519 +       } else {
6520 +               /* Make the connection go to the server */
6521 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6522 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6523 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6524 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6525 +       }
6526 +       port = exp_info->port;
6527 +       is_h225 = master_info->is_h225 == H225_PORT;
6528 +       UNLOCK_BH(&ip_h323_lock);
6529 +       
6530 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6531 +               newip = newsrcip;
6532 +       else
6533 +               newip = newdstip;
6534 +
6535 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6536 +
6537 +       mr.rangesize = 1;
6538 +       /* We don't want to manip the per-protocol, just the IPs... */
6539 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6540 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6541 +
6542 +       /* ... unless we're doing a MANIP_DST, in which case, make
6543 +          sure we map to the correct port */
6544 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6545 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6546 +               mr.range[0].min = mr.range[0].max
6547 +                       = ((union ip_conntrack_manip_proto)
6548 +                               { .tcp = { port } });
6549 +       }
6550 +
6551 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
6552 +       
6553 +       if (is_h225) {
6554 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6555 +               /* NAT expectfn called with ip_nat_lock write-locked */
6556 +               info->helper = &h245;
6557 +       }
6558 +       return ret;
6559 +}
6560 +
6561 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6562 +                                    struct sk_buff **pskb,
6563 +                                    enum ip_conntrack_info ctinfo)
6564 +{
6565 +       struct iphdr *iph = (*pskb)->nh.iph;
6566 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6567 +       char *data = (char *) tcph + tcph->doff * 4;
6568 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6569 +       u_int32_t datalen = tcplen - tcph->doff*4;
6570 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
6571 +       u_int32_t newip;
6572 +       u_int16_t port;
6573 +       int i;
6574 +
6575 +       MUST_BE_LOCKED(&ip_h323_lock);
6576 +
6577 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
6578 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6579 +                       ? "yes" : "no",
6580 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6581 +                       ? "yes" : "no");
6582 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6583 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6584 +               return 1;
6585 +
6586 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
6587 +               info->offset[IP_CT_DIR_ORIGINAL], 
6588 +               info->offset[IP_CT_DIR_REPLY],
6589 +               tcplen);
6590 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6591 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6592 +
6593 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
6594 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
6595 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6596 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6597 +               if (!between(info->seq[i], ntohl(tcph->seq), 
6598 +                            ntohl(tcph->seq) + datalen))
6599 +                       continue;
6600 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6601 +                            ntohl(tcph->seq) + datalen)) {
6602 +                       /* Partial retransmisison. It's a cracker being funky. */
6603 +                       if (net_ratelimit()) {
6604 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6605 +                                    info->seq[i],
6606 +                                    ntohl(tcph->seq),
6607 +                                    ntohl(tcph->seq) + datalen);
6608 +                       }
6609 +                       return 0;
6610 +               }
6611 +
6612 +               /* Change address inside packet to match way we're mapping
6613 +                  this connection. */
6614 +               if (i == IP_CT_DIR_ORIGINAL) {
6615 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6616 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6617 +               } else {
6618 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
6619 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6620 +               }
6621 +
6622 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
6623 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6624 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6625 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6626 +
6627 +               /* Modify the packet */
6628 +               *(u_int32_t *)(data + info->offset[i]) = newip;
6629 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
6630 +       
6631 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
6632 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6633 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6634 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6635 +       }
6636 +
6637 +       /* fix checksum information */
6638 +
6639 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6640 +                                    datalen, 0);
6641 +
6642 +       tcph->check = 0;
6643 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6644 +                                  csum_partial((char *)tcph, tcph->doff*4,
6645 +                                          (*pskb)->csum));
6646 +       ip_send_check(iph);
6647 +
6648 +       return 1;
6649 +}
6650 +
6651 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6652 +                          struct ip_conntrack *ct,
6653 +                          struct sk_buff **pskb,
6654 +                          enum ip_conntrack_info ctinfo,
6655 +                          struct ip_conntrack_expect *expect)
6656 +{
6657 +       u_int32_t newip;
6658 +       u_int16_t port;
6659 +       struct ip_conntrack_tuple newtuple;
6660 +       struct iphdr *iph = (*pskb)->nh.iph;
6661 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6662 +       char *data = (char *) tcph + tcph->doff * 4;
6663 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6664 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6665 +       int is_h225;
6666 +
6667 +       MUST_BE_LOCKED(&ip_h323_lock);
6668 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6669 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6670 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6671 +
6672 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
6673 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6674 +               /* Partial retransmisison. It's a cracker being funky. */
6675 +               if (net_ratelimit()) {
6676 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6677 +                            expect->seq,
6678 +                            ntohl(tcph->seq),
6679 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6680 +               }
6681 +               return 0;
6682 +       }
6683 +
6684 +       /* Change address inside packet to match way we're mapping
6685 +          this connection. */
6686 +       if (info->dir == IP_CT_DIR_REPLY) {
6687 +               /* Must be where client thinks server is */
6688 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6689 +               /* Expect something from client->server */
6690 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6691 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6692 +       } else {
6693 +               /* Must be where server thinks client is */
6694 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6695 +               /* Expect something from server->client */
6696 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6697 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6698 +       }
6699 +
6700 +       is_h225 = (master_info->is_h225 == H225_PORT);
6701 +
6702 +       if (is_h225) {
6703 +               newtuple.dst.protonum = IPPROTO_TCP;
6704 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6705 +       } else {
6706 +               newtuple.dst.protonum = IPPROTO_UDP;
6707 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6708 +       }
6709 +       
6710 +       /* Try to get same port: if not, try to change it. */
6711 +       for (port = ntohs(info->port); port != 0; port++) {
6712 +               if (is_h225)
6713 +                       newtuple.dst.u.tcp.port = htons(port);
6714 +               else
6715 +                       newtuple.dst.u.udp.port = htons(port);
6716 +
6717 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6718 +                       break;
6719 +       }
6720 +       if (port == 0) {
6721 +               DEBUGP("h323_data_fixup: no free port found!\n");
6722 +               return 0;
6723 +       }
6724 +
6725 +       port = htons(port);
6726 +
6727 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
6728 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6729 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6730 +
6731 +       /* Modify the packet */
6732 +       *(u_int32_t *)(data + info->offset) = newip;
6733 +       *(u_int16_t *)(data + info->offset + 4) = port;
6734 +       
6735 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
6736 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6737 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6738 +
6739 +       /* fix checksum information  */
6740 +       /* FIXME: usually repeated multiple times in the case of H.245! */
6741 +
6742 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6743 +                                    tcplen - tcph->doff*4, 0);
6744 +
6745 +       tcph->check = 0;
6746 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6747 +                                  csum_partial((char *)tcph, tcph->doff*4,
6748 +                                          (*pskb)->csum));
6749 +       ip_send_check(iph);
6750 +
6751 +       return 1;
6752 +}
6753 +
6754 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6755 +                                 struct ip_conntrack_expect *exp,
6756 +                                 struct ip_nat_info *info,
6757 +                                 enum ip_conntrack_info ctinfo,
6758 +                                 unsigned int hooknum,
6759 +                                 struct sk_buff **pskb)
6760 +{
6761 +       int dir;
6762 +       struct ip_ct_h225_expect *exp_info;
6763 +       
6764 +       /* Only mangle things once: original direction in POST_ROUTING
6765 +          and reply direction on PRE_ROUTING. */
6766 +       dir = CTINFO2DIR(ctinfo);
6767 +       DEBUGP("nat_h323: dir %s at hook %s\n",
6768 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6769 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6770 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6771 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6772 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6773 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6774 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6775 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6776 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6777 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6778 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6779 +               return NF_ACCEPT;
6780 +       }
6781 +
6782 +       if (!exp) {
6783 +               LOCK_BH(&ip_h323_lock);
6784 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6785 +                       UNLOCK_BH(&ip_h323_lock);
6786 +                       return NF_DROP;
6787 +               }
6788 +               UNLOCK_BH(&ip_h323_lock);
6789 +               return NF_ACCEPT;
6790 +       }
6791 +               
6792 +       exp_info = &exp->help.exp_h225_info;
6793 +
6794 +       LOCK_BH(&ip_h323_lock);
6795 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6796 +               UNLOCK_BH(&ip_h323_lock);
6797 +               return NF_DROP;
6798 +       }
6799 +       UNLOCK_BH(&ip_h323_lock);
6800 +
6801 +       return NF_ACCEPT;
6802 +}
6803 +
6804 +static struct ip_nat_helper h225 = 
6805 +       { { NULL, NULL },
6806 +         "H.225",                                      /* name */
6807 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
6808 +         THIS_MODULE,                                  /* module */
6809 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
6810 +           { 0, { 0 }, IPPROTO_TCP } },
6811 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
6812 +           { 0, { 0 }, 0xFFFF } },
6813 +         h225_nat_help,                                /* helper */
6814 +         h225_nat_expected                             /* expectfn */
6815 +       };
6816 +
6817 +static int __init init(void)
6818 +{
6819 +       int ret;
6820 +       
6821 +       ret = ip_nat_helper_register(&h225);
6822 +
6823 +       if (ret != 0)
6824 +               printk("ip_nat_h323: cannot initialize the module!\n");
6825 +
6826 +       return ret;
6827 +}
6828 +
6829 +static void __exit fini(void)
6830 +{
6831 +       ip_nat_helper_unregister(&h225);
6832 +}
6833 +
6834 +module_init(init);
6835 +module_exit(fini);
6836 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_mms.c
6837 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6838 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_mms.c     2004-06-08 10:39:44.000000000 +0200
6839 @@ -0,0 +1,350 @@
6840 +/* MMS extension for TCP NAT alteration.
6841 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6842 + * based on ip_nat_ftp.c and ip_nat_irc.c
6843 + *
6844 + * ip_nat_mms.c v0.3 2002-09-22
6845 + *
6846 + *      This program is free software; you can redistribute it and/or
6847 + *      modify it under the terms of the GNU General Public License
6848 + *      as published by the Free Software Foundation; either version
6849 + *      2 of the License, or (at your option) any later version.
6850 + *
6851 + *      Module load syntax:
6852 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6853 + *
6854 + *      Please give the ports of all MMS servers You wish to connect to.
6855 + *      If you don't specify ports, the default will be TCP port 1755.
6856 + *
6857 + *      More info on MMS protocol, firewalls and NAT:
6858 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6859 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6860 + *
6861 + *      The SDP project people are reverse-engineering MMS:
6862 + *      http://get.to/sdp
6863 + */
6864 +
6865 +/* FIXME: issue with UDP & fragmentation with this URL: 
6866 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
6867 +   may be related to out-of-order first packets:
6868 +   basically the expectation is set up correctly, then the server sends
6869 +   a first UDP packet which is fragmented plus arrives out-of-order.
6870 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
6871 +   an ICMP unreachable back to the server */
6872 +
6873 +#include <linux/module.h>
6874 +#include <linux/netfilter_ipv4.h>
6875 +#include <linux/ip.h>
6876 +#include <linux/tcp.h>
6877 +#include <net/tcp.h>
6878 +#include <linux/netfilter_ipv4/ip_nat.h>
6879 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6880 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6881 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6882 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6883 +
6884 +#if 0 
6885 +#define DEBUGP printk
6886 +#define DUMP_BYTES(address, counter)                                \
6887 +({                                                                  \
6888 +       int temp_counter;                                           \
6889 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6890 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
6891 +       };                                                          \
6892 +       DEBUGP("\n");                                               \
6893 +})
6894 +#else
6895 +#define DEBUGP(format, args...)
6896 +#define DUMP_BYTES(address, counter)
6897 +#endif
6898 +
6899 +#define MAX_PORTS 8
6900 +static int ports[MAX_PORTS];
6901 +static int ports_c = 0;
6902 +
6903 +#ifdef MODULE_PARM
6904 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6905 +#endif
6906 +
6907 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6908 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6909 +MODULE_LICENSE("GPL");
6910 +
6911 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6912 +
6913 +/* FIXME: Time out? --RR */
6914 +
6915 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6916 +                          struct ip_conntrack *ct,
6917 +                          struct sk_buff **pskb,
6918 +                          enum ip_conntrack_info ctinfo,
6919 +                          struct ip_conntrack_expect *expect)
6920 +{
6921 +       u_int32_t newip;
6922 +       struct ip_conntrack_tuple t;
6923 +       struct iphdr *iph = (*pskb)->nh.iph;
6924 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6925 +       char *data = (char *)tcph + tcph->doff * 4;
6926 +       int i, j, k, port;
6927 +       u_int16_t mms_proto;
6928 +
6929 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6930 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6931 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6932 +
6933 +       int zero_padding;
6934 +
6935 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6936 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6937 +       char proto_string[6];
6938 +       
6939 +       MUST_BE_LOCKED(&ip_mms_lock);
6940 +
6941 +       /* what was the protocol again ? */
6942 +       mms_proto = expect->tuple.dst.protonum;
6943 +       sprintf(proto_string, "%u", mms_proto);
6944 +       
6945 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6946 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6947 +              mms_proto == IPPROTO_UDP ? "UDP"
6948 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6949 +       
6950 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6951 +
6952 +       /* Alter conntrack's expectations. */
6953 +       t = expect->tuple;
6954 +       t.dst.ip = newip;
6955 +       for (port = ct_mms_info->port; port != 0; port++) {
6956 +               t.dst.u.tcp.port = htons(port);
6957 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
6958 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6959 +                       break;
6960 +               }
6961 +       }
6962 +       
6963 +       if(port == 0)
6964 +               return 0;
6965 +
6966 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6967 +               NIPQUAD(newip),
6968 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6969 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6970 +               port);
6971 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6972 +       
6973 +       memset(unicode_buffer, 0, sizeof(char)*75);
6974 +
6975 +       for (i=0; i<strlen(buffer); ++i)
6976 +               *(unicode_buffer+i*2)=*(buffer+i);
6977 +       
6978 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6979 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6980 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6981 +       
6982 +       /* add end of packet to it */
6983 +       for (j=0; j<ct_mms_info->padding; ++j) {
6984 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
6985 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6986 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6987 +       }
6988 +
6989 +       /* pad with zeroes at the end ? see explanation of weird math below */
6990 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6991 +       for (k=0; k<zero_padding; ++k)
6992 +               *(unicode_buffer+i*2+j+k)= (char)0;
6993 +       
6994 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6995 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6996 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6997 +       
6998 +       /* explanation, before I forget what I did:
6999 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
7000 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
7001 +          but note that things may have to be padded with zeroes to align by 8 
7002 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
7003 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
7004 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
7005 +       *mms_messageLength = *mms_chunkLenLV*8;
7006 +       
7007 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
7008 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
7009 +       
7010 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
7011 +                                expect->seq - ntohl(tcph->seq),
7012 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
7013 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
7014 +       DUMP_BYTES(unicode_buffer, 60);
7015 +       
7016 +       return 1;
7017 +}
7018 +
7019 +static unsigned int
7020 +mms_nat_expected(struct sk_buff **pskb,
7021 +                 unsigned int hooknum,
7022 +                 struct ip_conntrack *ct,
7023 +                 struct ip_nat_info *info)
7024 +{
7025 +       struct ip_nat_multi_range mr;
7026 +       u_int32_t newdstip, newsrcip, newip;
7027 +
7028 +       struct ip_conntrack *master = master_ct(ct);
7029 +
7030 +       IP_NF_ASSERT(info);
7031 +       IP_NF_ASSERT(master);
7032 +
7033 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7034 +
7035 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
7036 +
7037 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7038 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7039 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
7040 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7041 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7042 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7043 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
7044 +
7045 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
7046 +               newip = newsrcip;
7047 +       else
7048 +               newip = newdstip;
7049 +
7050 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
7051 +
7052 +       mr.rangesize = 1;
7053 +       /* We don't want to manip the per-protocol, just the IPs. */
7054 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7055 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
7056 +
7057 +       return ip_nat_setup_info(ct, &mr, hooknum);
7058 +}
7059 +
7060 +
7061 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
7062 +                        struct ip_conntrack_expect *exp,
7063 +                        struct ip_nat_info *info,
7064 +                        enum ip_conntrack_info ctinfo,
7065 +                        unsigned int hooknum,
7066 +                        struct sk_buff **pskb)
7067 +{
7068 +       struct iphdr *iph = (*pskb)->nh.iph;
7069 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
7070 +       unsigned int datalen;
7071 +       int dir;
7072 +       struct ip_ct_mms_expect *ct_mms_info;
7073 +
7074 +       if (!exp)
7075 +               DEBUGP("ip_nat_mms: no exp!!");
7076 +
7077 +       ct_mms_info = &exp->help.exp_mms_info;
7078 +       
7079 +       /* Only mangle things once: original direction in POST_ROUTING
7080 +          and reply direction on PRE_ROUTING. */
7081 +       dir = CTINFO2DIR(ctinfo);
7082 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7083 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7084 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
7085 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7086 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7087 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7088 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7089 +               return NF_ACCEPT;
7090 +       }
7091 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
7092 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7093 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7094 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7095 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7096 +       
7097 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7098 +       
7099 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
7100 +              exp->seq + ct_mms_info->len,
7101 +              ntohl(tcph->seq),
7102 +              ntohl(tcph->seq) + datalen);
7103 +       
7104 +       LOCK_BH(&ip_mms_lock);
7105 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
7106 +       if (between(exp->seq + ct_mms_info->len,
7107 +           ntohl(tcph->seq),
7108 +           ntohl(tcph->seq) + datalen)) {
7109 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
7110 +                       UNLOCK_BH(&ip_mms_lock);
7111 +                       return NF_DROP;
7112 +               }
7113 +       } else {
7114 +               /* Half a match?  This means a partial retransmisison.
7115 +                  It's a cracker being funky. */
7116 +               if (net_ratelimit()) {
7117 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
7118 +                              exp->seq, ct_mms_info->len,
7119 +                              ntohl(tcph->seq),
7120 +                              ntohl(tcph->seq) + datalen);
7121 +               }
7122 +               UNLOCK_BH(&ip_mms_lock);
7123 +               return NF_DROP;
7124 +       }
7125 +       UNLOCK_BH(&ip_mms_lock);
7126 +       
7127 +       return NF_ACCEPT;
7128 +}
7129 +
7130 +static struct ip_nat_helper mms[MAX_PORTS];
7131 +static char mms_names[MAX_PORTS][10];
7132 +
7133 +/* Not __exit: called from init() */
7134 +static void fini(void)
7135 +{
7136 +       int i;
7137 +
7138 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7139 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
7140 +               ip_nat_helper_unregister(&mms[i]);
7141 +       }
7142 +}
7143 +
7144 +static int __init init(void)
7145 +{
7146 +       int i, ret = 0;
7147 +       char *tmpname;
7148 +
7149 +       if (ports[0] == 0)
7150 +               ports[0] = MMS_PORT;
7151 +
7152 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
7153 +
7154 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
7155 +
7156 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
7157 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
7158 +               mms[i].mask.dst.protonum = 0xFFFF;
7159 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
7160 +               mms[i].help = mms_nat_help;
7161 +               mms[i].me = THIS_MODULE;
7162 +               mms[i].flags = 0;
7163 +               mms[i].expect = mms_nat_expected;
7164 +
7165 +               tmpname = &mms_names[i][0];
7166 +               if (ports[i] == MMS_PORT)
7167 +                       sprintf(tmpname, "mms");
7168 +               else
7169 +                       sprintf(tmpname, "mms-%d", i);
7170 +               mms[i].name = tmpname;
7171 +
7172 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
7173 +                               ports[i]);
7174 +               ret = ip_nat_helper_register(&mms[i]);
7175 +
7176 +               if (ret) {
7177 +                       printk("ip_nat_mms: error registering "
7178 +                              "helper for port %d\n", ports[i]);
7179 +                       fini();
7180 +                       return ret;
7181 +               }
7182 +               ports_c++;
7183 +       }
7184 +
7185 +       return ret;
7186 +}
7187 +
7188 +module_init(init);
7189 +module_exit(fini);
7190 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_quake3.c
7191 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c      1970-01-01 01:00:00.000000000 +0100
7192 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_quake3.c  2004-06-08 10:40:36.000000000 +0200
7193 @@ -0,0 +1,249 @@
7194 +/* Quake3 extension for UDP NAT alteration.
7195 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
7196 + * based on ip_nat_ftp.c and ip_nat_tftp.c
7197 + *
7198 + * ip_nat_quake3.c v0.0.3 2002-08-31
7199 + *
7200 + *      This program is free software; you can redistribute it and/or
7201 + *      modify it under the terms of the GNU General Public License
7202 + *      as published by the Free Software Foundation; either version
7203 + *      2 of the License, or (at your option) any later version.
7204 + *
7205 + *      Module load syntax:
7206 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
7207 + *
7208 + *      please give the ports of all Quake3 master servers You wish to
7209 + *      connect to. If you don't specify ports, the default will be UDP
7210 + *      port 27950.
7211 + *
7212 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
7213 + *
7214 + *      Notes: 
7215 + *      - If you're one of those people who would try anything to lower
7216 + *        latency while playing Quake (and who isn't :-) ), you may want to
7217 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
7218 + *        outgoing UDP traffic.
7219 + *        This will make ip_conntrack_quake3 add the necessary expectations,
7220 + *        but there will be no overhead for client->server UDP streams. If
7221 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
7222 + *        hook for every packet in the client->server UDP stream.
7223 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
7224 + *        The IP addresses in the master connection payload (=IP addresses
7225 + *        of Quake servers) have no relation with the master server so
7226 + *        DNAT'ing the master connection to a server should not change the
7227 + *        expected connections.
7228 + *      - Not tested due to lack of equipment:
7229 + *        - multiple Quake3 clients behind one MASQUERADE gateway
7230 + *        - what if Quake3 client is running on router too
7231 + */
7232 +
7233 +#include <linux/module.h>
7234 +#include <linux/netfilter_ipv4.h>
7235 +#include <linux/ip.h>
7236 +#include <linux/udp.h>
7237 +
7238 +#include <linux/netfilter.h>
7239 +#include <linux/netfilter_ipv4/ip_tables.h>
7240 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7241 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
7242 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7243 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7244 +
7245 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
7246 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
7247 +MODULE_LICENSE("GPL");
7248 +
7249 +#define MAX_PORTS 8
7250 +
7251 +static int ports[MAX_PORTS];
7252 +static int ports_c = 0;
7253 +#ifdef MODULE_PARM
7254 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
7255 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
7256 +#endif
7257 +
7258 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
7259 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
7260 +#if 0 
7261 +#define DEBUGP printk
7262 +#else
7263 +#define DEBUGP(format, args...)
7264 +#endif
7265 +
7266 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
7267 +
7268 +static unsigned int 
7269 +quake3_nat_help(struct ip_conntrack *ct,
7270 +                struct ip_conntrack_expect *exp,
7271 +                struct ip_nat_info *info,
7272 +                enum ip_conntrack_info ctinfo,
7273 +                unsigned int hooknum,
7274 +                struct sk_buff **pskb)
7275 +{
7276 +       struct iphdr *iph = (*pskb)->nh.iph;
7277 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7278 +       struct ip_conntrack_tuple repl;
7279 +       int dir = CTINFO2DIR(ctinfo);
7280 +       int i;
7281 +       
7282 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
7283 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7284 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7285 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7286 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
7287 +             );
7288 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7289 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
7290 +       
7291 +       /* Only mangle things once: original direction in POST_ROUTING
7292 +          and reply direction on PRE_ROUTING. */
7293 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7294 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7295 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
7296 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7297 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7298 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7299 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
7300 +               return NF_ACCEPT;
7301 +       }
7302 +
7303 +       if (!exp) {
7304 +               DEBUGP("no conntrack expectation to modify\n");
7305 +               return NF_ACCEPT;
7306 +       }
7307 +
7308 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
7309 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
7310 +                   i+6 < ntohs(udph->len);
7311 +                   i+=7) {
7312 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
7313 +                              i, ntohs(udph->len),
7314 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
7315 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
7316 +                       
7317 +                       memset(&repl, 0, sizeof(repl));
7318 +
7319 +                       repl.dst.protonum = IPPROTO_UDP;
7320 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7321 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
7322 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
7323 +                       
7324 +                       ip_conntrack_change_expect(exp, &repl);
7325 +               }
7326 +       }
7327 +       return NF_ACCEPT;
7328 +}
7329 +
7330 +static unsigned int 
7331 +quake3_nat_expected(struct sk_buff **pskb,
7332 +                    unsigned int hooknum,
7333 +                    struct ip_conntrack *ct, 
7334 +                    struct ip_nat_info *info) 
7335 +{
7336 +       const struct ip_conntrack *master = ct->master->expectant;
7337 +       struct ip_nat_multi_range mr;
7338 +       u_int32_t newsrcip, newdstip, newip;
7339 +#if 0 
7340 +       const struct ip_conntrack_tuple *repl =
7341 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
7342 +       struct iphdr *iph = (*pskb)->nh.iph;
7343 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
7344 +#endif
7345 +
7346 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
7347 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7348 +
7349 +       IP_NF_ASSERT(info);
7350 +       IP_NF_ASSERT(master);
7351 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7352 +       
7353 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7354 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7355 +       
7356 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
7357 +               newip = newsrcip;
7358 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7359 +                      "newsrc: %u.%u.%u.%u\n",
7360 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7361 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7362 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7363 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7364 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7365 +                      NIPQUAD(newip));
7366 +               
7367 +       } else {
7368 +               newip = newdstip;
7369 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
7370 +                      "newdst: %u.%u.%u.%u\n",
7371 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7372 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7373 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
7374 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
7375 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
7376 +                      NIPQUAD(newip));
7377 +       }
7378 +       
7379 +       mr.rangesize = 1;
7380 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7381 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
7382 +
7383 +       return ip_nat_setup_info(ct,&mr,hooknum);
7384 +}
7385 +
7386 +static struct ip_nat_helper quake3[MAX_PORTS];
7387 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
7388 +
7389 +static void fini(void)
7390 +{
7391 +       int i;
7392 +       
7393 +       for (i = 0 ; i < ports_c; i++) {
7394 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
7395 +                      ip_nat_helper_unregister(&quake3[i]);
7396 +       }
7397 +}
7398 +
7399 +static int __init init(void)
7400 +       {
7401 +               int i, ret = 0;
7402 +               char *tmpname;
7403 +
7404 +               if (!ports[0])
7405 +                       ports[0] = QUAKE3_MASTER_PORT;
7406 +               
7407 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
7408 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
7409 +
7410 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
7411 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
7412 +                       quake3[i].mask.dst.protonum = 0xFFFF;
7413 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
7414 +                       quake3[i].help = quake3_nat_help;
7415 +                       quake3[i].flags = 0;
7416 +                       quake3[i].me = THIS_MODULE;
7417 +                       quake3[i].expect = quake3_nat_expected;
7418 +                       
7419 +                       tmpname = &quake3_names[i][0];
7420 +                       if (ports[i] == QUAKE3_MASTER_PORT)
7421 +                               sprintf(tmpname, "quake3");
7422 +                       else
7423 +                               sprintf(tmpname, "quake3-%d", i);
7424 +                       quake3[i].name = tmpname;
7425 +                       
7426 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
7427 +                              ports[i], quake3[i].name);
7428 +                       ret = ip_nat_helper_register(&quake3[i]);
7429 +                       
7430 +                       if (ret) {
7431 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
7432 +                                      ports[i]);
7433 +                               fini();
7434 +                               return ret;
7435 +                       }
7436 +                       ports_c++;
7437 +               }
7438 +               return ret;
7439 +       }
7440 +       
7441 +module_init(init);
7442 +module_exit(fini);
7443 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
7444 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c        1970-01-01 01:00:00.000000000 +0100
7445 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rtsp.c    2004-06-08 10:40:46.000000000 +0200
7446 @@ -0,0 +1,621 @@
7447 +/*
7448 + * RTSP extension for TCP NAT alteration
7449 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
7450 + * based on ip_nat_irc.c
7451 + *
7452 + *      This program is free software; you can redistribute it and/or
7453 + *      modify it under the terms of the GNU General Public License
7454 + *      as published by the Free Software Foundation; either version
7455 + *      2 of the License, or (at your option) any later version.
7456 + *
7457 + * Module load syntax:
7458 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
7459 + *                           stunaddr=<address>
7460 + *                           destaction=[auto|strip|none]
7461 + *
7462 + * If no ports are specified, the default will be port 554 only.
7463 + *
7464 + * stunaddr specifies the address used to detect that a client is using STUN.
7465 + * If this address is seen in the destination parameter, it is assumed that
7466 + * the client has already punched a UDP hole in the firewall, so we don't
7467 + * mangle the client_port.  If none is specified, it is autodetected.  It
7468 + * only needs to be set if you have multiple levels of NAT.  It should be
7469 + * set to the external address that the STUN clients detect.  Note that in
7470 + * this case, it will not be possible for clients to use UDP with servers
7471 + * between the NATs.
7472 + *
7473 + * If no destaction is specified, auto is used.
7474 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
7475 + *   destaction=strip: always strip destination parameter (not recommended).
7476 + *   destaction=none:  do not touch destination parameter (not recommended).
7477 + */
7478 +
7479 +#include <linux/module.h>
7480 +#include <linux/netfilter_ipv4.h>
7481 +#include <linux/ip.h>
7482 +#include <linux/tcp.h>
7483 +#include <linux/kernel.h>
7484 +#include <net/tcp.h>
7485 +#include <linux/netfilter_ipv4/ip_nat.h>
7486 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7487 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7488 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
7489 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7490 +
7491 +#include <linux/inet.h>
7492 +#include <linux/ctype.h>
7493 +#define NF_NEED_STRNCASECMP
7494 +#define NF_NEED_STRTOU16
7495 +#include <linux/netfilter_helpers.h>
7496 +#define NF_NEED_MIME_NEXTLINE
7497 +#include <linux/netfilter_mime.h>
7498 +
7499 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7500 +#ifdef IP_NF_RTSP_DEBUG
7501 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args)
7502 +#else
7503 +#define DEBUGP(fmt, args...)
7504 +#endif
7505 +
7506 +#define MAX_PORTS       8
7507 +#define DSTACT_AUTO     0
7508 +#define DSTACT_STRIP    1
7509 +#define DSTACT_NONE     2
7510 +
7511 +static int      ports[MAX_PORTS];
7512 +static char*    stunaddr = NULL;
7513 +static char*    destaction = NULL;
7514 +
7515 +static int       num_ports = 0;
7516 +static u_int32_t extip = 0;
7517 +static int       dstact = 0;
7518 +
7519 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7520 +MODULE_DESCRIPTION("RTSP network address translation module");
7521 +MODULE_LICENSE("GPL");
7522 +#ifdef MODULE_PARM
7523 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7524 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7525 +MODULE_PARM(stunaddr, "s");
7526 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7527 +MODULE_PARM(destaction, "s");
7528 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7529 +#endif
7530 +
7531 +/* protects rtsp part of conntracks */
7532 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7533 +
7534 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7535 +
7536 +/*** helper functions ***/
7537 +
7538 +static void
7539 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7540 +{
7541 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
7542 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7543 +
7544 +    *pptcpdata = (char*)tcph + tcph->doff*4;
7545 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7546 +}
7547 +
7548 +/*** nat functions ***/
7549 +
7550 +/*
7551 + * Mangle the "Transport:" header:
7552 + *   - Replace all occurences of "client_port=<spec>"
7553 + *   - Handle destination parameter
7554 + *
7555 + * In:
7556 + *   ct, ctinfo = conntrack context
7557 + *   pskb       = packet
7558 + *   tranoff    = Transport header offset from TCP data
7559 + *   tranlen    = Transport header length (incl. CRLF)
7560 + *   rport_lo   = replacement low  port (host endian)
7561 + *   rport_hi   = replacement high port (host endian)
7562 + *
7563 + * Returns packet size difference.
7564 + *
7565 + * Assumes that a complete transport header is present, ending with CR or LF
7566 + */
7567 +static int
7568 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7569 +                 struct ip_conntrack_expect* exp,
7570 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
7571 +{
7572 +    char*       ptcp;
7573 +    uint        tcplen;
7574 +    char*       ptran;
7575 +    char        rbuf1[16];      /* Replacement buffer (one port) */
7576 +    uint        rbuf1len;       /* Replacement len (one port) */
7577 +    char        rbufa[16];      /* Replacement buffer (all ports) */
7578 +    uint        rbufalen;       /* Replacement len (all ports) */
7579 +    u_int32_t   newip;
7580 +    u_int16_t   loport, hiport;
7581 +    uint        off = 0;
7582 +    uint        diff;           /* Number of bytes we removed */
7583 +
7584 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7585 +    struct ip_conntrack_tuple t;
7586 +
7587 +    char    szextaddr[15+1];
7588 +    uint    extaddrlen;
7589 +    int     is_stun;
7590 +
7591 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7592 +    ptran = ptcp+tranoff;
7593 +
7594 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7595 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7596 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
7597 +    {
7598 +        INFOP("sanity check failed\n");
7599 +        return 0;
7600 +    }
7601 +    off += 10;
7602 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7603 +
7604 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7605 +    t = exp->tuple;
7606 +    t.dst.ip = newip;
7607 +
7608 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7609 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7610 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7611 +
7612 +    rbuf1len = rbufalen = 0;
7613 +    switch (prtspexp->pbtype)
7614 +    {
7615 +    case pb_single:
7616 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7617 +        {
7618 +            t.dst.u.udp.port = htons(loport);
7619 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7620 +            {
7621 +                DEBUGP("using port %hu\n", loport);
7622 +                break;
7623 +            }
7624 +        }
7625 +        if (loport != 0)
7626 +        {
7627 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7628 +            rbufalen = sprintf(rbufa, "%hu", loport);
7629 +        }
7630 +        break;
7631 +    case pb_range:
7632 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7633 +        {
7634 +            t.dst.u.udp.port = htons(loport);
7635 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7636 +            {
7637 +                hiport = loport + ~exp->mask.dst.u.udp.port;
7638 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
7639 +                break;
7640 +            }
7641 +        }
7642 +        if (loport != 0)
7643 +        {
7644 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7645 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7646 +        }
7647 +        break;
7648 +    case pb_discon:
7649 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7650 +        {
7651 +            t.dst.u.udp.port = htons(loport);
7652 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7653 +            {
7654 +                DEBUGP("using port %hu (1 of 2)\n", loport);
7655 +                break;
7656 +            }
7657 +        }
7658 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7659 +        {
7660 +            t.dst.u.udp.port = htons(hiport);
7661 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7662 +            {
7663 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
7664 +                break;
7665 +            }
7666 +        }
7667 +        if (loport != 0 && hiport != 0)
7668 +        {
7669 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7670 +            if (hiport == loport+1)
7671 +            {
7672 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7673 +            }
7674 +            else
7675 +            {
7676 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7677 +            }
7678 +        }
7679 +        break;
7680 +    }
7681 +
7682 +    if (rbuf1len == 0)
7683 +    {
7684 +        return 0;   /* cannot get replacement port(s) */
7685 +    }
7686 +
7687 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
7688 +    while (off < tranlen)
7689 +    {
7690 +        uint        saveoff;
7691 +        const char* pparamend;
7692 +        uint        nextparamoff;
7693 +
7694 +        pparamend = memchr(ptran+off, ',', tranlen-off);
7695 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7696 +        nextparamoff = pparamend-ptcp;
7697 +
7698 +        /*
7699 +         * We pass over each param twice.  On the first pass, we look for a
7700 +         * destination= field.  It is handled by the security policy.  If it
7701 +         * is present, allowed, and equal to our external address, we assume
7702 +         * that STUN is being used and we leave the client_port= field alone.
7703 +         */
7704 +        is_stun = 0;
7705 +        saveoff = off;
7706 +        while (off < nextparamoff)
7707 +        {
7708 +            const char* pfieldend;
7709 +            uint        nextfieldoff;
7710 +
7711 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7712 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7713 +
7714 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7715 +            {
7716 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7717 +                {
7718 +                    is_stun = 1;
7719 +                }
7720 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7721 +                {
7722 +                    diff = nextfieldoff-off;
7723 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7724 +                                                         off, diff, NULL, 0))
7725 +                    {
7726 +                        /* mangle failed, all we can do is bail */
7727 +                        return 0;
7728 +                    }
7729 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7730 +                    ptran = ptcp+tranoff;
7731 +                    tranlen -= diff;
7732 +                    nextparamoff -= diff;
7733 +                    nextfieldoff -= diff;
7734 +                }
7735 +            }
7736 +
7737 +            off = nextfieldoff;
7738 +        }
7739 +        if (is_stun)
7740 +        {
7741 +            continue;
7742 +        }
7743 +        off = saveoff;
7744 +        while (off < nextparamoff)
7745 +        {
7746 +            const char* pfieldend;
7747 +            uint        nextfieldoff;
7748 +
7749 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7750 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7751 +
7752 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
7753 +            {
7754 +                u_int16_t   port;
7755 +                uint        numlen;
7756 +                uint        origoff;
7757 +                uint        origlen;
7758 +                char*       rbuf    = rbuf1;
7759 +                uint        rbuflen = rbuf1len;
7760 +
7761 +                off += 12;
7762 +                origoff = (ptran-ptcp)+off;
7763 +                origlen = 0;
7764 +                numlen = nf_strtou16(ptran+off, &port);
7765 +                off += numlen;
7766 +                origlen += numlen;
7767 +                if (port != prtspexp->loport)
7768 +                {
7769 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
7770 +                }
7771 +                else
7772 +                {
7773 +                    if (ptran[off] == '-' || ptran[off] == '/')
7774 +                    {
7775 +                        off++;
7776 +                        origlen++;
7777 +                        numlen = nf_strtou16(ptran+off, &port);
7778 +                        off += numlen;
7779 +                        origlen += numlen;
7780 +                        rbuf = rbufa;
7781 +                        rbuflen = rbufalen;
7782 +                    }
7783 +
7784 +                    /*
7785 +                     * note we cannot just memcpy() if the sizes are the same.
7786 +                     * the mangle function does skb resizing, checks for a
7787 +                     * cloned skb, and updates the checksums.
7788 +                     *
7789 +                     * parameter 4 below is offset from start of tcp data.
7790 +                     */
7791 +                    diff = origlen-rbuflen;
7792 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7793 +                                              origoff, origlen, rbuf, rbuflen))
7794 +                    {
7795 +                        /* mangle failed, all we can do is bail */
7796 +                        return 0;
7797 +                    }
7798 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7799 +                    ptran = ptcp+tranoff;
7800 +                    tranlen -= diff;
7801 +                    nextparamoff -= diff;
7802 +                    nextfieldoff -= diff;
7803 +                }
7804 +            }
7805 +
7806 +            off = nextfieldoff;
7807 +        }
7808 +
7809 +        off = nextparamoff;
7810 +    }
7811 +
7812 +    return 1;
7813 +}
7814 +
7815 +static unsigned int
7816 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7817 +{
7818 +    struct ip_nat_multi_range mr;
7819 +    u_int32_t newdstip, newsrcip, newip;
7820 +
7821 +    struct ip_conntrack *master = master_ct(ct);
7822 +
7823 +    IP_NF_ASSERT(info);
7824 +    IP_NF_ASSERT(master);
7825 +
7826 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7827 +
7828 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7829 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7830 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7831 +
7832 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7833 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7834 +
7835 +    mr.rangesize = 1;
7836 +    /* We don't want to manip the per-protocol, just the IPs. */
7837 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7838 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
7839 +
7840 +    return ip_nat_setup_info(ct, &mr, hooknum);
7841 +}
7842 +
7843 +static uint
7844 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7845 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7846 +{
7847 +    char*   ptcp;
7848 +    uint    tcplen;
7849 +    uint    hdrsoff;
7850 +    uint    hdrslen;
7851 +    uint    lineoff;
7852 +    uint    linelen;
7853 +    uint    off;
7854 +
7855 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7856 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7857 +
7858 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7859 +
7860 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7861 +
7862 +    hdrsoff = exp->seq - ntohl(tcph->seq);
7863 +    hdrslen = prtspexp->len;
7864 +    off = hdrsoff;
7865 +
7866 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7867 +    {
7868 +        if (linelen == 0)
7869 +        {
7870 +            break;
7871 +        }
7872 +        if (off > hdrsoff+hdrslen)
7873 +        {
7874 +            INFOP("!! overrun !!");
7875 +            break;
7876 +        }
7877 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7878 +
7879 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7880 +        {
7881 +            uint oldtcplen = tcplen;
7882 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7883 +            {
7884 +                break;
7885 +            }
7886 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7887 +            hdrslen -= (oldtcplen-tcplen);
7888 +            off -= (oldtcplen-tcplen);
7889 +            lineoff -= (oldtcplen-tcplen);
7890 +            linelen -= (oldtcplen-tcplen);
7891 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7892 +        }
7893 +    }
7894 +
7895 +    return NF_ACCEPT;
7896 +}
7897 +
7898 +static uint
7899 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7900 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7901 +{
7902 +    /* XXX: unmangle */
7903 +    return NF_ACCEPT;
7904 +}
7905 +
7906 +static uint
7907 +help(struct ip_conntrack* ct,
7908 +     struct ip_conntrack_expect* exp,
7909 +     struct ip_nat_info* info,
7910 +     enum ip_conntrack_info ctinfo,
7911 +     unsigned int hooknum,
7912 +     struct sk_buff** pskb)
7913 +{
7914 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
7915 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7916 +    uint datalen;
7917 +    int dir;
7918 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
7919 +    int rc = NF_ACCEPT;
7920 +
7921 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7922 +    {
7923 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7924 +        return NF_ACCEPT;
7925 +    }
7926 +
7927 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
7928 +
7929 +    /*
7930 +     * Only mangle things once: original direction in POST_ROUTING
7931 +     * and reply direction on PRE_ROUTING.
7932 +     */
7933 +    dir = CTINFO2DIR(ctinfo);
7934 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7935 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7936 +    {
7937 +        DEBUGP("Not touching dir %s at hook %s\n",
7938 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7939 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7940 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7941 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7942 +        return NF_ACCEPT;
7943 +    }
7944 +    DEBUGP("got beyond not touching\n");
7945 +
7946 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7947 +
7948 +    LOCK_BH(&ip_rtsp_lock);
7949 +    /* Ensure the packet contains all of the marked data */
7950 +    if (!between(exp->seq + ct_rtsp_info->len,
7951 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7952 +    {
7953 +        /* Partial retransmission?  Probably a hacker. */
7954 +        if (net_ratelimit())
7955 +        {
7956 +            INFOP("partial packet %u/%u in %u/%u\n",
7957 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7958 +        }
7959 +        UNLOCK_BH(&ip_rtsp_lock);
7960 +        return NF_DROP;
7961 +    }
7962 +
7963 +    switch (dir)
7964 +    {
7965 +    case IP_CT_DIR_ORIGINAL:
7966 +        rc = help_out(ct, ctinfo, exp, pskb);
7967 +        break;
7968 +    case IP_CT_DIR_REPLY:
7969 +        rc = help_in(ct, ctinfo, exp, pskb);
7970 +        break;
7971 +    }
7972 +    UNLOCK_BH(&ip_rtsp_lock);
7973 +
7974 +    return rc;
7975 +}
7976 +
7977 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7978 +static char rtsp_names[MAX_PORTS][10];
7979 +
7980 +/* This function is intentionally _NOT_ defined as  __exit */
7981 +static void
7982 +fini(void)
7983 +{
7984 +    int i;
7985 +
7986 +    for (i = 0; i < num_ports; i++)
7987 +    {
7988 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
7989 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7990 +    }
7991 +}
7992 +
7993 +static int __init
7994 +init(void)
7995 +{
7996 +    int ret = 0;
7997 +    int i;
7998 +    struct ip_nat_helper* hlpr;
7999 +    char* tmpname;
8000 +
8001 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
8002 +
8003 +    if (ports[0] == 0)
8004 +    {
8005 +        ports[0] = RTSP_PORT;
8006 +    }
8007 +
8008 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
8009 +    {
8010 +        hlpr = &ip_nat_rtsp_helpers[i];
8011 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
8012 +
8013 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
8014 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
8015 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
8016 +        hlpr->mask.dst.protonum = 0xFFFF;
8017 +        hlpr->help = help;
8018 +        hlpr->flags = 0;
8019 +        hlpr->me = THIS_MODULE;
8020 +        hlpr->expect = expected;
8021 +
8022 +        tmpname = &rtsp_names[i][0];
8023 +        if (ports[i] == RTSP_PORT)
8024 +        {
8025 +                sprintf(tmpname, "rtsp");
8026 +        }
8027 +        else
8028 +        {
8029 +                sprintf(tmpname, "rtsp-%d", i);
8030 +        }
8031 +        hlpr->name = tmpname;
8032 +
8033 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
8034 +        ret = ip_nat_helper_register(hlpr);
8035 +
8036 +        if (ret)
8037 +        {
8038 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
8039 +            fini();
8040 +            return 1;
8041 +        }
8042 +        num_ports++;
8043 +    }
8044 +    if (stunaddr != NULL)
8045 +    {
8046 +        extip = in_aton(stunaddr);
8047 +    }
8048 +    if (destaction != NULL)
8049 +    {
8050 +        if (strcmp(destaction, "auto") == 0)
8051 +        {
8052 +            dstact = DSTACT_AUTO;
8053 +        }
8054 +        if (strcmp(destaction, "strip") == 0)
8055 +        {
8056 +            dstact = DSTACT_STRIP;
8057 +        }
8058 +        if (strcmp(destaction, "none") == 0)
8059 +        {
8060 +            dstact = DSTACT_NONE;
8061 +        }
8062 +    }
8063 +    return ret;
8064 +}
8065 +
8066 +module_init(init);
8067 +module_exit(fini);
8068 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rule.c
8069 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_rule.c        2004-06-07 21:14:10.000000000 +0200
8070 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_rule.c    2004-06-08 10:37:30.000000000 +0200
8071 @@ -75,7 +75,7 @@
8072                 0,
8073                 sizeof(struct ipt_entry),
8074                 sizeof(struct ipt_standard),
8075 -               0, { 0, 0 }, { } },
8076 +               0, NULL, 0, { 0, 0 }, { } },
8077               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
8078                 -NF_ACCEPT - 1 } },
8079             /* POST_ROUTING */
8080 @@ -83,7 +83,7 @@
8081                 0,
8082                 sizeof(struct ipt_entry),
8083                 sizeof(struct ipt_standard),
8084 -               0, { 0, 0 }, { } },
8085 +               0, NULL, 0, { 0, 0 }, { } },
8086               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
8087                 -NF_ACCEPT - 1 } },
8088             /* LOCAL_OUT */
8089 @@ -91,7 +91,7 @@
8090                 0,
8091                 sizeof(struct ipt_entry),
8092                 sizeof(struct ipt_standard),
8093 -               0, { 0, 0 }, { } },
8094 +               0, NULL, 0, { 0, 0 }, { } },
8095               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
8096                 -NF_ACCEPT - 1 } }
8097      },
8098 @@ -100,7 +100,7 @@
8099         0,
8100         sizeof(struct ipt_entry),
8101         sizeof(struct ipt_error),
8102 -       0, { 0, 0 }, { } },
8103 +       0, NULL, 0, { 0, 0 }, { } },
8104        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
8105           { } },
8106         "ERROR"
8107 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_standalone.c
8108 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c  2004-06-07 21:14:56.000000000 +0200
8109 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_standalone.c      2004-06-08 10:38:45.000000000 +0200
8110 @@ -176,6 +176,45 @@
8111         return do_bindings(ct, ctinfo, info, hooknum, pskb);
8112  }
8113  
8114 +struct nat_route_key
8115 +{
8116 +       u_int32_t addr;
8117 +#ifdef CONFIG_XFRM
8118 +       u_int16_t port;
8119 +#endif
8120 +};
8121 +
8122 +static inline void
8123 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
8124 +{
8125 +       struct iphdr *iph = skb->nh.iph;
8126 +
8127 +       key->addr = which ? iph->daddr : iph->saddr;
8128 +#ifdef CONFIG_XFRM
8129 +       key->port = 0;
8130 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8131 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8132 +               key->port = ports[which];
8133 +       }
8134 +#endif
8135 +}
8136 +
8137 +static inline int
8138 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
8139 +{
8140 +       struct iphdr *iph = skb->nh.iph;
8141 +
8142 +       if (key->addr != (which ? iph->daddr : iph->saddr))
8143 +               return 1;
8144 +#ifdef CONFIG_XFRM
8145 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
8146 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
8147 +               if (key->port != ports[which])
8148 +                       return 1;
8149 +       }
8150 +#endif
8151 +}
8152 +
8153  static unsigned int
8154  ip_nat_out(unsigned int hooknum,
8155            struct sk_buff **pskb,
8156 @@ -183,6 +222,9 @@
8157            const struct net_device *out,
8158            int (*okfn)(struct sk_buff *))
8159  {
8160 +       struct nat_route_key key;
8161 +       unsigned int ret;
8162 +
8163         /* root is playing with raw sockets. */
8164         if ((*pskb)->len < sizeof(struct iphdr)
8165             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8166 @@ -205,7 +247,29 @@
8167                         return NF_STOLEN;
8168         }
8169  
8170 -       return ip_nat_fn(hooknum, pskb, in, out, okfn);
8171 +       nat_route_key_get(*pskb, &key, 0);
8172 +       ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8173 +
8174 +       if (ret != NF_DROP && ret != NF_STOLEN
8175 +           && nat_route_key_compare(*pskb, &key, 0)) {
8176 +               if (ip_route_me_harder(pskb) != 0)
8177 +                       ret = NF_DROP;
8178 +#ifdef CONFIG_XFRM
8179 +               /*
8180 +                * POST_ROUTING hook is called with fixed outfn, we need
8181 +                * to manually confirm the packet and direct it to the
8182 +                * transformers if a policy matches.
8183 +                */
8184 +               else if ((*pskb)->dst->xfrm != NULL) {
8185 +                       ret = ip_conntrack_confirm(*pskb);
8186 +                       if (ret != NF_DROP) {
8187 +                               dst_output(*pskb);
8188 +                               ret = NF_STOLEN;
8189 +                       }
8190 +               }
8191 +#endif
8192 +       }
8193 +       return ret;
8194  }
8195  
8196  #ifdef CONFIG_IP_NF_NAT_LOCAL
8197 @@ -216,7 +280,7 @@
8198                 const struct net_device *out,
8199                 int (*okfn)(struct sk_buff *))
8200  {
8201 -       u_int32_t saddr, daddr;
8202 +       struct nat_route_key key;
8203         unsigned int ret;
8204  
8205         /* root is playing with raw sockets. */
8206 @@ -224,14 +288,14 @@
8207             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
8208                 return NF_ACCEPT;
8209  
8210 -       saddr = (*pskb)->nh.iph->saddr;
8211 -       daddr = (*pskb)->nh.iph->daddr;
8212 -
8213 +       nat_route_key_get(*pskb, &key, 1);
8214         ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
8215 +
8216         if (ret != NF_DROP && ret != NF_STOLEN
8217 -           && ((*pskb)->nh.iph->saddr != saddr
8218 -               || (*pskb)->nh.iph->daddr != daddr))
8219 -               return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
8220 +           && nat_route_key_compare(*pskb, &key, 1)) {
8221 +               if (ip_route_me_harder(pskb) != 0)
8222 +                       ret = NF_DROP;
8223 +       }
8224         return ret;
8225  }
8226  #endif
8227 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_talk.c
8228 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_nat_talk.c        1970-01-01 01:00:00.000000000 +0100
8229 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_nat_talk.c    2004-06-08 10:41:27.000000000 +0200
8230 @@ -0,0 +1,473 @@
8231 +/* 
8232 + * talk extension for UDP NAT alteration. 
8233 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8234 + *
8235 + *      This program is free software; you can redistribute it and/or
8236 + *      modify it under the terms of the GNU General Public License
8237 + *      as published by the Free Software Foundation; either version
8238 + *      2 of the License, or (at your option) any later version.
8239 + **
8240 + *     Module load syntax:
8241 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
8242 + *
8243 + *             talk=[0|1]      disable|enable old talk support
8244 + *            ntalk=[0|1]      disable|enable ntalk support
8245 + *           ntalk2=[0|1]      disable|enable ntalk2 support
8246 + *
8247 + *     The default is talk=1 ntalk=1 ntalk2=1
8248 + *
8249 + *  
8250 + */
8251 +#include <linux/module.h>
8252 +#include <linux/netfilter_ipv4.h>
8253 +#include <linux/ip.h>
8254 +#include <linux/udp.h>
8255 +#include <linux/kernel.h>
8256 +#include <net/tcp.h>
8257 +#include <net/udp.h>
8258 +
8259 +#include <linux/netfilter_ipv4/ip_nat.h>
8260 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
8261 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
8262 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
8263 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8264 +
8265 +/* Default all talk protocols are supported */
8266 +static int talk   = 1;
8267 +static int ntalk  = 1;
8268 +static int ntalk2 = 1;
8269 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
8270 +MODULE_DESCRIPTION("talk network address translation module");
8271 +#ifdef MODULE_PARM
8272 +MODULE_PARM(talk, "i");
8273 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
8274 +MODULE_PARM(ntalk, "i");
8275 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
8276 +MODULE_PARM(ntalk2, "i");
8277 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
8278 +#endif
8279 +
8280 +#if 0
8281 +#define DEBUGP printk
8282 +#define IP_NAT_TALK_DEBUG
8283 +#else
8284 +#define DEBUGP(format, args...)
8285 +#endif
8286 +
8287 +/* FIXME: Time out? --RR */
8288 +
8289 +static int
8290 +mangle_packet(struct sk_buff **pskb,
8291 +             struct ip_conntrack *ct,
8292 +             u_int32_t newip,
8293 +             u_int16_t port,
8294 +             struct talk_addr *addr,
8295 +             struct talk_addr *ctl_addr)
8296 +{
8297 +       struct iphdr *iph = (*pskb)->nh.iph;
8298 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8299 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
8300 +
8301 +       /* Fortunately talk sends a structure with the address and
8302 +          port in it. The size of the packet won't change. */
8303 +
8304 +       if (ctl_addr == NULL) {
8305 +               /* response */
8306 +               if (addr->ta_addr == INADDR_ANY)
8307 +                       return 1;
8308 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8309 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8310 +                      NIPQUAD(newip), ntohs(port));
8311 +               addr->ta_addr = newip;
8312 +               addr->ta_port = port;
8313 +       } else {
8314 +               /* message */
8315 +               if (addr->ta_addr != INADDR_ANY) {
8316 +                       /* Change address inside packet to match way we're mapping
8317 +                          this connection. */
8318 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8319 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8320 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
8321 +                              ntohs(addr->ta_port));
8322 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8323 +               }
8324 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
8325 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8326 +                      NIPQUAD(newip), ntohs(port));
8327 +               ctl_addr->ta_addr = newip;
8328 +               ctl_addr->ta_port = port;
8329 +       }
8330 +
8331 +       /* Fix checksums */
8332 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
8333 +       udph->check = 0;
8334 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
8335 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
8336 +               
8337 +       ip_send_check(iph);
8338 +       return 1;
8339 +}
8340 +
8341 +static int talk_help_msg(struct ip_conntrack *ct,
8342 +                        struct sk_buff **pskb,
8343 +                        u_char type,
8344 +                        struct talk_addr *addr,
8345 +                        struct talk_addr *ctl_addr)
8346 +{
8347 +       u_int32_t newip;
8348 +       u_int16_t port;
8349 +       
8350 +       unsigned int verdict = NF_ACCEPT;
8351 +
8352 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
8353 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8354 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
8355 +               type);
8356 +
8357 +       /* Change address inside packet to match way we're mapping
8358 +          this connection. */
8359 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8360 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
8361 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
8362 +               NIPQUAD(newip), ntohs(port));
8363 +
8364 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
8365 +               verdict = NF_DROP;
8366 +
8367 +       return verdict;
8368 +}
8369 +
8370 +static int talk_help_response(struct ip_conntrack *ct,
8371 +                             struct ip_conntrack_expect *exp,
8372 +                             struct sk_buff **pskb,
8373 +                             u_char type,
8374 +                             u_char answer,
8375 +                             struct talk_addr *addr)
8376 +{
8377 +       u_int32_t newip;
8378 +       u_int16_t port;
8379 +       struct ip_conntrack_tuple t;
8380 +       struct ip_ct_talk_expect *ct_talk_info;
8381 +
8382 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
8383 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
8384 +               type, answer);
8385 +       
8386 +       LOCK_BH(&ip_talk_lock);
8387 +       ct_talk_info = &exp->help.exp_talk_info;
8388 +
8389 +       if (!(answer == SUCCESS 
8390 +             && (type == LOOK_UP || type == ANNOUNCE)
8391 +             && exp != NULL)) {
8392 +               UNLOCK_BH(&ip_talk_lock);
8393 +               return NF_ACCEPT;
8394 +       }
8395 +               
8396 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
8397 +               ntohs(ct_talk_info->port), 
8398 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
8399 +
8400 +       /* Change address inside packet to match way we're mapping
8401 +          this connection. */
8402 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
8403 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
8404 +       /* We can read expect here without conntrack lock, since it's
8405 +          only set in ip_conntrack_talk , with ip_talk_lock held
8406 +          writable */ 
8407 +       t = exp->tuple;
8408 +       t.dst.ip = newip;
8409 +
8410 +       /* Try to get same port: if not, try to change it. */
8411 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
8412 +               if (type == LOOK_UP)
8413 +                       t.dst.u.tcp.port = htons(port);
8414 +               else
8415 +                       t.dst.u.udp.port = htons(port);
8416 +
8417 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
8418 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
8419 +                       break;
8420 +               }
8421 +       }
8422 +       UNLOCK_BH(&ip_talk_lock);
8423 +
8424 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
8425 +               return NF_DROP;
8426 +       
8427 +       return NF_ACCEPT;
8428 +}
8429 +
8430 +static unsigned int talk_help(struct ip_conntrack *ct,
8431 +                             struct ip_conntrack_expect *exp,
8432 +                             struct ip_nat_info *info,
8433 +                             enum ip_conntrack_info ctinfo,
8434 +                             unsigned int hooknum,
8435 +                             struct sk_buff **pskb,
8436 +                             int talk_port)
8437 +{
8438 +       struct iphdr *iph = (*pskb)->nh.iph;
8439 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8440 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
8441 +       char *data = (char *)udph + sizeof(struct udphdr);
8442 +       int dir;
8443 +
8444 +       /* Only mangle things once: original direction in POST_ROUTING
8445 +          and reply direction on PRE_ROUTING. */
8446 +       dir = CTINFO2DIR(ctinfo);
8447 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
8448 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
8449 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
8450 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8451 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8452 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8453 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
8454 +               return NF_ACCEPT;
8455 +       }
8456 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
8457 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8458 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8459 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8460 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8461 +              NIPQUAD(iph->saddr), ntohs(udph->source),
8462 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
8463 +              talk_port);
8464 +
8465 +       /* Because conntrack does not drop packets, checking must be repeated here... */
8466 +       if (talk_port == TALK_PORT) {
8467 +               if (dir == IP_CT_DIR_ORIGINAL
8468 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
8469 +                       return talk_help_msg(ct, pskb,
8470 +                                            ((struct talk_msg *)data)->type, 
8471 +                                            &(((struct talk_msg *)data)->addr),
8472 +                                            &(((struct talk_msg *)data)->ctl_addr));
8473 +               else if (dir == IP_CT_DIR_REPLY
8474 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
8475 +                       return talk_help_response(ct, exp, pskb,
8476 +                                                 ((struct talk_response *)data)->type, 
8477 +                                                 ((struct talk_response *)data)->answer,
8478 +                                                 &(((struct talk_response *)data)->addr));
8479 +               else {  
8480 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
8481 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
8482 +                              (unsigned)udplen - sizeof(struct udphdr), 
8483 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
8484 +                       return NF_DROP;
8485 +               }
8486 +       } else {
8487 +               if (dir == IP_CT_DIR_ORIGINAL) {
8488 +                       if (ntalk
8489 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
8490 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
8491 +                               return talk_help_msg(ct, pskb,
8492 +                                                    ((struct ntalk_msg *)data)->type, 
8493 +                                                    &(((struct ntalk_msg *)data)->addr),
8494 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
8495 +                       else if (ntalk2
8496 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8497 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8498 +                                && udplen == sizeof(struct udphdr) 
8499 +                                             + sizeof(struct ntalk2_msg) 
8500 +                                             + ((struct ntalk2_msg *)data)->extended)
8501 +                               return talk_help_msg(ct, pskb,
8502 +                                                    ((struct ntalk2_msg *)data)->type, 
8503 +                                                    &(((struct ntalk2_msg *)data)->addr),
8504 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
8505 +                       else {
8506 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
8507 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8508 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8509 +                               return NF_DROP;
8510 +                       }
8511 +               } else {
8512 +                       if (ntalk
8513 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8514 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8515 +                               return talk_help_response(ct, exp, pskb,
8516 +                                                         ((struct ntalk_response *)data)->type, 
8517 +                                                         ((struct ntalk_response *)data)->answer,
8518 +                                                         &(((struct ntalk_response *)data)->addr));
8519 +                       else if (ntalk2
8520 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8521 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8522 +                               return talk_help_response(ct, exp, pskb,
8523 +                                                         ((struct ntalk2_response *)data)->type, 
8524 +                                                         ((struct ntalk2_response *)data)->answer,
8525 +                                                         &(((struct ntalk2_response *)data)->addr));
8526 +                       else {
8527 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
8528 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8529 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8530 +                               return NF_DROP;
8531 +                       }
8532 +               }
8533 +       }
8534 +}
8535 +
8536 +static unsigned int help(struct ip_conntrack *ct,
8537 +                        struct ip_conntrack_expect *exp,
8538 +                        struct ip_nat_info *info,
8539 +                        enum ip_conntrack_info ctinfo,
8540 +                        unsigned int hooknum,
8541 +                        struct sk_buff **pskb)
8542 +{
8543 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8544 +}
8545 +
8546 +static unsigned int nhelp(struct ip_conntrack *ct,
8547 +                         struct ip_conntrack_expect *exp,
8548 +                         struct ip_nat_info *info,
8549 +                         enum ip_conntrack_info ctinfo,
8550 +                         unsigned int hooknum,
8551 +                         struct sk_buff **pskb)
8552 +{
8553 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8554 +}
8555 +
8556 +static unsigned int
8557 +talk_nat_expected(struct sk_buff **pskb,
8558 +                 unsigned int hooknum,
8559 +                 struct ip_conntrack *ct,
8560 +                 struct ip_nat_info *info);
8561 +
8562 +static struct ip_nat_helper talk_helpers[2] = 
8563 +       { { { NULL, NULL },
8564 +            "talk",                                    /* name */
8565 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8566 +            THIS_MODULE,                               /* module */
8567 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8568 +              { 0, { 0 }, IPPROTO_UDP } },
8569 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8570 +              { 0, { 0 }, 0xFFFF } },
8571 +            help,                                      /* helper */
8572 +            talk_nat_expected },                       /* expectfn */
8573 +         { { NULL, NULL },
8574 +            "ntalk",                                   /* name */
8575 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8576 +            THIS_MODULE,                                       /* module */
8577 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8578 +              { 0, { 0 }, IPPROTO_UDP } },
8579 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8580 +              { 0, { 0 }, 0xFFFF } },
8581 +            nhelp,                                     /* helper */
8582 +            talk_nat_expected }                                /* expectfn */
8583 +       };
8584 +          
8585 +static unsigned int
8586 +talk_nat_expected(struct sk_buff **pskb,
8587 +                 unsigned int hooknum,
8588 +                 struct ip_conntrack *ct,
8589 +                 struct ip_nat_info *info)
8590 +{
8591 +       struct ip_nat_multi_range mr;
8592 +       u_int32_t newdstip, newsrcip, newip;
8593 +       u_int16_t port;
8594 +       unsigned int ret;
8595 +       
8596 +       struct ip_conntrack *master = master_ct(ct);
8597 +
8598 +       IP_NF_ASSERT(info);
8599 +       IP_NF_ASSERT(master);
8600 +
8601 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8602 +
8603 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8604 +
8605 +       LOCK_BH(&ip_talk_lock);
8606 +       port = ct->master->help.exp_talk_info.port;
8607 +       UNLOCK_BH(&ip_talk_lock);
8608 +
8609 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8610 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8611 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8612 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8613 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8614 +              ct, master);
8615 +
8616 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8617 +               /* Callee client -> caller server */
8618 +#ifdef IP_NAT_TALK_DEBUG
8619 +               struct iphdr *iph = (*pskb)->nh.iph;
8620 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
8621 +
8622 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8623 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
8624 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
8625 +#endif
8626 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8627 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8628 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8629 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8630 +       } else {
8631 +               /* Callee client -> caller client */
8632 +#ifdef IP_NAT_TALK_DEBUG
8633 +               struct iphdr *iph = (*pskb)->nh.iph;
8634 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8635 +
8636 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8637 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
8638 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
8639 +#endif
8640 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8641 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8642 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8643 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8644 +       }
8645 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8646 +               newip = newsrcip;
8647 +       else
8648 +               newip = newdstip;
8649 +
8650 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8651 +
8652 +       mr.rangesize = 1;
8653 +       /* We don't want to manip the per-protocol, just the IPs... */
8654 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8655 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8656 +       
8657 +       /* ... unless we're doing a MANIP_DST, in which case, make
8658 +          sure we map to the correct port */
8659 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8660 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8661 +               mr.range[0].min = mr.range[0].max
8662 +                       = ((union ip_conntrack_manip_proto)
8663 +                               { .udp = { port } });
8664 +       }
8665 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
8666 +
8667 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8668 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8669 +               /* NAT expectfn called with ip_nat_lock write-locked */
8670 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
8671 +       }
8672 +       return ret;
8673 +}
8674 +
8675 +static int __init init(void)
8676 +{
8677 +       int ret = 0;
8678 +
8679 +       if (talk > 0) {
8680 +               ret = ip_nat_helper_register(&talk_helpers[0]);
8681 +
8682 +               if (ret != 0)
8683 +                       return ret;
8684 +       }
8685 +       if (ntalk > 0 || ntalk2 > 0) {
8686 +               ret = ip_nat_helper_register(&talk_helpers[1]);
8687 +
8688 +               if (ret != 0 && talk > 0)
8689 +                       ip_nat_helper_unregister(&talk_helpers[0]);
8690 +       }
8691 +       return ret;
8692 +}
8693 +
8694 +static void __exit fini(void)
8695 +{
8696 +       if (talk > 0)
8697 +               ip_nat_helper_unregister(&talk_helpers[0]);
8698 +       if (ntalk > 0 || ntalk2 > 0)
8699 +               ip_nat_helper_unregister(&talk_helpers[1]);
8700 +}
8701 +
8702 +module_init(init);
8703 +module_exit(fini);
8704 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_pool.c
8705 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_pool.c    1970-01-01 01:00:00.000000000 +0100
8706 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_pool.c        2004-06-08 10:31:45.000000000 +0200
8707 @@ -0,0 +1,334 @@
8708 +/* Kernel module for IP pool management */
8709 +
8710 +#include <linux/module.h>
8711 +#include <linux/ip.h>
8712 +#include <linux/skbuff.h>
8713 +#include <linux/netfilter_ipv4/ip_tables.h>
8714 +#include <linux/netfilter_ipv4/ip_pool.h>
8715 +#include <linux/errno.h>
8716 +#include <asm/uaccess.h>
8717 +#include <asm/bitops.h>
8718 +#include <linux/interrupt.h>
8719 +#include <linux/spinlock.h>
8720 +
8721 +#if 0
8722 +#define DP printk
8723 +#else
8724 +#define DP(format, args...)
8725 +#endif
8726 +
8727 +MODULE_LICENSE("GPL");
8728 +
8729 +#define NR_POOL 16
8730 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8731 +
8732 +struct ip_pool {
8733 +       u_int32_t first_ip;     /* host byte order, included in range */
8734 +       u_int32_t last_ip;      /* host byte order, included in range */
8735 +       void *members;          /* the bitmap proper */
8736 +       int nr_use;             /* total nr. of tests through this */
8737 +       int nr_match;           /* total nr. of matches through this */
8738 +       rwlock_t lock;
8739 +};
8740 +
8741 +static struct ip_pool *POOL;
8742 +
8743 +static inline struct ip_pool *lookup(ip_pool_t index)
8744 +{
8745 +       if (index < 0 || index >= nr_pool) {
8746 +               DP("ip_pool:lookup: bad index %d\n", index);
8747 +               return 0;
8748 +       }
8749 +       return POOL+index;
8750 +}
8751 +
8752 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8753 +{
8754 +        struct ip_pool *pool = lookup(index);
8755 +       int res = 0;
8756 +
8757 +       if (!pool || !pool->members)
8758 +               return 0;
8759 +       read_lock_bh(&pool->lock);
8760 +       if (pool->members) {
8761 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
8762 +                       addr -= pool->first_ip;
8763 +                       if (test_bit(addr, pool->members)) {
8764 +                               res = 1;
8765 +#ifdef CONFIG_IP_POOL_STATISTICS
8766 +                               pool->nr_match++;
8767 +#endif
8768 +                       }
8769 +               }
8770 +#ifdef CONFIG_IP_POOL_STATISTICS
8771 +               pool->nr_use++;
8772 +#endif
8773 +       }
8774 +       read_unlock_bh(&pool->lock);
8775 +       return res;
8776 +}
8777 +EXPORT_SYMBOL(ip_pool_match);
8778 +
8779 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8780 +{
8781 +       struct ip_pool *pool;
8782 +       int res = -1;
8783 +
8784 +       pool = lookup(index);
8785 +       if (    !pool || !pool->members
8786 +            || addr < pool->first_ip || addr > pool->last_ip)
8787 +               return -1;
8788 +       read_lock_bh(&pool->lock);
8789 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8790 +               addr -= pool->first_ip;
8791 +               res = isdel
8792 +                       ? (0 != test_and_clear_bit(addr, pool->members))
8793 +                       : (0 != test_and_set_bit(addr, pool->members));
8794 +       }
8795 +       read_unlock_bh(&pool->lock);
8796 +       return res;
8797 +}
8798 +
8799 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8800 +{
8801 +       int res = pool_change(index,addr,isdel);
8802 +
8803 +       if (!isdel) res = !res;
8804 +       return res;
8805 +}
8806 +EXPORT_SYMBOL(ip_pool_mod);
8807 +
8808 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8809 +{
8810 +       return 4*((((b-a+8)/8)+3)/4);
8811 +}
8812 +
8813 +static inline int poolbytes(ip_pool_t index)
8814 +{
8815 +       struct ip_pool *pool = lookup(index);
8816 +
8817 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8818 +}
8819 +
8820 +static int setpool(
8821 +       struct sock *sk,
8822 +       int optval,
8823 +       void *user,
8824 +       unsigned int len
8825 +) {
8826 +       struct ip_pool_request req;
8827 +
8828 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8829 +       if (!capable(CAP_NET_ADMIN))
8830 +               return -EPERM;
8831 +       if (optval != SO_IP_POOL)
8832 +               return -EBADF;
8833 +       if (len != sizeof(req))
8834 +               return -EINVAL;
8835 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
8836 +               return -EFAULT;
8837 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
8838 +       return -EINVAL;
8839 +}
8840 +
8841 +static int getpool(
8842 +       struct sock *sk,
8843 +       int optval,
8844 +       void *user,
8845 +       int *len
8846 +) {
8847 +       struct ip_pool_request req;
8848 +       struct ip_pool *pool;
8849 +       ip_pool_t i;
8850 +       int newbytes;
8851 +       void *newmembers;
8852 +       int res;
8853 +
8854 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
8855 +       if (!capable(CAP_NET_ADMIN))
8856 +               return -EINVAL;
8857 +       if (optval != SO_IP_POOL)
8858 +               return -EINVAL;
8859 +       if (*len != sizeof(req)) {
8860 +               return -EFAULT;
8861 +       }
8862 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
8863 +               return -EFAULT;
8864 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
8865 +       if (req.op < IP_POOL_BAD001) {
8866 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
8867 +               return -EFAULT;
8868 +       }
8869 +       switch(req.op) {
8870 +       case IP_POOL_HIGH_NR:
8871 +               DP("ip_pool HIGH_NR\n");
8872 +               req.index = IP_POOL_NONE;
8873 +               for (i=0; i<nr_pool; i++)
8874 +                       if (POOL[i].members)
8875 +                               req.index = i;
8876 +               return copy_to_user(user, &req, sizeof(req));
8877 +       case IP_POOL_LOOKUP:
8878 +               DP("ip_pool LOOKUP\n");
8879 +               pool = lookup(req.index);
8880 +               if (!pool)
8881 +                       return -EINVAL;
8882 +               if (!pool->members)
8883 +                       return -EBADF;
8884 +               req.addr = htonl(pool->first_ip);
8885 +               req.addr2 = htonl(pool->last_ip);
8886 +               return copy_to_user(user, &req, sizeof(req));
8887 +       case IP_POOL_USAGE:
8888 +               DP("ip_pool USE\n");
8889 +               pool = lookup(req.index);
8890 +               if (!pool)
8891 +                       return -EINVAL;
8892 +               if (!pool->members)
8893 +                       return -EBADF;
8894 +               req.addr = pool->nr_use;
8895 +               req.addr2 = pool->nr_match;
8896 +               return copy_to_user(user, &req, sizeof(req));
8897 +       case IP_POOL_TEST_ADDR:
8898 +               DP("ip_pool TEST 0x%08x\n", req.addr);
8899 +               pool = lookup(req.index);
8900 +               if (!pool)
8901 +                       return -EINVAL;
8902 +               res = 0;
8903 +               read_lock_bh(&pool->lock);
8904 +               if (!pool->members) {
8905 +                       DP("ip_pool TEST_ADDR no members in pool\n");
8906 +                       res = -EBADF;
8907 +                       goto unlock_and_return_res;
8908 +               }
8909 +               req.addr = ntohl(req.addr);
8910 +               if (req.addr < pool->first_ip) {
8911 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
8912 +                       res = -ERANGE;
8913 +                       goto unlock_and_return_res;
8914 +               }
8915 +               if (req.addr > pool->last_ip) {
8916 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
8917 +                       res = -ERANGE;
8918 +                       goto unlock_and_return_res;
8919 +               }
8920 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
8921 +                                       pool->members));
8922 +               read_unlock_bh(&pool->lock);
8923 +               return copy_to_user(user, &req, sizeof(req));
8924 +       case IP_POOL_FLUSH:
8925 +               DP("ip_pool FLUSH not yet implemented.\n");
8926 +               return -EBUSY;
8927 +       case IP_POOL_DESTROY:
8928 +               DP("ip_pool DESTROY not yet implemented.\n");
8929 +               return -EBUSY;
8930 +       case IP_POOL_INIT:
8931 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
8932 +               pool = lookup(req.index);
8933 +               if (!pool)
8934 +                       return -EINVAL;
8935 +               req.addr = ntohl(req.addr);
8936 +               req.addr2 = ntohl(req.addr2);
8937 +               if (req.addr > req.addr2) {
8938 +                       DP("ip_pool INIT bad ip range\n");
8939 +                       return -EINVAL;
8940 +               }
8941 +               newbytes = bitmap_bytes(req.addr, req.addr2);
8942 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
8943 +               if (!newmembers) {
8944 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
8945 +                       return -ENOMEM;
8946 +               }
8947 +               memset(newmembers, 0, newbytes);
8948 +               write_lock_bh(&pool->lock);
8949 +               if (pool->members) {
8950 +                       DP("ip_pool INIT pool %d exists\n", req.index);
8951 +                       kfree(newmembers);
8952 +                       res = -EBUSY;
8953 +                       goto unlock_and_return_res;
8954 +               }
8955 +               pool->first_ip = req.addr;
8956 +               pool->last_ip = req.addr2;
8957 +               pool->nr_use = 0;
8958 +               pool->nr_match = 0;
8959 +               pool->members = newmembers;
8960 +               write_unlock_bh(&pool->lock);
8961 +               return 0;
8962 +       case IP_POOL_ADD_ADDR:
8963 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
8964 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
8965 +               return copy_to_user(user, &req, sizeof(req));
8966 +       case IP_POOL_DEL_ADDR:
8967 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
8968 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
8969 +               return copy_to_user(user, &req, sizeof(req));
8970 +       default:
8971 +               DP("ip_pool:getpool bad op %d\n", req.op);
8972 +               return -EINVAL;
8973 +       }
8974 +       return -EINVAL;
8975 +
8976 +unlock_and_return_res:
8977 +       if (pool)
8978 +               read_unlock_bh(&pool->lock);
8979 +       return res;
8980 +}
8981 +
8982 +static struct nf_sockopt_ops so_pool
8983 += { { NULL, NULL }, PF_INET,
8984 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
8985 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
8986 +    0, NULL };
8987 +
8988 +MODULE_PARM(nr_pool, "i");
8989 +
8990 +static int __init init(void)
8991 +{
8992 +       ip_pool_t i;
8993 +       int res;
8994 +
8995 +       if (nr_pool < 1) {
8996 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
8997 +               return -EINVAL;
8998 +       }
8999 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
9000 +       if (!POOL) {
9001 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
9002 +                       nr_pool);
9003 +               return -ENOMEM;
9004 +       }
9005 +       for (i=0; i<nr_pool; i++) {
9006 +               POOL[i].first_ip = 0;
9007 +               POOL[i].last_ip = 0;
9008 +               POOL[i].members = 0;
9009 +               POOL[i].nr_use = 0;
9010 +               POOL[i].nr_match = 0;
9011 +               POOL[i].lock = RW_LOCK_UNLOCKED;
9012 +       }
9013 +       res = nf_register_sockopt(&so_pool);
9014 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
9015 +       if (res != 0) {
9016 +               kfree(POOL);
9017 +               POOL = 0;
9018 +       }
9019 +       return res;
9020 +}
9021 +
9022 +static void __exit fini(void)
9023 +{
9024 +       ip_pool_t i;
9025 +
9026 +       DP("ip_pool:fini BYEBYE\n");
9027 +       nf_unregister_sockopt(&so_pool);
9028 +       for (i=0; i<nr_pool; i++) {
9029 +               if (POOL[i].members) {
9030 +                       kfree(POOL[i].members);
9031 +                       POOL[i].members = 0;
9032 +               }
9033 +       }
9034 +       kfree(POOL);
9035 +       POOL = 0;
9036 +       DP("ip_pool:fini these are the famous last words\n");
9037 +       return;
9038 +}
9039 +
9040 +module_init(init);
9041 +module_exit(fini);
9042 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.7-rc3/net/ipv4/netfilter/ip_tables.c
9043 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ip_tables.c  2004-06-07 21:14:01.000000000 +0200
9044 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ip_tables.c      2004-06-08 10:37:30.000000000 +0200
9045 @@ -29,6 +29,14 @@
9046  
9047  #include <linux/netfilter_ipv4/ip_tables.h>
9048  
9049 +static const char *hooknames[] = { 
9050 +       [NF_IP_PRE_ROUTING] "PREROUTING",
9051 +       [NF_IP_LOCAL_IN] "INPUT",
9052 +       [NF_IP_FORWARD] "FORWARD",
9053 +       [NF_IP_LOCAL_OUT] "OUTPUT",
9054 +       [NF_IP_POST_ROUTING] "POSTROUTING",
9055 +};
9056 +
9057  MODULE_LICENSE("GPL");
9058  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
9059  MODULE_DESCRIPTION("IPv4 packet filter");
9060 @@ -323,6 +331,12 @@
9061  
9062                         t = ipt_get_target(e);
9063                         IP_NF_ASSERT(t->u.kernel.target);
9064 +
9065 +                       /* The packet traced and the rule isn't an unconditional return/END. */
9066 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {       
9067 +                               nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
9068 +                                             table->name, e->chainname, e->rulenum);
9069 +                       }
9070                         /* Standard target? */
9071                         if (!t->u.kernel.target->target) {
9072                                 int v;
9073 @@ -349,7 +363,6 @@
9074                                         /* set back pointer to next entry */
9075                                         back = next;
9076                                 }
9077 -
9078                                 e = get_entry(table_base, v);
9079                         } else {
9080                                 /* Targets which reenter must return
9081 @@ -475,6 +488,29 @@
9082         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
9083  }
9084  
9085 +static inline int
9086 +find_error_target(struct ipt_entry *s, 
9087 +                 struct ipt_entry *e,
9088 +                 char **chainname)
9089 +{
9090 +       struct ipt_entry_target *t;
9091 +       static struct ipt_entry *found = NULL;
9092 +
9093 +       if (s == e) {
9094 +               if (!found)
9095 +                       return 0;
9096 +               t = ipt_get_target(found);
9097 +               if (strcmp(t->u.user.name, 
9098 +                          IPT_ERROR_TARGET) == 0) {
9099 +                       *chainname = t->data;
9100 +                       return 1;
9101 +               }
9102 +       } else
9103 +               found = s;
9104 +       
9105 +       return 0;
9106 +}
9107 +
9108  /* All zeroes == unconditional rule. */
9109  static inline int
9110  unconditional(const struct ipt_ip *ip)
9111 @@ -494,6 +530,8 @@
9112  mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
9113  {
9114         unsigned int hook;
9115 +       char *chainname = NULL;
9116 +       u_int32_t rulenum;
9117  
9118         /* No recursion; use packet counter to save back ptrs (reset
9119            to 0 as we leave), and comefrom to save source hook bitmask */
9120 @@ -507,6 +545,8 @@
9121  
9122                 /* Set initial back pointer. */
9123                 e->counters.pcnt = pos;
9124 +               rulenum = 1;
9125 +               chainname = (char *) hooknames[hook];
9126  
9127                 for (;;) {
9128                         struct ipt_standard_target *t
9129 @@ -519,6 +559,8 @@
9130                         }
9131                         e->comefrom
9132                                 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
9133 +                       e->rulenum = rulenum++;
9134 +                       e->chainname = chainname;
9135  
9136                         /* Unconditional return/END. */
9137                         if (e->target_offset == sizeof(struct ipt_entry)
9138 @@ -528,6 +570,10 @@
9139                             && unconditional(&e->ip)) {
9140                                 unsigned int oldpos, size;
9141  
9142 +                               /* Set unconditional rulenum to zero. */
9143 +                               e->rulenum = 0;
9144 +                               e->counters.bcnt = 0;
9145 +
9146                                 /* Return: backtrack through the last
9147                                    big jump. */
9148                                 do {
9149 @@ -553,6 +599,11 @@
9150                                                 (newinfo->entries + pos);
9151                                 } while (oldpos == pos + e->next_offset);
9152  
9153 +                               /* Restore chainname, rulenum. */
9154 +                               chainname = e->chainname;
9155 +                               rulenum = e->counters.bcnt;
9156 +                               e->counters.bcnt = 0;
9157 +
9158                                 /* Move along one */
9159                                 size = e->next_offset;
9160                                 e = (struct ipt_entry *)
9161 @@ -568,6 +619,17 @@
9162                                         /* This a jump; chase it. */
9163                                         duprintf("Jump rule %u -> %u\n",
9164                                                  pos, newpos);
9165 +                                       e->counters.bcnt = rulenum++;
9166 +                                       rulenum = 1;
9167 +                                       e = (struct ipt_entry *)
9168 +                                               (newinfo->entries + newpos);
9169 +                                       if (IPT_ENTRY_ITERATE(newinfo->entries,
9170 +                                                             newinfo->size,
9171 +                                                             find_error_target,
9172 +                                                             e, &chainname) == 0) {
9173 +                                               printk("ip_tables: table screwed up!\n");
9174 +                                               return 0;
9175 +                                       }
9176                                 } else {
9177                                         /* ... this is a fallthru */
9178                                         newpos = pos + e->next_offset;
9179 @@ -1713,9 +1775,9 @@
9180  };
9181  
9182  #ifdef CONFIG_PROC_FS
9183 -static inline int print_name(const char *i,
9184 -                            off_t start_offset, char *buffer, int length,
9185 -                            off_t *pos, unsigned int *count)
9186 +static int print_name(const char *i,
9187 +                      off_t start_offset, char *buffer, int length,
9188 +                      off_t *pos, unsigned int *count)
9189  {
9190         if ((*count)++ >= start_offset) {
9191                 unsigned int namelen;
9192 @@ -1749,6 +1811,15 @@
9193         return pos;
9194  }
9195  
9196 +static inline int print_target(const struct ipt_target *t,
9197 +                               off_t start_offset, char *buffer, int length,
9198 +                               off_t *pos, unsigned int *count)
9199 +{
9200 +       if (t == &ipt_standard_target || t == &ipt_error_target)
9201 +               return 0;
9202 +       return print_name((char *)t, start_offset, buffer, length, pos, count);
9203 +}
9204 +
9205  static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
9206  {
9207         off_t pos = 0;
9208 @@ -1757,7 +1828,7 @@
9209         if (down_interruptible(&ipt_mutex) != 0)
9210                 return 0;
9211  
9212 -       LIST_FIND(&ipt_target, print_name, void *,
9213 +       LIST_FIND(&ipt_target, print_target, struct ipt_target *,
9214                   offset, buffer, length, &pos, &count);
9215         
9216         up(&ipt_mutex);
9217 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
9218 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c       1970-01-01 01:00:00.000000000 +0100
9219 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_CONNMARK.c   2004-06-08 10:36:58.000000000 +0200
9220 @@ -0,0 +1,118 @@
9221 +/* This kernel module is used to modify the connection mark values, or
9222 + * to optionally restore the skb nfmark from the connection mark
9223 + *
9224 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
9225 + * by Henrik Nordstrom <hno@marasystems.com>
9226 + *
9227 + * This program is free software; you can redistribute it and/or modify
9228 + * it under the terms of the GNU General Public License as published by
9229 + * the Free Software Foundation; either version 2 of the License, or
9230 + * (at your option) any later version.
9231 + *
9232 + * This program is distributed in the hope that it will be useful,
9233 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9234 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9235 + * GNU General Public License for more details.
9236 + *
9237 + * You should have received a copy of the GNU General Public License
9238 + * along with this program; if not, write to the Free Software
9239 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
9240 + */
9241 +#include <linux/module.h>
9242 +#include <linux/skbuff.h>
9243 +#include <linux/ip.h>
9244 +#include <net/checksum.h>
9245 +
9246 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
9247 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
9248 +MODULE_LICENSE("GPL");
9249 +
9250 +#include <linux/netfilter_ipv4/ip_tables.h>
9251 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
9252 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9253 +
9254 +static unsigned int
9255 +target(struct sk_buff **pskb,
9256 +       const struct net_device *in,
9257 +       const struct net_device *out,
9258 +       unsigned int hooknum,
9259 +       const void *targinfo,
9260 +       void *userinfo)
9261 +{
9262 +       const struct ipt_connmark_target_info *markinfo = targinfo;
9263 +       unsigned long diff;
9264 +       unsigned long nfmark;
9265 +       unsigned long newmark;
9266 +
9267 +       enum ip_conntrack_info ctinfo;
9268 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
9269 +       if (ct) {
9270 +           switch(markinfo->mode) {
9271 +           case IPT_CONNMARK_SET:
9272 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
9273 +               if (newmark != ct->mark)
9274 +                   ct->mark = newmark;
9275 +               break;
9276 +           case IPT_CONNMARK_SAVE:
9277 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
9278 +               if (ct->mark != newmark)
9279 +                   ct->mark = newmark;
9280 +               break;
9281 +           case IPT_CONNMARK_RESTORE:
9282 +               nfmark = (*pskb)->nfmark;
9283 +               diff = (ct->mark ^ nfmark & markinfo->mask);
9284 +               if (diff != 0) {
9285 +                   (*pskb)->nfmark = nfmark ^ diff;
9286 +                   (*pskb)->nfcache |= NFC_ALTERED;
9287 +               }
9288 +               break;
9289 +           }
9290 +       }
9291 +
9292 +       return IPT_CONTINUE;
9293 +}
9294 +
9295 +static int
9296 +checkentry(const char *tablename,
9297 +          const struct ipt_entry *e,
9298 +          void *targinfo,
9299 +          unsigned int targinfosize,
9300 +          unsigned int hook_mask)
9301 +{
9302 +       struct ipt_connmark_target_info *matchinfo = targinfo;
9303 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
9304 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
9305 +                      targinfosize,
9306 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
9307 +               return 0;
9308 +       }
9309 +
9310 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
9311 +           if (strcmp(tablename, "mangle") != 0) {
9312 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9313 +                   return 0;
9314 +           }
9315 +       }
9316 +
9317 +       return 1;
9318 +}
9319 +
9320 +static struct ipt_target ipt_connmark_reg = {
9321 +       .name = "CONNMARK",
9322 +       .target = &target,
9323 +       .checkentry = &checkentry,
9324 +       .me = THIS_MODULE
9325 +};
9326 +
9327 +static int __init init(void)
9328 +{
9329 +       return ipt_register_target(&ipt_connmark_reg);
9330 +}
9331 +
9332 +static void __exit fini(void)
9333 +{
9334 +       ipt_unregister_target(&ipt_connmark_reg);
9335 +}
9336 +
9337 +module_init(init);
9338 +module_exit(fini);
9339 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPMARK.c
9340 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
9341 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPMARK.c     2004-06-08 10:37:02.000000000 +0200
9342 @@ -0,0 +1,81 @@
9343 +/* This is a module which is used for setting the NFMARK field of an skb. */
9344 +#include <linux/module.h>
9345 +#include <linux/skbuff.h>
9346 +#include <linux/ip.h>
9347 +#include <net/checksum.h>
9348 +
9349 +#include <linux/netfilter_ipv4/ip_tables.h>
9350 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
9351 +
9352 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
9353 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
9354 +MODULE_LICENSE("GPL");
9355 +
9356 +static unsigned int
9357 +target(struct sk_buff **pskb,
9358 +       const struct net_device *in,
9359 +       const struct net_device *out,
9360 +       unsigned int hooknum,
9361 +       const void *targinfo,
9362 +       void *userinfo)
9363 +{
9364 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
9365 +       struct iphdr *iph = (*pskb)->nh.iph;
9366 +       unsigned long mark;
9367 +
9368 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
9369 +               mark = (unsigned long) ntohl(iph->saddr);
9370 +       else
9371 +               mark = (unsigned long) ntohl(iph->daddr);
9372 +
9373 +       mark &= ipmarkinfo->andmask;
9374 +       mark |= ipmarkinfo->ormask;
9375 +       
9376 +       if ((*pskb)->nfmark != mark) {
9377 +               (*pskb)->nfmark = mark;
9378 +               (*pskb)->nfcache |= NFC_ALTERED;
9379 +       }
9380 +       return IPT_CONTINUE;
9381 +}
9382 +
9383 +static int
9384 +checkentry(const char *tablename,
9385 +          const struct ipt_entry *e,
9386 +           void *targinfo,
9387 +           unsigned int targinfosize,
9388 +           unsigned int hook_mask)
9389 +{
9390 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
9391 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
9392 +                      targinfosize,
9393 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
9394 +               return 0;
9395 +       }
9396 +
9397 +       if (strcmp(tablename, "mangle") != 0) {
9398 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9399 +               return 0;
9400 +       }
9401 +
9402 +       return 1;
9403 +}
9404 +
9405 +static struct ipt_target ipt_ipmark_reg = { 
9406 +       .name = "IPMARK",
9407 +       .target = target,
9408 +       .checkentry = checkentry,
9409 +       .me = THIS_MODULE
9410 +};
9411 +
9412 +static int __init init(void)
9413 +{
9414 +       return ipt_register_target(&ipt_ipmark_reg);
9415 +}
9416 +
9417 +static void __exit fini(void)
9418 +{
9419 +       ipt_unregister_target(&ipt_ipmark_reg);
9420 +}
9421 +
9422 +module_init(init);
9423 +module_exit(fini);
9424 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
9425 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  1970-01-01 01:00:00.000000000 +0100
9426 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      2004-06-08 10:31:05.000000000 +0200
9427 @@ -0,0 +1,89 @@
9428 +/**
9429 + * Strip all IP options in the IP packet header.
9430 + *
9431 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
9432 + * This software is distributed under GNU GPL v2, 1991
9433 + */
9434 +
9435 +#include <linux/module.h>
9436 +#include <linux/skbuff.h>
9437 +#include <linux/ip.h>
9438 +#include <net/checksum.h>
9439 +
9440 +#include <linux/netfilter_ipv4/ip_tables.h>
9441 +
9442 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
9443 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
9444 +MODULE_LICENSE("GPL");
9445 +
9446 +static unsigned int
9447 +target(struct sk_buff **pskb,
9448 +       const struct net_device *in,
9449 +       const struct net_device *out,
9450 +       unsigned int hooknum,
9451 +       const void *targinfo,
9452 +       void *userinfo)
9453 +{
9454 +       struct iphdr *iph;
9455 +       struct sk_buff *skb;
9456 +       struct ip_options *opt;
9457 +       unsigned char *optiph;
9458 +       int l;
9459 +       
9460 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
9461 +               return NF_DROP;
9462
9463 +       skb = (*pskb);
9464 +       iph = (*pskb)->nh.iph;
9465 +       optiph = skb->nh.raw;
9466 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
9467 +
9468 +       /* if no options in packet then nothing to clear. */
9469 +       if (iph->ihl * 4 == sizeof(struct iphdr))
9470 +               return IPT_CONTINUE;
9471 +
9472 +       /* else clear all options */
9473 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
9474 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
9475 +       opt = &(IPCB(skb)->opt);
9476 +       opt->is_data = 0;
9477 +       opt->optlen = l;
9478 +
9479 +       skb->nfcache |= NFC_ALTERED;
9480 +
9481 +        return IPT_CONTINUE;
9482 +}
9483 +
9484 +static int
9485 +checkentry(const char *tablename,
9486 +          const struct ipt_entry *e,
9487 +           void *targinfo,
9488 +           unsigned int targinfosize,
9489 +           unsigned int hook_mask)
9490 +{
9491 +       if (strcmp(tablename, "mangle")) {
9492 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9493 +               return 0;
9494 +       }
9495 +       /* nothing else to check because no parameters */
9496 +       return 1;
9497 +}
9498 +
9499 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
9500 +       .name = "IPV4OPTSSTRIP",
9501 +       .target = target,
9502 +       .checkentry = checkentry,
9503 +       .me = THIS_MODULE };
9504 +
9505 +static int __init init(void)
9506 +{
9507 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
9508 +}
9509 +
9510 +static void __exit fini(void)
9511 +{
9512 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9513 +}
9514 +
9515 +module_init(init);
9516 +module_exit(fini);
9517 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_NETLINK.c
9518 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c        1970-01-01 01:00:00.000000000 +0100
9519 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_NETLINK.c    2004-06-08 10:31:09.000000000 +0200
9520 @@ -0,0 +1,119 @@
9521 +#include <linux/module.h>
9522 +#include <linux/version.h>
9523 +#include <linux/config.h>
9524 +#include <linux/socket.h>
9525 +#include <linux/skbuff.h>
9526 +#include <linux/kernel.h>
9527 +#include <linux/netlink.h>
9528 +#include <linux/netdevice.h>
9529 +#include <linux/mm.h>
9530 +#include <linux/socket.h>
9531 +#include <linux/netfilter_ipv4/ip_tables.h>
9532 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9533 +#include <net/sock.h>
9534 +
9535 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9536 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9537 +MODULE_LICENSE("GPL");
9538 +
9539 +#if 0
9540 +#define DEBUGP printk
9541 +#else
9542 +#define DEBUGP(format, args...)
9543 +#endif
9544 +
9545 +static struct sock *ipfwsk;
9546 +
9547 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9548 +                                   unsigned int hooknum,
9549 +                                   const struct net_device *in,
9550 +                                   const struct net_device *out,
9551 +                                   const void *targinfo, void *userinfo)
9552 +{
9553 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9554 +       struct iphdr *ip = (*pskb)->nh.iph;
9555 +       struct sk_buff *outskb;
9556 +       struct netlink_t nlhdr;
9557 +       size_t len=0;
9558 +
9559 +       /* Allocate a socket buffer */
9560 +       if ( MASK(nld->flags, USE_SIZE) )
9561 +               len = nld->size+sizeof(nlhdr);
9562 +       else
9563 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
9564 +
9565 +       outskb=alloc_skb(len, GFP_ATOMIC);
9566 +
9567 +       if (outskb) {
9568 +               nlhdr.len=len;
9569 +               
9570 +               if ( MASK(nld->flags, USE_MARK) )
9571 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
9572 +               else
9573 +                       nlhdr.mark=(*pskb)->nfmark;
9574 +               
9575 +               if ( in && in->name ) {
9576 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9577 +               }else if ( out && out->name ){
9578 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9579 +               }
9580 +
9581 +               skb_put(outskb, len);
9582 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9583 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9584 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9585 +       }else{
9586 +               if (net_ratelimit())
9587 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9588 +       }
9589 +
9590 +       if ( MASK(nld->flags, USE_DROP) )
9591 +               return NF_DROP;
9592 +
9593 +       return IPT_CONTINUE;
9594 +}
9595 +
9596 +static int ipt_netlink_checkentry(const char *tablename,
9597 +                              const struct ipt_entry *e,
9598 +                              void *targinfo,
9599 +                              unsigned int targinfosize,
9600 +                              unsigned int hookmask)
9601 +{
9602 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9603 +
9604 +       return 1;
9605 +}
9606 +
9607 +static struct ipt_target ipt_netlink_reg = { 
9608 +       {NULL, NULL},
9609 +       "NETLINK",
9610 +       ipt_netlink_target,
9611 +       ipt_netlink_checkentry,
9612 +       NULL,
9613 +       THIS_MODULE
9614 +};
9615 +
9616 +static int __init init(void)
9617 +{
9618 +       DEBUGP("ipt_NETLINK: init module\n");   
9619 +
9620 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
9621 +               return -EINVAL;
9622 +       }
9623 +
9624 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9625 +               return -EINVAL;
9626 +       }
9627 +
9628 +       return 0;
9629 +}
9630 +
9631 +static void __exit fini(void)
9632 +{
9633 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
9634 +       ipt_unregister_target(&ipt_netlink_reg);
9635 +       if(ipfwsk->sk_socket) sock_release(ipfwsk->sk_socket);
9636 +}
9637 +
9638 +module_init(init);
9639 +module_exit(fini);
9640 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_POOL.c
9641 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_POOL.c   1970-01-01 01:00:00.000000000 +0100
9642 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_POOL.c       2004-06-08 10:31:45.000000000 +0200
9643 @@ -0,0 +1,116 @@
9644 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9645 + *
9646 + * This target can be used almost everywhere. It acts on some specified
9647 + * IP pool, adding or deleting some IP address in the pool. The address
9648 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9649 + * of the packet under inspection.
9650 + *
9651 + * The target normally returns IPT_CONTINUE.
9652 + */
9653 +
9654 +#include <linux/types.h>
9655 +#include <linux/ip.h>
9656 +#include <linux/timer.h>
9657 +#include <linux/module.h>
9658 +#include <linux/netfilter.h>
9659 +#include <linux/netdevice.h>
9660 +#include <linux/if.h>
9661 +#include <linux/inetdevice.h>
9662 +#include <net/protocol.h>
9663 +#include <net/checksum.h>
9664 +#include <linux/netfilter_ipv4.h>
9665 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9666 +#include <linux/netfilter_ipv4/ipt_pool.h>
9667 +
9668 +#if 0
9669 +#define DEBUGP printk
9670 +#else
9671 +#define DEBUGP(format, args...)
9672 +#endif
9673 +
9674 +/*** NOTE NOTE NOTE NOTE ***
9675 +**
9676 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9677 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9678 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9679 +** is modified for the source IP address of the packet under inspection.
9680 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9681 +**
9682 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9683 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9684 +**
9685 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9686 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9687 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9688 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9689 +*/
9690 +
9691 +static int
9692 +do_check(const char *tablename,
9693 +              const struct ipt_entry *e,
9694 +              void *targinfo,
9695 +              unsigned int targinfosize,
9696 +              unsigned int hook_mask)
9697 +{
9698 +       const struct ipt_pool_info *ipi = targinfo;
9699 +
9700 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9701 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
9702 +               return 0;
9703 +       }
9704 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9705 +       return 1;
9706 +}
9707 +
9708 +static unsigned int
9709 +do_target(struct sk_buff **pskb,
9710 +               unsigned int hooknum,
9711 +               const struct net_device *in,
9712 +               const struct net_device *out,
9713 +               const void *targinfo,
9714 +               void *userinfo)
9715 +{
9716 +       const struct ipt_pool_info *ipi = targinfo;
9717 +       int modified;
9718 +       unsigned int verdict = IPT_CONTINUE;
9719 +
9720 +       if (ipi->src != IP_POOL_NONE) {
9721 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9722 +                                       ipi->flags & IPT_POOL_DEL_SRC);
9723 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9724 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9725 +                               verdict = NF_ACCEPT;
9726 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9727 +                               verdict = NF_DROP;
9728 +               }
9729 +       }
9730 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9731 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9732 +                                       ipi->flags & IPT_POOL_DEL_DST);
9733 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9734 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9735 +                               verdict = NF_ACCEPT;
9736 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9737 +                               verdict = NF_DROP;
9738 +               }
9739 +       }
9740 +       return verdict;
9741 +}
9742 +
9743 +static struct ipt_target pool_reg
9744 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9745 +
9746 +static int __init init(void)
9747 +{
9748 +       DEBUGP("init ipt_POOL\n");
9749 +       return ipt_register_target(&pool_reg);
9750 +}
9751 +
9752 +static void __exit fini(void)
9753 +{
9754 +       DEBUGP("fini ipt_POOL\n");
9755 +       ipt_unregister_target(&pool_reg);
9756 +}
9757 +
9758 +module_init(init);
9759 +module_exit(fini);
9760 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_REJECT.c
9761 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_REJECT.c 2004-06-07 21:14:56.000000000 +0200
9762 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_REJECT.c     2004-06-08 10:30:55.000000000 +0200
9763 @@ -142,12 +142,7 @@
9764         nskb->dst = &rt->u.dst;
9765  
9766         /* This packet will not be the same as the other: clear nf fields */
9767 -       nf_conntrack_put(nskb->nfct);
9768 -       nskb->nfct = NULL;
9769 -       nskb->nfcache = 0;
9770 -#ifdef CONFIG_NETFILTER_DEBUG
9771 -       nskb->nf_debug = 0;
9772 -#endif
9773 +       nf_reset(nskb);
9774         nskb->nfmark = 0;
9775  #ifdef CONFIG_BRIDGE_NETFILTER
9776         nf_bridge_put(nskb->nf_bridge);
9777 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ROUTE.c
9778 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ROUTE.c  1970-01-01 01:00:00.000000000 +0100
9779 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ROUTE.c      2004-06-08 10:37:08.000000000 +0200
9780 @@ -0,0 +1,393 @@
9781 +/*
9782 + * This implements the ROUTE target, which enables you to setup unusual
9783 + * routes not supported by the standard kernel routing table.
9784 + *
9785 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
9786 + *
9787 + * v 1.9 2004/05/14
9788 + *
9789 + * This software is distributed under GNU GPL v2, 1991
9790 + */
9791 +
9792 +#include <linux/module.h>
9793 +#include <linux/skbuff.h>
9794 +#include <linux/ip.h>
9795 +#include <linux/netfilter_ipv4/ip_tables.h>
9796 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
9797 +#include <linux/netdevice.h>
9798 +#include <linux/route.h>
9799 +#include <net/ip.h>
9800 +#include <net/route.h>
9801 +#include <net/icmp.h>
9802 +#include <net/checksum.h>
9803 +
9804 +#if 0
9805 +#define DEBUGP printk
9806 +#else
9807 +#define DEBUGP(format, args...)
9808 +#endif
9809 +
9810 +MODULE_LICENSE("GPL");
9811 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
9812 +MODULE_DESCRIPTION("iptables ROUTE target module");
9813 +
9814 +/* Try to route the packet according to the routing keys specified in
9815 + * route_info. Keys are :
9816 + *  - ifindex : 
9817 + *      0 if no oif preferred, 
9818 + *      otherwise set to the index of the desired oif
9819 + *  - route_info->gw :
9820 + *      0 if no gateway specified,
9821 + *      otherwise set to the next host to which the pkt must be routed
9822 + * If success, skb->dev is the output device to which the packet must 
9823 + * be sent and skb->dst is not NULL
9824 + *
9825 + * RETURN: -1 if an error occured
9826 + *          1 if the packet was succesfully routed to the 
9827 + *            destination desired
9828 + *          0 if the kernel routing table could not route the packet
9829 + *            according to the keys specified
9830 + */
9831 +static int route(struct sk_buff *skb,
9832 +                unsigned int ifindex,
9833 +                const struct ipt_route_target_info *route_info)
9834 +{
9835 +       int err;
9836 +       struct rtable *rt;
9837 +       struct iphdr *iph = skb->nh.iph;
9838 +       struct flowi fl = {
9839 +               .oif = ifindex,
9840 +               .nl_u = {
9841 +                       .ip4_u = {
9842 +                               .daddr = iph->daddr,
9843 +                               .saddr = 0,
9844 +                               .tos = RT_TOS(iph->tos),
9845 +                               .scope = RT_SCOPE_UNIVERSE,
9846 +                       }
9847 +               } 
9848 +       };
9849 +       
9850 +       /* The destination address may be overloaded by the target */
9851 +       if (route_info->gw)
9852 +               fl.fld_dst = route_info->gw;
9853 +       
9854 +       /* Trying to route the packet using the standard routing table. */
9855 +       if ((err = ip_route_output_key(&rt, &fl))) {
9856 +               if (net_ratelimit()) 
9857 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
9858 +               return -1;
9859 +       }
9860 +       
9861 +       /* Drop old route. */
9862 +       dst_release(skb->dst);
9863 +       skb->dst = NULL;
9864 +
9865 +       /* Success if no oif specified or if the oif correspond to the 
9866 +        * one desired */
9867 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
9868 +               skb->dst = &rt->u.dst;
9869 +               skb->dev = skb->dst->dev;
9870 +               return 1;
9871 +       }
9872 +       
9873 +       /* The interface selected by the routing table is not the one
9874 +        * specified by the user. This may happen because the dst address
9875 +        * is one of our own addresses.
9876 +        */
9877 +       if (net_ratelimit()) 
9878 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
9879 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
9880 +       
9881 +       return 0;
9882 +}
9883 +
9884 +
9885 +/* Stolen from ip_finish_output2
9886 + * PRE : skb->dev is set to the device we are leaving by
9887 + *       skb->dst is not NULL
9888 + * POST: the packet is sent with the link layer header pushed
9889 + *       the packet is destroyed
9890 + */
9891 +static void ip_direct_send(struct sk_buff *skb)
9892 +{
9893 +       struct dst_entry *dst = skb->dst;
9894 +       struct hh_cache *hh = dst->hh;
9895 +
9896 +       if (hh) {
9897 +               read_lock_bh(&hh->hh_lock);
9898 +               memcpy(skb->data - 16, hh->hh_data, 16);
9899 +               read_unlock_bh(&hh->hh_lock);
9900 +               skb_push(skb, hh->hh_len);
9901 +               hh->hh_output(skb);
9902 +       } else if (dst->neighbour)
9903 +               dst->neighbour->output(skb);
9904 +       else {
9905 +               if (net_ratelimit())
9906 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
9907 +               kfree_skb(skb);
9908 +       }
9909 +}
9910 +
9911 +
9912 +/* PRE : skb->dev is set to the device we are leaving by
9913 + * POST: - the packet is directly sent to the skb->dev device, without 
9914 + *         pushing the link layer header.
9915 + *       - the packet is destroyed
9916 + */
9917 +static inline int dev_direct_send(struct sk_buff *skb)
9918 +{
9919 +       return dev_queue_xmit(skb);
9920 +}
9921 +
9922 +
9923 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
9924 +                             struct sk_buff *skb) 
9925 +{
9926 +       unsigned int ifindex = 0;
9927 +       struct net_device *dev_out = NULL;
9928 +
9929 +       /* The user set the interface name to use.
9930 +        * Getting the current interface index.
9931 +        */
9932 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
9933 +               ifindex = dev_out->ifindex;
9934 +       } else {
9935 +               /* Unknown interface name : packet dropped */
9936 +               if (net_ratelimit()) 
9937 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
9938 +               return NF_DROP;
9939 +       }
9940 +
9941 +       /* Trying the standard way of routing packets */
9942 +       switch (route(skb, ifindex, route_info)) {
9943 +       case 1:
9944 +               dev_put(dev_out);
9945 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
9946 +                       return IPT_CONTINUE;
9947 +
9948 +               ip_direct_send(skb);
9949 +               return NF_STOLEN;
9950 +
9951 +       case 0:
9952 +               /* Failed to send to oif. Trying the hard way */
9953 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
9954 +                       return NF_DROP;
9955 +
9956 +               if (net_ratelimit()) 
9957 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
9958 +                              ifindex);
9959 +
9960 +               /* We have to force the use of an interface.
9961 +                * This interface must be a tunnel interface since
9962 +                * otherwise we can't guess the hw address for
9963 +                * the packet. For a tunnel interface, no hw address
9964 +                * is needed.
9965 +                */
9966 +               if ((dev_out->type != ARPHRD_TUNNEL)
9967 +                   && (dev_out->type != ARPHRD_IPGRE)) {
9968 +                       if (net_ratelimit()) 
9969 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
9970 +                       dev_put(dev_out);
9971 +                       return NF_DROP;
9972 +               }
9973 +       
9974 +               /* Send the packet. This will also free skb
9975 +                * Do not go through the POST_ROUTING hook because 
9976 +                * skb->dst is not set and because it will probably
9977 +                * get confused by the destination IP address.
9978 +                */
9979 +               skb->dev = dev_out;
9980 +               dev_direct_send(skb);
9981 +               dev_put(dev_out);
9982 +               return NF_STOLEN;
9983 +               
9984 +       default:
9985 +               /* Unexpected error */
9986 +               dev_put(dev_out);
9987 +               return NF_DROP;
9988 +       }
9989 +}
9990 +
9991 +
9992 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
9993 +                             struct sk_buff *skb) 
9994 +{
9995 +       struct net_device *dev_in = NULL;
9996 +
9997 +       /* Getting the current interface index. */
9998 +       if (!(dev_in = dev_get_by_name(route_info->iif))) {
9999 +               if (net_ratelimit()) 
10000 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
10001 +               return NF_DROP;
10002 +       }
10003 +
10004 +       skb->dev = dev_in;
10005 +       dst_release(skb->dst);
10006 +       skb->dst = NULL;
10007 +
10008 +       netif_rx(skb);
10009 +       dev_put(dev_in);
10010 +       return NF_STOLEN;
10011 +}
10012 +
10013 +
10014 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
10015 +                            struct sk_buff *skb) 
10016 +{
10017 +       if (route(skb, 0, route_info)!=1)
10018 +               return NF_DROP;
10019 +
10020 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
10021 +               return IPT_CONTINUE;
10022 +
10023 +       ip_direct_send(skb);
10024 +       return NF_STOLEN;
10025 +}
10026 +
10027 +
10028 +static unsigned int ipt_route_target(struct sk_buff **pskb,
10029 +                                    const struct net_device *in,
10030 +                                    const struct net_device *out,
10031 +                                    unsigned int hooknum,
10032 +                                    const void *targinfo,
10033 +                                    void *userinfo)
10034 +{
10035 +       const struct ipt_route_target_info *route_info = targinfo;
10036 +       struct sk_buff *skb = *pskb;
10037 +
10038 +       /* If we are at PREROUTING or INPUT hook
10039 +        * the TTL isn't decreased by the IP stack
10040 +        */
10041 +       if (hooknum == NF_IP_PRE_ROUTING ||
10042 +           hooknum == NF_IP_LOCAL_IN) {
10043 +
10044 +               struct iphdr *iph = skb->nh.iph;
10045 +
10046 +               if (iph->ttl <= 1) {
10047 +                       struct rtable *rt;
10048 +                       struct flowi fl = {
10049 +                               .oif = 0,
10050 +                               .nl_u = {
10051 +                                       .ip4_u = {
10052 +                                               .daddr = iph->daddr,
10053 +                                               .saddr = iph->saddr,
10054 +                                               .tos = RT_TOS(iph->tos),
10055 +                                               .scope = ((iph->tos & RTO_ONLINK) ?
10056 +                                                         RT_SCOPE_LINK :
10057 +                                                         RT_SCOPE_UNIVERSE)
10058 +                                       }
10059 +                               } 
10060 +                       };
10061 +
10062 +                       if (ip_route_output_key(&rt, &fl)) {
10063 +                               return NF_DROP;
10064 +                       }
10065 +
10066 +                       if (skb->dev == rt->u.dst.dev) {
10067 +                               /* Drop old route. */
10068 +                               dst_release(skb->dst);
10069 +                               skb->dst = &rt->u.dst;
10070 +
10071 +                               /* this will traverse normal stack, and 
10072 +                                * thus call conntrack on the icmp packet */
10073 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
10074 +                                         ICMP_EXC_TTL, 0);
10075 +                       }
10076 +
10077 +                       return NF_DROP;
10078 +               }
10079 +
10080 +               /*
10081 +                * If we are at INPUT the checksum must be recalculated since
10082 +                * the length could change as the result of a defragmentation.
10083 +                */
10084 +               if(hooknum == NF_IP_LOCAL_IN) {
10085 +                       iph->ttl = iph->ttl - 1;
10086 +                       iph->check = 0;
10087 +                       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
10088 +               } else {
10089 +                       ip_decrease_ttl(iph);
10090 +               }
10091 +       }
10092 +
10093 +       /* Tell conntrack to forget this packet since it may get confused 
10094 +        * when a packet is leaving with dst address == our address.
10095 +        * Good idea ? Dunno. Need advice.
10096 +        */
10097 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
10098 +               nf_conntrack_put(skb->nfct);
10099 +               skb->nfct = NULL;
10100 +               skb->nfcache = 0;
10101 +#ifdef CONFIG_NETFILTER_DEBUG
10102 +               skb->nf_debug = 0;
10103 +#endif
10104 +       }
10105 +
10106 +       if (route_info->oif[0] != '\0') 
10107 +               return route_oif(route_info, *pskb);
10108 +       
10109 +       if (route_info->iif[0] != '\0') 
10110 +               return route_iif(route_info, *pskb);
10111 +
10112 +       if (route_info->gw) 
10113 +               return route_gw(route_info, *pskb);
10114 +
10115 +       if (net_ratelimit()) 
10116 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
10117 +
10118 +       return IPT_CONTINUE;
10119 +}
10120 +
10121 +
10122 +static int ipt_route_checkentry(const char *tablename,
10123 +                               const struct ipt_entry *e,
10124 +                               void *targinfo,
10125 +                               unsigned int targinfosize,
10126 +                               unsigned int hook_mask)
10127 +{
10128 +       if (strcmp(tablename, "mangle") != 0) {
10129 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
10130 +                      tablename);
10131 +               return 0;
10132 +       }
10133 +
10134 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
10135 +                           | (1 << NF_IP_LOCAL_IN)
10136 +                           | (1 << NF_IP_FORWARD)
10137 +                           | (1 << NF_IP_LOCAL_OUT)
10138 +                           | (1 << NF_IP_POST_ROUTING))) {
10139 +               printk("ipt_ROUTE: bad hook\n");
10140 +               return 0;
10141 +       }
10142 +
10143 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
10144 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
10145 +                      targinfosize,
10146 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
10147 +               return 0;
10148 +       }
10149 +
10150 +       return 1;
10151 +}
10152 +
10153 +
10154 +static struct ipt_target ipt_route_reg = { 
10155 +       .name = "ROUTE",
10156 +       .target = ipt_route_target,
10157 +       .checkentry = ipt_route_checkentry,
10158 +       .me = THIS_MODULE,
10159 +};
10160 +
10161 +static int __init init(void)
10162 +{
10163 +       return ipt_register_target(&ipt_route_reg);
10164 +}
10165 +
10166 +
10167 +static void __exit fini(void)
10168 +{
10169 +       ipt_unregister_target(&ipt_route_reg);
10170 +}
10171 +
10172 +module_init(init);
10173 +module_exit(fini);
10174 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TARPIT.c
10175 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
10176 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TARPIT.c     2004-06-08 10:37:16.000000000 +0200
10177 @@ -0,0 +1,290 @@
10178 +/* 
10179 + * Kernel module to capture and hold incoming TCP connections using 
10180 + * no local per-connection resources.
10181 + * 
10182 + * Based on ipt_REJECT.c and offering functionality similar to 
10183 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
10184 + * 
10185 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
10186 + * 
10187 + * This program is free software; you can redistribute it and/or modify
10188 + * it under the terms of the GNU General Public License as published by
10189 + * the Free Software Foundation; either version 2 of the License, or
10190 + * (at your option) any later version.
10191 + *
10192 + * This program is distributed in the hope that it will be useful,
10193 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10194 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10195 + * GNU General Public License for more details.
10196 + *
10197 + * You should have received a copy of the GNU General Public License
10198 + * along with this program; if not, write to the Free Software
10199 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
10200 + * 
10201 + * Goal:
10202 + * - Allow incoming TCP connections to be established.
10203 + * - Passing data should result in the connection being switched to the 
10204 + *   persist state (0 byte window), in which the remote side stops sending 
10205 + *   data and asks to continue every 60 seconds.
10206 + * - Attempts to shut down the connection should be ignored completely, so 
10207 + *   the remote side ends up having to time it out.
10208 + *
10209 + * This means:
10210 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
10211 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
10212 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
10213 + */
10214 +
10215 +#include <linux/config.h>
10216 +#include <linux/module.h>
10217 +#include <linux/skbuff.h>
10218 +#include <linux/ip.h>
10219 +#include <net/ip.h>
10220 +#include <net/tcp.h>
10221 +#include <net/icmp.h>
10222 +struct in_device;
10223 +#include <net/route.h>
10224 +#include <linux/random.h>
10225 +#include <linux/netfilter_ipv4/ip_tables.h>
10226 +
10227 +#if 0
10228 +#define DEBUGP printk
10229 +#else
10230 +#define DEBUGP(format, args...)
10231 +#endif
10232 +
10233 +MODULE_LICENSE("GPL");
10234 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
10235 +
10236 +/* Stolen from ip_finish_output2 */
10237 +static int ip_direct_send(struct sk_buff *skb)
10238 +{
10239 +       struct dst_entry *dst = skb->dst;
10240 +       struct hh_cache *hh = dst->hh;
10241 +
10242 +       if (hh) {    
10243 +               read_lock_bh(&hh->hh_lock);
10244 +               memcpy(skb->data - 16, hh->hh_data, 16);
10245 +                read_unlock_bh(&hh->hh_lock);
10246 +                skb_push(skb, hh->hh_len);
10247 +                return hh->hh_output(skb);
10248 +        } else if (dst->neighbour)
10249 +                return dst->neighbour->output(skb);
10250 +
10251 +       if (net_ratelimit())
10252 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
10253 +        kfree_skb(skb);
10254 +        return -EINVAL;
10255 +}
10256 +
10257 +
10258 +/* Send reply */
10259 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
10260 +{
10261 +       struct sk_buff *nskb;
10262 +       struct rtable *nrt;
10263 +       struct tcphdr *otcph, *ntcph;
10264 +       struct flowi fl = {};
10265 +       unsigned int otcplen;
10266 +       u_int16_t tmp;
10267 +
10268 +       /* A truncated TCP header isn't going to be useful */
10269 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
10270 +               return;
10271 +
10272 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
10273 +                                  + oskb->nh.iph->ihl);
10274 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
10275 +
10276 +       /* No replies for RST or FIN */
10277 +       if (otcph->rst || otcph->fin)
10278 +               return;
10279 +
10280 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
10281 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
10282 +               return;
10283 +
10284 +       /* Check checksum. */
10285 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
10286 +                        oskb->nh.iph->daddr,
10287 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
10288 +               return;
10289 +
10290 +       /* Copy skb (even if skb is about to be dropped, we can't just
10291 +           clone it because there may be other things, such as tcpdump,
10292 +           interested in it) */
10293 +       nskb = skb_copy(oskb, GFP_ATOMIC);
10294 +       if (!nskb)
10295 +               return;
10296 +
10297 +       /* This packet will not be the same as the other: clear nf fields */
10298 +       nf_conntrack_put(nskb->nfct);
10299 +       nskb->nfct = NULL;
10300 +       nskb->nfcache = 0;
10301 +#ifdef CONFIG_NETFILTER_DEBUG
10302 +       nskb->nf_debug = 0;
10303 +#endif
10304 +
10305 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
10306 +
10307 +       /* Truncate to length (no data) */
10308 +       ntcph->doff = sizeof(struct tcphdr)/4;
10309 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
10310 +       nskb->nh.iph->tot_len = htons(nskb->len);
10311 +
10312 +       /* Swap source and dest */
10313 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
10314 +       tmp = ntcph->source;
10315 +       ntcph->source = ntcph->dest;
10316 +       ntcph->dest = tmp;
10317 +
10318 +       /* Use supplied sequence number or make a new one */
10319 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
10320 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
10321 +                                                       nskb->nh.iph->daddr, 
10322 +                                                       ntcph->source, 
10323 +                                                       ntcph->dest));
10324 +
10325 +       /* Our SYN-ACKs must have a >0 window */
10326 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
10327 +
10328 +       ntcph->urg_ptr = 0;
10329 +
10330 +       /* Reset flags */
10331 +       ((u_int8_t *)ntcph)[13] = 0;
10332 +
10333 +       if (otcph->syn && otcph->ack) {
10334 +               ntcph->rst = 1;
10335 +               ntcph->ack_seq = 0;
10336 +       } else {
10337 +               ntcph->syn = otcph->syn;
10338 +               ntcph->ack = 1;
10339 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
10340 +       }
10341 +
10342 +       /* Adjust TCP checksum */
10343 +       ntcph->check = 0;
10344 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
10345 +                                  nskb->nh.iph->saddr,
10346 +                                  nskb->nh.iph->daddr,
10347 +                                  csum_partial((char *)ntcph,
10348 +                                               sizeof(struct tcphdr), 0));
10349 +
10350 +       /* Adjust IP TTL */
10351 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
10352 +
10353 +       /* Set DF, id = 0 */
10354 +       nskb->nh.iph->frag_off = htons(IP_DF);
10355 +       nskb->nh.iph->id = 0;
10356 +
10357 +       /* Adjust IP checksum */
10358 +       nskb->nh.iph->check = 0;
10359 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
10360 +                                          nskb->nh.iph->ihl);
10361 +
10362 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
10363 +       fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
10364 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
10365 +       fl.oif = 0;
10366 +
10367 +       if (ip_route_output_key(&nrt, &fl))
10368 +               goto free_nskb;
10369 +
10370 +       dst_release(nskb->dst);
10371 +       nskb->dst = &nrt->u.dst;
10372 +
10373 +       /* "Never happens" */
10374 +       if (nskb->len > dst_pmtu(nskb->dst))
10375 +               goto free_nskb;
10376 +
10377 +       ip_direct_send (nskb);
10378 +
10379 +       return;
10380 +
10381 + free_nskb:
10382 +       kfree_skb(nskb);
10383 +}
10384 +
10385 +
10386 +static unsigned int tarpit(struct sk_buff **pskb,
10387 +                          const struct net_device *in,
10388 +                          const struct net_device *out,
10389 +                          unsigned int hooknum,
10390 +                          const void *targinfo,
10391 +                          void *userinfo)
10392 +{
10393 +       struct sk_buff *skb = *pskb;
10394 +       struct rtable *rt = (struct rtable*)skb->dst;
10395 +
10396 +       /* Do we have an input route cache entry? */
10397 +       if (!rt)
10398 +               return NF_DROP;
10399 +
10400 +        /* No replies to physical multicast/broadcast */
10401 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
10402 +               return NF_DROP;
10403 +
10404 +        /* Now check at the protocol level */
10405 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
10406 +                return NF_DROP;
10407 +
10408 +       /* Our naive response construction doesn't deal with IP
10409 +           options, and probably shouldn't try. */
10410 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
10411 +               return NF_DROP;
10412 +
10413 +        /* We aren't interested in fragments */
10414 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
10415 +                return NF_DROP;
10416 +
10417 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
10418 +
10419 +       return NF_DROP;
10420 +}
10421 +
10422 +
10423 +static int check(const char *tablename,
10424 +                const struct ipt_entry *e,
10425 +                void *targinfo,
10426 +                unsigned int targinfosize,
10427 +                unsigned int hook_mask)
10428 +{
10429 +       /* Only allow these for input/forward packet filtering. */
10430 +       if (strcmp(tablename, "filter") != 0) {
10431 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
10432 +               return 0;
10433 +       }
10434 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
10435 +                           | (1 << NF_IP_FORWARD))) != 0) {
10436 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
10437 +               return 0;
10438 +       }
10439 +
10440 +       /* Must specify that it's a TCP packet */
10441 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
10442 +               DEBUGP("TARPIT: not valid for non-tcp\n");
10443 +               return 0;
10444 +       }
10445 +
10446 +       return 1;
10447 +}
10448 +
10449 +static struct ipt_target ipt_tarpit_reg = { 
10450 +       .name = "TARPIT",
10451 +       .target = tarpit,
10452 +       .checkentry = check,
10453 +       .me = THIS_MODULE
10454 +};
10455 +
10456 +static int __init init(void)
10457 +{
10458 +       return ipt_register_target(&ipt_tarpit_reg);
10459 +}
10460 +
10461 +static void __exit fini(void)
10462 +{
10463 +       ipt_unregister_target(&ipt_tarpit_reg);
10464 +}
10465 +
10466 +module_init(init);
10467 +module_exit(fini);
10468 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TRACE.c
10469 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TRACE.c  1970-01-01 01:00:00.000000000 +0100
10470 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TRACE.c      2004-06-08 10:37:30.000000000 +0200
10471 @@ -0,0 +1,64 @@
10472 +/* This is a module which is used for setting 
10473 + * the NFC_TRACE flag in the nfcache field of an skb. 
10474 + */
10475 +#include <linux/module.h>
10476 +#include <linux/skbuff.h>
10477 +
10478 +#include <linux/netfilter_ipv4/ip_tables.h>
10479 +
10480 +static unsigned int
10481 +target(struct sk_buff **pskb,
10482 +       const struct net_device *in,
10483 +       const struct net_device *out,
10484 +       unsigned int hooknum,
10485 +       const void *targinfo,
10486 +       void *userinfo)
10487 +{
10488 +       (*pskb)->nfcache |= NFC_TRACE;
10489 +       return IPT_CONTINUE;
10490 +}
10491 +
10492 +static int
10493 +checkentry(const char *tablename,
10494 +          const struct ipt_entry *e,
10495 +           void *targinfo,
10496 +           unsigned int targinfosize,
10497 +           unsigned int hook_mask)
10498 +{
10499 +       if (targinfosize != 0) {
10500 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
10501 +                      targinfosize);
10502 +               return 0;
10503 +       }
10504 +
10505 +       if (strcmp(tablename, "raw") != 0) {
10506 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
10507 +               return 0;
10508 +       }
10509 +
10510 +       return 1;
10511 +}
10512 +
10513 +static struct ipt_target ipt_trace_reg = { 
10514 +       .name = "TRACE", 
10515 +       .target = target, 
10516 +       .checkentry = checkentry, 
10517 +       .me = THIS_MODULE
10518 +};
10519 +
10520 +static int __init init(void)
10521 +{
10522 +       if (ipt_register_target(&ipt_trace_reg))
10523 +               return -EINVAL;
10524 +
10525 +       return 0;
10526 +}
10527 +
10528 +static void __exit fini(void)
10529 +{
10530 +       ipt_unregister_target(&ipt_trace_reg);
10531 +}
10532 +
10533 +module_init(init);
10534 +module_exit(fini);
10535 +MODULE_LICENSE("GPL");
10536 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TTL.c
10537 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_TTL.c    1970-01-01 01:00:00.000000000 +0100
10538 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_TTL.c        2004-06-08 10:31:21.000000000 +0200
10539 @@ -0,0 +1,120 @@
10540 +/* TTL modification target for IP tables
10541 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
10542 + *
10543 + * Version: $Revision$
10544 + *
10545 + * This software is distributed under the terms of GNU GPL
10546 + */
10547 +
10548 +#include <linux/module.h>
10549 +#include <linux/skbuff.h>
10550 +#include <linux/ip.h>
10551 +#include <net/checksum.h>
10552 +
10553 +#include <linux/netfilter_ipv4/ip_tables.h>
10554 +#include <linux/netfilter_ipv4/ipt_TTL.h>
10555 +
10556 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
10557 +MODULE_DESCRIPTION("IP tables TTL modification module");
10558 +MODULE_LICENSE("GPL");
10559 +
10560 +static unsigned int 
10561 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 
10562 +               const struct net_device *out, unsigned int hooknum, 
10563 +               const void *targinfo, void *userinfo)
10564 +{
10565 +       struct iphdr *iph;
10566 +       const struct ipt_TTL_info *info = targinfo;
10567 +       u_int16_t diffs[2];
10568 +       int new_ttl;
10569 +
10570 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
10571 +               return NF_DROP;
10572 +
10573 +       iph = (*pskb)->nh.iph;
10574 +                        
10575 +       switch (info->mode) {
10576 +               case IPT_TTL_SET:
10577 +                       new_ttl = info->ttl;
10578 +                       break;
10579 +               case IPT_TTL_INC:
10580 +                       new_ttl = iph->ttl + info->ttl;
10581 +                       if (new_ttl > 255)
10582 +                               new_ttl = 255;
10583 +                       break;
10584 +               case IPT_TTL_DEC:
10585 +                       new_ttl = iph->ttl + info->ttl;
10586 +                       if (new_ttl < 0)
10587 +                               new_ttl = 0;
10588 +                       break;
10589 +               default:
10590 +                       new_ttl = iph->ttl;
10591 +                       break;
10592 +       }
10593 +
10594 +       if (new_ttl != iph->ttl) {
10595 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
10596 +               iph->ttl = new_ttl;
10597 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
10598 +               iph->check = csum_fold(csum_partial((char *)diffs,
10599 +                                                   sizeof(diffs),
10600 +                                                   iph->check^0xFFFF));
10601 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
10602 +       }
10603 +
10604 +       return IPT_CONTINUE;
10605 +}
10606 +
10607 +static int ipt_ttl_checkentry(const char *tablename,
10608 +               const struct ipt_entry *e,
10609 +               void *targinfo,
10610 +               unsigned int targinfosize,
10611 +               unsigned int hook_mask)
10612 +{
10613 +       struct ipt_TTL_info *info = targinfo;
10614 +
10615 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
10616 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
10617 +                               targinfosize,
10618 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
10619 +               return 0;       
10620 +       }       
10621 +
10622 +       if (strcmp(tablename, "mangle")) {
10623 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
10624 +               return 0;
10625 +       }
10626 +
10627 +       if (info->mode > IPT_TTL_MAXMODE) {
10628 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
10629 +                       info->mode);
10630 +               return 0;
10631 +       }
10632 +
10633 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
10634 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
10635 +               return 0;
10636 +       }
10637 +       
10638 +       return 1;
10639 +}
10640 +
10641 +static struct ipt_target ipt_TTL = { 
10642 +       .name = "TTL",
10643 +       .target = ipt_ttl_target, 
10644 +       .checkentry = ipt_ttl_checkentry, 
10645 +       .me = THIS_MODULE 
10646 +};
10647 +
10648 +static int __init init(void)
10649 +{
10650 +       return ipt_register_target(&ipt_TTL);
10651 +}
10652 +
10653 +static void __exit fini(void)
10654 +{
10655 +       ipt_unregister_target(&ipt_TTL);
10656 +}
10657 +
10658 +module_init(init);
10659 +module_exit(fini);
10660 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_XOR.c
10661 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_XOR.c    1970-01-01 01:00:00.000000000 +0100
10662 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_XOR.c        2004-06-08 10:37:54.000000000 +0200
10663 @@ -0,0 +1,117 @@
10664 +/* XOR target for IP tables
10665 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
10666 + * Based on ipt_TTL.c
10667 + *
10668 + * Version 1.0
10669 + *
10670 + * This software is distributed under the terms of GNU GPL
10671 + */
10672 +
10673 +#include <linux/module.h>
10674 +#include <linux/skbuff.h>
10675 +#include <linux/ip.h>
10676 +#include <linux/tcp.h>
10677 +#include <linux/udp.h>
10678 +
10679 +#include <linux/netfilter_ipv4/ip_tables.h>
10680 +#include <linux/netfilter_ipv4/ipt_XOR.h>
10681 +
10682 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
10683 +MODULE_DESCRIPTION("IP tables XOR module");
10684 +MODULE_LICENSE("GPL");
10685 +
10686 +static unsigned int 
10687 +ipt_xor_target(struct sk_buff **pskb, 
10688 +               const struct net_device *in, const struct net_device *out, 
10689 +               unsigned int hooknum, const void *targinfo, void *userinfo)
10690 +{
10691 +       struct ipt_XOR_info *info = (void *) targinfo;
10692 +       struct iphdr *iph;
10693 +       struct tcphdr *tcph;
10694 +       struct udphdr *udph;
10695 +       int i, j, k;
10696 +
10697 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
10698 +               return NF_DROP;
10699 +
10700 +       iph = (*pskb)->nh.iph;
10701 +  
10702 +       if (iph->protocol == IPPROTO_TCP) {
10703 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
10704 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
10705 +                       for (k=0; k<=info->block_size; k++) {
10706 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
10707 +                                               info->key[j];
10708 +                               i++;
10709 +                       }
10710 +                       j++;
10711 +                       if (info->key[j] == 0x00)
10712 +                               j = 0;
10713 +               }
10714 +       } else if (iph->protocol == IPPROTO_UDP) {
10715 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
10716 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
10717 +                       for (k=0; k<=info->block_size; k++) {
10718 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
10719 +                                               info->key[j];
10720 +                               i++;
10721 +                       }
10722 +                       j++;
10723 +                       if (info->key[j] == 0x00)
10724 +                               j = 0;
10725 +               }
10726 +       }
10727 +  
10728 +       return IPT_CONTINUE;
10729 +}
10730 +
10731 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
10732 +               void *targinfo, unsigned int targinfosize, 
10733 +               unsigned int hook_mask)
10734 +{
10735 +       struct ipt_XOR_info *info = targinfo;
10736 +
10737 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
10738 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
10739 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
10740 +               return 0;
10741 +       }       
10742 +
10743 +       if (strcmp(tablename, "mangle")) {
10744 +               printk(KERN_WARNING "XOR: can only be called from"
10745 +                               "\"mangle\" table, not \"%s\"\n", tablename);
10746 +               return 0; 
10747 +       }
10748 +
10749 +       if (!strcmp(info->key, "")) {
10750 +               printk(KERN_WARNING "XOR: You must specify a key");
10751 +               return 0;
10752 +       }
10753 +
10754 +       if (info->block_size == 0) {
10755 +               printk(KERN_WARNING "XOR: You must specify a block-size");
10756 +               return 0;
10757 +       }
10758 +
10759 +       return 1;
10760 +}
10761 +
10762 +static struct ipt_target ipt_XOR = { 
10763 +       .name = "XOR",
10764 +       .target = ipt_xor_target, 
10765 +       .checkentry = ipt_xor_checkentry,
10766 +       .me = THIS_MODULE,
10767 +};
10768 +
10769 +static int __init init(void)
10770 +{
10771 +       return ipt_register_target(&ipt_XOR);
10772 +}
10773 +
10774 +static void __exit fini(void)
10775 +{
10776 +       ipt_unregister_target(&ipt_XOR);
10777 +}
10778 +
10779 +module_init(init);
10780 +module_exit(fini);
10781 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_addrtype.c
10782 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_addrtype.c       1970-01-01 01:00:00.000000000 +0100
10783 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_addrtype.c   2004-06-08 10:38:04.000000000 +0200
10784 @@ -0,0 +1,75 @@
10785 +/*
10786 + *  iptables module to match inet_addr_type() of an ip.
10787 + *
10788 + *  Copyright (c) 2004 Patrick McHardy <kaber@trash.net>
10789 + *
10790 + *  This program is free software; you can redistribute it and/or modify
10791 + *  it under the terms of the GNU General Public License version 2 as
10792 + *  published by the Free Software Foundation.
10793 + */
10794 +
10795 +#include <linux/module.h>
10796 +#include <linux/skbuff.h>
10797 +#include <linux/netdevice.h>
10798 +#include <net/route.h>
10799 +
10800 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
10801 +#include <linux/netfilter_ipv4/ip_tables.h>
10802 +
10803 +MODULE_LICENSE("GPL");
10804 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
10805 +MODULE_DESCRIPTION("iptables addrtype match");
10806 +
10807 +static inline int match_type(u_int32_t addr, u_int16_t mask)
10808 +{
10809 +       return !!(mask & (1 << inet_addr_type(addr)));
10810 +}
10811 +
10812 +static int match(const struct sk_buff *skb, const struct net_device *in,
10813 +                const struct net_device *out, const void *matchinfo,
10814 +                int offset, int *hotdrop)
10815 +{
10816 +       const struct ipt_addrtype_info *info = matchinfo;
10817 +       const struct iphdr *iph = skb->nh.iph;
10818 +       int ret = 1;
10819 +
10820 +       if (info->source)
10821 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
10822 +       if (info->dest)
10823 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
10824 +       
10825 +       return ret;
10826 +}
10827 +
10828 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
10829 +                     void *matchinfo, unsigned int matchsize,
10830 +                     unsigned int hook_mask)
10831 +{
10832 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
10833 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
10834 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
10835 +               return 0;
10836 +       }
10837 +
10838 +       return 1;
10839 +}
10840 +
10841 +static struct ipt_match addrtype_match = {
10842 +       .name           = "addrtype",
10843 +       .match          = match,
10844 +       .checkentry     = checkentry,
10845 +       .me             = THIS_MODULE
10846 +};
10847 +
10848 +static int __init init(void)
10849 +{
10850 +       return ipt_register_match(&addrtype_match);
10851 +}
10852 +
10853 +static void __exit fini(void)
10854 +{
10855 +       ipt_unregister_match(&addrtype_match);
10856 +}
10857 +
10858 +module_init(init);
10859 +module_exit(fini);
10860 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connlimit.c
10861 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connlimit.c      1970-01-01 01:00:00.000000000 +0100
10862 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connlimit.c  2004-06-08 10:31:23.000000000 +0200
10863 @@ -0,0 +1,230 @@
10864 +/*
10865 + * netfilter module to limit the number of parallel tcp
10866 + * connections per IP address.
10867 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
10868 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
10869 + *             only ignore TIME_WAIT or gone connections
10870 + *
10871 + * based on ...
10872 + *
10873 + * Kernel module to match connection tracking information.
10874 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
10875 + */
10876 +#include <linux/module.h>
10877 +#include <linux/skbuff.h>
10878 +#include <linux/list.h>
10879 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10880 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
10881 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
10882 +#include <linux/netfilter_ipv4/ip_tables.h>
10883 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
10884 +
10885 +#define DEBUG 0
10886 +
10887 +MODULE_LICENSE("GPL");
10888 +
10889 +/* we'll save the tuples of all connections we care about */
10890 +struct ipt_connlimit_conn
10891 +{
10892 +        struct list_head list;
10893 +       struct ip_conntrack_tuple tuple;
10894 +};
10895 +
10896 +struct ipt_connlimit_data {
10897 +       spinlock_t lock;
10898 +       struct list_head iphash[256];
10899 +};
10900 +
10901 +static int ipt_iphash(u_int32_t addr)
10902 +{
10903 +       int hash;
10904 +
10905 +       hash  =  addr        & 0xff;
10906 +       hash ^= (addr >>  8) & 0xff;
10907 +       hash ^= (addr >> 16) & 0xff;
10908 +       hash ^= (addr >> 24) & 0xff;
10909 +       return hash;
10910 +}
10911 +
10912 +static int count_them(struct ipt_connlimit_data *data,
10913 +                     u_int32_t addr, u_int32_t mask,
10914 +                     struct ip_conntrack *ct)
10915 +{
10916 +#if DEBUG
10917 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
10918 +                                    "fin_wait", "time_wait", "close", "close_wait",
10919 +                                    "last_ack", "listen" };
10920 +#endif
10921 +       int addit = 1, matches = 0;
10922 +       struct ip_conntrack_tuple tuple;
10923 +       struct ip_conntrack_tuple_hash *found;
10924 +       struct ipt_connlimit_conn *conn;
10925 +       struct list_head *hash,*lh;
10926 +
10927 +       spin_lock(&data->lock);
10928 +       tuple = ct->tuplehash[0].tuple;
10929 +       hash = &data->iphash[ipt_iphash(addr & mask)];
10930 +
10931 +       /* check the saved connections */
10932 +       for (lh = hash->next; lh != hash; lh = lh->next) {
10933 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
10934 +               found = ip_conntrack_find_get(&conn->tuple,ct);
10935 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
10936 +                   found != NULL &&
10937 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
10938 +                       /* Just to be sure we have it only once in the list.
10939 +                          We should'nt see tuples twice unless someone hooks this
10940 +                          into a table without "-p tcp --syn" */
10941 +                       addit = 0;
10942 +               }
10943 +#if DEBUG
10944 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
10945 +                      ipt_iphash(addr & mask),
10946 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
10947 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
10948 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
10949 +#endif
10950 +               if (NULL == found) {
10951 +                       /* this one is gone */
10952 +                       lh = lh->prev;
10953 +                       list_del(lh->next);
10954 +                       kfree(conn);
10955 +                       continue;
10956 +               }
10957 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
10958 +                       /* we don't care about connections which are
10959 +                          closed already -> ditch it */
10960 +                       lh = lh->prev;
10961 +                       list_del(lh->next);
10962 +                       kfree(conn);
10963 +                       nf_conntrack_put(&found->ctrack->infos[0]);
10964 +                       continue;
10965 +               }
10966 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
10967 +                       /* same source IP address -> be counted! */
10968 +                       matches++;
10969 +               }
10970 +               nf_conntrack_put(&found->ctrack->infos[0]);
10971 +       }
10972 +       if (addit) {
10973 +               /* save the new connection in our list */
10974 +#if DEBUG
10975 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
10976 +                      ipt_iphash(addr & mask),
10977 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
10978 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
10979 +#endif
10980 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
10981 +               if (NULL == conn)
10982 +                       return -1;
10983 +               memset(conn,0,sizeof(*conn));
10984 +               INIT_LIST_HEAD(&conn->list);
10985 +               conn->tuple = tuple;
10986 +               list_add(&conn->list,hash);
10987 +               matches++;
10988 +       }
10989 +       spin_unlock(&data->lock);
10990 +       return matches;
10991 +}
10992 +
10993 +static int
10994 +match(const struct sk_buff *skb,
10995 +      const struct net_device *in,
10996 +      const struct net_device *out,
10997 +      const void *matchinfo,
10998 +      int offset,
10999 +      int *hotdrop)
11000 +{
11001 +       const struct ipt_connlimit_info *info = matchinfo;
11002 +       int connections, match;
11003 +       struct ip_conntrack *ct;
11004 +       enum ip_conntrack_info ctinfo;
11005 +
11006 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11007 +       if (NULL == ct) {
11008 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
11009 +               *hotdrop = 1;
11010 +               return 0;
11011 +       }
11012 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
11013 +       if (-1 == connections) {
11014 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
11015 +               *hotdrop = 1; /* let's free some memory :-) */
11016 +               return 0;
11017 +       }
11018 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
11019 +#if DEBUG
11020 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
11021 +              "connections=%d limit=%d match=%s\n",
11022 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
11023 +              connections, info->limit, match ? "yes" : "no");
11024 +#endif
11025 +
11026 +       return match;
11027 +}
11028 +
11029 +static int check(const char *tablename,
11030 +                const struct ipt_ip *ip,
11031 +                void *matchinfo,
11032 +                unsigned int matchsize,
11033 +                unsigned int hook_mask)
11034 +{
11035 +       struct ipt_connlimit_info *info = matchinfo;
11036 +       int i;
11037 +
11038 +       /* verify size */
11039 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
11040 +               return 0;
11041 +
11042 +       /* refuse anything but tcp */
11043 +       if (ip->proto != IPPROTO_TCP)
11044 +               return 0;
11045 +
11046 +       /* init private data */
11047 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
11048 +       spin_lock_init(&(info->data->lock));
11049 +       for (i = 0; i < 256; i++)
11050 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
11051 +       
11052 +       return 1;
11053 +}
11054 +
11055 +static void destroy(void *matchinfo, unsigned int matchinfosize)
11056 +{
11057 +       struct ipt_connlimit_info *info = matchinfo;
11058 +       struct ipt_connlimit_conn *conn;
11059 +       struct list_head *hash;
11060 +       int i;
11061 +
11062 +       /* cleanup */
11063 +       for (i = 0; i < 256; i++) {
11064 +               hash = &(info->data->iphash[i]);
11065 +               while (hash != hash->next) {
11066 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
11067 +                       list_del(hash->next);
11068 +                       kfree(conn);
11069 +               }
11070 +       }
11071 +       kfree(info->data);
11072 +}
11073 +
11074 +static struct ipt_match connlimit_match = { 
11075 +       .name = "connlimit",
11076 +       .match = &match,
11077 +       .checkentry = &check,
11078 +       .destroy = &destroy,
11079 +       .me = THIS_MODULE
11080 +};
11081 +
11082 +static int __init init(void)
11083 +{
11084 +       return ipt_register_match(&connlimit_match);
11085 +}
11086 +
11087 +static void __exit fini(void)
11088 +{
11089 +       ipt_unregister_match(&connlimit_match);
11090 +}
11091 +
11092 +module_init(init);
11093 +module_exit(fini);
11094 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connmark.c
11095 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_connmark.c       1970-01-01 01:00:00.000000000 +0100
11096 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_connmark.c   2004-06-08 10:36:58.000000000 +0200
11097 @@ -0,0 +1,81 @@
11098 +/* This kernel module matches connection mark values set by the
11099 + * CONNMARK target
11100 + *
11101 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
11102 + * by Henrik Nordstrom <hno@marasystems.com>
11103 + *
11104 + * This program is free software; you can redistribute it and/or modify
11105 + * it under the terms of the GNU General Public License as published by
11106 + * the Free Software Foundation; either version 2 of the License, or
11107 + * (at your option) any later version.
11108 + *
11109 + * This program is distributed in the hope that it will be useful,
11110 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11111 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11112 + * GNU General Public License for more details.
11113 + *
11114 + * You should have received a copy of the GNU General Public License
11115 + * along with this program; if not, write to the Free Software
11116 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
11117 + */
11118 +
11119 +#include <linux/module.h>
11120 +#include <linux/skbuff.h>
11121 +
11122 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
11123 +MODULE_DESCRIPTION("IP tables connmark match module");
11124 +MODULE_LICENSE("GPL");
11125 +
11126 +#include <linux/netfilter_ipv4/ip_tables.h>
11127 +#include <linux/netfilter_ipv4/ipt_connmark.h>
11128 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11129 +
11130 +static int
11131 +match(const struct sk_buff *skb,
11132 +      const struct net_device *in,
11133 +      const struct net_device *out,
11134 +      const void *matchinfo,
11135 +      int offset,
11136 +      int *hotdrop)
11137 +{
11138 +       const struct ipt_connmark_info *info = matchinfo;
11139 +       enum ip_conntrack_info ctinfo;
11140 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11141 +       if (!ct)
11142 +               return 0;
11143 +
11144 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
11145 +}
11146 +
11147 +static int
11148 +checkentry(const char *tablename,
11149 +          const struct ipt_ip *ip,
11150 +          void *matchinfo,
11151 +          unsigned int matchsize,
11152 +          unsigned int hook_mask)
11153 +{
11154 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
11155 +               return 0;
11156 +
11157 +       return 1;
11158 +}
11159 +
11160 +static struct ipt_match connmark_match = {
11161 +       .name = "connmark",
11162 +       .match = &match,
11163 +       .checkentry = &checkentry,
11164 +       .me = THIS_MODULE
11165 +};
11166 +
11167 +static int __init init(void)
11168 +{
11169 +       return ipt_register_match(&connmark_match);
11170 +}
11171 +
11172 +static void __exit fini(void)
11173 +{
11174 +       ipt_unregister_match(&connmark_match);
11175 +}
11176 +
11177 +module_init(init);
11178 +module_exit(fini);
11179 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_dstlimit.c
11180 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c       1970-01-01 01:00:00.000000000 +0100
11181 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_dstlimit.c   2004-06-08 10:31:34.000000000 +0200
11182 @@ -0,0 +1,690 @@
11183 +/* iptables match extension to limit the number of packets per second
11184 + * seperately for each destination.
11185 + *
11186 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
11187 + *
11188 + * $Id$
11189 + *
11190 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
11191 + *
11192 + * based on ipt_limit.c by:
11193 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
11194 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
11195 + * Rusty Russell       <rusty@rustcorp.com.au>
11196 + *
11197 + * The general idea is to create a hash table for every dstip and have a
11198 + * seperate limit counter per tuple.  This way you can do something like 'limit
11199 + * the number of syn packets for each of my internal addresses.
11200 + *
11201 + * Ideally this would just be implemented as a general 'hash' match, which would
11202 + * allow us to attach any iptables target to it's hash buckets.  But this is
11203 + * not possible in the current iptables architecture.  As always, pkttables for
11204 + * 2.7.x will help ;)
11205 + */
11206 +#include <linux/module.h>
11207 +#include <linux/skbuff.h>
11208 +#include <linux/spinlock.h>
11209 +#include <linux/random.h>
11210 +#include <linux/jhash.h>
11211 +#include <linux/slab.h>
11212 +#include <linux/vmalloc.h>
11213 +#include <linux/tcp.h>
11214 +#include <linux/udp.h>
11215 +#include <linux/proc_fs.h>
11216 +#include <linux/seq_file.h>
11217 +
11218 +#define ASSERT_READ_LOCK(x) 
11219 +#define ASSERT_WRITE_LOCK(x) 
11220 +#include <linux/netfilter_ipv4/lockhelp.h>
11221 +#include <linux/netfilter_ipv4/listhelp.h>
11222 +
11223 +#include <linux/netfilter_ipv4/ip_tables.h>
11224 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
11225 +
11226 +/* FIXME: this is just for IP_NF_ASSERRT */
11227 +#include <linux/netfilter_ipv4/ip_conntrack.h>
11228 +
11229 +#define MS2JIFFIES(x) ((x*HZ)/1000)
11230 +
11231 +MODULE_LICENSE("GPL");
11232 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
11233 +MODULE_DESCRIPTION("iptables match for limiting per destination");
11234 +
11235 +/* need to declare this at the top */
11236 +static struct proc_dir_entry *dstlimit_procdir;
11237 +static struct file_operations dl_file_ops;
11238 +
11239 +/* hash table crap */
11240 +
11241 +struct dsthash_dst {
11242 +       u_int32_t src_ip;
11243 +       u_int32_t dst_ip;
11244 +       u_int16_t port;
11245 +};
11246 +
11247 +struct dsthash_ent {
11248 +       /* static / read-only parts in the beginning */
11249 +       struct list_head list;
11250 +       struct dsthash_dst dst;
11251 +
11252 +       /* modified structure members in the end */
11253 +       unsigned long expires;          /* precalculated expiry time */
11254 +       struct {
11255 +               unsigned long prev;     /* last modification */
11256 +               u_int32_t credit;
11257 +               u_int32_t credit_cap, cost;
11258 +       } rateinfo;
11259 +};
11260 +
11261 +struct ipt_dstlimit_htable {
11262 +       struct list_head list;          /* global list of all htables */
11263 +       atomic_t use;
11264 +
11265 +       struct dstlimit_cfg cfg;        /* config */
11266 +
11267 +       /* used internally */
11268 +       spinlock_t lock;                /* lock for list_head */
11269 +       u_int32_t rnd;                  /* random seed for hash */
11270 +       struct timer_list timer;        /* timer for gc */
11271 +       atomic_t count;                 /* number entries in table */
11272 +
11273 +       /* seq_file stuff */
11274 +       struct proc_dir_entry *pde;
11275 +
11276 +       struct list_head hash[0];       /* hashtable itself */
11277 +};
11278 +
11279 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
11280 +static LIST_HEAD(dstlimit_htables);
11281 +static kmem_cache_t *dstlimit_cachep;
11282 +
11283 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
11284 +{
11285 +       return (ent->dst.dst_ip == b->dst_ip 
11286 +               && ent->dst.port == b->port
11287 +               && ent->dst.src_ip == b->src_ip);
11288 +}
11289 +
11290 +static inline u_int32_t
11291 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
11292 +{
11293 +       return (jhash_3words(dst->dst_ip, dst->port, 
11294 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
11295 +}
11296 +
11297 +static inline struct dsthash_ent *
11298 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11299 +{
11300 +       struct dsthash_ent *ent;
11301 +       u_int32_t hash = hash_dst(ht, dst);
11302 +       MUST_BE_LOCKED(&ht->lock);
11303 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
11304 +       return ent;
11305 +}
11306 +
11307 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
11308 +static struct dsthash_ent *
11309 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
11310 +{
11311 +       struct dsthash_ent *ent;
11312 +
11313 +       /* initialize hash with random val at the time we allocate
11314 +        * the first hashtable entry */
11315 +       if (!ht->rnd)
11316 +               get_random_bytes(&ht->rnd, 4);
11317 +
11318 +       if (ht->cfg.max &&
11319 +           atomic_read(&ht->count) >= ht->cfg.max) {
11320 +               /* FIXME: do something. question is what.. */
11321 +               if (net_ratelimit())
11322 +                       printk(KERN_WARNING 
11323 +                               "ipt_dstlimit: max count of %u reached\n", 
11324 +                               ht->cfg.max);
11325 +               return NULL;
11326 +       }
11327 +
11328 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
11329 +       if (!ent) {
11330 +               if (net_ratelimit())
11331 +                       printk(KERN_ERR 
11332 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
11333 +               return NULL;
11334 +       }
11335 +
11336 +       atomic_inc(&ht->count);
11337 +
11338 +       ent->dst.dst_ip = dst->dst_ip;
11339 +       ent->dst.port = dst->port;
11340 +       ent->dst.src_ip = dst->src_ip;
11341 +
11342 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
11343 +
11344 +       return ent;
11345 +}
11346 +
11347 +static inline void 
11348 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
11349 +{
11350 +       MUST_BE_LOCKED(&ht->lock);
11351 +
11352 +       list_del(&ent->list);
11353 +       kmem_cache_free(dstlimit_cachep, ent);
11354 +       atomic_dec(&ht->count);
11355 +}
11356 +static void htable_gc(unsigned long htlong);
11357 +
11358 +static int htable_create(struct ipt_dstlimit_info *minfo)
11359 +{
11360 +       int i;
11361 +       unsigned int size;
11362 +       struct ipt_dstlimit_htable *hinfo;
11363 +
11364 +       if (minfo->cfg.size)
11365 +               size = minfo->cfg.size;
11366 +       else {
11367 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
11368 +                        / sizeof(struct list_head));
11369 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
11370 +                       size = 8192;
11371 +               if (size < 16)
11372 +                       size = 16;
11373 +       }
11374 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
11375 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
11376 +                       + (sizeof(struct list_head) * size));
11377 +       if (!hinfo) {
11378 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
11379 +               return -1;
11380 +       }
11381 +       minfo->hinfo = hinfo;
11382 +
11383 +       /* copy match config into hashtable config */
11384 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
11385 +       hinfo->cfg.size = size;
11386 +       if (!hinfo->cfg.max)
11387 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
11388 +       else if (hinfo->cfg.max < hinfo->cfg.size)
11389 +               hinfo->cfg.max = hinfo->cfg.size;
11390 +
11391 +       for (i = 0; i < hinfo->cfg.size; i++)
11392 +               INIT_LIST_HEAD(&hinfo->hash[i]);
11393 +
11394 +       atomic_set(&hinfo->count, 0);
11395 +       atomic_set(&hinfo->use, 1);
11396 +       hinfo->rnd = 0;
11397 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
11398 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
11399 +       if (!hinfo->pde) {
11400 +               vfree(hinfo);
11401 +               return -1;
11402 +       }
11403 +       hinfo->pde->proc_fops = &dl_file_ops;
11404 +       hinfo->pde->data = hinfo;
11405 +
11406 +       init_timer(&hinfo->timer);
11407 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
11408 +       hinfo->timer.data = (unsigned long )hinfo;
11409 +       hinfo->timer.function = htable_gc;
11410 +       add_timer(&hinfo->timer);
11411 +
11412 +       WRITE_LOCK(&dstlimit_lock);
11413 +       list_add(&hinfo->list, &dstlimit_htables);
11414 +       WRITE_UNLOCK(&dstlimit_lock);
11415 +
11416 +       return 0;
11417 +}
11418 +
11419 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11420 +{
11421 +       return 1;
11422 +}
11423 +
11424 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
11425 +{
11426 +       return (jiffies >= he->expires);
11427 +}
11428 +
11429 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
11430 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
11431 +                                             struct dsthash_ent *he))
11432 +{
11433 +       int i;
11434 +
11435 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
11436 +
11437 +       /* lock hash table and iterate over it */
11438 +       LOCK_BH(&ht->lock);
11439 +       for (i = 0; i < ht->cfg.size; i++) {
11440 +               struct dsthash_ent *dh, *n;
11441 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
11442 +                       if ((*select)(ht, dh))
11443 +                               __dsthash_free(ht, dh);
11444 +               }
11445 +       }
11446 +       UNLOCK_BH(&ht->lock);
11447 +}
11448 +
11449 +/* hash table garbage collector, run by timer */
11450 +static void htable_gc(unsigned long htlong)
11451 +{
11452 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
11453 +
11454 +       htable_selective_cleanup(ht, select_gc);
11455 +
11456 +       /* re-add the timer accordingly */
11457 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
11458 +       add_timer(&ht->timer);
11459 +}
11460 +
11461 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
11462 +{
11463 +       /* remove timer, if it is pending */
11464 +       if (timer_pending(&hinfo->timer))
11465 +               del_timer(&hinfo->timer);
11466 +
11467 +       /* remove proc entry */
11468 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
11469 +
11470 +       htable_selective_cleanup(hinfo, select_all);
11471 +       vfree(hinfo);
11472 +}
11473 +
11474 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
11475 +{
11476 +       struct ipt_dstlimit_htable *hinfo;
11477 +
11478 +       READ_LOCK(&dstlimit_lock);
11479 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
11480 +               if (!strcmp(name, hinfo->pde->name)) {
11481 +                       atomic_inc(&hinfo->use);
11482 +                       READ_UNLOCK(&dstlimit_lock);
11483 +                       return hinfo;
11484 +               }
11485 +       }
11486 +       READ_UNLOCK(&dstlimit_lock);
11487 +
11488 +       return NULL;
11489 +}
11490 +
11491 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
11492 +{
11493 +       if (atomic_dec_and_test(&hinfo->use)) {
11494 +               WRITE_LOCK(&dstlimit_lock);
11495 +               list_del(&hinfo->list);
11496 +               WRITE_UNLOCK(&dstlimit_lock);
11497 +               htable_destroy(hinfo);
11498 +       }
11499 +}
11500 +
11501 +
11502 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
11503 + * see net/sched/sch_tbf.c in the linux source tree
11504 + */
11505 +
11506 +/* Rusty: This is my (non-mathematically-inclined) understanding of
11507 +   this algorithm.  The `average rate' in jiffies becomes your initial
11508 +   amount of credit `credit' and the most credit you can ever have
11509 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
11510 +   test, `cost'.
11511 +
11512 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
11513 +   If you get credit balance more than this, the extra credit is
11514 +   discarded.  Every time the match passes, you lose `cost' credits;
11515 +   if you don't have that many, the test fails.
11516 +
11517 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
11518 +
11519 +   To get the maximum range, we multiply by this factor (ie. you get N
11520 +   credits per jiffy).  We want to allow a rate as low as 1 per day
11521 +   (slowest userspace tool allows), which means
11522 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
11523 +*/
11524 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
11525 +
11526 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
11527 + * us the power of 2 below the theoretical max, so GCC simply does a
11528 + * shift. */
11529 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
11530 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
11531 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
11532 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
11533 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
11534 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
11535 +
11536 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
11537 +
11538 +/* Precision saver. */
11539 +static inline u_int32_t
11540 +user2credits(u_int32_t user)
11541 +{
11542 +       /* If multiplying would overflow... */
11543 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
11544 +               /* Divide first. */
11545 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
11546 +
11547 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
11548 +}
11549 +
11550 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
11551 +{
11552 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
11553 +                                       * CREDITS_PER_JIFFY;
11554 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
11555 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
11556 +}
11557 +
11558 +static int
11559 +dstlimit_match(const struct sk_buff *skb,
11560 +               const struct net_device *in,
11561 +               const struct net_device *out,
11562 +               const void *matchinfo,
11563 +               int offset,
11564 +               int *hotdrop)
11565 +{
11566 +       struct ipt_dstlimit_info *r = 
11567 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
11568 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
11569 +       unsigned long now = jiffies;
11570 +       struct dsthash_ent *dh;
11571 +       struct dsthash_dst dst;
11572 +
11573 +       memset(&dst, 0, sizeof(dst));
11574 +
11575 +       /* dest ip is always in hash */
11576 +       dst.dst_ip = skb->nh.iph->daddr;
11577 +
11578 +       /* source ip only if respective hashmode, otherwise set to
11579 +        * zero */
11580 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
11581 +               dst.src_ip = skb->nh.iph->saddr;
11582 +
11583 +       /* dest port only if respective mode */
11584 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
11585 +               u16 ports[2];
11586 +
11587 +               /* Must not be a fragment. */
11588 +               if (offset)
11589 +                       return 0;
11590 +
11591 +               /* Must be big enough to read ports (both UDP and TCP have
11592 +                  them at the start). */
11593 +               if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
11594 +                       /* We've been asked to examine this packet, and we
11595 +                          can't.  Hence, no choice but to drop. */
11596 +                       *hotdrop = 1;
11597 +                       return 0;
11598 +               }
11599 +
11600 +               switch (skb->nh.iph->protocol) {
11601 +                       struct tcphdr *th;
11602 +                       struct udphdr *uh;
11603 +               case IPPROTO_TCP:
11604 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11605 +                       dst.port = th->dest;
11606 +                       break;
11607 +               case IPPROTO_UDP:
11608 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
11609 +                       dst.port = uh->dest;
11610 +                       break;
11611 +               default:
11612 +                       break;
11613 +               }
11614 +       } 
11615 +
11616 +       LOCK_BH(&hinfo->lock);
11617 +       dh = __dsthash_find(hinfo, &dst);
11618 +       if (!dh) {
11619 +               dh = __dsthash_alloc_init(hinfo, &dst);
11620 +
11621 +               if (!dh) {
11622 +                       /* enomem... don't match == DROP */
11623 +                       if (net_ratelimit())
11624 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
11625 +                       UNLOCK_BH(&hinfo->lock);
11626 +                       return 0;
11627 +               }
11628 +
11629 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
11630 +
11631 +               dh->rateinfo.prev = jiffies;
11632 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
11633 +                                                       hinfo->cfg.burst);
11634 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
11635 +                                                       hinfo->cfg.burst);
11636 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
11637 +
11638 +               UNLOCK_BH(&hinfo->lock);
11639 +               return 1;
11640 +       }
11641 +
11642 +       /* update expiration timeout */
11643 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
11644 +
11645 +       rateinfo_recalc(dh, now);
11646 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
11647 +               /* We're underlimit. */
11648 +               dh->rateinfo.credit -= dh->rateinfo.cost;
11649 +               UNLOCK_BH(&hinfo->lock);
11650 +               return 1;
11651 +       }
11652 +
11653 +               UNLOCK_BH(&hinfo->lock);
11654 +
11655 +       /* default case: we're overlimit, thus don't match */
11656 +       return 0;
11657 +}
11658 +
11659 +static int
11660 +dstlimit_checkentry(const char *tablename,
11661 +                    const struct ipt_ip *ip,
11662 +                    void *matchinfo,
11663 +                    unsigned int matchsize,
11664 +                    unsigned int hook_mask)
11665 +{
11666 +       struct ipt_dstlimit_info *r = matchinfo;
11667 +
11668 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
11669 +               return 0;
11670 +
11671 +       /* Check for overflow. */
11672 +       if (r->cfg.burst == 0
11673 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
11674 +                                       user2credits(r->cfg.avg)) {
11675 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
11676 +                      r->cfg.avg, r->cfg.burst);
11677 +               return 0;
11678 +       }
11679 +
11680 +       if (r->cfg.mode == 0 
11681 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
11682 +                         |IPT_DSTLIMIT_HASH_DIP
11683 +                         |IPT_DSTLIMIT_HASH_SIP))
11684 +               return 0;
11685 +
11686 +       if (!r->cfg.gc_interval)
11687 +               return 0;
11688 +       
11689 +       if (!r->cfg.expire)
11690 +               return 0;
11691 +
11692 +       r->hinfo = htable_find_get(r->name);
11693 +       if (!r->hinfo && (htable_create(r) != 0)) {
11694 +               return 0;
11695 +       }
11696 +
11697 +       /* Ugly hack: For SMP, we only want to use one set */
11698 +       r->u.master = r;
11699 +
11700 +       return 1;
11701 +}
11702 +
11703 +static void
11704 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
11705 +{
11706 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
11707 +
11708 +       htable_put(r->hinfo);
11709 +}
11710 +
11711 +static struct ipt_match ipt_dstlimit = { 
11712 +       .list = { .prev = NULL, .next = NULL }, 
11713 +       .name = "dstlimit", 
11714 +       .match = dstlimit_match, 
11715 +       .checkentry = dstlimit_checkentry, 
11716 +       .destroy = dstlimit_destroy,
11717 +       .me = THIS_MODULE 
11718 +};
11719 +
11720 +/* PROC stuff */
11721 +
11722 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
11723 +{
11724 +       struct proc_dir_entry *pde = s->private;
11725 +       struct ipt_dstlimit_htable *htable = pde->data;
11726 +       unsigned int *bucket;
11727 +
11728 +       LOCK_BH(&htable->lock);
11729 +       if (*pos >= htable->cfg.size)
11730 +               return NULL;
11731 +
11732 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
11733 +       if (!bucket)
11734 +               return ERR_PTR(-ENOMEM);
11735 +
11736 +       *bucket = *pos;
11737 +       return bucket;
11738 +}
11739 +
11740 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
11741 +{
11742 +       struct proc_dir_entry *pde = s->private;
11743 +       struct ipt_dstlimit_htable *htable = pde->data;
11744 +       unsigned int *bucket = (unsigned int *)v;
11745 +
11746 +       *pos = ++(*bucket);
11747 +       if (*pos >= htable->cfg.size) {
11748 +               kfree(v);
11749 +               return NULL;
11750 +       }
11751 +       return bucket;
11752 +}
11753 +
11754 +static void dl_seq_stop(struct seq_file *s, void *v)
11755 +{
11756 +       struct proc_dir_entry *pde = s->private;
11757 +       struct ipt_dstlimit_htable *htable = pde->data;
11758 +       unsigned int *bucket = (unsigned int *)v;
11759 +
11760 +       kfree(bucket);
11761 +
11762 +       UNLOCK_BH(&htable->lock);
11763 +}
11764 +
11765 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
11766 +{
11767 +       /* recalculate to show accurate numbers */
11768 +       rateinfo_recalc(ent, jiffies);
11769 +
11770 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
11771 +                       (ent->expires - jiffies)/HZ,
11772 +                       NIPQUAD(ent->dst.src_ip),
11773 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
11774 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
11775 +                       ent->rateinfo.cost);
11776 +}
11777 +
11778 +static int dl_seq_show(struct seq_file *s, void *v)
11779 +{
11780 +       struct proc_dir_entry *pde = s->private;
11781 +       struct ipt_dstlimit_htable *htable = pde->data;
11782 +       unsigned int *bucket = (unsigned int *)v;
11783 +
11784 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
11785 +                     struct dsthash_ent *, s)) {
11786 +               /* buffer was filled and unable to print that tuple */
11787 +               return 1;
11788 +       }
11789 +       return 0;
11790 +}
11791 +
11792 +static struct seq_operations dl_seq_ops = {
11793 +       .start = dl_seq_start,
11794 +       .next  = dl_seq_next,
11795 +       .stop  = dl_seq_stop,
11796 +       .show  = dl_seq_show
11797 +};
11798 +
11799 +static int dl_proc_open(struct inode *inode, struct file *file)
11800 +{
11801 +       int ret = seq_open(file, &dl_seq_ops);
11802 +
11803 +       if (!ret) {
11804 +               struct seq_file *sf = file->private_data;
11805 +               sf->private = PDE(inode);
11806 +       }
11807 +       return ret;
11808 +}
11809 +
11810 +static struct file_operations dl_file_ops = {
11811 +       .owner   = THIS_MODULE,
11812 +       .open    = dl_proc_open,
11813 +       .read    = seq_read,
11814 +       .llseek  = seq_lseek,
11815 +       .release = seq_release
11816 +};
11817 +
11818 +static int init_or_fini(int fini)
11819 +{
11820 +       int ret = 0;
11821 +
11822 +       if (fini)
11823 +               goto cleanup;
11824 +
11825 +       if (ipt_register_match(&ipt_dstlimit)) {
11826 +               ret = -EINVAL;
11827 +               goto cleanup_nothing;
11828 +       }
11829 +
11830 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
11831 +        * quite small ? */
11832 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
11833 +                                           sizeof(struct dsthash_ent), 0,
11834 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
11835 +       if (!dstlimit_cachep) {
11836 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
11837 +               ret = -ENOMEM;
11838 +               goto cleanup_unreg_match;
11839 +       }
11840 +
11841 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
11842 +       if (!dstlimit_procdir) {
11843 +               printk(KERN_ERR "Unable to create proc dir entry\n");
11844 +               ret = -ENOMEM;
11845 +               goto cleanup_free_slab;
11846 +       }
11847 +
11848 +       return ret;
11849 +
11850 +cleanup:
11851 +       remove_proc_entry("ipt_dstlimit", proc_net);
11852 +cleanup_free_slab:
11853 +       kmem_cache_destroy(dstlimit_cachep);
11854 +cleanup_unreg_match:
11855 +       ipt_unregister_match(&ipt_dstlimit);
11856 +cleanup_nothing:
11857 +       return ret;
11858 +       
11859 +}
11860 +
11861 +static int __init init(void)
11862 +{
11863 +       return init_or_fini(0);
11864 +}
11865 +
11866 +static void __exit fini(void)
11867 +{
11868 +       init_or_fini(1);
11869 +}
11870 +
11871 +module_init(init);
11872 +module_exit(fini);
11873 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_fuzzy.c
11874 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c  1970-01-01 01:00:00.000000000 +0100
11875 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_fuzzy.c      2004-06-08 10:31:37.000000000 +0200
11876 @@ -0,0 +1,185 @@
11877 +/*
11878 + *  This module implements a simple TSK FLC 
11879 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
11880 + * to limit , in an adaptive and flexible way , the packet rate crossing 
11881 + * a given stream . It serves as an initial and very simple (but effective)
11882 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
11883 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
11884 + * into our code in a precise , adaptive and efficient manner. 
11885 + *  The goal is very similar to that of "limit" match , but using techniques of
11886 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
11887 + * avoiding over and undershoots - and stuff like that .
11888 + *
11889 + *
11890 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
11891 + * 2002-08-17  : Changed to eliminate floating point operations .
11892 + * 2002-08-23  : Coding style changes .
11893 +*/
11894 +
11895 +#include <linux/module.h>
11896 +#include <linux/skbuff.h>
11897 +#include <linux/ip.h>
11898 +#include <linux/random.h>
11899 +#include <net/tcp.h>
11900 +#include <linux/spinlock.h>
11901 +#include <linux/netfilter_ipv4/ip_tables.h>
11902 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
11903 +
11904 +/*
11905 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
11906 + Expressed in percentage
11907 +*/
11908 +
11909 +#define PAR_LOW                1/100
11910 +#define PAR_HIGH       1
11911 +
11912 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
11913 +
11914 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
11915 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
11916 +MODULE_LICENSE("GPL");
11917 +
11918 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11919 +{
11920 +       if (tx >= maxi)
11921 +               return 100;
11922 +
11923 +       if (tx <= mini)
11924 +               return 0;
11925 +
11926 +       return ( (100*(tx-mini)) / (maxi-mini) );
11927 +}
11928 +
11929 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11930 +{
11931 +       if (tx <= mini)
11932 +               return 100;
11933 +
11934 +       if (tx >= maxi)
11935 +               return 0;
11936 +
11937 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
11938 +}
11939 +
11940 +static int
11941 +ipt_fuzzy_match(const struct sk_buff *pskb,
11942 +              const struct net_device *in,
11943 +              const struct net_device *out,
11944 +              const void *matchinfo,
11945 +              int offset,
11946 +              int *hotdrop)
11947 +{
11948 +       /* From userspace */
11949 +       
11950 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
11951 +
11952 +       u_int8_t random_number;
11953 +       unsigned long amount;
11954 +       u_int8_t howhigh, howlow;
11955 +       
11956 +
11957 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
11958 +
11959 +       info->bytes_total += pskb->len;
11960 +       info->packets_total++;
11961 +
11962 +       info->present_time = jiffies;
11963 +       
11964 +       if (info->present_time >= info->previous_time)
11965 +               amount = info->present_time - info->previous_time;
11966 +       else { 
11967 +               /* There was a transition : I choose to re-sample 
11968 +                  and keep the old acceptance rate...
11969 +               */
11970 +
11971 +               amount = 0;
11972 +               info->previous_time = info->present_time;
11973 +               info->bytes_total = info->packets_total = 0;
11974 +       };
11975 +       
11976 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
11977 +       {
11978 +
11979 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
11980 +                                       / amount );
11981 +
11982 +               info->previous_time = info->present_time;
11983 +               info->bytes_total = info->packets_total = 0;
11984 +
11985 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
11986 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
11987 +
11988 +               info->acceptance_rate = (u_int8_t) \
11989 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
11990 +
11991 +               /* In fact , the above defuzzification would require a denominator
11992 +                  proportional to (howhigh+howlow) but , in this particular case ,
11993 +                  that expression is constant .
11994 +                  An imediate consequence is that it isn't necessary to call 
11995 +                  both mf_high and mf_low - but to keep things understandable ,
11996 +                  I did so .  */ 
11997 +
11998 +       }
11999 +       
12000 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
12001 +
12002 +
12003 +       if ( info->acceptance_rate < 100 )
12004 +       {                
12005 +               get_random_bytes((void *)(&random_number), 1);
12006 +
12007 +               /*  If within the acceptance , it can pass => don't match */
12008 +               if (random_number <= (255 * info->acceptance_rate) / 100)
12009 +                       return 0;
12010 +               else
12011 +                       return 1; /* It can't pass ( It matches ) */
12012 +       } ;
12013 +
12014 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
12015 +       
12016 +}
12017 +
12018 +static int
12019 +ipt_fuzzy_checkentry(const char *tablename,
12020 +                  const struct ipt_ip *e,
12021 +                  void *matchinfo,
12022 +                  unsigned int matchsize,
12023 +                  unsigned int hook_mask)
12024 +{
12025 +       
12026 +       const struct ipt_fuzzy_info *info = matchinfo;
12027 +
12028 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
12029 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
12030 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
12031 +               return 0;
12032 +       }
12033 +
12034 +       if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
12035 +           || (info->minimum_rate >= info->maximum_rate )) {
12036 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
12037 +               return 0;
12038 +       }
12039 +
12040 +       return 1;
12041 +}
12042 +
12043 +static struct ipt_match ipt_fuzzy_reg = { 
12044 +       .name = "fuzzy",
12045 +       .match = ipt_fuzzy_match,
12046 +       .checkentry = ipt_fuzzy_checkentry,
12047 +       .me = THIS_MODULE
12048 +};
12049 +
12050 +static int __init init(void)
12051 +{
12052 +       return ipt_register_match(&ipt_fuzzy_reg);
12053 +}
12054 +
12055 +static void __exit fini(void)
12056 +{
12057 +       ipt_unregister_match(&ipt_fuzzy_reg);
12058 +}
12059 +
12060 +module_init(init);
12061 +module_exit(fini);
12062 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_helper.c
12063 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-06-07 21:14:55.000000000 +0200
12064 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_helper.c     2004-06-08 10:42:23.000000000 +0200
12065 @@ -41,17 +41,17 @@
12066         struct ip_conntrack_expect *exp;
12067         struct ip_conntrack *ct;
12068         enum ip_conntrack_info ctinfo;
12069 -       int ret = 0;
12070 +       int ret = info->invert;
12071         
12072         ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
12073         if (!ct) {
12074                 DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
12075 -               return 0;
12076 +               return ret;
12077         }
12078  
12079         if (!ct->master) {
12080                 DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
12081 -               return 0;
12082 +               return ret;
12083         }
12084  
12085         exp = ct->master;
12086 @@ -71,8 +71,11 @@
12087         DEBUGP("master's name = %s , info->name = %s\n", 
12088                 exp->expectant->helper->name, info->name);
12089  
12090 -       ret = !strncmp(exp->expectant->helper->name, info->name, 
12091 -                      strlen(exp->expectant->helper->name)) ^ info->invert;
12092 +       if (info->name[0] == '\0')
12093 +               ret ^= 1;
12094 +       else
12095 +               ret ^= !strncmp(exp->expectant->helper->name, info->name, 
12096 +                               strlen(exp->expectant->helper->name));
12097  out_unlock:
12098         READ_UNLOCK(&ip_conntrack_lock);
12099         return ret;
12100 @@ -92,10 +95,6 @@
12101         if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
12102                 return 0;
12103  
12104 -       /* verify that we actually should match anything */
12105 -       if ( strlen(info->name) == 0 )
12106 -               return 0;
12107 -       
12108         return 1;
12109  }
12110  
12111 @@ -108,7 +107,6 @@
12112  
12113  static int __init init(void)
12114  {
12115 -       need_ip_conntrack();
12116         return ipt_register_match(&helper_match);
12117  }
12118  
12119 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ipv4options.c
12120 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c    1970-01-01 01:00:00.000000000 +0100
12121 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_ipv4options.c        2004-06-08 10:31:39.000000000 +0200
12122 @@ -0,0 +1,172 @@
12123 +/*
12124 +  This is a module which is used to match ipv4 options.
12125 +  This file is distributed under the terms of the GNU General Public
12126 +  License (GPL). Copies of the GPL can be obtained from:
12127 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
12128 +
12129 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
12130 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
12131 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
12132 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
12133 +  19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
12134 +*/
12135 +
12136 +#include <linux/module.h>
12137 +#include <linux/skbuff.h>
12138 +#include <net/ip.h>
12139 +
12140 +#include <linux/netfilter_ipv4/ip_tables.h>
12141 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
12142 +
12143 +MODULE_LICENSE("GPL");
12144 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12145 +
12146 +static int
12147 +match(const struct sk_buff *skb,
12148 +      const struct net_device *in,
12149 +      const struct net_device *out,
12150 +      const void *matchinfo,
12151 +      int offset,
12152 +      int *hotdrop)
12153 +{
12154 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
12155 +       const struct iphdr *iph = skb->nh.iph;
12156 +       const struct ip_options *opt;
12157 +
12158 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
12159 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
12160 +
12161 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
12162 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12163 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12164 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12165 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12166 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
12167 +                       return 0;
12168 +               return 1;
12169 +       }
12170 +       else {
12171 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
12172 +                       /* there are options, and we don't need to care which one */
12173 +                       return 1;
12174 +               else {
12175 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
12176 +                               /* there are options but we don't want any ! */
12177 +                               return 0;
12178 +               }
12179 +       }
12180 +
12181 +       opt = &(IPCB(skb)->opt);
12182 +
12183 +       /* source routing */
12184 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
12185 +               if (!((opt->srr) & (opt->is_strictroute)))
12186 +                       return 0;
12187 +       }
12188 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
12189 +               if (!((opt->srr) & (!opt->is_strictroute)))
12190 +                       return 0;
12191 +       }
12192 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
12193 +               if (opt->srr)
12194 +                       return 0;
12195 +       }
12196 +       /* record route */
12197 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
12198 +               if (!opt->rr)
12199 +                       return 0;
12200 +       }
12201 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
12202 +               if (opt->rr)
12203 +                       return 0;
12204 +       }
12205 +       /* timestamp */
12206 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
12207 +               if (!opt->ts)
12208 +                       return 0;
12209 +       }
12210 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
12211 +               if (opt->ts)
12212 +                       return 0;
12213 +       }
12214 +       /* router-alert option  */
12215 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
12216 +               if (!opt->router_alert)
12217 +                       return 0;
12218 +       }
12219 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
12220 +               if (opt->router_alert)
12221 +                       return 0;
12222 +       }
12223 +
12224 +       /* we match ! */
12225 +       return 1;
12226 +}
12227 +
12228 +static int
12229 +checkentry(const char *tablename,
12230 +          const struct ipt_ip *ip,
12231 +          void *matchinfo,
12232 +          unsigned int matchsize,
12233 +          unsigned int hook_mask)
12234 +{
12235 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
12236 +       /* Check the size */
12237 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
12238 +               return 0;
12239 +       /* Now check the coherence of the data ... */
12240 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
12241 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
12242 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
12243 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
12244 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
12245 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
12246 +               return 0; /* opposites */
12247 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
12248 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
12249 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12250 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
12251 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
12252 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
12253 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
12254 +               return 0; /* opposites */
12255 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
12256 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
12257 +               return 0; /* cannot match in the same time loose and strict source routing */
12258 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
12259 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
12260 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
12261 +               return 0; /* opposites */
12262 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
12263 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
12264 +               return 0; /* opposites */
12265 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
12266 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
12267 +               return 0; /* opposites */
12268 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
12269 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
12270 +               return 0; /* opposites */
12271 +
12272 +       /* everything looks ok. */
12273 +       return 1;
12274 +}
12275 +
12276 +static struct ipt_match ipv4options_match = { 
12277 +       .name = "ipv4options",
12278 +       .match = match,
12279 +       .checkentry = checkentry,
12280 +       .me = THIS_MODULE
12281 +};
12282 +
12283 +static int __init init(void)
12284 +{
12285 +       return ipt_register_match(&ipv4options_match);
12286 +}
12287 +
12288 +static void __exit fini(void)
12289 +{
12290 +       ipt_unregister_match(&ipv4options_match);
12291 +}
12292 +
12293 +module_init(init);
12294 +module_exit(fini);
12295 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_mport.c
12296 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_mport.c  1970-01-01 01:00:00.000000000 +0100
12297 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_mport.c      2004-06-08 10:31:40.000000000 +0200
12298 @@ -0,0 +1,116 @@
12299 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
12300 +   the same place so we can treat them as equal. */
12301 +#include <linux/module.h>
12302 +#include <linux/types.h>
12303 +#include <linux/udp.h>
12304 +#include <linux/skbuff.h>
12305 +
12306 +#include <linux/netfilter_ipv4/ipt_mport.h>
12307 +#include <linux/netfilter_ipv4/ip_tables.h>
12308 +
12309 +MODULE_LICENSE("GPL");
12310 +
12311 +#if 0
12312 +#define duprintf(format, args...) printk(format , ## args)
12313 +#else
12314 +#define duprintf(format, args...)
12315 +#endif
12316 +
12317 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
12318 +static inline int
12319 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
12320 +{
12321 +       unsigned int i;
12322 +        unsigned int m;
12323 +        u_int16_t pflags = minfo->pflags;
12324 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
12325 +                u_int16_t s, e;
12326 +
12327 +                if (pflags & m
12328 +                    && minfo->ports[i] == 65535)
12329 +                        return 0;
12330 +
12331 +                s = minfo->ports[i];
12332 +
12333 +                if (pflags & m) {
12334 +                        e = minfo->ports[++i];
12335 +                        m <<= 1;
12336 +                } else
12337 +                        e = s;
12338 +
12339 +                if (minfo->flags & IPT_MPORT_SOURCE
12340 +                    && src >= s && src <= e)
12341 +                        return 1;
12342 +
12343 +               if (minfo->flags & IPT_MPORT_DESTINATION
12344 +                   && dst >= s && dst <= e)
12345 +                       return 1;
12346 +       }
12347 +
12348 +       return 0;
12349 +}
12350 +
12351 +static int
12352 +match(const struct sk_buff *skb,
12353 +      const struct net_device *in,
12354 +      const struct net_device *out,
12355 +      const void *matchinfo,
12356 +      int offset,
12357 +      int *hotdrop)
12358 +{
12359 +       u16 ports[2];
12360 +       const struct ipt_mport *minfo = matchinfo;
12361 +
12362 +       if (offset)
12363 +               return 0;
12364 +
12365 +       /* Must be big enough to read ports (both UDP and TCP have
12366 +           them at the start). */
12367 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
12368 +               /* We've been asked to examine this packet, and we
12369 +                  can't.  Hence, no choice but to drop. */
12370 +                       duprintf("ipt_multiport:"
12371 +                                " Dropping evil offset=0 tinygram.\n");
12372 +                       *hotdrop = 1;
12373 +                       return 0;
12374 +       }
12375 +
12376 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
12377 +}
12378 +
12379 +/* Called when user tries to insert an entry of this type. */
12380 +static int
12381 +checkentry(const char *tablename,
12382 +          const struct ipt_ip *ip,
12383 +          void *matchinfo,
12384 +          unsigned int matchsize,
12385 +          unsigned int hook_mask)
12386 +{
12387 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
12388 +               return 0;
12389 +
12390 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
12391 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
12392 +               && !(ip->invflags & IPT_INV_PROTO)
12393 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
12394 +}
12395 +
12396 +static struct ipt_match mport_match = { 
12397 +       .name = "mport",
12398 +       .match = &match,
12399 +       .checkentry = &checkentry,
12400 +       .me = THIS_MODULE
12401 +};
12402 +
12403 +static int __init init(void)
12404 +{
12405 +       return ipt_register_match(&mport_match);
12406 +}
12407 +
12408 +static void __exit fini(void)
12409 +{
12410 +       ipt_unregister_match(&mport_match);
12411 +}
12412 +
12413 +module_init(init);
12414 +module_exit(fini);
12415 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_nth.c
12416 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_nth.c    1970-01-01 01:00:00.000000000 +0100
12417 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_nth.c        2004-06-08 10:31:42.000000000 +0200
12418 @@ -0,0 +1,166 @@
12419 +/*
12420 +  This is a module which is used for match support for every Nth packet
12421 +  This file is distributed under the terms of the GNU General Public
12422 +  License (GPL). Copies of the GPL can be obtained from:
12423 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
12424 +
12425 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
12426 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
12427 +        * added support for multiple counters
12428 +        * added support for matching on individual packets
12429 +          in the counter cycle
12430 +  2004-02-19 Harald Welte <laforge@netfilter.org>
12431 +       * port to 2.6.x
12432 +
12433 +*/
12434 +
12435 +#include <linux/module.h>
12436 +#include <linux/skbuff.h>
12437 +#include <linux/ip.h>
12438 +#include <net/tcp.h>
12439 +#include <linux/spinlock.h>
12440 +#include <linux/netfilter_ipv4/ip_tables.h>
12441 +#include <linux/netfilter_ipv4/ipt_nth.h>
12442 +
12443 +MODULE_LICENSE("GPL");
12444 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
12445 +
12446 +/*
12447 + * State information.
12448 + */
12449 +struct state {
12450 +       spinlock_t lock;
12451 +       u_int16_t number;
12452 +};
12453 +
12454 +static struct state states[IPT_NTH_NUM_COUNTERS];
12455 +
12456 +static int
12457 +ipt_nth_match(const struct sk_buff *pskb,
12458 +             const struct net_device *in,
12459 +             const struct net_device *out,
12460 +             const void *matchinfo,
12461 +             int offset,
12462 +             int *hotdrop)
12463 +{
12464 +       /* Parameters from userspace */
12465 +       const struct ipt_nth_info *info = matchinfo;
12466 +        unsigned counter = info->counter;
12467 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
12468 +       {
12469 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12470 +               return 0;
12471 +        };
12472 +
12473 +        spin_lock(&states[counter].lock);
12474 +
12475 +        /* Are we matching every nth packet?*/
12476 +        if (info->packet == 0xFF)
12477 +        {
12478 +               /* We're matching every nth packet and only every nth packet*/
12479 +               /* Do we match or invert match? */
12480 +               if (info->not == 0)
12481 +               {
12482 +                       if (states[counter].number == 0)
12483 +                       {
12484 +                               ++states[counter].number;
12485 +                               goto match;
12486 +                       }
12487 +                       if (states[counter].number >= info->every)
12488 +                               states[counter].number = 0; /* reset the counter */
12489 +                       else
12490 +                               ++states[counter].number;
12491 +                       goto dontmatch;
12492 +               }
12493 +               else
12494 +               {
12495 +                       if (states[counter].number == 0)
12496 +                       {
12497 +                               ++states[counter].number;
12498 +                               goto dontmatch;
12499 +                       }
12500 +                       if (states[counter].number >= info->every)
12501 +                               states[counter].number = 0;
12502 +                       else
12503 +                               ++states[counter].number;
12504 +                       goto match;
12505 +               }
12506 +        }
12507 +        else
12508 +        {
12509 +               /* We're using the --packet, so there must be a rule for every value */
12510 +               if (states[counter].number == info->packet)
12511 +               {
12512 +                       /* only increment the counter when a match happens */
12513 +                       if (states[counter].number >= info->every)
12514 +                               states[counter].number = 0; /* reset the counter */
12515 +                       else
12516 +                               ++states[counter].number;
12517 +                       goto match;
12518 +               }
12519 +               else
12520 +                       goto dontmatch;
12521 +       }
12522 +
12523 + dontmatch:
12524 +       /* don't match */
12525 +       spin_unlock(&states[counter].lock);
12526 +       return 0;
12527 +
12528 + match:
12529 +       spin_unlock(&states[counter].lock);
12530 +       return 1;
12531 +}
12532 +
12533 +static int
12534 +ipt_nth_checkentry(const char *tablename,
12535 +                  const struct ipt_ip *e,
12536 +                  void *matchinfo,
12537 +                  unsigned int matchsize,
12538 +                  unsigned int hook_mask)
12539 +{
12540 +       /* Parameters from userspace */
12541 +       const struct ipt_nth_info *info = matchinfo;
12542 +        unsigned counter = info->counter;
12543 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
12544 +       {
12545 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
12546 +                       return 0;
12547 +               };
12548 +
12549 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
12550 +               printk("nth: matchsize %u != %u\n", matchsize,
12551 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
12552 +               return 0;
12553 +       }
12554 +
12555 +       states[counter].number = info->startat;
12556 +
12557 +       return 1;
12558 +}
12559 +
12560 +static struct ipt_match ipt_nth_reg = { 
12561 +       .name = "nth",
12562 +       .match = ipt_nth_match,
12563 +       .checkentry = ipt_nth_checkentry,
12564 +       .me = THIS_MODULE
12565 +};
12566 +
12567 +static int __init init(void)
12568 +{
12569 +       unsigned counter;
12570 +
12571 +       memset(&states, 0, sizeof(states));
12572 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
12573 +               spin_lock_init(&(states[counter].lock));
12574 +
12575 +       return ipt_register_match(&ipt_nth_reg);
12576 +}
12577 +
12578 +static void __exit fini(void)
12579 +{
12580 +       ipt_unregister_match(&ipt_nth_reg);
12581 +}
12582 +
12583 +module_init(init);
12584 +module_exit(fini);
12585 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_osf.c
12586 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_osf.c    1970-01-01 01:00:00.000000000 +0100
12587 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_osf.c        2004-06-08 10:31:44.000000000 +0200
12588 @@ -0,0 +1,865 @@
12589 +/*
12590 + * ipt_osf.c
12591 + *
12592 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
12593 + *
12594 + *
12595 + * This program is free software; you can redistribute it and/or modify
12596 + * it under the terms of the GNU General Public License as published by
12597 + * the Free Software Foundation; either version 2 of the License, or
12598 + * (at your option) any later version.
12599 + *
12600 + * This program is distributed in the hope that it will be useful,
12601 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12602 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12603 + * GNU General Public License for more details.
12604 + *
12605 + * You should have received a copy of the GNU General Public License
12606 + * along with this program; if not, write to the Free Software
12607 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12608 + */
12609 +
12610 +/*
12611 + * OS fingerprint matching module.
12612 + * It simply compares various parameters from SYN packet with
12613 + * some hardcoded ones.
12614 + *
12615 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
12616 + * for his p0f.
12617 + */
12618 +
12619 +#include <linux/config.h>
12620 +#include <linux/kernel.h>
12621 +#include <linux/types.h>
12622 +#include <linux/string.h>
12623 +#include <linux/smp.h>
12624 +#include <linux/module.h>
12625 +#include <linux/skbuff.h>
12626 +#include <linux/file.h>
12627 +#include <linux/ip.h>
12628 +#include <linux/proc_fs.h>
12629 +#include <linux/fs.h>
12630 +#include <linux/slab.h>
12631 +#include <linux/spinlock.h>
12632 +#include <linux/ctype.h>
12633 +#include <linux/list.h>
12634 +#include <linux/if.h>
12635 +
12636 +#include <net/sock.h>
12637 +#include <net/ip.h>
12638 +
12639 +#include <linux/netfilter_ipv4/ip_tables.h>
12640 +
12641 +#include <linux/netfilter_ipv4/ipt_osf.h>
12642 +
12643 +#define OSF_DEBUG
12644 +
12645 +#ifdef OSF_DEBUG
12646 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
12647 +#define loga(x...)             printk(x)
12648 +#else
12649 +#define log(x...)              do {} while(0)
12650 +#define loga(x...)             do {} while(0)
12651 +#endif
12652 +
12653 +#define FMATCH_WRONG           0
12654 +#define FMATCH_OK              1
12655 +#define FMATCH_OPT_WRONG       2
12656 +
12657 +#define OPTDEL                 ','
12658 +#define OSFPDEL                ':'
12659 +#define MAXOPTSTRLEN           128
12660 +#define OSFFLUSH               "FLUSH"
12661 +
12662 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
12663 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
12664 +static struct list_head        finger_list;    
12665 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
12666 +                     const void *, int, 
12667 +                     const void *, u_int16_t, 
12668 +                     int *);
12669 +static int checkentry(const char *, const struct ipt_ip *, void *,
12670 +                          unsigned int, unsigned int);
12671 +
12672 +static unsigned long seq, ipt_osf_groups = 1;
12673 +static struct sock *nts;
12674 +
12675 +static struct ipt_match osf_match = 
12676 +{ 
12677 +       { NULL, NULL }, 
12678 +       "osf", 
12679 +       &match, 
12680 +       &checkentry, 
12681 +       NULL, 
12682 +       THIS_MODULE 
12683 +};
12684 +
12685 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
12686 +{
12687 +       unsigned int size;
12688 +       struct sk_buff *skb;
12689 +       struct ipt_osf_nlmsg *data;
12690 +       struct nlmsghdr *nlh;
12691 +
12692 +       size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
12693 +
12694 +       skb = alloc_skb(size, GFP_ATOMIC);
12695 +       if (!skb)
12696 +       {
12697 +               log("skb_alloc() failed.\n");
12698 +               return;
12699 +       }
12700 +       
12701 +       nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
12702 +       
12703 +       data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
12704 +
12705 +       memcpy(&data->f, f, sizeof(struct osf_finger));
12706 +       memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
12707 +       memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
12708 +
12709 +       NETLINK_CB(skb).dst_groups = ipt_osf_groups;
12710 +       netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
12711 +
12712 +nlmsg_failure:
12713 +       return;
12714 +}
12715 +
12716 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
12717 +{
12718 +       struct iphdr *ip = skb->nh.iph;
12719 +
12720 +       if (flags & IPT_OSF_SMART)
12721 +       {
12722 +               struct in_device *in_dev = in_dev_get(skb->dev);
12723 +
12724 +               for_ifa(in_dev)
12725 +               {
12726 +                       if (inet_ifa_match(ip->saddr, ifa))
12727 +                       {
12728 +                               in_dev_put(in_dev);
12729 +                               return (ip->ttl == f_ttl);
12730 +                       }
12731 +               }
12732 +               endfor_ifa(in_dev);
12733 +               
12734 +               in_dev_put(in_dev);
12735 +               return (ip->ttl <= f_ttl);
12736 +       }
12737 +       else
12738 +               return (ip->ttl == f_ttl);
12739 +}
12740 +
12741 +static int
12742 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
12743 +      const void *matchinfo, int offset,
12744 +      const void *hdr, u_int16_t datalen,
12745 +      int *hotdrop)
12746 +{
12747 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
12748 +       struct iphdr *ip = skb->nh.iph;
12749 +       struct tcphdr *tcp;
12750 +       int fmatch = FMATCH_WRONG, fcount = 0;
12751 +       unsigned long totlen, optsize = 0, window;
12752 +       unsigned char df, *optp = NULL, *_optp = NULL;
12753 +       char check_WSS = 0;
12754 +       struct list_head *ent;
12755 +       struct osf_finger *f;
12756 +
12757 +       if (!ip || !info)
12758 +               return 0;
12759 +                               
12760 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
12761 +
12762 +       if (!tcp->syn)
12763 +               return 0;
12764 +       
12765 +       totlen = ntohs(ip->tot_len);
12766 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
12767 +       window = ntohs(tcp->window);
12768 +       
12769 +       if (tcp->doff*4 > sizeof(struct tcphdr))
12770 +       {
12771 +               _optp = optp = (char *)(tcp+1);
12772 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
12773 +       }
12774 +
12775 +       
12776 +       /* Actually we can create hash/table of all genres and search
12777 +        * only in appropriate part, but here is initial variant,
12778 +        * so will use slow path.
12779 +        */
12780 +       read_lock(&osf_lock);
12781 +       list_for_each(ent, &finger_list)
12782 +       {
12783 +               f = list_entry(ent, struct osf_finger, flist);
12784 +       
12785 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
12786 +                       continue;
12787 +
12788 +               optp = _optp;
12789 +               fmatch = FMATCH_WRONG;
12790 +
12791 +               if (totlen == f->ss && df == f->df && 
12792 +                       smart_dec(skb, info->flags, f->ttl))
12793 +               {
12794 +                       unsigned long foptsize;
12795 +                       int optnum;
12796 +                       unsigned short mss = 0;
12797 +
12798 +                       check_WSS = 0;
12799 +
12800 +                       switch (f->wss.wc)
12801 +                       {
12802 +                               case 0:   check_WSS = 0; break;
12803 +                               case 'S': check_WSS = 1; break;
12804 +                               case 'T': check_WSS = 2; break;
12805 +                               case '%': check_WSS = 3; break;
12806 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
12807 +                                                        f->wss.wc, f->genre, f->details);
12808 +                                        check_WSS = 4;
12809 +                                        break;
12810 +                       }
12811 +                       if (check_WSS == 4)
12812 +                               continue;
12813 +
12814 +                       /* Check options */
12815 +
12816 +                       foptsize = 0;
12817 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
12818 +                               foptsize += f->opt[optnum].length;
12819 +
12820 +                               
12821 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
12822 +                               continue;
12823 +
12824 +                       if (!optp)
12825 +                       {
12826 +                               fmatch = FMATCH_OK;
12827 +                               loga("\tYEP : matching without options.\n");
12828 +                               if ((info->flags & IPT_OSF_LOG) && 
12829 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
12830 +                                       break;
12831 +                               else
12832 +                                       continue;
12833 +                       }
12834 +                       
12835 +
12836 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
12837 +                       {
12838 +                               if (f->opt[optnum].kind == (*optp)) 
12839 +                               {
12840 +                                       unsigned char len = f->opt[optnum].length;
12841 +                                       unsigned char *optend = optp + len;
12842 +                                       int loop_cont = 0;
12843 +
12844 +                                       fmatch = FMATCH_OK;
12845 +
12846 +
12847 +                                       switch (*optp)
12848 +                                       {
12849 +                                               case OSFOPT_MSS:
12850 +                                                       mss = ntohs(*(unsigned short *)(optp+2));
12851 +                                                       break;
12852 +                                               case OSFOPT_TS:
12853 +                                                       loop_cont = 1;
12854 +                                                       break;
12855 +                                       }
12856 +                                       
12857 +                                       if (loop_cont)
12858 +                                       {
12859 +                                               optp = optend;
12860 +                                               continue;
12861 +                                       }
12862 +                                       
12863 +                                       if (len != 1)
12864 +                                       {
12865 +                                               /* Skip kind and length fields*/
12866 +                                               optp += 2; 
12867 +
12868 +                                               if (f->opt[optnum].wc.val != 0)
12869 +                                               {
12870 +                                                       unsigned long tmp = 0;
12871 +                                                       
12872 +                                                       /* Hmmm... It looks a bit ugly. :) */
12873 +                                                       memcpy(&tmp, optp, 
12874 +                                                               (len > sizeof(unsigned long)?
12875 +                                                                       sizeof(unsigned long):len));
12876 +                                                       /* 2 + 2: optlen(2 bytes) + 
12877 +                                                        *      kind(1 byte) + length(1 byte) */
12878 +                                                       if (len == 4) 
12879 +                                                               tmp = ntohs(tmp);
12880 +                                                       else
12881 +                                                               tmp = ntohl(tmp);
12882 +
12883 +                                                       if (f->opt[optnum].wc.wc == '%')
12884 +                                                       {
12885 +                                                               if ((tmp % f->opt[optnum].wc.val) != 0)
12886 +                                                                       fmatch = FMATCH_OPT_WRONG;
12887 +                                                       }
12888 +                                                       else if (tmp != f->opt[optnum].wc.val)
12889 +                                                               fmatch = FMATCH_OPT_WRONG;
12890 +                                               }
12891 +                                       }
12892 +
12893 +                                       optp = optend;
12894 +                               }
12895 +                               else
12896 +                                       fmatch = FMATCH_OPT_WRONG;
12897 +
12898 +                               if (fmatch != FMATCH_OK)
12899 +                                       break;
12900 +                       }
12901 +
12902 +                       if (fmatch != FMATCH_OPT_WRONG)
12903 +                       {
12904 +                               fmatch = FMATCH_WRONG;
12905 +
12906 +                               switch (check_WSS)
12907 +                               {
12908 +                                       case 0:
12909 +                                               if (f->wss.val == 0 || window == f->wss.val)
12910 +                                                       fmatch = FMATCH_OK;
12911 +                                               break;
12912 +                                       case 1: /* MSS */
12913 +/* Lurked in OpenBSD */
12914 +#define SMART_MSS      1460
12915 +                                               if (window == f->wss.val*mss || 
12916 +                                                       window == f->wss.val*SMART_MSS)
12917 +                                                       fmatch = FMATCH_OK;
12918 +                                               break;
12919 +                                       case 2: /* MTU */
12920 +                                               if (window == f->wss.val*(mss+40) ||
12921 +                                                       window == f->wss.val*(SMART_MSS+40))
12922 +                                                       fmatch = FMATCH_OK;
12923 +                                               break;
12924 +                                       case 3: /* MOD */
12925 +                                               if ((window % f->wss.val) == 0)
12926 +                                                       fmatch = FMATCH_OK;
12927 +                                               break;
12928 +                               }
12929 +                       }
12930 +                                       
12931 +
12932 +                       if (fmatch == FMATCH_OK)
12933 +                       {
12934 +                               fcount++;
12935 +                               log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n", 
12936 +                                       f->genre, f->version,
12937 +                                       f->subtype, f->details,
12938 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
12939 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest),
12940 +                                       f->ttl - ip->ttl);
12941 +                               if (info->flags & IPT_OSF_NETLINK)
12942 +                               {
12943 +                                       spin_lock_bh(&ipt_osf_netlink_lock);
12944 +                                       ipt_osf_nlsend(f, skb);
12945 +                                       spin_unlock_bh(&ipt_osf_netlink_lock);
12946 +                               }
12947 +                               if ((info->flags & IPT_OSF_LOG) && 
12948 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
12949 +                                       break;
12950 +                       }
12951 +               }
12952 +       }
12953 +       if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
12954 +       {
12955 +               unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
12956 +               unsigned int i, optsize;
12957 +               struct osf_finger fg;
12958 +
12959 +               memset(&fg, 0, sizeof(fg));
12960 +
12961 +               if ((info->flags & IPT_OSF_LOG))
12962 +                       log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
12963 +               if (optp)
12964 +               {
12965 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
12966 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
12967 +                                         opt, optsize) < 0)
12968 +                       {
12969 +                               if (info->flags & IPT_OSF_LOG)
12970 +                                       loga("TRUNCATED");
12971 +                               if (info->flags & IPT_OSF_NETLINK)
12972 +                                       strcpy(fg.details, "TRUNCATED");
12973 +                       }
12974 +                       else
12975 +                       {
12976 +                               for (i = 0; i < optsize; i++)
12977 +                               {
12978 +                                       if (info->flags & IPT_OSF_LOG)
12979 +                                               loga("%02X", opt[i]);
12980 +                               }
12981 +                               if (info->flags & IPT_OSF_NETLINK)
12982 +                                       memcpy(fg.details, opt, MAXDETLEN);
12983 +                       }
12984 +               }
12985 +               if ((info->flags & IPT_OSF_LOG))
12986 +                       loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
12987 +                               NIPQUAD(ip->saddr), ntohs(tcp->source),
12988 +                               NIPQUAD(ip->daddr), ntohs(tcp->dest));
12989 +               
12990 +               if (info->flags & IPT_OSF_NETLINK)
12991 +               {
12992 +                       fg.wss.val      = window;
12993 +                       fg.ttl          = ip->ttl;
12994 +                       fg.df           = df;
12995 +                       fg.ss           = totlen;
12996 +                       strncpy(fg.genre, "Unknown", MAXGENRELEN);
12997 +
12998 +                       spin_lock_bh(&ipt_osf_netlink_lock);
12999 +                       ipt_osf_nlsend(&fg, skb);
13000 +                       spin_unlock_bh(&ipt_osf_netlink_lock);
13001 +               }
13002 +       }
13003 +
13004 +       read_unlock(&osf_lock);
13005 +
13006 +       return (fmatch == FMATCH_OK)?1:0;
13007 +}
13008 +
13009 +static int
13010 +checkentry(const char *tablename,
13011 +           const struct ipt_ip *ip,
13012 +           void *matchinfo,
13013 +           unsigned int matchsize,
13014 +           unsigned int hook_mask)
13015 +{
13016 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
13017 +               return 0;
13018 +       if (ip->proto != IPPROTO_TCP)
13019 +              return 0;
13020 +
13021 +       return 1;
13022 +}
13023 +
13024 +static char * osf_strchr(char *ptr, char c)
13025 +{
13026 +       char *tmp;
13027 +
13028 +       tmp = strchr(ptr, c);
13029 +
13030 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
13031 +               tmp++;
13032 +
13033 +       return tmp;
13034 +}
13035 +
13036 +static struct osf_finger * finger_alloc(void)
13037 +{
13038 +       struct osf_finger *f;
13039 +
13040 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
13041 +       if (f)
13042 +               memset(f, 0, sizeof(struct osf_finger));
13043 +       
13044 +       return f;
13045 +}
13046 +
13047 +static void finger_free(struct osf_finger *f)
13048 +{
13049 +       memset(f, 0, sizeof(struct osf_finger));
13050 +       kfree(f);
13051 +}
13052 +
13053 +
13054 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
13055 +{
13056 +       int i, op;
13057 +       char *ptr, wc;
13058 +       unsigned long val;
13059 +
13060 +       ptr = &obuf[0];
13061 +       i = 0;
13062 +       while (ptr != NULL && i < olen)
13063 +       {
13064 +               val = 0;
13065 +               op = 0;
13066 +               wc = 0;
13067 +               switch (obuf[i])
13068 +               {
13069 +                       case 'N': 
13070 +                               op = OSFOPT_NOP;
13071 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13072 +                               if (ptr)
13073 +                               {
13074 +                                       *ptr = '\0';
13075 +                                       ptr++;
13076 +                                       i += (int)(ptr-&obuf[i]);
13077 +
13078 +                               }
13079 +                               else
13080 +                                       i++;
13081 +                               break;
13082 +                       case 'S': 
13083 +                               op = OSFOPT_SACKP;
13084 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13085 +                               if (ptr)
13086 +                               {
13087 +                                       *ptr = '\0';
13088 +                                       ptr++;
13089 +                                       i += (int)(ptr-&obuf[i]);
13090 +
13091 +                               }
13092 +                               else
13093 +                                       i++;
13094 +                               break;
13095 +                       case 'T': 
13096 +                               op = OSFOPT_TS;
13097 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13098 +                               if (ptr)
13099 +                               {
13100 +                                       *ptr = '\0';
13101 +                                       ptr++;
13102 +                                       i += (int)(ptr-&obuf[i]);
13103 +
13104 +                               }
13105 +                               else
13106 +                                       i++;
13107 +                               break;
13108 +                       case 'W': 
13109 +                               op = OSFOPT_WSO;
13110 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13111 +                               if (ptr)
13112 +                               {
13113 +                                       switch (obuf[i+1])
13114 +                                       {
13115 +                                               case '%':       wc = '%'; break;
13116 +                                               case 'S':       wc = 'S'; break;
13117 +                                               case 'T':       wc = 'T'; break;
13118 +                                               default:        wc = 0; break;
13119 +                                       }
13120 +                                       
13121 +                                       *ptr = '\0';
13122 +                                       ptr++;
13123 +                                       if (wc)
13124 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
13125 +                                       else
13126 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
13127 +                                       i += (int)(ptr-&obuf[i]);
13128 +
13129 +                               }
13130 +                               else
13131 +                                       i++;
13132 +                               break;
13133 +                       case 'M': 
13134 +                               op = OSFOPT_MSS;
13135 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13136 +                               if (ptr)
13137 +                               {
13138 +                                       if (obuf[i+1] == '%')
13139 +                                               wc = '%';
13140 +                                       *ptr = '\0';
13141 +                                       ptr++;
13142 +                                       if (wc)
13143 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
13144 +                                       else
13145 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
13146 +                                       i += (int)(ptr-&obuf[i]);
13147 +
13148 +                               }
13149 +                               else
13150 +                                       i++;
13151 +                               break;
13152 +                       case 'E': 
13153 +                               op = OSFOPT_EOL;
13154 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13155 +                               if (ptr)
13156 +                               {
13157 +                                       *ptr = '\0';
13158 +                                       ptr++;
13159 +                                       i += (int)(ptr-&obuf[i]);
13160 +
13161 +                               }
13162 +                               else
13163 +                                       i++;
13164 +                               break;
13165 +                       default:
13166 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
13167 +                               if (ptr)
13168 +                               {
13169 +                                       ptr++;
13170 +                                       i += (int)(ptr-&obuf[i]);
13171 +
13172 +                               }
13173 +                               else
13174 +                                       i++;
13175 +                               break;
13176 +               }
13177 +
13178 +               opt[*optnum].kind       = IANA_opts[op].kind;
13179 +               opt[*optnum].length     = IANA_opts[op].length;
13180 +               opt[*optnum].wc.wc      = wc;
13181 +               opt[*optnum].wc.val     = val;
13182 +
13183 +               (*optnum)++;
13184 +       }
13185 +}
13186 +
13187 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
13188 +{
13189 +       struct list_head *ent;
13190 +       struct osf_finger *f = NULL;
13191 +       int i;
13192 +       
13193 +       *eof = 1;
13194 +       count = 0;
13195 +
13196 +       read_lock_bh(&osf_lock);
13197 +       list_for_each(ent, &finger_list)
13198 +       {
13199 +               f = list_entry(ent, struct osf_finger, flist);
13200 +
13201 +               log("%s [%s]", f->genre, f->details);
13202 +               
13203 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
13204 +                                       f->genre, f->version,
13205 +                                       f->subtype, f->details);
13206 +               
13207 +               if (f->opt_num)
13208 +               {
13209 +                       loga(" OPT: ");
13210 +                       //count += sprintf(buf+count, " OPT: ");
13211 +                       for (i=0; i<f->opt_num; ++i)
13212 +                       {
13213 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
13214 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13215 +                               loga("%d.%c%lu; ", 
13216 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
13217 +                       }
13218 +               }
13219 +               loga("\n");
13220 +               count += sprintf(buf+count, "\n");
13221 +       }
13222 +       read_unlock_bh(&osf_lock);
13223 +
13224 +       return count;
13225 +}
13226 +
13227 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
13228 +{
13229 +       int cnt;
13230 +       unsigned long i;
13231 +       char obuf[MAXOPTSTRLEN];
13232 +       struct osf_finger *finger;
13233 +       struct list_head *ent, *n;
13234 +
13235 +       char *pbeg, *pend;
13236 +
13237 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
13238 +       {
13239 +               int i = 0;
13240 +               write_lock_bh(&osf_lock);
13241 +               list_for_each_safe(ent, n, &finger_list)
13242 +               {
13243 +                       i++;
13244 +                       finger = list_entry(ent, struct osf_finger, flist);
13245 +                       list_del(&finger->flist);
13246 +                       finger_free(finger);
13247 +               }
13248 +               write_unlock_bh(&osf_lock);
13249 +       
13250 +               log("Flushed %d entries.\n", i);
13251 +               
13252 +               return count;
13253 +       }
13254 +
13255 +       
13256 +       cnt = 0;
13257 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
13258 +               if (buffer[i] == ':')
13259 +                       cnt++;
13260 +
13261 +       if (cnt != 8 || i != count)
13262 +       {
13263 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
13264 +                       cnt, i, count);
13265 +               return count;
13266 +       }
13267 +
13268 +       memset(obuf, 0, sizeof(obuf));
13269 +       
13270 +       finger = finger_alloc();
13271 +       if (!finger)
13272 +       {
13273 +               log("Failed to allocate new fingerprint entry.\n");
13274 +               return -ENOMEM;
13275 +       }
13276 +
13277 +       pbeg = (char *)buffer;
13278 +       pend = osf_strchr(pbeg, OSFPDEL);
13279 +       if (pend)
13280 +       {
13281 +               *pend = '\0';
13282 +               if (pbeg[0] == 'S')
13283 +               {
13284 +                       finger->wss.wc = 'S';
13285 +                       if (pbeg[1] == '%')
13286 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13287 +                       else if (pbeg[1] == '*')
13288 +                               finger->wss.val = 0;
13289 +                       else 
13290 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13291 +               }
13292 +               else if (pbeg[0] == 'T')
13293 +               {
13294 +                       finger->wss.wc = 'T';
13295 +                       if (pbeg[1] == '%')
13296 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
13297 +                       else if (pbeg[1] == '*')
13298 +                               finger->wss.val = 0;
13299 +                       else 
13300 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13301 +               }
13302 +               else if (pbeg[0] == '%')
13303 +               {
13304 +                       finger->wss.wc = '%';
13305 +                       finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
13306 +               }
13307 +               else if (isdigit(pbeg[0]))
13308 +               {
13309 +                       finger->wss.wc = 0;
13310 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
13311 +               }
13312 +
13313 +               pbeg = pend+1;
13314 +       }
13315 +       pend = osf_strchr(pbeg, OSFPDEL);
13316 +       if (pend)
13317 +       {
13318 +               *pend = '\0';
13319 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
13320 +               pbeg = pend+1;
13321 +       }
13322 +       pend = osf_strchr(pbeg, OSFPDEL);
13323 +       if (pend)
13324 +       {
13325 +               *pend = '\0';
13326 +               finger->df = simple_strtoul(pbeg, NULL, 10);
13327 +               pbeg = pend+1;
13328 +       }
13329 +       pend = osf_strchr(pbeg, OSFPDEL);
13330 +       if (pend)
13331 +       {
13332 +               *pend = '\0';
13333 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
13334 +               pbeg = pend+1;
13335 +       }
13336 +
13337 +       pend = osf_strchr(pbeg, OSFPDEL);
13338 +       if (pend)
13339 +       {
13340 +               *pend = '\0';
13341 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
13342 +               pbeg = pend+1;
13343 +       }
13344 +
13345 +       pend = osf_strchr(pbeg, OSFPDEL);
13346 +       if (pend)
13347 +       {
13348 +               *pend = '\0';
13349 +               if (pbeg[0] == '@' || pbeg[0] == '*')
13350 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
13351 +               else
13352 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
13353 +               pbeg = pend+1;
13354 +       }
13355 +       
13356 +       pend = osf_strchr(pbeg, OSFPDEL);
13357 +       if (pend)
13358 +       {
13359 +               *pend = '\0';
13360 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
13361 +               pbeg = pend+1;
13362 +       }
13363 +       
13364 +       pend = osf_strchr(pbeg, OSFPDEL);
13365 +       if (pend)
13366 +       {
13367 +               *pend = '\0';
13368 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
13369 +               pbeg = pend+1;
13370 +       }
13371 +
13372 +       cnt = snprintf(finger->details, 
13373 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
13374 +                       "%s", pbeg);
13375 +       
13376 +       log("%s - %s[%s] : %s\n", 
13377 +               finger->genre, finger->version,
13378 +               finger->subtype, finger->details);
13379 +       
13380 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
13381 +       
13382 +
13383 +       write_lock_bh(&osf_lock);
13384 +       list_add_tail(&finger->flist, &finger_list);
13385 +       write_unlock_bh(&osf_lock);
13386 +
13387 +       return count;
13388 +}
13389 +
13390 +static int __init osf_init(void)
13391 +{
13392 +       int err;
13393 +       struct proc_dir_entry *p;
13394 +
13395 +       log("Startng OS fingerprint matching module.\n");
13396 +
13397 +       INIT_LIST_HEAD(&finger_list);
13398 +       
13399 +       err = ipt_register_match(&osf_match);
13400 +       if (err)
13401 +       {
13402 +               log("Failed to register OS fingerprint matching module.\n");
13403 +               return -ENXIO;
13404 +       }
13405 +
13406 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
13407 +       if (!p)
13408 +       {
13409 +               ipt_unregister_match(&osf_match);
13410 +               return -ENXIO;
13411 +       }
13412 +
13413 +       p->write_proc = osf_proc_write;
13414 +       p->read_proc  = osf_proc_read;
13415 +       
13416 +       nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
13417 +       if (!nts)
13418 +       {
13419 +               log("netlink_kernel_create() failed\n");
13420 +               remove_proc_entry("sys/net/ipv4/osf", NULL);
13421 +               ipt_unregister_match(&osf_match);
13422 +               return -ENOMEM;
13423 +       }
13424 +
13425 +       return 0;
13426 +}
13427 +
13428 +static void __exit osf_fini(void)
13429 +{
13430 +       struct list_head *ent, *n;
13431 +       struct osf_finger *f;
13432 +       
13433 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
13434 +       ipt_unregister_match(&osf_match);
13435 +       if (nts && nts->sk_socket)
13436 +               sock_release(nts->sk_socket);
13437 +
13438 +       list_for_each_safe(ent, n, &finger_list)
13439 +       {
13440 +               f = list_entry(ent, struct osf_finger, flist);
13441 +               list_del(&f->flist);
13442 +               finger_free(f);
13443 +       }
13444 +       
13445 +       log("OS fingerprint matching module finished.\n");
13446 +}
13447 +
13448 +module_init(osf_init);
13449 +module_exit(osf_fini);
13450 +
13451 +MODULE_LICENSE("GPL");
13452 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
13453 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
13454 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_owner.c
13455 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_owner.c  2004-06-07 21:15:11.000000000 +0200
13456 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_owner.c      2004-06-08 10:39:56.000000000 +0200
13457 @@ -6,12 +6,19 @@
13458   * This program is free software; you can redistribute it and/or modify
13459   * it under the terms of the GNU General Public License version 2 as
13460   * published by the Free Software Foundation.
13461 + *
13462 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
13463   */
13464  
13465  #include <linux/module.h>
13466  #include <linux/skbuff.h>
13467  #include <linux/file.h>
13468 +#include <linux/ip.h>
13469 +#include <linux/tcp.h>
13470 +#include <linux/udp.h>
13471  #include <net/sock.h>
13472 +#include <net/tcp.h>
13473 +#include <net/udp.h>
13474  
13475  #include <linux/netfilter_ipv4/ipt_owner.h>
13476  #include <linux/netfilter_ipv4/ip_tables.h>
13477 @@ -21,7 +28,7 @@
13478  MODULE_DESCRIPTION("iptables owner match");
13479  
13480  static int
13481 -match_comm(const struct sk_buff *skb, const char *comm)
13482 +match_comm(const struct sock *sk, const char *comm)
13483  {
13484         struct task_struct *g, *p;
13485         struct files_struct *files;
13486 @@ -38,7 +45,7 @@
13487                         spin_lock(&files->file_lock);
13488                         for (i=0; i < files->max_fds; i++) {
13489                                 if (fcheck_files(files, i) ==
13490 -                                   skb->sk->sk_socket->file) {
13491 +                                   sk->sk_socket->file) {
13492                                         spin_unlock(&files->file_lock);
13493                                         task_unlock(p);
13494                                         read_unlock(&tasklist_lock);
13495 @@ -54,7 +61,7 @@
13496  }
13497  
13498  static int
13499 -match_pid(const struct sk_buff *skb, pid_t pid)
13500 +match_pid(const struct sock *sk, pid_t pid)
13501  {
13502         struct task_struct *p;
13503         struct files_struct *files;
13504 @@ -70,7 +77,7 @@
13505                 spin_lock(&files->file_lock);
13506                 for (i=0; i < files->max_fds; i++) {
13507                         if (fcheck_files(files, i) ==
13508 -                           skb->sk->sk_socket->file) {
13509 +                           sk->sk_socket->file) {
13510                                 spin_unlock(&files->file_lock);
13511                                 task_unlock(p);
13512                                 read_unlock(&tasklist_lock);
13513 @@ -86,10 +93,10 @@
13514  }
13515  
13516  static int
13517 -match_sid(const struct sk_buff *skb, pid_t sid)
13518 +match_sid(const struct sock *sk, pid_t sid)
13519  {
13520         struct task_struct *g, *p;
13521 -       struct file *file = skb->sk->sk_socket->file;
13522 +       struct file *file = sk->sk_socket->file;
13523         int i, found=0;
13524  
13525         read_lock(&tasklist_lock);
13526 @@ -129,41 +136,71 @@
13527        int *hotdrop)
13528  {
13529         const struct ipt_owner_info *info = matchinfo;
13530 +       struct iphdr *iph = skb->nh.iph;
13531 +       struct sock *sk = NULL;
13532 +       int ret = 0;
13533 +
13534 +       if (out) {
13535 +               sk = skb->sk;
13536 +       } else {
13537 +               if (iph->protocol == IPPROTO_TCP) {
13538 +                       struct tcphdr *tcph =
13539 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
13540 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
13541 +                                          iph->daddr, tcph->dest,
13542 +                                          skb->dev->ifindex);
13543 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
13544 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
13545 +                               return ret;
13546 +                       }
13547 +               } else if (iph->protocol == IPPROTO_UDP) {
13548 +                       struct udphdr *udph =
13549 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
13550 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
13551 +                                          udph->dest, skb->dev->ifindex);
13552 +               }
13553 +       }
13554  
13555 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
13556 -               return 0;
13557 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
13558 +               goto out;
13559  
13560         if(info->match & IPT_OWNER_UID) {
13561 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
13562 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
13563                     !!(info->invert & IPT_OWNER_UID))
13564 -                       return 0;
13565 +                       goto out;
13566         }
13567  
13568         if(info->match & IPT_OWNER_GID) {
13569 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
13570 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
13571                     !!(info->invert & IPT_OWNER_GID))
13572 -                       return 0;
13573 +                       goto out;
13574         }
13575  
13576         if(info->match & IPT_OWNER_PID) {
13577 -               if (!match_pid(skb, info->pid) ^
13578 +               if (!match_pid(sk, info->pid) ^
13579                     !!(info->invert & IPT_OWNER_PID))
13580 -                       return 0;
13581 +                       goto out;
13582         }
13583  
13584         if(info->match & IPT_OWNER_SID) {
13585 -               if (!match_sid(skb, info->sid) ^
13586 +               if (!match_sid(sk, info->sid) ^
13587                     !!(info->invert & IPT_OWNER_SID))
13588 -                       return 0;
13589 +                       goto out;
13590         }
13591  
13592         if(info->match & IPT_OWNER_COMM) {
13593 -               if (!match_comm(skb, info->comm) ^
13594 +               if (!match_comm(sk, info->comm) ^
13595                     !!(info->invert & IPT_OWNER_COMM))
13596 -                       return 0;
13597 +                       goto out;
13598         }
13599  
13600 -       return 1;
13601 +       ret = 1;
13602 +
13603 +out:
13604 +       if (in && sk)
13605 +               sock_put(sk);
13606 +
13607 +       return ret;
13608  }
13609  
13610  static int
13611 @@ -173,11 +210,19 @@
13612             unsigned int matchsize,
13613             unsigned int hook_mask)
13614  {
13615 -        if (hook_mask
13616 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
13617 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
13618 -                return 0;
13619 -        }
13620 +       if (hook_mask
13621 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
13622 +           (1 << NF_IP_LOCAL_IN))) {
13623 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
13624 +                      "or POST_ROUTING.\n");
13625 +               return 0;
13626 +       }
13627 +
13628 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
13629 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
13630 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
13631 +               return 0;
13632 +       }
13633  
13634         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
13635                 printk("Matchsize %u != %Zu\n", matchsize,
13636 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_policy.c
13637 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
13638 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_policy.c     2004-06-08 10:42:36.000000000 +0200
13639 @@ -0,0 +1,176 @@
13640 +/* IP tables module for matching IPsec policy
13641 + *
13642 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
13643 + *
13644 + * This program is free software; you can redistribute it and/or modify
13645 + * it under the terms of the GNU General Public License version 2 as
13646 + * published by the Free Software Foundation.
13647 + */
13648 +
13649 +#include <linux/kernel.h>
13650 +#include <linux/config.h>
13651 +#include <linux/module.h>
13652 +#include <linux/skbuff.h>
13653 +#include <linux/init.h>
13654 +#include <net/xfrm.h>
13655 +
13656 +#include <linux/netfilter_ipv4.h>
13657 +#include <linux/netfilter_ipv4/ipt_policy.h>
13658 +#include <linux/netfilter_ipv4/ip_tables.h>
13659 +
13660 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
13661 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
13662 +MODULE_LICENSE("GPL");
13663 +
13664 +
13665 +static inline int
13666 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
13667 +{
13668 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
13669 +
13670 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
13671 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
13672 +           MISMATCH(proto, x->id.proto) ||
13673 +           MISMATCH(mode, x->props.mode) ||
13674 +           MISMATCH(spi, x->id.spi) ||
13675 +           MISMATCH(reqid, x->props.reqid))
13676 +               return 0;
13677 +       return 1;
13678 +}
13679 +
13680 +static int
13681 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
13682 +{
13683 +       const struct ipt_policy_elem *e;
13684 +       struct sec_path *sp = skb->sp;
13685 +       int strict = info->flags & POLICY_MATCH_STRICT;
13686 +       int i, pos;
13687 +
13688 +       if (sp == NULL)
13689 +               return -1;
13690 +       if (strict && info->len != sp->len)
13691 +               return 0;
13692 +
13693 +       for (i = sp->len - 1; i >= 0; i--) {
13694 +               pos = strict ? i - sp->len + 1 : 0;
13695 +               if (pos >= info->len)
13696 +                       return 0;
13697 +               e = &info->pol[pos];
13698 +
13699 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
13700 +                       if (!strict)
13701 +                               return 1;
13702 +               } else if (strict)
13703 +                       return 0;
13704 +       }
13705 +
13706 +       return strict ? 1 : 0;
13707 +}
13708 +
13709 +static int
13710 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
13711 +{
13712 +       const struct ipt_policy_elem *e;
13713 +       struct dst_entry *dst = skb->dst;
13714 +       int strict = info->flags & POLICY_MATCH_STRICT;
13715 +       int i, pos;
13716 +
13717 +       if (dst->xfrm == NULL)
13718 +               return -1;
13719 +
13720 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
13721 +               pos = strict ? i : 0;
13722 +               if (pos >= info->len)
13723 +                       return 0;
13724 +               e = &info->pol[pos];
13725 +
13726 +               if (match_xfrm_state(dst->xfrm, e)) {
13727 +                       if (!strict)
13728 +                               return 1;
13729 +               } else if (strict)
13730 +                       return 0;
13731 +       }
13732 +
13733 +       return strict ? 1 : 0;
13734 +}
13735 +
13736 +static int match(const struct sk_buff *skb,
13737 +                 const struct net_device *in,
13738 +                 const struct net_device *out,
13739 +                 const void *matchinfo, int offset, int *hotdrop)
13740 +{
13741 +       const struct ipt_policy_info *info = matchinfo;
13742 +       int ret;
13743 +
13744 +       if (info->flags & POLICY_MATCH_IN)
13745 +               ret = match_policy_in(skb, info);
13746 +       else
13747 +               ret = match_policy_out(skb, info);
13748 +
13749 +       if (ret < 0) {
13750 +               if (info->flags & POLICY_MATCH_NONE)
13751 +                       ret = 1;
13752 +               else
13753 +                       ret = 0;
13754 +       } else if (info->flags & POLICY_MATCH_NONE)
13755 +               ret = 0;
13756 +
13757 +       return ret;
13758 +}
13759 +
13760 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
13761 +                      void *matchinfo, unsigned int matchsize,
13762 +                      unsigned int hook_mask)
13763 +{
13764 +       struct ipt_policy_info *info = matchinfo;
13765 +
13766 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
13767 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
13768 +                      matchsize, IPT_ALIGN(sizeof(*info)));
13769 +               return 0;
13770 +       }
13771 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
13772 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
13773 +                               "outgoing policy selected\n");
13774 +               return 0;
13775 +       }
13776 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
13777 +           && info->flags & POLICY_MATCH_OUT) {
13778 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
13779 +                               "PRE_ROUTING and INPUT\n");
13780 +               return 0;
13781 +       }
13782 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
13783 +           && info->flags & POLICY_MATCH_IN) {
13784 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
13785 +                               "POST_ROUTING and OUTPUT\n");
13786 +               return 0;
13787 +       }
13788 +       if (info->len > POLICY_MAX_ELEM) {
13789 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
13790 +               return 0;
13791 +       }
13792 +
13793 +       return 1;
13794 +}
13795 +
13796 +static struct ipt_match policy_match =
13797 +{
13798 +       .name           = "policy",
13799 +       .match          = match,
13800 +       .checkentry     = checkentry,
13801 +       .me             = THIS_MODULE,
13802 +};
13803 +
13804 +static int __init init(void)
13805 +{
13806 +       return ipt_register_match(&policy_match);
13807 +}
13808 +
13809 +static void __exit fini(void)
13810 +{
13811 +       ipt_unregister_match(&policy_match);
13812 +}
13813 +
13814 +module_init(init);
13815 +module_exit(fini);
13816 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_pool.c
13817 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_pool.c   1970-01-01 01:00:00.000000000 +0100
13818 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_pool.c       2004-06-08 10:31:45.000000000 +0200
13819 @@ -0,0 +1,71 @@
13820 +/* Kernel module to match an IP address pool. */
13821 +
13822 +#include <linux/module.h>
13823 +#include <linux/ip.h>
13824 +#include <linux/skbuff.h>
13825 +
13826 +#include <linux/netfilter_ipv4/ip_tables.h>
13827 +#include <linux/netfilter_ipv4/ip_pool.h>
13828 +#include <linux/netfilter_ipv4/ipt_pool.h>
13829 +
13830 +static inline int match_pool(
13831 +       ip_pool_t index,
13832 +       __u32 addr,
13833 +       int inv
13834 +) {
13835 +       if (ip_pool_match(index, ntohl(addr)))
13836 +               inv = !inv;
13837 +       return inv;
13838 +}
13839 +
13840 +static int match(
13841 +       const struct sk_buff *skb,
13842 +       const struct net_device *in,
13843 +       const struct net_device *out,
13844 +       const void *matchinfo,
13845 +       int offset,
13846 +       const void *hdr,
13847 +       u_int16_t datalen,
13848 +       int *hotdrop
13849 +) {
13850 +       const struct ipt_pool_info *info = matchinfo;
13851 +       const struct iphdr *iph = skb->nh.iph;
13852 +
13853 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
13854 +                                               info->flags&IPT_POOL_INV_SRC))
13855 +               return 0;
13856 +
13857 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
13858 +                                               info->flags&IPT_POOL_INV_DST))
13859 +               return 0;
13860 +
13861 +       return 1;
13862 +}
13863 +
13864 +static int checkentry(
13865 +       const char *tablename,
13866 +       const struct ipt_ip *ip,
13867 +       void *matchinfo,
13868 +       unsigned int matchsize,
13869 +       unsigned int hook_mask
13870 +) {
13871 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
13872 +               return 0;
13873 +       return 1;
13874 +}
13875 +
13876 +static struct ipt_match pool_match
13877 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
13878 +
13879 +static int __init init(void)
13880 +{
13881 +       return ipt_register_match(&pool_match);
13882 +}
13883 +
13884 +static void __exit fini(void)
13885 +{
13886 +       ipt_unregister_match(&pool_match);
13887 +}
13888 +
13889 +module_init(init);
13890 +module_exit(fini);
13891 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_psd.c
13892 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_psd.c    1970-01-01 01:00:00.000000000 +0100
13893 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_psd.c        2004-06-08 10:31:53.000000000 +0200
13894 @@ -0,0 +1,358 @@
13895 +/*
13896 +  This is a module which is used for PSD (portscan detection)
13897 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
13898 +  and LOG target module.
13899 +
13900 +  Copyright (C) 2000,2001 astaro AG
13901 +
13902 +  This file is distributed under the terms of the GNU General Public
13903 +  License (GPL). Copies of the GPL can be obtained from:
13904 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
13905 +
13906 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
13907 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
13908 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
13909 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
13910 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
13911 +  2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
13912 +*/
13913 +
13914 +#include <linux/module.h>
13915 +#include <linux/skbuff.h>
13916 +#include <linux/ip.h>
13917 +#include <net/tcp.h>
13918 +#include <linux/spinlock.h>
13919 +#include <linux/netfilter_ipv4/ip_tables.h>
13920 +#include <linux/netfilter_ipv4/ipt_psd.h>
13921 +
13922 +#if 0
13923 +#define DEBUGP printk
13924 +#else
13925 +#define DEBUGP(format, args...)
13926 +#endif
13927 +
13928 +MODULE_LICENSE("GPL");
13929 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
13930 +
13931 +#define HF_DADDR_CHANGING   0x01
13932 +#define HF_SPORT_CHANGING   0x02
13933 +#define HF_TOS_CHANGING            0x04
13934 +#define HF_TTL_CHANGING            0x08
13935 +
13936 +/*
13937 + * Information we keep per each target port
13938 + */
13939 +struct port {
13940 +       u_int16_t number;      /* port number */
13941 +       u_int8_t proto;        /* protocol number */
13942 +       u_int8_t and_flags;    /* tcp ANDed flags */
13943 +       u_int8_t or_flags;     /* tcp ORed flags */
13944 +};
13945 +
13946 +/*
13947 + * Information we keep per each source address.
13948 + */
13949 +struct host {
13950 +       struct host *next;              /* Next entry with the same hash */
13951 +       clock_t timestamp;              /* Last update time */
13952 +       struct in_addr src_addr;        /* Source address */
13953 +       struct in_addr dest_addr;       /* Destination address */
13954 +       unsigned short src_port;        /* Source port */
13955 +       int count;                      /* Number of ports in the list */
13956 +       int weight;                     /* Total weight of ports in the list */
13957 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
13958 +       unsigned char tos;              /* TOS */
13959 +       unsigned char ttl;              /* TTL */
13960 +       unsigned char flags;            /* HF_ flags bitmask */
13961 +};
13962 +
13963 +/*
13964 + * State information.
13965 + */
13966 +static struct {
13967 +       spinlock_t lock;
13968 +       struct host list[LIST_SIZE];    /* List of source addresses */
13969 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
13970 +       int index;                      /* Oldest entry to be replaced */
13971 +} state;
13972 +
13973 +/*
13974 + * Convert an IP address into a hash table index.
13975 + */
13976 +static inline int hashfunc(struct in_addr addr)
13977 +{
13978 +       unsigned int value;
13979 +       int hash;
13980 +
13981 +       value = addr.s_addr;
13982 +       hash = 0;
13983 +       do {
13984 +               hash ^= value;
13985 +       } while ((value >>= HASH_LOG));
13986 +
13987 +       return hash & (HASH_SIZE - 1);
13988 +}
13989 +
13990 +static int
13991 +ipt_psd_match(const struct sk_buff *pskb,
13992 +             const struct net_device *in,
13993 +             const struct net_device *out,
13994 +             const void *matchinfo,
13995 +             int offset,
13996 +             int *hotdrop)
13997 +{
13998 +       struct iphdr *ip_hdr;
13999 +       struct tcphdr *tcp_hdr;
14000 +       struct in_addr addr;
14001 +       u_int16_t src_port,dest_port;
14002 +       u_int8_t tcp_flags, proto;
14003 +       clock_t now;
14004 +       struct host *curr, *last, **head;
14005 +       int hash, index, count;
14006 +
14007 +       /* Parameters from userspace */
14008 +       const struct ipt_psd_info *psdinfo = matchinfo;
14009 +
14010 +       /* IP header */
14011 +       ip_hdr = pskb->nh.iph;
14012 +
14013 +       /* Sanity check */
14014 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
14015 +               DEBUGP("PSD: sanity check failed\n");
14016 +               return 0;
14017 +       }
14018 +
14019 +       /* TCP or UDP ? */
14020 +       proto = ip_hdr->protocol;
14021 +
14022 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
14023 +               DEBUGP("PSD: protocol not supported\n");
14024 +               return 0;
14025 +       }
14026 +
14027 +       /* Get the source address, source & destination ports, and TCP flags */
14028 +
14029 +       addr.s_addr = ip_hdr->saddr;
14030 +
14031 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
14032 +
14033 +       /* Yep, it´s dirty */
14034 +       src_port = tcp_hdr->source;
14035 +       dest_port = tcp_hdr->dest;
14036 +
14037 +       if (proto == IPPROTO_TCP) {
14038 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
14039 +       }
14040 +       else {
14041 +               tcp_flags = 0x00;
14042 +       }
14043 +
14044 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
14045 +        * them spoof us. [DHCP needs this feature - HW] */
14046 +       if (!addr.s_addr) {
14047 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
14048 +               return 0;
14049 +       }
14050 +
14051 +       /* Use jiffies here not to depend on someone setting the time while we're
14052 +        * running; we need to be careful with possible return value overflows. */
14053 +       now = jiffies;
14054 +
14055 +       spin_lock(&state.lock);
14056 +
14057 +       /* Do we know this source address already? */
14058 +       count = 0;
14059 +       last = NULL;
14060 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
14061 +               do {
14062 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
14063 +                       count++;
14064 +                       if (curr->next) last = curr;
14065 +               } while ((curr = curr->next));
14066 +
14067 +       if (curr) {
14068 +
14069 +               /* We know this address, and the entry isn't too old. Update it. */
14070 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
14071 +                   time_after_eq(now, curr->timestamp)) {
14072 +
14073 +                       /* Just update the appropriate list entry if we've seen this port already */
14074 +                       for (index = 0; index < curr->count; index++) {
14075 +                               if (curr->ports[index].number == dest_port) {
14076 +                                       curr->ports[index].proto = proto;
14077 +                                       curr->ports[index].and_flags &= tcp_flags;
14078 +                                       curr->ports[index].or_flags |= tcp_flags;
14079 +                                       goto out_no_match;
14080 +                               }
14081 +                       }
14082 +
14083 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
14084 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
14085 +                               goto out_no_match;
14086 +
14087 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
14088 +                       curr->timestamp = now;
14089 +
14090 +                       /* Logged this scan already? Then drop the packet. */
14091 +                       if (curr->weight >= psdinfo->weight_threshold)
14092 +                               goto out_match;
14093 +
14094 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
14095 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
14096 +                               curr->flags |= HF_DADDR_CHANGING;
14097 +                       if (curr->src_port != src_port)
14098 +                               curr->flags |= HF_SPORT_CHANGING;
14099 +                       if (curr->tos != ip_hdr->tos)
14100 +                               curr->flags |= HF_TOS_CHANGING;
14101 +                       if (curr->ttl != ip_hdr->ttl)
14102 +                               curr->flags |= HF_TTL_CHANGING;
14103 +
14104 +                       /* Update the total weight */
14105 +                       curr->weight += (ntohs(dest_port) < 1024) ?
14106 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14107 +
14108 +                       /* Got enough destination ports to decide that this is a scan? */
14109 +                       /* Then log it and drop the packet. */
14110 +                       if (curr->weight >= psdinfo->weight_threshold)
14111 +                               goto out_match;
14112 +
14113 +                       /* Remember the new port */
14114 +                       if (curr->count < SCAN_MAX_COUNT) {
14115 +                               curr->ports[curr->count].number = dest_port;
14116 +                               curr->ports[curr->count].proto = proto;
14117 +                               curr->ports[curr->count].and_flags = tcp_flags;
14118 +                               curr->ports[curr->count].or_flags = tcp_flags;
14119 +                               curr->count++;
14120 +                       }
14121 +
14122 +                       goto out_no_match;
14123 +               }
14124 +
14125 +               /* We know this address, but the entry is outdated. Mark it unused, and
14126 +                * remove from the hash table. We'll allocate a new entry instead since
14127 +                * this one might get re-used too soon. */
14128 +               curr->src_addr.s_addr = 0;
14129 +               if (last)
14130 +                       last->next = last->next->next;
14131 +               else if (*head)
14132 +                       *head = (*head)->next;
14133 +               last = NULL;
14134 +       }
14135 +
14136 +       /* We don't need an ACK from a new source address */
14137 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
14138 +               goto out_no_match;
14139 +
14140 +       /* Got too many source addresses with the same hash value? Then remove the
14141 +        * oldest one from the hash table, so that they can't take too much of our
14142 +        * CPU time even with carefully chosen spoofed IP addresses. */
14143 +       if (count >= HASH_MAX && last) last->next = NULL;
14144 +
14145 +       /* We're going to re-use the oldest list entry, so remove it from the hash
14146 +        * table first (if it is really already in use, and isn't removed from the
14147 +        * hash table already because of the HASH_MAX check above). */
14148 +
14149 +       /* First, find it */
14150 +       if (state.list[state.index].src_addr.s_addr)
14151 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
14152 +       else
14153 +               head = &last;
14154 +       last = NULL;
14155 +       if ((curr = *head))
14156 +       do {
14157 +               if (curr == &state.list[state.index]) break;
14158 +               last = curr;
14159 +       } while ((curr = curr->next));
14160 +
14161 +       /* Then, remove it */
14162 +       if (curr) {
14163 +               if (last)
14164 +                       last->next = last->next->next;
14165 +               else if (*head)
14166 +                       *head = (*head)->next;
14167 +       }
14168 +
14169 +       /* Get our list entry */
14170 +       curr = &state.list[state.index++];
14171 +       if (state.index >= LIST_SIZE) state.index = 0;
14172 +
14173 +       /* Link it into the hash table */
14174 +       head = &state.hash[hash];
14175 +       curr->next = *head;
14176 +       *head = curr;
14177 +
14178 +       /* And fill in the fields */
14179 +       curr->timestamp = now;
14180 +       curr->src_addr = addr;
14181 +       curr->dest_addr.s_addr = ip_hdr->daddr;
14182 +       curr->src_port = src_port;
14183 +       curr->count = 1;
14184 +       curr->weight = (ntohs(dest_port) < 1024) ?
14185 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
14186 +       curr->ports[0].number = dest_port;
14187 +       curr->ports[0].proto = proto;
14188 +       curr->ports[0].and_flags = tcp_flags;
14189 +       curr->ports[0].or_flags = tcp_flags;
14190 +       curr->tos = ip_hdr->tos;
14191 +       curr->ttl = ip_hdr->ttl;
14192 +
14193 +out_no_match:
14194 +       spin_unlock(&state.lock);
14195 +       return 0;
14196 +
14197 +out_match:
14198 +       spin_unlock(&state.lock);
14199 +       return 1;
14200 +}
14201 +
14202 +static int ipt_psd_checkentry(const char *tablename,
14203 +                             const struct ipt_ip *e,
14204 +                             void *matchinfo,
14205 +                             unsigned int matchsize,
14206 +                             unsigned int hook_mask)
14207 +{
14208 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
14209 +
14210 +       /* we accept TCP only */
14211 +/*     if (e->ip.proto != IPPROTO_TCP) { */
14212 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
14213 +/*             return 0; */
14214 +/*     } */
14215 +
14216 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
14217 +               DEBUGP("PSD: matchsize %u != %u\n",
14218 +                      matchsize,
14219 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
14220 +               return 0;
14221 +       }
14222 +
14223 +       return 1;
14224 +}
14225 +
14226 +static struct ipt_match ipt_psd_reg = {
14227 +       .name = "psd",
14228 +       .match = ipt_psd_match,
14229 +       .checkentry = ipt_psd_checkentry,
14230 +       .me = THIS_MODULE };
14231 +
14232 +static int __init init(void)
14233 +{
14234 +       if (ipt_register_match(&ipt_psd_reg))
14235 +               return -EINVAL;
14236 +
14237 +       memset(&state, 0, sizeof(state));
14238 +
14239 +       spin_lock_init(&(state.lock));
14240 +
14241 +       printk("netfilter PSD loaded - (c) astaro AG\n");
14242 +       return 0;
14243 +}
14244 +
14245 +static void __exit fini(void)
14246 +{
14247 +       ipt_unregister_match(&ipt_psd_reg);
14248 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
14249 +}
14250 +
14251 +module_init(init);
14252 +module_exit(fini);
14253 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_quota.c
14254 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_quota.c  1970-01-01 01:00:00.000000000 +0100
14255 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_quota.c      2004-06-08 10:31:54.000000000 +0200
14256 @@ -0,0 +1,91 @@
14257 +/* 
14258 + * netfilter module to enforce network quotas
14259 + *
14260 + * Sam Johnston <samj@samj.net>
14261 + */
14262 +#include <linux/module.h>
14263 +#include <linux/skbuff.h>
14264 +#include <linux/spinlock.h>
14265 +#include <linux/interrupt.h>
14266 +
14267 +#include <linux/netfilter_ipv4/ip_tables.h>
14268 +#include <linux/netfilter_ipv4/ipt_quota.h>
14269 +
14270 +MODULE_LICENSE("GPL");
14271 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
14272 +
14273 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
14274 +
14275 +static int
14276 +match(const struct sk_buff *skb,
14277 +      const struct net_device *in,
14278 +      const struct net_device *out,
14279 +      const void *matchinfo,
14280 +      int offset, int *hotdrop)
14281 +{
14282 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
14283 +       unsigned int datalen;
14284 +
14285 +       if (skb->len < sizeof(struct iphdr))
14286 +               return NF_ACCEPT;
14287 +       
14288 +       datalen = skb->len - skb->nh.iph->ihl*4;
14289 +
14290 +        spin_lock_bh(&quota_lock);
14291 +
14292 +        if (q->quota >= datalen) {
14293 +                /* we can afford this one */
14294 +                q->quota -= datalen;
14295 +                spin_unlock_bh(&quota_lock);
14296 +
14297 +#ifdef DEBUG_IPT_QUOTA
14298 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
14299 +#endif
14300 +                return 1;
14301 +        }
14302 +
14303 +        /* so we do not allow even small packets from now on */
14304 +        q->quota = 0;
14305 +
14306 +#ifdef DEBUG_IPT_QUOTA
14307 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
14308 +#endif
14309 +
14310 +        spin_unlock_bh(&quota_lock);
14311 +        return 0;
14312 +}
14313 +
14314 +static int
14315 +checkentry(const char *tablename,
14316 +           const struct ipt_ip *ip,
14317 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
14318 +{
14319 +        /* TODO: spinlocks? sanity checks? */
14320 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
14321 +                return 0;
14322 +
14323 +        return 1;
14324 +}
14325 +
14326 +static struct ipt_match quota_match = {
14327 +       .name = "quota",
14328 +       .match = match,
14329 +       .checkentry = checkentry,
14330 +       .me = THIS_MODULE
14331 +};
14332 +
14333 +static int __init
14334 +init(void)
14335 +{
14336 +        return ipt_register_match(&quota_match);
14337 +}
14338 +
14339 +static void __exit
14340 +fini(void)
14341 +{
14342 +        ipt_unregister_match(&quota_match);
14343 +}
14344 +
14345 +module_init(init);
14346 +module_exit(fini);
14347 +
14348 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_random.c
14349 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
14350 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_random.c     2004-06-08 10:31:56.000000000 +0200
14351 @@ -0,0 +1,96 @@
14352 +/*
14353 +  This is a module which is used for a "random" match support.
14354 +  This file is distributed under the terms of the GNU General Public
14355 +  License (GPL). Copies of the GPL can be obtained from:
14356 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
14357 +
14358 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
14359 +*/
14360 +
14361 +#include <linux/module.h>
14362 +#include <linux/skbuff.h>
14363 +#include <linux/ip.h>
14364 +#include <linux/random.h>
14365 +#include <net/tcp.h>
14366 +#include <linux/spinlock.h>
14367 +#include <linux/netfilter_ipv4/ip_tables.h>
14368 +#include <linux/netfilter_ipv4/ipt_random.h>
14369 +
14370 +MODULE_LICENSE("GPL");
14371 +
14372 +static int
14373 +ipt_rand_match(const struct sk_buff *pskb,
14374 +              const struct net_device *in,
14375 +              const struct net_device *out,
14376 +              const void *matchinfo,
14377 +              int offset,
14378 +              const void *hdr,
14379 +              u_int16_t datalen,
14380 +              int *hotdrop)
14381 +{
14382 +       /* Parameters from userspace */
14383 +       const struct ipt_rand_info *info = matchinfo;
14384 +       u_int8_t random_number;
14385 +
14386 +       /* get 1 random number from the kernel random number generation routine */
14387 +       get_random_bytes((void *)(&random_number), 1);
14388 +
14389 +       /* Do we match ? */
14390 +       if (random_number <= info->average)
14391 +               return 1;
14392 +       else
14393 +               return 0;
14394 +}
14395 +
14396 +static int
14397 +ipt_rand_checkentry(const char *tablename,
14398 +                  const struct ipt_ip *e,
14399 +                  void *matchinfo,
14400 +                  unsigned int matchsize,
14401 +                  unsigned int hook_mask)
14402 +{
14403 +       /* Parameters from userspace */
14404 +       const struct ipt_rand_info *info = matchinfo;
14405 +
14406 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
14407 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
14408 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
14409 +               return 0;
14410 +       }
14411 +
14412 +       /* must be  1 <= average % <= 99 */
14413 +       /* 1  x 2.55 = 2   */
14414 +       /* 99 x 2.55 = 252 */
14415 +       if ((info->average < 2) || (info->average > 252)) {
14416 +               printk("ipt_random:  invalid average %u\n", info->average);
14417 +               return 0;
14418 +       }
14419 +
14420 +       return 1;
14421 +}
14422 +
14423 +static struct ipt_match ipt_rand_reg = { 
14424 +       {NULL, NULL},
14425 +       "random",
14426 +       ipt_rand_match,
14427 +       ipt_rand_checkentry,
14428 +       NULL,
14429 +       THIS_MODULE };
14430 +
14431 +static int __init init(void)
14432 +{
14433 +       if (ipt_register_match(&ipt_rand_reg))
14434 +               return -EINVAL;
14435 +
14436 +       printk("ipt_random match loaded\n");
14437 +       return 0;
14438 +}
14439 +
14440 +static void __exit fini(void)
14441 +{
14442 +       ipt_unregister_match(&ipt_rand_reg);
14443 +       printk("ipt_random match unloaded\n");
14444 +}
14445 +
14446 +module_init(init);
14447 +module_exit(fini);
14448 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_realm.c
14449 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_realm.c  1970-01-01 01:00:00.000000000 +0100
14450 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_realm.c      2004-06-08 10:32:20.000000000 +0200
14451 @@ -0,0 +1,78 @@
14452 +/* IP tables module for matching the routing realm
14453 + *
14454 + * $Id$
14455 + *
14456 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
14457 + *
14458 + * This program is free software; you can redistribute it and/or modify
14459 + * it under the terms of the GNU General Public License version 2 as
14460 + * published by the Free Software Foundation.
14461 + */
14462 +
14463 +#include <linux/module.h>
14464 +#include <linux/skbuff.h>
14465 +#include <linux/netdevice.h>
14466 +#include <net/route.h>
14467 +
14468 +#include <linux/netfilter_ipv4/ipt_realm.h>
14469 +#include <linux/netfilter_ipv4/ip_tables.h>
14470 +
14471 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
14472 +MODULE_LICENSE("GPL");
14473 +
14474 +static int
14475 +match(const struct sk_buff *skb,
14476 +      const struct net_device *in,
14477 +      const struct net_device *out,
14478 +      const void *matchinfo,
14479 +      int offset,
14480 +      int *hotdrop)
14481 +{
14482 +       const struct ipt_realm_info *info = matchinfo;
14483 +       struct dst_entry *dst = skb->dst;
14484 +    
14485 +       if (!dst)
14486 +               return 0;
14487 +
14488 +       return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
14489 +}
14490 +
14491 +static int check(const char *tablename,
14492 +                 const struct ipt_ip *ip,
14493 +                 void *matchinfo,
14494 +                 unsigned int matchsize,
14495 +                 unsigned int hook_mask)
14496 +{
14497 +       if (hook_mask
14498 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
14499 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
14500 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
14501 +                      "LOCAL_IN or FORWARD.\n");
14502 +               return 0;
14503 +       }
14504 +
14505 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
14506 +               return 0;
14507 +
14508 +       return 1;
14509 +}
14510 +
14511 +static struct ipt_match realm_match = {
14512 +       .name = "realm",
14513 +       .match = match, 
14514 +       .checkentry = check,
14515 +       .me = THIS_MODULE
14516 +};
14517 +
14518 +static int __init init(void)
14519 +{
14520 +       return ipt_register_match(&realm_match);
14521 +}
14522 +
14523 +static void __exit fini(void)
14524 +{
14525 +       ipt_unregister_match(&realm_match);
14526 +}
14527 +
14528 +module_init(init);
14529 +module_exit(fini);
14530 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_sctp.c
14531 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_sctp.c   1970-01-01 01:00:00.000000000 +0100
14532 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_sctp.c       2004-06-08 10:32:21.000000000 +0200
14533 @@ -0,0 +1,199 @@
14534 +#include <linux/module.h>
14535 +#include <linux/skbuff.h>
14536 +#include <net/ip.h>
14537 +#include <linux/sctp.h>
14538 +
14539 +#include <linux/netfilter_ipv4/ip_tables.h>
14540 +#include <linux/netfilter_ipv4/ipt_sctp.h>
14541 +
14542 +#if 0
14543 +#define duprintf(format, args...) printk(format , ## args)
14544 +#else
14545 +#define duprintf(format, args...)
14546 +#endif
14547 +
14548 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
14549 +                                             || (!!((invflag) & (option)) ^ (cond)))
14550 +
14551 +static int
14552 +match_flags(const struct ipt_sctp_flag_info *flag_info,
14553 +           const int flag_count,
14554 +           u_int8_t chunktype,
14555 +           u_int8_t chunkflags)
14556 +{
14557 +       int i;
14558 +
14559 +       for (i = 0; i < flag_count; i++) {
14560 +               if (flag_info[i].chunktype == chunktype) {
14561 +                       return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
14562 +               }
14563 +       }
14564 +
14565 +       return 1;
14566 +}
14567 +
14568 +static int
14569 +match_packet(const struct sk_buff *skb,
14570 +            const u_int32_t *chunkmap,
14571 +            int chunk_match_type,
14572 +            const struct ipt_sctp_flag_info *flag_info,
14573 +            const int flag_count,
14574 +            int *hotdrop)
14575 +{
14576 +       int offset;
14577 +       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
14578 +       sctp_chunkhdr_t sch;
14579 +
14580 +       int i = 0;
14581 +
14582 +       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
14583 +               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
14584 +       }
14585 +
14586 +       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
14587 +       do {
14588 +               if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
14589 +                       duprintf("Dropping invalid SCTP packet.\n");
14590 +                       *hotdrop = 1;
14591 +                       return 0;
14592 +               }
14593 +
14594 +               duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
14595 +                               ++i, offset, sch.type, htons(sch.length), sch.flags);
14596 +
14597 +               offset += (htons(sch.length) + 3) & ~3;
14598 +
14599 +               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
14600 +
14601 +               if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
14602 +                       switch (chunk_match_type) {
14603 +                       case SCTP_CHUNK_MATCH_ANY:
14604 +                               if (match_flags(flag_info, flag_count, 
14605 +                                       sch.type, sch.flags)) {
14606 +                                       return 1;
14607 +                               }
14608 +                               break;
14609 +
14610 +                       case SCTP_CHUNK_MATCH_ALL:
14611 +                               if (match_flags(flag_info, flag_count, 
14612 +                                       sch.type, sch.flags)) {
14613 +                                       SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
14614 +                               }
14615 +                               break;
14616 +
14617 +                       case SCTP_CHUNK_MATCH_ONLY:
14618 +                               if (!match_flags(flag_info, flag_count, 
14619 +                                       sch.type, sch.flags)) {
14620 +                                       return 0;
14621 +                               }
14622 +                               break;
14623 +                       }
14624 +               } else {
14625 +                       switch (chunk_match_type) {
14626 +                       case SCTP_CHUNK_MATCH_ONLY:
14627 +                               return 0;
14628 +                       }
14629 +               }
14630 +       } while (offset < skb->len);
14631 +
14632 +       switch (chunk_match_type) {
14633 +       case SCTP_CHUNK_MATCH_ALL:
14634 +               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
14635 +       case SCTP_CHUNK_MATCH_ANY:
14636 +               return 0;
14637 +       case SCTP_CHUNK_MATCH_ONLY:
14638 +               return 1;
14639 +       }
14640 +
14641 +       /* This will never be reached, but required to stop compiler whine */
14642 +       return 0;
14643 +}
14644 +
14645 +static int
14646 +match(const struct sk_buff *skb,
14647 +      const struct net_device *in,
14648 +      const struct net_device *out,
14649 +      const void *matchinfo,
14650 +      int offset,
14651 +      int *hotdrop)
14652 +{
14653 +       const struct ipt_sctp_info *info;
14654 +       sctp_sctphdr_t sh;
14655 +
14656 +       info = (const struct ipt_sctp_info *)matchinfo;
14657 +
14658 +       if (offset) {
14659 +               duprintf("Dropping non-first fragment.. FIXME\n");
14660 +               return 0;
14661 +       }
14662 +       
14663 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
14664 +               duprintf("Dropping evil TCP offset=0 tinygram.\n");
14665 +               *hotdrop = 1;
14666 +               return 0;
14667 +               }
14668 +       duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
14669 +
14670 +       return  SCCHECK(((ntohs(sh.source) >= info->spts[0]) 
14671 +                       && (ntohs(sh.source) <= info->spts[1])), 
14672 +                       IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
14673 +               && SCCHECK(((ntohs(sh.dest) >= info->dpts[0]) 
14674 +                       && (ntohs(sh.dest) <= info->dpts[1])), 
14675 +                       IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
14676 +               && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
14677 +                                       info->flag_info, info->flag_count, 
14678 +                                       hotdrop),
14679 +                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
14680 +}
14681 +
14682 +static int
14683 +checkentry(const char *tablename,
14684 +          const struct ipt_ip *ip,
14685 +          void *matchinfo,
14686 +          unsigned int matchsize,
14687 +          unsigned int hook_mask)
14688 +{
14689 +       const struct ipt_sctp_info *info;
14690 +
14691 +       info = (const struct ipt_sctp_info *)matchinfo;
14692 +
14693 +       return ip->proto == IPPROTO_SCTP
14694 +               && !(ip->invflags & IPT_INV_PROTO)
14695 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
14696 +               && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
14697 +               && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
14698 +               && !(info->invflags & ~info->flags)
14699 +               && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
14700 +                       (info->chunk_match_type &
14701 +                               (SCTP_CHUNK_MATCH_ALL 
14702 +                               | SCTP_CHUNK_MATCH_ANY
14703 +                               | SCTP_CHUNK_MATCH_ONLY)));
14704 +}
14705 +
14706 +static struct ipt_match sctp_match = 
14707 +{ 
14708 +       .list = { NULL, NULL},
14709 +       .name = "sctp",
14710 +       .match = &match,
14711 +       .checkentry = &checkentry,
14712 +       .destroy = NULL,
14713 +       .me = THIS_MODULE
14714 +};
14715 +
14716 +static int __init init(void)
14717 +{
14718 +       return ipt_register_match(&sctp_match);
14719 +}
14720 +
14721 +static void __exit fini(void)
14722 +{
14723 +       ipt_unregister_match(&sctp_match);
14724 +}
14725 +
14726 +module_init(init);
14727 +module_exit(fini);
14728 +
14729 +MODULE_LICENSE("GPL");
14730 +MODULE_AUTHOR("Kiran Kumar Immidi");
14731 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
14732 +
14733 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_string.c
14734 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
14735 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_string.c     2004-06-08 10:41:24.000000000 +0200
14736 @@ -0,0 +1,183 @@
14737 +/* Kernel module to match a string into a packet.
14738 + *
14739 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
14740 + * 
14741 + * ChangeLog
14742 + *     24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
14743 + *             Initial 2.6 port
14744 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
14745 + *             Fixed SMP re-entrancy problem using per-cpu data areas
14746 + *             for the skip/shift tables.
14747 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14748 + *             Fixed kernel panic, due to overrunning boyer moore string
14749 + *             tables. Also slightly tweaked heuristic for deciding what
14750 + *             search algo to use.
14751 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
14752 + *             Implemented Boyer Moore Sublinear search algorithm
14753 + *             alongside the existing linear search based on memcmp().
14754 + *             Also a quick check to decide which method to use on a per
14755 + *             packet basis.
14756 + */
14757 +
14758 +#include <linux/smp.h>
14759 +#include <linux/percpu.h>
14760 +#include <linux/module.h>
14761 +#include <linux/skbuff.h>
14762 +#include <linux/file.h>
14763 +#include <net/sock.h>
14764 +
14765 +#include <linux/netfilter_ipv4/ip_tables.h>
14766 +#include <linux/netfilter_ipv4/ipt_string.h>
14767 +
14768 +MODULE_LICENSE("GPL");
14769 +
14770 +struct string_per_cpu {
14771 +       int skip[BM_MAX_HLEN];
14772 +       int shift[BM_MAX_HLEN];
14773 +       int len[BM_MAX_HLEN];
14774 +};
14775 +
14776 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
14777 +
14778 +
14779 +/* Boyer Moore Sublinear string search - VERY FAST */
14780 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
14781 +{
14782 +       int M1, right_end, sk, sh;  
14783 +       int ended, j, i;
14784 +
14785 +       int *skip, *shift, *len;
14786 +       
14787 +       /* use data suitable for this CPU */
14788 +       shift=__get_cpu_var(bm_string_data).shift;
14789 +       skip=__get_cpu_var(bm_string_data).skip;
14790 +       len=__get_cpu_var(bm_string_data).len;
14791 +       
14792 +       /* Setup skip/shift tables */
14793 +       M1 = right_end = needle_len-1;
14794 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
14795 +       for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
14796 +
14797 +       for (i = 1; i < needle_len; i++) {   
14798 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
14799 +               len[i] = j;  
14800 +       }  
14801 +
14802 +       shift[0] = 1;  
14803 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
14804 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
14805 +       ended = 0;  
14806 +       
14807 +       for (i = 0; i < needle_len; i++) {  
14808 +               if (len[i] == M1 - i) ended = i;  
14809 +               if (ended) shift[i] = ended;  
14810 +       }  
14811 +
14812 +       /* Do the search*/  
14813 +       while (right_end < haystack_len)
14814 +       {
14815 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
14816 +               if (i == needle_len) {
14817 +                       return haystack+(right_end - M1);
14818 +               }
14819 +               
14820 +               sk = skip[(int)haystack[right_end - i]];  
14821 +               sh = shift[i];
14822 +               right_end = max(right_end - i + sk, right_end + sh);  
14823 +       }
14824 +
14825 +       return NULL;
14826 +}  
14827 +
14828 +/* Linear string search based on memcmp() */
14829 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
14830 +{
14831 +       char *k = haystack + (haystack_len-needle_len);
14832 +       char *t = haystack;
14833 +       
14834 +       while ( t <= k ) {
14835 +               if (memcmp(t, needle, needle_len) == 0)
14836 +                       return t;
14837 +               t++;
14838 +       }
14839 +
14840 +       return NULL;
14841 +}
14842 +
14843 +static int
14844 +match(const struct sk_buff *skb,
14845 +      const struct net_device *in,
14846 +      const struct net_device *out,
14847 +      const void *matchinfo,
14848 +      int offset,
14849 +      int *hotdrop)
14850 +{
14851 +       const struct ipt_string_info *info = matchinfo;
14852 +       struct iphdr *ip = skb->nh.iph;
14853 +       int hlen, nlen;
14854 +       char *needle, *haystack;
14855 +       proc_ipt_search search=search_linear;
14856 +
14857 +       if ( !ip ) return 0;
14858 +
14859 +       /* get lenghts, and validate them */
14860 +       nlen=info->len;
14861 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
14862 +       if ( nlen > hlen ) return 0;
14863 +
14864 +       needle=(char *)&info->string;
14865 +       haystack=(char *)ip+(ip->ihl*4);
14866 +
14867 +       /* The sublinear search comes in to its own
14868 +        * on the larger packets */
14869 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
14870 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
14871 +               if ( hlen < BM_MAX_HLEN ) {
14872 +                       search=search_sublinear;
14873 +               }else{
14874 +                       if (net_ratelimit())
14875 +                               printk(KERN_INFO "ipt_string: Packet too big "
14876 +                                       "to attempt sublinear string search "
14877 +                                       "(%d bytes)\n", hlen );
14878 +               }
14879 +       }
14880 +       
14881 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
14882 +}
14883 +
14884 +static int
14885 +checkentry(const char *tablename,
14886 +           const struct ipt_ip *ip,
14887 +           void *matchinfo,
14888 +           unsigned int matchsize,
14889 +           unsigned int hook_mask)
14890 +{
14891 +
14892 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
14893 +               return 0;
14894 +
14895 +       return 1;
14896 +}
14897 +
14898 +static struct ipt_match string_match = {
14899 +    .name = "string",
14900 +    .match = &match,
14901 +    .checkentry = &checkentry,
14902 +    .me = THIS_MODULE
14903 +};
14904 +
14905 +
14906 +static int __init init(void)
14907 +{
14908 +       return ipt_register_match(&string_match);
14909 +}
14910 +
14911 +static void __exit fini(void)
14912 +{
14913 +       ipt_unregister_match(&string_match);
14914 +}
14915 +
14916 +module_init(init);
14917 +module_exit(fini);
14918 +
14919 +
14920 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_time.c
14921 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_time.c   1970-01-01 01:00:00.000000000 +0100
14922 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_time.c       2004-06-08 10:32:31.000000000 +0200
14923 @@ -0,0 +1,189 @@
14924 +/*
14925 +  This is a module which is used for time matching
14926 +  It is using some modified code from dietlibc (localtime() function)
14927 +  that you can find at http://www.fefe.de/dietlibc/
14928 +  This file is distributed under the terms of the GNU General Public
14929 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
14930 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
14931 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
14932 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
14933 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
14934 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
14935 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
14936 +  2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
14937 +*/
14938 +
14939 +#include <linux/module.h>
14940 +#include <linux/skbuff.h>
14941 +#include <linux/netfilter_ipv4/ip_tables.h>
14942 +#include <linux/netfilter_ipv4/ipt_time.h>
14943 +#include <linux/time.h>
14944 +
14945 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
14946 +MODULE_DESCRIPTION("Match arrival timestamp/date");
14947 +MODULE_LICENSE("GPL");
14948 +
14949 +struct tm
14950 +{
14951 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
14952 +       int tm_min;                   /* Minutes.     [0-59] */
14953 +       int tm_hour;                  /* Hours.       [0-23] */
14954 +       int tm_mday;                  /* Day.         [1-31] */
14955 +       int tm_mon;                   /* Month.       [0-11] */
14956 +       int tm_year;                  /* Year - 1900.  */
14957 +       int tm_wday;                  /* Day of week. [0-6] */
14958 +       int tm_yday;                  /* Days in year.[0-365] */
14959 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
14960 +
14961 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
14962 +       const char *tm_zone;          /* we don't care, we count from GMT */
14963 +};
14964 +
14965 +void
14966 +localtime(const time_t *timepr, struct tm *r);
14967 +
14968 +static int
14969 +match(const struct sk_buff *skb,
14970 +      const struct net_device *in,
14971 +      const struct net_device *out,
14972 +      const void *matchinfo,
14973 +      int offset,
14974 +      const void *hdr,
14975 +      u_int16_t datalen,
14976 +      int *hotdrop)
14977 +{
14978 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
14979 +       struct tm currenttime;                          /* time human readable */
14980 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
14981 +       u_int16_t packet_time;
14982 +       struct timeval kerneltimeval;
14983 +       time_t packet_local_time;
14984 +
14985 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
14986 +       if (info->kerneltime)
14987 +       {
14988 +               do_gettimeofday(&kerneltimeval);
14989 +               packet_local_time = kerneltimeval.tv_sec;
14990 +       }
14991 +       else
14992 +               packet_local_time = skb->stamp.tv_sec;
14993 +
14994 +       /* First we make sure we are in the date start-stop boundaries */
14995 +       if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
14996 +               return 0; /* We are outside the date boundaries */
14997 +
14998 +       /* Transform the timestamp of the packet, in a human readable form */
14999 +       localtime(&packet_local_time, &currenttime);
15000 +
15001 +       /* check if we match this timestamp, we start by the days... */
15002 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
15003 +               return 0; /* the day doesn't match */
15004 +
15005 +       /* ... check the time now */
15006 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
15007 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
15008 +               return 0;
15009 +
15010 +       /* here we match ! */
15011 +       return 1;
15012 +}
15013 +
15014 +static int
15015 +checkentry(const char *tablename,
15016 +           const struct ipt_ip *ip,
15017 +           void *matchinfo,
15018 +           unsigned int matchsize,
15019 +           unsigned int hook_mask)
15020 +{
15021 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
15022 +
15023 +       /* First, check that we are in the correct hooks */
15024 +       if (hook_mask
15025 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
15026 +       {
15027 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
15028 +               return 0;
15029 +       }
15030 +       /* we use the kerneltime if we are in forward or output */
15031 +       info->kerneltime = 1;
15032 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
15033 +               /* we use the skb time */
15034 +               info->kerneltime = 0;
15035 +
15036 +       /* Check the size */
15037 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
15038 +               return 0;
15039 +       /* Now check the coherence of the data ... */
15040 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
15041 +           (info->time_stop  > 1439))
15042 +       {
15043 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
15044 +               return 0;
15045 +       }
15046 +
15047 +       return 1;
15048 +}
15049 +
15050 +static struct ipt_match time_match
15051 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
15052 +
15053 +static int __init init(void)
15054 +{
15055 +       printk("ipt_time loading\n");
15056 +       return ipt_register_match(&time_match);
15057 +}
15058 +
15059 +static void __exit fini(void)
15060 +{
15061 +       ipt_unregister_match(&time_match);
15062 +       printk("ipt_time unloaded\n");
15063 +}
15064 +
15065 +module_init(init);
15066 +module_exit(fini);
15067 +
15068 +
15069 +/* The part below is borowed and modified from dietlibc */
15070 +
15071 +/* seconds per day */
15072 +#define SPD 24*60*60
15073 +
15074 +void
15075 +localtime(const time_t *timepr, struct tm *r) {
15076 +       time_t i;
15077 +       time_t timep;
15078 +       extern struct timezone sys_tz;
15079 +       const unsigned int __spm[12] =
15080 +               { 0,
15081 +                 (31),
15082 +                 (31+28),
15083 +                 (31+28+31),
15084 +                 (31+28+31+30),
15085 +                 (31+28+31+30+31),
15086 +                 (31+28+31+30+31+30),
15087 +                 (31+28+31+30+31+30+31),
15088 +                 (31+28+31+30+31+30+31+31),
15089 +                 (31+28+31+30+31+30+31+31+30),
15090 +                 (31+28+31+30+31+30+31+31+30+31),
15091 +                 (31+28+31+30+31+30+31+31+30+31+30),
15092 +               };
15093 +       register time_t work;
15094 +
15095 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
15096 +       work=timep%(SPD);
15097 +       r->tm_sec=work%60; work/=60;
15098 +       r->tm_min=work%60; r->tm_hour=work/60;
15099 +       work=timep/(SPD);
15100 +       r->tm_wday=(4+work)%7;
15101 +       for (i=1970; ; ++i) {
15102 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
15103 +               if (work>k)
15104 +                       work-=k;
15105 +               else
15106 +                       break;
15107 +       }
15108 +       r->tm_year=i-1900;
15109 +       for (i=11; i && __spm[i]>work; --i) ;
15110 +       r->tm_mon=i;
15111 +       r->tm_mday=work-__spm[i]+1;
15112 +}
15113 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_u32.c
15114 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_u32.c    1970-01-01 01:00:00.000000000 +0100
15115 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_u32.c        2004-06-08 10:32:32.000000000 +0200
15116 @@ -0,0 +1,211 @@
15117 +/* Kernel module to match u32 packet content. */
15118 +
15119 +/* 
15120 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
15121 +have specified values.  The specification of what to extract is general 
15122 +enough to find data at given offsets from tcp headers or payloads.
15123 +
15124 + --u32 tests
15125 + The argument amounts to a program in a small language described below.
15126 + tests := location = value |  tests && location = value
15127 + value := range | value , range
15128 + range := number | number : number
15129 +  a single number, n, is interpreted the same as n:n
15130 +  n:m is interpreted as the range of numbers >=n and <=m
15131 + location := number | location operator number
15132 + operator := & | << | >> | @
15133 +
15134 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
15135 + membership operator and the value syntax describes a set.  The @ operator
15136 + is what allows moving to the next header and is described further below.
15137 +
15138 + *** Until I can find out how to avoid it, there are some artificial limits
15139 + on the size of the tests:
15140 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
15141 + - no more than 10 ranges (and 9 commas) per value
15142 + - no more than 10 numbers (and 9 operators) per location
15143 +
15144 + To describe the meaning of location, imagine the following machine that
15145 + interprets it.  There are three registers:
15146 +  A is of type char*, initially the address of the IP header
15147 +  B and C are unsigned 32 bit integers, initially zero
15148 +
15149 +  The instructions are:
15150 +   number      B = number;
15151 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
15152 +   &number     C = C&number
15153 +   <<number    C = C<<number
15154 +   >>number    C = C>>number
15155 +   @number     A = A+C; then do the instruction number
15156 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
15157 +  Otherwise the result of the computation is the final value of C.
15158 +
15159 + Whitespace is allowed but not required in the tests.
15160 + However the characters that do occur there are likely to require
15161 + shell quoting, so it's a good idea to enclose the arguments in quotes.
15162 +
15163 +Example:
15164 + match IP packets with total length >= 256
15165 + The IP header contains a total length field in bytes 2-3.
15166 + --u32 "0&0xFFFF=0x100:0xFFFF" 
15167 + read bytes 0-3
15168 + AND that with FFFF (giving bytes 2-3),
15169 + and test whether that's in the range [0x100:0xFFFF]
15170 +
15171 +Example: (more realistic, hence more complicated)
15172 + match icmp packets with icmp type 0
15173 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
15174 + --u32 "6&0xFF=1 && ...
15175 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
15176 + Next test that it's not a fragment.
15177 +  (If so it might be part of such a packet but we can't always tell.)
15178 +  n.b. This test is generally needed if you want to match anything
15179 +  beyond the IP header.
15180 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
15181 + packet (not a fragment).  Alternatively, you can allow first fragments
15182 + by only testing the last 5 bits of byte 6.
15183 + ... 4&0x3FFF=0 && ...
15184 + Last test: the first byte past the IP header (the type) is 0
15185 + This is where we have to use the @syntax.  The length of the IP header
15186 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
15187 + IP header itself.
15188 + ... 0>>22&0x3C@0>>24=0"
15189 + The first 0 means read bytes 0-3,
15190 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
15191 +   the first byte, so only 22 bits is four times that plus a few more bits.
15192 + &3C then eliminates the two extra bits on the right and the first four 
15193 + bits of the first byte.
15194 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
15195 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
15196 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
15197 + @ means to use this number as a new offset into the packet, and read
15198 + four bytes starting from there.  This is the first 4 bytes of the icmp
15199 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
15200 + the value 24 to the right to throw out all but the first byte and compare
15201 + the result with 0.
15202 +
15203 +Example: 
15204 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
15205 + First we test that the packet is a tcp packet (similar to icmp).
15206 + --u32 "6&0xFF=6 && ...
15207 + Next, test that it's not a fragment (same as above).
15208 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
15209 + 0>>22&3C as above computes the number of bytes in the IP header.
15210 + @ makes this the new offset into the packet, which is the start of the
15211 + tcp header.  The length of the tcp header (again in 32 bit words) is
15212 + the left half of byte 12 of the tcp header.  The 12>>26&3C
15213 + computes this length in bytes (similar to the IP header before).
15214 + @ makes this the new offset, which is the start of the tcp payload.
15215 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
15216 + result is any of 1, 2, 5 or 8
15217 +*/
15218 +
15219 +#include <linux/module.h>
15220 +#include <linux/skbuff.h>
15221 +
15222 +#include <linux/netfilter_ipv4/ipt_u32.h>
15223 +#include <linux/netfilter_ipv4/ip_tables.h>
15224 +
15225 +/* #include <asm-i386/timex.h> for timing */
15226 +
15227 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
15228 +MODULE_DESCRIPTION("IP tables u32 matching module");
15229 +MODULE_LICENSE("GPL");
15230 +
15231 +static int
15232 +match(const struct sk_buff *skb,
15233 +      const struct net_device *in,
15234 +      const struct net_device *out,
15235 +      const void *matchinfo,
15236 +      int offset,
15237 +      const void *hdr,
15238 +      u_int16_t datalen,
15239 +      int *hotdrop)
15240 +{
15241 +       const struct ipt_u32 *data = matchinfo;
15242 +       int testind, i;
15243 +       unsigned char* origbase = (char*)skb->nh.iph;
15244 +       unsigned char* base = origbase;
15245 +       unsigned char* head = skb->head;
15246 +       unsigned char* end = skb->end;
15247 +       int nnums, nvals;
15248 +       u_int32_t pos, val;
15249 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
15250 +          cycles1 = get_cycles(); */
15251 +
15252 +       for (testind=0; testind < data->ntests; testind++) {
15253 +               base = origbase; /* reset for each test */
15254 +               pos = data->tests[testind].location[0].number;
15255 +               if (base+pos+3 > end || base+pos < head) 
15256 +                       return 0;
15257 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
15258 +                       (base[pos+2]<<8) + base[pos+3];
15259 +               nnums = data->tests[testind].nnums;
15260 +               for (i=1; i < nnums; i++) {
15261 +                       u_int32_t number = data->tests[testind].location[i].number;
15262 +                       switch (data->tests[testind].location[i].nextop) {
15263 +                       case IPT_U32_AND: 
15264 +                               val = val & number; 
15265 +                               break;
15266 +                       case IPT_U32_LEFTSH: 
15267 +                               val = val << number;
15268 +                               break;
15269 +                       case IPT_U32_RIGHTSH: 
15270 +                               val = val >> number; 
15271 +                               break;
15272 +                       case IPT_U32_AT:
15273 +                               base = base + val;
15274 +                               pos = number;
15275 +                               if (base+pos+3 > end || base+pos < head) 
15276 +                                       return 0;
15277 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
15278 +                                       (base[pos+2]<<8) + base[pos+3];
15279 +                               break;
15280 +                       }
15281 +               }
15282 +               nvals = data->tests[testind].nvalues;
15283 +               for (i=0; i < nvals; i++) {
15284 +                       if ((data->tests[testind].value[i].min <= val) &&
15285 +                           (val <= data->tests[testind].value[i].max)) {
15286 +                               break;
15287 +                       }
15288 +               }
15289 +               if (i >= data->tests[testind].nvalues) {
15290 +                       /* cycles2 = get_cycles(); 
15291 +                          printk("failed %d in %d cycles\n", testind, 
15292 +                                 cycles2-cycles1); */
15293 +                       return 0;
15294 +               }
15295 +       }
15296 +       /* cycles2 = get_cycles();
15297 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
15298 +       return 1;
15299 +}
15300 +
15301 +static int
15302 +checkentry(const char *tablename,
15303 +           const struct ipt_ip *ip,
15304 +           void *matchinfo,
15305 +           unsigned int matchsize,
15306 +           unsigned int hook_mask)
15307 +{
15308 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
15309 +               return 0;
15310 +       return 1;
15311 +}
15312 +
15313 +static struct ipt_match u32_match
15314 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
15315 +
15316 +static int __init init(void)
15317 +{
15318 +       return ipt_register_match(&u32_match);
15319 +}
15320 +
15321 +static void __exit fini(void)
15322 +{
15323 +       ipt_unregister_match(&u32_match);
15324 +}
15325 +
15326 +module_init(init);
15327 +module_exit(fini);
15328 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.7-rc3/net/ipv4/netfilter/ipt_unclean.c
15329 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/ipt_unclean.c        1970-01-01 01:00:00.000000000 +0100
15330 +++ linux-2.6.7-rc3/net/ipv4/netfilter/ipt_unclean.c    2004-06-08 10:41:16.000000000 +0200
15331 @@ -0,0 +1,604 @@
15332 +/* Kernel module to match suspect packets. */
15333 +#include <linux/module.h>
15334 +#include <linux/skbuff.h>
15335 +#include <linux/ip.h>
15336 +#include <linux/udp.h>
15337 +#include <linux/tcp.h>
15338 +#include <linux/icmp.h>
15339 +#include <net/checksum.h>
15340 +
15341 +#include <linux/netfilter_ipv4/ip_tables.h>
15342 +
15343 +#define limpk(format, args...)                                          \
15344 +do {                                                                    \
15345 +       if (net_ratelimit())                                             \
15346 +               printk("ipt_unclean: %s" format,                         \
15347 +                      embedded ? "(embedded packet) " : "" , ## args);  \
15348 +} while(0)
15349 +
15350 +enum icmp_error_status
15351 +{
15352 +       ICMP_MAY_BE_ERROR,
15353 +       ICMP_IS_ERROR,
15354 +       ICMP_NOT_ERROR
15355 +};
15356 +
15357 +struct icmp_info
15358 +{
15359 +       size_t min_len, max_len;
15360 +       enum icmp_error_status err;
15361 +       u_int8_t min_code, max_code;
15362 +};
15363 +
15364 +static int
15365 +check_ip(struct iphdr *iph, size_t length, int embedded);
15366 +
15367 +/* ICMP-specific checks. */
15368 +static int
15369 +check_icmp(const struct icmphdr *icmph,
15370 +          u_int16_t datalen,
15371 +          unsigned int offset,
15372 +          int more_frags,
15373 +          int embedded)
15374 +{
15375 +       static struct icmp_info info[]
15376 +               = { [ICMP_ECHOREPLY]
15377 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15378 +                   [ICMP_DEST_UNREACH]
15379 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
15380 +                   [ICMP_SOURCE_QUENCH]
15381 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
15382 +                   [ICMP_REDIRECT]
15383 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
15384 +                   [ICMP_ECHO]
15385 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0  },
15386 +                   /* Router advertisement. */
15387 +                   [9]
15388 +                   = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
15389 +                   /* Router solicitation. */
15390 +                   [10]
15391 +                   = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
15392 +                   [ICMP_TIME_EXCEEDED]
15393 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1  },
15394 +                   [ICMP_PARAMETERPROB]
15395 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
15396 +                   [ICMP_TIMESTAMP]
15397 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15398 +                   [ICMP_TIMESTAMPREPLY]
15399 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
15400 +                   [ICMP_INFO_REQUEST]
15401 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15402 +                   [ICMP_INFO_REPLY]
15403 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
15404 +                   [ICMP_ADDRESS]
15405 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
15406 +                   [ICMP_ADDRESSREPLY]
15407 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
15408 +
15409 +       /* Can't do anything if it's a fragment. */
15410 +       if (offset)
15411 +               return 1;
15412 +
15413 +       /* Must cover type and code. */
15414 +       if (datalen < 2) {
15415 +               limpk("ICMP len=%u too short\n", datalen);
15416 +               return 0;
15417 +       }
15418 +
15419 +       /* If not embedded. */
15420 +       if (!embedded) {
15421 +               /* Bad checksum?  Don't print, just ignore. */
15422 +               if (!more_frags
15423 +                   && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
15424 +                       return 0;
15425 +
15426 +               /* CHECK: Truncated ICMP (even if first fragment). */
15427 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15428 +                   && info[icmph->type].min_len != 0
15429 +                   && datalen < info[icmph->type].min_len) {
15430 +                       limpk("ICMP type %u len %u too short\n",
15431 +                             icmph->type, datalen);
15432 +                       return 0;
15433 +               }
15434 +
15435 +               /* CHECK: Check within known error ICMPs. */
15436 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15437 +                   && info[icmph->type].err == ICMP_IS_ERROR) {
15438 +                       /* CHECK: Embedded packet must be at least
15439 +                          length of iph + 8 bytes. */
15440 +                       struct iphdr *inner = (void *)icmph + 8;
15441 +
15442 +                       /* datalen > 8 since all ICMP_IS_ERROR types
15443 +                           have min length > 8 */
15444 +                       if (datalen - 8 < sizeof(struct iphdr)) {
15445 +                               limpk("ICMP error internal way too short\n");
15446 +                               return 0;
15447 +                       }
15448 +                       if (datalen - 8 < inner->ihl*4 + 8) {
15449 +                               limpk("ICMP error internal too short\n");
15450 +                               return 0;
15451 +                       }
15452 +                       if (!check_ip(inner, datalen - 8, 1))
15453 +                               return 0;
15454 +               }
15455 +       } else {
15456 +               /* CHECK: Can't embed ICMP unless known non-error. */
15457 +               if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
15458 +                   || info[icmph->type].err != ICMP_NOT_ERROR) {
15459 +                       limpk("ICMP type %u not embeddable\n",
15460 +                             icmph->type);
15461 +                       return 0;
15462 +               }
15463 +       }
15464 +
15465 +       /* CHECK: Invalid ICMP codes. */
15466 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15467 +           && (icmph->code < info[icmph->type].min_code
15468 +               || icmph->code > info[icmph->type].max_code)) {
15469 +               limpk("ICMP type=%u code=%u\n",
15470 +                     icmph->type, icmph->code);
15471 +               return 0;
15472 +       }
15473 +
15474 +       /* CHECK: Above maximum length. */
15475 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
15476 +           && info[icmph->type].max_len != 0
15477 +           && datalen > info[icmph->type].max_len) {
15478 +               limpk("ICMP type=%u too long: %u bytes\n",
15479 +                     icmph->type, datalen);
15480 +               return 0;
15481 +       }
15482 +
15483 +       switch (icmph->type) {
15484 +       case ICMP_PARAMETERPROB: {
15485 +               /* CHECK: Problem param must be within error packet's
15486 +                * IP header. */
15487 +               struct iphdr *iph = (void *)icmph + 8;
15488 +               u_int32_t arg = ntohl(icmph->un.gateway);
15489 +
15490 +               if (icmph->code == 0) {
15491 +                       /* Code 0 means that upper 8 bits is pointer
15492 +                           to problem. */
15493 +                       if ((arg >> 24) >= iph->ihl*4) {
15494 +                               limpk("ICMP PARAMETERPROB ptr = %u\n",
15495 +                                     ntohl(icmph->un.gateway) >> 24);
15496 +                               return 0;
15497 +                       }
15498 +                       arg &= 0x00FFFFFF;
15499 +               }
15500 +
15501 +               /* CHECK: Rest must be zero. */
15502 +               if (arg) {
15503 +                       limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
15504 +                             arg);
15505 +                       return 0;
15506 +               }
15507 +               break;
15508 +       }
15509 +
15510 +       case ICMP_TIME_EXCEEDED:
15511 +       case ICMP_SOURCE_QUENCH:
15512 +               /* CHECK: Unused must be zero. */
15513 +               if (icmph->un.gateway != 0) {
15514 +                       limpk("ICMP type=%u unused = %u\n",
15515 +                             icmph->type, ntohl(icmph->un.gateway));
15516 +                       return 0;
15517 +               }
15518 +               break;
15519 +       }
15520 +
15521 +       return 1;
15522 +}
15523 +
15524 +/* UDP-specific checks. */
15525 +static int
15526 +check_udp(const struct iphdr *iph,
15527 +         const struct udphdr *udph,
15528 +         u_int16_t datalen,
15529 +         unsigned int offset,
15530 +         int more_frags,
15531 +         int embedded)
15532 +{
15533 +       /* Can't do anything if it's a fragment. */
15534 +       if (offset)
15535 +               return 1;
15536 +
15537 +       /* CHECK: Must cover UDP header. */
15538 +       if (datalen < sizeof(struct udphdr)) {
15539 +               limpk("UDP len=%u too short\n", datalen);
15540 +               return 0;
15541 +       }
15542 +
15543 +       /* Bad checksum?  Don't print, just say it's unclean. */
15544 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
15545 +       if (!more_frags && !embedded && udph->check
15546 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
15547 +                                csum_partial((char *)udph, datalen, 0)) != 0)
15548 +               return 0;
15549 +
15550 +       /* CHECK: Destination port can't be zero. */
15551 +       if (!udph->dest) {
15552 +               limpk("UDP zero destination port\n");
15553 +               return 0;
15554 +       }
15555 +
15556 +       if (!more_frags) {
15557 +               if (!embedded) {
15558 +                       /* CHECK: UDP length must match. */
15559 +                       if (ntohs(udph->len) != datalen) {
15560 +                               limpk("UDP len too short %u vs %u\n",
15561 +                                     ntohs(udph->len), datalen);
15562 +                               return 0;
15563 +                       }
15564 +               } else {
15565 +                       /* CHECK: UDP length be >= this truncated pkt. */
15566 +                       if (ntohs(udph->len) < datalen) {
15567 +                               limpk("UDP len too long %u vs %u\n",
15568 +                                     ntohs(udph->len), datalen);
15569 +                               return 0;
15570 +                       }
15571 +               }
15572 +       } else {
15573 +               /* CHECK: UDP length must be > this frag's length. */
15574 +               if (ntohs(udph->len) <= datalen) {
15575 +                       limpk("UDP fragment len too short %u vs %u\n",
15576 +                             ntohs(udph->len), datalen);
15577 +                       return 0;
15578 +               }
15579 +       }
15580 +
15581 +       return 1;
15582 +}
15583 +
15584 +#define        TH_FIN  0x01
15585 +#define        TH_SYN  0x02
15586 +#define        TH_RST  0x04
15587 +#define        TH_PUSH 0x08
15588 +#define        TH_ACK  0x10
15589 +#define        TH_URG  0x20
15590 +#define        TH_ECE  0x40
15591 +#define        TH_CWR  0x80
15592 +
15593 +/* table of valid flag combinations - ECE and CWR are always valid */
15594 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
15595 +{
15596 +       [TH_SYN]                        = 1,
15597 +       [TH_SYN|TH_ACK]                 = 1,
15598 +       [TH_RST]                        = 1,
15599 +       [TH_RST|TH_ACK]                 = 1,
15600 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
15601 +       [TH_FIN|TH_ACK]                 = 1,
15602 +       [TH_ACK]                        = 1,
15603 +       [TH_ACK|TH_PUSH]                = 1,
15604 +       [TH_ACK|TH_URG]                 = 1,
15605 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
15606 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
15607 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
15608 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
15609 +};
15610 +
15611 +/* TCP-specific checks. */
15612 +static int
15613 +check_tcp(const struct iphdr *iph,
15614 +         const struct tcphdr *tcph,
15615 +         u_int16_t datalen,
15616 +         unsigned int offset,
15617 +         int more_frags,
15618 +         int embedded)
15619 +{
15620 +       u_int8_t *opt = (u_int8_t *)tcph;
15621 +       u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
15622 +       u_int8_t tcpflags;
15623 +       int end_of_options = 0;
15624 +       size_t i;
15625 +
15626 +       /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
15627 +       /* In fact, this is caught below (offset < 516). */
15628 +
15629 +       /* Can't do anything if it's a fragment. */
15630 +       if (offset)
15631 +               return 1;
15632 +
15633 +       /* CHECK: Smaller than minimal TCP hdr. */
15634 +       if (datalen < sizeof(struct tcphdr)) {
15635 +               if (!embedded) {
15636 +                       limpk("Packet length %u < TCP header.\n", datalen);
15637 +                       return 0;
15638 +               }
15639 +               /* Must have ports available (datalen >= 8), from
15640 +                   check_icmp which set embedded = 1 */
15641 +               /* CHECK: TCP ports inside ICMP error */
15642 +               if (!tcph->source || !tcph->dest) {
15643 +                       limpk("Zero TCP ports %u/%u.\n",
15644 +                             htons(tcph->source), htons(tcph->dest));
15645 +                       return 0;
15646 +               }
15647 +               return 1;
15648 +       }
15649 +
15650 +       /* CHECK: Smaller than actual TCP hdr. */
15651 +       if (datalen < tcph->doff * 4) {
15652 +               if (!embedded) {
15653 +                       limpk("Packet length %u < actual TCP header.\n",
15654 +                             datalen);
15655 +                       return 0;
15656 +               } else
15657 +                       return 1;
15658 +       }
15659 +
15660 +       /* Bad checksum?  Don't print, just say it's unclean. */
15661 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
15662 +       if (!more_frags && !embedded
15663 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
15664 +                                csum_partial((char *)tcph, datalen, 0)) != 0)
15665 +               return 0;
15666 +
15667 +       /* CHECK: TCP ports non-zero */
15668 +       if (!tcph->source || !tcph->dest) {
15669 +               limpk("Zero TCP ports %u/%u.\n",
15670 +                     htons(tcph->source), htons(tcph->dest));
15671 +               return 0;
15672 +       }
15673 +
15674 +       /* CHECK: TCP reserved bits zero. */
15675 +       if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
15676 +               limpk("TCP reserved bits not zero\n");
15677 +               return 0;
15678 +       }
15679 +
15680 +       /* CHECK: TCP flags. */
15681 +       tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
15682 +       if (!tcp_valid_flags[tcpflags]) {
15683 +               limpk("TCP flags bad: %u\n", tcpflags);
15684 +               return 0;
15685 +       }
15686 +
15687 +       for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
15688 +               switch (opt[i]) {
15689 +               case 0:
15690 +                       end_of_options = 1;
15691 +                       i++;
15692 +                       break;
15693 +               case 1:
15694 +                       i++;
15695 +                       break;
15696 +               default:
15697 +                       /* CHECK: options after EOO. */
15698 +                       if (end_of_options) {
15699 +                               limpk("TCP option %u after end\n",
15700 +                                     opt[i]);
15701 +                               return 0;
15702 +                       }
15703 +                       /* CHECK: options at tail. */
15704 +                       else if (i+1 >= tcph->doff * 4) {
15705 +                               limpk("TCP option %u at tail\n",
15706 +                                     opt[i]);
15707 +                               return 0;
15708 +                       }
15709 +                       /* CHECK: zero-length options. */
15710 +                       else if (opt[i+1] == 0) {
15711 +                               limpk("TCP option %u 0 len\n",
15712 +                                     opt[i]);
15713 +                               return 0;
15714 +                       }
15715 +                       /* CHECK: oversize options. */
15716 +                       else if (&opt[i] + opt[i+1] > endhdr) {
15717 +                               limpk("TCP option %u at %Zu too long\n",
15718 +                                     (unsigned int) opt[i], i);
15719 +                               return 0;
15720 +                       }
15721 +                       /* Move to next option */
15722 +                       i += opt[i+1];
15723 +               }
15724 +       }
15725 +
15726 +       return 1;
15727 +}
15728 +
15729 +/* Returns 1 if ok */
15730 +/* Standard IP checks. */
15731 +static int
15732 +check_ip(struct iphdr *iph, size_t length, int embedded)
15733 +{
15734 +       u_int8_t *opt = (u_int8_t *)iph;
15735 +       u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
15736 +       int end_of_options = 0;
15737 +       void *protoh;
15738 +       size_t datalen;
15739 +       unsigned int i;
15740 +       unsigned int offset;
15741 +
15742 +       /* Should only happen for local outgoing raw-socket packets. */
15743 +       /* CHECK: length >= ip header. */
15744 +       if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
15745 +               limpk("Packet length %Zu < IP header.\n", length);
15746 +               return 0;
15747 +       }
15748 +
15749 +       offset = ntohs(iph->frag_off) & IP_OFFSET;
15750 +       protoh = (void *)iph + iph->ihl * 4;
15751 +       datalen = length - iph->ihl * 4;
15752 +
15753 +       /* CHECK: Embedded fragment. */
15754 +       if (embedded && offset) {
15755 +               limpk("Embedded fragment.\n");
15756 +               return 0;
15757 +       }
15758 +
15759 +       for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
15760 +               switch (opt[i]) {
15761 +               case 0:
15762 +                       end_of_options = 1;
15763 +                       i++;
15764 +                       break;
15765 +               case 1:
15766 +                       i++;
15767 +                       break;
15768 +               default:
15769 +                       /* CHECK: options after EOO. */
15770 +                       if (end_of_options) {
15771 +                               limpk("IP option %u after end\n",
15772 +                                     opt[i]);
15773 +                               return 0;
15774 +                       }
15775 +                       /* CHECK: options at tail. */
15776 +                       else if (i+1 >= iph->ihl * 4) {
15777 +                               limpk("IP option %u at tail\n",
15778 +                                     opt[i]);
15779 +                               return 0;
15780 +                       }
15781 +                       /* CHECK: zero-length or one-length options. */
15782 +                       else if (opt[i+1] < 2) {
15783 +                               limpk("IP option %u %u len\n",
15784 +                                     opt[i], opt[i+1]);
15785 +                               return 0;
15786 +                       }
15787 +                       /* CHECK: oversize options. */
15788 +                       else if (&opt[i] + opt[i+1] > endhdr) {
15789 +                               limpk("IP option %u at %u too long\n",
15790 +                                     opt[i], i);
15791 +                               return 0;
15792 +                       }
15793 +                       /* Move to next option */
15794 +                       i += opt[i+1];
15795 +               }
15796 +       }
15797 +
15798 +       /* Fragment checks. */
15799 +
15800 +       /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
15801 +       if ((ntohs(iph->frag_off) & IP_MF)
15802 +           && (ntohs(iph->tot_len) % 8) != 0) {
15803 +               limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
15804 +               return 0;
15805 +       }
15806 +
15807 +       /* CHECK: Oversize fragment a-la Ping of Death. */
15808 +       if (offset * 8 + datalen > 65535) {
15809 +               limpk("Oversize fragment to %u.\n", offset * 8);
15810 +               return 0;
15811 +       }
15812 +
15813 +       /* CHECK: DF set and offset or MF set. */
15814 +       if ((ntohs(iph->frag_off) & IP_DF)
15815 +           && (offset || (ntohs(iph->frag_off) & IP_MF))) {
15816 +               limpk("DF set and offset=%u, MF=%u.\n",
15817 +                     offset, ntohs(iph->frag_off) & IP_MF);
15818 +               return 0;
15819 +       }
15820 +
15821 +       /* CHECK: Zero-sized fragments. */
15822 +       if ((offset || (ntohs(iph->frag_off) & IP_MF))
15823 +           && datalen == 0) {
15824 +               limpk("Zero size fragment offset=%u\n", offset);
15825 +               return 0;
15826 +       }
15827 +
15828 +       /* Note: we can have even middle fragments smaller than this:
15829 +          consider a large packet passing through a 600MTU then
15830 +          576MTU link: this gives a fragment of 24 data bytes.  But
15831 +          everyone packs fragments largest first, hence a fragment
15832 +          can't START before 576 - MAX_IP_HEADER_LEN. */
15833 +
15834 +       /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
15835 +          down to 128 (576 taken from RFC 791: All hosts must be
15836 +          prepared to accept datagrams of up to 576 octets).  Use 128
15837 +          here. */
15838 +#define MIN_LIKELY_MTU 128
15839 +       /* CHECK: Min size of first frag = 128. */
15840 +       if ((ntohs(iph->frag_off) & IP_MF)
15841 +           && offset == 0
15842 +           && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
15843 +               limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
15844 +                     MIN_LIKELY_MTU);
15845 +               return 0;
15846 +       }
15847 +
15848 +       /* CHECK: Min offset of frag = 128 - IP hdr len. */
15849 +       if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
15850 +               limpk("Fragment starts at %u < %u\n", offset * 8,
15851 +                     MIN_LIKELY_MTU - iph->ihl * 4);
15852 +               return 0;
15853 +       }
15854 +
15855 +       /* CHECK: Protocol specification non-zero. */
15856 +       if (iph->protocol == 0) {
15857 +               limpk("Zero protocol\n");
15858 +               return 0;
15859 +       }
15860 +
15861 +       /* CHECK: Do not use what is unused.
15862 +        * First bit of fragmentation flags should be unused.
15863 +        * May be used by OS fingerprinting tools.
15864 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
15865 +        */
15866 +       if (ntohs(iph->frag_off)>>15) {
15867 +               limpk("IP unused bit set\n");
15868 +               return 0;
15869 +       }
15870 +
15871 +       /* Per-protocol checks. */
15872 +       switch (iph->protocol) {
15873 +       case IPPROTO_ICMP:
15874 +               return check_icmp(protoh, datalen, offset,
15875 +                                 (ntohs(iph->frag_off) & IP_MF),
15876 +                                 embedded);
15877 +
15878 +       case IPPROTO_UDP:
15879 +               return check_udp(iph, protoh, datalen, offset,
15880 +                                (ntohs(iph->frag_off) & IP_MF),
15881 +                                embedded);
15882 +
15883 +       case IPPROTO_TCP:
15884 +               return check_tcp(iph, protoh, datalen, offset,
15885 +                                (ntohs(iph->frag_off) & IP_MF),
15886 +                                embedded);
15887 +       default:
15888 +               /* Ignorance is bliss. */
15889 +               return 1;
15890 +       }
15891 +}
15892 +
15893 +static int
15894 +match(const struct sk_buff *skb,
15895 +      const struct net_device *in,
15896 +      const struct net_device *out,
15897 +      const void *matchinfo,
15898 +      int offset,
15899 +      const void *hdr,
15900 +      u_int16_t datalen,
15901 +      int *hotdrop)
15902 +{
15903 +       return !check_ip(skb->nh.iph, skb->len, 0);
15904 +}
15905 +
15906 +/* Called when user tries to insert an entry of this type. */
15907 +static int
15908 +checkentry(const char *tablename,
15909 +          const struct ipt_ip *ip,
15910 +          void *matchinfo,
15911 +          unsigned int matchsize,
15912 +          unsigned int hook_mask)
15913 +{
15914 +       if (matchsize != IPT_ALIGN(0))
15915 +               return 0;
15916 +
15917 +       return 1;
15918 +}
15919 +
15920 +static struct ipt_match unclean_match
15921 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
15922 +
15923 +static int __init init(void)
15924 +{
15925 +       return ipt_register_match(&unclean_match);
15926 +}
15927 +
15928 +static void __exit fini(void)
15929 +{
15930 +       ipt_unregister_match(&unclean_match);
15931 +}
15932 +
15933 +module_init(init);
15934 +module_exit(fini);
15935 +MODULE_LICENSE("GPL");
15936 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.7-rc3/net/ipv4/netfilter/iptable_filter.c
15937 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_filter.c     2004-06-07 21:14:05.000000000 +0200
15938 +++ linux-2.6.7-rc3/net/ipv4/netfilter/iptable_filter.c 2004-06-08 10:37:30.000000000 +0200
15939 @@ -59,7 +59,7 @@
15940                 0,
15941                 sizeof(struct ipt_entry),
15942                 sizeof(struct ipt_standard),
15943 -               0, { 0, 0 }, { } },
15944 +               0, NULL, 0, { 0, 0 }, { } },
15945               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15946                 -NF_ACCEPT - 1 } },
15947             /* FORWARD */
15948 @@ -67,7 +67,7 @@
15949                 0,
15950                 sizeof(struct ipt_entry),
15951                 sizeof(struct ipt_standard),
15952 -               0, { 0, 0 }, { } },
15953 +               0, NULL, 0, { 0, 0 }, { } },
15954               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15955                 -NF_ACCEPT - 1 } },
15956             /* LOCAL_OUT */
15957 @@ -75,7 +75,7 @@
15958                 0,
15959                 sizeof(struct ipt_entry),
15960                 sizeof(struct ipt_standard),
15961 -               0, { 0, 0 }, { } },
15962 +               0, NULL, 0, { 0, 0 }, { } },
15963               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15964                 -NF_ACCEPT - 1 } }
15965      },
15966 @@ -84,7 +84,7 @@
15967         0,
15968         sizeof(struct ipt_entry),
15969         sizeof(struct ipt_error),
15970 -       0, { 0, 0 }, { } },
15971 +       0, NULL, 0, { 0, 0 }, { } },
15972        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15973           { } },
15974         "ERROR"
15975 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.7-rc3/net/ipv4/netfilter/iptable_mangle.c
15976 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_mangle.c     2004-06-07 21:14:58.000000000 +0200
15977 +++ linux-2.6.7-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-06-08 10:37:30.000000000 +0200
15978 @@ -74,7 +74,7 @@
15979                 0,
15980                 sizeof(struct ipt_entry),
15981                 sizeof(struct ipt_standard),
15982 -               0, { 0, 0 }, { } },
15983 +               0, NULL, 0, { 0, 0 }, { } },
15984               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15985                 -NF_ACCEPT - 1 } },
15986             /* LOCAL_IN */
15987 @@ -82,7 +82,7 @@
15988                 0,
15989                 sizeof(struct ipt_entry),
15990                 sizeof(struct ipt_standard),
15991 -               0, { 0, 0 }, { } },
15992 +               0, NULL, 0, { 0, 0 }, { } },
15993               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15994                 -NF_ACCEPT - 1 } },
15995             /* FORWARD */
15996 @@ -90,7 +90,7 @@
15997                 0,
15998                 sizeof(struct ipt_entry),
15999                 sizeof(struct ipt_standard),
16000 -               0, { 0, 0 }, { } },
16001 +               0, NULL, 0, { 0, 0 }, { } },
16002               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16003                 -NF_ACCEPT - 1 } },
16004             /* LOCAL_OUT */
16005 @@ -98,7 +98,7 @@
16006                 0,
16007                 sizeof(struct ipt_entry),
16008                 sizeof(struct ipt_standard),
16009 -               0, { 0, 0 }, { } },
16010 +               0, NULL, 0, { 0, 0 }, { } },
16011               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16012                 -NF_ACCEPT - 1 } },
16013             /* POST_ROUTING */
16014 @@ -106,7 +106,7 @@
16015                 0,
16016                 sizeof(struct ipt_entry),
16017                 sizeof(struct ipt_standard),
16018 -               0, { 0, 0 }, { } },
16019 +               0, NULL, 0, { 0, 0 }, { } },
16020               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16021                 -NF_ACCEPT - 1 } },
16022      },
16023 @@ -115,7 +115,7 @@
16024         0,
16025         sizeof(struct ipt_entry),
16026         sizeof(struct ipt_error),
16027 -       0, { 0, 0 }, { } },
16028 +       0, NULL, 0, { 0, 0 }, { } },
16029        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16030           { } },
16031         "ERROR"
16032 @@ -173,8 +173,13 @@
16033         if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
16034             && ((*pskb)->nh.iph->saddr != saddr
16035                 || (*pskb)->nh.iph->daddr != daddr
16036 +#ifdef CONFIG_IP_ROUTE_FWMARK
16037                 || (*pskb)->nfmark != nfmark
16038 -               || (*pskb)->nh.iph->tos != tos))
16039 +#endif
16040 +#ifdef CONFIG_IP_ROUTE_TOS
16041 +               || (*pskb)->nh.iph->tos != tos
16042 +#endif
16043 +              ))
16044                 return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
16045  
16046         return ret;
16047 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.7-rc3/net/ipv4/netfilter/iptable_raw.c
16048 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/iptable_raw.c        2004-06-07 21:14:59.000000000 +0200
16049 +++ linux-2.6.7-rc3/net/ipv4/netfilter/iptable_raw.c    2004-06-08 10:37:30.000000000 +0200
16050 @@ -46,7 +46,7 @@
16051                 0,
16052                 sizeof(struct ipt_entry),
16053                 sizeof(struct ipt_standard),
16054 -               0, { 0, 0 }, { } },
16055 +               0, NULL, 0, { 0, 0 }, { } },
16056               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16057                 -NF_ACCEPT - 1 } },
16058             /* LOCAL_OUT */
16059 @@ -54,7 +54,7 @@
16060                 0,
16061                 sizeof(struct ipt_entry),
16062                 sizeof(struct ipt_standard),
16063 -               0, { 0, 0 }, { } },
16064 +               0, NULL, 0, { 0, 0 }, { } },
16065               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
16066                 -NF_ACCEPT - 1 } }
16067      },
16068 @@ -63,7 +63,7 @@
16069         0,
16070         sizeof(struct ipt_entry),
16071         sizeof(struct ipt_error),
16072 -       0, { 0, 0 }, { } },
16073 +       0, NULL, 0, { 0, 0 }, { } },
16074        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
16075           { } },
16076         "ERROR"
16077 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/netfilter/string.2.6.patch linux-2.6.7-rc3/net/ipv4/netfilter/string.2.6.patch
16078 --- linux-2.6.7-rc3.org/net/ipv4/netfilter/string.2.6.patch     1970-01-01 01:00:00.000000000 +0100
16079 +++ linux-2.6.7-rc3/net/ipv4/netfilter/string.2.6.patch 2004-06-08 10:41:24.000000000 +0200
16080 @@ -0,0 +1,152 @@
16081 +--- ipt_string.c.old    Mon Mar 29 06:00:23 2004
16082 ++++ ipt_string.c    Mon Mar 29 06:01:04 2004
16083 +@@ -3,6 +3,8 @@
16084 +  * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
16085 +  * 
16086 +  * ChangeLog
16087 ++ *     24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
16088 ++ *             Initial 2.6 port
16089 +  *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
16090 +  *             Fixed SMP re-entrancy problem using per-cpu data areas
16091 +  *             for the skip/shift tables.
16092 +@@ -18,6 +20,7 @@
16093 +  */
16094
16095 + #include <linux/smp.h>
16096 ++#include <linux/percpu.h>
16097 + #include <linux/module.h>
16098 + #include <linux/skbuff.h>
16099 + #include <linux/file.h>
16100 +@@ -29,12 +32,13 @@
16101 + MODULE_LICENSE("GPL");
16102
16103 + struct string_per_cpu {
16104 +-       int *skip;
16105 +-       int *shift;
16106 +-       int *len;
16107 ++       int skip[BM_MAX_HLEN];
16108 ++       int shift[BM_MAX_HLEN];
16109 ++       int len[BM_MAX_HLEN];
16110 + };
16111
16112 +-struct string_per_cpu *bm_string_data=NULL;
16113 ++static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
16114 ++
16115
16116 + /* Boyer Moore Sublinear string search - VERY FAST */
16117 + char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
16118 +@@ -45,14 +49,14 @@
16119 +        int *skip, *shift, *len;
16120 +        
16121 +        /* use data suitable for this CPU */
16122 +-       shift=bm_string_data[smp_processor_id()].shift;
16123 +-       skip=bm_string_data[smp_processor_id()].skip;
16124 +-       len=bm_string_data[smp_processor_id()].len;
16125 ++       shift=__get_cpu_var(bm_string_data).shift;
16126 ++       skip=__get_cpu_var(bm_string_data).skip;
16127 ++       len=__get_cpu_var(bm_string_data).len;
16128 +        
16129 +        /* Setup skip/shift tables */
16130 +        M1 = right_end = needle_len-1;
16131 +        for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
16132 +-       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
16133 ++       for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
16134
16135 +        for (i = 1; i < needle_len; i++) {   
16136 +                for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
16137 +@@ -77,7 +81,7 @@
16138 +                        return haystack+(right_end - M1);
16139 +                }
16140 +                
16141 +-               sk = skip[haystack[right_end - i]];  
16142 ++               sk = skip[(int)haystack[right_end - i]];  
16143 +                sh = shift[i];
16144 +                right_end = max(right_end - i + sk, right_end + sh);  
16145 +        }
16146 +@@ -100,15 +104,12 @@
16147 +        return NULL;
16148 + }
16149
16150 +-
16151 + static int
16152 + match(const struct sk_buff *skb,
16153 +       const struct net_device *in,
16154 +       const struct net_device *out,
16155 +       const void *matchinfo,
16156 +       int offset,
16157 +-      const void *hdr,
16158 +-      u_int16_t datalen,
16159 +       int *hotdrop)
16160 + {
16161 +        const struct ipt_string_info *info = matchinfo;
16162 +@@ -158,61 +159,25 @@
16163 +        return 1;
16164 + }
16165
16166 +-void string_freeup_data(void)
16167 +-{
16168 +-       int c;
16169 +-       
16170 +-       if ( bm_string_data ) {
16171 +-               for(c=0; c<smp_num_cpus; c++) {
16172 +-                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
16173 +-                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
16174 +-                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
16175 +-               }
16176 +-               kfree(bm_string_data);
16177 +-       }
16178 +-}
16179 ++static struct ipt_match string_match = {
16180 ++    .name = "string",
16181 ++    .match = &match,
16182 ++    .checkentry = &checkentry,
16183 ++    .me = THIS_MODULE
16184 ++};
16185
16186 +-static struct ipt_match string_match
16187 +-= { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
16188
16189 + static int __init init(void)
16190 + {
16191 +-       int c;
16192 +-       size_t tlen;
16193 +-       size_t alen;
16194 +-
16195 +-       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
16196 +-       alen=sizeof(int)*BM_MAX_HLEN;
16197 +-       
16198 +-       /* allocate array of structures */
16199 +-       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
16200 +-               return 0;
16201 +-       }
16202 +-       
16203 +-       memset(bm_string_data, 0, tlen);
16204 +-       
16205 +-       /* allocate our skip/shift tables */
16206 +-       for(c=0; c<smp_num_cpus; c++) {
16207 +-               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
16208 +-                       goto alloc_fail;
16209 +-               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
16210 +-                       goto alloc_fail;
16211 +-               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
16212 +-                       goto alloc_fail;
16213 +-       }
16214 +-       
16215 +        return ipt_register_match(&string_match);
16216 +-
16217 +-alloc_fail:
16218 +-       string_freeup_data();
16219 +-       return 0;
16220 + }
16221
16222 + static void __exit fini(void)
16223 + {
16224 +        ipt_unregister_match(&string_match);
16225 +-       string_freeup_data();
16226 + }
16227
16228 + module_init(init);
16229 + module_exit(fini);
16230 ++
16231 ++
16232 +
16233 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/raw.c linux-2.6.7-rc3/net/ipv4/raw.c
16234 --- linux-2.6.7-rc3.org/net/ipv4/raw.c  2004-06-07 21:14:25.000000000 +0200
16235 +++ linux-2.6.7-rc3/net/ipv4/raw.c      2004-06-08 10:38:46.000000000 +0200
16236 @@ -249,6 +249,7 @@
16237                 kfree_skb(skb);
16238                 return NET_RX_DROP;
16239         }
16240 +       nf_reset(skb);
16241  
16242         skb_push(skb, skb->data - skb->nh.raw);
16243  
16244 @@ -307,7 +308,7 @@
16245         }
16246  
16247         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
16248 -                     dst_output);
16249 +                     ip_dst_output);
16250         if (err > 0)
16251                 err = inet->recverr ? net_xmit_errno(err) : 0;
16252         if (err)
16253 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.7-rc3/net/ipv4/tcp_ipv4.c
16254 --- linux-2.6.7-rc3.org/net/ipv4/tcp_ipv4.c     2004-06-07 21:14:04.000000000 +0200
16255 +++ linux-2.6.7-rc3/net/ipv4/tcp_ipv4.c 2004-06-08 10:39:56.000000000 +0200
16256 @@ -1785,6 +1785,7 @@
16257  
16258         if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
16259                 goto discard_and_relse;
16260 +       nf_reset(skb);
16261  
16262         if (sk_filter(sk, skb, 0))
16263                 goto discard_and_relse;
16264 @@ -2636,6 +2637,7 @@
16265  EXPORT_SYMBOL(tcp_v4_connect);
16266  EXPORT_SYMBOL(tcp_v4_do_rcv);
16267  EXPORT_SYMBOL(tcp_v4_lookup_listener);
16268 +EXPORT_SYMBOL(tcp_v4_lookup);
16269  EXPORT_SYMBOL(tcp_v4_rebuild_header);
16270  EXPORT_SYMBOL(tcp_v4_remember_stamp);
16271  EXPORT_SYMBOL(tcp_v4_send_check);
16272 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/udp.c linux-2.6.7-rc3/net/ipv4/udp.c
16273 --- linux-2.6.7-rc3.org/net/ipv4/udp.c  2004-06-07 21:13:39.000000000 +0200
16274 +++ linux-2.6.7-rc3/net/ipv4/udp.c      2004-06-08 10:39:56.000000000 +0200
16275 @@ -1045,6 +1045,7 @@
16276                 kfree_skb(skb);
16277                 return -1;
16278         }
16279 +       nf_reset(skb);
16280  
16281         if (up->encap_type) {
16282                 /*
16283 @@ -1210,6 +1211,7 @@
16284  
16285         if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
16286                 goto drop;
16287 +       nf_reset(skb);
16288  
16289         /* No socket. Drop packet silently, if checksum is wrong */
16290         if (udp_checksum_complete(skb))
16291 @@ -1558,6 +1560,7 @@
16292  EXPORT_SYMBOL(udp_port_rover);
16293  EXPORT_SYMBOL(udp_prot);
16294  EXPORT_SYMBOL(udp_sendmsg);
16295 +EXPORT_SYMBOL(udp_v4_lookup);
16296  
16297  #ifdef CONFIG_PROC_FS
16298  EXPORT_SYMBOL(udp_proc_register);
16299 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.7-rc3/net/ipv4/xfrm4_tunnel.c
16300 --- linux-2.6.7-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-06-07 21:13:38.000000000 +0200
16301 +++ linux-2.6.7-rc3/net/ipv4/xfrm4_tunnel.c     2004-06-08 10:38:44.000000000 +0200
16302 @@ -77,6 +77,7 @@
16303                 err = -EHOSTUNREACH;
16304                 goto error_nolock;
16305         }
16306 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
16307         return NET_XMIT_BYPASS;
16308  
16309  error_nolock:
16310 @@ -171,6 +172,7 @@
16311         .handler        =       ipip_rcv,
16312         .err_handler    =       ipip_err,
16313         .no_policy      =       1,
16314 +       .xfrm_prot      =       1,
16315  };
16316  
16317  static int __init ipip_init(void)
16318 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/ip6_tunnel.c linux-2.6.7-rc3/net/ipv6/ip6_tunnel.c
16319 --- linux-2.6.7-rc3.org/net/ipv6/ip6_tunnel.c   2004-06-07 21:13:37.000000000 +0200
16320 +++ linux-2.6.7-rc3/net/ipv6/ip6_tunnel.c       2004-06-08 10:30:55.000000000 +0200
16321 @@ -715,13 +715,7 @@
16322         ipv6h->nexthdr = proto;
16323         ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
16324         ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
16325 -#ifdef CONFIG_NETFILTER
16326 -       nf_conntrack_put(skb->nfct);
16327 -       skb->nfct = NULL;
16328 -#ifdef CONFIG_NETFILTER_DEBUG
16329 -       skb->nf_debug = 0;
16330 -#endif
16331 -#endif
16332 +       nf_reset(skb);
16333         pkt_len = skb->len;
16334         err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, 
16335                       skb->dst->dev, dst_output);
16336 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.7-rc3/net/ipv6/netfilter/Kconfig
16337 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/Kconfig      2004-06-07 21:14:58.000000000 +0200
16338 +++ linux-2.6.7-rc3/net/ipv6/netfilter/Kconfig  2004-06-08 10:42:36.000000000 +0200
16339 @@ -230,5 +230,107 @@
16340           <file:Documentation/modules.txt>.  If unsure, say `N'.
16341           help
16342  
16343 +config IP6_NF_TARGET_HL
16344 +       tristate  'HL target support'
16345 +       depends on IP6_NF_MANGLE
16346 +       help
16347 +         This option adds a `HL' target, which allows you to modify the value of
16348 +         IPv6 Hop Limit field.
16349 +       
16350 +         If you want to compile it as a module, say M here and read
16351 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16352 +
16353 +config IP6_NF_TARGET_REJECT
16354 +       tristate  'REJECT target support'
16355 +       depends on IP6_NF_FILTER
16356 +       help
16357 +         The REJECT target allows a filtering rule to specify that an ICMPv6
16358 +         error should be issued in response to an incoming packet, rather
16359 +         than silently being dropped.
16360 +       
16361 +         If you want to compile it as a module, say M here and read
16362 +         Documentation/modules.txt.  If unsure, say `N'.
16363 +
16364 +config IP6_NF_MATCH_FUZZY
16365 +       tristate  'Fuzzy match support'
16366 +       depends on IP6_NF_FILTER
16367 +       help
16368 +         This option adds a `fuzzy' match, which allows you to match
16369 +         packets according to a fuzzy logic based law.
16370 +       
16371 +         If you want to compile it as a module, say M here and read
16372 +         Documentation/modules.txt.  If unsure, say `N'.
16373 +
16374 +config IP6_NF_MATCH_NTH
16375 +       tristate  'Nth match support'
16376 +       depends on IP6_NF_IPTABLES
16377 +       help
16378 +         This option adds a `Nth' match, which allow you to make
16379 +         rules that match every Nth packet.  By default there are 
16380 +         16 different counters.
16381 +       
16382 +         [options]
16383 +          --every     Nth              Match every Nth packet
16384 +         [--counter]  num              Use counter 0-15 (default:0)
16385 +         [--start]    num              Initialize the counter at the number 'num'
16386 +                                       instead of 0. Must be between 0 and Nth-1
16387 +         [--packet]   num              Match on 'num' packet. Must be between 0
16388 +                                       and Nth-1.
16389 +       
16390 +                                       If --packet is used for a counter than
16391 +                                       there must be Nth number of --packet
16392 +                                       rules, covering all values between 0 and
16393 +                                       Nth-1 inclusively.
16394 +        
16395 +         If you want to compile it as a module, say M here and read
16396 +         Documentation/modules.txt.  If unsure, say `N'.
16397 +
16398 +config IP6_NF_MATCH_RANDOM
16399 +       tristate  'Random match support'
16400 +       depends on IP6_NF_IPTABLES
16401 +       help
16402 +         This option adds a `random' match,
16403 +         which allow you to match packets randomly
16404 +         following a given probability.
16405 +        
16406 +         If you want to compile it as a module, say M here and read
16407 +         Documentation/modules.txt.  If unsure, say `N'.
16408 +
16409 +config IP6_NF_TARGET_ROUTE
16410 +       tristate '    ROUTE target support'
16411 +       depends on IP6_NF_MANGLE
16412 +       help
16413 +         This option adds a `ROUTE' target, which enables you to setup unusual
16414 +         routes. The ROUTE target is also able to change the incoming interface
16415 +         of a packet.
16416 +       
16417 +         The target can be or not a final target. It has to be used inside the 
16418 +         mangle table.
16419 +         
16420 +         Not working as a module.
16421 +
16422 +config IP6_NF_TARGET_TRACE
16423 +       tristate  'TRACE target support'
16424 +       depends on IP6_NF_RAW
16425 +       help
16426 +         The TRACE target allows packets to be traced as those
16427 +         matches any subsequent rule in any table/rule. The matched
16428 +         rule and the packet is logged with the prefix
16429 +       
16430 +         TRACE: tablename/chainname/rulenum  
16431 +       
16432 +         If you want to compile it as a module, say M here and read
16433 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
16434 +
16435 +config IP6_NF_MATCH_POLICY
16436 +       tristate "IPsec policy match support"
16437 +       depends on IP6_NF_IPTABLES && XFRM
16438 +       help
16439 +         Policy matching allows you to match packets based on the
16440 +         IPsec policy that was used during decapsulation/will
16441 +         be used during encapsulation.
16442 +
16443 +         To compile it as a module, choose M here.  If unsure, say N.
16444 +
16445  endmenu
16446  
16447 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.7-rc3/net/ipv6/netfilter/Makefile
16448 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/Makefile     2004-06-07 21:14:33.000000000 +0200
16449 +++ linux-2.6.7-rc3/net/ipv6/netfilter/Makefile 2004-06-08 10:42:36.000000000 +0200
16450 @@ -8,18 +8,28 @@
16451  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
16452  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
16453  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
16454 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
16455  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
16456  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
16457  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
16458  obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
16459  obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
16460 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
16461  obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
16462  obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
16463  obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
16464  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
16465  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
16466  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
16467 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
16468 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
16469  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
16470  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
16471 +
16472 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
16473 +
16474 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
16475 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
16476  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
16477 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
16478  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
16479 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6_tables.c
16480 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-06-07 21:14:58.000000000 +0200
16481 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6_tables.c     2004-06-08 10:37:30.000000000 +0200
16482 @@ -38,6 +38,14 @@
16483  #define IPV6_HDR_LEN   (sizeof(struct ipv6hdr))
16484  #define IPV6_OPTHDR_LEN        (sizeof(struct ipv6_opt_hdr))
16485  
16486 +static const char *hook6names[] = { 
16487 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
16488 +       [NF_IP6_LOCAL_IN] "INPUT",
16489 +       [NF_IP6_FORWARD] "FORWARD",
16490 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
16491 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
16492 +};
16493 +
16494  /*#define DEBUG_IP_FIREWALL*/
16495  /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
16496  /*#define DEBUG_IP_FIREWALL_USER*/
16497 @@ -406,6 +414,12 @@
16498  
16499                         t = ip6t_get_target(e);
16500                         IP_NF_ASSERT(t->u.kernel.target);
16501 +
16502 +                       /* The packet traced and the rule isn't an unconditional return/END. */
16503 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
16504 +                               nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
16505 +                                             table->name, e->chainname, e->rulenum);
16506 +                       }
16507                         /* Standard target? */
16508                         if (!t->u.kernel.target->target) {
16509                                 int v;
16510 @@ -559,6 +573,29 @@
16511         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
16512  }
16513  
16514 +static inline int
16515 +find_error_target(struct ip6t_entry *s, 
16516 +                 struct ip6t_entry *e,
16517 +                 char **chainname)
16518 +{
16519 +       struct ip6t_entry_target *t;
16520 +       static struct ip6t_entry *found = NULL;
16521 +
16522 +       if (s == e) {
16523 +               if (!found)
16524 +                       return 0;
16525 +               t = ip6t_get_target(found);
16526 +               if (strcmp(t->u.user.name, 
16527 +                          IP6T_ERROR_TARGET) == 0) {
16528 +                       *chainname = t->data;
16529 +                       return 1;
16530 +               }
16531 +       } else
16532 +               found = s;
16533 +       
16534 +       return 0;
16535 +}
16536 +
16537  /* All zeroes == unconditional rule. */
16538  static inline int
16539  unconditional(const struct ip6t_ip6 *ipv6)
16540 @@ -578,6 +615,8 @@
16541  mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
16542  {
16543         unsigned int hook;
16544 +       char *chainname = NULL;
16545 +       u_int32_t rulenum;
16546  
16547         /* No recursion; use packet counter to save back ptrs (reset
16548            to 0 as we leave), and comefrom to save source hook bitmask */
16549 @@ -591,6 +630,8 @@
16550  
16551                 /* Set initial back pointer. */
16552                 e->counters.pcnt = pos;
16553 +               rulenum = 1;
16554 +               chainname = (char *) hook6names[hook];
16555  
16556                 for (;;) {
16557                         struct ip6t_standard_target *t
16558 @@ -603,6 +644,8 @@
16559                         }
16560                         e->comefrom
16561                                 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
16562 +                       e->rulenum = rulenum++;
16563 +                       e->chainname = chainname;
16564  
16565                         /* Unconditional return/END. */
16566                         if (e->target_offset == sizeof(struct ip6t_entry)
16567 @@ -612,6 +655,10 @@
16568                             && unconditional(&e->ipv6)) {
16569                                 unsigned int oldpos, size;
16570  
16571 +                               /* Set unconditional rulenum to zero. */
16572 +                               e->rulenum = 0;
16573 +                               e->counters.bcnt = 0;
16574 +
16575                                 /* Return: backtrack through the last
16576                                    big jump. */
16577                                 do {
16578 @@ -637,6 +684,11 @@
16579                                                 (newinfo->entries + pos);
16580                                 } while (oldpos == pos + e->next_offset);
16581  
16582 +                               /* Restore chainname, rulenum. */
16583 +                               chainname = e->chainname;
16584 +                               rulenum = e->counters.bcnt;
16585 +                               e->counters.bcnt = 0;
16586 +
16587                                 /* Move along one */
16588                                 size = e->next_offset;
16589                                 e = (struct ip6t_entry *)
16590 @@ -652,6 +704,17 @@
16591                                         /* This a jump; chase it. */
16592                                         duprintf("Jump rule %u -> %u\n",
16593                                                  pos, newpos);
16594 +                                       e->counters.bcnt = rulenum++;
16595 +                                       rulenum = 1;
16596 +                                       e = (struct ip6t_entry *)
16597 +                                               (newinfo->entries + newpos);
16598 +                                       if (IP6T_ENTRY_ITERATE(newinfo->entries,
16599 +                                                              newinfo->size,
16600 +                                                              find_error_target,
16601 +                                                              e, &chainname) == 0) {
16602 +                                               printk("ip6_tables: table screwed up!\n");
16603 +                                               return 0;
16604 +                                       }
16605                                 } else {
16606                                         /* ... this is a fallthru */
16607                                         newpos = pos + e->next_offset;
16608 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_HL.c
16609 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_HL.c    1970-01-01 01:00:00.000000000 +0100
16610 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_HL.c        2004-06-08 10:31:03.000000000 +0200
16611 @@ -0,0 +1,105 @@
16612 +/* 
16613 + * Hop Limit modification target for ip6tables
16614 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
16615 + * Based on HW's TTL module
16616 + *
16617 + * This software is distributed under the terms of GNU GPL
16618 + */
16619 +
16620 +#include <linux/module.h>
16621 +#include <linux/skbuff.h>
16622 +#include <linux/ip.h>
16623 +
16624 +#include <linux/netfilter_ipv6/ip6_tables.h>
16625 +#include <linux/netfilter_ipv6/ip6t_HL.h>
16626 +
16627 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
16628 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
16629 +MODULE_LICENSE("GPL");
16630 +
16631 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
16632 +               const struct net_device *in, const struct net_device *out,
16633 +               const void *targinfo, void *userinfo)
16634 +{
16635 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
16636 +       const struct ip6t_HL_info *info = targinfo;
16637 +       u_int16_t diffs[2];
16638 +       int new_hl;
16639 +                        
16640 +       switch (info->mode) {
16641 +               case IP6T_HL_SET:
16642 +                       new_hl = info->hop_limit;
16643 +                       break;
16644 +               case IP6T_HL_INC:
16645 +                       new_hl = ip6h->hop_limit + info->hop_limit;
16646 +                       if (new_hl > 255)
16647 +                               new_hl = 255;
16648 +                       break;
16649 +               case IP6T_HL_DEC:
16650 +                       new_hl = ip6h->hop_limit + info->hop_limit;
16651 +                       if (new_hl < 0)
16652 +                               new_hl = 0;
16653 +                       break;
16654 +               default:
16655 +                       new_hl = ip6h->hop_limit;
16656 +                       break;
16657 +       }
16658 +
16659 +       if (new_hl != ip6h->hop_limit) {
16660 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
16661 +               ip6h->hop_limit = new_hl;
16662 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
16663 +       }
16664 +
16665 +       return IP6T_CONTINUE;
16666 +}
16667 +
16668 +static int ip6t_hl_checkentry(const char *tablename,
16669 +               const struct ip6t_entry *e,
16670 +               void *targinfo,
16671 +               unsigned int targinfosize,
16672 +               unsigned int hook_mask)
16673 +{
16674 +       struct ip6t_HL_info *info = targinfo;
16675 +
16676 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
16677 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
16678 +                               targinfosize,
16679 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
16680 +               return 0;       
16681 +       }       
16682 +
16683 +       if (strcmp(tablename, "mangle")) {
16684 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
16685 +               return 0;
16686 +       }
16687 +
16688 +       if (info->mode > IP6T_HL_MAXMODE) {
16689 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
16690 +                       info->mode);
16691 +               return 0;
16692 +       }
16693 +
16694 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
16695 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
16696 +               return 0;
16697 +       }
16698 +       
16699 +       return 1;
16700 +}
16701 +
16702 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
16703 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
16704 +
16705 +static int __init init(void)
16706 +{
16707 +       return ip6t_register_target(&ip6t_HL);
16708 +}
16709 +
16710 +static void __exit fini(void)
16711 +{
16712 +       ip6t_unregister_target(&ip6t_HL);
16713 +}
16714 +
16715 +module_init(init);
16716 +module_exit(fini);
16717 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_REJECT.c
16718 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c        1970-01-01 01:00:00.000000000 +0100
16719 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_REJECT.c    2004-06-08 10:31:20.000000000 +0200
16720 @@ -0,0 +1,458 @@
16721 +/*
16722 + * IP6 tables REJECT target module
16723 + * Linux INET6 implementation
16724 + *
16725 + * Copyright (C)2003 USAGI/WIDE Project
16726 + *
16727 + * Authors:
16728 + *     Yasuyuki Kozakai        <yasuyuki.kozakai@toshiba.co.jp>
16729 + *
16730 + * Based on net/ipv4/netfilter/ipt_REJECT.c
16731 + *
16732 + * This program is free software; you can redistribute it and/or
16733 + * modify it under the terms of the GNU General Public License
16734 + * as published by the Free Software Foundation; either version
16735 + * 2 of the License, or (at your option) any later version.
16736 + */
16737 +
16738 +#include <linux/config.h>
16739 +#include <linux/module.h>
16740 +#include <linux/skbuff.h>
16741 +#include <linux/icmpv6.h>
16742 +#include <net/ipv6.h>
16743 +#include <net/tcp.h>
16744 +#include <net/icmp.h>
16745 +#include <net/ip6_fib.h>
16746 +#include <net/ip6_route.h>
16747 +#include <net/flow.h>
16748 +#include <linux/netfilter_ipv6/ip6_tables.h>
16749 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
16750 +
16751 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
16752 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
16753 +MODULE_LICENSE("GPL");
16754 +
16755 +#if 0
16756 +#define DEBUGP printk
16757 +#else
16758 +#define DEBUGP(format, args...)
16759 +#endif
16760 +
16761 +#if 0
16762 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
16763 +{
16764 +       void (*attach)(struct sk_buff *, struct nf_ct_info *);
16765 +       if (nfct && (attach = ip6_ct_attach) != NULL) {
16766 +               mb();
16767 +               attach(new_skb, nfct);
16768 +       }
16769 +}
16770 +#endif
16771 +
16772 +static int maybe_reroute(struct sk_buff *skb)
16773 +{
16774 +       if (skb->nfcache & NFC_ALTERED){
16775 +               if (ip6_route_me_harder(skb) != 0){
16776 +                       kfree_skb(skb);
16777 +                       return -EINVAL;
16778 +               }
16779 +       }
16780 +
16781 +       return dst_output(skb);
16782 +}
16783 +
16784 +/* Send RST reply */
16785 +static void send_reset(struct sk_buff *oldskb)
16786 +{
16787 +       struct sk_buff *nskb;
16788 +       struct tcphdr otcph, *tcph;
16789 +       unsigned int otcplen, tcphoff, hh_len;
16790 +       int needs_ack;
16791 +       struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
16792 +       struct dst_entry *dst = NULL;
16793 +       u8 proto;
16794 +       struct flowi fl;
16795 +       proto = oip6h->nexthdr;
16796 +       int err;
16797 +
16798 +       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
16799 +           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
16800 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
16801 +               return;
16802 +       }
16803 +
16804 +       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
16805 +                                  &proto, oldskb->len - ((u8*)(oip6h+1)
16806 +                                                         - oldskb->data));
16807 +
16808 +       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
16809 +               DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
16810 +               return;
16811 +       }
16812 +
16813 +       otcplen = oldskb->len - tcphoff;
16814 +
16815 +       /* IP header checks: fragment, too short. */
16816 +       if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
16817 +               DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
16818 +                       proto, otcplen);
16819 +               return;
16820 +       }
16821 +
16822 +       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
16823 +               if (net_ratelimit())
16824 +                       printk("ip6t_REJECT: Can't copy tcp header\n");
16825 +               return;
16826 +       }
16827 +
16828 +       /* No RST for RST. */
16829 +       if (otcph.rst) {
16830 +               DEBUGP("ip6t_REJECT: RST is set\n");
16831 +               return;
16832 +       }
16833 +
16834 +       /* Check checksum. */
16835 +       if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
16836 +                           skb_checksum(oldskb, tcphoff, otcplen, 0))) {
16837 +               DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
16838 +               return;
16839 +       }
16840 +
16841 +       memset(&fl, 0, sizeof(fl));
16842 +       fl.proto = IPPROTO_TCP;
16843 +       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
16844 +       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
16845 +       fl.fl_ip_sport = otcph.dest;
16846 +       fl.fl_ip_dport = otcph.source;
16847 +       err = ip6_dst_lookup(NULL, &dst, &fl);
16848 +       if (err) {
16849 +               if (net_ratelimit())
16850 +                       printk("ip6t_REJECT: can't find dst. err = %d\n", err);
16851 +               return;
16852 +       }
16853 +
16854 +       hh_len = (dst->dev->hard_header_len + 15)&~15;
16855 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
16856 +                        + sizeof(struct tcphdr) + dst->trailer_len,
16857 +                        GFP_ATOMIC);
16858 +
16859 +       if (!nskb) {
16860 +               if (net_ratelimit())
16861 +                       printk("ip6t_REJECT: Can't alloc skb\n");
16862 +               dst_release(dst);
16863 +               return;
16864 +       }
16865 +
16866 +       nskb->dst = dst;
16867 +       dst_hold(dst);
16868 +
16869 +       skb_reserve(nskb, hh_len + dst->header_len);
16870 +
16871 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
16872 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
16873 +       ip6h->version = 6;
16874 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
16875 +       ip6h->nexthdr = IPPROTO_TCP;
16876 +       ip6h->payload_len = htons(sizeof(struct tcphdr));
16877 +       ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
16878 +       ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
16879 +
16880 +       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
16881 +       /* Truncate to length (no data) */
16882 +       tcph->doff = sizeof(struct tcphdr)/4;
16883 +       tcph->source = otcph.dest;
16884 +       tcph->dest = otcph.source;
16885 +
16886 +       if (otcph.ack) {
16887 +               needs_ack = 0;
16888 +               tcph->seq = otcph.ack_seq;
16889 +               tcph->ack_seq = 0;
16890 +       } else {
16891 +               needs_ack = 1;
16892 +               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
16893 +                                     + otcplen - (otcph.doff<<2));
16894 +               tcph->seq = 0;
16895 +       }
16896 +
16897 +       /* Reset flags */
16898 +       ((u_int8_t *)tcph)[13] = 0;
16899 +       tcph->rst = 1;
16900 +       tcph->ack = needs_ack;
16901 +       tcph->window = 0;
16902 +       tcph->urg_ptr = 0;
16903 +       tcph->check = 0;
16904 +
16905 +       /* Adjust TCP checksum */
16906 +       tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
16907 +                                     &nskb->nh.ipv6h->daddr,
16908 +                                     sizeof(struct tcphdr), IPPROTO_TCP,
16909 +                                     csum_partial((char *)tcph,
16910 +                                                  sizeof(struct tcphdr), 0));
16911 +
16912 +#if 0
16913 +       connection_attach(nskb, oldskb->nfct);
16914 +#endif
16915 +
16916 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
16917 +               maybe_reroute);
16918 +
16919 +       dst_release(dst);
16920 +}
16921 +
16922 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
16923 +{
16924 +       struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
16925 +       struct icmp6hdr *icmp6h;
16926 +       struct dst_entry *dst = NULL;
16927 +       struct rt6_info *rt;
16928 +       int tmo;
16929 +       __u32 csum;
16930 +       unsigned int len, datalen, hh_len;
16931 +       int saddr_type, daddr_type;
16932 +       unsigned int ptr, ip6off;
16933 +       u8 proto;
16934 +       struct flowi fl;
16935 +       struct sk_buff *nskb;
16936 +       char *data;
16937 +
16938 +       saddr_type = ipv6_addr_type(&hdr->saddr);
16939 +       daddr_type = ipv6_addr_type(&hdr->daddr);
16940 +
16941 +       if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
16942 +           (!(daddr_type & IPV6_ADDR_UNICAST))) {
16943 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
16944 +               return;
16945 +       }
16946 +
16947 +       ip6off = skb_in->nh.raw - skb_in->data;
16948 +       proto = hdr->nexthdr;
16949 +       ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
16950 +                              skb_in->len - ip6off);
16951 +
16952 +       if ((ptr < 0) || (ptr > skb_in->len)) {
16953 +               ptr = ip6off + sizeof(struct ipv6hdr);
16954 +               proto = hdr->nexthdr;
16955 +       } else if (proto == IPPROTO_ICMPV6) {
16956 +                u8 type;
16957 +
16958 +                if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
16959 +                                                     icmp6_type), &type, 1)) {
16960 +                       DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
16961 +                       return;
16962 +               }
16963 +
16964 +               if (!(type & ICMPV6_INFOMSG_MASK)) {
16965 +                       DEBUGP("ip6t_REJECT: no reply to icmp error\n");
16966 +                       return;
16967 +               }
16968 +        } else if (proto == IPPROTO_UDP) {
16969 +               int plen = skb_in->len - (ptr - ip6off);
16970 +               uint16_t check;
16971 +
16972 +               if (plen < sizeof(struct udphdr)) {
16973 +                       DEBUGP("ip6t_REJECT: too short\n");
16974 +                       return;
16975 +               }
16976 +
16977 +               if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
16978 +                                 &check, 2)) {
16979 +                       if (net_ratelimit())
16980 +                               printk("ip6t_REJECT: can't get copy from skb");
16981 +                       return;
16982 +               }
16983 +
16984 +               if (check &&
16985 +                   csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
16986 +                                   IPPROTO_UDP,
16987 +                                   skb_checksum(skb_in, ptr, plen, 0))) {
16988 +                       DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
16989 +                       return;
16990 +               }
16991 +       }
16992 +
16993 +       memset(&fl, 0, sizeof(fl));
16994 +       fl.proto = IPPROTO_ICMPV6;
16995 +       ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
16996 +       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
16997 +       fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
16998 +       fl.fl_icmp_code = code;
16999 +
17000 +       if (ip6_dst_lookup(NULL, &dst, &fl)) {
17001 +               return;
17002 +       }
17003 +
17004 +       rt = (struct rt6_info *)dst;
17005 +       tmo = 1*HZ;
17006 +
17007 +       if (rt->rt6i_dst.plen < 128)
17008 +               tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
17009 +
17010 +       if (!xrlim_allow(dst, tmo)) {
17011 +               if (net_ratelimit())
17012 +                       printk("ip6t_REJECT: rate limitted\n");
17013 +               goto dst_release_out;
17014 +       }
17015 +
17016 +       len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
17017 +
17018 +       if (len > dst_pmtu(dst))
17019 +               len = dst_pmtu(dst);
17020 +       if (len > IPV6_MIN_MTU)
17021 +               len = IPV6_MIN_MTU;
17022 +
17023 +       datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
17024 +       hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
17025 +
17026 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
17027 +                        GFP_ATOMIC);
17028 +
17029 +       if (!nskb) {
17030 +               if (net_ratelimit())
17031 +                       printk("ip6t_REJECT: can't alloc skb\n");
17032 +               goto dst_release_out;
17033 +       }
17034 +
17035 +       nskb->priority = 0;
17036 +       nskb->dst = dst;
17037 +       dst_hold(dst);
17038 +
17039 +       skb_reserve(nskb, hh_len + dst->header_len);
17040 +
17041 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
17042 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
17043 +       ip6h->version = 6;
17044 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
17045 +       ip6h->nexthdr = IPPROTO_ICMPV6;
17046 +       ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
17047 +       ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
17048 +       ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
17049 +
17050 +       icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
17051 +       icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
17052 +       icmp6h->icmp6_code = code;
17053 +       icmp6h->icmp6_cksum = 0;
17054 +
17055 +       data = skb_put(nskb, datalen);
17056 +
17057 +       csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
17058 +       csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
17059 +       icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
17060 +                                            datalen + sizeof(struct icmp6hdr),
17061 +                                            IPPROTO_ICMPV6, csum);
17062 +
17063 +#if 0
17064 +       connection_attach(nskb, skb_in->nfct);
17065 +#endif
17066 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
17067 +               maybe_reroute);
17068 +
17069 +dst_release_out:
17070 +       dst_release(dst);
17071 +}
17072 +
17073 +static unsigned int reject6_target(struct sk_buff **pskb,
17074 +                          unsigned int hooknum,
17075 +                          const struct net_device *in,
17076 +                          const struct net_device *out,
17077 +                          const void *targinfo,
17078 +                          void *userinfo)
17079 +{
17080 +       const struct ip6t_reject_info *reject = targinfo;
17081 +
17082 +       DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
17083 +       /* WARNING: This code causes reentry within ip6tables.
17084 +          This means that the ip6tables jump stack is now crap.  We
17085 +          must return an absolute verdict. --RR */
17086 +       switch (reject->with) {
17087 +       case IP6T_ICMP6_NO_ROUTE:
17088 +               send_unreach(*pskb, ICMPV6_NOROUTE);
17089 +               break;
17090 +       case IP6T_ICMP6_ADM_PROHIBITED:
17091 +               send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
17092 +               break;
17093 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
17094 +               send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
17095 +               break;
17096 +       case IP6T_ICMP6_ADDR_UNREACH:
17097 +               send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
17098 +               break;
17099 +       case IP6T_ICMP6_PORT_UNREACH:
17100 +               send_unreach(*pskb, ICMPV6_PORT_UNREACH);
17101 +               break;
17102 +       case IP6T_ICMP6_ECHOREPLY:
17103 +               /* Do nothing */
17104 +               break;
17105 +       case IP6T_TCP_RESET:
17106 +               send_reset(*pskb);
17107 +               break;
17108 +       default:
17109 +               if (net_ratelimit())
17110 +                       printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
17111 +               break;
17112 +       }
17113 +
17114 +       return NF_DROP;
17115 +}
17116 +
17117 +static int check(const char *tablename,
17118 +                const struct ip6t_entry *e,
17119 +                void *targinfo,
17120 +                unsigned int targinfosize,
17121 +                unsigned int hook_mask)
17122 +{
17123 +       const struct ip6t_reject_info *rejinfo = targinfo;
17124 +
17125 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
17126 +               DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
17127 +               return 0;
17128 +       }
17129 +
17130 +       /* Only allow these for packet filtering. */
17131 +       if (strcmp(tablename, "filter") != 0) {
17132 +               DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
17133 +               return 0;
17134 +       }
17135 +
17136 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
17137 +                          | (1 << NF_IP6_FORWARD)
17138 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
17139 +               DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
17140 +               return 0;
17141 +       }
17142 +
17143 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
17144 +               printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
17145 +               return 0;
17146 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
17147 +               /* Must specify that it's a TCP packet */
17148 +               if (e->ipv6.proto != IPPROTO_TCP
17149 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
17150 +                       DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
17151 +                       return 0;
17152 +               }
17153 +       }
17154 +
17155 +       return 1;
17156 +}
17157 +
17158 +static struct ip6t_target ip6t_reject_reg = {
17159 +       .name           = "REJECT",
17160 +       .target         = reject6_target,
17161 +       .checkentry     = check,
17162 +       .me             = THIS_MODULE
17163 +};
17164 +
17165 +static int __init init(void)
17166 +{
17167 +       if (ip6t_register_target(&ip6t_reject_reg))
17168 +               return -EINVAL;
17169 +       return 0;
17170 +}
17171 +
17172 +static void __exit fini(void)
17173 +{
17174 +       ip6t_unregister_target(&ip6t_reject_reg);
17175 +}
17176 +
17177 +module_init(init);
17178 +module_exit(fini);
17179 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_ROUTE.c
17180 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_ROUTE.c 1970-01-01 01:00:00.000000000 +0100
17181 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_ROUTE.c     2004-06-08 10:37:08.000000000 +0200
17182 @@ -0,0 +1,289 @@
17183 +/*
17184 + * This implements the ROUTE v6 target, which enables you to setup unusual
17185 + * routes not supported by the standard kernel routing table.
17186 + *
17187 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
17188 + *
17189 + * v 1.0 2003/08/05
17190 + *
17191 + * This software is distributed under GNU GPL v2, 1991
17192 + */
17193 +
17194 +#include <linux/module.h>
17195 +#include <linux/skbuff.h>
17196 +#include <linux/ipv6.h>
17197 +#include <linux/netfilter_ipv6/ip6_tables.h>
17198 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
17199 +#include <linux/netdevice.h>
17200 +#include <net/ipv6.h>
17201 +#include <net/ndisc.h>
17202 +#include <net/ip6_route.h>
17203 +#include <linux/icmpv6.h>
17204 +
17205 +#if 1
17206 +#define DEBUGP printk
17207 +#else
17208 +#define DEBUGP(format, args...)
17209 +#endif
17210 +
17211 +#define NIP6(addr) \
17212 +       ntohs((addr).s6_addr16[0]), \
17213 +       ntohs((addr).s6_addr16[1]), \
17214 +       ntohs((addr).s6_addr16[2]), \
17215 +       ntohs((addr).s6_addr16[3]), \
17216 +       ntohs((addr).s6_addr16[4]), \
17217 +       ntohs((addr).s6_addr16[5]), \
17218 +       ntohs((addr).s6_addr16[6]), \
17219 +       ntohs((addr).s6_addr16[7])
17220 +
17221 +/* Route the packet according to the routing keys specified in
17222 + * route_info. Keys are :
17223 + *  - ifindex : 
17224 + *      0 if no oif preferred, 
17225 + *      otherwise set to the index of the desired oif
17226 + *  - route_info->gw :
17227 + *      0 if no gateway specified,
17228 + *      otherwise set to the next host to which the pkt must be routed
17229 + * If success, skb->dev is the output device to which the packet must 
17230 + * be sent and skb->dst is not NULL
17231 + *
17232 + * RETURN:  1 if the packet was succesfully routed to the 
17233 + *            destination desired
17234 + *          0 if the kernel routing table could not route the packet
17235 + *            according to the keys specified
17236 + */
17237 +static int 
17238 +route6(struct sk_buff *skb,
17239 +       unsigned int ifindex,
17240 +       const struct ip6t_route_target_info *route_info)
17241 +{
17242 +       struct rt6_info *rt = NULL;
17243 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17244 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17245 +
17246 +       DEBUGP("ip6t_ROUTE: called with: ");
17247 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
17248 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
17249 +       DEBUGP("OUT=%s\n", route_info->oif);
17250 +       
17251 +       if (ipv6_addr_any(gw))
17252 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
17253 +       else
17254 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
17255 +
17256 +       if (!rt)
17257 +               goto no_route;
17258 +
17259 +       DEBUGP("ip6t_ROUTE: routing gives: ");
17260 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
17261 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
17262 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
17263 +
17264 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
17265 +               goto wrong_route;
17266 +       
17267 +       if (!rt->rt6i_nexthop) {
17268 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
17269 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
17270 +       }
17271 +
17272 +       /* Drop old route. */
17273 +       dst_release(skb->dst);
17274 +       skb->dst = &rt->u.dst;
17275 +       skb->dev = rt->rt6i_dev;
17276 +       return 1;
17277 +
17278 + wrong_route:
17279 +       dst_release(&rt->u.dst);
17280 + no_route:
17281 +       if (!net_ratelimit())
17282 +               return 0;
17283 +
17284 +       printk("ip6t_ROUTE: no explicit route found ");
17285 +       if (ifindex)
17286 +               printk("via interface %s ", route_info->oif);
17287 +       if (!ipv6_addr_any(gw))
17288 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
17289 +       printk("\n");
17290 +       return 0;
17291 +}
17292 +
17293 +
17294 +/* Stolen from ip6_output_finish
17295 + * PRE : skb->dev is set to the device we are leaving by
17296 + *       skb->dst is not NULL
17297 + * POST: the packet is sent with the link layer header pushed
17298 + *       the packet is destroyed
17299 + */
17300 +static void ip_direct_send(struct sk_buff *skb)
17301 +{
17302 +       struct dst_entry *dst = skb->dst;
17303 +       struct hh_cache *hh = dst->hh;
17304 +
17305 +       if (hh) {
17306 +               read_lock_bh(&hh->hh_lock);
17307 +               memcpy(skb->data - 16, hh->hh_data, 16);
17308 +               read_unlock_bh(&hh->hh_lock);
17309 +               skb_push(skb, hh->hh_len);
17310 +               hh->hh_output(skb);
17311 +       } else if (dst->neighbour)
17312 +               dst->neighbour->output(skb);
17313 +       else {
17314 +               if (net_ratelimit())
17315 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
17316 +               kfree_skb(skb);
17317 +       }
17318 +}
17319 +
17320 +
17321 +static unsigned int 
17322 +route6_oif(const struct ip6t_route_target_info *route_info,
17323 +          struct sk_buff *skb) 
17324 +{
17325 +       unsigned int ifindex = 0;
17326 +       struct net_device *dev_out = NULL;
17327 +
17328 +       /* The user set the interface name to use.
17329 +        * Getting the current interface index.
17330 +        */
17331 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
17332 +               ifindex = dev_out->ifindex;
17333 +       } else {
17334 +               /* Unknown interface name : packet dropped */
17335 +               if (net_ratelimit()) 
17336 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
17337 +
17338 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17339 +                       return IP6T_CONTINUE;
17340 +               else
17341 +                       return NF_DROP;
17342 +       }
17343 +
17344 +       /* Trying the standard way of routing packets */
17345 +       if (route6(skb, ifindex, route_info)) {
17346 +               dev_put(dev_out);
17347 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17348 +                       return IP6T_CONTINUE;
17349 +               
17350 +               ip_direct_send(skb);
17351 +               return NF_STOLEN;
17352 +       } else 
17353 +               return NF_DROP;
17354 +}
17355 +
17356 +
17357 +static unsigned int 
17358 +route6_gw(const struct ip6t_route_target_info *route_info,
17359 +         struct sk_buff *skb) 
17360 +{
17361 +       if (route6(skb, 0, route_info)) {
17362 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
17363 +                       return IP6T_CONTINUE;
17364 +
17365 +               ip_direct_send(skb);
17366 +               return NF_STOLEN;
17367 +       } else
17368 +               return NF_DROP;
17369 +}
17370 +
17371 +
17372 +static unsigned int 
17373 +ip6t_route_target(struct sk_buff **pskb,
17374 +                 unsigned int hooknum,
17375 +                 const struct net_device *in,
17376 +                 const struct net_device *out,
17377 +                 const void *targinfo,
17378 +                 void *userinfo)
17379 +{
17380 +       const struct ip6t_route_target_info *route_info = targinfo;
17381 +       struct sk_buff *skb = *pskb;
17382 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
17383 +
17384 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
17385 +               goto do_it;
17386 +
17387 +       /* If we are at PREROUTING or INPUT hook
17388 +        * the TTL isn't decreased by the IP stack
17389 +        */
17390 +       if (hooknum == NF_IP6_PRE_ROUTING ||
17391 +           hooknum == NF_IP6_LOCAL_IN) {
17392 +
17393 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
17394 +
17395 +               if (ipv6h->hop_limit <= 1) {
17396 +                       /* Force OUTPUT device used as source address */
17397 +                       skb->dev = skb->dst->dev;
17398 +
17399 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
17400 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
17401 +
17402 +                       return NF_DROP;
17403 +               }
17404 +
17405 +               ipv6h->hop_limit--;
17406 +       }
17407 +
17408 +
17409 + do_it:
17410 +       if (route_info->oif[0]) 
17411 +               return route6_oif(route_info, *pskb);
17412 +       
17413 +       if (!ipv6_addr_any(gw))
17414 +               return route6_gw(route_info, *pskb);
17415 +
17416 +       if (net_ratelimit()) 
17417 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
17418 +
17419 +       return IP6T_CONTINUE;
17420 +}
17421 +
17422 +
17423 +static int 
17424 +ip6t_route_checkentry(const char *tablename,
17425 +                     const struct ip6t_entry *e,
17426 +                     void *targinfo,
17427 +                     unsigned int targinfosize,
17428 +                     unsigned int hook_mask)
17429 +{
17430 +       if (strcmp(tablename, "mangle") != 0) {
17431 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
17432 +               return 0;
17433 +       }
17434 +
17435 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
17436 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
17437 +                      targinfosize,
17438 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
17439 +               return 0;
17440 +       }
17441 +
17442 +       return 1;
17443 +}
17444 +
17445 +
17446 +static struct ip6t_target ip6t_route_reg = {
17447 +       .name       = "ROUTE",
17448 +       .target     = ip6t_route_target,
17449 +       .checkentry = ip6t_route_checkentry,
17450 +       .me         = THIS_MODULE
17451 +};
17452 +
17453 +
17454 +static int __init init(void)
17455 +{
17456 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
17457 +       if (ip6t_register_target(&ip6t_route_reg))
17458 +               return -EINVAL;
17459 +
17460 +       return 0;
17461 +}
17462 +
17463 +
17464 +static void __exit fini(void)
17465 +{
17466 +       ip6t_unregister_target(&ip6t_route_reg);
17467 +}
17468 +
17469 +module_init(init);
17470 +module_exit(fini);
17471 +MODULE_LICENSE("GPL");
17472 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_TRACE.c
17473 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
17474 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_TRACE.c     2004-06-08 10:37:30.000000000 +0200
17475 @@ -0,0 +1,65 @@
17476 +/* This is a module which is used for setting
17477 + * the NFC_TRACE flag in the nfcache field of an skb. 
17478 + */
17479 +#include <linux/module.h>
17480 +#include <linux/skbuff.h>
17481 +
17482 +#include <linux/netfilter_ipv6/ip6_tables.h>
17483 +
17484 +MODULE_LICENSE("GPL");
17485 +
17486 +static unsigned int
17487 +target(struct sk_buff **pskb,
17488 +       unsigned int hooknum,
17489 +       const struct net_device *in,
17490 +       const struct net_device *out,
17491 +       const void *targinfo,
17492 +       void *userinfo)
17493 +{
17494 +       (*pskb)->nfcache |= NFC_TRACE;
17495 +       return IP6T_CONTINUE;
17496 +}
17497 +
17498 +static int 
17499 +checkentry(const char *tablename,
17500 +                  const struct ip6t_entry *e,
17501 +           void *targinfo,
17502 +           unsigned int targinfosize,
17503 +           unsigned int hook_mask)
17504 +{
17505 +       if (targinfosize != 0) {
17506 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
17507 +                      targinfosize);
17508 +               return 0;
17509 +       }
17510 +
17511 +       if (strcmp(tablename, "raw") != 0) {
17512 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
17513 +               return 0;
17514 +       }
17515 +
17516 +       return 1;
17517 +}
17518 +
17519 +static struct ip6t_target ip6t_trace_reg = { 
17520 +       .name = "TRACE",
17521 +       .target = target, 
17522 +       .checkentry = checkentry, 
17523 +       .me = THIS_MODULE
17524 +};
17525 +
17526 +static int __init init(void)
17527 +{
17528 +       if (ip6t_register_target(&ip6t_trace_reg))
17529 +               return -EINVAL;
17530 +
17531 +       return 0;
17532 +}
17533 +
17534 +static void __exit fini(void)
17535 +{
17536 +       ip6t_unregister_target(&ip6t_trace_reg);
17537 +}
17538 +
17539 +module_init(init);
17540 +module_exit(fini);
17541 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_fuzzy.c
17542 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
17543 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_fuzzy.c     2004-06-08 10:31:37.000000000 +0200
17544 @@ -0,0 +1,189 @@
17545 +/*
17546 + * This module implements a simple TSK FLC
17547 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
17548 + * to limit , in an adaptive and flexible way , the packet rate crossing
17549 + * a given stream . It serves as an initial and very simple (but effective)
17550 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
17551 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
17552 + * into our code in a precise , adaptive and efficient manner.
17553 + *  The goal is very similar to that of "limit" match , but using techniques of
17554 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
17555 + * avoiding over and undershoots - and stuff like that .
17556 + *
17557 + *
17558 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
17559 + * 2002-08-17  : Changed to eliminate floating point operations .
17560 + * 2002-08-23  : Coding style changes .
17561 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
17562 + */
17563 +
17564 +#include <linux/module.h>
17565 +#include <linux/skbuff.h>
17566 +#include <linux/ipv6.h>
17567 +#include <linux/random.h>
17568 +#include <net/tcp.h>
17569 +#include <linux/spinlock.h>
17570 +#include <linux/netfilter_ipv6/ip6_tables.h>
17571 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
17572 +
17573 +/*
17574 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
17575 + Expressed in percentage
17576 +*/
17577 +
17578 +#define PAR_LOW                1/100
17579 +#define PAR_HIGH       1
17580 +
17581 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
17582 +
17583 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
17584 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
17585 +MODULE_LICENSE("GPL");
17586 +
17587 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17588 +{
17589 +       if (tx >= maxi) return 100;
17590 +
17591 +       if (tx <= mini) return 0;
17592 +
17593 +       return ((100 * (tx-mini)) / (maxi-mini));
17594 +}
17595 +
17596 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
17597 +{
17598 +       if (tx <= mini) return 100;
17599 +
17600 +       if (tx >= maxi) return 0;
17601 +
17602 +       return ((100 * (maxi - tx)) / (maxi - mini));
17603 +
17604 +}
17605 +
17606 +static int
17607 +ip6t_fuzzy_match(const struct sk_buff *pskb,
17608 +              const struct net_device *in,
17609 +              const struct net_device *out,
17610 +              const void *matchinfo,
17611 +              int offset,
17612 +              const void *hdr,
17613 +              u_int16_t datalen,
17614 +              int *hotdrop)
17615 +{
17616 +       /* From userspace */
17617 +
17618 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
17619 +
17620 +       u_int8_t random_number;
17621 +       unsigned long amount;
17622 +       u_int8_t howhigh, howlow;
17623 +
17624 +
17625 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
17626 +
17627 +       info->bytes_total += pskb->len;
17628 +       info->packets_total++;
17629 +
17630 +       info->present_time = jiffies;
17631 +
17632 +       if (info->present_time >= info->previous_time)
17633 +               amount = info->present_time - info->previous_time;
17634 +       else {
17635 +               /* There was a transition : I choose to re-sample
17636 +                  and keep the old acceptance rate...
17637 +               */
17638 +
17639 +               amount = 0;
17640 +               info->previous_time = info->present_time;
17641 +               info->bytes_total = info->packets_total = 0;
17642 +            };
17643 +
17644 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
17645 +
17646 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
17647 +                                       / amount);
17648 +
17649 +               info->previous_time = info->present_time;
17650 +               info->bytes_total = info->packets_total = 0;
17651 +
17652 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
17653 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
17654 +
17655 +               info->acceptance_rate = (u_int8_t) \
17656 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
17657 +
17658 +       /* In fact, the above defuzzification would require a denominator
17659 +        * proportional to (howhigh+howlow) but, in this particular case,
17660 +        * that expression is constant.
17661 +        * An imediate consequence is that it is not necessary to call
17662 +        * both mf_high and mf_low - but to keep things understandable,
17663 +        * I did so.
17664 +        */
17665 +
17666 +       }
17667 +
17668 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
17669 +
17670 +
17671 +       if (info->acceptance_rate < 100)
17672 +       {
17673 +               get_random_bytes((void *)(&random_number), 1);
17674 +
17675 +               /*  If within the acceptance , it can pass => don't match */
17676 +               if (random_number <= (255 * info->acceptance_rate) / 100)
17677 +                       return 0;
17678 +               else
17679 +                       return 1; /* It can't pass (It matches) */
17680 +       };
17681 +
17682 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
17683 +
17684 +}
17685 +
17686 +static int
17687 +ip6t_fuzzy_checkentry(const char *tablename,
17688 +                  const struct ip6t_ip6 *ip,
17689 +                  void *matchinfo,
17690 +                  unsigned int matchsize,
17691 +                  unsigned int hook_mask)
17692 +{
17693 +
17694 +       const struct ip6t_fuzzy_info *info = matchinfo;
17695 +
17696 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
17697 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
17698 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
17699 +               return 0;
17700 +       }
17701 +
17702 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
17703 +        || (info->minimum_rate >= info->maximum_rate)) {
17704 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
17705 +               return 0;
17706 +       }
17707 +
17708 +       return 1;
17709 +}
17710 +
17711 +static struct ip6t_match ip6t_fuzzy_reg = {
17712 +       {NULL, NULL},
17713 +       "fuzzy",
17714 +       ip6t_fuzzy_match,
17715 +       ip6t_fuzzy_checkentry,
17716 +       NULL,
17717 +       THIS_MODULE };
17718 +
17719 +static int __init init(void)
17720 +{
17721 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
17722 +               return -EINVAL;
17723 +
17724 +       return 0;
17725 +}
17726 +
17727 +static void __exit fini(void)
17728 +{
17729 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
17730 +}
17731 +
17732 +module_init(init);
17733 +module_exit(fini);
17734 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_nth.c
17735 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_nth.c   1970-01-01 01:00:00.000000000 +0100
17736 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_nth.c       2004-06-08 10:31:42.000000000 +0200
17737 @@ -0,0 +1,173 @@
17738 +/*
17739 +  This is a module which is used for match support for every Nth packet
17740 +  This file is distributed under the terms of the GNU General Public
17741 +  License (GPL). Copies of the GPL can be obtained from:
17742 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
17743 +
17744 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
17745 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
17746 +        * added support for multiple counters
17747 +        * added support for matching on individual packets
17748 +          in the counter cycle
17749 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
17750 +
17751 +*/
17752 +
17753 +#include <linux/module.h>
17754 +#include <linux/skbuff.h>
17755 +#include <linux/ip.h>
17756 +#include <net/tcp.h>
17757 +#include <linux/spinlock.h>
17758 +#include <linux/netfilter_ipv6/ip6_tables.h>
17759 +#include <linux/netfilter_ipv6/ip6t_nth.h>
17760 +
17761 +MODULE_LICENSE("GPL");
17762 +
17763 +/*
17764 + * State information.
17765 + */
17766 +struct state {
17767 +       spinlock_t lock;
17768 +       u_int16_t number;
17769 +};
17770 +
17771 +static struct state states[IP6T_NTH_NUM_COUNTERS];
17772 +
17773 +static int
17774 +ip6t_nth_match(const struct sk_buff *pskb,
17775 +             const struct net_device *in,
17776 +             const struct net_device *out,
17777 +             const void *matchinfo,
17778 +             int offset,
17779 +             const void *hdr,
17780 +             u_int16_t datalen,
17781 +             int *hotdrop)
17782 +{
17783 +       /* Parameters from userspace */
17784 +       const struct ip6t_nth_info *info = matchinfo;
17785 +        unsigned counter = info->counter;
17786 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
17787 +       {
17788 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
17789 +               return 0;
17790 +        };
17791 +
17792 +        spin_lock(&states[counter].lock);
17793 +
17794 +        /* Are we matching every nth packet?*/
17795 +        if (info->packet == 0xFF)
17796 +        {
17797 +               /* We're matching every nth packet and only every nth packet*/
17798 +               /* Do we match or invert match? */
17799 +               if (info->not == 0)
17800 +               {
17801 +                       if (states[counter].number == 0)
17802 +                       {
17803 +                               ++states[counter].number;
17804 +                               goto match;
17805 +                       }
17806 +                       if (states[counter].number >= info->every)
17807 +                               states[counter].number = 0; /* reset the counter */
17808 +                       else
17809 +                               ++states[counter].number;
17810 +                       goto dontmatch;
17811 +               }
17812 +               else
17813 +               {
17814 +                       if (states[counter].number == 0)
17815 +                       {
17816 +                               ++states[counter].number;
17817 +                               goto dontmatch;
17818 +                       }
17819 +                       if (states[counter].number >= info->every)
17820 +                               states[counter].number = 0;
17821 +                       else
17822 +                               ++states[counter].number;
17823 +                       goto match;
17824 +               }
17825 +        }
17826 +        else
17827 +        {
17828 +               /* We're using the --packet, so there must be a rule for every value */
17829 +               if (states[counter].number == info->packet)
17830 +               {
17831 +                       /* only increment the counter when a match happens */
17832 +                       if (states[counter].number >= info->every)
17833 +                               states[counter].number = 0; /* reset the counter */
17834 +                       else
17835 +                               ++states[counter].number;
17836 +                       goto match;
17837 +               }
17838 +               else
17839 +                       goto dontmatch;
17840 +       }
17841 +
17842 + dontmatch:
17843 +       /* don't match */
17844 +       spin_unlock(&states[counter].lock);
17845 +       return 0;
17846 +
17847 + match:
17848 +       spin_unlock(&states[counter].lock);
17849 +       return 1;
17850 +}
17851 +
17852 +static int
17853 +ip6t_nth_checkentry(const char *tablename,
17854 +                  const struct ip6t_ip6 *e,
17855 +                  void *matchinfo,
17856 +                  unsigned int matchsize,
17857 +                  unsigned int hook_mask)
17858 +{
17859 +       /* Parameters from userspace */
17860 +       const struct ip6t_nth_info *info = matchinfo;
17861 +        unsigned counter = info->counter;
17862 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
17863 +       {
17864 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
17865 +                       return 0;
17866 +               };
17867 +
17868 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
17869 +               printk("nth: matchsize %u != %u\n", matchsize,
17870 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
17871 +               return 0;
17872 +       }
17873 +
17874 +       states[counter].number = info->startat;
17875 +
17876 +       return 1;
17877 +}
17878 +
17879 +static struct ip6t_match ip6t_nth_reg = { 
17880 +       {NULL, NULL},
17881 +       "nth",
17882 +       ip6t_nth_match,
17883 +       ip6t_nth_checkentry,
17884 +       NULL,
17885 +       THIS_MODULE };
17886 +
17887 +static int __init init(void)
17888 +{
17889 +       unsigned counter;
17890 +        memset(&states, 0, sizeof(states));
17891 +       if (ip6t_register_match(&ip6t_nth_reg))
17892 +               return -EINVAL;
17893 +
17894 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
17895 +       {
17896 +               spin_lock_init(&(states[counter].lock));
17897 +        };
17898 +
17899 +       printk("ip6t_nth match loaded\n");
17900 +       return 0;
17901 +}
17902 +
17903 +static void __exit fini(void)
17904 +{
17905 +       ip6t_unregister_match(&ip6t_nth_reg);
17906 +       printk("ip6t_nth match unloaded\n");
17907 +}
17908 +
17909 +module_init(init);
17910 +module_exit(fini);
17911 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_owner.c
17912 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-06-07 21:14:56.000000000 +0200
17913 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_owner.c     2004-06-08 10:40:01.000000000 +0200
17914 @@ -21,6 +21,39 @@
17915  MODULE_LICENSE("GPL");
17916  
17917  static int
17918 +match_comm(const struct sk_buff *skb, const char *comm)
17919 +{
17920 +       struct task_struct *p, *g;
17921 +       struct files_struct *files;
17922 +       int i;
17923 +
17924 +       read_lock(&tasklist_lock);
17925 +       do_each_thread(g, p) {
17926 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
17927 +                       continue;
17928 +
17929 +               task_lock(p);
17930 +               files = p->files;
17931 +               if(files) {
17932 +                       read_lock(&files->file_lock);
17933 +                       for (i=0; i < files->max_fds; i++) {
17934 +                               if (fcheck_files(files, i) ==
17935 +                                   skb->sk->sk_socket->file) {
17936 +                                       read_unlock(&files->file_lock);
17937 +                                       task_unlock(p);
17938 +                                       read_unlock(&tasklist_lock);
17939 +                                       return 1;
17940 +                               }
17941 +                       }
17942 +                       read_unlock(&files->file_lock);
17943 +               }
17944 +               task_unlock(p);
17945 +       } while_each_thread(g, p);
17946 +       read_unlock(&tasklist_lock);
17947 +       return 0;
17948 +}
17949 +
17950 +static int
17951  match_pid(const struct sk_buff *skb, pid_t pid)
17952  {
17953         struct task_struct *p;
17954 @@ -125,6 +158,12 @@
17955                         return 0;
17956         }
17957  
17958 +       if(info->match & IP6T_OWNER_COMM) {
17959 +               if (!match_comm(skb, info->comm) ^
17960 +                   !!(info->invert & IP6T_OWNER_COMM))
17961 +                       return 0;
17962 +       }
17963 +
17964         return 1;
17965  }
17966  
17967 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_policy.c
17968 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_policy.c        1970-01-01 01:00:00.000000000 +0100
17969 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_policy.c    2004-06-08 10:42:36.000000000 +0200
17970 @@ -0,0 +1,201 @@
17971 +/* IP tables module for matching IPsec policy
17972 + *
17973 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
17974 + *
17975 + * This program is free software; you can redistribute it and/or modify
17976 + * it under the terms of the GNU General Public License version 2 as
17977 + * published by the Free Software Foundation.
17978 + */
17979 +
17980 +#include <linux/kernel.h>
17981 +#include <linux/config.h>
17982 +#include <linux/module.h>
17983 +#include <linux/skbuff.h>
17984 +#include <linux/init.h>
17985 +#include <net/xfrm.h>
17986 +
17987 +#include <linux/netfilter_ipv6.h>
17988 +#include <linux/netfilter_ipv6/ip6t_policy.h>
17989 +#include <linux/netfilter_ipv6/ip6_tables.h>
17990 +
17991 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
17992 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
17993 +MODULE_LICENSE("GPL");
17994 +
17995 +
17996 +static inline int ip6_masked_addrcmp(struct in6_addr addr1,
17997 +                                     struct in6_addr mask,
17998 +                                     struct in6_addr addr2)
17999 +{
18000 +       int i;
18001 +
18002 +       for (i = 0; i < 16; i++) {
18003 +               if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
18004 +                   (addr2.s6_addr[i] & mask.s6_addr[i]))
18005 +                       return 1;
18006 +       }
18007 +       return 0;
18008 +}
18009 +
18010 +
18011 +static inline int
18012 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
18013 +{
18014 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
18015 +       
18016 +       struct in6_addr xfrm_saddr, xfrm_daddr;
18017 +       
18018 +       if ((e->match.saddr
18019 +            && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
18020 +               ^ e->invert.saddr ) ||
18021 +           (e->match.daddr
18022 +            && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
18023 +               ^ e->invert.daddr ) ||
18024 +           MISMATCH(proto, x->id.proto) ||
18025 +           MISMATCH(mode, x->props.mode) ||
18026 +           MISMATCH(spi, x->id.spi) ||
18027 +           MISMATCH(reqid, x->props.reqid))
18028 +               return 0;
18029 +       return 1;
18030 +}
18031 +
18032 +static int
18033 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18034 +{
18035 +       const struct ip6t_policy_elem *e;
18036 +       struct sec_path *sp = skb->sp;
18037 +       int strict = info->flags & POLICY_MATCH_STRICT;
18038 +       int i, pos;
18039 +
18040 +       if (sp == NULL)
18041 +               return -1;
18042 +       if (strict && info->len != sp->len)
18043 +               return 0;
18044 +
18045 +       for (i = sp->len - 1; i >= 0; i--) {
18046 +               pos = strict ? i - sp->len + 1 : 0;
18047 +               if (pos >= info->len)
18048 +                       return 0;
18049 +               e = &info->pol[pos];
18050 +
18051 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
18052 +                       if (!strict)
18053 +                               return 1;
18054 +               } else if (strict)
18055 +                       return 0;
18056 +       }
18057 +
18058 +       return strict ? 1 : 0;
18059 +}
18060 +
18061 +static int
18062 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
18063 +{
18064 +       const struct ip6t_policy_elem *e;
18065 +       struct dst_entry *dst = skb->dst;
18066 +       int strict = info->flags & POLICY_MATCH_STRICT;
18067 +       int i, pos;
18068 +
18069 +       if (dst->xfrm == NULL)
18070 +               return -1;
18071 +
18072 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
18073 +               pos = strict ? i : 0;
18074 +               if (pos >= info->len)
18075 +                       return 0;
18076 +               e = &info->pol[pos];
18077 +
18078 +               if (match_xfrm_state(dst->xfrm, e)) {
18079 +                       if (!strict)
18080 +                               return 1;
18081 +               } else if (strict)
18082 +                       return 0;
18083 +       }
18084 +
18085 +       return strict ? 1 : 0;
18086 +}
18087 +
18088 +static int match(const struct sk_buff *skb,
18089 +                 const struct net_device *in,
18090 +                 const struct net_device *out,
18091 +                 const void *matchinfo,
18092 +                int offset,
18093 +                const void *hdr,
18094 +                u_int16_t datalen,
18095 +                int *hotdrop)
18096 +{
18097 +       const struct ip6t_policy_info *info = matchinfo;
18098 +       int ret;
18099 +
18100 +       if (info->flags & POLICY_MATCH_IN)
18101 +               ret = match_policy_in(skb, info);
18102 +       else
18103 +               ret = match_policy_out(skb, info);
18104 +
18105 +       if (ret < 0) {
18106 +               if (info->flags & POLICY_MATCH_NONE)
18107 +                       ret = 1;
18108 +               else
18109 +                       ret = 0;
18110 +       } else if (info->flags & POLICY_MATCH_NONE)
18111 +               ret = 0;
18112 +
18113 +       return ret;
18114 +}
18115 +
18116 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
18117 +                      void *matchinfo, unsigned int matchsize,
18118 +                      unsigned int hook_mask)
18119 +{
18120 +       struct ip6t_policy_info *info = matchinfo;
18121 +
18122 +       if (matchsize != IP6T_ALIGN(sizeof(*info))) {
18123 +               printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
18124 +                      matchsize, IP6T_ALIGN(sizeof(*info)));
18125 +               return 0;
18126 +       }
18127 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
18128 +               printk(KERN_ERR "ip6t_policy: neither incoming nor "
18129 +                               "outgoing policy selected\n");
18130 +               return 0;
18131 +       }
18132 +       if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
18133 +           && info->flags & POLICY_MATCH_OUT) {
18134 +               printk(KERN_ERR "ip6t_policy: output policy not valid in "
18135 +                               "PRE_ROUTING and INPUT\n");
18136 +               return 0;
18137 +       }
18138 +       if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
18139 +           && info->flags & POLICY_MATCH_IN) {
18140 +               printk(KERN_ERR "ip6t_policy: input policy not valid in "
18141 +                               "POST_ROUTING and OUTPUT\n");
18142 +               return 0;
18143 +       }
18144 +       if (info->len > POLICY_MAX_ELEM) {
18145 +               printk(KERN_ERR "ip6t_policy: too many policy elements\n");
18146 +               return 0;
18147 +       }
18148 +
18149 +       return 1;
18150 +}
18151 +
18152 +static struct ip6t_match policy_match =
18153 +{
18154 +       .name           = "policy",
18155 +       .match          = match,
18156 +       .checkentry     = checkentry,
18157 +       .me             = THIS_MODULE,
18158 +};
18159 +
18160 +static int __init init(void)
18161 +{
18162 +       return ip6t_register_match(&policy_match);
18163 +}
18164 +
18165 +static void __exit fini(void)
18166 +{
18167 +       ip6t_unregister_match(&policy_match);
18168 +}
18169 +
18170 +module_init(init);
18171 +module_exit(fini);
18172 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_random.c
18173 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6t_random.c        1970-01-01 01:00:00.000000000 +0100
18174 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6t_random.c    2004-06-08 10:31:56.000000000 +0200
18175 @@ -0,0 +1,97 @@
18176 +/*
18177 +  This is a module which is used for a "random" match support.
18178 +  This file is distributed under the terms of the GNU General Public
18179 +  License (GPL). Copies of the GPL can be obtained from:
18180 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
18181 +
18182 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
18183 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
18184 +*/
18185 +
18186 +#include <linux/module.h>
18187 +#include <linux/skbuff.h>
18188 +#include <linux/ip.h>
18189 +#include <linux/random.h>
18190 +#include <net/tcp.h>
18191 +#include <linux/spinlock.h>
18192 +#include <linux/netfilter_ipv6/ip6_tables.h>
18193 +#include <linux/netfilter_ipv6/ip6t_random.h>
18194 +
18195 +MODULE_LICENSE("GPL");
18196 +
18197 +static int
18198 +ip6t_rand_match(const struct sk_buff *pskb,
18199 +              const struct net_device *in,
18200 +              const struct net_device *out,
18201 +              const void *matchinfo,
18202 +              int offset,
18203 +              const void *hdr,
18204 +              u_int16_t datalen,
18205 +              int *hotdrop)
18206 +{
18207 +       /* Parameters from userspace */
18208 +       const struct ip6t_rand_info *info = matchinfo;
18209 +       u_int8_t random_number;
18210 +
18211 +       /* get 1 random number from the kernel random number generation routine */
18212 +       get_random_bytes((void *)(&random_number), 1);
18213 +
18214 +       /* Do we match ? */
18215 +       if (random_number <= info->average)
18216 +               return 1;
18217 +       else
18218 +               return 0;
18219 +}
18220 +
18221 +static int
18222 +ip6t_rand_checkentry(const char *tablename,
18223 +                  const struct ip6t_ip6 *e,
18224 +                  void *matchinfo,
18225 +                  unsigned int matchsize,
18226 +                  unsigned int hook_mask)
18227 +{
18228 +       /* Parameters from userspace */
18229 +       const struct ip6t_rand_info *info = matchinfo;
18230 +
18231 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
18232 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
18233 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
18234 +               return 0;
18235 +       }
18236 +
18237 +       /* must be  1 <= average % <= 99 */
18238 +       /* 1  x 2.55 = 2   */
18239 +       /* 99 x 2.55 = 252 */
18240 +       if ((info->average < 2) || (info->average > 252)) {
18241 +               printk("ip6t_random:  invalid average %u\n", info->average);
18242 +               return 0;
18243 +       }
18244 +
18245 +       return 1;
18246 +}
18247 +
18248 +static struct ip6t_match ip6t_rand_reg = { 
18249 +       {NULL, NULL},
18250 +       "random",
18251 +       ip6t_rand_match,
18252 +       ip6t_rand_checkentry,
18253 +       NULL,
18254 +       THIS_MODULE };
18255 +
18256 +static int __init init(void)
18257 +{
18258 +       if (ip6t_register_match(&ip6t_rand_reg))
18259 +               return -EINVAL;
18260 +
18261 +       printk("ip6t_random match loaded\n");
18262 +       return 0;
18263 +}
18264 +
18265 +static void __exit fini(void)
18266 +{
18267 +       ip6t_unregister_match(&ip6t_rand_reg);
18268 +       printk("ip6t_random match unloaded\n");
18269 +}
18270 +
18271 +module_init(init);
18272 +module_exit(fini);
18273 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_filter.c
18274 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_filter.c    2004-06-07 21:13:37.000000000 +0200
18275 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_filter.c        2004-06-08 10:37:30.000000000 +0200
18276 @@ -58,7 +58,7 @@
18277                 0,
18278                 sizeof(struct ip6t_entry),
18279                 sizeof(struct ip6t_standard),
18280 -               0, { 0, 0 }, { } },
18281 +               0, NULL, 0, { 0, 0 }, { } },
18282               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18283                 -NF_ACCEPT - 1 } },
18284             /* FORWARD */
18285 @@ -66,7 +66,7 @@
18286                 0,
18287                 sizeof(struct ip6t_entry),
18288                 sizeof(struct ip6t_standard),
18289 -               0, { 0, 0 }, { } },
18290 +               0, NULL, 0, { 0, 0 }, { } },
18291               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18292                 -NF_ACCEPT - 1 } },
18293             /* LOCAL_OUT */
18294 @@ -74,7 +74,7 @@
18295                 0,
18296                 sizeof(struct ip6t_entry),
18297                 sizeof(struct ip6t_standard),
18298 -               0, { 0, 0 }, { } },
18299 +               0, NULL, 0, { 0, 0 }, { } },
18300               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18301                 -NF_ACCEPT - 1 } }
18302      },
18303 @@ -83,7 +83,7 @@
18304         0,
18305         sizeof(struct ip6t_entry),
18306         sizeof(struct ip6t_error),
18307 -       0, { 0, 0 }, { } },
18308 +       0, NULL, 0, { 0, 0 }, { } },
18309        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18310           { } },
18311         "ERROR"
18312 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_mangle.c
18313 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_mangle.c    2004-06-07 21:14:05.000000000 +0200
18314 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_mangle.c        2004-06-08 10:37:30.000000000 +0200
18315 @@ -73,7 +73,7 @@
18316                 0,
18317                 sizeof(struct ip6t_entry),
18318                 sizeof(struct ip6t_standard),
18319 -               0, { 0, 0 }, { } },
18320 +               0, NULL, 0, { 0, 0 }, { } },
18321               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18322                 -NF_ACCEPT - 1 } },
18323             /* LOCAL_IN */
18324 @@ -81,7 +81,7 @@
18325                 0,
18326                 sizeof(struct ip6t_entry),
18327                 sizeof(struct ip6t_standard),
18328 -               0, { 0, 0 }, { } },
18329 +               0, NULL, 0, { 0, 0 }, { } },
18330               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18331                 -NF_ACCEPT - 1 } },
18332             /* FORWARD */
18333 @@ -89,7 +89,7 @@
18334                 0,
18335                 sizeof(struct ip6t_entry),
18336                 sizeof(struct ip6t_standard),
18337 -               0, { 0, 0 }, { } },
18338 +               0, NULL, 0, { 0, 0 }, { } },
18339               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18340                 -NF_ACCEPT - 1 } },
18341             /* LOCAL_OUT */
18342 @@ -97,7 +97,7 @@
18343                 0,
18344                 sizeof(struct ip6t_entry),
18345                 sizeof(struct ip6t_standard),
18346 -               0, { 0, 0 }, { } },
18347 +               0, NULL, 0, { 0, 0 }, { } },
18348               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18349                 -NF_ACCEPT - 1 } },
18350             /* POST_ROUTING */
18351 @@ -105,7 +105,7 @@
18352                 0,
18353                 sizeof(struct ip6t_entry),
18354                 sizeof(struct ip6t_standard),
18355 -               0, { 0, 0 }, { } },
18356 +               0, NULL, 0, { 0, 0 }, { } },
18357               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18358                 -NF_ACCEPT - 1 } }
18359      },
18360 @@ -114,7 +114,7 @@
18361         0,
18362         sizeof(struct ip6t_entry),
18363         sizeof(struct ip6t_error),
18364 -       0, { 0, 0 }, { } },
18365 +       0, NULL, 0, { 0, 0 }, { } },
18366        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18367           { } },
18368         "ERROR"
18369 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_raw.c
18370 --- linux-2.6.7-rc3.org/net/ipv6/netfilter/ip6table_raw.c       2004-06-07 21:14:43.000000000 +0200
18371 +++ linux-2.6.7-rc3/net/ipv6/netfilter/ip6table_raw.c   2004-06-08 10:37:30.000000000 +0200
18372 @@ -52,7 +52,7 @@
18373                 0,
18374                 sizeof(struct ip6t_entry),
18375                 sizeof(struct ip6t_standard),
18376 -               0, { 0, 0 }, { } },
18377 +               0, NULL, 0, { 0, 0 }, { } },
18378               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18379                 -NF_ACCEPT - 1 } },
18380             /* LOCAL_OUT */
18381 @@ -60,7 +60,7 @@
18382                 0,
18383                 sizeof(struct ip6t_entry),
18384                 sizeof(struct ip6t_standard),
18385 -               0, { 0, 0 }, { } },
18386 +               0, NULL, 0, { 0, 0 }, { } },
18387               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
18388                 -NF_ACCEPT - 1 } },
18389      },
18390 @@ -69,7 +69,7 @@
18391         0,
18392         sizeof(struct ip6t_entry),
18393         sizeof(struct ip6t_error),
18394 -       0, { 0, 0 }, { } },
18395 +       0, NULL, 0, { 0, 0 }, { } },
18396        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
18397           { } },
18398         "ERROR"
18399 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/ipv6/sit.c linux-2.6.7-rc3/net/ipv6/sit.c
18400 --- linux-2.6.7-rc3.org/net/ipv6/sit.c  2004-06-07 21:14:59.000000000 +0200
18401 +++ linux-2.6.7-rc3/net/ipv6/sit.c      2004-06-08 10:30:55.000000000 +0200
18402 @@ -388,13 +388,7 @@
18403                 skb->dev = tunnel->dev;
18404                 dst_release(skb->dst);
18405                 skb->dst = NULL;
18406 -#ifdef CONFIG_NETFILTER
18407 -               nf_conntrack_put(skb->nfct);
18408 -               skb->nfct = NULL;
18409 -#ifdef CONFIG_NETFILTER_DEBUG
18410 -               skb->nf_debug = 0;
18411 -#endif
18412 -#endif
18413 +               nf_reset(skb);
18414                 ipip6_ecn_decapsulate(iph, skb);
18415                 netif_rx(skb);
18416                 read_unlock(&ipip6_lock);
18417 @@ -580,13 +574,7 @@
18418         if ((iph->ttl = tiph->ttl) == 0)
18419                 iph->ttl        =       iph6->hop_limit;
18420  
18421 -#ifdef CONFIG_NETFILTER
18422 -       nf_conntrack_put(skb->nfct);
18423 -       skb->nfct = NULL;
18424 -#ifdef CONFIG_NETFILTER_DEBUG
18425 -       skb->nf_debug = 0;
18426 -#endif
18427 -#endif
18428 +       nf_reset(skb);
18429  
18430         IPTUNNEL_XMIT();
18431         tunnel->recursion--;
18432 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/xfrm/xfrm_input.c linux-2.6.7-rc3/net/xfrm/xfrm_input.c
18433 --- linux-2.6.7-rc3.org/net/xfrm/xfrm_input.c   2004-06-07 21:13:35.000000000 +0200
18434 +++ linux-2.6.7-rc3/net/xfrm/xfrm_input.c       2004-06-08 10:38:44.000000000 +0200
18435 @@ -29,6 +29,9 @@
18436         if (!sp)
18437                 return NULL;
18438  
18439 +#ifdef CONFIG_NETFILTER
18440 +       sp->decap_done = 0;
18441 +#endif
18442         sp->len = 0;
18443         if (src) {
18444                 int i;
18445 diff -Nur --exclude '*.orig' linux-2.6.7-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.7-rc3/net/xfrm/xfrm_policy.c
18446 --- linux-2.6.7-rc3.org/net/xfrm/xfrm_policy.c  2004-06-07 21:14:24.000000000 +0200
18447 +++ linux-2.6.7-rc3/net/xfrm/xfrm_policy.c      2004-06-08 10:38:46.000000000 +0200
18448 @@ -21,6 +21,7 @@
18449  #include <linux/workqueue.h>
18450  #include <linux/notifier.h>
18451  #include <linux/netdevice.h>
18452 +#include <linux/netfilter.h>
18453  #include <net/xfrm.h>
18454  #include <net/ip.h>
18455  
18456 @@ -911,6 +912,7 @@
18457  
18458         if (_decode_session(skb, &fl, family) < 0)
18459                 return 0;
18460 +       nf_nat_decode_session(skb, &fl, family);
18461  
18462         /* First, check used SA against their selectors. */
18463         if (skb->sp) {
This page took 1.759676 seconds and 3 git commands to generate.