]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.6-rc3-pom-ng-20040429.patch
- CSZ scheduler removed from kernel tree.
[packages/kernel.git] / 2.6.6-rc3-pom-ng-20040429.patch
1   Netfilter SNAP 20040429
2    included:
3    PENDING/expect-evict-order
4    PENDING/init_conntrack-optimize
5    PENDING/ipt_helper-invert-fix
6    PENDING/nf-log
7    PENDING/nf_reset
8    PENDING/orphaned-expect-fix
9    PENDING/proc-no-internal-targets
10    BASE/HOPLIMIT
11    BASE/IPV4OPTSSTRING
12    BASE/NETLINK                 // fix socket -> sk_socket
13    BASE/REJECT
14    BASE/TTL
15    BASE/connlimit
16    BASE/dstlimit
17    BASE/fuzzy
18    BASE/ipv4options
19    BASE/mport
20    BASE/nth
21    BASE/osf                     // fix socket -> sk_socket
22    BASE/pool                    // added EXPORT_SYMBOL(ip_pool_mod, ip_pool_match)
23    BASE/psd
24    BASE/quota
25    BASE/random
26    BASE/realm
27    BASE/sctp
28    BASE/time
29    BASE/u32
30    EXTRA/CONNMARK               // main linux.patch needs fix
31    EXTRA/IPMARK
32    EXTRA/ROUTE
33    EXTRA/TARPIT                 // fix Makefile.ladd and req patch for 2.6
34    EXTRA/TRACE
35    EXTRA/XOR
36    EXTRA/addrtype
37    EXTRA/eggdrop-conntrack
38    EXTRA/h323-conntrack-nat
39    EXTRA/ipsec-01-output-hooks
40    EXTRA/ipsec-02-input-hooks
41    EXTRA/ipsec-03-policy-lookup
42    EXTRA/ipsec-04-policy-check
43    EXTRA/ipt_helper-any
44    EXTRA/mms-conntrack-nat
45    EXTRA/owner-socketlookup
46    EXTRA/ownercmd
47    EXTRA/policy
48    EXTRA/quake3-conntrack-nat
49    EXTRA/rsh
50    EXTRA/rtsp-conntrack
51    EXTRA/sctp-conntrack-nat
52    EXTRA/string                 // required unclean module - included
53    EXTRA/talk-conntrack-nat
54    
55 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter.h linux-2.6.6-rc3/include/linux/netfilter.h
56 --- linux-2.6.6-rc3.org/include/linux/netfilter.h       2004-04-28 03:35:48.000000000 +0200
57 +++ linux-2.6.6-rc3/include/linux/netfilter.h   2004-04-30 09:12:42.000000000 +0200
58 @@ -23,6 +23,7 @@
59     <= 0x2000 is used for protocol-flags. */
60  #define NFC_UNKNOWN 0x4000
61  #define NFC_ALTERED 0x8000
62 +#define NFC_TRACE   0x10000
63  
64  #ifdef __KERNEL__
65  #include <linux/config.h>
66 @@ -137,12 +138,14 @@
67  /* This is gross, but inline doesn't cut it for avoiding the function
68     call in fast path: gcc doesn't inline (needs value tracking?). --RR */
69  #ifdef CONFIG_NETFILTER_DEBUG
70 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
71 - nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
72 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
73 +(!(cond)                                                               \
74 + ? (okfn)(skb)                                                                 \
75 + : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
76  #define NF_HOOK_THRESH nf_hook_slow
77  #else
78 -#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
79 -(list_empty(&nf_hooks[(pf)][(hook)])                                   \
80 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)         \
81 +(!(cond) || list_empty(&nf_hooks[(pf)][(hook)])                                \
82   ? (okfn)(skb)                                                         \
83   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
84  #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)     \
85 @@ -150,6 +153,8 @@
86   ? (okfn)(skb)                                                         \
87   : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
88  #endif
89 +#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)                    \
90 + NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)
91  
92  int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
93                  struct net_device *indev, struct net_device *outdev,
94 @@ -182,7 +187,24 @@
95  
96  #else /* !CONFIG_NETFILTER */
97  #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
98 +#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
99  #endif /*CONFIG_NETFILTER*/
100  
101 +#ifdef CONFIG_XFRM
102 +#ifdef CONFIG_IP_NF_NAT_NEEDED
103 +struct flowi;
104 +extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl);
105 +
106 +static inline void
107 +nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
108 +{
109 +       if (family == AF_INET)
110 +               nf_nat_decode_session4(skb, fl);
111 +}
112 +#else /* CONFIG_IP_NF_NAT_NEEDED */
113 +#define nf_nat_decode_session(skb,fl,family)
114 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
115 +#endif /* CONFIG_XFRM */
116 +
117  #endif /*__KERNEL__*/
118  #endif /*__LINUX_NETFILTER_H*/
119 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h linux-2.6.6-rc3/include/linux/netfilter_helpers.h
120 --- linux-2.6.6-rc3.org/include/linux/netfilter_helpers.h       1970-01-01 01:00:00.000000000 +0100
121 +++ linux-2.6.6-rc3/include/linux/netfilter_helpers.h   2004-04-30 09:14:05.000000000 +0200
122 @@ -0,0 +1,133 @@
123 +/*
124 + * Helpers for netfiler modules.  This file provides implementations for basic
125 + * functions such as strncasecmp(), etc.
126 + *
127 + * gcc will warn for defined but unused functions, so we only include the
128 + * functions requested.  The following macros are used:
129 + *   NF_NEED_STRNCASECMP        nf_strncasecmp()
130 + *   NF_NEED_STRTOU16           nf_strtou16()
131 + *   NF_NEED_STRTOU32           nf_strtou32()
132 + */
133 +#ifndef _NETFILTER_HELPERS_H
134 +#define _NETFILTER_HELPERS_H
135 +
136 +/* Only include these functions for kernel code. */
137 +#ifdef __KERNEL__
138 +
139 +#include <linux/ctype.h>
140 +#define iseol(c) ( (c) == '\r' || (c) == '\n' )
141 +
142 +/*
143 + * The standard strncasecmp()
144 + */
145 +#ifdef NF_NEED_STRNCASECMP
146 +static int
147 +nf_strncasecmp(const char* s1, const char* s2, u_int32_t len)
148 +{
149 +    if (s1 == NULL || s2 == NULL)
150 +    {
151 +        if (s1 == NULL && s2 == NULL)
152 +        {
153 +            return 0;
154 +        }
155 +        return (s1 == NULL) ? -1 : 1;
156 +    }
157 +    while (len > 0 && tolower(*s1) == tolower(*s2))
158 +    {
159 +        len--;
160 +        s1++;
161 +        s2++;
162 +    }
163 +    return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) );
164 +}
165 +#endif /* NF_NEED_STRNCASECMP */
166 +
167 +/*
168 + * Parse a string containing a 16-bit unsigned integer.
169 + * Returns the number of chars used, or zero if no number is found.
170 + */
171 +#ifdef NF_NEED_STRTOU16
172 +static int
173 +nf_strtou16(const char* pbuf, u_int16_t* pval)
174 +{
175 +    int n = 0;
176 +
177 +    *pval = 0;
178 +    while (isdigit(pbuf[n]))
179 +    {
180 +        *pval = (*pval * 10) + (pbuf[n] - '0');
181 +        n++;
182 +    }
183 +
184 +    return n;
185 +}
186 +#endif /* NF_NEED_STRTOU16 */
187 +
188 +/*
189 + * Parse a string containing a 32-bit unsigned integer.
190 + * Returns the number of chars used, or zero if no number is found.
191 + */
192 +#ifdef NF_NEED_STRTOU32
193 +static int
194 +nf_strtou32(const char* pbuf, u_int32_t* pval)
195 +{
196 +    int n = 0;
197 +
198 +    *pval = 0;
199 +    while (pbuf[n] >= '0' && pbuf[n] <= '9')
200 +    {
201 +        *pval = (*pval * 10) + (pbuf[n] - '0');
202 +        n++;
203 +    }
204 +
205 +    return n;
206 +}
207 +#endif /* NF_NEED_STRTOU32 */
208 +
209 +/*
210 + * Given a buffer and length, advance to the next line and mark the current
211 + * line.
212 + */
213 +#ifdef NF_NEED_NEXTLINE
214 +static int
215 +nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
216 +{
217 +    uint    off = *poff;
218 +    uint    physlen = 0;
219 +
220 +    if (off >= len)
221 +    {
222 +        return 0;
223 +    }
224 +
225 +    while (p[off] != '\n')
226 +    {
227 +        if (len-off <= 1)
228 +        {
229 +            return 0;
230 +        }
231 +
232 +        physlen++;
233 +        off++;
234 +    }
235 +
236 +    /* if we saw a crlf, physlen needs adjusted */
237 +    if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
238 +    {
239 +        physlen--;
240 +    }
241 +
242 +    /* advance past the newline */
243 +    off++;
244 +
245 +    *plineoff = *poff;
246 +    *plinelen = physlen;
247 +    *poff = off;
248 +
249 +    return 1;
250 +}
251 +#endif /* NF_NEED_NEXTLINE */
252 +
253 +#endif /* __KERNEL__ */
254 +
255 +#endif /* _NETFILTER_HELPERS_H */
256 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h
257 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack.h     2004-04-28 03:36:37.000000000 +0200
258 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack.h 2004-04-30 09:14:39.000000000 +0200
259 @@ -51,10 +51,12 @@
260  
261  #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
262  #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
263 +#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
264  
265  /* per conntrack: protocol private data */
266  union ip_conntrack_proto {
267         /* insert conntrack proto private data here */
268 +       struct ip_ct_sctp sctp;
269         struct ip_ct_tcp tcp;
270         struct ip_ct_icmp icmp;
271  };
272 @@ -64,6 +66,11 @@
273  };
274  
275  /* Add protocol helper include file here */
276 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
277 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
278 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
279 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
280 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
281  #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
282  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
283  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
284 @@ -71,6 +78,11 @@
285  /* per expectation: application helper private data */
286  union ip_conntrack_expect_help {
287         /* insert conntrack helper private data (expect) here */
288 +       struct ip_ct_talk_expect exp_talk_info;
289 +       struct ip_ct_rtsp_expect exp_rtsp_info;
290 +       struct ip_ct_rsh_expect exp_rsh_info;
291 +       struct ip_ct_mms_expect exp_mms_info;
292 +       struct ip_ct_h225_expect exp_h225_info;
293         struct ip_ct_amanda_expect exp_amanda_info;
294         struct ip_ct_ftp_expect exp_ftp_info;
295         struct ip_ct_irc_expect exp_irc_info;
296 @@ -85,6 +97,11 @@
297  /* per conntrack: application helper private data */
298  union ip_conntrack_help {
299         /* insert conntrack helper private data (master) here */
300 +       struct ip_ct_talk_master ct_talk_info;
301 +       struct ip_ct_rtsp_master ct_rtsp_info;
302 +       struct ip_ct_rsh_master ct_rsh_info;
303 +       struct ip_ct_mms_master ct_mms_info;
304 +       struct ip_ct_h225_master ct_h225_info;
305         struct ip_ct_ftp_master ct_ftp_info;
306         struct ip_ct_irc_master ct_irc_info;
307  };
308 @@ -207,6 +224,10 @@
309         } nat;
310  #endif /* CONFIG_IP_NF_NAT_NEEDED */
311  
312 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
313 +       unsigned long mark;
314 +#endif
315 +
316  };
317  
318  /* get master conntrack via master expectation */
319 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h
320 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h        1970-01-01 01:00:00.000000000 +0100
321 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_h323.h    2004-04-30 09:12:34.000000000 +0200
322 @@ -0,0 +1,31 @@
323 +#ifndef _IP_CONNTRACK_H323_H
324 +#define _IP_CONNTRACK_H323_H
325 +/* H.323 connection tracking. */
326 +
327 +#ifdef __KERNEL__
328 +/* Protects H.323 related data */
329 +#include <linux/netfilter_ipv4/lockhelp.h>
330 +DECLARE_LOCK_EXTERN(ip_h323_lock);
331 +#endif
332 +
333 +/* Default H.225 port */
334 +#define H225_PORT      1720
335 +
336 +/* This structure is per expected connection */
337 +struct ip_ct_h225_expect {
338 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
339 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
340 +       unsigned int offset;            /* offset of the address in the payload */
341 +};
342 +
343 +/* This structure exists only once per master */
344 +struct ip_ct_h225_master {
345 +       int is_h225;                            /* H.225 or H.245 connection */
346 +#ifdef CONFIG_IP_NF_NAT_NEEDED
347 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
348 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
349 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
350 +#endif
351 +};
352 +
353 +#endif /* _IP_CONNTRACK_H323_H */
354 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h
355 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h 1970-01-01 01:00:00.000000000 +0100
356 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_mms.h     2004-04-30 09:12:58.000000000 +0200
357 @@ -0,0 +1,31 @@
358 +#ifndef _IP_CONNTRACK_MMS_H
359 +#define _IP_CONNTRACK_MMS_H
360 +/* MMS tracking. */
361 +
362 +#ifdef __KERNEL__
363 +#include <linux/netfilter_ipv4/lockhelp.h>
364 +
365 +DECLARE_LOCK_EXTERN(ip_mms_lock);
366 +
367 +#define MMS_PORT                         1755
368 +#define MMS_SRV_MSG_ID                   196610
369 +
370 +#define MMS_SRV_MSG_OFFSET               36
371 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
372 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
373 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
374 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
375 +#endif
376 +
377 +/* This structure is per expected connection */
378 +struct ip_ct_mms_expect {
379 +       u_int32_t len;
380 +       u_int32_t padding;
381 +       u_int16_t port;
382 +};
383 +
384 +/* This structure exists only once per master */
385 +struct ip_ct_mms_master {
386 +};
387 +
388 +#endif /* _IP_CONNTRACK_MMS_H */
389 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
390 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h      1970-01-01 01:00:00.000000000 +0100
391 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_quake3.h  2004-04-30 09:13:29.000000000 +0200
392 @@ -0,0 +1,21 @@
393 +#ifndef _IP_CT_QUAKE3
394 +#define _IP_CT_QUAKE3
395 +
396 +/* Don't confuse with 27960, often used as the Server Port */
397 +#define QUAKE3_MASTER_PORT 27950
398 +
399 +struct quake3_search {
400 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
401 +       const char *pattern;
402 +       size_t plen;
403 +}; 
404 +
405 +/* This structure is per expected connection */
406 +struct ip_ct_quake3_expect {
407 +};
408 +
409 +/* This structure exists only once per master */
410 +struct ip_ct_quake3_master {
411 +};
412 +
413 +#endif /* _IP_CT_QUAKE3 */
414 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
415 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h 1970-01-01 01:00:00.000000000 +0100
416 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rsh.h     2004-04-30 09:13:59.000000000 +0200
417 @@ -0,0 +1,35 @@
418 +/* RSH extension for IP connection tracking, Version 1.0
419 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
420 + * based on HW's ip_conntrack_irc.c     
421 + *
422 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
423 + *
424 + *      This program is free software; you can redistribute it and/or
425 + *      modify it under the terms of the GNU General Public License
426 + *      as published by the Free Software Foundation; either version
427 + *      2 of the License, or (at your option) any later version.
428 + */
429 +#ifndef _IP_CONNTRACK_RSH_H
430 +#define _IP_CONNTRACK_RSH_H
431 +
432 +#ifdef __KERNEL__
433 +#include <linux/netfilter_ipv4/lockhelp.h>
434 +
435 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
436 +#endif
437 +
438 +
439 +#define RSH_PORT       514
440 +
441 +/* This structure is per expected connection */
442 +struct ip_ct_rsh_expect
443 +{
444 +       u_int16_t port;
445 +};
446 +
447 +/* This structure exists only once per master */
448 +struct ip_ct_rsh_master {
449 +};
450 +
451 +#endif /* _IP_CONNTRACK_RSH_H */
452 +
453 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h
454 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h        1970-01-01 01:00:00.000000000 +0100
455 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_rtsp.h    2004-04-30 09:14:05.000000000 +0200
456 @@ -0,0 +1,68 @@
457 +/*
458 + * RTSP extension for IP connection tracking.
459 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
460 + * based on ip_conntrack_irc.h
461 + *
462 + *      This program is free software; you can redistribute it and/or
463 + *      modify it under the terms of the GNU General Public License
464 + *      as published by the Free Software Foundation; either version
465 + *      2 of the License, or (at your option) any later version.
466 + */
467 +#ifndef _IP_CONNTRACK_RTSP_H
468 +#define _IP_CONNTRACK_RTSP_H
469 +
470 +/* #define IP_NF_RTSP_DEBUG */
471 +#define IP_NF_RTSP_VERSION "0.01"
472 +
473 +/* port block types */
474 +typedef enum {
475 +    pb_single,  /* client_port=x */
476 +    pb_range,   /* client_port=x-y */
477 +    pb_discon   /* client_port=x/y (rtspbis) */
478 +} portblock_t;
479 +
480 +/* We record seq number and length of rtsp headers here, all in host order. */
481 +
482 +/*
483 + * This structure is per expected connection.  It is a member of struct
484 + * ip_conntrack_expect.  The TCP SEQ for the conntrack expect is stored
485 + * there and we are expected to only store the length of the data which
486 + * needs replaced.  If a packet contains multiple RTSP messages, we create
487 + * one expected connection per message.
488 + *
489 + * We use these variables to mark the entire header block.  This may seem
490 + * like overkill, but the nature of RTSP requires it.  A header may appear
491 + * multiple times in a message.  We must treat two Transport headers the
492 + * same as one Transport header with two entries.
493 + */
494 +struct ip_ct_rtsp_expect
495 +{
496 +    u_int32_t   len;        /* length of header block */
497 +    portblock_t pbtype;     /* Type of port block that was requested */
498 +    u_int16_t   loport;     /* Port that was requested, low or first */
499 +    u_int16_t   hiport;     /* Port that was requested, high or second */
500 +#if 0
501 +    uint        method;     /* RTSP method */
502 +    uint        cseq;       /* CSeq from request */
503 +#endif
504 +};
505 +
506 +/* This structure exists only once per master */
507 +struct ip_ct_rtsp_master
508 +{
509 +    /* Empty (?) */
510 +};
511 +
512 +
513 +#ifdef __KERNEL__
514 +
515 +#include <linux/netfilter_ipv4/lockhelp.h>
516 +
517 +#define RTSP_PORT   554
518 +
519 +/* Protects rtsp part of conntracks */
520 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
521 +
522 +#endif /* __KERNEL__ */
523 +
524 +#endif /* _IP_CONNTRACK_RTSP_H */
525 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h
526 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_sctp.h        1970-01-01 01:00:00.000000000 +0100
527 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_sctp.h    2004-04-30 09:14:08.000000000 +0200
528 @@ -0,0 +1,25 @@
529 +#ifndef _IP_CONNTRACK_SCTP_H
530 +#define _IP_CONNTRACK_SCTP_H
531 +/* SCTP tracking. */
532 +
533 +enum sctp_conntrack {
534 +       SCTP_CONNTRACK_NONE,
535 +       SCTP_CONNTRACK_CLOSED,
536 +       SCTP_CONNTRACK_COOKIE_WAIT,
537 +       SCTP_CONNTRACK_COOKIE_ECHOED,
538 +       SCTP_CONNTRACK_ESTABLISHED,
539 +       SCTP_CONNTRACK_SHUTDOWN_SENT,
540 +       SCTP_CONNTRACK_SHUTDOWN_RECD,
541 +       SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
542 +       SCTP_CONNTRACK_MAX
543 +};
544 +
545 +struct ip_ct_sctp
546 +{
547 +       enum sctp_conntrack state;
548 +
549 +       u_int32_t vtag[IP_CT_DIR_MAX];
550 +       u_int32_t ttag[IP_CT_DIR_MAX];
551 +};
552 +
553 +#endif /* _IP_CONNTRACK_SCTP_H */
554 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h
555 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h        1970-01-01 01:00:00.000000000 +0100
556 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_talk.h    2004-04-30 09:14:39.000000000 +0200
557 @@ -0,0 +1,152 @@
558 +#ifndef _IP_CONNTRACK_TALK_H
559 +#define _IP_CONNTRACK_TALK_H
560 +/* TALK tracking. */
561 +
562 +#ifdef __KERNEL__
563 +#include <linux/in.h>
564 +#include <linux/netfilter_ipv4/lockhelp.h>
565 +
566 +/* Protects talk part of conntracks */
567 +DECLARE_LOCK_EXTERN(ip_talk_lock);
568 +#endif
569 +
570 +
571 +#define TALK_PORT      517
572 +#define NTALK_PORT     518
573 +
574 +/* talk structures and constants from <protocols/talkd.h> */
575 +
576 +/*
577 + * 4.3BSD struct sockaddr
578 + */
579 +struct talk_addr {
580 +       u_int16_t ta_family;
581 +       u_int16_t ta_port;
582 +       u_int32_t ta_addr;
583 +       u_int32_t ta_junk1;
584 +       u_int32_t ta_junk2;
585 +};
586 +
587 +#define        TALK_OLD_NSIZE  9
588 +#define        TALK_NSIZE      12
589 +#define        TALK_TTY_NSIZE  16
590 +
591 +/*
592 + * Client->server request message formats.
593 + */
594 +struct talk_msg {
595 +       u_char  type;           /* request type, see below */
596 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
597 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
598 +       u_char  pad;
599 +       u_int32_t id_num;       /* message id */
600 +       int32_t pid;            /* caller's process id */
601 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
602 +       struct  talk_addr addr;         /* old (4.3) style */
603 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
604 +};
605 +
606 +struct ntalk_msg {
607 +       u_char  vers;           /* protocol version */
608 +       u_char  type;           /* request type, see below */
609 +       u_char  answer;         /* not used */
610 +       u_char  pad;
611 +       u_int32_t id_num;       /* message id */
612 +       struct  talk_addr addr;         /* old (4.3) style */
613 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
614 +       int32_t pid;            /* caller's process id */
615 +       char    l_name[TALK_NSIZE];/* caller's name */
616 +       char    r_name[TALK_NSIZE];/* callee's name */
617 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
618 +};
619 +
620 +struct ntalk2_msg {
621 +       u_char  vers;           /* talk protocol version    */
622 +       u_char  type;           /* request type             */
623 +       u_char  answer;         /*  */
624 +       u_char  extended;       /* !0 if additional parts   */
625 +       u_int32_t id_num;       /* message id number (dels) */
626 +       struct  talk_addr addr;         /* target address   */
627 +       struct  talk_addr ctl_addr;     /* reply to address */
628 +       int32_t pid;            /* caller's process id */
629 +       char    l_name[TALK_NSIZE];  /* caller's name */
630 +       char    r_name[TALK_NSIZE];  /* callee's name */
631 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
632 +};
633 +
634 +/*
635 + * Server->client response message formats.
636 + */
637 +struct talk_response {
638 +       u_char  type;           /* type of request message, see below */
639 +       u_char  answer;         /* response to request message, see below */
640 +       u_char  pad[2];
641 +       u_int32_t id_num;       /* message id */
642 +       struct  talk_addr addr; /* address for establishing conversation */
643 +};
644 +
645 +struct ntalk_response {
646 +       u_char  vers;           /* protocol version */
647 +       u_char  type;           /* type of request message, see below */
648 +       u_char  answer;         /* response to request message, see below */
649 +       u_char  pad;
650 +       u_int32_t id_num;       /* message id */
651 +       struct  talk_addr addr; /* address for establishing conversation */
652 +};
653 +
654 +struct ntalk2_response {
655 +       u_char  vers;           /* protocol version         */
656 +       u_char  type;           /* type of request message  */
657 +       u_char  answer;         /* response to request      */
658 +       u_char  rvers;          /* Version of answering vers*/
659 +       u_int32_t id_num;       /* message id number        */
660 +       struct  talk_addr addr; /* address for connection   */
661 +       /* This is at the end to compatiblize this with NTALK version.   */
662 +       char    r_name[TALK_NSIZE]; /* callee's name            */
663 +};
664 +
665 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
666 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
667 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
668 +
669 +#define        TALK_VERSION    0               /* protocol versions */
670 +#define        NTALK_VERSION   1
671 +#define        NTALK2_VERSION  2
672 +
673 +/* message type values */
674 +#define LEAVE_INVITE   0       /* leave invitation with server */
675 +#define LOOK_UP                1       /* check for invitation by callee */
676 +#define DELETE         2       /* delete invitation by caller */
677 +#define ANNOUNCE       3       /* announce invitation by caller */
678 +/* NTALK2 */
679 +#define REPLY_QUERY    4       /* request reply data from local daemon */
680 +
681 +/* answer values */
682 +#define SUCCESS                0       /* operation completed properly */
683 +#define NOT_HERE       1       /* callee not logged in */
684 +#define FAILED         2       /* operation failed for unexplained reason */
685 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
686 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
687 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
688 +#define        BADVERSION      6       /* request has invalid protocol version */
689 +#define        BADADDR         7       /* request has invalid addr value */
690 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
691 +/* NTALK2 */
692 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
693 +#define TRY_HERE       10      /* Not on this machine, try this      */
694 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
695 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
696 +
697 +/* We don't really need much for talk */
698 +struct ip_ct_talk_expect
699 +{
700 +       /* Port that was to be used */
701 +       u_int16_t port;
702 +};
703 +
704 +/* This structure exists only once per master */
705 +struct ip_ct_talk_master
706 +{
707 +};
708 +
709 +#endif /* _IP_CONNTRACK_TALK_H */
710 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
711 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h       2004-04-28 03:36:22.000000000 +0200
712 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h   2004-04-30 09:14:08.000000000 +0200
713 @@ -25,6 +25,9 @@
714         struct {
715                 u_int16_t id;
716         } icmp;
717 +       struct {
718 +               u_int16_t port;
719 +       } sctp;
720  };
721  
722  /* The manipulable part of the tuple. */
723 @@ -55,6 +58,9 @@
724                         struct {
725                                 u_int8_t type, code;
726                         } icmp;
727 +                       struct {
728 +                               u_int16_t port;
729 +                       } sctp;
730                 } u;
731  
732                 /* The protocol. */
733 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h
734 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_pool.h  1970-01-01 01:00:00.000000000 +0100
735 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_pool.h      2004-04-30 09:10:40.000000000 +0200
736 @@ -0,0 +1,64 @@
737 +#ifndef _IP_POOL_H
738 +#define _IP_POOL_H
739 +
740 +/***************************************************************************/
741 +/*  This program is free software; you can redistribute it and/or modify   */
742 +/*  it under the terms of the GNU General Public License as published by   */
743 +/*  the Free Software Foundation; either version 2 of the License, or     */
744 +/*  (at your option) any later version.                                           */
745 +/*                                                                        */
746 +/*  This program is distributed in the hope that it will be useful,       */
747 +/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
748 +/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
749 +/*  GNU General Public License for more details.                          */
750 +/*                                                                        */
751 +/*  You should have received a copy of the GNU General Public License     */
752 +/*  along with this program; if not, write to the Free Software                   */
753 +/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
754 +/***************************************************************************/
755 +
756 +/* A sockopt of such quality has hardly ever been seen before on the open
757 + * market!  This little beauty, hardly ever used: above 64, so it's
758 + * traditionally used for firewalling, not touched (even once!) by the
759 + * 2.0, 2.2 and 2.4 kernels!
760 + *
761 + * Comes with its own certificate of authenticity, valid anywhere in the
762 + * Free world!
763 + *
764 + * Rusty, 19.4.2000
765 + */
766 +#define SO_IP_POOL 81
767 +
768 +typedef int ip_pool_t;                 /* pool index */
769 +#define IP_POOL_NONE   ((ip_pool_t)-1)
770 +
771 +struct ip_pool_request {
772 +       int op;
773 +       ip_pool_t index;
774 +       u_int32_t addr;
775 +       u_int32_t addr2;
776 +};
777 +
778 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
779 +
780 +#define IP_POOL_BAD001         0x00000010
781 +
782 +#define IP_POOL_FLUSH          0x00000011      /* req.index, no arguments */
783 +#define IP_POOL_INIT           0x00000012      /* from addr to addr2 incl. */
784 +#define IP_POOL_DESTROY                0x00000013      /* req.index, no arguments */
785 +#define IP_POOL_ADD_ADDR       0x00000014      /* add addr to pool */
786 +#define IP_POOL_DEL_ADDR       0x00000015      /* del addr from pool */
787 +#define IP_POOL_HIGH_NR                0x00000016      /* result in req.index */
788 +#define IP_POOL_LOOKUP         0x00000017      /* result in addr and addr2 */
789 +#define IP_POOL_USAGE          0x00000018      /* result in addr */
790 +#define IP_POOL_TEST_ADDR      0x00000019      /* result (0/1) returned */
791 +
792 +#ifdef __KERNEL__
793 +
794 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
795 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
796 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
797 +
798 +#endif
799 +
800 +#endif /*_IP_POOL_H*/
801 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h
802 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ip_tables.h        2004-04-28 03:35:48.000000000 +0200
803 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ip_tables.h    2004-04-30 09:11:53.000000000 +0200
804 @@ -134,6 +134,12 @@
805         /* Back pointer */
806         unsigned int comefrom;
807  
808 +       /* Name of the chain */
809 +       char *chainname;
810 +       
811 +       /* Rule number in the chain. */
812 +       u_int32_t rulenum;
813 +
814         /* Packet and byte counters. */
815         struct ipt_counters counters;
816  
817 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h
818 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h     1970-01-01 01:00:00.000000000 +0100
819 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_CONNMARK.h 2004-04-30 09:11:35.000000000 +0200
820 @@ -0,0 +1,25 @@
821 +#ifndef _IPT_CONNMARK_H_target
822 +#define _IPT_CONNMARK_H_target
823 +
824 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
825 + * by Henrik Nordstrom <hno@marasystems.com>
826 + *
827 + * This program is free software; you can redistribute it and/or modify
828 + * it under the terms of the GNU General Public License as published by
829 + * the Free Software Foundation; either version 2 of the License, or
830 + * (at your option) any later version.
831 + */
832 +
833 +enum {
834 +       IPT_CONNMARK_SET = 0,
835 +       IPT_CONNMARK_SAVE,
836 +       IPT_CONNMARK_RESTORE
837 +};
838 +
839 +struct ipt_connmark_target_info {
840 +       unsigned long mark;
841 +       unsigned long mask;
842 +       u_int8_t mode;
843 +};
844 +
845 +#endif /*_IPT_CONNMARK_H_target*/
846 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h
847 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_IPMARK.h       1970-01-01 01:00:00.000000000 +0100
848 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_IPMARK.h   2004-04-30 09:11:38.000000000 +0200
849 @@ -0,0 +1,13 @@
850 +#ifndef _IPT_IPMARK_H_target
851 +#define _IPT_IPMARK_H_target
852 +
853 +struct ipt_ipmark_target_info {
854 +       unsigned long andmask;
855 +       unsigned long ormask;
856 +       unsigned int addr;
857 +};
858 +
859 +#define IPT_IPMARK_SRC    0
860 +#define IPT_IPMARK_DST    1
861 +
862 +#endif /*_IPT_IPMARK_H_target*/
863 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h
864 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h      1970-01-01 01:00:00.000000000 +0100
865 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h  2004-04-30 09:10:09.000000000 +0200
866 @@ -0,0 +1,27 @@
867 +#ifndef _IPT_FWMON_H
868 +#define _IPT_FWMON_H
869 +
870 +/* Bitmask macros */
871 +#define MASK(x,y) (x & y)
872 +#define MASK_SET(x,y) x |= y
873 +#define MASK_UNSET(x,y) x &= ~y
874 +
875 +#define USE_MARK       0x00000001
876 +#define USE_DROP       0x00000002
877 +#define USE_SIZE       0x00000004
878 +
879 +struct ipt_nldata
880 +{      
881 +       unsigned int flags;
882 +       unsigned int mark;
883 +       unsigned int size;
884 +};
885 +
886 +/* Old header */
887 +struct netlink_t {
888 +       unsigned int len;
889 +       unsigned int mark;
890 +       char iface[IFNAMSIZ];
891 +};
892 +
893 +#endif /*_IPT_FWMON_H*/
894 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h
895 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h  1970-01-01 01:00:00.000000000 +0100
896 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_TTL.h      2004-04-30 09:10:15.000000000 +0200
897 @@ -0,0 +1,21 @@
898 +/* TTL modification module for IP tables
899 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
900 +
901 +#ifndef _IPT_TTL_H
902 +#define _IPT_TTL_H
903 +
904 +enum {
905 +       IPT_TTL_SET = 0,
906 +       IPT_TTL_INC,
907 +       IPT_TTL_DEC
908 +};
909 +
910 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
911 +
912 +struct ipt_TTL_info {
913 +       u_int8_t        mode;
914 +       u_int8_t        ttl;
915 +};
916 +
917 +
918 +#endif
919 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h
920 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_XOR.h  1970-01-01 01:00:00.000000000 +0100
921 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_XOR.h      2004-04-30 09:11:56.000000000 +0200
922 @@ -0,0 +1,9 @@
923 +#ifndef _IPT_XOR_H
924 +#define _IPT_XOR_H
925 +
926 +struct ipt_XOR_info {
927 +       char            key[30];
928 +       u_int8_t        block_size;
929 +};
930 +
931 +#endif /* _IPT_XOR_H */
932 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h
933 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_addrtype.h     1970-01-01 01:00:00.000000000 +0100
934 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_addrtype.h 2004-04-30 09:11:57.000000000 +0200
935 @@ -0,0 +1,11 @@
936 +#ifndef _IPT_ADDRTYPE_H
937 +#define _IPT_ADDRTYPE_H
938 +
939 +struct ipt_addrtype_info {
940 +       u_int16_t       source;         /* source-type mask */
941 +       u_int16_t       dest;           /* dest-type mask */
942 +       int             invert_source;
943 +       int             invert_dest;
944 +};
945 +
946 +#endif
947 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h
948 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h    1970-01-01 01:00:00.000000000 +0100
949 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h        2004-04-30 09:10:17.000000000 +0200
950 @@ -0,0 +1,12 @@
951 +#ifndef _IPT_CONNLIMIT_H
952 +#define _IPT_CONNLIMIT_H
953 +
954 +struct ipt_connlimit_data;
955 +
956 +struct ipt_connlimit_info {
957 +       int limit;
958 +       int inverse;
959 +       u_int32_t mask;
960 +       struct ipt_connlimit_data *data;
961 +};
962 +#endif /* _IPT_CONNLIMIT_H */
963 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h
964 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_connmark.h     1970-01-01 01:00:00.000000000 +0100
965 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_connmark.h 2004-04-30 09:11:35.000000000 +0200
966 @@ -0,0 +1,18 @@
967 +#ifndef _IPT_CONNMARK_H
968 +#define _IPT_CONNMARK_H
969 +
970 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
971 + * by Henrik Nordstrom <hno@marasystems.com>
972 + *
973 + * This program is free software; you can redistribute it and/or modify
974 + * it under the terms of the GNU General Public License as published by
975 + * the Free Software Foundation; either version 2 of the License, or
976 + * (at your option) any later version.
977 + */
978 +
979 +struct ipt_connmark_info {
980 +       unsigned long mark, mask;
981 +       u_int8_t invert;
982 +};
983 +
984 +#endif /*_IPT_CONNMARK_H*/
985 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h
986 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h     1970-01-01 01:00:00.000000000 +0100
987 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-04-30 09:10:21.000000000 +0200
988 @@ -0,0 +1,39 @@
989 +#ifndef _IPT_DSTLIMIT_H
990 +#define _IPT_DSTLIMIT_H
991 +
992 +/* timings are in milliseconds. */
993 +#define IPT_DSTLIMIT_SCALE 10000
994 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
995 +   seconds, or one every 59 hours. */
996 +
997 +/* details of this structure hidden by the implementation */
998 +struct ipt_dstlimit_htable;
999 +
1000 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
1001 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
1002 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
1003 +
1004 +struct dstlimit_cfg {
1005 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
1006 +       u_int32_t avg;    /* Average secs between packets * scale */
1007 +       u_int32_t burst;  /* Period multiplier for upper limit. */
1008 +
1009 +       /* user specified */
1010 +       u_int32_t size;         /* how many buckets */
1011 +       u_int32_t max;          /* max number of entries */
1012 +       u_int32_t gc_interval;  /* gc interval */
1013 +       u_int32_t expire;       /* when do entries expire? */
1014 +};
1015 +
1016 +struct ipt_dstlimit_info {
1017 +       char name [IFNAMSIZ];           /* name */
1018 +       struct dstlimit_cfg cfg;
1019 +       struct ipt_dstlimit_htable *hinfo;
1020 +
1021 +       /* Used internally by the kernel */
1022 +       union {
1023 +               void *ptr;
1024 +               struct ipt_dstlimit_info *master;
1025 +       } u;
1026 +};
1027 +#endif /*_IPT_DSTLIMIT_H*/
1028 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h
1029 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h        1970-01-01 01:00:00.000000000 +0100
1030 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h    2004-04-30 09:10:22.000000000 +0200
1031 @@ -0,0 +1,21 @@
1032 +#ifndef _IPT_FUZZY_H
1033 +#define _IPT_FUZZY_H
1034 +
1035 +#include <linux/param.h>
1036 +#include <linux/types.h>
1037 +
1038 +#define MAXFUZZYRATE 10000000
1039 +#define MINFUZZYRATE 3
1040 +
1041 +struct ipt_fuzzy_info {
1042 +       u_int32_t minimum_rate;
1043 +       u_int32_t maximum_rate;
1044 +       u_int32_t packets_total;
1045 +       u_int32_t bytes_total;
1046 +       u_int32_t previous_time;
1047 +       u_int32_t present_time;
1048 +       u_int32_t mean_rate;
1049 +       u_int8_t acceptance_rate;
1050 +};
1051 +
1052 +#endif /*_IPT_FUZZY_H*/
1053 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h
1054 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h  1970-01-01 01:00:00.000000000 +0100
1055 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h      2004-04-30 09:10:27.000000000 +0200
1056 @@ -0,0 +1,21 @@
1057 +#ifndef __ipt_ipv4options_h_included__
1058 +#define __ipt_ipv4options_h_included__
1059 +
1060 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
1061 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
1062 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
1063 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
1064 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
1065 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
1066 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
1067 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
1068 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
1069 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
1070 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
1071 +
1072 +struct ipt_ipv4options_info {
1073 +       u_int16_t options;
1074 +};
1075 +
1076 +
1077 +#endif /* __ipt_ipv4options_h_included__ */
1078 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h
1079 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h        1970-01-01 01:00:00.000000000 +0100
1080 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_mport.h    2004-04-30 09:10:30.000000000 +0200
1081 @@ -0,0 +1,24 @@
1082 +#ifndef _IPT_MPORT_H
1083 +#define _IPT_MPORT_H
1084 +#include <linux/netfilter_ipv4/ip_tables.h>
1085 +
1086 +#define IPT_MPORT_SOURCE (1<<0)
1087 +#define IPT_MPORT_DESTINATION (1<<1)
1088 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1089 +
1090 +#define IPT_MULTI_PORTS        15
1091 +
1092 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1093 +/* every entry in ports[] except for the last one has one bit in pflags
1094 + * associated with it. If this bit is set, the port is the first port of
1095 + * a portrange, with the next entry being the last.
1096 + * End of list is marked with pflags bit set and port=65535.
1097 + * If 14 ports are used (last one does not have a pflag), the last port
1098 + * is repeated to fill the last entry in ports[] */
1099 +struct ipt_mport
1100 +{
1101 +       u_int8_t flags:2;                       /* Type of comparison */
1102 +       u_int16_t pflags:14;                    /* Port flags */
1103 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
1104 +};
1105 +#endif /*_IPT_MPORT_H*/
1106 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h
1107 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h  1970-01-01 01:00:00.000000000 +0100
1108 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_nth.h      2004-04-30 09:10:36.000000000 +0200
1109 @@ -0,0 +1,19 @@
1110 +#ifndef _IPT_NTH_H
1111 +#define _IPT_NTH_H
1112 +
1113 +#include <linux/param.h>
1114 +#include <linux/types.h>
1115 +
1116 +#ifndef IPT_NTH_NUM_COUNTERS
1117 +#define IPT_NTH_NUM_COUNTERS 16
1118 +#endif
1119 +
1120 +struct ipt_nth_info {
1121 +       u_int8_t every;
1122 +       u_int8_t not;
1123 +       u_int8_t startat;
1124 +       u_int8_t counter;
1125 +       u_int8_t packet;
1126 +};
1127 +
1128 +#endif /*_IPT_NTH_H*/
1129 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h
1130 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h  1970-01-01 01:00:00.000000000 +0100
1131 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_osf.h      2004-04-30 09:10:38.000000000 +0200
1132 @@ -0,0 +1,148 @@
1133 +/*
1134 + * ipt_osf.h
1135 + *
1136 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1137 + *
1138 + *
1139 + * This program is free software; you can redistribute it and/or modify
1140 + * it under the terms of the GNU General Public License as published by
1141 + * the Free Software Foundation; either version 2 of the License, or
1142 + * (at your option) any later version.
1143 + *
1144 + * This program is distributed in the hope that it will be useful,
1145 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1146 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1147 + * GNU General Public License for more details.
1148 + *
1149 + * You should have received a copy of the GNU General Public License
1150 + * along with this program; if not, write to the Free Software
1151 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1152 + */
1153 +
1154 +#ifndef _IPT_OSF_H
1155 +#define _IPT_OSF_H
1156 +
1157 +#define MAXGENRELEN            32
1158 +#define MAXDETLEN              64
1159 +
1160 +#define IPT_OSF_GENRE          1
1161 +#define        IPT_OSF_SMART           2
1162 +#define IPT_OSF_LOG            4
1163 +#define IPT_OSF_NETLINK                8
1164 +
1165 +#define IPT_OSF_LOGLEVEL_ALL   0
1166 +#define IPT_OSF_LOGLEVEL_FIRST 1
1167 +
1168 +#include <linux/list.h>
1169 +
1170 +#ifndef __KERNEL__
1171 +#include <netinet/ip.h>
1172 +#include <netinet/tcp.h>
1173 +
1174 +struct list_head
1175 +{
1176 +       struct list_head *prev, *next;
1177 +};
1178 +#endif
1179 +
1180 +struct ipt_osf_info
1181 +{
1182 +       char                    genre[MAXGENRELEN];
1183 +       int                     len;
1184 +       unsigned long           flags;
1185 +       int                     loglevel;
1186 +       int                     invert; /* UNSUPPORTED */
1187 +};
1188 +
1189 +struct osf_wc
1190 +{
1191 +       char                    wc;
1192 +       unsigned long           val;
1193 +};
1194 +
1195 +/* This struct represents IANA options
1196 + * http://www.iana.org/assignments/tcp-parameters
1197 + */
1198 +struct osf_opt
1199 +{
1200 +       unsigned char           kind;
1201 +       unsigned char           length;
1202 +       struct osf_wc           wc;
1203 +};
1204 +
1205 +struct osf_finger
1206 +{
1207 +       struct list_head        flist;
1208 +       struct osf_wc           wss;
1209 +       unsigned char           ttl;
1210 +       unsigned char           df;
1211 +       unsigned long           ss;
1212 +       unsigned char           genre[MAXGENRELEN];
1213 +       unsigned char           version[MAXGENRELEN], subtype[MAXGENRELEN];
1214 +       
1215 +       /* Not needed, but for consistency with original table from Michal Zalewski */
1216 +       unsigned char           details[MAXDETLEN]; 
1217 +
1218 +       int                     opt_num;
1219 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1220 +
1221 +};
1222 +
1223 +struct ipt_osf_nlmsg
1224 +{
1225 +       struct osf_finger       f;
1226 +       struct iphdr            ip;
1227 +       struct tcphdr           tcp;
1228 +};
1229 +
1230 +#ifdef __KERNEL__
1231 +
1232 +/* Defines for IANA option kinds */
1233 +
1234 +#define OSFOPT_EOL             0       /* End of options */
1235 +#define OSFOPT_NOP             1       /* NOP */
1236 +#define OSFOPT_MSS             2       /* Maximum segment size */
1237 +#define OSFOPT_WSO             3       /* Window scale option */
1238 +#define OSFOPT_SACKP           4       /* SACK permitted */
1239 +#define OSFOPT_SACK            5       /* SACK */
1240 +#define OSFOPT_ECHO            6       
1241 +#define OSFOPT_ECHOREPLY       7
1242 +#define OSFOPT_TS              8       /* Timestamp option */
1243 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
1244 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
1245 +/* Others are not used in current OSF */
1246 +
1247 +static struct osf_opt IANA_opts[] = 
1248 +{
1249 +       {0, 1,},
1250 +       {1, 1,},
1251 +       {2, 4,},
1252 +       {3, 3,},
1253 +       {4, 2,},
1254 +       {5, 1 ,}, /* SACK length is not defined */
1255 +       {6, 6,},
1256 +       {7, 6,},
1257 +       {8, 10,},
1258 +       {9, 2,},
1259 +       {10, 3,},
1260 +       {11, 1,}, /* CC: Suppose 1 */
1261 +       {12, 1,}, /* the same */
1262 +       {13, 1,}, /* and here too */
1263 +       {14, 3,},
1264 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1265 +       {16, 1,},
1266 +       {17, 1,},
1267 +       {18, 3,},
1268 +       {19, 18,},
1269 +       {20, 1,},
1270 +       {21, 1,},
1271 +       {22, 1,},
1272 +       {23, 1,},
1273 +       {24, 1,},
1274 +       {25, 1,},
1275 +       {26, 1,},
1276 +};
1277 +
1278 +#endif /* __KERNEL__ */
1279 +
1280 +#endif /* _IPT_OSF_H */
1281 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h
1282 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_policy.h       1970-01-01 01:00:00.000000000 +0100
1283 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_policy.h   2004-04-30 09:13:22.000000000 +0200
1284 @@ -0,0 +1,52 @@
1285 +#ifndef _IPT_POLICY_H
1286 +#define _IPT_POLICY_H
1287 +
1288 +#define POLICY_MAX_ELEM        4
1289 +
1290 +enum ipt_policy_flags
1291 +{
1292 +       POLICY_MATCH_IN         = 0x1,
1293 +       POLICY_MATCH_OUT        = 0x2,
1294 +       POLICY_MATCH_NONE       = 0x4,
1295 +       POLICY_MATCH_STRICT     = 0x8,
1296 +};
1297 +
1298 +enum ipt_policy_modes
1299 +{
1300 +       POLICY_MODE_TRANSPORT,
1301 +       POLICY_MODE_TUNNEL
1302 +};
1303 +
1304 +struct ipt_policy_spec
1305 +{
1306 +       u_int8_t        saddr:1,
1307 +                       daddr:1,
1308 +                       proto:1,
1309 +                       mode:1,
1310 +                       spi:1,
1311 +                       reqid:1;
1312 +};
1313 +
1314 +struct ipt_policy_elem
1315 +{
1316 +       u_int32_t       saddr;
1317 +       u_int32_t       smask;
1318 +       u_int32_t       daddr;
1319 +       u_int32_t       dmask;
1320 +       u_int32_t       spi;
1321 +       u_int32_t       reqid;
1322 +       u_int8_t        proto;
1323 +       u_int8_t        mode;
1324 +
1325 +       struct ipt_policy_spec  match;
1326 +       struct ipt_policy_spec  invert;
1327 +};
1328 +
1329 +struct ipt_policy_info
1330 +{
1331 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
1332 +       u_int16_t flags;
1333 +       u_int16_t len;
1334 +};
1335 +
1336 +#endif /* _IPT_POLICY_H */
1337 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h
1338 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1339 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_pool.h     2004-04-30 09:10:40.000000000 +0200
1340 @@ -0,0 +1,25 @@
1341 +#ifndef _IPT_POOL_H
1342 +#define _IPT_POOL_H
1343 +
1344 +#include <linux/netfilter_ipv4/ip_pool.h>
1345 +
1346 +#define IPT_POOL_INV_SRC       0x00000001
1347 +#define IPT_POOL_INV_DST       0x00000002
1348 +#define IPT_POOL_DEL_SRC       0x00000004
1349 +#define IPT_POOL_DEL_DST       0x00000008
1350 +#define IPT_POOL_INV_MOD_SRC   0x00000010
1351 +#define IPT_POOL_INV_MOD_DST   0x00000020
1352 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
1353 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
1354 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
1355 +#define IPT_POOL_MOD_DST_DROP  0x00000200
1356 +
1357 +/* match info */
1358 +struct ipt_pool_info
1359 +{
1360 +       ip_pool_t src;
1361 +       ip_pool_t dst;
1362 +       unsigned flags;
1363 +};
1364 +
1365 +#endif /*_IPT_POOL_H*/
1366 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h
1367 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h  1970-01-01 01:00:00.000000000 +0100
1368 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_psd.h      2004-04-30 09:10:44.000000000 +0200
1369 @@ -0,0 +1,40 @@
1370 +#ifndef _IPT_PSD_H
1371 +#define _IPT_PSD_H
1372 +
1373 +#include <linux/param.h>
1374 +#include <linux/types.h>
1375 +
1376 +/*
1377 + * High port numbers have a lower weight to reduce the frequency of false
1378 + * positives, such as from passive mode FTP transfers.
1379 + */
1380 +#define PORT_WEIGHT_PRIV               3
1381 +#define PORT_WEIGHT_HIGH               1
1382 +
1383 +/*
1384 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1385 + * from the same source, with no longer than DELAY ticks between ports.
1386 + */
1387 +#define SCAN_MIN_COUNT                 7
1388 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1389 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
1390 +#define SCAN_DELAY_THRESHOLD           (HZ * 3)
1391 +
1392 +/*
1393 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1394 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1395 + * HASH_MAX source addresses per the same hash value.
1396 + */
1397 +#define LIST_SIZE                      0x100
1398 +#define HASH_LOG                       9
1399 +#define HASH_SIZE                      (1 << HASH_LOG)
1400 +#define HASH_MAX                       0x10
1401 +
1402 +struct ipt_psd_info {
1403 +       unsigned int weight_threshold;
1404 +       unsigned int delay_threshold;
1405 +       unsigned short lo_ports_weight;
1406 +       unsigned short hi_ports_weight;
1407 +};
1408 +
1409 +#endif /*_IPT_PSD_H*/
1410 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h
1411 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h        1970-01-01 01:00:00.000000000 +0100
1412 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_quota.h    2004-04-30 09:10:45.000000000 +0200
1413 @@ -0,0 +1,11 @@
1414 +#ifndef _IPT_QUOTA_H
1415 +#define _IPT_QUOTA_H
1416 +
1417 +/* print debug info in both kernel/netfilter module & iptable library */
1418 +//#define DEBUG_IPT_QUOTA
1419 +
1420 +struct ipt_quota_info {
1421 +        u_int64_t quota;
1422 +};
1423 +
1424 +#endif /*_IPT_QUOTA_H*/
1425 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h
1426 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_random.h       1970-01-01 01:00:00.000000000 +0100
1427 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_random.h   2004-04-30 09:10:46.000000000 +0200
1428 @@ -0,0 +1,11 @@
1429 +#ifndef _IPT_RAND_H
1430 +#define _IPT_RAND_H
1431 +
1432 +#include <linux/param.h>
1433 +#include <linux/types.h>
1434 +
1435 +struct ipt_rand_info {
1436 +       u_int8_t average;
1437 +};
1438 +
1439 +#endif /*_IPT_RAND_H*/
1440 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h
1441 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h        1970-01-01 01:00:00.000000000 +0100
1442 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_realm.h    2004-04-30 09:10:50.000000000 +0200
1443 @@ -0,0 +1,9 @@
1444 +#ifndef _IPT_REALM_H
1445 +#define _IPT_REALM_H
1446 +
1447 +struct ipt_realm_info {
1448 +       u_int32_t id;
1449 +       u_int32_t mask;
1450 +       u_int8_t invert;
1451 +};
1452 +#endif /*_IPT_REALM_H*/
1453 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h
1454 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_sctp.h 1970-01-01 01:00:00.000000000 +0100
1455 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_sctp.h     2004-04-30 09:10:52.000000000 +0200
1456 @@ -0,0 +1,107 @@
1457 +#ifndef _IPT_SCTP_H_
1458 +#define _IPT_SCTP_H_
1459 +
1460 +#define IPT_SCTP_SRC_PORTS             0x01
1461 +#define IPT_SCTP_DEST_PORTS            0x02
1462 +#define IPT_SCTP_CHUNK_TYPES           0x04
1463 +
1464 +#define IPT_SCTP_VALID_FLAGS           0x07
1465 +
1466 +#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
1467 +
1468 +
1469 +struct ipt_sctp_flag_info {
1470 +       u_int8_t chunktype;
1471 +       u_int8_t flag;
1472 +       u_int8_t flag_mask;
1473 +};
1474 +
1475 +#define IPT_NUM_SCTP_FLAGS     4
1476 +
1477 +struct ipt_sctp_info {
1478 +       u_int16_t dpts[2];  /* Min, Max */
1479 +       u_int16_t spts[2];  /* Min, Max */
1480 +
1481 +       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
1482 +
1483 +#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
1484 +#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
1485 +#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
1486 +
1487 +       u_int32_t chunk_match_type;
1488 +       struct ipt_sctp_flag_info flag_info[IPT_NUM_SCTP_FLAGS];
1489 +       int flag_count;
1490 +
1491 +       u_int32_t flags;
1492 +       u_int32_t invflags;
1493 +};
1494 +
1495 +#define bytes(type) (sizeof(type) * 8)
1496 +
1497 +#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
1498 +       do {                                            \
1499 +               chunkmap[type / bytes(u_int32_t)] |=    \
1500 +                       1 << (type % bytes(u_int32_t)); \
1501 +       } while (0)
1502 +
1503 +#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
1504 +       do {                                                    \
1505 +               chunkmap[type / bytes(u_int32_t)] &=            \
1506 +                       ~(1 << (type % bytes(u_int32_t)));      \
1507 +       } while (0)
1508 +
1509 +#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
1510 +({                                                             \
1511 +       (chunkmap[type / bytes (u_int32_t)] &                   \
1512 +               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
1513 +})
1514 +
1515 +#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
1516 +       do {                                                    \
1517 +               int i;                                          \
1518 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1519 +                       chunkmap[i] = 0;                        \
1520 +       } while (0)
1521 +
1522 +#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
1523 +       do {                                                    \
1524 +               int i;                                          \
1525 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1526 +                       chunkmap[i] = ~0;                       \
1527 +       } while (0)
1528 +
1529 +#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
1530 +       do {                                                    \
1531 +               int i;                                          \
1532 +               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
1533 +                       destmap[i] = srcmap[i];                 \
1534 +       } while (0)
1535 +
1536 +#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
1537 +({                                                     \
1538 +       int i;                                          \
1539 +       int flag = 1;                                   \
1540 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1541 +               if (chunkmap[i]) {                      \
1542 +                       flag = 0;                       \
1543 +                       break;                          \
1544 +               }                                       \
1545 +       }                                               \
1546 +        flag;                                          \
1547 +})
1548 +
1549 +#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
1550 +({                                                     \
1551 +       int i;                                          \
1552 +       int flag = 1;                                   \
1553 +       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
1554 +               if (chunkmap[i] != ~0) {                \
1555 +                       flag = 0;                       \
1556 +                               break;                  \
1557 +               }                                       \
1558 +       }                                               \
1559 +        flag;                                          \
1560 +})
1561 +
1562 +#endif /* _IPT_SCTP_H_ */
1563 +
1564 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h
1565 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_string.h       1970-01-01 01:00:00.000000000 +0100
1566 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_string.h   2004-04-30 09:14:35.000000000 +0200
1567 @@ -0,0 +1,21 @@
1568 +#ifndef _IPT_STRING_H
1569 +#define _IPT_STRING_H
1570 +
1571 +/* *** PERFORMANCE TWEAK ***
1572 + * Packet size and search string threshold,
1573 + * above which sublinear searches is used. */
1574 +#define IPT_STRING_HAYSTACK_THRESH     100
1575 +#define IPT_STRING_NEEDLE_THRESH       20
1576 +
1577 +#define BM_MAX_NLEN 256
1578 +#define BM_MAX_HLEN 1024
1579 +
1580 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
1581 +
1582 +struct ipt_string_info {
1583 +    char string[BM_MAX_NLEN];
1584 +    u_int16_t invert;
1585 +    u_int16_t len;
1586 +};
1587 +
1588 +#endif /* _IPT_STRING_H */
1589 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h
1590 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1591 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_time.h     2004-04-30 09:10:54.000000000 +0200
1592 @@ -0,0 +1,13 @@
1593 +#ifndef __ipt_time_h_included__
1594 +#define __ipt_time_h_included__
1595 +
1596 +
1597 +struct ipt_time_info {
1598 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
1599 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
1600 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
1601 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
1602 +};
1603 +
1604 +
1605 +#endif /* __ipt_time_h_included__ */
1606 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h
1607 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h  1970-01-01 01:00:00.000000000 +0100
1608 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4/ipt_u32.h      2004-04-30 09:10:55.000000000 +0200
1609 @@ -0,0 +1,40 @@
1610 +#ifndef _IPT_U32_H
1611 +#define _IPT_U32_H
1612 +#include <linux/netfilter_ipv4/ip_tables.h>
1613 +
1614 +enum ipt_u32_ops
1615 +{
1616 +       IPT_U32_AND,
1617 +       IPT_U32_LEFTSH,
1618 +       IPT_U32_RIGHTSH,
1619 +       IPT_U32_AT
1620 +};
1621 +
1622 +struct ipt_u32_location_element
1623 +{
1624 +       u_int32_t number;
1625 +       u_int8_t nextop;
1626 +};
1627 +struct ipt_u32_value_element
1628 +{
1629 +       u_int32_t min;
1630 +       u_int32_t max;
1631 +};
1632 +/* *** any way to allow for an arbitrary number of elements?
1633 +   for now I settle for a limit of 10 of each */
1634 +#define U32MAXSIZE 10
1635 +struct ipt_u32_test
1636 +{
1637 +       u_int8_t nnums;
1638 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
1639 +       u_int8_t nvalues;
1640 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
1641 +};
1642 +
1643 +struct ipt_u32
1644 +{
1645 +       u_int8_t ntests;
1646 +       struct ipt_u32_test tests[U32MAXSIZE+1];
1647 +};
1648 +
1649 +#endif /*_IPT_U32_H*/
1650 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h linux-2.6.6-rc3/include/linux/netfilter_ipv4.h
1651 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv4.h  2004-04-28 03:36:31.000000000 +0200
1652 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv4.h      2004-04-30 09:12:40.000000000 +0200
1653 @@ -7,6 +7,8 @@
1654  
1655  #include <linux/config.h>
1656  #include <linux/netfilter.h>
1657 +#include <linux/netdevice.h>
1658 +#include <net/protocol.h>
1659  
1660  /* IP Cache bits. */
1661  /* Src IP address. */
1662 @@ -85,6 +87,58 @@
1663     Returns true or false. */
1664  extern int skb_ip_make_writable(struct sk_buff **pskb,
1665                                 unsigned int writable_len);
1666 +
1667 +#if defined(CONFIG_XFRM) && defined(CONFIG_NETFILTER)
1668 +#include <net/route.h>
1669 +#include <net/xfrm.h>
1670 +
1671 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1672 +{
1673 +       return !skb->sp || skb->sp->decap_done;
1674 +}
1675 +
1676 +static inline int
1677 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1678 +{
1679 +       return skb->sp && !skb->sp->decap_done
1680 +              && (!ipprot || !ipprot->xfrm_prot);
1681 +}
1682 +
1683 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1684 +{
1685 +       return skb->sp && !skb->sp->decap_done
1686 +              && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL);
1687 +}
1688 +
1689 +extern int nf_rcv_postxfrm_local(struct sk_buff *skb);
1690 +extern int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb);
1691 +#else /* CONFIG_XFRM */
1692 +static inline int nf_hook_input_cond(struct sk_buff *skb)
1693 +{
1694 +       return 1;
1695 +}
1696 +
1697 +static inline int
1698 +nf_xfrm_local_done(struct sk_buff *skb, struct inet_protocol *ipprot)
1699 +{
1700 +       return 0;
1701 +}
1702 +
1703 +static inline int nf_xfrm_nonlocal_done(struct sk_buff *skb)
1704 +{
1705 +       return 0;
1706 +}
1707 +
1708 +static inline int nf_rcv_postxfrm_local(struct sk_buff *skb)
1709 +{
1710 +       return 0;
1711 +}
1712 +
1713 +static inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
1714 +{
1715 +       return 0; 
1716 +}
1717 +#endif /* CONFIG_XFRM */
1718  #endif /*__KERNEL__*/
1719  
1720  #endif /*__LINUX_IP_NETFILTER_H*/
1721 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h
1722 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6_tables.h       2004-04-28 03:36:37.000000000 +0200
1723 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6_tables.h   2004-04-30 09:11:53.000000000 +0200
1724 @@ -140,6 +140,12 @@
1725         /* Back pointer */
1726         unsigned int comefrom;
1727  
1728 +       /* Name of the chain */
1729 +       char *chainname;
1730 +       
1731 +       /* Rule number in the chain. */
1732 +       u_int32_t rulenum;
1733 +
1734         /* Packet and byte counters. */
1735         struct ip6t_counters counters;
1736  
1737 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h
1738 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h  1970-01-01 01:00:00.000000000 +0100
1739 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_HL.h      2004-04-30 09:10:04.000000000 +0200
1740 @@ -0,0 +1,22 @@
1741 +/* Hop Limit modification module for ip6tables
1742 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1743 + * Based on HW's TTL module */
1744 +
1745 +#ifndef _IP6T_HL_H
1746 +#define _IP6T_HL_H
1747 +
1748 +enum {
1749 +       IP6T_HL_SET = 0,
1750 +       IP6T_HL_INC,
1751 +       IP6T_HL_DEC
1752 +};
1753 +
1754 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
1755 +
1756 +struct ip6t_HL_info {
1757 +       u_int8_t        mode;
1758 +       u_int8_t        hop_limit;
1759 +};
1760 +
1761 +
1762 +#endif
1763 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h
1764 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-04-28 03:34:59.000000000 +0200
1765 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-04-30 09:10:13.000000000 +0200
1766 @@ -2,15 +2,17 @@
1767  #define _IP6T_REJECT_H
1768  
1769  enum ip6t_reject_with {
1770 -       IP6T_ICMP_NET_UNREACHABLE,
1771 -       IP6T_ICMP_HOST_UNREACHABLE,
1772 -       IP6T_ICMP_PROT_UNREACHABLE,
1773 -       IP6T_ICMP_PORT_UNREACHABLE,
1774 -       IP6T_ICMP_ECHOREPLY
1775 +       IP6T_ICMP6_NO_ROUTE,
1776 +       IP6T_ICMP6_ADM_PROHIBITED,
1777 +       IP6T_ICMP6_NOT_NEIGHBOUR,
1778 +       IP6T_ICMP6_ADDR_UNREACH,
1779 +       IP6T_ICMP6_PORT_UNREACH,
1780 +       IP6T_ICMP6_ECHOREPLY,
1781 +       IP6T_TCP_RESET
1782  };
1783  
1784  struct ip6t_reject_info {
1785         enum ip6t_reject_with with;      /* reject type */
1786  };
1787  
1788 -#endif /*_IPT_REJECT_H*/
1789 +#endif /*_IP6T_REJECT_H*/
1790 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1791 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h       1970-01-01 01:00:00.000000000 +0100
1792 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h   2004-04-30 09:10:22.000000000 +0200
1793 @@ -0,0 +1,21 @@
1794 +#ifndef _IP6T_FUZZY_H
1795 +#define _IP6T_FUZZY_H
1796 +
1797 +#include <linux/param.h>
1798 +#include <linux/types.h>
1799 +
1800 +#define MAXFUZZYRATE 10000000
1801 +#define MINFUZZYRATE 3
1802 +
1803 +struct ip6t_fuzzy_info {
1804 +       u_int32_t minimum_rate;
1805 +       u_int32_t maximum_rate;
1806 +       u_int32_t packets_total;
1807 +       u_int32_t bytes_total;
1808 +       u_int32_t previous_time;
1809 +       u_int32_t present_time;
1810 +       u_int32_t mean_rate;
1811 +       u_int8_t acceptance_rate;
1812 +};
1813 +
1814 +#endif /*_IP6T_FUZZY_H*/
1815 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h
1816 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1817 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_nth.h     2004-04-30 09:10:36.000000000 +0200
1818 @@ -0,0 +1,19 @@
1819 +#ifndef _IP6T_NTH_H
1820 +#define _IP6T_NTH_H
1821 +
1822 +#include <linux/param.h>
1823 +#include <linux/types.h>
1824 +
1825 +#ifndef IP6T_NTH_NUM_COUNTERS
1826 +#define IP6T_NTH_NUM_COUNTERS 16
1827 +#endif
1828 +
1829 +struct ip6t_nth_info {
1830 +       u_int8_t every;
1831 +       u_int8_t not;
1832 +       u_int8_t startat;
1833 +       u_int8_t counter;
1834 +       u_int8_t packet;
1835 +};
1836 +
1837 +#endif /*_IP6T_NTH_H*/
1838 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h
1839 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_owner.h       2004-04-28 03:36:03.000000000 +0200
1840 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_owner.h   2004-04-30 09:13:19.000000000 +0200
1841 @@ -6,12 +6,14 @@
1842  #define IP6T_OWNER_GID 0x02
1843  #define IP6T_OWNER_PID 0x04
1844  #define IP6T_OWNER_SID 0x08
1845 +#define IP6T_OWNER_COMM 0x10
1846  
1847  struct ip6t_owner_info {
1848      uid_t uid;
1849      gid_t gid;
1850      pid_t pid;
1851      pid_t sid;
1852 +    char comm[16];
1853      u_int8_t match, invert;    /* flags */
1854  };
1855  
1856 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h
1857 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_policy.h      1970-01-01 01:00:00.000000000 +0100
1858 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_policy.h  2004-04-30 09:13:22.000000000 +0200
1859 @@ -0,0 +1,52 @@
1860 +#ifndef _IP6T_POLICY_H\r
1861 +#define _IP6T_POLICY_H\r
1862 +\r
1863 +#define POLICY_MAX_ELEM        4\r
1864 +\r
1865 +enum ip6t_policy_flags\r
1866 +{\r
1867 +       POLICY_MATCH_IN         = 0x1,\r
1868 +       POLICY_MATCH_OUT        = 0x2,\r
1869 +       POLICY_MATCH_NONE       = 0x4,\r
1870 +       POLICY_MATCH_STRICT     = 0x8,\r
1871 +};\r
1872 +\r
1873 +enum ip6t_policy_modes\r
1874 +{\r
1875 +       POLICY_MODE_TRANSPORT,\r
1876 +       POLICY_MODE_TUNNEL\r
1877 +};\r
1878 +\r
1879 +struct ip6t_policy_spec\r
1880 +{\r
1881 +       u_int8_t        saddr:1,\r
1882 +                       daddr:1,\r
1883 +                       proto:1,\r
1884 +                       mode:1,\r
1885 +                       spi:1,\r
1886 +                       reqid:1;\r
1887 +};\r
1888 +\r
1889 +struct ip6t_policy_elem\r
1890 +{\r
1891 +       struct in6_addr saddr;\r
1892 +       struct in6_addr smask;\r
1893 +       struct in6_addr daddr;\r
1894 +       struct in6_addr dmask;\r
1895 +       u_int32_t       spi;\r
1896 +       u_int32_t       reqid;\r
1897 +       u_int8_t        proto;\r
1898 +       u_int8_t        mode;\r
1899 +\r
1900 +       struct ip6t_policy_spec match;\r
1901 +       struct ip6t_policy_spec invert;\r
1902 +};\r
1903 +\r
1904 +struct ip6t_policy_info\r
1905 +{\r
1906 +       struct ip6t_policy_elem pol[POLICY_MAX_ELEM];\r
1907 +       u_int16_t flags;\r
1908 +       u_int16_t len;\r
1909 +};\r
1910 +\r
1911 +#endif /* _IP6T_POLICY_H */\r
1912 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h
1913 --- linux-2.6.6-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h      1970-01-01 01:00:00.000000000 +0100
1914 +++ linux-2.6.6-rc3/include/linux/netfilter_ipv6/ip6t_random.h  2004-04-30 09:10:46.000000000 +0200
1915 @@ -0,0 +1,11 @@
1916 +#ifndef _IP6T_RAND_H
1917 +#define _IP6T_RAND_H
1918 +
1919 +#include <linux/param.h>
1920 +#include <linux/types.h>
1921 +
1922 +struct ip6t_rand_info {
1923 +       u_int8_t average;
1924 +};
1925 +
1926 +#endif /*_IP6T_RAND_H*/
1927 diff -Nur linux-2.6.6-rc3.org/include/linux/netfilter_mime.h linux-2.6.6-rc3/include/linux/netfilter_mime.h
1928 --- linux-2.6.6-rc3.org/include/linux/netfilter_mime.h  1970-01-01 01:00:00.000000000 +0100
1929 +++ linux-2.6.6-rc3/include/linux/netfilter_mime.h      2004-04-30 09:14:05.000000000 +0200
1930 @@ -0,0 +1,89 @@
1931 +/*
1932 + * MIME functions for netfilter modules.  This file provides implementations
1933 + * for basic MIME parsing.  MIME headers are used in many protocols, such as
1934 + * HTTP, RTSP, SIP, etc.
1935 + *
1936 + * gcc will warn for defined but unused functions, so we only include the
1937 + * functions requested.  The following macros are used:
1938 + *   NF_NEED_MIME_NEXTLINE      nf_mime_nextline()
1939 + */
1940 +#ifndef _NETFILTER_MIME_H
1941 +#define _NETFILTER_MIME_H
1942 +
1943 +/* Only include these functions for kernel code. */
1944 +#ifdef __KERNEL__
1945 +
1946 +#include <linux/ctype.h>
1947 +
1948 +/*
1949 + * Given a buffer and length, advance to the next line and mark the current
1950 + * line.  If the current line is empty, *plinelen will be set to zero.  If
1951 + * not, it will be set to the actual line length (including CRLF).
1952 + *
1953 + * 'line' in this context means logical line (includes LWS continuations).
1954 + * Returns 1 on success, 0 on failure.
1955 + */
1956 +#ifdef NF_NEED_MIME_NEXTLINE
1957 +static int
1958 +nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen)
1959 +{
1960 +    uint    off = *poff;
1961 +    uint    physlen = 0;
1962 +    int     is_first_line = 1;
1963 +
1964 +    if (off >= len)
1965 +    {
1966 +        return 0;
1967 +    }
1968 +
1969 +    do
1970 +    {
1971 +        while (p[off] != '\n')
1972 +        {
1973 +            if (len-off <= 1)
1974 +            {
1975 +                return 0;
1976 +            }
1977 +
1978 +            physlen++;
1979 +            off++;
1980 +        }
1981 +
1982 +        /* if we saw a crlf, physlen needs adjusted */
1983 +        if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r')
1984 +        {
1985 +            physlen--;
1986 +        }
1987 +
1988 +        /* advance past the newline */
1989 +        off++;
1990 +
1991 +        /* check for an empty line */
1992 +        if (physlen == 0)
1993 +        {
1994 +            break;
1995 +        }
1996 +
1997 +        /* check for colon on the first physical line */
1998 +        if (is_first_line)
1999 +        {
2000 +            is_first_line = 0;
2001 +            if (memchr(p+(*poff), ':', physlen) == NULL)
2002 +            {
2003 +                return 0;
2004 +            }
2005 +        }
2006 +    }
2007 +    while (p[off] == ' ' || p[off] == '\t');
2008 +
2009 +    *plineoff = *poff;
2010 +    *plinelen = (physlen == 0) ? 0 : (off - *poff);
2011 +    *poff = off;
2012 +
2013 +    return 1;
2014 +}
2015 +#endif /* NF_NEED_MIME_NEXTLINE */
2016 +
2017 +#endif /* __KERNEL__ */
2018 +
2019 +#endif /* _NETFILTER_MIME_H */
2020 diff -Nur linux-2.6.6-rc3.org/include/linux/skbuff.h linux-2.6.6-rc3/include/linux/skbuff.h
2021 --- linux-2.6.6-rc3.org/include/linux/skbuff.h  2004-04-30 08:34:16.000000000 +0200
2022 +++ linux-2.6.6-rc3/include/linux/skbuff.h      2004-04-30 09:09:38.000000000 +0200
2023 @@ -1049,6 +1049,14 @@
2024         if (nfct)
2025                 atomic_inc(&nfct->master->use);
2026  }
2027 +static inline void nf_reset(struct sk_buff *skb)
2028 +{
2029 +       nf_conntrack_put(skb->nfct);
2030 +       skb->nfct = NULL;
2031 +#ifdef CONFIG_NETFILTER_DEBUG
2032 +       skb->nf_debug = 0;
2033 +#endif
2034 +}
2035  
2036  #ifdef CONFIG_BRIDGE_NETFILTER
2037  static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
2038 @@ -1061,9 +1069,10 @@
2039         if (nf_bridge)
2040                 atomic_inc(&nf_bridge->use);
2041  }
2042 -#endif
2043 -
2044 -#endif
2045 +#endif /* CONFIG_BRIDGE_NETFILTER */
2046 +#else /* CONFIG_NETFILTER */
2047 +static inline void nf_reset(struct sk_buff *skb) {}
2048 +#endif /* CONFIG_NETFILTER */
2049  
2050  #endif /* __KERNEL__ */
2051  #endif /* _LINUX_SKBUFF_H */
2052 diff -Nur linux-2.6.6-rc3.org/include/net/ip.h linux-2.6.6-rc3/include/net/ip.h
2053 --- linux-2.6.6-rc3.org/include/net/ip.h        2004-04-28 03:36:16.000000000 +0200
2054 +++ linux-2.6.6-rc3/include/net/ip.h    2004-04-30 09:12:39.000000000 +0200
2055 @@ -30,6 +30,8 @@
2056  #include <linux/netdevice.h>
2057  #include <linux/inetdevice.h>
2058  #include <linux/in_route.h>
2059 +#include <linux/netfilter.h>
2060 +#include <linux/netfilter_ipv4.h>
2061  #include <net/route.h>
2062  #include <net/arp.h>
2063  
2064 @@ -48,6 +50,7 @@
2065  #define IPSKB_TRANSLATED       2
2066  #define IPSKB_FORWARDED                4
2067  #define IPSKB_XFRM_TUNNEL_SIZE 8
2068 +#define IPSKB_XFRM_TRANSFORMED 16
2069  };
2070  
2071  struct ipcm_cookie
2072 @@ -212,6 +215,12 @@
2073                 __ip_select_ident(iph, dst, more);
2074  }
2075  
2076 +extern inline int ip_dst_output(struct sk_buff *skb)
2077 +{
2078 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2079 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2080 +}
2081 +
2082  /*
2083   *     Map a multicast IP onto multicast MAC for type ethernet.
2084   */
2085 diff -Nur linux-2.6.6-rc3.org/include/net/protocol.h linux-2.6.6-rc3/include/net/protocol.h
2086 --- linux-2.6.6-rc3.org/include/net/protocol.h  2004-04-28 03:35:44.000000000 +0200
2087 +++ linux-2.6.6-rc3/include/net/protocol.h      2004-04-30 09:12:40.000000000 +0200
2088 @@ -39,6 +39,7 @@
2089         int                     (*handler)(struct sk_buff *skb);
2090         void                    (*err_handler)(struct sk_buff *skb, u32 info);
2091         int                     no_policy;
2092 +       int                     xfrm_prot;
2093  };
2094  
2095  #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
2096 diff -Nur linux-2.6.6-rc3.org/include/net/tcp.h linux-2.6.6-rc3/include/net/tcp.h
2097 --- linux-2.6.6-rc3.org/include/net/tcp.h       2004-04-30 08:34:16.000000000 +0200
2098 +++ linux-2.6.6-rc3/include/net/tcp.h   2004-04-30 09:13:14.000000000 +0200
2099 @@ -162,6 +162,7 @@
2100  extern void tcp_bucket_unlock(struct sock *sk);
2101  extern int tcp_port_rover;
2102  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
2103 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
2104  
2105  /* These are AF independent. */
2106  static __inline__ int tcp_bhashfn(__u16 lport)
2107 diff -Nur linux-2.6.6-rc3.org/include/net/udp.h linux-2.6.6-rc3/include/net/udp.h
2108 --- linux-2.6.6-rc3.org/include/net/udp.h       2004-04-28 03:36:29.000000000 +0200
2109 +++ linux-2.6.6-rc3/include/net/udp.h   2004-04-30 09:13:14.000000000 +0200
2110 @@ -74,6 +74,8 @@
2111  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
2112  extern int     udp_disconnect(struct sock *sk, int flags);
2113  
2114 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
2115 +
2116  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
2117  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
2118  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
2119 diff -Nur linux-2.6.6-rc3.org/include/net/xfrm.h linux-2.6.6-rc3/include/net/xfrm.h
2120 --- linux-2.6.6-rc3.org/include/net/xfrm.h      2004-04-28 03:36:31.000000000 +0200
2121 +++ linux-2.6.6-rc3/include/net/xfrm.h  2004-04-30 09:12:40.000000000 +0200
2122 @@ -540,6 +540,9 @@
2123  {
2124         atomic_t                refcnt;
2125         int                     len;
2126 +#ifdef CONFIG_NETFILTER
2127 +       int                     decap_done;
2128 +#endif
2129         struct sec_decap_state  x[XFRM_MAX_DEPTH];
2130  };
2131  
2132 diff -Nur linux-2.6.6-rc3.org/net/core/netfilter.c linux-2.6.6-rc3/net/core/netfilter.c
2133 --- linux-2.6.6-rc3.org/net/core/netfilter.c    2004-04-28 03:35:46.000000000 +0200
2134 +++ linux-2.6.6-rc3/net/core/netfilter.c        2004-04-30 09:12:42.000000000 +0200
2135 @@ -27,6 +27,8 @@
2136  #include <linux/icmp.h>
2137  #include <net/sock.h>
2138  #include <net/route.h>
2139 +#include <net/xfrm.h>
2140 +#include <net/ip.h>
2141  #include <linux/ip.h>
2142  
2143  /* In this code, we can be waiting indefinitely for userspace to
2144 @@ -638,7 +640,6 @@
2145  #ifdef CONFIG_IP_ROUTE_FWMARK
2146                 fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
2147  #endif
2148 -               fl.proto = iph->protocol;
2149                 if (ip_route_output_key(&rt, &fl) != 0)
2150                         return -1;
2151  
2152 @@ -665,6 +666,20 @@
2153         if ((*pskb)->dst->error)
2154                 return -1;
2155  
2156 +#ifdef CONFIG_XFRM
2157 +       if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
2158 +               struct xfrm_policy_afinfo *afinfo;
2159 +
2160 +               afinfo = xfrm_policy_get_afinfo(AF_INET);
2161 +               if (afinfo != NULL) {
2162 +                       afinfo->decode_session(*pskb, &fl);
2163 +                       xfrm_policy_put_afinfo(afinfo);
2164 +                       if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
2165 +                               return -1;
2166 +               }
2167 +       }
2168 +#endif
2169 +
2170         /* Change in oif may mean change in hh_len. */
2171         hh_len = (*pskb)->dst->dev->hard_header_len;
2172         if (skb_headroom(*pskb) < hh_len) {
2173 @@ -682,6 +697,71 @@
2174         return 0;
2175  }
2176  
2177 +#ifdef CONFIG_XFRM
2178 +inline int nf_rcv_postxfrm_nonlocal(struct sk_buff *skb)
2179 +{
2180 +       skb->sp->decap_done = 1;
2181 +       dst_release(skb->dst);
2182 +       skb->dst = NULL;
2183 +       nf_reset(skb);
2184 +       return netif_rx(skb);
2185 +}
2186 +
2187 +int nf_rcv_postxfrm_local(struct sk_buff *skb)
2188 +{
2189 +       __skb_push(skb, skb->data - skb->nh.raw);
2190 +       /* Fix header len and checksum if last xfrm was transport mode */
2191 +       if (!skb->sp->x[skb->sp->len - 1].xvec->props.mode) {
2192 +               skb->nh.iph->tot_len = htons(skb->len);
2193 +               ip_send_check(skb->nh.iph);
2194 +       }
2195 +       return nf_rcv_postxfrm_nonlocal(skb);
2196 +}
2197 +
2198 +#ifdef CONFIG_IP_NF_NAT_NEEDED
2199 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2200 +#include <linux/netfilter_ipv4/ip_nat.h>
2201 +
2202 +void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
2203 +{
2204 +       struct ip_conntrack *ct;
2205 +       struct ip_conntrack_tuple *t;
2206 +       struct ip_nat_info_manip *m;
2207 +       unsigned int i;
2208 +
2209 +       if (skb->nfct == NULL)
2210 +               return;
2211 +       ct = (struct ip_conntrack *)skb->nfct->master;
2212 +
2213 +       for (i = 0; i < ct->nat.info.num_manips; i++) {
2214 +               m = &ct->nat.info.manips[i];
2215 +               t = &ct->tuplehash[m->direction].tuple;
2216 +
2217 +               switch (m->hooknum) {
2218 +               case NF_IP_PRE_ROUTING:
2219 +                       if (m->maniptype != IP_NAT_MANIP_DST)
2220 +                               break;
2221 +                       fl->fl4_dst = t->dst.ip;
2222 +                       if (t->dst.protonum == IPPROTO_TCP ||
2223 +                           t->dst.protonum == IPPROTO_UDP)
2224 +                               fl->fl_ip_dport = t->dst.u.tcp.port;
2225 +                       break;
2226 +#ifdef CONFIG_IP_NF_NAT_LOCAL
2227 +               case NF_IP_LOCAL_IN:
2228 +                       if (m->maniptype != IP_NAT_MANIP_SRC)
2229 +                               break;
2230 +                       fl->fl4_src = t->src.ip;
2231 +                       if (t->dst.protonum == IPPROTO_TCP ||
2232 +                           t->dst.protonum == IPPROTO_UDP)
2233 +                               fl->fl_ip_sport = t->src.u.tcp.port;
2234 +                       break;
2235 +#endif
2236 +               }
2237 +       }
2238 +}
2239 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
2240 +#endif
2241 +
2242  int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
2243  {
2244         struct sk_buff *nskb;
2245 @@ -839,3 +919,4 @@
2246  EXPORT_SYMBOL(nf_unregister_hook);
2247  EXPORT_SYMBOL(nf_unregister_queue_handler);
2248  EXPORT_SYMBOL(nf_unregister_sockopt);
2249 +EXPORT_SYMBOL(nf_rcv_postxfrm_local);
2250 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ah4.c linux-2.6.6-rc3/net/ipv4/ah4.c
2251 --- linux-2.6.6-rc3.org/net/ipv4/ah4.c  2004-04-28 03:36:34.000000000 +0200
2252 +++ linux-2.6.6-rc3/net/ipv4/ah4.c      2004-04-30 09:12:40.000000000 +0200
2253 @@ -145,6 +145,7 @@
2254                 err = -EHOSTUNREACH;
2255                 goto error_nolock;
2256         }
2257 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2258         return NET_XMIT_BYPASS;
2259  
2260  error:
2261 @@ -343,6 +344,7 @@
2262         .handler        =       xfrm4_rcv,
2263         .err_handler    =       ah4_err,
2264         .no_policy      =       1,
2265 +       .xfrm_prot      =       1,
2266  };
2267  
2268  static int __init ah4_init(void)
2269 diff -Nur linux-2.6.6-rc3.org/net/ipv4/esp4.c linux-2.6.6-rc3/net/ipv4/esp4.c
2270 --- linux-2.6.6-rc3.org/net/ipv4/esp4.c 2004-04-28 03:36:01.000000000 +0200
2271 +++ linux-2.6.6-rc3/net/ipv4/esp4.c     2004-04-30 09:12:40.000000000 +0200
2272 @@ -216,6 +216,7 @@
2273                 err = -EHOSTUNREACH;
2274                 goto error_nolock;
2275         }
2276 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2277         return NET_XMIT_BYPASS;
2278  
2279  error:
2280 @@ -598,6 +599,7 @@
2281         .handler        =       xfrm4_rcv,
2282         .err_handler    =       esp4_err,
2283         .no_policy      =       1,
2284 +       .xfrm_prot      =       1,
2285  };
2286  
2287  static int __init esp4_init(void)
2288 diff -Nur linux-2.6.6-rc3.org/net/ipv4/igmp.c linux-2.6.6-rc3/net/ipv4/igmp.c
2289 --- linux-2.6.6-rc3.org/net/ipv4/igmp.c 2004-04-28 03:36:55.000000000 +0200
2290 +++ linux-2.6.6-rc3/net/ipv4/igmp.c     2004-04-30 09:12:39.000000000 +0200
2291 @@ -342,7 +342,7 @@
2292         pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
2293  
2294         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
2295 -                      dst_output);
2296 +                      ip_dst_output);
2297  }
2298  
2299  static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel)
2300 @@ -672,7 +672,7 @@
2301         ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
2302  
2303         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2304 -                      dst_output);
2305 +                      ip_dst_output);
2306  }
2307  
2308  static void igmp_gq_timer_expire(unsigned long data)
2309 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_forward.c linux-2.6.6-rc3/net/ipv4/ip_forward.c
2310 --- linux-2.6.6-rc3.org/net/ipv4/ip_forward.c   2004-04-28 03:34:59.000000000 +0200
2311 +++ linux-2.6.6-rc3/net/ipv4/ip_forward.c       2004-04-30 09:12:39.000000000 +0200
2312 @@ -51,7 +51,7 @@
2313         if (unlikely(opt->optlen))
2314                 ip_forward_options(skb);
2315  
2316 -       return dst_output(skb);
2317 +       return ip_dst_output(skb);
2318  }
2319  
2320  int ip_forward(struct sk_buff *skb)
2321 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_gre.c linux-2.6.6-rc3/net/ipv4/ip_gre.c
2322 --- linux-2.6.6-rc3.org/net/ipv4/ip_gre.c       2004-04-28 03:36:22.000000000 +0200
2323 +++ linux-2.6.6-rc3/net/ipv4/ip_gre.c   2004-04-30 09:09:38.000000000 +0200
2324 @@ -643,13 +643,7 @@
2325                 skb->dev = tunnel->dev;
2326                 dst_release(skb->dst);
2327                 skb->dst = NULL;
2328 -#ifdef CONFIG_NETFILTER
2329 -               nf_conntrack_put(skb->nfct);
2330 -               skb->nfct = NULL;
2331 -#ifdef CONFIG_NETFILTER_DEBUG
2332 -               skb->nf_debug = 0;
2333 -#endif
2334 -#endif
2335 +               nf_reset(skb);
2336                 ipgre_ecn_decapsulate(iph, skb);
2337                 netif_rx(skb);
2338                 read_unlock(&ipgre_lock);
2339 @@ -877,13 +871,7 @@
2340                 }
2341         }
2342  
2343 -#ifdef CONFIG_NETFILTER
2344 -       nf_conntrack_put(skb->nfct);
2345 -       skb->nfct = NULL;
2346 -#ifdef CONFIG_NETFILTER_DEBUG
2347 -       skb->nf_debug = 0;
2348 -#endif
2349 -#endif
2350 +       nf_reset(skb);
2351  
2352         IPTUNNEL_XMIT();
2353         tunnel->recursion--;
2354 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_input.c linux-2.6.6-rc3/net/ipv4/ip_input.c
2355 --- linux-2.6.6-rc3.org/net/ipv4/ip_input.c     2004-04-28 03:35:06.000000000 +0200
2356 +++ linux-2.6.6-rc3/net/ipv4/ip_input.c 2004-04-30 09:12:42.000000000 +0200
2357 @@ -202,18 +202,10 @@
2358  
2359  #ifdef CONFIG_NETFILTER_DEBUG
2360         nf_debug_ip_local_deliver(skb);
2361 -       skb->nf_debug = 0;
2362  #endif /*CONFIG_NETFILTER_DEBUG*/
2363  
2364         __skb_pull(skb, ihl);
2365  
2366 -#ifdef CONFIG_NETFILTER
2367 -       /* Free reference early: we don't need it any more, and it may
2368 -           hold ip_conntrack module loaded indefinitely. */
2369 -       nf_conntrack_put(skb->nfct);
2370 -       skb->nfct = NULL;
2371 -#endif /*CONFIG_NETFILTER*/
2372 -
2373          /* Point into the IP datagram, just past the header. */
2374          skb->h.raw = skb->data;
2375  
2376 @@ -228,6 +220,13 @@
2377         resubmit:
2378                 hash = protocol & (MAX_INET_PROTOS - 1);
2379                 raw_sk = sk_head(&raw_v4_htable[hash]);
2380 +               ipprot = inet_protos[hash];
2381 +               smp_read_barrier_depends();
2382 +
2383 +               if (nf_xfrm_local_done(skb, ipprot)) {
2384 +                       nf_rcv_postxfrm_local(skb);
2385 +                       goto out;
2386 +               }
2387  
2388                 /* If there maybe a raw socket we must check - if not we
2389                  * don't care less
2390 @@ -235,14 +234,15 @@
2391                 if (raw_sk)
2392                         raw_v4_input(skb, skb->nh.iph, hash);
2393  
2394 -               if ((ipprot = inet_protos[hash]) != NULL) {
2395 +               if (ipprot != NULL) {
2396                         int ret;
2397  
2398 -                       smp_read_barrier_depends();
2399 -                       if (!ipprot->no_policy &&
2400 -                           !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2401 -                               kfree_skb(skb);
2402 -                               goto out;
2403 +                       if (!ipprot->no_policy) {
2404 +                               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2405 +                                       kfree_skb(skb);
2406 +                                       goto out;
2407 +                               }
2408 +                               nf_reset(skb);
2409                         }
2410                         ret = ipprot->handler(skb);
2411                         if (ret < 0) {
2412 @@ -283,8 +283,8 @@
2413                         return 0;
2414         }
2415  
2416 -       return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2417 -                      ip_local_deliver_finish);
2418 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
2419 +                           ip_local_deliver_finish, nf_hook_input_cond(skb));
2420  }
2421  
2422  static inline int ip_rcv_finish(struct sk_buff *skb)
2423 @@ -301,6 +301,9 @@
2424                         goto drop; 
2425         }
2426  
2427 +       if (nf_xfrm_nonlocal_done(skb))
2428 +               return nf_rcv_postxfrm_nonlocal(skb);
2429 +
2430  #ifdef CONFIG_NET_CLS_ROUTE
2431         if (skb->dst->tclassid) {
2432                 struct ip_rt_acct *st = ip_rt_acct + 256*smp_processor_id();
2433 @@ -422,8 +425,8 @@
2434                 }
2435         }
2436  
2437 -       return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2438 -                      ip_rcv_finish);
2439 +       return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
2440 +                           ip_rcv_finish, nf_hook_input_cond(skb));
2441  
2442  inhdr_error:
2443         IP_INC_STATS_BH(IpInHdrErrors);
2444 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ip_output.c linux-2.6.6-rc3/net/ipv4/ip_output.c
2445 --- linux-2.6.6-rc3.org/net/ipv4/ip_output.c    2004-04-28 03:36:55.000000000 +0200
2446 +++ linux-2.6.6-rc3/net/ipv4/ip_output.c        2004-04-30 09:12:39.000000000 +0200
2447 @@ -123,6 +123,15 @@
2448         return ttl;
2449  }
2450  
2451 +#ifdef CONFIG_NETFILTER
2452 +/* out-of-line copy is only required with netfilter */
2453 +int ip_dst_output(struct sk_buff *skb)
2454 +{
2455 +       return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
2456 +                           skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
2457 +}
2458 +#endif
2459 +
2460  /* 
2461   *             Add an ip header to a skbuff and send it out.
2462   *
2463 @@ -165,7 +174,7 @@
2464  
2465         /* Send it out. */
2466         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2467 -                      dst_output);
2468 +                      ip_dst_output);
2469  }
2470  
2471  static inline int ip_finish_output2(struct sk_buff *skb)
2472 @@ -283,7 +292,7 @@
2473                 return ip_finish_output(skb);
2474  }
2475  
2476 -int ip_output(struct sk_buff *skb)
2477 +static inline int ip_output2(struct sk_buff *skb)
2478  {
2479         IP_INC_STATS(IpOutRequests);
2480  
2481 @@ -294,6 +303,16 @@
2482                 return ip_finish_output(skb);
2483  }
2484  
2485 +int ip_output(struct sk_buff *skb)
2486 +{
2487 +       int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
2488 +
2489 +       if (transformed)
2490 +               nf_reset(skb);
2491 +       return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
2492 +                           skb->dst->dev, ip_output2, transformed);
2493 +}
2494 +
2495  int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
2496  {
2497         struct sock *sk = skb->sk;
2498 @@ -387,7 +406,7 @@
2499         skb->priority = sk->sk_priority;
2500  
2501         return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
2502 -                      dst_output);
2503 +                      ip_dst_output);
2504  
2505  no_route:
2506         IP_INC_STATS(IpOutNoRoutes);
2507 @@ -1177,7 +1196,7 @@
2508  
2509         /* Netfilter gets whole the not fragmented skb. */
2510         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
2511 -                     skb->dst->dev, dst_output);
2512 +                     skb->dst->dev, ip_dst_output);
2513         if (err) {
2514                 if (err > 0)
2515                         err = inet->recverr ? net_xmit_errno(err) : 0;
2516 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipcomp.c linux-2.6.6-rc3/net/ipv4/ipcomp.c
2517 --- linux-2.6.6-rc3.org/net/ipv4/ipcomp.c       2004-04-28 03:36:33.000000000 +0200
2518 +++ linux-2.6.6-rc3/net/ipv4/ipcomp.c   2004-04-30 09:12:40.000000000 +0200
2519 @@ -231,6 +231,7 @@
2520                 err = -EHOSTUNREACH;
2521                 goto error_nolock;
2522         }
2523 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
2524         err = NET_XMIT_BYPASS;
2525  
2526  out_exit:
2527 @@ -407,6 +408,7 @@
2528         .handler        =       xfrm4_rcv,
2529         .err_handler    =       ipcomp4_err,
2530         .no_policy      =       1,
2531 +       .xfrm_prot      =       1,
2532  };
2533  
2534  static int __init ipcomp4_init(void)
2535 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipip.c linux-2.6.6-rc3/net/ipv4/ipip.c
2536 --- linux-2.6.6-rc3.org/net/ipv4/ipip.c 2004-04-28 03:37:06.000000000 +0200
2537 +++ linux-2.6.6-rc3/net/ipv4/ipip.c     2004-04-30 09:12:40.000000000 +0200
2538 @@ -478,6 +478,11 @@
2539  
2540         read_lock(&ipip_lock);
2541         if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
2542 +               /* IPIP packets decapsulated by IPsec missed netfilter hooks */
2543 +               if (nf_xfrm_local_done(skb, NULL)) {
2544 +                       nf_rcv_postxfrm_local(skb);
2545 +                       return 0;
2546 +               }
2547                 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
2548                         kfree_skb(skb);
2549                         return 0;
2550 @@ -496,13 +501,7 @@
2551                 skb->dev = tunnel->dev;
2552                 dst_release(skb->dst);
2553                 skb->dst = NULL;
2554 -#ifdef CONFIG_NETFILTER
2555 -               nf_conntrack_put(skb->nfct);
2556 -               skb->nfct = NULL;
2557 -#ifdef CONFIG_NETFILTER_DEBUG
2558 -               skb->nf_debug = 0;
2559 -#endif
2560 -#endif
2561 +               nf_reset(skb);
2562                 ipip_ecn_decapsulate(iph, skb);
2563                 netif_rx(skb);
2564                 read_unlock(&ipip_lock);
2565 @@ -647,13 +646,7 @@
2566         if ((iph->ttl = tiph->ttl) == 0)
2567                 iph->ttl        =       old_iph->ttl;
2568  
2569 -#ifdef CONFIG_NETFILTER
2570 -       nf_conntrack_put(skb->nfct);
2571 -       skb->nfct = NULL;
2572 -#ifdef CONFIG_NETFILTER_DEBUG
2573 -       skb->nf_debug = 0;
2574 -#endif
2575 -#endif
2576 +       nf_reset(skb);
2577  
2578         IPTUNNEL_XMIT();
2579         tunnel->recursion--;
2580 diff -Nur linux-2.6.6-rc3.org/net/ipv4/ipmr.c linux-2.6.6-rc3/net/ipv4/ipmr.c
2581 --- linux-2.6.6-rc3.org/net/ipv4/ipmr.c 2004-04-28 03:35:47.000000000 +0200
2582 +++ linux-2.6.6-rc3/net/ipv4/ipmr.c     2004-04-30 09:12:39.000000000 +0200
2583 @@ -1120,7 +1120,7 @@
2584         if (unlikely(opt->optlen))
2585                 ip_forward_options(skb);
2586  
2587 -       return dst_output(skb);
2588 +       return ip_dst_output(skb);
2589  }
2590  
2591  /*
2592 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig
2593 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Kconfig      2004-04-28 03:36:31.000000000 +0200
2594 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Kconfig  2004-04-30 09:14:39.000000000 +0200
2595 @@ -206,6 +206,11 @@
2596  
2597           To compile it as a module, choose M here.  If unsure, say N.
2598  
2599 +config IP_NF_MATCH_UNCLEAN
2600 +       tristate  'unclean match support (EXPERIMENTAL)'
2601 +       depends on EXPERIMENTAL && IP_NF_IPTABLES
2602 +         help
2603 +
2604  config IP_NF_MATCH_TTL
2605         tristate "TTL match support"
2606         depends on IP_NF_IPTABLES
2607 @@ -603,5 +608,227 @@
2608           <file:Documentation/modules.txt>.  If unsure, say `N'.
2609           help
2610  
2611 +config IP_NF_TARGET_IPV4OPTSSTRIP
2612 +       tristate  'IPV4OPTSSTRIP target support'
2613 +       depends on IP_NF_MANGLE
2614 +         help
2615 +
2616 +config IP_NF_TARGET_NETLINK
2617 +       tristate  'NETLINK target support'
2618 +       depends on IP_NF_FILTER
2619 +         help
2620 +
2621 +config IP_NF_TARGET_TTL
2622 +       tristate  'TTL target support'
2623 +       depends on IP_NF_MANGLE
2624 +         help
2625 +
2626 +config IP_NF_MATCH_CONNLIMIT
2627 +       tristate  'Connections/IP limit match support'
2628 +       depends on IP_NF_IPTABLES
2629 +         help
2630 +
2631 +config IP_NF_MATCH_DSTLIMIT
2632 +       tristate  'dstlimit match support'
2633 +       depends on IP_NF_IPTABLES
2634 +         help
2635 +
2636 +config IP_NF_MATCH_FUZZY
2637 +       tristate  'fuzzy match support'
2638 +       depends on IP_NF_IPTABLES
2639 +         help
2640 +
2641 +config IP_NF_MATCH_IPV4OPTIONS
2642 +       tristate  'IPV4OPTIONS match support'
2643 +       depends on IP_NF_IPTABLES
2644 +         help
2645 +
2646 +config IP_NF_MATCH_MPORT
2647 +       tristate  'Multiple port with ranges match support'
2648 +       depends on IP_NF_IPTABLES
2649 +         help
2650 +
2651 +config IP_NF_MATCH_NTH
2652 +       tristate  'Nth match support'
2653 +       depends on IP_NF_IPTABLES
2654 +         help
2655 +
2656 +config IP_NF_MATCH_OSF
2657 +       tristate  'OSF match support'
2658 +       depends on IP_NF_IPTABLES
2659 +         help
2660 +
2661 +config IP_POOL_STATISTICS
2662 +       bool  'enable statistics on pool usage'
2663 +       depends on IP_NF_POOL!=n
2664 +
2665 +config IP_NF_POOL
2666 +       tristate  'IP address pool support'
2667 +       depends on IP_NF_IPTABLES
2668 +         help
2669 +
2670 +config IP_NF_MATCH_PSD
2671 +       tristate  'psd match support'
2672 +       depends on IP_NF_IPTABLES
2673 +         help
2674 +
2675 +config IP_NF_MATCH_QUOTA
2676 +       tristate  'quota match support'
2677 +       depends on IP_NF_IPTABLES
2678 +         help
2679 +
2680 +config IP_NF_MATCH_RANDOM
2681 +       tristate  'random match support'
2682 +       depends on IP_NF_IPTABLES
2683 +         help
2684 +
2685 +config IP_NF_MATCH_REALM
2686 +       tristate  'realm match support'
2687 +       depends on IP_NF_IPTABLES && NET_CLS_ROUTE
2688 +         help
2689 +
2690 +config IP_NF_MATCH_SCTP
2691 +       tristate  'SCTP protocol match support'
2692 +       depends on IP_NF_IPTABLES
2693 +         help
2694 +
2695 +config IP_NF_MATCH_TIME
2696 +       tristate  'TIME match support'
2697 +       depends on IP_NF_IPTABLES
2698 +         help
2699 +
2700 +config IP_NF_MATCH_U32
2701 +       tristate  'U32 match support'
2702 +       depends on IP_NF_IPTABLES
2703 +         help
2704 +
2705 +config IP_NF_CONNTRACK_MARK
2706 +       bool  'Connection mark tracking support'
2707 +config IP_NF_TARGET_CONNMARK
2708 +       tristate  'CONNMARK target support'
2709 +       depends on IP_NF_MANGLE
2710 +config IP_NF_MATCH_CONNMARK
2711 +       tristate  ' Connection mark match support'
2712 +       depends on IP_NF_IPTABLES
2713 +         help
2714 +
2715 +config IP_NF_TARGET_IPMARK
2716 +       tristate  'IPMARK target support'
2717 +       depends on IP_NF_MANGLE
2718 +         help
2719 +
2720 +config IP_NF_TARGET_TARPIT
2721 +       tristate 'TARPIT target support'
2722 +       depends on IP_NF_FILTER
2723 +         help
2724 +
2725 +config IP_NF_TARGET_TRACE
2726 +       tristate  'TRACE target support'
2727 +       depends on IP_NF_RAW
2728 +       help
2729 +         The TRACE target allows packets to be traced as those
2730 +         matches any subsequent rule in any table/rule. The matched
2731 +         rule and the packet is logged with the prefix
2732 +       
2733 +         TRACE: tablename/chainname/rulenum  
2734 +       
2735 +         If you want to compile it as a module, say M here and read
2736 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
2737 +         help
2738 +
2739 +config IP_NF_TARGET_XOR
2740 +       tristate  'XOR target support'
2741 +       depends on IP_NF_MANGLE
2742 +         help
2743 +
2744 +config IP_NF_MATCH_ADDRTYPE
2745 +       tristate  'address type match support'
2746 +       depends on IP_NF_IPTABLES
2747 +         help
2748 +
2749 +config IP_NF_EGG
2750 +       tristate  'Eggdrop bot support'
2751 +       depends on IP_NF_CONNTRACK
2752 +         help
2753 +
2754 +config IP_NF_NAT_H323
2755 +       tristate
2756 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2757 +       default IP_NF_NAT if IP_NF_H323=y
2758 +       default m if IP_NF_H323=m
2759 +
2760 +config IP_NF_H323
2761 +       tristate  'H.323 (netmeeting) support'
2762 +       depends on IP_NF_CONNTRACK
2763 +         help
2764 +
2765 +config IP_NF_NAT_MMS
2766 +       tristate
2767 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2768 +       default IP_NF_NAT if IP_NF_MMS=y
2769 +       default m if IP_NF_MMS=m
2770 +
2771 +config IP_NF_MMS
2772 +       tristate  'MMS protocol support'
2773 +       depends on IP_NF_CONNTRACK
2774 +         help
2775 +
2776 +config IP_NF_MATCH_POLICY
2777 +       tristate "IPsec policy match support"
2778 +       depends on IP_NF_IPTABLES && XFRM
2779 +       help
2780 +         Policy matching allows you to match packets based on the
2781 +         IPsec policy that was used during decapsulation/will
2782 +         be used during encapsulation.
2783 +
2784 +         To compile it as a module, choose M here.  If unsure, say N.
2785 +         help
2786 +
2787 +config IP_NF_NAT_QUAKE3
2788 +       tristate
2789 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT !=n
2790 +       default IP_NF_NAT if IP_NF_QUAKE3=y
2791 +       default m if IP_NF_QUAKE3=m
2792 +
2793 +config IP_NF_QUAKE3
2794 +       tristate "Quake3 protocol support"
2795 +       depends on IP_NF_CONNTRACK
2796 +         help
2797 +
2798 +config IP_NF_RSH
2799 +       tristate  'RSH protocol support'
2800 +       depends on IP_NF_CONNTRACK
2801 +         help
2802 +
2803 +config IP_NF_NAT_RTSP
2804 +       tristate
2805 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2806 +       default IP_NF_NAT if IP_NF_RTSP=y
2807 +       default m if IP_NF_RTSP=m
2808 +config IP_NF_RTSP
2809 +       tristate  ' RTSP protocol support'
2810 +       depends on IP_NF_CONNTRACK
2811 +         help
2812 +
2813 +config IP_NF_CT_PROTO_SCTP
2814 +       tristate  'SCTP protocol connection tracking support'
2815 +       depends on IP_NF_CONNTRACK
2816 +         help
2817 +
2818 +config IP_NF_MATCH_STRING
2819 +       tristate  'String match support'
2820 +       depends on IP_NF_IPTABLES
2821 +         help
2822 +
2823 +config IP_NF_NAT_TALK
2824 +       tristate
2825 +       depends on IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
2826 +       default IP_NF_NAT if IP_NF_TALK=y
2827 +       default m if IP_NF_TALK=m
2828 +config IP_NF_TALK
2829 +       tristate  'talk protocol support'
2830 +       depends on IP_NF_CONNTRACK
2831 +         help
2832 +
2833  endmenu
2834  
2835 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.6-rc3/net/ipv4/netfilter/Makefile
2836 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/Makefile     2004-04-28 03:35:21.000000000 +0200
2837 +++ linux-2.6.6-rc3/net/ipv4/netfilter/Makefile 2004-04-30 09:14:39.000000000 +0200
2838 @@ -19,10 +19,34 @@
2839  # connection tracking
2840  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
2841  
2842 +# talk protocol support
2843 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
2844 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
2845 +
2846 +
2847 +# SCTP protocol connection tracking
2848 +obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o
2849
2850 +# H.323 support
2851 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
2852 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
2853 +
2854 +
2855  # connection tracking helpers
2856 +
2857 +# rtsp protocol support
2858 +obj-$(CONFIG_IP_NF_RTSP) += ip_conntrack_rtsp.o
2859 +obj-$(CONFIG_IP_NF_NAT_RTSP) += ip_nat_rtsp.o
2860 +
2861 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
2862 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
2863  obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
2864  obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
2865  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
2866 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
2867 +
2868 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
2869 +
2870  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
2871  
2872  # NAT helpers 
2873 @@ -30,6 +69,8 @@
2874  obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
2875  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
2876  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
2877 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
2878 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
2879  
2880  # generic IP tables 
2881  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
2882 @@ -43,15 +84,39 @@
2883  # matches
2884  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
2885  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
2886 +obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
2887 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
2888 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
2889  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
2890 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
2891  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
2892  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
2893  
2894  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
2895  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
2896 +
2897 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
2898 +
2899  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
2900  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
2901  
2902 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
2903 +
2904 +
2905 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
2906 +
2907 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
2908 +
2909 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
2910 +
2911 +
2912 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
2913 +
2914 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
2915 +
2916 +
2917 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
2918 +
2919  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
2920  
2921  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
2922 @@ -60,12 +125,22 @@
2923  
2924  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
2925  
2926 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
2927 +
2928 +
2929 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
2930 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
2931  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
2932  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
2933 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
2934 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
2935  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
2936  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
2937 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
2938 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
2939  
2940  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
2941 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
2942  
2943  # targets
2944  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
2945 @@ -73,6 +148,8 @@
2946  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
2947  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
2948  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
2949 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
2950 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
2951  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
2952  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
2953  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
2954 @@ -80,8 +157,14 @@
2955  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
2956  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
2957  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
2958 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
2959 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
2960 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
2961 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
2962 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
2963  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
2964  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
2965 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
2966  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
2967  
2968  # generic ARP tables
2969 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c
2970 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_core.c  2004-04-28 03:34:58.000000000 +0200
2971 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_core.c      2004-04-30 09:11:35.000000000 +0200
2972 @@ -324,8 +324,9 @@
2973                 ip_conntrack_destroyed(ct);
2974  
2975         WRITE_LOCK(&ip_conntrack_lock);
2976 -       /* Delete us from our own list to prevent corruption later */
2977 -       list_del(&ct->sibling_list);
2978 +       /* Make sure don't leave any orphaned expectations lying around */
2979 +       if (ct->expecting)
2980 +               remove_expectations(ct, 1);
2981  
2982         /* Delete our master expectation */
2983         if (ct->master) {
2984 @@ -692,42 +693,53 @@
2985                              struct ip_conntrack_expect *, tuple);
2986         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
2987  
2988 -       /* If master is not in hash table yet (ie. packet hasn't left
2989 -          this machine yet), how can other end know about expected?
2990 -          Hence these are not the droids you are looking for (if
2991 -          master ct never got confirmed, we'd hold a reference to it
2992 -          and weird things would happen to future packets). */
2993 -       if (expected && !is_confirmed(expected->expectant))
2994 -               expected = NULL;
2995 -
2996 -       /* Look up the conntrack helper for master connections only */
2997 -       if (!expected)
2998 -               conntrack->helper = ip_ct_find_helper(&repl_tuple);
2999 -
3000 -       /* If the expectation is dying, then this is a loser. */
3001 -       if (expected
3002 -           && expected->expectant->helper->timeout
3003 -           && ! del_timer(&expected->timeout))
3004 -               expected = NULL;
3005 -
3006         if (expected) {
3007 -               DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3008 -                       conntrack, expected);
3009 -               /* Welcome, Mr. Bond.  We've been expecting you... */
3010 -               IP_NF_ASSERT(master_ct(conntrack));
3011 -               __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3012 -               conntrack->master = expected;
3013 -               expected->sibling = conntrack;
3014 -               LIST_DELETE(&ip_conntrack_expect_list, expected);
3015 -               expected->expectant->expecting--;
3016 -               nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3017 -       }
3018 -       atomic_inc(&ip_conntrack_count);
3019 +               /* If master is not in hash table yet (ie. packet hasn't left
3020 +                  this machine yet), how can other end know about expected?
3021 +                  Hence these are not the droids you are looking for (if
3022 +                  master ct never got confirmed, we'd hold a reference to it
3023 +                  and weird things would happen to future packets). */
3024 +               if (!is_confirmed(expected->expectant)) {
3025 +                       
3026 +                       conntrack->helper = ip_ct_find_helper(&repl_tuple);
3027 +                       goto end;
3028 +               }
3029 +
3030 +               /* Expectation is dying... */
3031 +               if (expected->expectant->helper->timeout
3032 +                   && ! del_timer(&expected->timeout)) {
3033 +                       goto end;       
3034 +               }
3035 +
3036 +                DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
3037 +                       conntrack, expected);
3038 +                /* Welcome, Mr. Bond.  We've been expecting you... */
3039 +                IP_NF_ASSERT(master_ct(conntrack));
3040 +                __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
3041 +                conntrack->master = expected;
3042 +                expected->sibling = conntrack;
3043 +#if CONFIG_IP_NF_CONNTRACK_MARK
3044 +               conntrack->mark = expected->expectant->mark;
3045 +#endif
3046 +                LIST_DELETE(&ip_conntrack_expect_list, expected);
3047 +                expected->expectant->expecting--;
3048 +                nf_conntrack_get(&master_ct(conntrack)->infos[0]);
3049 +
3050 +               /* this is a braindead... --pablo */
3051 +               atomic_inc(&ip_conntrack_count);
3052 +               WRITE_UNLOCK(&ip_conntrack_lock);
3053 +
3054 +               if (expected->expectfn)
3055 +                       expected->expectfn(conntrack);
3056 +
3057 +               goto ret;
3058 +        } else 
3059 +                conntrack->helper = ip_ct_find_helper(&repl_tuple);
3060 +
3061 +end:   atomic_inc(&ip_conntrack_count);
3062         WRITE_UNLOCK(&ip_conntrack_lock);
3063  
3064 -       if (expected && expected->expectfn)
3065 -               expected->expectfn(conntrack);
3066 -       return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3067 +ret:   return &conntrack->tuplehash[IP_CT_DIR_ORIGINAL];
3068  }
3069  
3070  /* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
3071 @@ -947,9 +959,8 @@
3072         atomic_set(&new->use, 1);
3073  
3074         /* add to expected list for this connection */
3075 -       list_add(&new->expected_list, &related_to->sibling_list);
3076 +       list_add_tail(&new->expected_list, &related_to->sibling_list);
3077         /* add to global list of expectations */
3078 -
3079         list_prepend(&ip_conntrack_expect_list, &new->list);
3080         /* add and start timer if required */
3081         if (related_to->helper->timeout) {
3082 @@ -1003,7 +1014,6 @@
3083  
3084         } else if (related_to->helper->max_expected && 
3085                    related_to->expecting >= related_to->helper->max_expected) {
3086 -               struct list_head *cur_item;
3087                 /* old == NULL */
3088                 if (!(related_to->helper->flags & 
3089                       IP_CT_HELPER_F_REUSE_EXPECT)) {
3090 @@ -1029,21 +1039,14 @@
3091                        NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
3092   
3093                 /* choose the the oldest expectation to evict */
3094 -               list_for_each(cur_item, &related_to->sibling_list) { 
3095 -                       struct ip_conntrack_expect *cur;
3096 -
3097 -                       cur = list_entry(cur_item, 
3098 -                                        struct ip_conntrack_expect,
3099 -                                        expected_list);
3100 -                       if (cur->sibling == NULL) {
3101 -                               old = cur;
3102 +               list_for_each_entry(old, &related_to->sibling_list, 
3103 +                                                     expected_list)
3104 +                       if (old->sibling == NULL)
3105                                 break;
3106 -                       }
3107 -               }
3108  
3109 -               /* (!old) cannot happen, since related_to->expecting is the
3110 -                * number of unconfirmed expects */
3111 -               IP_NF_ASSERT(old);
3112 +               /* We cannot fail since related_to->expecting is the number
3113 +                * of unconfirmed expectations */
3114 +               IP_NF_ASSERT(old && old->sibling == NULL);
3115  
3116                 /* newnat14 does not reuse the real allocated memory
3117                  * structures but rather unexpects the old and
3118 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c
3119 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_egg.c   1970-01-01 01:00:00.000000000 +0100
3120 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_egg.c       2004-04-30 09:12:26.000000000 +0200
3121 @@ -0,0 +1,237 @@
3122 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
3123 + * based on ip_conntrack_irc.c 
3124 + *
3125 + *      This module only supports the share userfile-send command,
3126 + *      used by eggdrops to share it's userfile.
3127 + *
3128 + *      There are no support for NAT at the moment.
3129 + *
3130 + *      This program is free software; you can redistribute it and/or
3131 + *      modify it under the terms of the GNU General Public License
3132 + *      as published by the Free Software Foundation; either version
3133 + *      2 of the License, or (at your option) any later version.
3134 + *
3135 + *     Module load syntax:
3136 + *     
3137 + *     please give the ports of all Eggdrops You have running
3138 + *      on your system, the default port is 3333.
3139 + *
3140 + *      2001-04-19: Security update. IP addresses are now compared
3141 + *                  to prevent unauthorized "related" access.
3142 + *
3143 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
3144 + *                 Port to netfilter 'newnat' API.
3145 + */
3146 +
3147 +#include <linux/module.h>
3148 +#include <linux/netfilter.h>
3149 +#include <linux/ip.h>
3150 +#include <net/checksum.h>
3151 +#include <net/tcp.h>
3152 +
3153 +#include <linux/netfilter_ipv4/lockhelp.h>
3154 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3155 +
3156 +#define MAX_PORTS 8
3157 +static int ports[MAX_PORTS];
3158 +static int ports_c = 0;
3159 +static unsigned int egg_timeout = 300;
3160 +
3161 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
3162 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
3163 +MODULE_LICENSE("GPL");
3164 +#ifdef MODULE_PARM
3165 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3166 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
3167 +#endif
3168 +
3169 +DECLARE_LOCK(ip_egg_lock);
3170 +struct module *ip_conntrack_egg = THIS_MODULE;
3171 +
3172 +#if 0
3173 +#define DEBUGP printk
3174 +#else
3175 +#define DEBUGP(format, args...)
3176 +#endif
3177 +
3178 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
3179 +/* tries to get the ip_addr and port out of a eggdrop command
3180 +   return value: -1 on failure, 0 on success 
3181 +   data                pointer to first byte of DCC command data
3182 +   data_end    pointer to last byte of dcc command data
3183 +   ip          returns parsed ip of dcc command
3184 +   port                returns parsed port of dcc command */
3185 +{
3186 +       if (data > data_end)
3187 +               return -1;
3188 +       
3189 +       *ip = simple_strtoul(data, &data, 10);
3190 +
3191 +       /* skip blanks between ip and port */
3192 +       while (*data == ' ' && data < data_end)
3193 +               data++;
3194 +
3195 +       *port = simple_strtoul(data, &data, 10);
3196 +       return 0;
3197 +}
3198 +
3199 +
3200 +static int help(const struct iphdr *iph, size_t len,
3201 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
3202 +{
3203 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
3204 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
3205 +       char *data = (char *) tcph + tcph->doff * 4;
3206 +       char *data_limit;
3207 +       u_int32_t tcplen = len - iph->ihl * 4;
3208 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3209 +       int dir = CTINFO2DIR(ctinfo);
3210 +       int bytes_scanned = 0;
3211 +       struct ip_conntrack_expect exp;
3212 +
3213 +       u_int32_t egg_ip;
3214 +       u_int16_t egg_port;
3215 +
3216 +       DEBUGP("entered\n");
3217 +
3218 +       /* If packet is coming from IRC server */
3219 +       if (dir != IP_CT_DIR_REPLY)
3220 +               return NF_ACCEPT;
3221 +
3222 +       /* Until there's been traffic both ways, don't look in packets. */
3223 +       if (ctinfo != IP_CT_ESTABLISHED
3224 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3225 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
3226 +               return NF_ACCEPT;
3227 +       }
3228 +
3229 +       /* Not whole TCP header? */
3230 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
3231 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
3232 +               return NF_ACCEPT;
3233 +       }
3234 +
3235 +       /* Checksum invalid?  Ignore. */
3236 +       /* FIXME: Source route IP option packets --RR */
3237 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3238 +                        csum_partial((char *) tcph, tcplen, 0))) {
3239 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
3240 +                       tcph, tcplen, NIPQUAD(iph->saddr),
3241 +                       NIPQUAD(iph->daddr));
3242 +               return NF_ACCEPT;
3243 +       }
3244 +
3245 +       data_limit = (char *) data + datalen;
3246 +       while (datalen > 5 && bytes_scanned < 128) {
3247 +               if (memcmp(data, "s us ", 5)) {
3248 +                       data++;
3249 +                       datalen--;
3250 +                       bytes_scanned++;
3251 +                       continue;
3252 +               }
3253 +
3254 +               data += 5;
3255 +
3256 +               DEBUGP("Userfile-share found in connection "
3257 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
3258 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
3259 +
3260 +               if (parse_command((char *) data, data_limit, &egg_ip,
3261 +                                 &egg_port)) {
3262 +                       DEBUGP("no data in userfile-share pkt\n");
3263 +                       return NF_ACCEPT;
3264 +               }
3265 +
3266 +               memset(&exp, 0, sizeof(exp));
3267 +
3268 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
3269 +                       if (net_ratelimit())
3270 +                               printk("Forged Eggdrop command from "
3271 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
3272 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
3273 +                                      HIPQUAD(egg_ip), egg_port);
3274 +                       return NF_ACCEPT;
3275 +               }
3276 +
3277 +               exp.tuple.src.ip = iph->daddr;
3278 +               exp.tuple.src.u.tcp.port = 0;
3279 +               exp.tuple.dst.ip = htonl(egg_ip);
3280 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
3281 +               exp.tuple.dst.protonum = IPPROTO_TCP;
3282 +
3283 +               exp.mask.dst.u.tcp.port = 0xffff;
3284 +               exp.mask.dst.protonum = 0xffff;
3285 +
3286 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
3287 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
3288 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
3289 +
3290 +               ip_conntrack_expect_related(ct, &exp);
3291 +               break;
3292 +       }
3293 +       return NF_ACCEPT;
3294 +}
3295 +
3296 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
3297 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
3298 +
3299 +static void deregister_helpers(void) {
3300 +       int i;
3301 +       
3302 +       for (i = 0; i < ports_c; i++) {
3303 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
3304 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
3305 +       }
3306 +}
3307 +
3308 +static int __init init(void)
3309 +{
3310 +       int i, ret;
3311 +       char *tmpname;
3312 +
3313 +       /* If no port given, default to standard eggdrop port */
3314 +       if (ports[0] == 0)
3315 +               ports[0] = 3333;
3316 +
3317 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3318 +               memset(&egg_helpers[i], 0,
3319 +                      sizeof(struct ip_conntrack_helper));
3320 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
3321 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
3322 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
3323 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
3324 +               egg_helpers[i].max_expected = 1;
3325 +               egg_helpers[i].timeout = egg_timeout;
3326 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3327 +               egg_helpers[i].me = THIS_MODULE;
3328 +               egg_helpers[i].help = help;
3329 +
3330 +               tmpname = &egg_names[i][0];
3331 +               if (ports[i] == 3333)
3332 +                       sprintf(tmpname, "eggdrop");
3333 +               else
3334 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
3335 +               egg_helpers[i].name = tmpname;
3336 +
3337 +               DEBUGP("port #%d: %d\n", i, ports[i]);
3338 +
3339 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
3340 +
3341 +               if (ret) {
3342 +                       printk("ip_conntrack_egg: ERROR registering helper "
3343 +                               "for port %d\n", ports[i]);
3344 +                       deregister_helpers();
3345 +                       return 1;
3346 +               }
3347 +               ports_c++;
3348 +       }
3349 +       return 0;
3350 +}
3351 +
3352 +static void __exit fini(void)
3353 +{
3354 +       deregister_helpers();
3355 +}
3356 +
3357 +module_init(init);
3358 +module_exit(fini);
3359 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c
3360 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_h323.c  1970-01-01 01:00:00.000000000 +0100
3361 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_h323.c      2004-04-30 09:12:34.000000000 +0200
3362 @@ -0,0 +1,308 @@
3363 +/* 
3364 + * H.323 'brute force' extension for H.323 connection tracking. 
3365 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3366 + *
3367 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
3368 + * (http://www.coritel.it/projects/sofia/nat/)
3369 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
3370 + * the unregistered helpers to the conntrack entries.
3371 + */
3372 +
3373 +
3374 +#include <linux/module.h>
3375 +#include <linux/netfilter.h>
3376 +#include <linux/ip.h>
3377 +#include <net/checksum.h>
3378 +#include <net/tcp.h>
3379 +
3380 +#include <linux/netfilter_ipv4/lockhelp.h>
3381 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3382 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
3383 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3384 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
3385 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
3386 +
3387 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3388 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
3389 +MODULE_LICENSE("GPL");
3390 +
3391 +DECLARE_LOCK(ip_h323_lock);
3392 +struct module *ip_conntrack_h323 = THIS_MODULE;
3393 +
3394 +#if 0
3395 +#define DEBUGP printk
3396 +#else
3397 +#define DEBUGP(format, args...)
3398 +#endif
3399 +
3400 +/* FIXME: This should be in userspace.  Later. */
3401 +static int h245_help(const struct iphdr *iph, size_t len,
3402 +                    struct ip_conntrack *ct,
3403 +                    enum ip_conntrack_info ctinfo)
3404 +{
3405 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3406 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3407 +       unsigned char *data_limit;
3408 +       u_int32_t tcplen = len - iph->ihl * 4;
3409 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3410 +       int dir = CTINFO2DIR(ctinfo);
3411 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3412 +       struct ip_conntrack_expect expect, *exp = &expect;
3413 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3414 +       u_int16_t data_port;
3415 +       u_int32_t data_ip;
3416 +       unsigned int i;
3417 +
3418 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3419 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3420 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3421 +
3422 +       /* Can't track connections formed before we registered */
3423 +       if (!info)
3424 +               return NF_ACCEPT;
3425 +               
3426 +       /* Until there's been traffic both ways, don't look in packets. */
3427 +       if (ctinfo != IP_CT_ESTABLISHED
3428 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3429 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
3430 +               return NF_ACCEPT;
3431 +       }
3432 +
3433 +       /* Not whole TCP header or too short packet? */
3434 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3435 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
3436 +               return NF_ACCEPT;
3437 +       }
3438 +
3439 +       /* Checksum invalid?  Ignore. */
3440 +       /* FIXME: Source route IP option packets --RR */
3441 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3442 +                             csum_partial((char *)tcph, tcplen, 0))) {
3443 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3444 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3445 +                      NIPQUAD(iph->daddr));
3446 +               return NF_ACCEPT;
3447 +       }
3448 +
3449 +       data_limit = (unsigned char *) data + datalen;
3450 +       /* bytes: 0123   45
3451 +                 ipadrr port */
3452 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3453 +               data_ip = *((u_int32_t *)data);
3454 +               if (data_ip == iph->saddr) {
3455 +                       data_port = *((u_int16_t *)(data + 4));
3456 +                       memset(&expect, 0, sizeof(expect));
3457 +                       /* update the H.225 info */
3458 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
3459 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3460 +                               NIPQUAD(iph->saddr), ntohs(data_port));
3461 +                       LOCK_BH(&ip_h323_lock);
3462 +                       info->is_h225 = H225_PORT + 1;
3463 +                       exp_info->port = data_port;
3464 +                       exp_info->dir = dir;
3465 +                       exp_info->offset = i;
3466 +
3467 +                       exp->seq = ntohl(tcph->seq) + i;
3468 +                   
3469 +                       exp->tuple = ((struct ip_conntrack_tuple)
3470 +                               { { ct->tuplehash[!dir].tuple.src.ip,
3471 +                                   { 0 } },
3472 +                                 { data_ip,
3473 +                                   { .tcp = { data_port } },
3474 +                                   IPPROTO_UDP }});
3475 +                       exp->mask = ((struct ip_conntrack_tuple)
3476 +                               { { 0xFFFFFFFF, { 0 } },
3477 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3478 +       
3479 +                       exp->expectfn = NULL;
3480 +                       
3481 +                       /* Ignore failure; should only happen with NAT */
3482 +                       ip_conntrack_expect_related(ct, exp);
3483 +
3484 +                       UNLOCK_BH(&ip_h323_lock);
3485 +               }
3486 +       }
3487 +
3488 +       return NF_ACCEPT;
3489 +
3490 +}
3491 +
3492 +/* H.245 helper is not registered! */
3493 +static struct ip_conntrack_helper h245 = 
3494 +       { { NULL, NULL },
3495 +          "H.245",                             /* name */
3496 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
3497 +          NULL,                                        /* module */
3498 +          8,                                   /* max_ expected */
3499 +          240,                                 /* timeout */
3500 +          { { 0, { 0 } },                      /* tuple */
3501 +            { 0, { 0 }, IPPROTO_TCP } },
3502 +          { { 0, { 0xFFFF } },                 /* mask */
3503 +            { 0, { 0 }, 0xFFFF } },
3504 +          h245_help                            /* helper */
3505 +       };
3506 +
3507 +static int h225_expect(struct ip_conntrack *ct)
3508 +{
3509 +       WRITE_LOCK(&ip_conntrack_lock);
3510 +       ct->helper = &h245;
3511 +       DEBUGP("h225_expect: helper for %p added\n", ct);
3512 +       WRITE_UNLOCK(&ip_conntrack_lock);
3513 +       
3514 +       return NF_ACCEPT;       /* unused */
3515 +}
3516 +
3517 +/* FIXME: This should be in userspace.  Later. */
3518 +static int h225_help(const struct iphdr *iph, size_t len,
3519 +                    struct ip_conntrack *ct,
3520 +                    enum ip_conntrack_info ctinfo)
3521 +{
3522 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3523 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
3524 +       unsigned char *data_limit;
3525 +       u_int32_t tcplen = len - iph->ihl * 4;
3526 +       u_int32_t datalen = tcplen - tcph->doff * 4;
3527 +       int dir = CTINFO2DIR(ctinfo);
3528 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
3529 +       struct ip_conntrack_expect expect, *exp = &expect;
3530 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
3531 +       u_int16_t data_port;
3532 +       u_int32_t data_ip;
3533 +       unsigned int i;
3534 +       
3535 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
3536 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
3537 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
3538 +
3539 +       /* Can't track connections formed before we registered */
3540 +       if (!info)
3541 +               return NF_ACCEPT;
3542 +
3543 +       /* Until there's been traffic both ways, don't look in packets. */
3544 +       if (ctinfo != IP_CT_ESTABLISHED
3545 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
3546 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
3547 +               return NF_ACCEPT;
3548 +       }
3549 +
3550 +       /* Not whole TCP header or too short packet? */
3551 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
3552 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
3553 +               return NF_ACCEPT;
3554 +       }
3555 +
3556 +       /* Checksum invalid?  Ignore. */
3557 +       /* FIXME: Source route IP option packets --RR */
3558 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3559 +                             csum_partial((char *)tcph, tcplen, 0))) {
3560 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3561 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3562 +                      NIPQUAD(iph->daddr));
3563 +               return NF_ACCEPT;
3564 +       }
3565 +       
3566 +       data_limit = (unsigned char *) data + datalen;
3567 +       /* bytes: 0123   45
3568 +                 ipadrr port */
3569 +       for (i = 0; data < (data_limit - 5); data++, i++) {
3570 +               data_ip = *((u_int32_t *)data);
3571 +               if (data_ip == iph->saddr) {
3572 +                       data_port = *((u_int16_t *)(data + 4));
3573 +                       if (data_port == tcph->source) {
3574 +                               /* Signal address */
3575 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
3576 +                                       NIPQUAD(iph->saddr));
3577 +                               /* Update the H.225 info so that NAT can mangle the address/port
3578 +                                  even when we have no expected connection! */
3579 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3580 +                               LOCK_BH(&ip_h323_lock);
3581 +                               info->dir = dir;
3582 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
3583 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
3584 +                               UNLOCK_BH(&ip_h323_lock);
3585 +#endif
3586 +                       } else {
3587 +                               memset(&expect, 0, sizeof(expect));
3588 +
3589 +                               /* update the H.225 info */
3590 +                               LOCK_BH(&ip_h323_lock);
3591 +                               info->is_h225 = H225_PORT;
3592 +                               exp_info->port = data_port;
3593 +                               exp_info->dir = dir;
3594 +                               exp_info->offset = i;
3595 +
3596 +                               exp->seq = ntohl(tcph->seq) + i;
3597 +
3598 +                               exp->tuple = ((struct ip_conntrack_tuple)
3599 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
3600 +                                           { 0 } },
3601 +                                         { data_ip,
3602 +                                           { .tcp = { data_port } },
3603 +                                           IPPROTO_TCP }});
3604 +                               exp->mask = ((struct ip_conntrack_tuple)
3605 +                                       { { 0xFFFFFFFF, { 0 } },
3606 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3607 +       
3608 +                               exp->expectfn = h225_expect;
3609 +                               
3610 +                               /* Ignore failure */
3611 +                               ip_conntrack_expect_related(ct, exp);
3612 +
3613 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
3614 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3615 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
3616 +
3617 +                               UNLOCK_BH(&ip_h323_lock);
3618 +                       }  
3619 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3620 +               } else if (data_ip == iph->daddr) {
3621 +                       data_port = *((u_int16_t *)(data + 4));
3622 +                       if (data_port == tcph->dest) {
3623 +                               /* Signal address */
3624 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
3625 +                                       NIPQUAD(iph->daddr));
3626 +                               /* Update the H.225 info so that NAT can mangle the address/port
3627 +                                  even when we have no expected connection! */
3628 +                               LOCK_BH(&ip_h323_lock);
3629 +                               info->dir = dir;
3630 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
3631 +                               info->offset[IP_CT_DIR_REPLY] = i;
3632 +                               UNLOCK_BH(&ip_h323_lock);
3633 +                       }
3634 +#endif
3635 +               }
3636 +       }
3637 +
3638 +       return NF_ACCEPT;
3639 +
3640 +}
3641 +
3642 +static struct ip_conntrack_helper h225 = 
3643 +       { { NULL, NULL },
3644 +         "H.225",                                      /* name */
3645 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
3646 +         THIS_MODULE,                                  /* module */
3647 +         2,                                            /* max_expected */
3648 +         240,                                          /* timeout */
3649 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
3650 +           { 0, { 0 }, IPPROTO_TCP } },
3651 +         { { 0, { 0xFFFF } },                          /* mask */
3652 +           { 0, { 0 }, 0xFFFF } },
3653 +         h225_help                                     /* helper */
3654 +       };
3655 +
3656 +static int __init init(void)
3657 +{
3658 +       return ip_conntrack_helper_register(&h225);
3659 +}
3660 +
3661 +static void __exit fini(void)
3662 +{
3663 +       /* Unregister H.225 helper */   
3664 +       ip_conntrack_helper_unregister(&h225);
3665 +}
3666 +
3667 +EXPORT_SYMBOL(ip_h323_lock);
3668 +
3669 +module_init(init);
3670 +module_exit(fini);
3671 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c
3672 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_mms.c   1970-01-01 01:00:00.000000000 +0100
3673 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_mms.c       2004-04-30 09:12:58.000000000 +0200
3674 @@ -0,0 +1,308 @@
3675 +/* MMS extension for IP connection tracking
3676 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
3677 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
3678 + *
3679 + * ip_conntrack_mms.c v0.3 2002-09-22
3680 + *
3681 + *      This program is free software; you can redistribute it and/or
3682 + *      modify it under the terms of the GNU General Public License
3683 + *      as published by the Free Software Foundation; either version
3684 + *      2 of the License, or (at your option) any later version.
3685 + *
3686 + *      Module load syntax:
3687 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
3688 + *
3689 + *      Please give the ports of all MMS servers You wish to connect to.
3690 + *      If you don't specify ports, the default will be TCP port 1755.
3691 + *
3692 + *      More info on MMS protocol, firewalls and NAT:
3693 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
3694 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
3695 + *
3696 + *      The SDP project people are reverse-engineering MMS:
3697 + *      http://get.to/sdp
3698 + */
3699 +
3700 +#include <linux/config.h>
3701 +#include <linux/module.h>
3702 +#include <linux/netfilter.h>
3703 +#include <linux/ip.h>
3704 +#include <linux/ctype.h>
3705 +#include <net/checksum.h>
3706 +#include <net/tcp.h>
3707 +
3708 +#include <linux/netfilter_ipv4/lockhelp.h>
3709 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
3710 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
3711 +
3712 +DECLARE_LOCK(ip_mms_lock);
3713 +struct module *ip_conntrack_mms = THIS_MODULE;
3714 +
3715 +#define MAX_PORTS 8
3716 +static int ports[MAX_PORTS];
3717 +static int ports_c;
3718 +#ifdef MODULE_PARM
3719 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
3720 +#endif
3721 +
3722 +#if 0 
3723 +#define DEBUGP printk
3724 +#else
3725 +#define DEBUGP(format, args...)
3726 +#endif
3727 +
3728 +EXPORT_SYMBOL(ip_mms_lock);
3729 +
3730 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
3731 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
3732 +MODULE_LICENSE("GPL");
3733 +
3734 +/* #define isdigit(c) (c >= '0' && c <= '9') */
3735 +
3736 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
3737 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
3738 +{
3739 +       int i;
3740 +       for (i = 0; i < unicode_size; ++i) {
3741 +               string[i] = (char)(unicode[i]);
3742 +       }
3743 +       string[unicode_size] = 0x00;
3744 +}
3745 +
3746 +__inline static int atoi(char *s) 
3747 +{
3748 +       int i=0;
3749 +       while (isdigit(*s)) {
3750 +               i = i*10 + *(s++) - '0';
3751 +       }
3752 +       return i;
3753 +}
3754 +
3755 +/* convert ip address string like "192.168.0.10" to unsigned int */
3756 +__inline static u_int32_t asciiiptoi(char *s)
3757 +{
3758 +       unsigned int i, j, k;
3759 +
3760 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
3761 +               i+=atoi(s);
3762 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
3763 +                       ;
3764 +       }
3765 +       i+=atoi(s);
3766 +       return ntohl(i);
3767 +}
3768 +
3769 +int parse_mms(const char *data, 
3770 +             const unsigned int datalen,
3771 +             u_int32_t *mms_ip,
3772 +             u_int16_t *mms_proto,
3773 +             u_int16_t *mms_port,
3774 +             char **mms_string_b,
3775 +             char **mms_string_e,
3776 +             char **mms_padding_e)
3777 +{
3778 +       int unicode_size, i;
3779 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
3780 +       char getlengthstring[28];
3781 +       
3782 +       for(unicode_size=0; 
3783 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
3784 +           unicode_size++)
3785 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
3786 +                       return -1; /* out of bounds - incomplete packet */
3787 +       
3788 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
3789 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
3790 +       
3791 +       /* IP address ? */
3792 +       *mms_ip = asciiiptoi(tempstring+2);
3793 +       
3794 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
3795 +               
3796 +       /* protocol ? */
3797 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
3798 +               *mms_proto = IPPROTO_TCP;
3799 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
3800 +               *mms_proto = IPPROTO_UDP;
3801 +
3802 +       /* port ? */
3803 +       *mms_port = atoi(tempstring+7+i);
3804 +
3805 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
3806 +          unicode string, one to the end of the string, and one to the end 
3807 +          of the packet, since we must keep track of the number of bytes 
3808 +          between end of the unicode string and the end of packet (padding) */
3809 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
3810 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
3811 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
3812 +       return 0;
3813 +}
3814 +
3815 +
3816 +/* FIXME: This should be in userspace.  Later. */
3817 +static int help(const struct iphdr *iph, size_t len,
3818 +               struct ip_conntrack *ct,
3819 +               enum ip_conntrack_info ctinfo)
3820 +{
3821 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
3822 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
3823 +       const char *data = (const char *)tcph + tcph->doff * 4;
3824 +       unsigned int tcplen = len - iph->ihl * 4;
3825 +       unsigned int datalen = tcplen - tcph->doff * 4;
3826 +       int dir = CTINFO2DIR(ctinfo);
3827 +       struct ip_conntrack_expect expect, *exp = &expect; 
3828 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
3829 +       
3830 +       u_int32_t mms_ip;
3831 +       u_int16_t mms_proto;
3832 +       char mms_proto_string[8];
3833 +       u_int16_t mms_port;
3834 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
3835 +            
3836 +       /* Until there's been traffic both ways, don't look in packets. */
3837 +       if (ctinfo != IP_CT_ESTABLISHED
3838 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
3839 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
3840 +               return NF_ACCEPT;
3841 +       }
3842 +
3843 +       /* Not whole TCP header? */
3844 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
3845 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
3846 +               return NF_ACCEPT;
3847 +       }
3848 +
3849 +       /* Checksum invalid?  Ignore. */
3850 +       /* FIXME: Source route IP option packets --RR */
3851 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
3852 +           csum_partial((char *)tcph, tcplen, 0))) {
3853 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
3854 +                      tcph, tcplen, NIPQUAD(iph->saddr),
3855 +                      NIPQUAD(iph->daddr));
3856 +               return NF_ACCEPT;
3857 +       }
3858 +       
3859 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
3860 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
3861 +          the client has already sent a packet to the server with the server's hostname 
3862 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
3863 +          server will break the connection if this doesn't correspond to its own host 
3864 +          header. The client can also connect to an IP address; if it's the server's IP
3865 +          address, it will not break the connection. When doing DNAT on a connection 
3866 +          where the client uses a server's IP address, the nat module should detect
3867 +          this and change this string accordingly to the DNATed address. This should
3868 +          probably be done by checking for an IP address, then storing it as a member
3869 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
3870 +          */
3871 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
3872 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
3873 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
3874 +                      (u8)*(data+36), (u8)*(data+37), 
3875 +                      (u8)*(data+38), (u8)*(data+39),
3876 +                      datalen);
3877 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
3878 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
3879 +                       if(net_ratelimit())
3880 +                               /* FIXME: more verbose debugging ? */
3881 +                               printk(KERN_WARNING
3882 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
3883 +
3884 +               memset(&expect, 0, sizeof(expect));
3885 +
3886 +               sprintf(mms_proto_string, "(%u)", mms_proto);
3887 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
3888 +                      mms_proto == IPPROTO_TCP ? "TCP"
3889 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
3890 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
3891 +                      NIPQUAD(mms_ip),
3892 +                      mms_port);
3893 +               
3894 +               /* it's possible that the client will just ask the server to tunnel
3895 +                  the stream over the same TCP session (from port 1755): there's 
3896 +                  shouldn't be a need to add an expectation in that case, but it
3897 +                  makes NAT packet mangling so much easier */
3898 +               LOCK_BH(&ip_mms_lock);
3899 +
3900 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
3901 +               
3902 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
3903 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
3904 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
3905 +               exp_mms_info->port    = mms_port;
3906 +               
3907 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
3908 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
3909 +               
3910 +               exp->tuple = ((struct ip_conntrack_tuple)
3911 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
3912 +                             { mms_ip,
3913 +                               { .tcp = { (__u16) ntohs(mms_port) } },
3914 +                               mms_proto } }
3915 +                            );
3916 +               exp->mask  = ((struct ip_conntrack_tuple)
3917 +                            { { 0xFFFFFFFF, { 0 } },
3918 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
3919 +               exp->expectfn = NULL;
3920 +               ip_conntrack_expect_related(ct, &expect);
3921 +               UNLOCK_BH(&ip_mms_lock);
3922 +       }
3923 +
3924 +       return NF_ACCEPT;
3925 +}
3926 +
3927 +static struct ip_conntrack_helper mms[MAX_PORTS];
3928 +static char mms_names[MAX_PORTS][10];
3929 +
3930 +/* Not __exit: called from init() */
3931 +static void fini(void)
3932 +{
3933 +       int i;
3934 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3935 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
3936 +                               ports[i]);
3937 +               ip_conntrack_helper_unregister(&mms[i]);
3938 +       }
3939 +}
3940 +
3941 +static int __init init(void)
3942 +{
3943 +       int i, ret;
3944 +       char *tmpname;
3945 +
3946 +       if (ports[0] == 0)
3947 +               ports[0] = MMS_PORT;
3948 +
3949 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
3950 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
3951 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
3952 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
3953 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
3954 +               mms[i].mask.dst.protonum = 0xFFFF;
3955 +               mms[i].max_expected = 1;
3956 +               mms[i].timeout = 0;
3957 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
3958 +               mms[i].me = THIS_MODULE;
3959 +               mms[i].help = help;
3960 +
3961 +               tmpname = &mms_names[i][0];
3962 +               if (ports[i] == MMS_PORT)
3963 +                       sprintf(tmpname, "mms");
3964 +               else
3965 +                       sprintf(tmpname, "mms-%d", ports[i]);
3966 +               mms[i].name = tmpname;
3967 +
3968 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
3969 +                               ports[i]);
3970 +               ret = ip_conntrack_helper_register(&mms[i]);
3971 +
3972 +               if (ret) {
3973 +                       fini();
3974 +                       return ret;
3975 +               }
3976 +               ports_c++;
3977 +       }
3978 +       return 0;
3979 +}
3980 +
3981 +module_init(init);
3982 +module_exit(fini);
3983 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
3984 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_proto_sctp.c    1970-01-01 01:00:00.000000000 +0100
3985 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_proto_sctp.c        2004-04-30 09:14:08.000000000 +0200
3986 @@ -0,0 +1,529 @@
3987 +/*
3988 + * Connection tracking protocol helper module for SCTP.
3989 + * 
3990 + * SCTP is defined in RFC 2960. References to various sections in this code 
3991 + * are to this RFC.
3992 + * 
3993 + * This program is free software; you can redistribute it and/or modify
3994 + * it under the terms of the GNU General Public License version 2 as
3995 + * published by the Free Software Foundation.
3996 + */
3997 +
3998 +#include <linux/types.h>
3999 +#include <linux/sched.h>
4000 +#include <linux/timer.h>
4001 +#include <linux/netfilter.h>
4002 +#include <linux/module.h>
4003 +#include <linux/in.h>
4004 +#include <linux/ip.h>
4005 +#include <linux/sctp.h>
4006 +#include <linux/string.h>
4007 +
4008 +#include <linux/netfilter_ipv4/ip_conntrack.h>
4009 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
4010 +#include <linux/netfilter_ipv4/lockhelp.h>
4011 +
4012 +#if 0
4013 +#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
4014 +#else
4015 +#define DEBUGP(format, args...)
4016 +#endif
4017 +
4018 +/* Protects conntrack->proto.sctp */
4019 +static DECLARE_RWLOCK(sctp_lock);
4020 +
4021 +/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
4022 +   closely.  They're more complex. --RR 
4023 +
4024 +   And so for me for SCTP :D -Kiran */
4025 +
4026 +static const char *sctp_conntrack_names[] = {
4027 +       "NONE",
4028 +       "CLOSED",
4029 +       "COOKIE_WAIT",
4030 +       "COOKIE_ECHOED",
4031 +       "ESTABLISHED",
4032 +       "SHUTDOWN_SENT",
4033 +       "SHUTDOWN_RECD",
4034 +       "SHUTDOWN_ACK_SENT",
4035 +};
4036 +
4037 +#define SECS  * HZ
4038 +#define MINS  * 60 SECS
4039 +#define HOURS * 60 MINS
4040 +#define DAYS  * 24 HOURS
4041 +
4042 +unsigned long ip_ct_sctp_timeout_closed            =  10 SECS;
4043 +unsigned long ip_ct_sctp_timeout_cookie_wait       =   3 SECS;
4044 +unsigned long ip_ct_sctp_timeout_cookie_echoed     =   3 SECS;
4045 +unsigned long ip_ct_sctp_timeout_established       =   5 DAYS;
4046 +unsigned long ip_ct_sctp_timeout_shutdown_sent     = 300 SECS / 1000;
4047 +unsigned long ip_ct_sctp_timeout_shutdown_recd     = 300 SECS / 1000;
4048 +unsigned long ip_ct_sctp_timeout_shutdown_ack_sent =   3 SECS;
4049 +
4050 +static unsigned long * sctp_timeouts[]
4051 += { 0,                                     /* SCTP_CONNTRACK_NONE  */
4052 +    &ip_ct_sctp_timeout_closed,                   /* SCTP_CONNTRACK_CLOSED */
4053 +    &ip_ct_sctp_timeout_cookie_wait,       /* SCTP_CONNTRACK_COOKIE_WAIT */
4054 +    &ip_ct_sctp_timeout_cookie_echoed,     /* SCTP_CONNTRACK_COOKIE_ECHOED */
4055 +    &ip_ct_sctp_timeout_established,       /* SCTP_CONNTRACK_ESTABLISHED */
4056 +    &ip_ct_sctp_timeout_shutdown_sent,     /* SCTP_CONNTRACK_SHUTDOWN_SENT */
4057 +    &ip_ct_sctp_timeout_shutdown_recd,     /* SCTP_CONNTRACK_SHUTDOWN_RECD */
4058 +    &ip_ct_sctp_timeout_shutdown_ack_sent  /* SCTP_CONNTRACK_SHUTDOWN_ACK_SENT */
4059 + };
4060 +
4061 +#define sNO SCTP_CONNTRACK_NONE
4062 +#define        sCL SCTP_CONNTRACK_CLOSED
4063 +#define        sCW SCTP_CONNTRACK_COOKIE_WAIT
4064 +#define        sCE SCTP_CONNTRACK_COOKIE_ECHOED
4065 +#define        sES SCTP_CONNTRACK_ESTABLISHED
4066 +#define        sSS SCTP_CONNTRACK_SHUTDOWN_SENT
4067 +#define        sSR SCTP_CONNTRACK_SHUTDOWN_RECD
4068 +#define        sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
4069 +#define        sIV SCTP_CONNTRACK_MAX
4070 +
4071 +/* 
4072 +       These are the descriptions of the states:
4073 +
4074 +NOTE: These state names are tantalizingly similar to the states of an 
4075 +SCTP endpoint. But the interpretation of the states is a little different,
4076 +considering that these are the states of the connection and not of an end 
4077 +point. Please note the subtleties. -Kiran
4078 +
4079 +NONE              - Nothing so far.
4080 +COOKIE WAIT       - We have seen an INIT chunk in the original direction, or also 
4081 +                    an INIT_ACK chunk in the reply direction.
4082 +COOKIE ECHOED     - We have seen a COOKIE_ECHO chunk in the original direction.
4083 +ESTABLISHED       - We have seen a COOKIE_ACK in the reply direction.
4084 +SHUTDOWN_SENT     - We have seen a SHUTDOWN chunk in the original direction.
4085 +SHUTDOWN_RECD     - We have seen a SHUTDOWN chunk in the reply directoin.
4086 +SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
4087 +                    to that of the SHUTDOWN chunk.
4088 +CLOSED            - We have seen a SHUTDOWN_COMPLETE chunk in the direction of 
4089 +                    the SHUTDOWN chunk. Connection is closed.
4090 +*/
4091 +
4092 +/* TODO
4093 + - I have assumed that the first INIT is in the original direction. 
4094 + This messes things when an INIT comes in the reply direction in CLOSED
4095 + state.
4096 + - Check the error type in the reply dir before transitioning from 
4097 +cookie echoed to closed.
4098 + - Sec 5.2.4 of RFC 2960
4099 + - Multi Homing support.
4100 +*/
4101 +
4102 +/* SCTP conntrack state transitions */
4103 +static enum sctp_conntrack sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
4104 +       {
4105 +/*     ORIGINAL        */
4106 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4107 +/* init         */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
4108 +/* init_ack     */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4109 +/* abort        */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4110 +/* shutdown     */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
4111 +/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4112 +/* error        */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
4113 +/* cookie_echo  */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
4114 +/* cookie_ack   */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
4115 +/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4116 +       },
4117 +       {
4118 +/*     REPLY   */
4119 +/*                  sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
4120 +/* init         */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
4121 +/* init_ack     */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
4122 +/* abort        */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
4123 +/* shutdown     */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
4124 +/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
4125 +/* error        */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
4126 +/* cookie_echo  */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
4127 +/* cookie_ack   */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
4128 +/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
4129 +       }
4130 +};
4131 +
4132 +static int sctp_pkt_to_tuple(const struct sk_buff *skb,
4133 +                            unsigned int dataoff,
4134 +                            struct ip_conntrack_tuple *tuple)
4135 +{
4136 +       sctp_sctphdr_t hdr;
4137 +
4138 +       DEBUGP(__FUNCTION__);
4139 +       DEBUGP("\n");
4140 +
4141 +       /* Actually only need first 8 bytes. */
4142 +       if (skb_copy_bits(skb, dataoff, &hdr, 8) != 0)
4143 +               return 0;
4144 +
4145 +       tuple->src.u.sctp.port = hdr.source;
4146 +       tuple->dst.u.sctp.port = hdr.dest;
4147 +
4148 +       return 1;
4149 +}
4150 +
4151 +static int sctp_invert_tuple(struct ip_conntrack_tuple *tuple,
4152 +                            const struct ip_conntrack_tuple *orig)
4153 +{
4154 +       DEBUGP(__FUNCTION__);
4155 +       DEBUGP("\n");
4156 +
4157 +       tuple->src.u.sctp.port = orig->dst.u.sctp.port;
4158 +       tuple->dst.u.sctp.port = orig->src.u.sctp.port;
4159 +       return 1;
4160 +}
4161 +
4162 +/* Print out the per-protocol part of the tuple. */
4163 +static unsigned int sctp_print_tuple(char *buffer,
4164 +                                    const struct ip_conntrack_tuple *tuple)
4165 +{
4166 +       DEBUGP(__FUNCTION__);
4167 +       DEBUGP("\n");
4168 +
4169 +       return sprintf(buffer, "sport=%hu dport=%hu ",
4170 +                      ntohs(tuple->src.u.sctp.port),
4171 +                      ntohs(tuple->dst.u.sctp.port));
4172 +}
4173 +
4174 +/* Print out the private part of the conntrack. */
4175 +static unsigned int sctp_print_conntrack(char *buffer,
4176 +                                        const struct ip_conntrack *conntrack)
4177 +{
4178 +       enum sctp_conntrack state;
4179 +
4180 +       DEBUGP(__FUNCTION__);
4181 +       DEBUGP("\n");
4182 +
4183 +       READ_LOCK(&sctp_lock);
4184 +       state = conntrack->proto.sctp.state;
4185 +       READ_UNLOCK(&sctp_lock);
4186 +
4187 +       return sprintf(buffer, "%s ", sctp_conntrack_names[state]);
4188 +}
4189 +
4190 +#define for_each_sctp_chunk(skb, sch, offset, count)   \
4191 +for (offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t), count = 0;       \
4192 +       offset < skb->len && !skb_copy_bits(skb, offset, &sch, sizeof(sch));    \
4193 +       offset += (htons(sch.length) + 3) & ~3, count++)
4194 +
4195 +/* Some validity checks to make sure the chunks are fine */
4196 +static int do_basic_checks(struct ip_conntrack *conntrack,
4197 +                          const struct sk_buff *skb,
4198 +                          char *map)
4199 +{
4200 +       u_int32_t offset, count;
4201 +       sctp_chunkhdr_t sch;
4202 +       int flag;
4203 +
4204 +       DEBUGP(__FUNCTION__);
4205 +       DEBUGP("\n");
4206 +
4207 +       flag = 0;
4208 +
4209 +       for_each_sctp_chunk (skb, sch, offset, count) {
4210 +               DEBUGP("Chunk Num: %d  Type: %d\n", count, sch.type);
4211 +
4212 +               if (sch.type == SCTP_CID_INIT 
4213 +                       || sch.type == SCTP_CID_INIT_ACK
4214 +                       || sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4215 +                       flag = 1;
4216 +               }
4217 +
4218 +               /* Cookie Ack/Echo chunks not the first OR 
4219 +                  Init / Init Ack / Shutdown compl chunks not the only chunks */
4220 +               if ((sch.type == SCTP_CID_COOKIE_ACK 
4221 +                       || sch.type == SCTP_CID_COOKIE_ECHO
4222 +                       || flag)
4223 +                    && count !=0 ) {
4224 +                       DEBUGP("Basic checks failed\n");
4225 +                       return 1;
4226 +               }
4227 +
4228 +               if (map) {
4229 +                       set_bit (sch.type, (void *)map);
4230 +               }
4231 +       }
4232 +
4233 +       DEBUGP("Basic checks passed\n");
4234 +       return 0;
4235 +}
4236 +
4237 +static int new_state(enum ip_conntrack_dir dir,
4238 +                    enum sctp_conntrack cur_state,
4239 +                    int chunk_type)
4240 +{
4241 +       int i;
4242 +
4243 +       DEBUGP(__FUNCTION__);
4244 +       DEBUGP("\n");
4245 +
4246 +       DEBUGP("Chunk type: %d\n", chunk_type);
4247 +
4248 +       switch (chunk_type) {
4249 +               case SCTP_CID_INIT: 
4250 +                       DEBUGP("SCTP_CID_INIT\n");
4251 +                       i = 0; break;
4252 +               case SCTP_CID_INIT_ACK: 
4253 +                       DEBUGP("SCTP_CID_INIT_ACK\n");
4254 +                       i = 1; break;
4255 +               case SCTP_CID_ABORT: 
4256 +                       DEBUGP("SCTP_CID_ABORT\n");
4257 +                       i = 2; break;
4258 +               case SCTP_CID_SHUTDOWN: 
4259 +                       DEBUGP("SCTP_CID_SHUTDOWN\n");
4260 +                       i = 3; break;
4261 +               case SCTP_CID_SHUTDOWN_ACK: 
4262 +                       DEBUGP("SCTP_CID_SHUTDOWN_ACK\n");
4263 +                       i = 4; break;
4264 +               case SCTP_CID_ERROR: 
4265 +                       DEBUGP("SCTP_CID_ERROR\n");
4266 +                       i = 5; break;
4267 +               case SCTP_CID_COOKIE_ECHO: 
4268 +                       DEBUGP("SCTP_CID_COOKIE_ECHO\n");
4269 +                       i = 6; break;
4270 +               case SCTP_CID_COOKIE_ACK: 
4271 +                       DEBUGP("SCTP_CID_COOKIE_ACK\n");
4272 +                       i = 7; break;
4273 +               case SCTP_CID_SHUTDOWN_COMPLETE: 
4274 +                       DEBUGP("SCTP_CID_SHUTDOWN_COMPLETE\n");
4275 +                       i = 8; break;
4276 +               default:
4277 +                       /* Other chunks like DATA, SACK, HEARTBEAT and
4278 +                       its ACK do not cause a change in state */
4279 +                       DEBUGP("Unknown chunk type, Will stay in %s\n", 
4280 +                                               sctp_conntrack_names[cur_state]);
4281 +                       return cur_state;
4282 +       }
4283 +
4284 +       DEBUGP("dir: %d   cur_state: %s  chunk_type: %d  new_state: %s\n", 
4285 +                       dir, sctp_conntrack_names[cur_state], chunk_type,
4286 +                       sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
4287 +
4288 +       return sctp_conntracks[dir][i][cur_state];
4289 +}
4290 +
4291 +/* Returns verdict for packet, or -1 for invalid. */
4292 +static int sctp_packet(struct ip_conntrack *conntrack,
4293 +                      const struct sk_buff *skb,
4294 +                      enum ip_conntrack_info ctinfo)
4295 +{
4296 +       enum sctp_conntrack newconntrack, oldsctpstate;
4297 +       sctp_sctphdr_t sctph;
4298 +       sctp_chunkhdr_t sch;
4299 +       u_int32_t offset, count;
4300 +       char map[256 / sizeof (char)] = {0};
4301 +
4302 +       DEBUGP(__FUNCTION__);
4303 +       DEBUGP("\n");
4304 +
4305 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4306 +               return -1;
4307 +
4308 +       if (do_basic_checks(conntrack, skb, map) != 0)
4309 +               return -1;
4310 +
4311 +       /* Check the verification tag (Sec 8.5) */
4312 +       if (!test_bit(SCTP_CID_INIT, (void *)map)
4313 +               && !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, (void *)map)
4314 +               && !test_bit(SCTP_CID_COOKIE_ECHO, (void *)map)
4315 +               && !test_bit(SCTP_CID_ABORT, (void *)map)
4316 +               && !test_bit(SCTP_CID_SHUTDOWN_ACK, (void *)map)
4317 +               && (sctph.vtag != conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4318 +               DEBUGP("Verification tag check failed\n");
4319 +               return -1;
4320 +       }
4321 +
4322 +       oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
4323 +       for_each_sctp_chunk (skb, sch, offset, count) {
4324 +               WRITE_LOCK(&sctp_lock);
4325 +
4326 +               /* Special cases of Verification tag check (Sec 8.5.1) */
4327 +               if (sch.type == SCTP_CID_INIT) {
4328 +                       /* Sec 8.5.1 (A) */
4329 +                       if (sctph.vtag != 0) {
4330 +                               WRITE_UNLOCK(&sctp_lock);
4331 +                               return -1;
4332 +                       }
4333 +               } else if (sch.type == SCTP_CID_ABORT) {
4334 +                       /* Sec 8.5.1 (B) */
4335 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4336 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4337 +                                                       [1 - CTINFO2DIR(ctinfo)])) {
4338 +                               WRITE_UNLOCK(&sctp_lock);
4339 +                               return -1;
4340 +                       }
4341 +               } else if (sch.type == SCTP_CID_SHUTDOWN_COMPLETE) {
4342 +                       /* Sec 8.5.1 (C) */
4343 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
4344 +                               && !(sctph.vtag == conntrack->proto.sctp.vtag
4345 +                                                       [1 - CTINFO2DIR(ctinfo)] 
4346 +                                       && (sch.flags & 1))) {
4347 +                               WRITE_UNLOCK(&sctp_lock);
4348 +                               return -1;
4349 +                       }
4350 +               } else if (sch.type == SCTP_CID_COOKIE_ECHO) {
4351 +                       /* Sec 8.5.1 (D) */
4352 +                       if (!(sctph.vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
4353 +                               WRITE_UNLOCK(&sctp_lock);
4354 +                               return -1;
4355 +                       }
4356 +               }
4357 +
4358 +               oldsctpstate = conntrack->proto.sctp.state;
4359 +               newconntrack = new_state(CTINFO2DIR(ctinfo), oldsctpstate, sch.type);
4360 +
4361 +               /* Invalid */
4362 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4363 +                       DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
4364 +                              CTINFO2DIR(ctinfo), sch.type, oldsctpstate);
4365 +                       WRITE_UNLOCK(&sctp_lock);
4366 +                       return -1;
4367 +               }
4368 +
4369 +               /* If it is an INIT or an INIT ACK note down the vtag */
4370 +               if (sch.type == SCTP_CID_INIT 
4371 +                       || sch.type == SCTP_CID_INIT_ACK) {
4372 +                       sctp_inithdr_t inithdr;
4373 +
4374 +                       if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t),
4375 +                               &inithdr, sizeof(inithdr)) != 0) {
4376 +                                       WRITE_UNLOCK(&sctp_lock);
4377 +                                       return -1;
4378 +                       }
4379 +                       DEBUGP("Setting vtag %x for dir %d\n", 
4380 +                                       inithdr.init_tag, CTINFO2DIR(ctinfo));
4381 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = inithdr.init_tag;
4382 +               }
4383 +
4384 +               conntrack->proto.sctp.state = newconntrack;
4385 +               WRITE_UNLOCK(&sctp_lock);
4386 +       }
4387 +
4388 +       ip_ct_refresh(conntrack, *sctp_timeouts[newconntrack]);
4389 +
4390 +       if (oldsctpstate == SCTP_CONNTRACK_COOKIE_ECHOED
4391 +               && CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY
4392 +               && newconntrack == SCTP_CONNTRACK_ESTABLISHED) {
4393 +               DEBUGP("Setting assured bit\n");
4394 +               set_bit(IPS_ASSURED_BIT, &conntrack->status);
4395 +       }
4396 +
4397 +       return NF_ACCEPT;
4398 +}
4399 +
4400 +/* Called when a new connection for this protocol found. */
4401 +static int sctp_new(struct ip_conntrack *conntrack, 
4402 +                   const struct sk_buff *skb)
4403 +{
4404 +       enum sctp_conntrack newconntrack;
4405 +       sctp_sctphdr_t sctph;
4406 +       sctp_chunkhdr_t sch;
4407 +       u_int32_t offset, count;
4408 +       char map[256 / sizeof (char)] = {0};
4409 +
4410 +       DEBUGP(__FUNCTION__);
4411 +       DEBUGP("\n");
4412 +
4413 +       if (skb_copy_bits(skb, skb->nh.iph->ihl * 4, &sctph, sizeof(sctph)) != 0)
4414 +               return -1;
4415 +
4416 +       if (do_basic_checks(conntrack, skb, map) != 0)
4417 +               return -1;
4418 +
4419 +       /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
4420 +       if ((test_bit (SCTP_CID_ABORT, (void *)map))
4421 +               || (test_bit (SCTP_CID_SHUTDOWN_COMPLETE, (void *)map))
4422 +               || (test_bit (SCTP_CID_COOKIE_ACK, (void *)map))) {
4423 +               return -1;
4424 +       }
4425 +
4426 +       newconntrack = SCTP_CONNTRACK_MAX;
4427 +       for_each_sctp_chunk (skb, sch, offset, count) {
4428 +               /* Don't need lock here: this conntrack not in circulation yet */
4429 +               newconntrack = new_state (IP_CT_DIR_ORIGINAL, 
4430 +                                               SCTP_CONNTRACK_NONE, sch.type);
4431 +
4432 +               /* Invalid: delete conntrack */
4433 +               if (newconntrack == SCTP_CONNTRACK_MAX) {
4434 +                       DEBUGP("ip_conntrack_sctp: invalid new deleting.\n");
4435 +                       return 0;
4436 +               }
4437 +
4438 +               /* Copy the vtag into the state info */
4439 +               if (sch.type == SCTP_CID_INIT) {
4440 +                       if (sctph.vtag == 0) {
4441 +                               sctp_inithdr_t inithdr;
4442 +
4443 +                               if (skb_copy_bits(skb, offset + sizeof (sctp_chunkhdr_t), 
4444 +                                       &inithdr, sizeof(inithdr)) != 0) {
4445 +                                               return -1;
4446 +                               }
4447 +
4448 +                               DEBUGP("Setting vtag %x for new conn\n", 
4449 +                                       inithdr.init_tag);
4450 +
4451 +                               conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = 
4452 +                                                               inithdr.init_tag;
4453 +                       } else {
4454 +                               /* Sec 8.5.1 (A) */
4455 +                               return -1;
4456 +                       }
4457 +               }
4458 +               /* If it is a shutdown ack OOTB packet, we expect a return
4459 +                  shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
4460 +               else {
4461 +                       DEBUGP("Setting vtag %x for new conn OOTB\n", 
4462 +                               sctph.vtag);
4463 +                       conntrack->proto.sctp.vtag[IP_CT_DIR_REPLY] = sctph.vtag;
4464 +               }
4465 +
4466 +               conntrack->proto.sctp.state = newconntrack;
4467 +       }
4468 +
4469 +       return 1;
4470 +}
4471 +
4472 +static int sctp_exp_matches_pkt(struct ip_conntrack_expect *exp,
4473 +                               const struct sk_buff *skb)
4474 +{
4475 +       /* To be implemented */
4476 +       return 0;
4477 +}
4478 +
4479 +struct ip_conntrack_protocol ip_conntrack_protocol_sctp = { 
4480 +       .list            = { NULL, NULL }, 
4481 +       .proto           = IPPROTO_SCTP, 
4482 +       .name            = "sctp",
4483 +       .pkt_to_tuple    = sctp_pkt_to_tuple, 
4484 +       .invert_tuple    = sctp_invert_tuple, 
4485 +       .print_tuple     = sctp_print_tuple, 
4486 +       .print_conntrack = sctp_print_conntrack,
4487 +       .packet          = sctp_packet, 
4488 +       .new             = sctp_new, 
4489 +       .destroy         = NULL, 
4490 +       .exp_matches_pkt = sctp_exp_matches_pkt, 
4491 +       .me              = THIS_MODULE 
4492 +};
4493 +
4494 +int __init init(void)
4495 +{
4496 +       int ret;
4497 +
4498 +       ret = ip_conntrack_protocol_register(&ip_conntrack_protocol_sctp);
4499 +       DEBUGP("SCTP conntrack module loading %s\n", 
4500 +                                       ret ? "failed": "succeeded");
4501 +       return ret;
4502 +}
4503 +
4504 +void __exit fini(void)
4505 +{
4506 +       ip_conntrack_protocol_unregister(&ip_conntrack_protocol_sctp);
4507 +       DEBUGP("SCTP conntrack module unloaded\n");
4508 +}
4509 +
4510 +module_init(init);
4511 +module_exit(fini);
4512 +
4513 +MODULE_LICENSE("GPL");
4514 +MODULE_AUTHOR("Kiran Kumar Immidi");
4515 +MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
4516 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c
4517 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_quake3.c        1970-01-01 01:00:00.000000000 +0100
4518 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_quake3.c    2004-04-30 09:13:29.000000000 +0200
4519 @@ -0,0 +1,156 @@
4520 +/* Quake3 extension for IP connection tracking
4521 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
4522 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
4523 + *
4524 + * ip_conntrack_quake3.c v0.04 2002-08-31
4525 + *
4526 + *      This program is free software; you can redistribute it and/or
4527 + *      modify it under the terms of the GNU General Public License
4528 + *      as published by the Free Software Foundation; either version
4529 + *      2 of the License, or (at your option) any later version.
4530 + *
4531 + *      Module load syntax:
4532 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
4533 + *
4534 + *      please give the ports of all Quake3 master servers You wish to 
4535 + *      connect to. If you don't specify ports, the default will be UDP 
4536 + *      port 27950.
4537 + *
4538 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
4539 + */
4540 +
4541 +#include <linux/module.h>
4542 +#include <linux/ip.h>
4543 +#include <linux/udp.h>
4544 +
4545 +#include <linux/netfilter.h>
4546 +#include <linux/netfilter_ipv4/ip_tables.h>
4547 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4548 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
4549 +
4550 +struct module *ip_conntrack_quake3 = THIS_MODULE;
4551 +
4552 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
4553 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
4554 +MODULE_LICENSE("GPL");
4555 +
4556 +#define MAX_PORTS 8
4557 +static int ports[MAX_PORTS];
4558 +static int ports_c = 0;
4559 +#ifdef MODULE_PARM
4560 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4561 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
4562 +#endif
4563 +
4564 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
4565 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
4566 +#if 0 
4567 +#define DEBUGP printk
4568 +#else
4569 +#define DEBUGP(format, args...)
4570 +#endif
4571 +
4572 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
4573 +
4574 +static int quake3_help(const struct iphdr *iph, size_t len,
4575 +       struct ip_conntrack *ct,
4576 +       enum ip_conntrack_info ctinfo)
4577 +{
4578 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
4579 +       int dir = CTINFO2DIR(ctinfo);
4580 +       struct ip_conntrack_expect exp;
4581 +       int i;
4582 +       
4583 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
4584 +       if (ctinfo != IP_CT_ESTABLISHED
4585 +           && ctinfo != IP_CT_IS_REPLY) {
4586 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
4587 +               return NF_ACCEPT;
4588 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
4589 +       
4590 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
4591 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
4592 +                   i+6 < ntohs(udph->len);
4593 +                   i+=7) {
4594 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
4595 +                              i, ntohs(udph->len),
4596 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
4597 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
4598 +
4599 +                       memset(&exp, 0, sizeof(exp));
4600 +
4601 +                       exp.tuple = ((struct ip_conntrack_tuple)
4602 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
4603 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
4604 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
4605 +                                        IPPROTO_UDP } }
4606 +                                   );
4607 +                       exp.mask  = ((struct ip_conntrack_tuple)
4608 +                                    { { 0xFFFFFFFF, { 0 } },
4609 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
4610 +                       exp.expectfn = NULL;
4611 +
4612 +                       ip_conntrack_expect_related(ct, &exp);
4613 +               }
4614 +
4615 +       }
4616 +       
4617 +       return(NF_ACCEPT);
4618 +}
4619 +
4620 +static struct ip_conntrack_helper quake3[MAX_PORTS];
4621 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
4622 +
4623 +static void fini(void)
4624 +{
4625 +       int i;
4626 +
4627 +       for(i = 0 ; (i < ports_c); i++) {
4628 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
4629 +                                       ports[i]);
4630 +               ip_conntrack_helper_unregister(&quake3[i]);
4631 +       } 
4632 +}
4633 +
4634 +static int __init init(void)
4635 +{
4636 +       int i, ret;
4637 +       char *tmpname;
4638 +
4639 +       if(!ports[0])
4640 +               ports[0]=QUAKE3_MASTER_PORT;
4641 +
4642 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
4643 +               /* Create helper structure */
4644 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
4645 +
4646 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
4647 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
4648 +               quake3[i].mask.dst.protonum = 0xFFFF;
4649 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
4650 +               quake3[i].help = quake3_help;
4651 +               quake3[i].me = THIS_MODULE;
4652 +
4653 +               tmpname = &quake3_names[i][0];
4654 +               if (ports[i] == QUAKE3_MASTER_PORT)
4655 +                       sprintf(tmpname, "quake3");
4656 +               else
4657 +                       sprintf(tmpname, "quake3-%d", i);
4658 +               quake3[i].name = tmpname;
4659 +               
4660 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
4661 +                      ports[i]);
4662 +
4663 +               ret=ip_conntrack_helper_register(&quake3[i]);
4664 +               if(ret) {
4665 +                       fini();
4666 +                       return(ret);
4667 +               }
4668 +               ports_c++;
4669 +       }
4670 +
4671 +       return(0);
4672 +}
4673 +
4674 +module_init(init);
4675 +module_exit(fini);
4676 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c
4677 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rsh.c   1970-01-01 01:00:00.000000000 +0100
4678 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rsh.c       2004-04-30 09:13:59.000000000 +0200
4679 @@ -0,0 +1,331 @@
4680 +/* RSH extension for IP connection tracking, Version 1.0
4681 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
4682 + * based on HW's ip_conntrack_irc.c    
4683 + *
4684 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
4685 + *
4686 + *      This program is free software; you can redistribute it and/or
4687 + *      modify it under the terms of the GNU General Public License
4688 + *      as published by the Free Software Foundation; either version
4689 + *      2 of the License, or (at your option) any later version.
4690 + **
4691 + *     Module load syntax:
4692 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
4693 + *     
4694 + *     please give the ports of all RSH servers You wish to connect to.
4695 + *     If You don't specify ports, the default will be port 514
4696 + **
4697 + *      Note to all:
4698 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
4699 + *        unfortunately I babysit some sysadmins that won't migrate
4700 + *       their legacy crap, in our second tier.
4701 + */
4702 +
4703 +
4704 +/*
4705 + *  Some docco ripped from the net to teach me all there is to know about
4706 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
4707 + *  this module).
4708 + *
4709 + *  I have no idea what "unix rshd man pages" these guys have .. but that
4710 + *  is some pretty detailed docco!
4711 + **
4712 + *
4713 + *  4. Of the rsh protocol.
4714 + *  -----------------------
4715 + * 
4716 + *   The rshd listens on TCP port #514. The following info is from the unix
4717 + *   rshd man pages :
4718 + * 
4719 + *   "Service Request Protocol
4720 + * 
4721 + *    When the rshd daemon receives a service request, it initiates the
4722 + *    following protocol:
4723 + * 
4724 + *     1. The rshd daemon checks the source port number for the request.
4725 + *        If the port number is not in the range 0 through 1023, the rshd daemon
4726 + *        terminates the connection.
4727 + * 
4728 + *     2. The rshd daemon reads characters from the socket up to a null byte.
4729 + *        The string read is interpreted as an ASCII number (base 10). If this
4730 + *        number is nonzero, the rshd daemon interprets it as the port number
4731 + *        of a secondary stream to be used as standard error. A second connection
4732 + *        is created to the specified port on the client host. The source port
4733 + *        on the local host is in the range 0 through 1023.
4734 + * 
4735 + *     3. The rshd daemon uses the source address of the initial connection
4736 + *        request to determine the name of the client host. If the name cannot
4737 + *        be determined, the rshd daemon uses the dotted decimal representation
4738 + *        of the client host's address.
4739 + * 
4740 + *     4. The rshd daemon retrieves the following information from the initial
4741 + *        socket:
4742 + * 
4743 + *         * A null-terminated string of at most 16 bytes interpreted as
4744 + *           the user name of the user on the client host.
4745 + * 
4746 + *         * A null-terminated string of at most 16 bytes interpreted as
4747 + *           the user name to be used on the local server host.
4748 + * 
4749 + *         * Another null-terminated string interpreted as a command line
4750 + *           to be passed to a shell on the local server host.
4751 + * 
4752 + *     5. The rshd daemon attempts to validate the user using the following steps:
4753 + * 
4754 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
4755 + *            file and tries to switch to the home directory (using the chdir
4756 + *            subroutine). If either the lookup or the directory change fails,
4757 + *            the rshd daemon terminates the connection.
4758 + * 
4759 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
4760 + *            the /etc/hosts.equiv file to see if the name of the client
4761 + *            workstation is listed. If the client workstation is listed as an
4762 + *            equivalent host, the rshd daemon validates the user.
4763 + * 
4764 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
4765 + *            authenticate the user by checking the .rhosts file.
4766 + * 
4767 + *         d. If either the $HOME/.rhosts authentication fails or the
4768 + *            client host is not an equivalent host, the rshd daemon
4769 + *            terminates the connection.
4770 + * 
4771 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
4772 + *        on the initial connection and passes the command line to the user's
4773 + *        local login shell. The shell then inherits the network connections
4774 + *        established by the rshd daemon."
4775 + * 
4776 + */
4777 +
4778 +
4779 +#include <linux/module.h>
4780 +#include <linux/netfilter.h>
4781 +#include <linux/ip.h>
4782 +#include <net/checksum.h>
4783 +#include <net/tcp.h>
4784 +
4785 +#include <linux/netfilter_ipv4/lockhelp.h>
4786 +#include <linux/netfilter_ipv4/ip_tables.h>
4787 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4788 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
4789 +
4790 +#define MAX_PORTS 8
4791 +static int ports[MAX_PORTS];
4792 +static int ports_n_c = 0;
4793 +
4794 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
4795 +MODULE_DESCRIPTION("RSH connection tracking module");
4796 +MODULE_LICENSE("GPL");
4797 +#ifdef MODULE_PARM
4798 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
4799 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
4800 +#endif
4801 +
4802 +DECLARE_LOCK(ip_rsh_lock);
4803 +struct module *ip_conntrack_rsh = THIS_MODULE;
4804 +
4805 +#if 0
4806 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
4807 +                                       format, ## args)
4808 +#else
4809 +#define DEBUGP(format, args...)
4810 +#endif
4811 +
4812 +
4813 +
4814 +/* FIXME: This should be in userspace.  Later. */
4815 +static int help(const struct iphdr *iph, size_t len,
4816 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4817 +{
4818 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
4819 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
4820 +       const char *data = (const char *) tcph + tcph->doff * 4;
4821 +       u_int32_t tcplen = len - iph->ihl * 4;
4822 +       int dir = CTINFO2DIR(ctinfo);
4823 +        struct ip_conntrack_expect expect, *exp = &expect;
4824 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
4825 +       u_int16_t port;
4826 +       int maxoctet;
4827 +
4828 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
4829 +        *  original array size used in rshd/glibc) -- is there a
4830 +        *  vulnerability in rshd.c in the looped port *= 10?
4831 +        */
4832 +
4833 +
4834 +       DEBUGP("entered\n");
4835 +
4836 +       /* bail if packet is not from RSH client */
4837 +       if (dir == IP_CT_DIR_REPLY)
4838 +               return NF_ACCEPT;
4839 +
4840 +       /* Until there's been traffic both ways, don't look in packets. */
4841 +       if (ctinfo != IP_CT_ESTABLISHED
4842 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
4843 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
4844 +               return NF_ACCEPT;
4845 +       }
4846 +
4847 +       /* Not whole TCP header? */
4848 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
4849 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
4850 +               return NF_ACCEPT;
4851 +       }
4852 +
4853 +       /* Checksum invalid?  Ignore. */
4854 +       /* FIXME: Source route IP option packets --RR */
4855 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
4856 +                        csum_partial((char *) tcph, tcplen, 0))) {
4857 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
4858 +                    tcph, tcplen, NIPQUAD(iph->saddr),
4859 +                    NIPQUAD(iph->daddr));
4860 +               return NF_ACCEPT;
4861 +       }
4862 +
4863 +       /* find the rsh stderr port */
4864 +       maxoctet = 4;
4865 +       port = 0;
4866 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
4867 +               if (*data < 0)
4868 +                       return(1);
4869 +               if (*data == 0)
4870 +                       break;
4871 +               if (*data < 48 || *data > 57) {
4872 +                       DEBUGP("these aren't the packets you're looking for ..\n");
4873 +                       return NF_ACCEPT;
4874 +               }
4875 +               port = port * 10 + ( *data - 48 );
4876 +       }
4877 +
4878 +       /* dont relate sessions that try to expose the client */
4879 +       DEBUGP("found port %u\n", port);
4880 +       if (port > 1023) {
4881 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
4882 +               return NF_ACCEPT;
4883 +       }
4884 +
4885 +
4886 +       LOCK_BH(&ip_rsh_lock);
4887 +
4888 +       /*  new(,related) connection is;
4889 +        *          reply + dst (uint)port + src port (0:1023)
4890 +        */
4891 +       memset(&expect, 0, sizeof(expect));
4892 +
4893 +       /*  save some discovered data, in case someone ever wants to write
4894 +        *  a NAT module for this bastard ..
4895 +        */
4896 +       exp_rsh_info->port = port;
4897 +
4898 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
4899 +
4900 +
4901 +       /* Watch out, Radioactive-Man! */
4902 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
4903 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
4904 +       exp->tuple.src.u.tcp.port = 0;
4905 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
4906 +       exp->tuple.dst.protonum = IPPROTO_TCP;
4907 +
4908 +       exp->mask.src.ip = 0xffffffff;
4909 +       exp->mask.dst.ip = 0xffffffff;
4910 +
4911 +       exp->mask.src.u.tcp.port = htons(0xfc00);
4912 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
4913 +       exp->mask.dst.protonum = 0xffff;
4914 +
4915 +       exp->expectfn = NULL;
4916 +
4917 +       ip_conntrack_expect_related(ct, &expect);
4918 +
4919 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4920 +               NIPQUAD(exp->tuple.src.ip),
4921 +               ntohs(exp->tuple.src.u.tcp.port),
4922 +               NIPQUAD(exp->tuple.dst.ip),
4923 +               ntohs(exp->tuple.dst.u.tcp.port));
4924 +
4925 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4926 +               NIPQUAD(exp->mask.src.ip),
4927 +               ntohs(exp->mask.src.u.tcp.port),
4928 +               NIPQUAD(exp->mask.dst.ip),
4929 +               ntohs(exp->mask.dst.u.tcp.port));
4930 +       UNLOCK_BH(&ip_rsh_lock);
4931 +
4932 +       return NF_ACCEPT;
4933 +}
4934 +
4935 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
4936 +
4937 +static void fini(void);
4938 +
4939 +static int __init init(void)
4940 +{
4941 +       int port, ret;
4942 +       static char name[10];
4943 +
4944 +
4945 +       /* If no port given, default to standard RSH port */
4946 +       if (ports[0] == 0)
4947 +               ports[0] = RSH_PORT;
4948 +
4949 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
4950 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
4951 +
4952 +                if (ports[port] == RSH_PORT)
4953 +                        sprintf(name, "rsh");
4954 +                else
4955 +                        sprintf(name, "rsh-%d", port);
4956 +
4957 +               rsh_helpers[port].name = name;
4958 +               rsh_helpers[port].me = THIS_MODULE;
4959 +               rsh_helpers[port].max_expected = 1;
4960 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
4961 +               rsh_helpers[port].timeout = 0;
4962 +
4963 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
4964 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
4965 +
4966 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
4967 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
4968 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
4969 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
4970 +
4971 +               rsh_helpers[port].help = help;
4972 +
4973 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
4974 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4975 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
4976 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
4977 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
4978 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
4979 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
4980 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
4981 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
4982 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
4983 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
4984 +
4985 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
4986 +
4987 +               if (ret) {
4988 +                       printk("ERROR registering port %d\n",
4989 +                               ports[port]);
4990 +                       fini();
4991 +                       return -EBUSY;
4992 +               }
4993 +               ports_n_c++;
4994 +       }
4995 +       return 0;
4996 +}
4997 +
4998 +/* This function is intentionally _NOT_ defined as __exit, because 
4999 + * it is needed by the init function */
5000 +static void fini(void)
5001 +{
5002 +       int port;
5003 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
5004 +               DEBUGP("unregistering port %d\n", ports[port]);
5005 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
5006 +       }
5007 +}
5008 +
5009 +module_init(init);
5010 +module_exit(fini);
5011 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c
5012 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_rtsp.c  1970-01-01 01:00:00.000000000 +0100
5013 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_rtsp.c      2004-04-30 09:14:05.000000000 +0200
5014 @@ -0,0 +1,507 @@
5015 +/*
5016 + * RTSP extension for IP connection tracking
5017 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
5018 + * based on ip_conntrack_irc.c
5019 + *
5020 + *      This program is free software; you can redistribute it and/or
5021 + *      modify it under the terms of the GNU General Public License
5022 + *      as published by the Free Software Foundation; either version
5023 + *      2 of the License, or (at your option) any later version.
5024 + *
5025 + * Module load syntax:
5026 + *   insmod ip_conntrack_rtsp.o ports=port1,port2,...port<MAX_PORTS>
5027 + *                              max_outstanding=n setup_timeout=secs
5028 + *
5029 + * If no ports are specified, the default will be port 554.
5030 + *
5031 + * With max_outstanding you can define the maximum number of not yet
5032 + * answered SETUP requests per RTSP session (default 8).
5033 + * With setup_timeout you can specify how long the system waits for
5034 + * an expected data channel (default 300 seconds).
5035 + */
5036 +
5037 +#include <linux/config.h>
5038 +#include <linux/module.h>
5039 +#include <linux/netfilter.h>
5040 +#include <linux/ip.h>
5041 +#include <net/checksum.h>
5042 +#include <net/tcp.h>
5043 +
5044 +#include <linux/netfilter_ipv4/lockhelp.h>
5045 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5046 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
5047 +
5048 +#include <linux/ctype.h>
5049 +#define NF_NEED_STRNCASECMP
5050 +#define NF_NEED_STRTOU16
5051 +#define NF_NEED_STRTOU32
5052 +#define NF_NEED_NEXTLINE
5053 +#include <linux/netfilter_helpers.h>
5054 +#define NF_NEED_MIME_NEXTLINE
5055 +#include <linux/netfilter_mime.h>
5056 +
5057 +#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */
5058 +
5059 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5060 +#ifdef IP_NF_RTSP_DEBUG
5061 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
5062 +#else
5063 +#define DEBUGP(fmt, args...)
5064 +#endif
5065 +
5066 +#define MAX_PORTS 8
5067 +static int ports[MAX_PORTS];
5068 +static int num_ports = 0;
5069 +static int max_outstanding = 8;
5070 +static unsigned int setup_timeout = 300;
5071 +
5072 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
5073 +MODULE_DESCRIPTION("RTSP connection tracking module");
5074 +MODULE_LICENSE("GPL");
5075 +#ifdef MODULE_PARM
5076 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
5077 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
5078 +MODULE_PARM(max_outstanding, "i");
5079 +MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session");
5080 +MODULE_PARM(setup_timeout, "i");
5081 +MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels");
5082 +#endif
5083 +
5084 +DECLARE_LOCK(ip_rtsp_lock);
5085 +struct module* ip_conntrack_rtsp = THIS_MODULE;
5086 +
5087 +/*
5088 + * Max mappings we will allow for one RTSP connection (for RTP, the number
5089 + * of allocated ports is twice this value).  Note that SMIL burns a lot of
5090 + * ports so keep this reasonably high.  If this is too low, you will see a
5091 + * lot of "no free client map entries" messages.
5092 + */
5093 +#define MAX_PORT_MAPS 16
5094 +
5095 +/*** default port list was here in the masq code: 554, 3030, 4040 ***/
5096 +
5097 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
5098 +
5099 +/*
5100 + * Parse an RTSP packet.
5101 + *
5102 + * Returns zero if parsing failed.
5103 + *
5104 + * Parameters:
5105 + *  IN      ptcp        tcp data pointer
5106 + *  IN      tcplen      tcp data len
5107 + *  IN/OUT  ptcpoff     points to current tcp offset
5108 + *  OUT     phdrsoff    set to offset of rtsp headers
5109 + *  OUT     phdrslen    set to length of rtsp headers
5110 + *  OUT     pcseqoff    set to offset of CSeq header
5111 + *  OUT     pcseqlen    set to length of CSeq header
5112 + */
5113 +static int
5114 +rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff,
5115 +                   uint* phdrsoff, uint* phdrslen,
5116 +                   uint* pcseqoff, uint* pcseqlen)
5117 +{
5118 +    uint    entitylen = 0;
5119 +    uint    lineoff;
5120 +    uint    linelen;
5121 +
5122 +    if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5123 +    {
5124 +        return 0;
5125 +    }
5126 +
5127 +    *phdrsoff = *ptcpoff;
5128 +    while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen))
5129 +    {
5130 +        if (linelen == 0)
5131 +        {
5132 +            if (entitylen > 0)
5133 +            {
5134 +                *ptcpoff += min(entitylen, tcplen - *ptcpoff);
5135 +            }
5136 +            break;
5137 +        }
5138 +        if (lineoff+linelen > tcplen)
5139 +        {
5140 +            INFOP("!! overrun !!\n");
5141 +            break;
5142 +        }
5143 +
5144 +        if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0)
5145 +        {
5146 +            *pcseqoff = lineoff;
5147 +            *pcseqlen = linelen;
5148 +        }
5149 +        if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0)
5150 +        {
5151 +            uint off = lineoff+15;
5152 +            SKIP_WSPACE(ptcp+lineoff, linelen, off);
5153 +            nf_strtou32(ptcp+off, &entitylen);
5154 +        }
5155 +    }
5156 +    *phdrslen = (*ptcpoff) - (*phdrsoff);
5157 +
5158 +    return 1;
5159 +}
5160 +
5161 +/*
5162 + * Find lo/hi client ports (if any) in transport header
5163 + * In:
5164 + *   ptcp, tcplen = packet
5165 + *   tranoff, tranlen = buffer to search
5166 + *
5167 + * Out:
5168 + *   pport_lo, pport_hi = lo/hi ports (host endian)
5169 + *
5170 + * Returns nonzero if any client ports found
5171 + *
5172 + * Note: it is valid (and expected) for the client to request multiple
5173 + * transports, so we need to parse the entire line.
5174 + */
5175 +static int
5176 +rtsp_parse_transport(char* ptran, uint tranlen,
5177 +                     struct ip_ct_rtsp_expect* prtspexp)
5178 +{
5179 +    int     rc = 0;
5180 +    uint    off = 0;
5181 +
5182 +    if (tranlen < 10 || !iseol(ptran[tranlen-1]) ||
5183 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
5184 +    {
5185 +        INFOP("sanity check failed\n");
5186 +        return 0;
5187 +    }
5188 +    DEBUGP("tran='%.*s'\n", (int)tranlen, ptran);
5189 +    off += 10;
5190 +    SKIP_WSPACE(ptran, tranlen, off);
5191 +
5192 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
5193 +    while (off < tranlen)
5194 +    {
5195 +        const char* pparamend;
5196 +        uint        nextparamoff;
5197 +
5198 +        pparamend = memchr(ptran+off, ',', tranlen-off);
5199 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
5200 +        nextparamoff = pparamend-ptran;
5201 +
5202 +        while (off < nextparamoff)
5203 +        {
5204 +            const char* pfieldend;
5205 +            uint        nextfieldoff;
5206 +
5207 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
5208 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
5209 +
5210 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
5211 +            {
5212 +                u_int16_t   port;
5213 +                uint        numlen;
5214 +
5215 +                off += 12;
5216 +                numlen = nf_strtou16(ptran+off, &port);
5217 +                off += numlen;
5218 +                if (prtspexp->loport != 0 && prtspexp->loport != port)
5219 +                {
5220 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
5221 +                }
5222 +                else
5223 +                {
5224 +                    prtspexp->loport = prtspexp->hiport = port;
5225 +                    if (ptran[off] == '-')
5226 +                    {
5227 +                        off++;
5228 +                        numlen = nf_strtou16(ptran+off, &port);
5229 +                        off += numlen;
5230 +                        prtspexp->pbtype = pb_range;
5231 +                        prtspexp->hiport = port;
5232 +
5233 +                        // If we have a range, assume rtp:
5234 +                        // loport must be even, hiport must be loport+1
5235 +                        if ((prtspexp->loport & 0x0001) != 0 ||
5236 +                            prtspexp->hiport != prtspexp->loport+1)
5237 +                        {
5238 +                            DEBUGP("incorrect range: %hu-%hu, correcting\n",
5239 +                                   prtspexp->loport, prtspexp->hiport);
5240 +                            prtspexp->loport &= 0xfffe;
5241 +                            prtspexp->hiport = prtspexp->loport+1;
5242 +                        }
5243 +                    }
5244 +                    else if (ptran[off] == '/')
5245 +                    {
5246 +                        off++;
5247 +                        numlen = nf_strtou16(ptran+off, &port);
5248 +                        off += numlen;
5249 +                        prtspexp->pbtype = pb_discon;
5250 +                        prtspexp->hiport = port;
5251 +                    }
5252 +                    rc = 1;
5253 +                }
5254 +            }
5255 +
5256 +            /*
5257 +             * Note we don't look for the destination parameter here.
5258 +             * If we are using NAT, the NAT module will handle it.  If not,
5259 +             * and the client is sending packets elsewhere, the expectation
5260 +             * will quietly time out.
5261 +             */
5262 +
5263 +            off = nextfieldoff;
5264 +        }
5265 +
5266 +        off = nextparamoff;
5267 +    }
5268 +
5269 +    return rc;
5270 +}
5271 +
5272 +/*** conntrack functions ***/
5273 +
5274 +/* outbound packet: client->server */
5275 +static int
5276 +help_out(const struct iphdr* iph, size_t pktlen,
5277 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5278 +{
5279 +    int dir = CTINFO2DIR(ctinfo);   /* = IP_CT_DIR_ORIGINAL */
5280 +    struct  tcphdr* tcph = (void*)iph + iph->ihl * 4;
5281 +    uint    tcplen = pktlen - iph->ihl * 4;
5282 +    char*   pdata = (char*)tcph + tcph->doff * 4;
5283 +    uint    datalen = tcplen - tcph->doff * 4;
5284 +    uint    dataoff = 0;
5285 +
5286 +    struct ip_conntrack_expect exp;
5287 +
5288 +    while (dataoff < datalen)
5289 +    {
5290 +        uint    cmdoff = dataoff;
5291 +        uint    hdrsoff = 0;
5292 +        uint    hdrslen = 0;
5293 +        uint    cseqoff = 0;
5294 +        uint    cseqlen = 0;
5295 +        uint    lineoff = 0;
5296 +        uint    linelen = 0;
5297 +        uint    off;
5298 +        int     rc;
5299 +
5300 +        if (!rtsp_parse_message(pdata, datalen, &dataoff,
5301 +                                &hdrsoff, &hdrslen,
5302 +                                &cseqoff, &cseqlen))
5303 +        {
5304 +            break;      /* not a valid message */
5305 +        }
5306 +
5307 +        if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0)
5308 +        {
5309 +            continue;   /* not a SETUP message */
5310 +        }
5311 +        DEBUGP("found a setup message\n");
5312 +
5313 +        memset(&exp, 0, sizeof(exp));
5314 +
5315 +        off = 0;
5316 +        while (nf_mime_nextline(pdata+hdrsoff, hdrslen, &off,
5317 +                                &lineoff, &linelen))
5318 +        {
5319 +            if (linelen == 0)
5320 +            {
5321 +                break;
5322 +            }
5323 +            if (off > hdrsoff+hdrslen)
5324 +            {
5325 +                INFOP("!! overrun !!");
5326 +                break;
5327 +            }
5328 +
5329 +            if (nf_strncasecmp(pdata+hdrsoff+lineoff, "Transport:", 10) == 0)
5330 +            {
5331 +                rtsp_parse_transport(pdata+hdrsoff+lineoff, linelen,
5332 +                                     &exp.help.exp_rtsp_info);
5333 +            }
5334 +        }
5335 +
5336 +        if (exp.help.exp_rtsp_info.loport == 0)
5337 +        {
5338 +            DEBUGP("no udp transports found\n");
5339 +            continue;   /* no udp transports found */
5340 +        }
5341 +
5342 +        DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n",
5343 +              (int)exp.help.exp_rtsp_info.pbtype,
5344 +              exp.help.exp_rtsp_info.loport,
5345 +              exp.help.exp_rtsp_info.hiport);
5346 +
5347 +        LOCK_BH(&ip_rtsp_lock);
5348 +        exp.seq = ntohl(tcph->seq) + hdrsoff; /* mark all the headers */
5349 +        exp.help.exp_rtsp_info.len = hdrslen;
5350 +
5351 +        exp.tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
5352 +        exp.mask.src.ip  = 0xffffffff;
5353 +        exp.tuple.dst.ip = ct->tuplehash[dir].tuple.src.ip;
5354 +        exp.mask.dst.ip  = 0xffffffff;
5355 +        exp.tuple.dst.u.udp.port = exp.help.exp_rtsp_info.loport;
5356 +        exp.mask.dst.u.udp.port  = (exp.help.exp_rtsp_info.pbtype == pb_range) ? 0xfffe : 0xffff;
5357 +        exp.tuple.dst.protonum = IPPROTO_UDP;
5358 +        exp.mask.dst.protonum  = 0xffff;
5359 +
5360 +        DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
5361 +                NIPQUAD(exp.tuple.src.ip),
5362 +                ntohs(exp.tuple.src.u.tcp.port),
5363 +                NIPQUAD(exp.tuple.dst.ip),
5364 +                ntohs(exp.tuple.dst.u.tcp.port));
5365 +
5366 +        /* pass the request off to the nat helper */
5367 +        rc = ip_conntrack_expect_related(ct, &exp);
5368 +        UNLOCK_BH(&ip_rtsp_lock);
5369 +        if (rc == 0)
5370 +        {
5371 +            DEBUGP("ip_conntrack_expect_related succeeded\n");
5372 +        }
5373 +        else
5374 +        {
5375 +            INFOP("ip_conntrack_expect_related failed (%d)\n", rc);
5376 +        }
5377 +    }
5378 +
5379 +    return NF_ACCEPT;
5380 +}
5381 +
5382 +/* inbound packet: server->client */
5383 +static int
5384 +help_in(const struct iphdr* iph, size_t pktlen,
5385 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5386 +{
5387 +    return NF_ACCEPT;
5388 +}
5389 +
5390 +static int
5391 +help(const struct iphdr* iph, size_t pktlen,
5392 +                struct ip_conntrack* ct, enum ip_conntrack_info ctinfo)
5393 +{
5394 +    /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
5395 +    struct tcphdr* tcph = (void*)iph + iph->ihl * 4;
5396 +    u_int32_t tcplen = pktlen - iph->ihl * 4;
5397 +
5398 +    /* Until there's been traffic both ways, don't look in packets. */
5399 +    if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
5400 +    {
5401 +        DEBUGP("conntrackinfo = %u\n", ctinfo);
5402 +        return NF_ACCEPT;
5403 +    }
5404 +
5405 +    /* Not whole TCP header? */
5406 +    if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4)
5407 +    {
5408 +        DEBUGP("tcplen = %u\n", (unsigned)tcplen);
5409 +        return NF_ACCEPT;
5410 +    }
5411 +
5412 +    /* Checksum invalid?  Ignore. */
5413 +    /* FIXME: Source route IP option packets --RR */
5414 +    if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
5415 +                     csum_partial((char*)tcph, tcplen, 0)))
5416 +    {
5417 +        DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5418 +               tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
5419 +        return NF_ACCEPT;
5420 +    }
5421 +
5422 +    switch (CTINFO2DIR(ctinfo))
5423 +    {
5424 +    case IP_CT_DIR_ORIGINAL:
5425 +        help_out(iph, pktlen, ct, ctinfo);
5426 +        break;
5427 +    case IP_CT_DIR_REPLY:
5428 +        help_in(iph, pktlen, ct, ctinfo);
5429 +        break;
5430 +    }
5431 +
5432 +    return NF_ACCEPT;
5433 +}
5434 +
5435 +static struct ip_conntrack_helper rtsp_helpers[MAX_PORTS];
5436 +static char rtsp_names[MAX_PORTS][10];
5437 +
5438 +/* This function is intentionally _NOT_ defined as __exit */
5439 +static void
5440 +fini(void)
5441 +{
5442 +    int i;
5443 +    for (i = 0; i < num_ports; i++)
5444 +    {
5445 +        DEBUGP("unregistering port %d\n", ports[i]);
5446 +        ip_conntrack_helper_unregister(&rtsp_helpers[i]);
5447 +    }
5448 +}
5449 +
5450 +static int __init
5451 +init(void)
5452 +{
5453 +    int i, ret;
5454 +    struct ip_conntrack_helper *hlpr;
5455 +    char *tmpname;
5456 +
5457 +    printk("ip_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n");
5458 +
5459 +    if (max_outstanding < 1)
5460 +    {
5461 +        printk("ip_conntrack_rtsp: max_outstanding must be a positive integer\n");
5462 +        return -EBUSY;
5463 +    }
5464 +    if (setup_timeout < 0)
5465 +    {
5466 +        printk("ip_conntrack_rtsp: setup_timeout must be a positive integer\n");
5467 +        return -EBUSY;
5468 +    }
5469 +
5470 +    /* If no port given, default to standard rtsp port */
5471 +    if (ports[0] == 0)
5472 +    {
5473 +        ports[0] = RTSP_PORT;
5474 +    }
5475 +
5476 +    for (i = 0; (i < MAX_PORTS) && ports[i]; i++)
5477 +    {
5478 +        hlpr = &rtsp_helpers[i];
5479 +        memset(hlpr, 0, sizeof(struct ip_conntrack_helper));
5480 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
5481 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
5482 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
5483 +        hlpr->mask.dst.protonum = 0xFFFF;
5484 +        hlpr->max_expected = max_outstanding;
5485 +        hlpr->timeout = setup_timeout;
5486 +        hlpr->flags = IP_CT_HELPER_F_REUSE_EXPECT;
5487 +        hlpr->me = ip_conntrack_rtsp;
5488 +        hlpr->help = help;
5489 +
5490 +        tmpname = &rtsp_names[i][0];
5491 +        if (ports[i] == RTSP_PORT)
5492 +        {
5493 +            sprintf(tmpname, "rtsp");
5494 +        }
5495 +        else
5496 +        {
5497 +            sprintf(tmpname, "rtsp-%d", i);
5498 +        }
5499 +        hlpr->name = tmpname;
5500 +
5501 +        DEBUGP("port #%d: %d\n", i, ports[i]);
5502 +
5503 +        ret = ip_conntrack_helper_register(hlpr);
5504 +
5505 +        if (ret)
5506 +        {
5507 +            printk("ip_conntrack_rtsp: ERROR registering port %d\n", ports[i]);
5508 +            fini();
5509 +            return -EBUSY;
5510 +        }
5511 +        num_ports++;
5512 +    }
5513 +    return 0;
5514 +}
5515 +
5516 +#ifdef CONFIG_IP_NF_NAT_NEEDED
5517 +EXPORT_SYMBOL(ip_rtsp_lock);
5518 +#endif
5519 +
5520 +module_init(init);
5521 +module_exit(fini);
5522 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c
5523 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-04-28 03:35:45.000000000 +0200
5524 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-04-30 09:12:41.000000000 +0200
5525 @@ -110,6 +110,9 @@
5526                 len += sprintf(buffer + len, "[ASSURED] ");
5527         len += sprintf(buffer + len, "use=%u ",
5528                        atomic_read(&conntrack->ct_general.use));
5529 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
5530 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
5531 +#endif
5532         len += sprintf(buffer + len, "\n");
5533  
5534         return len;
5535 @@ -633,6 +636,7 @@
5536  EXPORT_SYMBOL(ip_conntrack_alter_reply);
5537  EXPORT_SYMBOL(ip_conntrack_destroyed);
5538  EXPORT_SYMBOL(ip_conntrack_get);
5539 +EXPORT_SYMBOL(__ip_conntrack_confirm);
5540  EXPORT_SYMBOL(need_ip_conntrack);
5541  EXPORT_SYMBOL(ip_conntrack_helper_register);
5542  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
5543 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c
5544 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_conntrack_talk.c  1970-01-01 01:00:00.000000000 +0100
5545 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_conntrack_talk.c      2004-04-30 09:14:39.000000000 +0200
5546 @@ -0,0 +1,360 @@
5547 +/* 
5548 + * talk extension for IP connection tracking. 
5549 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5550 + *
5551 + *      This program is free software; you can redistribute it and/or
5552 + *      modify it under the terms of the GNU General Public License
5553 + *      as published by the Free Software Foundation; either version
5554 + *      2 of the License, or (at your option) any later version.
5555 + **
5556 + *     Module load syntax:
5557 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
5558 + *
5559 + *             talk=[0|1]      disable|enable old talk support
5560 + *            ntalk=[0|1]      disable|enable ntalk support
5561 + *           ntalk2=[0|1]      disable|enable ntalk2 support
5562 + *
5563 + *     The default is talk=1 ntalk=1 ntalk2=1
5564 + *
5565 + *     The helper does not support simultaneous talk requests.
5566 + **
5567 + *
5568 + *             ASCII art on talk protocols
5569 + *     
5570 + *     
5571 + *     caller server               callee server
5572 + *             |     \           /
5573 + *             |       \       /
5574 + *             |         \   /
5575 + *             |           /  
5576 + *             |         /   \
5577 + *           2 |     1 /       \ 3
5578 + *     caller client  ----------- callee client
5579 + *                              4
5580 + *
5581 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
5582 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
5583 + *     3. callee client <-> caller server: LOOK_UP invitation
5584 + *     4. callee client <-> caller client: talk data channel
5585 + *
5586 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
5587 + *      draft-hunter-talk-00.txt
5588 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
5589 + */
5590 +#include <linux/config.h>
5591 +#include <linux/module.h>
5592 +#include <linux/netfilter.h>
5593 +#include <linux/ip.h>
5594 +#include <net/checksum.h>
5595 +#include <net/udp.h>
5596 +
5597 +#include <linux/netfilter_ipv4/lockhelp.h>
5598 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5599 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5600 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5601 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
5602 +
5603 +/* Default all talk protocols are supported */
5604 +static int talk = 1;
5605 +static int ntalk = 1;
5606 +static int ntalk2 = 1;
5607 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5608 +MODULE_DESCRIPTION("talk connection tracking module");
5609 +MODULE_LICENSE("GPL");
5610 +#ifdef MODULE_PARM
5611 +MODULE_PARM(talk, "i");
5612 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
5613 +MODULE_PARM(ntalk, "i");
5614 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
5615 +MODULE_PARM(ntalk2, "i");
5616 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
5617 +#endif
5618 +
5619 +DECLARE_LOCK(ip_talk_lock);
5620 +struct module *ip_conntrack_talk = THIS_MODULE;
5621 +
5622 +#if 0
5623 +#define DEBUGP printk
5624 +#else
5625 +#define DEBUGP(format, args...)
5626 +#endif
5627 +
5628 +static int talk_expect(struct ip_conntrack *ct);
5629 +static int ntalk_expect(struct ip_conntrack *ct);
5630 +
5631 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
5632 +
5633 +static int talk_help_response(const struct iphdr *iph, size_t len,
5634 +                             struct ip_conntrack *ct,
5635 +                             enum ip_conntrack_info ctinfo,
5636 +                             int talk_port,
5637 +                             u_char mode,
5638 +                             u_char type,
5639 +                             u_char answer,
5640 +                             struct talk_addr *addr)
5641 +{
5642 +       int dir = CTINFO2DIR(ctinfo);
5643 +       struct ip_conntrack_expect expect, *exp = &expect;
5644 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
5645 +
5646 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
5647 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
5648 +               type, answer);
5649 +
5650 +       if (!(answer == SUCCESS && type == mode))
5651 +               return NF_ACCEPT;
5652 +       
5653 +       memset(&expect, 0, sizeof(expect));
5654 +       
5655 +       if (type == ANNOUNCE) {
5656 +
5657 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
5658 +
5659 +               /* update the talk info */
5660 +               LOCK_BH(&ip_talk_lock);
5661 +               exp_talk_info->port = htons(talk_port);
5662 +
5663 +               /* expect callee client -> caller server message */
5664 +               exp->tuple = ((struct ip_conntrack_tuple)
5665 +                       { { ct->tuplehash[dir].tuple.src.ip,
5666 +                           { 0 } },
5667 +                         { ct->tuplehash[dir].tuple.dst.ip,
5668 +                           { .tcp = { htons(talk_port) } },
5669 +                           IPPROTO_UDP }});
5670 +               exp->mask = ((struct ip_conntrack_tuple)
5671 +                       { { 0xFFFFFFFF, { 0 } },
5672 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
5673 +               
5674 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
5675 +
5676 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
5677 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
5678 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
5679 +
5680 +               /* Ignore failure; should only happen with NAT */
5681 +               ip_conntrack_expect_related(ct, &expect);
5682 +               UNLOCK_BH(&ip_talk_lock);
5683 +       }
5684 +       if (type == LOOK_UP) {
5685 +
5686 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
5687 +
5688 +               /* update the talk info */
5689 +               LOCK_BH(&ip_talk_lock);
5690 +               exp_talk_info->port = addr->ta_port;
5691 +
5692 +               /* expect callee client -> caller client connection */
5693 +               exp->tuple = ((struct ip_conntrack_tuple)
5694 +                       { { ct->tuplehash[!dir].tuple.src.ip,
5695 +                           { 0 } },
5696 +                         { addr->ta_addr,
5697 +                           { addr->ta_port },
5698 +                           IPPROTO_TCP }});
5699 +               exp->mask = ((struct ip_conntrack_tuple)
5700 +                       { { 0xFFFFFFFF, { 0 } },
5701 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5702 +               
5703 +               exp->expectfn = NULL;
5704 +               
5705 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
5706 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
5707 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
5708 +
5709 +               /* Ignore failure; should only happen with NAT */
5710 +               ip_conntrack_expect_related(ct, &expect);
5711 +               UNLOCK_BH(&ip_talk_lock);
5712 +       }
5713 +                   
5714 +       return NF_ACCEPT;
5715 +}
5716 +
5717 +/* FIXME: This should be in userspace.  Later. */
5718 +static int talk_help(const struct iphdr *iph, size_t len,
5719 +                    struct ip_conntrack *ct,
5720 +                    enum ip_conntrack_info ctinfo,
5721 +                    int talk_port,
5722 +                    u_char mode)
5723 +{
5724 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
5725 +       const char *data = (const char *)udph + sizeof(struct udphdr);
5726 +       int dir = CTINFO2DIR(ctinfo);
5727 +       size_t udplen;
5728 +
5729 +       DEBUGP("ip_ct_talk_help: help entered\n");
5730 +
5731 +       /* Until there's been traffic both ways, don't look in packets. */
5732 +       if (ctinfo != IP_CT_ESTABLISHED
5733 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
5734 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
5735 +               return NF_ACCEPT;
5736 +       }
5737 +
5738 +       /* Not whole UDP header? */
5739 +       udplen = len - iph->ihl * 4;
5740 +       if (udplen < sizeof(struct udphdr)) {
5741 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
5742 +               return NF_ACCEPT;
5743 +       }
5744 +
5745 +       /* Checksum invalid?  Ignore. */
5746 +       /* FIXME: Source route IP option packets --RR */
5747 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5748 +                             csum_partial((char *)udph, udplen, 0))) {
5749 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
5750 +                      udph, udplen, NIPQUAD(iph->saddr),
5751 +                      NIPQUAD(iph->daddr));
5752 +               return NF_ACCEPT;
5753 +       }
5754 +       
5755 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
5756 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
5757 +
5758 +       if (dir == IP_CT_DIR_ORIGINAL)
5759 +               return NF_ACCEPT;
5760 +               
5761 +       if (talk_port == TALK_PORT
5762 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
5763 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5764 +                                         ((struct talk_response *)data)->type, 
5765 +                                         ((struct talk_response *)data)->answer,
5766 +                                         &(((struct talk_response *)data)->addr));
5767 +       else if (talk_port == NTALK_PORT
5768 +                 && ntalk
5769 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
5770 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
5771 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5772 +                                         ((struct ntalk_response *)data)->type, 
5773 +                                         ((struct ntalk_response *)data)->answer,
5774 +                                         &(((struct ntalk_response *)data)->addr));
5775 +       else if (talk_port == NTALK_PORT
5776 +                && ntalk2
5777 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
5778 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
5779 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
5780 +                                         ((struct ntalk2_response *)data)->type, 
5781 +                                         ((struct ntalk2_response *)data)->answer,
5782 +                                         &(((struct ntalk2_response *)data)->addr));
5783 +       else {
5784 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
5785 +                      (unsigned)udplen - sizeof(struct udphdr), 
5786 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
5787 +               return NF_ACCEPT;
5788 +       }
5789 +}
5790 +
5791 +static int lookup_help(const struct iphdr *iph, size_t len,
5792 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5793 +{
5794 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
5795 +}
5796 +
5797 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
5798 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5799 +{
5800 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
5801 +}
5802 +
5803 +static struct ip_conntrack_helper lookup_helpers[2] = 
5804 +       { { { NULL, NULL },
5805 +           "talk",                                     /* name */
5806 +           0,                                          /* flags */
5807 +           NULL,                                       /* module */
5808 +           1,                                          /* max_expected */
5809 +           240,                                        /* timeout */
5810 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
5811 +             { 0, { 0 }, IPPROTO_UDP } },
5812 +           { { 0, { 0xFFFF } },                        /* mask */
5813 +             { 0, { 0 }, 0xFFFF } },
5814 +           lookup_help },                              /* helper */
5815 +          { { NULL, NULL },
5816 +            "ntalk",                                   /* name */
5817 +           0,                                          /* flags */
5818 +           NULL,                                       /* module */
5819 +           1,                                          /* max_expected */
5820 +           240,                                        /* timeout */
5821 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
5822 +             { 0, { 0 }, IPPROTO_UDP } },
5823 +           { { 0, { 0xFFFF } },                        /* mask */
5824 +             { 0, { 0 }, 0xFFFF } },
5825 +           lookup_nhelp }                              /* helper */
5826 +        };
5827 +
5828 +static int talk_expect(struct ip_conntrack *ct)
5829 +{
5830 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
5831 +       WRITE_LOCK(&ip_conntrack_lock);
5832 +       ct->helper = &lookup_helpers[0];
5833 +       WRITE_UNLOCK(&ip_conntrack_lock);
5834 +        
5835 +       return NF_ACCEPT;       /* unused */
5836 +}
5837 +
5838 +static int ntalk_expect(struct ip_conntrack *ct)
5839 +{
5840 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
5841 +       WRITE_LOCK(&ip_conntrack_lock);
5842 +       ct->helper = &lookup_helpers[1];
5843 +       WRITE_UNLOCK(&ip_conntrack_lock);
5844 +        
5845 +       return NF_ACCEPT;       /* unused */
5846 +}
5847 +
5848 +static int help(const struct iphdr *iph, size_t len,
5849 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5850 +{
5851 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
5852 +}
5853 +
5854 +static int nhelp(const struct iphdr *iph, size_t len,
5855 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
5856 +{
5857 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
5858 +}
5859 +
5860 +static struct ip_conntrack_helper talk_helpers[2] = 
5861 +       { { { NULL, NULL },
5862 +           "talk",                                     /* name */
5863 +           0,                                          /* flags */
5864 +           THIS_MODULE,                                /* module */
5865 +           1,                                          /* max_expected */
5866 +           240,                                        /* timeout */
5867 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
5868 +             { 0, { 0 }, IPPROTO_UDP } },
5869 +           { { 0, { 0xFFFF } },                        /* mask */
5870 +             { 0, { 0 }, 0xFFFF } },
5871 +           help },                                     /* helper */
5872 +          { { NULL, NULL },
5873 +           "ntalk",                                    /* name */
5874 +           0,                                          /* flags */
5875 +           THIS_MODULE,                                /* module */
5876 +           1,                                          /* max_expected */
5877 +           240,                                        /* timeout */
5878 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
5879 +             { 0, { 0 }, IPPROTO_UDP } },
5880 +           { { 0, { 0xFFFF } },                        /* mask */
5881 +             { 0, { 0 }, 0xFFFF } },
5882 +           nhelp }                                     /* helper */
5883 +       };
5884 +
5885 +static int __init init(void)
5886 +{
5887 +       if (talk > 0)
5888 +               ip_conntrack_helper_register(&talk_helpers[0]);
5889 +       if (ntalk > 0 || ntalk2 > 0)
5890 +               ip_conntrack_helper_register(&talk_helpers[1]);
5891 +               
5892 +       return 0;
5893 +}
5894 +
5895 +static void __exit fini(void)
5896 +{
5897 +       if (talk > 0)
5898 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
5899 +       if (ntalk > 0 || ntalk2 > 0)
5900 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
5901 +}
5902 +
5903 +EXPORT_SYMBOL(ip_talk_lock);
5904 +
5905 +module_init(init);
5906 +module_exit(fini);
5907 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c
5908 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_core.c        2004-04-28 03:35:10.000000000 +0200
5909 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_core.c    2004-04-30 09:09:25.000000000 +0200
5910 @@ -816,7 +816,7 @@
5911  
5912                 /* Have to grab read lock before sibling_list traversal */
5913                 READ_LOCK(&ip_conntrack_lock);
5914 -               list_for_each(cur_item, &ct->sibling_list) { 
5915 +               list_for_each_prev(cur_item, &ct->sibling_list) { 
5916                         exp = list_entry(cur_item, struct ip_conntrack_expect, 
5917                                          expected_list);
5918                                          
5919 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c
5920 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_h323.c        1970-01-01 01:00:00.000000000 +0100
5921 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_h323.c    2004-04-30 09:12:34.000000000 +0200
5922 @@ -0,0 +1,419 @@
5923 +/* 
5924 + * H.323 'brute force' extension for NAT alteration. 
5925 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5926 + *
5927 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
5928 + * (http://www.coritel.it/projects/sofia/nat.html)
5929 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
5930 + * the unregistered helpers to the conntrack entries.
5931 + */
5932 +
5933 +
5934 +#include <linux/module.h>
5935 +#include <linux/netfilter.h>
5936 +#include <linux/ip.h>
5937 +#include <net/checksum.h>
5938 +#include <net/tcp.h>
5939 +
5940 +#include <linux/netfilter_ipv4/lockhelp.h>
5941 +#include <linux/netfilter_ipv4/ip_nat.h>
5942 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
5943 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5944 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
5945 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5946 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
5947 +
5948 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5949 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
5950 +MODULE_LICENSE("GPL");
5951 +
5952 +DECLARE_LOCK_EXTERN(ip_h323_lock);
5953 +struct module *ip_nat_h323 = THIS_MODULE;
5954 +
5955 +#if 0
5956 +#define DEBUGP printk
5957 +#else
5958 +#define DEBUGP(format, args...)
5959 +#endif
5960 +
5961 +/* FIXME: Time out? --RR */
5962 +
5963 +static unsigned int 
5964 +h225_nat_expected(struct sk_buff **pskb,
5965 +                 unsigned int hooknum,
5966 +                 struct ip_conntrack *ct,
5967 +                 struct ip_nat_info *info);
5968 +
5969 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
5970 +                                 struct ip_conntrack_expect *exp,
5971 +                                 struct ip_nat_info *info,
5972 +                                 enum ip_conntrack_info ctinfo,
5973 +                                 unsigned int hooknum,
5974 +                                 struct sk_buff **pskb);
5975 +                 
5976 +static struct ip_nat_helper h245 = 
5977 +       { { NULL, NULL },
5978 +          "H.245",                             /* name */
5979 +         0,                                    /* flags */
5980 +         NULL,                                 /* module */
5981 +         { { 0, { 0 } },                       /* tuple */
5982 +           { 0, { 0 }, IPPROTO_TCP } },
5983 +         { { 0, { 0xFFFF } },                  /* mask */
5984 +           { 0, { 0 }, 0xFFFF } },
5985 +         h225_nat_help,                        /* helper */
5986 +         h225_nat_expected                     /* expectfn */
5987 +       };
5988 +
5989 +static unsigned int
5990 +h225_nat_expected(struct sk_buff **pskb,
5991 +                 unsigned int hooknum,
5992 +                 struct ip_conntrack *ct,
5993 +                 struct ip_nat_info *info)
5994 +{
5995 +       struct ip_nat_multi_range mr;
5996 +       u_int32_t newdstip, newsrcip, newip;
5997 +       u_int16_t port;
5998 +       struct ip_ct_h225_expect *exp_info;
5999 +       struct ip_ct_h225_master *master_info;
6000 +       struct ip_conntrack *master = master_ct(ct);
6001 +       unsigned int is_h225, ret;
6002 +       
6003 +       IP_NF_ASSERT(info);
6004 +       IP_NF_ASSERT(master);
6005 +
6006 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
6007 +
6008 +       DEBUGP("h225_nat_expected: We have a connection!\n");
6009 +       master_info = &ct->master->expectant->help.ct_h225_info;
6010 +       exp_info = &ct->master->help.exp_h225_info;
6011 +
6012 +       LOCK_BH(&ip_h323_lock);
6013 +
6014 +       DEBUGP("master: ");
6015 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6016 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
6017 +       DEBUGP("conntrack: ");
6018 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6019 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
6020 +               /* Make connection go to the client. */
6021 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6022 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6023 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
6024 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6025 +       } else {
6026 +               /* Make the connection go to the server */
6027 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6028 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6029 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
6030 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
6031 +       }
6032 +       port = exp_info->port;
6033 +       is_h225 = master_info->is_h225 == H225_PORT;
6034 +       UNLOCK_BH(&ip_h323_lock);
6035 +       
6036 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6037 +               newip = newsrcip;
6038 +       else
6039 +               newip = newdstip;
6040 +
6041 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6042 +
6043 +       mr.rangesize = 1;
6044 +       /* We don't want to manip the per-protocol, just the IPs... */
6045 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6046 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6047 +
6048 +       /* ... unless we're doing a MANIP_DST, in which case, make
6049 +          sure we map to the correct port */
6050 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
6051 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
6052 +               mr.range[0].min = mr.range[0].max
6053 +                       = ((union ip_conntrack_manip_proto)
6054 +                               { .tcp = { port } });
6055 +       }
6056 +
6057 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
6058 +       
6059 +       if (is_h225) {
6060 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
6061 +               /* NAT expectfn called with ip_nat_lock write-locked */
6062 +               info->helper = &h245;
6063 +       }
6064 +       return ret;
6065 +}
6066 +
6067 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
6068 +                                    struct sk_buff **pskb,
6069 +                                    enum ip_conntrack_info ctinfo)
6070 +{
6071 +       struct iphdr *iph = (*pskb)->nh.iph;
6072 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6073 +       char *data = (char *) tcph + tcph->doff * 4;
6074 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6075 +       u_int32_t datalen = tcplen - tcph->doff*4;
6076 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
6077 +       u_int32_t newip;
6078 +       u_int16_t port;
6079 +       int i;
6080 +
6081 +       MUST_BE_LOCKED(&ip_h323_lock);
6082 +
6083 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
6084 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6085 +                       ? "yes" : "no",
6086 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6087 +                       ? "yes" : "no");
6088 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
6089 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
6090 +               return 1;
6091 +
6092 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
6093 +               info->offset[IP_CT_DIR_ORIGINAL], 
6094 +               info->offset[IP_CT_DIR_REPLY],
6095 +               tcplen);
6096 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6097 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6098 +
6099 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
6100 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
6101 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
6102 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
6103 +               if (!between(info->seq[i], ntohl(tcph->seq), 
6104 +                            ntohl(tcph->seq) + datalen))
6105 +                       continue;
6106 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
6107 +                            ntohl(tcph->seq) + datalen)) {
6108 +                       /* Partial retransmisison. It's a cracker being funky. */
6109 +                       if (net_ratelimit()) {
6110 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6111 +                                    info->seq[i],
6112 +                                    ntohl(tcph->seq),
6113 +                                    ntohl(tcph->seq) + datalen);
6114 +                       }
6115 +                       return 0;
6116 +               }
6117 +
6118 +               /* Change address inside packet to match way we're mapping
6119 +                  this connection. */
6120 +               if (i == IP_CT_DIR_ORIGINAL) {
6121 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
6122 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
6123 +               } else {
6124 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
6125 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
6126 +               }
6127 +
6128 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
6129 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6130 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6131 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6132 +
6133 +               /* Modify the packet */
6134 +               *(u_int32_t *)(data + info->offset[i]) = newip;
6135 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
6136 +       
6137 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
6138 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
6139 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
6140 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
6141 +       }
6142 +
6143 +       /* fix checksum information */
6144 +
6145 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6146 +                                    datalen, 0);
6147 +
6148 +       tcph->check = 0;
6149 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6150 +                                  csum_partial((char *)tcph, tcph->doff*4,
6151 +                                          (*pskb)->csum));
6152 +       ip_send_check(iph);
6153 +
6154 +       return 1;
6155 +}
6156 +
6157 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
6158 +                          struct ip_conntrack *ct,
6159 +                          struct sk_buff **pskb,
6160 +                          enum ip_conntrack_info ctinfo,
6161 +                          struct ip_conntrack_expect *expect)
6162 +{
6163 +       u_int32_t newip;
6164 +       u_int16_t port;
6165 +       struct ip_conntrack_tuple newtuple;
6166 +       struct iphdr *iph = (*pskb)->nh.iph;
6167 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
6168 +       char *data = (char *) tcph + tcph->doff * 4;
6169 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
6170 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
6171 +       int is_h225;
6172 +
6173 +       MUST_BE_LOCKED(&ip_h323_lock);
6174 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
6175 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6176 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6177 +
6178 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
6179 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
6180 +               /* Partial retransmisison. It's a cracker being funky. */
6181 +               if (net_ratelimit()) {
6182 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
6183 +                            expect->seq,
6184 +                            ntohl(tcph->seq),
6185 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
6186 +               }
6187 +               return 0;
6188 +       }
6189 +
6190 +       /* Change address inside packet to match way we're mapping
6191 +          this connection. */
6192 +       if (info->dir == IP_CT_DIR_REPLY) {
6193 +               /* Must be where client thinks server is */
6194 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6195 +               /* Expect something from client->server */
6196 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6197 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6198 +       } else {
6199 +               /* Must be where server thinks client is */
6200 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6201 +               /* Expect something from server->client */
6202 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
6203 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6204 +       }
6205 +
6206 +       is_h225 = (master_info->is_h225 == H225_PORT);
6207 +
6208 +       if (is_h225) {
6209 +               newtuple.dst.protonum = IPPROTO_TCP;
6210 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
6211 +       } else {
6212 +               newtuple.dst.protonum = IPPROTO_UDP;
6213 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
6214 +       }
6215 +       
6216 +       /* Try to get same port: if not, try to change it. */
6217 +       for (port = ntohs(info->port); port != 0; port++) {
6218 +               if (is_h225)
6219 +                       newtuple.dst.u.tcp.port = htons(port);
6220 +               else
6221 +                       newtuple.dst.u.udp.port = htons(port);
6222 +
6223 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
6224 +                       break;
6225 +       }
6226 +       if (port == 0) {
6227 +               DEBUGP("h323_data_fixup: no free port found!\n");
6228 +               return 0;
6229 +       }
6230 +
6231 +       port = htons(port);
6232 +
6233 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
6234 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6235 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6236 +
6237 +       /* Modify the packet */
6238 +       *(u_int32_t *)(data + info->offset) = newip;
6239 +       *(u_int16_t *)(data + info->offset + 4) = port;
6240 +       
6241 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
6242 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
6243 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
6244 +
6245 +       /* fix checksum information  */
6246 +       /* FIXME: usually repeated multiple times in the case of H.245! */
6247 +
6248 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
6249 +                                    tcplen - tcph->doff*4, 0);
6250 +
6251 +       tcph->check = 0;
6252 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6253 +                                  csum_partial((char *)tcph, tcph->doff*4,
6254 +                                          (*pskb)->csum));
6255 +       ip_send_check(iph);
6256 +
6257 +       return 1;
6258 +}
6259 +
6260 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
6261 +                                 struct ip_conntrack_expect *exp,
6262 +                                 struct ip_nat_info *info,
6263 +                                 enum ip_conntrack_info ctinfo,
6264 +                                 unsigned int hooknum,
6265 +                                 struct sk_buff **pskb)
6266 +{
6267 +       int dir;
6268 +       struct ip_ct_h225_expect *exp_info;
6269 +       
6270 +       /* Only mangle things once: original direction in POST_ROUTING
6271 +          and reply direction on PRE_ROUTING. */
6272 +       dir = CTINFO2DIR(ctinfo);
6273 +       DEBUGP("nat_h323: dir %s at hook %s\n",
6274 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6275 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6276 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6277 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6278 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6279 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6280 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
6281 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6282 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6283 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6284 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6285 +               return NF_ACCEPT;
6286 +       }
6287 +
6288 +       if (!exp) {
6289 +               LOCK_BH(&ip_h323_lock);
6290 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
6291 +                       UNLOCK_BH(&ip_h323_lock);
6292 +                       return NF_DROP;
6293 +               }
6294 +               UNLOCK_BH(&ip_h323_lock);
6295 +               return NF_ACCEPT;
6296 +       }
6297 +               
6298 +       exp_info = &exp->help.exp_h225_info;
6299 +
6300 +       LOCK_BH(&ip_h323_lock);
6301 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
6302 +               UNLOCK_BH(&ip_h323_lock);
6303 +               return NF_DROP;
6304 +       }
6305 +       UNLOCK_BH(&ip_h323_lock);
6306 +
6307 +       return NF_ACCEPT;
6308 +}
6309 +
6310 +static struct ip_nat_helper h225 = 
6311 +       { { NULL, NULL },
6312 +         "H.225",                                      /* name */
6313 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
6314 +         THIS_MODULE,                                  /* module */
6315 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
6316 +           { 0, { 0 }, IPPROTO_TCP } },
6317 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
6318 +           { 0, { 0 }, 0xFFFF } },
6319 +         h225_nat_help,                                /* helper */
6320 +         h225_nat_expected                             /* expectfn */
6321 +       };
6322 +
6323 +static int __init init(void)
6324 +{
6325 +       int ret;
6326 +       
6327 +       ret = ip_nat_helper_register(&h225);
6328 +
6329 +       if (ret != 0)
6330 +               printk("ip_nat_h323: cannot initialize the module!\n");
6331 +
6332 +       return ret;
6333 +}
6334 +
6335 +static void __exit fini(void)
6336 +{
6337 +       ip_nat_helper_unregister(&h225);
6338 +}
6339 +
6340 +module_init(init);
6341 +module_exit(fini);
6342 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c
6343 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_mms.c 1970-01-01 01:00:00.000000000 +0100
6344 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_mms.c     2004-04-30 09:12:58.000000000 +0200
6345 @@ -0,0 +1,350 @@
6346 +/* MMS extension for TCP NAT alteration.
6347 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6348 + * based on ip_nat_ftp.c and ip_nat_irc.c
6349 + *
6350 + * ip_nat_mms.c v0.3 2002-09-22
6351 + *
6352 + *      This program is free software; you can redistribute it and/or
6353 + *      modify it under the terms of the GNU General Public License
6354 + *      as published by the Free Software Foundation; either version
6355 + *      2 of the License, or (at your option) any later version.
6356 + *
6357 + *      Module load syntax:
6358 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
6359 + *
6360 + *      Please give the ports of all MMS servers You wish to connect to.
6361 + *      If you don't specify ports, the default will be TCP port 1755.
6362 + *
6363 + *      More info on MMS protocol, firewalls and NAT:
6364 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6365 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6366 + *
6367 + *      The SDP project people are reverse-engineering MMS:
6368 + *      http://get.to/sdp
6369 + */
6370 +
6371 +/* FIXME: issue with UDP & fragmentation with this URL: 
6372 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
6373 +   may be related to out-of-order first packets:
6374 +   basically the expectation is set up correctly, then the server sends
6375 +   a first UDP packet which is fragmented plus arrives out-of-order.
6376 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
6377 +   an ICMP unreachable back to the server */
6378 +
6379 +#include <linux/module.h>
6380 +#include <linux/netfilter_ipv4.h>
6381 +#include <linux/ip.h>
6382 +#include <linux/tcp.h>
6383 +#include <net/tcp.h>
6384 +#include <linux/netfilter_ipv4/ip_nat.h>
6385 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6386 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6387 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6388 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6389 +
6390 +#if 0 
6391 +#define DEBUGP printk
6392 +#define DUMP_BYTES(address, counter)                                \
6393 +({                                                                  \
6394 +       int temp_counter;                                           \
6395 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
6396 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
6397 +       };                                                          \
6398 +       DEBUGP("\n");                                               \
6399 +})
6400 +#else
6401 +#define DEBUGP(format, args...)
6402 +#define DUMP_BYTES(address, counter)
6403 +#endif
6404 +
6405 +#define MAX_PORTS 8
6406 +static int ports[MAX_PORTS];
6407 +static int ports_c = 0;
6408 +
6409 +#ifdef MODULE_PARM
6410 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6411 +#endif
6412 +
6413 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6414 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
6415 +MODULE_LICENSE("GPL");
6416 +
6417 +DECLARE_LOCK_EXTERN(ip_mms_lock);
6418 +
6419 +/* FIXME: Time out? --RR */
6420 +
6421 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
6422 +                          struct ip_conntrack *ct,
6423 +                          struct sk_buff **pskb,
6424 +                          enum ip_conntrack_info ctinfo,
6425 +                          struct ip_conntrack_expect *expect)
6426 +{
6427 +       u_int32_t newip;
6428 +       struct ip_conntrack_tuple t;
6429 +       struct iphdr *iph = (*pskb)->nh.iph;
6430 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6431 +       char *data = (char *)tcph + tcph->doff * 4;
6432 +       int i, j, k, port;
6433 +       u_int16_t mms_proto;
6434 +
6435 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
6436 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
6437 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
6438 +
6439 +       int zero_padding;
6440 +
6441 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
6442 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
6443 +       char proto_string[6];
6444 +       
6445 +       MUST_BE_LOCKED(&ip_mms_lock);
6446 +
6447 +       /* what was the protocol again ? */
6448 +       mms_proto = expect->tuple.dst.protonum;
6449 +       sprintf(proto_string, "%u", mms_proto);
6450 +       
6451 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
6452 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
6453 +              mms_proto == IPPROTO_UDP ? "UDP"
6454 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
6455 +       
6456 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6457 +
6458 +       /* Alter conntrack's expectations. */
6459 +       t = expect->tuple;
6460 +       t.dst.ip = newip;
6461 +       for (port = ct_mms_info->port; port != 0; port++) {
6462 +               t.dst.u.tcp.port = htons(port);
6463 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
6464 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
6465 +                       break;
6466 +               }
6467 +       }
6468 +       
6469 +       if(port == 0)
6470 +               return 0;
6471 +
6472 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
6473 +               NIPQUAD(newip),
6474 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
6475 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
6476 +               port);
6477 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
6478 +       
6479 +       memset(unicode_buffer, 0, sizeof(char)*75);
6480 +
6481 +       for (i=0; i<strlen(buffer); ++i)
6482 +               *(unicode_buffer+i*2)=*(buffer+i);
6483 +       
6484 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
6485 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
6486 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
6487 +       
6488 +       /* add end of packet to it */
6489 +       for (j=0; j<ct_mms_info->padding; ++j) {
6490 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
6491 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
6492 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
6493 +       }
6494 +
6495 +       /* pad with zeroes at the end ? see explanation of weird math below */
6496 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
6497 +       for (k=0; k<zero_padding; ++k)
6498 +               *(unicode_buffer+i*2+j+k)= (char)0;
6499 +       
6500 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
6501 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6502 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6503 +       
6504 +       /* explanation, before I forget what I did:
6505 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
6506 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
6507 +          but note that things may have to be padded with zeroes to align by 8 
6508 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
6509 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
6510 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
6511 +       *mms_messageLength = *mms_chunkLenLV*8;
6512 +       
6513 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
6514 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
6515 +       
6516 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
6517 +                                expect->seq - ntohl(tcph->seq),
6518 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
6519 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
6520 +       DUMP_BYTES(unicode_buffer, 60);
6521 +       
6522 +       return 1;
6523 +}
6524 +
6525 +static unsigned int
6526 +mms_nat_expected(struct sk_buff **pskb,
6527 +                 unsigned int hooknum,
6528 +                 struct ip_conntrack *ct,
6529 +                 struct ip_nat_info *info)
6530 +{
6531 +       struct ip_nat_multi_range mr;
6532 +       u_int32_t newdstip, newsrcip, newip;
6533 +
6534 +       struct ip_conntrack *master = master_ct(ct);
6535 +
6536 +       IP_NF_ASSERT(info);
6537 +       IP_NF_ASSERT(master);
6538 +
6539 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6540 +
6541 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
6542 +
6543 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6544 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6545 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
6546 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6547 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6548 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
6549 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
6550 +
6551 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
6552 +               newip = newsrcip;
6553 +       else
6554 +               newip = newdstip;
6555 +
6556 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
6557 +
6558 +       mr.rangesize = 1;
6559 +       /* We don't want to manip the per-protocol, just the IPs. */
6560 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6561 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
6562 +
6563 +       return ip_nat_setup_info(ct, &mr, hooknum);
6564 +}
6565 +
6566 +
6567 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
6568 +                        struct ip_conntrack_expect *exp,
6569 +                        struct ip_nat_info *info,
6570 +                        enum ip_conntrack_info ctinfo,
6571 +                        unsigned int hooknum,
6572 +                        struct sk_buff **pskb)
6573 +{
6574 +       struct iphdr *iph = (*pskb)->nh.iph;
6575 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6576 +       unsigned int datalen;
6577 +       int dir;
6578 +       struct ip_ct_mms_expect *ct_mms_info;
6579 +
6580 +       if (!exp)
6581 +               DEBUGP("ip_nat_mms: no exp!!");
6582 +
6583 +       ct_mms_info = &exp->help.exp_mms_info;
6584 +       
6585 +       /* Only mangle things once: original direction in POST_ROUTING
6586 +          and reply direction on PRE_ROUTING. */
6587 +       dir = CTINFO2DIR(ctinfo);
6588 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6589 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6590 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
6591 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6592 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6593 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6594 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6595 +               return NF_ACCEPT;
6596 +       }
6597 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
6598 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6599 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6600 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6601 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
6602 +       
6603 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
6604 +       
6605 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
6606 +              exp->seq + ct_mms_info->len,
6607 +              ntohl(tcph->seq),
6608 +              ntohl(tcph->seq) + datalen);
6609 +       
6610 +       LOCK_BH(&ip_mms_lock);
6611 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
6612 +       if (between(exp->seq + ct_mms_info->len,
6613 +           ntohl(tcph->seq),
6614 +           ntohl(tcph->seq) + datalen)) {
6615 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
6616 +                       UNLOCK_BH(&ip_mms_lock);
6617 +                       return NF_DROP;
6618 +               }
6619 +       } else {
6620 +               /* Half a match?  This means a partial retransmisison.
6621 +                  It's a cracker being funky. */
6622 +               if (net_ratelimit()) {
6623 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
6624 +                              exp->seq, ct_mms_info->len,
6625 +                              ntohl(tcph->seq),
6626 +                              ntohl(tcph->seq) + datalen);
6627 +               }
6628 +               UNLOCK_BH(&ip_mms_lock);
6629 +               return NF_DROP;
6630 +       }
6631 +       UNLOCK_BH(&ip_mms_lock);
6632 +       
6633 +       return NF_ACCEPT;
6634 +}
6635 +
6636 +static struct ip_nat_helper mms[MAX_PORTS];
6637 +static char mms_names[MAX_PORTS][10];
6638 +
6639 +/* Not __exit: called from init() */
6640 +static void fini(void)
6641 +{
6642 +       int i;
6643 +
6644 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6645 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
6646 +               ip_nat_helper_unregister(&mms[i]);
6647 +       }
6648 +}
6649 +
6650 +static int __init init(void)
6651 +{
6652 +       int i, ret = 0;
6653 +       char *tmpname;
6654 +
6655 +       if (ports[0] == 0)
6656 +               ports[0] = MMS_PORT;
6657 +
6658 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6659 +
6660 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
6661 +
6662 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
6663 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6664 +               mms[i].mask.dst.protonum = 0xFFFF;
6665 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
6666 +               mms[i].help = mms_nat_help;
6667 +               mms[i].me = THIS_MODULE;
6668 +               mms[i].flags = 0;
6669 +               mms[i].expect = mms_nat_expected;
6670 +
6671 +               tmpname = &mms_names[i][0];
6672 +               if (ports[i] == MMS_PORT)
6673 +                       sprintf(tmpname, "mms");
6674 +               else
6675 +                       sprintf(tmpname, "mms-%d", i);
6676 +               mms[i].name = tmpname;
6677 +
6678 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
6679 +                               ports[i]);
6680 +               ret = ip_nat_helper_register(&mms[i]);
6681 +
6682 +               if (ret) {
6683 +                       printk("ip_nat_mms: error registering "
6684 +                              "helper for port %d\n", ports[i]);
6685 +                       fini();
6686 +                       return ret;
6687 +               }
6688 +               ports_c++;
6689 +       }
6690 +
6691 +       return ret;
6692 +}
6693 +
6694 +module_init(init);
6695 +module_exit(fini);
6696 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c
6697 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_quake3.c      1970-01-01 01:00:00.000000000 +0100
6698 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_quake3.c  2004-04-30 09:13:29.000000000 +0200
6699 @@ -0,0 +1,249 @@
6700 +/* Quake3 extension for UDP NAT alteration.
6701 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6702 + * based on ip_nat_ftp.c and ip_nat_tftp.c
6703 + *
6704 + * ip_nat_quake3.c v0.0.3 2002-08-31
6705 + *
6706 + *      This program is free software; you can redistribute it and/or
6707 + *      modify it under the terms of the GNU General Public License
6708 + *      as published by the Free Software Foundation; either version
6709 + *      2 of the License, or (at your option) any later version.
6710 + *
6711 + *      Module load syntax:
6712 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
6713 + *
6714 + *      please give the ports of all Quake3 master servers You wish to
6715 + *      connect to. If you don't specify ports, the default will be UDP
6716 + *      port 27950.
6717 + *
6718 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
6719 + *
6720 + *      Notes: 
6721 + *      - If you're one of those people who would try anything to lower
6722 + *        latency while playing Quake (and who isn't :-) ), you may want to
6723 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
6724 + *        outgoing UDP traffic.
6725 + *        This will make ip_conntrack_quake3 add the necessary expectations,
6726 + *        but there will be no overhead for client->server UDP streams. If
6727 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
6728 + *        hook for every packet in the client->server UDP stream.
6729 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
6730 + *        The IP addresses in the master connection payload (=IP addresses
6731 + *        of Quake servers) have no relation with the master server so
6732 + *        DNAT'ing the master connection to a server should not change the
6733 + *        expected connections.
6734 + *      - Not tested due to lack of equipment:
6735 + *        - multiple Quake3 clients behind one MASQUERADE gateway
6736 + *        - what if Quake3 client is running on router too
6737 + */
6738 +
6739 +#include <linux/module.h>
6740 +#include <linux/netfilter_ipv4.h>
6741 +#include <linux/ip.h>
6742 +#include <linux/udp.h>
6743 +
6744 +#include <linux/netfilter.h>
6745 +#include <linux/netfilter_ipv4/ip_tables.h>
6746 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6747 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
6748 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6749 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6750 +
6751 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6752 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
6753 +MODULE_LICENSE("GPL");
6754 +
6755 +#define MAX_PORTS 8
6756 +
6757 +static int ports[MAX_PORTS];
6758 +static int ports_c = 0;
6759 +#ifdef MODULE_PARM
6760 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
6761 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
6762 +#endif
6763 +
6764 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
6765 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
6766 +#if 0 
6767 +#define DEBUGP printk
6768 +#else
6769 +#define DEBUGP(format, args...)
6770 +#endif
6771 +
6772 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
6773 +
6774 +static unsigned int 
6775 +quake3_nat_help(struct ip_conntrack *ct,
6776 +                struct ip_conntrack_expect *exp,
6777 +                struct ip_nat_info *info,
6778 +                enum ip_conntrack_info ctinfo,
6779 +                unsigned int hooknum,
6780 +                struct sk_buff **pskb)
6781 +{
6782 +       struct iphdr *iph = (*pskb)->nh.iph;
6783 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
6784 +       struct ip_conntrack_tuple repl;
6785 +       int dir = CTINFO2DIR(ctinfo);
6786 +       int i;
6787 +       
6788 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
6789 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6790 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6791 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6792 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
6793 +             );
6794 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6795 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
6796 +       
6797 +       /* Only mangle things once: original direction in POST_ROUTING
6798 +          and reply direction on PRE_ROUTING. */
6799 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
6800 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
6801 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
6802 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
6803 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6804 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6805 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
6806 +               return NF_ACCEPT;
6807 +       }
6808 +
6809 +       if (!exp) {
6810 +               DEBUGP("no conntrack expectation to modify\n");
6811 +               return NF_ACCEPT;
6812 +       }
6813 +
6814 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
6815 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
6816 +                   i+6 < ntohs(udph->len);
6817 +                   i+=7) {
6818 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
6819 +                              i, ntohs(udph->len),
6820 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
6821 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
6822 +                       
6823 +                       memset(&repl, 0, sizeof(repl));
6824 +
6825 +                       repl.dst.protonum = IPPROTO_UDP;
6826 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
6827 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
6828 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
6829 +                       
6830 +                       ip_conntrack_change_expect(exp, &repl);
6831 +               }
6832 +       }
6833 +       return NF_ACCEPT;
6834 +}
6835 +
6836 +static unsigned int 
6837 +quake3_nat_expected(struct sk_buff **pskb,
6838 +                    unsigned int hooknum,
6839 +                    struct ip_conntrack *ct, 
6840 +                    struct ip_nat_info *info) 
6841 +{
6842 +       const struct ip_conntrack *master = ct->master->expectant;
6843 +       struct ip_nat_multi_range mr;
6844 +       u_int32_t newsrcip, newdstip, newip;
6845 +#if 0 
6846 +       const struct ip_conntrack_tuple *repl =
6847 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
6848 +       struct iphdr *iph = (*pskb)->nh.iph;
6849 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
6850 +#endif
6851 +
6852 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
6853 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
6854 +
6855 +       IP_NF_ASSERT(info);
6856 +       IP_NF_ASSERT(master);
6857 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
6858 +       
6859 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
6860 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
6861 +       
6862 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
6863 +               newip = newsrcip;
6864 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6865 +                      "newsrc: %u.%u.%u.%u\n",
6866 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6867 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6868 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6869 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6870 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6871 +                      NIPQUAD(newip));
6872 +               
6873 +       } else {
6874 +               newip = newdstip;
6875 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
6876 +                      "newdst: %u.%u.%u.%u\n",
6877 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
6878 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
6879 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
6880 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
6881 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
6882 +                      NIPQUAD(newip));
6883 +       }
6884 +       
6885 +       mr.rangesize = 1;
6886 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
6887 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
6888 +
6889 +       return ip_nat_setup_info(ct,&mr,hooknum);
6890 +}
6891 +
6892 +static struct ip_nat_helper quake3[MAX_PORTS];
6893 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
6894 +
6895 +static void fini(void)
6896 +{
6897 +       int i;
6898 +       
6899 +       for (i = 0 ; i < ports_c; i++) {
6900 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
6901 +                      ip_nat_helper_unregister(&quake3[i]);
6902 +       }
6903 +}
6904 +
6905 +static int __init init(void)
6906 +       {
6907 +               int i, ret = 0;
6908 +               char *tmpname;
6909 +
6910 +               if (!ports[0])
6911 +                       ports[0] = QUAKE3_MASTER_PORT;
6912 +               
6913 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
6914 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
6915 +
6916 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
6917 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
6918 +                       quake3[i].mask.dst.protonum = 0xFFFF;
6919 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
6920 +                       quake3[i].help = quake3_nat_help;
6921 +                       quake3[i].flags = 0;
6922 +                       quake3[i].me = THIS_MODULE;
6923 +                       quake3[i].expect = quake3_nat_expected;
6924 +                       
6925 +                       tmpname = &quake3_names[i][0];
6926 +                       if (ports[i] == QUAKE3_MASTER_PORT)
6927 +                               sprintf(tmpname, "quake3");
6928 +                       else
6929 +                               sprintf(tmpname, "quake3-%d", i);
6930 +                       quake3[i].name = tmpname;
6931 +                       
6932 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
6933 +                              ports[i], quake3[i].name);
6934 +                       ret = ip_nat_helper_register(&quake3[i]);
6935 +                       
6936 +                       if (ret) {
6937 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
6938 +                                      ports[i]);
6939 +                               fini();
6940 +                               return ret;
6941 +                       }
6942 +                       ports_c++;
6943 +               }
6944 +               return ret;
6945 +       }
6946 +       
6947 +module_init(init);
6948 +module_exit(fini);
6949 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c
6950 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rtsp.c        1970-01-01 01:00:00.000000000 +0100
6951 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rtsp.c    2004-04-30 09:14:05.000000000 +0200
6952 @@ -0,0 +1,621 @@
6953 +/*
6954 + * RTSP extension for TCP NAT alteration
6955 + * (C) 2003 by Tom Marshall <tmarshall@real.com>
6956 + * based on ip_nat_irc.c
6957 + *
6958 + *      This program is free software; you can redistribute it and/or
6959 + *      modify it under the terms of the GNU General Public License
6960 + *      as published by the Free Software Foundation; either version
6961 + *      2 of the License, or (at your option) any later version.
6962 + *
6963 + * Module load syntax:
6964 + *      insmod ip_nat_rtsp.o ports=port1,port2,...port<MAX_PORTS>
6965 + *                           stunaddr=<address>
6966 + *                           destaction=[auto|strip|none]
6967 + *
6968 + * If no ports are specified, the default will be port 554 only.
6969 + *
6970 + * stunaddr specifies the address used to detect that a client is using STUN.
6971 + * If this address is seen in the destination parameter, it is assumed that
6972 + * the client has already punched a UDP hole in the firewall, so we don't
6973 + * mangle the client_port.  If none is specified, it is autodetected.  It
6974 + * only needs to be set if you have multiple levels of NAT.  It should be
6975 + * set to the external address that the STUN clients detect.  Note that in
6976 + * this case, it will not be possible for clients to use UDP with servers
6977 + * between the NATs.
6978 + *
6979 + * If no destaction is specified, auto is used.
6980 + *   destaction=auto:  strip destination parameter if it is not stunaddr.
6981 + *   destaction=strip: always strip destination parameter (not recommended).
6982 + *   destaction=none:  do not touch destination parameter (not recommended).
6983 + */
6984 +
6985 +#include <linux/module.h>
6986 +#include <linux/netfilter_ipv4.h>
6987 +#include <linux/ip.h>
6988 +#include <linux/tcp.h>
6989 +#include <linux/kernel.h>
6990 +#include <net/tcp.h>
6991 +#include <linux/netfilter_ipv4/ip_nat.h>
6992 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
6993 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
6994 +#include <linux/netfilter_ipv4/ip_conntrack_rtsp.h>
6995 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6996 +
6997 +#include <linux/inet.h>
6998 +#include <linux/ctype.h>
6999 +#define NF_NEED_STRNCASECMP
7000 +#define NF_NEED_STRTOU16
7001 +#include <linux/netfilter_helpers.h>
7002 +#define NF_NEED_MIME_NEXTLINE
7003 +#include <linux/netfilter_mime.h>
7004 +
7005 +#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7006 +#ifdef IP_NF_RTSP_DEBUG
7007 +#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__, ## args)
7008 +#else
7009 +#define DEBUGP(fmt, args...)
7010 +#endif
7011 +
7012 +#define MAX_PORTS       8
7013 +#define DSTACT_AUTO     0
7014 +#define DSTACT_STRIP    1
7015 +#define DSTACT_NONE     2
7016 +
7017 +static int      ports[MAX_PORTS];
7018 +static char*    stunaddr = NULL;
7019 +static char*    destaction = NULL;
7020 +
7021 +static int       num_ports = 0;
7022 +static u_int32_t extip = 0;
7023 +static int       dstact = 0;
7024 +
7025 +MODULE_AUTHOR("Tom Marshall <tmarshall@real.com>");
7026 +MODULE_DESCRIPTION("RTSP network address translation module");
7027 +MODULE_LICENSE("GPL");
7028 +#ifdef MODULE_PARM
7029 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
7030 +MODULE_PARM_DESC(ports, "port numbers of RTSP servers");
7031 +MODULE_PARM(stunaddr, "s");
7032 +MODULE_PARM_DESC(stunaddr, "Address for detecting STUN");
7033 +MODULE_PARM(destaction, "s");
7034 +MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)");
7035 +#endif
7036 +
7037 +/* protects rtsp part of conntracks */
7038 +DECLARE_LOCK_EXTERN(ip_rtsp_lock);
7039 +
7040 +#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; }
7041 +
7042 +/*** helper functions ***/
7043 +
7044 +static void
7045 +get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen)
7046 +{
7047 +    struct iphdr*   iph  = (struct iphdr*)skb->nh.iph;
7048 +    struct tcphdr*  tcph = (struct tcphdr*)((char*)iph + iph->ihl*4);
7049 +
7050 +    *pptcpdata = (char*)tcph + tcph->doff*4;
7051 +    *ptcpdatalen = ((char*)skb->h.raw + skb->len) - *pptcpdata;
7052 +}
7053 +
7054 +/*** nat functions ***/
7055 +
7056 +/*
7057 + * Mangle the "Transport:" header:
7058 + *   - Replace all occurences of "client_port=<spec>"
7059 + *   - Handle destination parameter
7060 + *
7061 + * In:
7062 + *   ct, ctinfo = conntrack context
7063 + *   pskb       = packet
7064 + *   tranoff    = Transport header offset from TCP data
7065 + *   tranlen    = Transport header length (incl. CRLF)
7066 + *   rport_lo   = replacement low  port (host endian)
7067 + *   rport_hi   = replacement high port (host endian)
7068 + *
7069 + * Returns packet size difference.
7070 + *
7071 + * Assumes that a complete transport header is present, ending with CR or LF
7072 + */
7073 +static int
7074 +rtsp_mangle_tran(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7075 +                 struct ip_conntrack_expect* exp,
7076 +                 struct sk_buff** pskb, uint tranoff, uint tranlen)
7077 +{
7078 +    char*       ptcp;
7079 +    uint        tcplen;
7080 +    char*       ptran;
7081 +    char        rbuf1[16];      /* Replacement buffer (one port) */
7082 +    uint        rbuf1len;       /* Replacement len (one port) */
7083 +    char        rbufa[16];      /* Replacement buffer (all ports) */
7084 +    uint        rbufalen;       /* Replacement len (all ports) */
7085 +    u_int32_t   newip;
7086 +    u_int16_t   loport, hiport;
7087 +    uint        off = 0;
7088 +    uint        diff;           /* Number of bytes we removed */
7089 +
7090 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7091 +    struct ip_conntrack_tuple t;
7092 +
7093 +    char    szextaddr[15+1];
7094 +    uint    extaddrlen;
7095 +    int     is_stun;
7096 +
7097 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7098 +    ptran = ptcp+tranoff;
7099 +
7100 +    if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen ||
7101 +        tranlen < 10 || !iseol(ptran[tranlen-1]) ||
7102 +        nf_strncasecmp(ptran, "Transport:", 10) != 0)
7103 +    {
7104 +        INFOP("sanity check failed\n");
7105 +        return 0;
7106 +    }
7107 +    off += 10;
7108 +    SKIP_WSPACE(ptcp+tranoff, tranlen, off);
7109 +
7110 +    newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7111 +    t = exp->tuple;
7112 +    t.dst.ip = newip;
7113 +
7114 +    extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip))
7115 +                       : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip));
7116 +    DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto"));
7117 +
7118 +    rbuf1len = rbufalen = 0;
7119 +    switch (prtspexp->pbtype)
7120 +    {
7121 +    case pb_single:
7122 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7123 +        {
7124 +            t.dst.u.udp.port = htons(loport);
7125 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7126 +            {
7127 +                DEBUGP("using port %hu\n", loport);
7128 +                break;
7129 +            }
7130 +        }
7131 +        if (loport != 0)
7132 +        {
7133 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7134 +            rbufalen = sprintf(rbufa, "%hu", loport);
7135 +        }
7136 +        break;
7137 +    case pb_range:
7138 +        for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */
7139 +        {
7140 +            t.dst.u.udp.port = htons(loport);
7141 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7142 +            {
7143 +                hiport = loport + ~exp->mask.dst.u.udp.port;
7144 +                DEBUGP("using ports %hu-%hu\n", loport, hiport);
7145 +                break;
7146 +            }
7147 +        }
7148 +        if (loport != 0)
7149 +        {
7150 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7151 +            rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1);
7152 +        }
7153 +        break;
7154 +    case pb_discon:
7155 +        for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */
7156 +        {
7157 +            t.dst.u.udp.port = htons(loport);
7158 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7159 +            {
7160 +                DEBUGP("using port %hu (1 of 2)\n", loport);
7161 +                break;
7162 +            }
7163 +        }
7164 +        for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */
7165 +        {
7166 +            t.dst.u.udp.port = htons(hiport);
7167 +            if (ip_conntrack_change_expect(exp, &t) == 0)
7168 +            {
7169 +                DEBUGP("using port %hu (2 of 2)\n", hiport);
7170 +                break;
7171 +            }
7172 +        }
7173 +        if (loport != 0 && hiport != 0)
7174 +        {
7175 +            rbuf1len = sprintf(rbuf1, "%hu", loport);
7176 +            if (hiport == loport+1)
7177 +            {
7178 +                rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport);
7179 +            }
7180 +            else
7181 +            {
7182 +                rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport);
7183 +            }
7184 +        }
7185 +        break;
7186 +    }
7187 +
7188 +    if (rbuf1len == 0)
7189 +    {
7190 +        return 0;   /* cannot get replacement port(s) */
7191 +    }
7192 +
7193 +    /* Transport: tran;field;field=val,tran;field;field=val,... */
7194 +    while (off < tranlen)
7195 +    {
7196 +        uint        saveoff;
7197 +        const char* pparamend;
7198 +        uint        nextparamoff;
7199 +
7200 +        pparamend = memchr(ptran+off, ',', tranlen-off);
7201 +        pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1;
7202 +        nextparamoff = pparamend-ptcp;
7203 +
7204 +        /*
7205 +         * We pass over each param twice.  On the first pass, we look for a
7206 +         * destination= field.  It is handled by the security policy.  If it
7207 +         * is present, allowed, and equal to our external address, we assume
7208 +         * that STUN is being used and we leave the client_port= field alone.
7209 +         */
7210 +        is_stun = 0;
7211 +        saveoff = off;
7212 +        while (off < nextparamoff)
7213 +        {
7214 +            const char* pfieldend;
7215 +            uint        nextfieldoff;
7216 +
7217 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7218 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7219 +
7220 +            if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0)
7221 +            {
7222 +                if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0)
7223 +                {
7224 +                    is_stun = 1;
7225 +                }
7226 +                if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun))
7227 +                {
7228 +                    diff = nextfieldoff-off;
7229 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7230 +                                                         off, diff, NULL, 0))
7231 +                    {
7232 +                        /* mangle failed, all we can do is bail */
7233 +                        return 0;
7234 +                    }
7235 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7236 +                    ptran = ptcp+tranoff;
7237 +                    tranlen -= diff;
7238 +                    nextparamoff -= diff;
7239 +                    nextfieldoff -= diff;
7240 +                }
7241 +            }
7242 +
7243 +            off = nextfieldoff;
7244 +        }
7245 +        if (is_stun)
7246 +        {
7247 +            continue;
7248 +        }
7249 +        off = saveoff;
7250 +        while (off < nextparamoff)
7251 +        {
7252 +            const char* pfieldend;
7253 +            uint        nextfieldoff;
7254 +
7255 +            pfieldend = memchr(ptran+off, ';', nextparamoff-off);
7256 +            nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1;
7257 +
7258 +            if (strncmp(ptran+off, "client_port=", 12) == 0)
7259 +            {
7260 +                u_int16_t   port;
7261 +                uint        numlen;
7262 +                uint        origoff;
7263 +                uint        origlen;
7264 +                char*       rbuf    = rbuf1;
7265 +                uint        rbuflen = rbuf1len;
7266 +
7267 +                off += 12;
7268 +                origoff = (ptran-ptcp)+off;
7269 +                origlen = 0;
7270 +                numlen = nf_strtou16(ptran+off, &port);
7271 +                off += numlen;
7272 +                origlen += numlen;
7273 +                if (port != prtspexp->loport)
7274 +                {
7275 +                    DEBUGP("multiple ports found, port %hu ignored\n", port);
7276 +                }
7277 +                else
7278 +                {
7279 +                    if (ptran[off] == '-' || ptran[off] == '/')
7280 +                    {
7281 +                        off++;
7282 +                        origlen++;
7283 +                        numlen = nf_strtou16(ptran+off, &port);
7284 +                        off += numlen;
7285 +                        origlen += numlen;
7286 +                        rbuf = rbufa;
7287 +                        rbuflen = rbufalen;
7288 +                    }
7289 +
7290 +                    /*
7291 +                     * note we cannot just memcpy() if the sizes are the same.
7292 +                     * the mangle function does skb resizing, checks for a
7293 +                     * cloned skb, and updates the checksums.
7294 +                     *
7295 +                     * parameter 4 below is offset from start of tcp data.
7296 +                     */
7297 +                    diff = origlen-rbuflen;
7298 +                    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
7299 +                                              origoff, origlen, rbuf, rbuflen))
7300 +                    {
7301 +                        /* mangle failed, all we can do is bail */
7302 +                        return 0;
7303 +                    }
7304 +                    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7305 +                    ptran = ptcp+tranoff;
7306 +                    tranlen -= diff;
7307 +                    nextparamoff -= diff;
7308 +                    nextfieldoff -= diff;
7309 +                }
7310 +            }
7311 +
7312 +            off = nextfieldoff;
7313 +        }
7314 +
7315 +        off = nextparamoff;
7316 +    }
7317 +
7318 +    return 1;
7319 +}
7320 +
7321 +static unsigned int
7322 +expected(struct sk_buff **pskb, uint hooknum, struct ip_conntrack* ct, struct ip_nat_info* info)
7323 +{
7324 +    struct ip_nat_multi_range mr;
7325 +    u_int32_t newdstip, newsrcip, newip;
7326 +
7327 +    struct ip_conntrack *master = master_ct(ct);
7328 +
7329 +    IP_NF_ASSERT(info);
7330 +    IP_NF_ASSERT(master);
7331 +
7332 +    IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
7333 +
7334 +    newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7335 +    newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7336 +    newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip;
7337 +
7338 +    DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n",
7339 +           NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip));
7340 +
7341 +    mr.rangesize = 1;
7342 +    /* We don't want to manip the per-protocol, just the IPs. */
7343 +    mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
7344 +    mr.range[0].min_ip = mr.range[0].max_ip = newip;
7345 +
7346 +    return ip_nat_setup_info(ct, &mr, hooknum);
7347 +}
7348 +
7349 +static uint
7350 +help_out(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7351 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7352 +{
7353 +    char*   ptcp;
7354 +    uint    tcplen;
7355 +    uint    hdrsoff;
7356 +    uint    hdrslen;
7357 +    uint    lineoff;
7358 +    uint    linelen;
7359 +    uint    off;
7360 +
7361 +    struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph;
7362 +    struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4);
7363 +
7364 +    struct ip_ct_rtsp_expect* prtspexp = &exp->help.exp_rtsp_info;
7365 +
7366 +    get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7367 +
7368 +    hdrsoff = exp->seq - ntohl(tcph->seq);
7369 +    hdrslen = prtspexp->len;
7370 +    off = hdrsoff;
7371 +
7372 +    while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen))
7373 +    {
7374 +        if (linelen == 0)
7375 +        {
7376 +            break;
7377 +        }
7378 +        if (off > hdrsoff+hdrslen)
7379 +        {
7380 +            INFOP("!! overrun !!");
7381 +            break;
7382 +        }
7383 +        DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7384 +
7385 +        if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0)
7386 +        {
7387 +            uint oldtcplen = tcplen;
7388 +            if (!rtsp_mangle_tran(ct, ctinfo, exp, pskb, lineoff, linelen))
7389 +            {
7390 +                break;
7391 +            }
7392 +            get_skb_tcpdata(*pskb, &ptcp, &tcplen);
7393 +            hdrslen -= (oldtcplen-tcplen);
7394 +            off -= (oldtcplen-tcplen);
7395 +            lineoff -= (oldtcplen-tcplen);
7396 +            linelen -= (oldtcplen-tcplen);
7397 +            DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff);
7398 +        }
7399 +    }
7400 +
7401 +    return NF_ACCEPT;
7402 +}
7403 +
7404 +static uint
7405 +help_in(struct ip_conntrack* ct, enum ip_conntrack_info ctinfo,
7406 +         struct ip_conntrack_expect* exp, struct sk_buff** pskb)
7407 +{
7408 +    /* XXX: unmangle */
7409 +    return NF_ACCEPT;
7410 +}
7411 +
7412 +static uint
7413 +help(struct ip_conntrack* ct,
7414 +     struct ip_conntrack_expect* exp,
7415 +     struct ip_nat_info* info,
7416 +     enum ip_conntrack_info ctinfo,
7417 +     unsigned int hooknum,
7418 +     struct sk_buff** pskb)
7419 +{
7420 +    struct iphdr*  iph  = (struct iphdr*)(*pskb)->nh.iph;
7421 +    struct tcphdr* tcph = (struct tcphdr*)((char*)iph + iph->ihl * 4);
7422 +    uint datalen;
7423 +    int dir;
7424 +    struct ip_ct_rtsp_expect* ct_rtsp_info;
7425 +    int rc = NF_ACCEPT;
7426 +
7427 +    if (ct == NULL || exp == NULL || info == NULL || pskb == NULL)
7428 +    {
7429 +        DEBUGP("!! null ptr (%p,%p,%p,%p) !!\n", ct, exp, info, pskb);
7430 +        return NF_ACCEPT;
7431 +    }
7432 +
7433 +    ct_rtsp_info = &exp->help.exp_rtsp_info;
7434 +
7435 +    /*
7436 +     * Only mangle things once: original direction in POST_ROUTING
7437 +     * and reply direction on PRE_ROUTING.
7438 +     */
7439 +    dir = CTINFO2DIR(ctinfo);
7440 +    if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7441 +          || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY)))
7442 +    {
7443 +        DEBUGP("Not touching dir %s at hook %s\n",
7444 +               dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7445 +               hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7446 +               : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7447 +               : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7448 +        return NF_ACCEPT;
7449 +    }
7450 +    DEBUGP("got beyond not touching\n");
7451 +
7452 +    datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
7453 +
7454 +    LOCK_BH(&ip_rtsp_lock);
7455 +    /* Ensure the packet contains all of the marked data */
7456 +    if (!between(exp->seq + ct_rtsp_info->len,
7457 +                 ntohl(tcph->seq), ntohl(tcph->seq) + datalen))
7458 +    {
7459 +        /* Partial retransmission?  Probably a hacker. */
7460 +        if (net_ratelimit())
7461 +        {
7462 +            INFOP("partial packet %u/%u in %u/%u\n",
7463 +                   exp->seq, ct_rtsp_info->len, ntohl(tcph->seq), ntohl(tcph->seq) + datalen);
7464 +        }
7465 +        UNLOCK_BH(&ip_rtsp_lock);
7466 +        return NF_DROP;
7467 +    }
7468 +
7469 +    switch (dir)
7470 +    {
7471 +    case IP_CT_DIR_ORIGINAL:
7472 +        rc = help_out(ct, ctinfo, exp, pskb);
7473 +        break;
7474 +    case IP_CT_DIR_REPLY:
7475 +        rc = help_in(ct, ctinfo, exp, pskb);
7476 +        break;
7477 +    }
7478 +    UNLOCK_BH(&ip_rtsp_lock);
7479 +
7480 +    return rc;
7481 +}
7482 +
7483 +static struct ip_nat_helper ip_nat_rtsp_helpers[MAX_PORTS];
7484 +static char rtsp_names[MAX_PORTS][10];
7485 +
7486 +/* This function is intentionally _NOT_ defined as  __exit */
7487 +static void
7488 +fini(void)
7489 +{
7490 +    int i;
7491 +
7492 +    for (i = 0; i < num_ports; i++)
7493 +    {
7494 +        DEBUGP("unregistering helper for port %d\n", ports[i]);
7495 +        ip_nat_helper_unregister(&ip_nat_rtsp_helpers[i]);
7496 +    }
7497 +}
7498 +
7499 +static int __init
7500 +init(void)
7501 +{
7502 +    int ret = 0;
7503 +    int i;
7504 +    struct ip_nat_helper* hlpr;
7505 +    char* tmpname;
7506 +
7507 +    printk("ip_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n");
7508 +
7509 +    if (ports[0] == 0)
7510 +    {
7511 +        ports[0] = RTSP_PORT;
7512 +    }
7513 +
7514 +    for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++)
7515 +    {
7516 +        hlpr = &ip_nat_rtsp_helpers[i];
7517 +        memset(hlpr, 0, sizeof(struct ip_nat_helper));
7518 +
7519 +        hlpr->tuple.dst.protonum = IPPROTO_TCP;
7520 +        hlpr->tuple.src.u.tcp.port = htons(ports[i]);
7521 +        hlpr->mask.src.u.tcp.port = 0xFFFF;
7522 +        hlpr->mask.dst.protonum = 0xFFFF;
7523 +        hlpr->help = help;
7524 +        hlpr->flags = 0;
7525 +        hlpr->me = THIS_MODULE;
7526 +        hlpr->expect = expected;
7527 +
7528 +        tmpname = &rtsp_names[i][0];
7529 +        if (ports[i] == RTSP_PORT)
7530 +        {
7531 +                sprintf(tmpname, "rtsp");
7532 +        }
7533 +        else
7534 +        {
7535 +                sprintf(tmpname, "rtsp-%d", i);
7536 +        }
7537 +        hlpr->name = tmpname;
7538 +
7539 +        DEBUGP("registering helper for port %d: name %s\n", ports[i], hlpr->name);
7540 +        ret = ip_nat_helper_register(hlpr);
7541 +
7542 +        if (ret)
7543 +        {
7544 +            printk("ip_nat_rtsp: error registering helper for port %d\n", ports[i]);
7545 +            fini();
7546 +            return 1;
7547 +        }
7548 +        num_ports++;
7549 +    }
7550 +    if (stunaddr != NULL)
7551 +    {
7552 +        extip = in_aton(stunaddr);
7553 +    }
7554 +    if (destaction != NULL)
7555 +    {
7556 +        if (strcmp(destaction, "auto") == 0)
7557 +        {
7558 +            dstact = DSTACT_AUTO;
7559 +        }
7560 +        if (strcmp(destaction, "strip") == 0)
7561 +        {
7562 +            dstact = DSTACT_STRIP;
7563 +        }
7564 +        if (strcmp(destaction, "none") == 0)
7565 +        {
7566 +            dstact = DSTACT_NONE;
7567 +        }
7568 +    }
7569 +    return ret;
7570 +}
7571 +
7572 +module_init(init);
7573 +module_exit(fini);
7574 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c
7575 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_rule.c        2004-04-28 03:35:44.000000000 +0200
7576 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_rule.c    2004-04-30 09:11:53.000000000 +0200
7577 @@ -75,7 +75,7 @@
7578                 0,
7579                 sizeof(struct ipt_entry),
7580                 sizeof(struct ipt_standard),
7581 -               0, { 0, 0 }, { } },
7582 +               0, NULL, 0, { 0, 0 }, { } },
7583               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7584                 -NF_ACCEPT - 1 } },
7585             /* POST_ROUTING */
7586 @@ -83,7 +83,7 @@
7587                 0,
7588                 sizeof(struct ipt_entry),
7589                 sizeof(struct ipt_standard),
7590 -               0, { 0, 0 }, { } },
7591 +               0, NULL, 0, { 0, 0 }, { } },
7592               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7593                 -NF_ACCEPT - 1 } },
7594             /* LOCAL_OUT */
7595 @@ -91,7 +91,7 @@
7596                 0,
7597                 sizeof(struct ipt_entry),
7598                 sizeof(struct ipt_standard),
7599 -               0, { 0, 0 }, { } },
7600 +               0, NULL, 0, { 0, 0 }, { } },
7601               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
7602                 -NF_ACCEPT - 1 } }
7603      },
7604 @@ -100,7 +100,7 @@
7605         0,
7606         sizeof(struct ipt_entry),
7607         sizeof(struct ipt_error),
7608 -       0, { 0, 0 }, { } },
7609 +       0, NULL, 0, { 0, 0 }, { } },
7610        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
7611           { } },
7612         "ERROR"
7613 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c
7614 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_standalone.c  2004-04-28 03:36:29.000000000 +0200
7615 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_standalone.c      2004-04-30 09:12:41.000000000 +0200
7616 @@ -175,6 +175,45 @@
7617         return do_bindings(ct, ctinfo, info, hooknum, pskb);
7618  }
7619  
7620 +struct nat_route_key
7621 +{
7622 +       u_int32_t addr;
7623 +#ifdef CONFIG_XFRM
7624 +       u_int16_t port;
7625 +#endif
7626 +};
7627 +
7628 +static inline void
7629 +nat_route_key_get(struct sk_buff *skb, struct nat_route_key *key, int which)
7630 +{
7631 +       struct iphdr *iph = skb->nh.iph;
7632 +
7633 +       key->addr = which ? iph->daddr : iph->saddr;
7634 +#ifdef CONFIG_XFRM
7635 +       key->port = 0;
7636 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7637 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7638 +               key->port = ports[which];
7639 +       }
7640 +#endif
7641 +}
7642 +
7643 +static inline int
7644 +nat_route_key_compare(struct sk_buff *skb, struct nat_route_key *key, int which)
7645 +{
7646 +       struct iphdr *iph = skb->nh.iph;
7647 +
7648 +       if (key->addr != (which ? iph->daddr : iph->saddr))
7649 +               return 1;
7650 +#ifdef CONFIG_XFRM
7651 +       if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) {
7652 +               u_int16_t *ports = (u_int16_t *)(skb->nh.raw + iph->ihl*4);
7653 +               if (key->port != ports[which])
7654 +                       return 1;
7655 +       }
7656 +#endif
7657 +}
7658 +
7659  static unsigned int
7660  ip_nat_out(unsigned int hooknum,
7661            struct sk_buff **pskb,
7662 @@ -182,6 +221,9 @@
7663            const struct net_device *out,
7664            int (*okfn)(struct sk_buff *))
7665  {
7666 +       struct nat_route_key key;
7667 +       unsigned int ret;
7668 +
7669         /* root is playing with raw sockets. */
7670         if ((*pskb)->len < sizeof(struct iphdr)
7671             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7672 @@ -204,7 +246,29 @@
7673                         return NF_STOLEN;
7674         }
7675  
7676 -       return ip_nat_fn(hooknum, pskb, in, out, okfn);
7677 +       nat_route_key_get(*pskb, &key, 0);
7678 +       ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7679 +
7680 +       if (ret != NF_DROP && ret != NF_STOLEN
7681 +           && nat_route_key_compare(*pskb, &key, 0)) {
7682 +               if (ip_route_me_harder(pskb) != 0)
7683 +                       ret = NF_DROP;
7684 +#ifdef CONFIG_XFRM
7685 +               /*
7686 +                * POST_ROUTING hook is called with fixed outfn, we need
7687 +                * to manually confirm the packet and direct it to the
7688 +                * transformers if a policy matches.
7689 +                */
7690 +               else if ((*pskb)->dst->xfrm != NULL) {
7691 +                       ret = ip_conntrack_confirm(*pskb);
7692 +                       if (ret != NF_DROP) {
7693 +                               dst_output(*pskb);
7694 +                               ret = NF_STOLEN;
7695 +                       }
7696 +               }
7697 +#endif
7698 +       }
7699 +       return ret;
7700  }
7701  
7702  #ifdef CONFIG_IP_NF_NAT_LOCAL
7703 @@ -215,7 +279,7 @@
7704                 const struct net_device *out,
7705                 int (*okfn)(struct sk_buff *))
7706  {
7707 -       u_int32_t saddr, daddr;
7708 +       struct nat_route_key key;
7709         unsigned int ret;
7710  
7711         /* root is playing with raw sockets. */
7712 @@ -223,14 +287,14 @@
7713             || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
7714                 return NF_ACCEPT;
7715  
7716 -       saddr = (*pskb)->nh.iph->saddr;
7717 -       daddr = (*pskb)->nh.iph->daddr;
7718 -
7719 +       nat_route_key_get(*pskb, &key, 1);
7720         ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
7721 +
7722         if (ret != NF_DROP && ret != NF_STOLEN
7723 -           && ((*pskb)->nh.iph->saddr != saddr
7724 -               || (*pskb)->nh.iph->daddr != daddr))
7725 -               return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
7726 +           && nat_route_key_compare(*pskb, &key, 1)) {
7727 +               if (ip_route_me_harder(pskb) != 0)
7728 +                       ret = NF_DROP;
7729 +       }
7730         return ret;
7731  }
7732  #endif
7733 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c
7734 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_nat_talk.c        1970-01-01 01:00:00.000000000 +0100
7735 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_nat_talk.c    2004-04-30 09:14:39.000000000 +0200
7736 @@ -0,0 +1,473 @@
7737 +/* 
7738 + * talk extension for UDP NAT alteration. 
7739 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
7740 + *
7741 + *      This program is free software; you can redistribute it and/or
7742 + *      modify it under the terms of the GNU General Public License
7743 + *      as published by the Free Software Foundation; either version
7744 + *      2 of the License, or (at your option) any later version.
7745 + **
7746 + *     Module load syntax:
7747 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
7748 + *
7749 + *             talk=[0|1]      disable|enable old talk support
7750 + *            ntalk=[0|1]      disable|enable ntalk support
7751 + *           ntalk2=[0|1]      disable|enable ntalk2 support
7752 + *
7753 + *     The default is talk=1 ntalk=1 ntalk2=1
7754 + *
7755 + *  
7756 + */
7757 +#include <linux/module.h>
7758 +#include <linux/netfilter_ipv4.h>
7759 +#include <linux/ip.h>
7760 +#include <linux/udp.h>
7761 +#include <linux/kernel.h>
7762 +#include <net/tcp.h>
7763 +#include <net/udp.h>
7764 +
7765 +#include <linux/netfilter_ipv4/ip_nat.h>
7766 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
7767 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
7768 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
7769 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7770 +
7771 +/* Default all talk protocols are supported */
7772 +static int talk   = 1;
7773 +static int ntalk  = 1;
7774 +static int ntalk2 = 1;
7775 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
7776 +MODULE_DESCRIPTION("talk network address translation module");
7777 +#ifdef MODULE_PARM
7778 +MODULE_PARM(talk, "i");
7779 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
7780 +MODULE_PARM(ntalk, "i");
7781 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
7782 +MODULE_PARM(ntalk2, "i");
7783 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
7784 +#endif
7785 +
7786 +#if 0
7787 +#define DEBUGP printk
7788 +#define IP_NAT_TALK_DEBUG
7789 +#else
7790 +#define DEBUGP(format, args...)
7791 +#endif
7792 +
7793 +/* FIXME: Time out? --RR */
7794 +
7795 +static int
7796 +mangle_packet(struct sk_buff **pskb,
7797 +             struct ip_conntrack *ct,
7798 +             u_int32_t newip,
7799 +             u_int16_t port,
7800 +             struct talk_addr *addr,
7801 +             struct talk_addr *ctl_addr)
7802 +{
7803 +       struct iphdr *iph = (*pskb)->nh.iph;
7804 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7805 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
7806 +
7807 +       /* Fortunately talk sends a structure with the address and
7808 +          port in it. The size of the packet won't change. */
7809 +
7810 +       if (ctl_addr == NULL) {
7811 +               /* response */
7812 +               if (addr->ta_addr == INADDR_ANY)
7813 +                       return 1;
7814 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
7815 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7816 +                      NIPQUAD(newip), ntohs(port));
7817 +               addr->ta_addr = newip;
7818 +               addr->ta_port = port;
7819 +       } else {
7820 +               /* message */
7821 +               if (addr->ta_addr != INADDR_ANY) {
7822 +                       /* Change address inside packet to match way we're mapping
7823 +                          this connection. */
7824 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
7825 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7826 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
7827 +                              ntohs(addr->ta_port));
7828 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7829 +               }
7830 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
7831 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7832 +                      NIPQUAD(newip), ntohs(port));
7833 +               ctl_addr->ta_addr = newip;
7834 +               ctl_addr->ta_port = port;
7835 +       }
7836 +
7837 +       /* Fix checksums */
7838 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
7839 +       udph->check = 0;
7840 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
7841 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
7842 +               
7843 +       ip_send_check(iph);
7844 +       return 1;
7845 +}
7846 +
7847 +static int talk_help_msg(struct ip_conntrack *ct,
7848 +                        struct sk_buff **pskb,
7849 +                        u_char type,
7850 +                        struct talk_addr *addr,
7851 +                        struct talk_addr *ctl_addr)
7852 +{
7853 +       u_int32_t newip;
7854 +       u_int16_t port;
7855 +       
7856 +       unsigned int verdict = NF_ACCEPT;
7857 +
7858 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
7859 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7860 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
7861 +               type);
7862 +
7863 +       /* Change address inside packet to match way we're mapping
7864 +          this connection. */
7865 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7866 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
7867 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
7868 +               NIPQUAD(newip), ntohs(port));
7869 +
7870 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
7871 +               verdict = NF_DROP;
7872 +
7873 +       return verdict;
7874 +}
7875 +
7876 +static int talk_help_response(struct ip_conntrack *ct,
7877 +                             struct ip_conntrack_expect *exp,
7878 +                             struct sk_buff **pskb,
7879 +                             u_char type,
7880 +                             u_char answer,
7881 +                             struct talk_addr *addr)
7882 +{
7883 +       u_int32_t newip;
7884 +       u_int16_t port;
7885 +       struct ip_conntrack_tuple t;
7886 +       struct ip_ct_talk_expect *ct_talk_info;
7887 +
7888 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
7889 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
7890 +               type, answer);
7891 +       
7892 +       LOCK_BH(&ip_talk_lock);
7893 +       ct_talk_info = &exp->help.exp_talk_info;
7894 +
7895 +       if (!(answer == SUCCESS 
7896 +             && (type == LOOK_UP || type == ANNOUNCE)
7897 +             && exp != NULL)) {
7898 +               UNLOCK_BH(&ip_talk_lock);
7899 +               return NF_ACCEPT;
7900 +       }
7901 +               
7902 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
7903 +               ntohs(ct_talk_info->port), 
7904 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
7905 +
7906 +       /* Change address inside packet to match way we're mapping
7907 +          this connection. */
7908 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
7909 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
7910 +       /* We can read expect here without conntrack lock, since it's
7911 +          only set in ip_conntrack_talk , with ip_talk_lock held
7912 +          writable */ 
7913 +       t = exp->tuple;
7914 +       t.dst.ip = newip;
7915 +
7916 +       /* Try to get same port: if not, try to change it. */
7917 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
7918 +               if (type == LOOK_UP)
7919 +                       t.dst.u.tcp.port = htons(port);
7920 +               else
7921 +                       t.dst.u.udp.port = htons(port);
7922 +
7923 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
7924 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
7925 +                       break;
7926 +               }
7927 +       }
7928 +       UNLOCK_BH(&ip_talk_lock);
7929 +
7930 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
7931 +               return NF_DROP;
7932 +       
7933 +       return NF_ACCEPT;
7934 +}
7935 +
7936 +static unsigned int talk_help(struct ip_conntrack *ct,
7937 +                             struct ip_conntrack_expect *exp,
7938 +                             struct ip_nat_info *info,
7939 +                             enum ip_conntrack_info ctinfo,
7940 +                             unsigned int hooknum,
7941 +                             struct sk_buff **pskb,
7942 +                             int talk_port)
7943 +{
7944 +       struct iphdr *iph = (*pskb)->nh.iph;
7945 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
7946 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
7947 +       char *data = (char *)udph + sizeof(struct udphdr);
7948 +       int dir;
7949 +
7950 +       /* Only mangle things once: original direction in POST_ROUTING
7951 +          and reply direction on PRE_ROUTING. */
7952 +       dir = CTINFO2DIR(ctinfo);
7953 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
7954 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
7955 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
7956 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7957 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7958 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7959 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
7960 +               return NF_ACCEPT;
7961 +       }
7962 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
7963 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
7964 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
7965 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
7966 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
7967 +              NIPQUAD(iph->saddr), ntohs(udph->source),
7968 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
7969 +              talk_port);
7970 +
7971 +       /* Because conntrack does not drop packets, checking must be repeated here... */
7972 +       if (talk_port == TALK_PORT) {
7973 +               if (dir == IP_CT_DIR_ORIGINAL
7974 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
7975 +                       return talk_help_msg(ct, pskb,
7976 +                                            ((struct talk_msg *)data)->type, 
7977 +                                            &(((struct talk_msg *)data)->addr),
7978 +                                            &(((struct talk_msg *)data)->ctl_addr));
7979 +               else if (dir == IP_CT_DIR_REPLY
7980 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
7981 +                       return talk_help_response(ct, exp, pskb,
7982 +                                                 ((struct talk_response *)data)->type, 
7983 +                                                 ((struct talk_response *)data)->answer,
7984 +                                                 &(((struct talk_response *)data)->addr));
7985 +               else {  
7986 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
7987 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
7988 +                              (unsigned)udplen - sizeof(struct udphdr), 
7989 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
7990 +                       return NF_DROP;
7991 +               }
7992 +       } else {
7993 +               if (dir == IP_CT_DIR_ORIGINAL) {
7994 +                       if (ntalk
7995 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
7996 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
7997 +                               return talk_help_msg(ct, pskb,
7998 +                                                    ((struct ntalk_msg *)data)->type, 
7999 +                                                    &(((struct ntalk_msg *)data)->addr),
8000 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
8001 +                       else if (ntalk2
8002 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
8003 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
8004 +                                && udplen == sizeof(struct udphdr) 
8005 +                                             + sizeof(struct ntalk2_msg) 
8006 +                                             + ((struct ntalk2_msg *)data)->extended)
8007 +                               return talk_help_msg(ct, pskb,
8008 +                                                    ((struct ntalk2_msg *)data)->type, 
8009 +                                                    &(((struct ntalk2_msg *)data)->addr),
8010 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
8011 +                       else {
8012 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
8013 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8014 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
8015 +                               return NF_DROP;
8016 +                       }
8017 +               } else {
8018 +                       if (ntalk
8019 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
8020 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
8021 +                               return talk_help_response(ct, exp, pskb,
8022 +                                                         ((struct ntalk_response *)data)->type, 
8023 +                                                         ((struct ntalk_response *)data)->answer,
8024 +                                                         &(((struct ntalk_response *)data)->addr));
8025 +                       else if (ntalk2
8026 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
8027 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
8028 +                               return talk_help_response(ct, exp, pskb,
8029 +                                                         ((struct ntalk2_response *)data)->type, 
8030 +                                                         ((struct ntalk2_response *)data)->answer,
8031 +                                                         &(((struct ntalk2_response *)data)->addr));
8032 +                       else {
8033 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
8034 +                                      (unsigned)udplen - sizeof(struct udphdr), 
8035 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
8036 +                               return NF_DROP;
8037 +                       }
8038 +               }
8039 +       }
8040 +}
8041 +
8042 +static unsigned int help(struct ip_conntrack *ct,
8043 +                        struct ip_conntrack_expect *exp,
8044 +                        struct ip_nat_info *info,
8045 +                        enum ip_conntrack_info ctinfo,
8046 +                        unsigned int hooknum,
8047 +                        struct sk_buff **pskb)
8048 +{
8049 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
8050 +}
8051 +
8052 +static unsigned int nhelp(struct ip_conntrack *ct,
8053 +                         struct ip_conntrack_expect *exp,
8054 +                         struct ip_nat_info *info,
8055 +                         enum ip_conntrack_info ctinfo,
8056 +                         unsigned int hooknum,
8057 +                         struct sk_buff **pskb)
8058 +{
8059 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
8060 +}
8061 +
8062 +static unsigned int
8063 +talk_nat_expected(struct sk_buff **pskb,
8064 +                 unsigned int hooknum,
8065 +                 struct ip_conntrack *ct,
8066 +                 struct ip_nat_info *info);
8067 +
8068 +static struct ip_nat_helper talk_helpers[2] = 
8069 +       { { { NULL, NULL },
8070 +            "talk",                                    /* name */
8071 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8072 +            THIS_MODULE,                               /* module */
8073 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
8074 +              { 0, { 0 }, IPPROTO_UDP } },
8075 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8076 +              { 0, { 0 }, 0xFFFF } },
8077 +            help,                                      /* helper */
8078 +            talk_nat_expected },                       /* expectfn */
8079 +         { { NULL, NULL },
8080 +            "ntalk",                                   /* name */
8081 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
8082 +            THIS_MODULE,                                       /* module */
8083 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
8084 +              { 0, { 0 }, IPPROTO_UDP } },
8085 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
8086 +              { 0, { 0 }, 0xFFFF } },
8087 +            nhelp,                                     /* helper */
8088 +            talk_nat_expected }                                /* expectfn */
8089 +       };
8090 +          
8091 +static unsigned int
8092 +talk_nat_expected(struct sk_buff **pskb,
8093 +                 unsigned int hooknum,
8094 +                 struct ip_conntrack *ct,
8095 +                 struct ip_nat_info *info)
8096 +{
8097 +       struct ip_nat_multi_range mr;
8098 +       u_int32_t newdstip, newsrcip, newip;
8099 +       u_int16_t port;
8100 +       unsigned int ret;
8101 +       
8102 +       struct ip_conntrack *master = master_ct(ct);
8103 +
8104 +       IP_NF_ASSERT(info);
8105 +       IP_NF_ASSERT(master);
8106 +
8107 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
8108 +
8109 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
8110 +
8111 +       LOCK_BH(&ip_talk_lock);
8112 +       port = ct->master->help.exp_talk_info.port;
8113 +       UNLOCK_BH(&ip_talk_lock);
8114 +
8115 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
8116 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
8117 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
8118 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
8119 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
8120 +              ct, master);
8121 +
8122 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8123 +               /* Callee client -> caller server */
8124 +#ifdef IP_NAT_TALK_DEBUG
8125 +               struct iphdr *iph = (*pskb)->nh.iph;
8126 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
8127 +
8128 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8129 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
8130 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
8131 +#endif
8132 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
8133 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
8134 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8135 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8136 +       } else {
8137 +               /* Callee client -> caller client */
8138 +#ifdef IP_NAT_TALK_DEBUG
8139 +               struct iphdr *iph = (*pskb)->nh.iph;
8140 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
8141 +
8142 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8143 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
8144 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
8145 +#endif
8146 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
8147 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
8148 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
8149 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
8150 +       }
8151 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
8152 +               newip = newsrcip;
8153 +       else
8154 +               newip = newdstip;
8155 +
8156 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
8157 +
8158 +       mr.rangesize = 1;
8159 +       /* We don't want to manip the per-protocol, just the IPs... */
8160 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
8161 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
8162 +       
8163 +       /* ... unless we're doing a MANIP_DST, in which case, make
8164 +          sure we map to the correct port */
8165 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
8166 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
8167 +               mr.range[0].min = mr.range[0].max
8168 +                       = ((union ip_conntrack_manip_proto)
8169 +                               { .udp = { port } });
8170 +       }
8171 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
8172 +
8173 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
8174 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
8175 +               /* NAT expectfn called with ip_nat_lock write-locked */
8176 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
8177 +       }
8178 +       return ret;
8179 +}
8180 +
8181 +static int __init init(void)
8182 +{
8183 +       int ret = 0;
8184 +
8185 +       if (talk > 0) {
8186 +               ret = ip_nat_helper_register(&talk_helpers[0]);
8187 +
8188 +               if (ret != 0)
8189 +                       return ret;
8190 +       }
8191 +       if (ntalk > 0 || ntalk2 > 0) {
8192 +               ret = ip_nat_helper_register(&talk_helpers[1]);
8193 +
8194 +               if (ret != 0 && talk > 0)
8195 +                       ip_nat_helper_unregister(&talk_helpers[0]);
8196 +       }
8197 +       return ret;
8198 +}
8199 +
8200 +static void __exit fini(void)
8201 +{
8202 +       if (talk > 0)
8203 +               ip_nat_helper_unregister(&talk_helpers[0]);
8204 +       if (ntalk > 0 || ntalk2 > 0)
8205 +               ip_nat_helper_unregister(&talk_helpers[1]);
8206 +}
8207 +
8208 +module_init(init);
8209 +module_exit(fini);
8210 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c
8211 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_pool.c    1970-01-01 01:00:00.000000000 +0100
8212 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_pool.c        2004-04-30 09:10:40.000000000 +0200
8213 @@ -0,0 +1,334 @@
8214 +/* Kernel module for IP pool management */
8215 +
8216 +#include <linux/module.h>
8217 +#include <linux/ip.h>
8218 +#include <linux/skbuff.h>
8219 +#include <linux/netfilter_ipv4/ip_tables.h>
8220 +#include <linux/netfilter_ipv4/ip_pool.h>
8221 +#include <linux/errno.h>
8222 +#include <asm/uaccess.h>
8223 +#include <asm/bitops.h>
8224 +#include <linux/interrupt.h>
8225 +#include <linux/spinlock.h>
8226 +
8227 +#if 0
8228 +#define DP printk
8229 +#else
8230 +#define DP(format, args...)
8231 +#endif
8232 +
8233 +MODULE_LICENSE("GPL");
8234 +
8235 +#define NR_POOL 16
8236 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
8237 +
8238 +struct ip_pool {
8239 +       u_int32_t first_ip;     /* host byte order, included in range */
8240 +       u_int32_t last_ip;      /* host byte order, included in range */
8241 +       void *members;          /* the bitmap proper */
8242 +       int nr_use;             /* total nr. of tests through this */
8243 +       int nr_match;           /* total nr. of matches through this */
8244 +       rwlock_t lock;
8245 +};
8246 +
8247 +static struct ip_pool *POOL;
8248 +
8249 +static inline struct ip_pool *lookup(ip_pool_t index)
8250 +{
8251 +       if (index < 0 || index >= nr_pool) {
8252 +               DP("ip_pool:lookup: bad index %d\n", index);
8253 +               return 0;
8254 +       }
8255 +       return POOL+index;
8256 +}
8257 +
8258 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
8259 +{
8260 +        struct ip_pool *pool = lookup(index);
8261 +       int res = 0;
8262 +
8263 +       if (!pool || !pool->members)
8264 +               return 0;
8265 +       read_lock_bh(&pool->lock);
8266 +       if (pool->members) {
8267 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
8268 +                       addr -= pool->first_ip;
8269 +                       if (test_bit(addr, pool->members)) {
8270 +                               res = 1;
8271 +#ifdef CONFIG_IP_POOL_STATISTICS
8272 +                               pool->nr_match++;
8273 +#endif
8274 +                       }
8275 +               }
8276 +#ifdef CONFIG_IP_POOL_STATISTICS
8277 +               pool->nr_use++;
8278 +#endif
8279 +       }
8280 +       read_unlock_bh(&pool->lock);
8281 +       return res;
8282 +}
8283 +EXPORT_SYMBOL(ip_pool_match);
8284 +
8285 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
8286 +{
8287 +       struct ip_pool *pool;
8288 +       int res = -1;
8289 +
8290 +       pool = lookup(index);
8291 +       if (    !pool || !pool->members
8292 +            || addr < pool->first_ip || addr > pool->last_ip)
8293 +               return -1;
8294 +       read_lock_bh(&pool->lock);
8295 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
8296 +               addr -= pool->first_ip;
8297 +               res = isdel
8298 +                       ? (0 != test_and_clear_bit(addr, pool->members))
8299 +                       : (0 != test_and_set_bit(addr, pool->members));
8300 +       }
8301 +       read_unlock_bh(&pool->lock);
8302 +       return res;
8303 +}
8304 +
8305 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
8306 +{
8307 +       int res = pool_change(index,addr,isdel);
8308 +
8309 +       if (!isdel) res = !res;
8310 +       return res;
8311 +}
8312 +EXPORT_SYMBOL(ip_pool_mod);
8313 +
8314 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
8315 +{
8316 +       return 4*((((b-a+8)/8)+3)/4);
8317 +}
8318 +
8319 +static inline int poolbytes(ip_pool_t index)
8320 +{
8321 +       struct ip_pool *pool = lookup(index);
8322 +
8323 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
8324 +}
8325 +
8326 +static int setpool(
8327 +       struct sock *sk,
8328 +       int optval,
8329 +       void *user,
8330 +       unsigned int len
8331 +) {
8332 +       struct ip_pool_request req;
8333 +
8334 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
8335 +       if (!capable(CAP_NET_ADMIN))
8336 +               return -EPERM;
8337 +       if (optval != SO_IP_POOL)
8338 +               return -EBADF;
8339 +       if (len != sizeof(req))
8340 +               return -EINVAL;
8341 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
8342 +               return -EFAULT;
8343 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
8344 +       return -EINVAL;
8345 +}
8346 +
8347 +static int getpool(
8348 +       struct sock *sk,
8349 +       int optval,
8350 +       void *user,
8351 +       int *len
8352 +) {
8353 +       struct ip_pool_request req;
8354 +       struct ip_pool *pool;
8355 +       ip_pool_t i;
8356 +       int newbytes;
8357 +       void *newmembers;
8358 +       int res;
8359 +
8360 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
8361 +       if (!capable(CAP_NET_ADMIN))
8362 +               return -EINVAL;
8363 +       if (optval != SO_IP_POOL)
8364 +               return -EINVAL;
8365 +       if (*len != sizeof(req)) {
8366 +               return -EFAULT;
8367 +       }
8368 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
8369 +               return -EFAULT;
8370 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
8371 +       if (req.op < IP_POOL_BAD001) {
8372 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
8373 +               return -EFAULT;
8374 +       }
8375 +       switch(req.op) {
8376 +       case IP_POOL_HIGH_NR:
8377 +               DP("ip_pool HIGH_NR\n");
8378 +               req.index = IP_POOL_NONE;
8379 +               for (i=0; i<nr_pool; i++)
8380 +                       if (POOL[i].members)
8381 +                               req.index = i;
8382 +               return copy_to_user(user, &req, sizeof(req));
8383 +       case IP_POOL_LOOKUP:
8384 +               DP("ip_pool LOOKUP\n");
8385 +               pool = lookup(req.index);
8386 +               if (!pool)
8387 +                       return -EINVAL;
8388 +               if (!pool->members)
8389 +                       return -EBADF;
8390 +               req.addr = htonl(pool->first_ip);
8391 +               req.addr2 = htonl(pool->last_ip);
8392 +               return copy_to_user(user, &req, sizeof(req));
8393 +       case IP_POOL_USAGE:
8394 +               DP("ip_pool USE\n");
8395 +               pool = lookup(req.index);
8396 +               if (!pool)
8397 +                       return -EINVAL;
8398 +               if (!pool->members)
8399 +                       return -EBADF;
8400 +               req.addr = pool->nr_use;
8401 +               req.addr2 = pool->nr_match;
8402 +               return copy_to_user(user, &req, sizeof(req));
8403 +       case IP_POOL_TEST_ADDR:
8404 +               DP("ip_pool TEST 0x%08x\n", req.addr);
8405 +               pool = lookup(req.index);
8406 +               if (!pool)
8407 +                       return -EINVAL;
8408 +               res = 0;
8409 +               read_lock_bh(&pool->lock);
8410 +               if (!pool->members) {
8411 +                       DP("ip_pool TEST_ADDR no members in pool\n");
8412 +                       res = -EBADF;
8413 +                       goto unlock_and_return_res;
8414 +               }
8415 +               req.addr = ntohl(req.addr);
8416 +               if (req.addr < pool->first_ip) {
8417 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
8418 +                       res = -ERANGE;
8419 +                       goto unlock_and_return_res;
8420 +               }
8421 +               if (req.addr > pool->last_ip) {
8422 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
8423 +                       res = -ERANGE;
8424 +                       goto unlock_and_return_res;
8425 +               }
8426 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
8427 +                                       pool->members));
8428 +               read_unlock_bh(&pool->lock);
8429 +               return copy_to_user(user, &req, sizeof(req));
8430 +       case IP_POOL_FLUSH:
8431 +               DP("ip_pool FLUSH not yet implemented.\n");
8432 +               return -EBUSY;
8433 +       case IP_POOL_DESTROY:
8434 +               DP("ip_pool DESTROY not yet implemented.\n");
8435 +               return -EBUSY;
8436 +       case IP_POOL_INIT:
8437 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
8438 +               pool = lookup(req.index);
8439 +               if (!pool)
8440 +                       return -EINVAL;
8441 +               req.addr = ntohl(req.addr);
8442 +               req.addr2 = ntohl(req.addr2);
8443 +               if (req.addr > req.addr2) {
8444 +                       DP("ip_pool INIT bad ip range\n");
8445 +                       return -EINVAL;
8446 +               }
8447 +               newbytes = bitmap_bytes(req.addr, req.addr2);
8448 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
8449 +               if (!newmembers) {
8450 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
8451 +                       return -ENOMEM;
8452 +               }
8453 +               memset(newmembers, 0, newbytes);
8454 +               write_lock_bh(&pool->lock);
8455 +               if (pool->members) {
8456 +                       DP("ip_pool INIT pool %d exists\n", req.index);
8457 +                       kfree(newmembers);
8458 +                       res = -EBUSY;
8459 +                       goto unlock_and_return_res;
8460 +               }
8461 +               pool->first_ip = req.addr;
8462 +               pool->last_ip = req.addr2;
8463 +               pool->nr_use = 0;
8464 +               pool->nr_match = 0;
8465 +               pool->members = newmembers;
8466 +               write_unlock_bh(&pool->lock);
8467 +               return 0;
8468 +       case IP_POOL_ADD_ADDR:
8469 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
8470 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
8471 +               return copy_to_user(user, &req, sizeof(req));
8472 +       case IP_POOL_DEL_ADDR:
8473 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
8474 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
8475 +               return copy_to_user(user, &req, sizeof(req));
8476 +       default:
8477 +               DP("ip_pool:getpool bad op %d\n", req.op);
8478 +               return -EINVAL;
8479 +       }
8480 +       return -EINVAL;
8481 +
8482 +unlock_and_return_res:
8483 +       if (pool)
8484 +               read_unlock_bh(&pool->lock);
8485 +       return res;
8486 +}
8487 +
8488 +static struct nf_sockopt_ops so_pool
8489 += { { NULL, NULL }, PF_INET,
8490 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
8491 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
8492 +    0, NULL };
8493 +
8494 +MODULE_PARM(nr_pool, "i");
8495 +
8496 +static int __init init(void)
8497 +{
8498 +       ip_pool_t i;
8499 +       int res;
8500 +
8501 +       if (nr_pool < 1) {
8502 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
8503 +               return -EINVAL;
8504 +       }
8505 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
8506 +       if (!POOL) {
8507 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
8508 +                       nr_pool);
8509 +               return -ENOMEM;
8510 +       }
8511 +       for (i=0; i<nr_pool; i++) {
8512 +               POOL[i].first_ip = 0;
8513 +               POOL[i].last_ip = 0;
8514 +               POOL[i].members = 0;
8515 +               POOL[i].nr_use = 0;
8516 +               POOL[i].nr_match = 0;
8517 +               POOL[i].lock = RW_LOCK_UNLOCKED;
8518 +       }
8519 +       res = nf_register_sockopt(&so_pool);
8520 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
8521 +       if (res != 0) {
8522 +               kfree(POOL);
8523 +               POOL = 0;
8524 +       }
8525 +       return res;
8526 +}
8527 +
8528 +static void __exit fini(void)
8529 +{
8530 +       ip_pool_t i;
8531 +
8532 +       DP("ip_pool:fini BYEBYE\n");
8533 +       nf_unregister_sockopt(&so_pool);
8534 +       for (i=0; i<nr_pool; i++) {
8535 +               if (POOL[i].members) {
8536 +                       kfree(POOL[i].members);
8537 +                       POOL[i].members = 0;
8538 +               }
8539 +       }
8540 +       kfree(POOL);
8541 +       POOL = 0;
8542 +       DP("ip_pool:fini these are the famous last words\n");
8543 +       return;
8544 +}
8545 +
8546 +module_init(init);
8547 +module_exit(fini);
8548 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c
8549 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ip_tables.c  2004-04-28 03:35:21.000000000 +0200
8550 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ip_tables.c      2004-04-30 09:11:53.000000000 +0200
8551 @@ -29,6 +29,14 @@
8552  
8553  #include <linux/netfilter_ipv4/ip_tables.h>
8554  
8555 +static const char *hooknames[] = { 
8556 +       [NF_IP_PRE_ROUTING] "PREROUTING",
8557 +       [NF_IP_LOCAL_IN] "INPUT",
8558 +       [NF_IP_FORWARD] "FORWARD",
8559 +       [NF_IP_LOCAL_OUT] "OUTPUT",
8560 +       [NF_IP_POST_ROUTING] "POSTROUTING",
8561 +};
8562 +
8563  MODULE_LICENSE("GPL");
8564  MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
8565  MODULE_DESCRIPTION("IPv4 packet filter");
8566 @@ -326,6 +334,12 @@
8567  
8568                         t = ipt_get_target(e);
8569                         IP_NF_ASSERT(t->u.kernel.target);
8570 +
8571 +                       /* The packet traced and the rule isn't an unconditional return/END. */
8572 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {       
8573 +                               nf_log_packet(PF_INET, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
8574 +                                             table->name, e->chainname, e->rulenum);
8575 +                       }
8576                         /* Standard target? */
8577                         if (!t->u.kernel.target->target) {
8578                                 int v;
8579 @@ -352,7 +366,6 @@
8580                                         /* set back pointer to next entry */
8581                                         back = next;
8582                                 }
8583 -
8584                                 e = get_entry(table_base, v);
8585                         } else {
8586                                 /* Targets which reenter must return
8587 @@ -478,6 +491,29 @@
8588         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
8589  }
8590  
8591 +static inline int
8592 +find_error_target(struct ipt_entry *s, 
8593 +                 struct ipt_entry *e,
8594 +                 char **chainname)
8595 +{
8596 +       struct ipt_entry_target *t;
8597 +       static struct ipt_entry *found = NULL;
8598 +
8599 +       if (s == e) {
8600 +               if (!found)
8601 +                       return 0;
8602 +               t = ipt_get_target(found);
8603 +               if (strcmp(t->u.user.name, 
8604 +                          IPT_ERROR_TARGET) == 0) {
8605 +                       *chainname = t->data;
8606 +                       return 1;
8607 +               }
8608 +       } else
8609 +               found = s;
8610 +       
8611 +       return 0;
8612 +}
8613 +
8614  /* All zeroes == unconditional rule. */
8615  static inline int
8616  unconditional(const struct ipt_ip *ip)
8617 @@ -497,6 +533,8 @@
8618  mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
8619  {
8620         unsigned int hook;
8621 +       char *chainname = NULL;
8622 +       u_int32_t rulenum;
8623  
8624         /* No recursion; use packet counter to save back ptrs (reset
8625            to 0 as we leave), and comefrom to save source hook bitmask */
8626 @@ -510,6 +548,8 @@
8627  
8628                 /* Set initial back pointer. */
8629                 e->counters.pcnt = pos;
8630 +               rulenum = 1;
8631 +               chainname = (char *) hooknames[hook];
8632  
8633                 for (;;) {
8634                         struct ipt_standard_target *t
8635 @@ -522,6 +562,8 @@
8636                         }
8637                         e->comefrom
8638                                 |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
8639 +                       e->rulenum = rulenum++;
8640 +                       e->chainname = chainname;
8641  
8642                         /* Unconditional return/END. */
8643                         if (e->target_offset == sizeof(struct ipt_entry)
8644 @@ -531,6 +573,10 @@
8645                             && unconditional(&e->ip)) {
8646                                 unsigned int oldpos, size;
8647  
8648 +                               /* Set unconditional rulenum to zero. */
8649 +                               e->rulenum = 0;
8650 +                               e->counters.bcnt = 0;
8651 +
8652                                 /* Return: backtrack through the last
8653                                    big jump. */
8654                                 do {
8655 @@ -556,6 +602,11 @@
8656                                                 (newinfo->entries + pos);
8657                                 } while (oldpos == pos + e->next_offset);
8658  
8659 +                               /* Restore chainname, rulenum. */
8660 +                               chainname = e->chainname;
8661 +                               rulenum = e->counters.bcnt;
8662 +                               e->counters.bcnt = 0;
8663 +
8664                                 /* Move along one */
8665                                 size = e->next_offset;
8666                                 e = (struct ipt_entry *)
8667 @@ -571,6 +622,17 @@
8668                                         /* This a jump; chase it. */
8669                                         duprintf("Jump rule %u -> %u\n",
8670                                                  pos, newpos);
8671 +                                       e->counters.bcnt = rulenum++;
8672 +                                       rulenum = 1;
8673 +                                       e = (struct ipt_entry *)
8674 +                                               (newinfo->entries + newpos);
8675 +                                       if (IPT_ENTRY_ITERATE(newinfo->entries,
8676 +                                                             newinfo->size,
8677 +                                                             find_error_target,
8678 +                                                             e, &chainname) == 0) {
8679 +                                               printk("ip_tables: table screwed up!\n");
8680 +                                               return 0;
8681 +                                       }
8682                                 } else {
8683                                         /* ... this is a fallthru */
8684                                         newpos = pos + e->next_offset;
8685 @@ -1716,9 +1778,9 @@
8686  };
8687  
8688  #ifdef CONFIG_PROC_FS
8689 -static inline int print_name(const char *i,
8690 -                            off_t start_offset, char *buffer, int length,
8691 -                            off_t *pos, unsigned int *count)
8692 +static int print_name(const char *i,
8693 +                      off_t start_offset, char *buffer, int length,
8694 +                      off_t *pos, unsigned int *count)
8695  {
8696         if ((*count)++ >= start_offset) {
8697                 unsigned int namelen;
8698 @@ -1752,6 +1814,15 @@
8699         return pos;
8700  }
8701  
8702 +static inline int print_target(const struct ipt_target *t,
8703 +                               off_t start_offset, char *buffer, int length,
8704 +                               off_t *pos, unsigned int *count)
8705 +{
8706 +       if (t != &ipt_standard_target && t != &ipt_error_target)
8707 +               return 0;
8708 +       return print_name((char *)t, start_offset, buffer, length, pos, count);
8709 +}
8710 +
8711  static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
8712  {
8713         off_t pos = 0;
8714 @@ -1760,7 +1831,7 @@
8715         if (down_interruptible(&ipt_mutex) != 0)
8716                 return 0;
8717  
8718 -       LIST_FIND(&ipt_target, print_name, void *,
8719 +       LIST_FIND(&ipt_target, print_target, struct ipt_target *,
8720                   offset, buffer, length, &pos, &count);
8721         
8722         up(&ipt_mutex);
8723 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c
8724 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_CONNMARK.c       1970-01-01 01:00:00.000000000 +0100
8725 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_CONNMARK.c   2004-04-30 09:11:35.000000000 +0200
8726 @@ -0,0 +1,118 @@
8727 +/* This kernel module is used to modify the connection mark values, or
8728 + * to optionally restore the skb nfmark from the connection mark
8729 + *
8730 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
8731 + * by Henrik Nordstrom <hno@marasystems.com>
8732 + *
8733 + * This program is free software; you can redistribute it and/or modify
8734 + * it under the terms of the GNU General Public License as published by
8735 + * the Free Software Foundation; either version 2 of the License, or
8736 + * (at your option) any later version.
8737 + *
8738 + * This program is distributed in the hope that it will be useful,
8739 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8740 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8741 + * GNU General Public License for more details.
8742 + *
8743 + * You should have received a copy of the GNU General Public License
8744 + * along with this program; if not, write to the Free Software
8745 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
8746 + */
8747 +#include <linux/module.h>
8748 +#include <linux/skbuff.h>
8749 +#include <linux/ip.h>
8750 +#include <net/checksum.h>
8751 +
8752 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
8753 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
8754 +MODULE_LICENSE("GPL");
8755 +
8756 +#include <linux/netfilter_ipv4/ip_tables.h>
8757 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
8758 +#include <linux/netfilter_ipv4/ip_conntrack.h>
8759 +
8760 +static unsigned int
8761 +target(struct sk_buff **pskb,
8762 +       const struct net_device *in,
8763 +       const struct net_device *out,
8764 +       unsigned int hooknum,
8765 +       const void *targinfo,
8766 +       void *userinfo)
8767 +{
8768 +       const struct ipt_connmark_target_info *markinfo = targinfo;
8769 +       unsigned long diff;
8770 +       unsigned long nfmark;
8771 +       unsigned long newmark;
8772 +
8773 +       enum ip_conntrack_info ctinfo;
8774 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
8775 +       if (ct) {
8776 +           switch(markinfo->mode) {
8777 +           case IPT_CONNMARK_SET:
8778 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
8779 +               if (newmark != ct->mark)
8780 +                   ct->mark = newmark;
8781 +               break;
8782 +           case IPT_CONNMARK_SAVE:
8783 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
8784 +               if (ct->mark != newmark)
8785 +                   ct->mark = newmark;
8786 +               break;
8787 +           case IPT_CONNMARK_RESTORE:
8788 +               nfmark = (*pskb)->nfmark;
8789 +               diff = (ct->mark ^ nfmark & markinfo->mask);
8790 +               if (diff != 0) {
8791 +                   (*pskb)->nfmark = nfmark ^ diff;
8792 +                   (*pskb)->nfcache |= NFC_ALTERED;
8793 +               }
8794 +               break;
8795 +           }
8796 +       }
8797 +
8798 +       return IPT_CONTINUE;
8799 +}
8800 +
8801 +static int
8802 +checkentry(const char *tablename,
8803 +          const struct ipt_entry *e,
8804 +          void *targinfo,
8805 +          unsigned int targinfosize,
8806 +          unsigned int hook_mask)
8807 +{
8808 +       struct ipt_connmark_target_info *matchinfo = targinfo;
8809 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
8810 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
8811 +                      targinfosize,
8812 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
8813 +               return 0;
8814 +       }
8815 +
8816 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
8817 +           if (strcmp(tablename, "mangle") != 0) {
8818 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8819 +                   return 0;
8820 +           }
8821 +       }
8822 +
8823 +       return 1;
8824 +}
8825 +
8826 +static struct ipt_target ipt_connmark_reg = {
8827 +       .name = "CONNMARK",
8828 +       .target = &target,
8829 +       .checkentry = &checkentry,
8830 +       .me = THIS_MODULE
8831 +};
8832 +
8833 +static int __init init(void)
8834 +{
8835 +       return ipt_register_target(&ipt_connmark_reg);
8836 +}
8837 +
8838 +static void __exit fini(void)
8839 +{
8840 +       ipt_unregister_target(&ipt_connmark_reg);
8841 +}
8842 +
8843 +module_init(init);
8844 +module_exit(fini);
8845 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c
8846 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPMARK.c 1970-01-01 01:00:00.000000000 +0100
8847 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPMARK.c     2004-04-30 09:11:38.000000000 +0200
8848 @@ -0,0 +1,81 @@
8849 +/* This is a module which is used for setting the NFMARK field of an skb. */
8850 +#include <linux/module.h>
8851 +#include <linux/skbuff.h>
8852 +#include <linux/ip.h>
8853 +#include <net/checksum.h>
8854 +
8855 +#include <linux/netfilter_ipv4/ip_tables.h>
8856 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
8857 +
8858 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
8859 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
8860 +MODULE_LICENSE("GPL");
8861 +
8862 +static unsigned int
8863 +target(struct sk_buff **pskb,
8864 +       const struct net_device *in,
8865 +       const struct net_device *out,
8866 +       unsigned int hooknum,
8867 +       const void *targinfo,
8868 +       void *userinfo)
8869 +{
8870 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
8871 +       struct iphdr *iph = (*pskb)->nh.iph;
8872 +       unsigned long mark;
8873 +
8874 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
8875 +               mark = (unsigned long) ntohl(iph->saddr);
8876 +       else
8877 +               mark = (unsigned long) ntohl(iph->daddr);
8878 +
8879 +       mark &= ipmarkinfo->andmask;
8880 +       mark |= ipmarkinfo->ormask;
8881 +       
8882 +       if ((*pskb)->nfmark != mark) {
8883 +               (*pskb)->nfmark = mark;
8884 +               (*pskb)->nfcache |= NFC_ALTERED;
8885 +       }
8886 +       return IPT_CONTINUE;
8887 +}
8888 +
8889 +static int
8890 +checkentry(const char *tablename,
8891 +          const struct ipt_entry *e,
8892 +           void *targinfo,
8893 +           unsigned int targinfosize,
8894 +           unsigned int hook_mask)
8895 +{
8896 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
8897 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
8898 +                      targinfosize,
8899 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
8900 +               return 0;
8901 +       }
8902 +
8903 +       if (strcmp(tablename, "mangle") != 0) {
8904 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8905 +               return 0;
8906 +       }
8907 +
8908 +       return 1;
8909 +}
8910 +
8911 +static struct ipt_target ipt_ipmark_reg = { 
8912 +       .name = "IPMARK",
8913 +       .target = target,
8914 +       .checkentry = checkentry,
8915 +       .me = THIS_MODULE
8916 +};
8917 +
8918 +static int __init init(void)
8919 +{
8920 +       return ipt_register_target(&ipt_ipmark_reg);
8921 +}
8922 +
8923 +static void __exit fini(void)
8924 +{
8925 +       ipt_unregister_target(&ipt_ipmark_reg);
8926 +}
8927 +
8928 +module_init(init);
8929 +module_exit(fini);
8930 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
8931 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  1970-01-01 01:00:00.000000000 +0100
8932 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      2004-04-30 09:10:05.000000000 +0200
8933 @@ -0,0 +1,89 @@
8934 +/**
8935 + * Strip all IP options in the IP packet header.
8936 + *
8937 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
8938 + * This software is distributed under GNU GPL v2, 1991
8939 + */
8940 +
8941 +#include <linux/module.h>
8942 +#include <linux/skbuff.h>
8943 +#include <linux/ip.h>
8944 +#include <net/checksum.h>
8945 +
8946 +#include <linux/netfilter_ipv4/ip_tables.h>
8947 +
8948 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
8949 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
8950 +MODULE_LICENSE("GPL");
8951 +
8952 +static unsigned int
8953 +target(struct sk_buff **pskb,
8954 +       const struct net_device *in,
8955 +       const struct net_device *out,
8956 +       unsigned int hooknum,
8957 +       const void *targinfo,
8958 +       void *userinfo)
8959 +{
8960 +       struct iphdr *iph;
8961 +       struct sk_buff *skb;
8962 +       struct ip_options *opt;
8963 +       unsigned char *optiph;
8964 +       int l;
8965 +       
8966 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
8967 +               return NF_DROP;
8968
8969 +       skb = (*pskb);
8970 +       iph = (*pskb)->nh.iph;
8971 +       optiph = skb->nh.raw;
8972 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
8973 +
8974 +       /* if no options in packet then nothing to clear. */
8975 +       if (iph->ihl * 4 == sizeof(struct iphdr))
8976 +               return IPT_CONTINUE;
8977 +
8978 +       /* else clear all options */
8979 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
8980 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
8981 +       opt = &(IPCB(skb)->opt);
8982 +       opt->is_data = 0;
8983 +       opt->optlen = l;
8984 +
8985 +       skb->nfcache |= NFC_ALTERED;
8986 +
8987 +        return IPT_CONTINUE;
8988 +}
8989 +
8990 +static int
8991 +checkentry(const char *tablename,
8992 +          const struct ipt_entry *e,
8993 +           void *targinfo,
8994 +           unsigned int targinfosize,
8995 +           unsigned int hook_mask)
8996 +{
8997 +       if (strcmp(tablename, "mangle")) {
8998 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
8999 +               return 0;
9000 +       }
9001 +       /* nothing else to check because no parameters */
9002 +       return 1;
9003 +}
9004 +
9005 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
9006 +       .name = "IPV4OPTSSTRIP",
9007 +       .target = target,
9008 +       .checkentry = checkentry,
9009 +       .me = THIS_MODULE };
9010 +
9011 +static int __init init(void)
9012 +{
9013 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
9014 +}
9015 +
9016 +static void __exit fini(void)
9017 +{
9018 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
9019 +}
9020 +
9021 +module_init(init);
9022 +module_exit(fini);
9023 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c
9024 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c        1970-01-01 01:00:00.000000000 +0100
9025 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_NETLINK.c    2004-04-30 09:10:09.000000000 +0200
9026 @@ -0,0 +1,119 @@
9027 +#include <linux/module.h>
9028 +#include <linux/version.h>
9029 +#include <linux/config.h>
9030 +#include <linux/socket.h>
9031 +#include <linux/skbuff.h>
9032 +#include <linux/kernel.h>
9033 +#include <linux/netlink.h>
9034 +#include <linux/netdevice.h>
9035 +#include <linux/mm.h>
9036 +#include <linux/socket.h>
9037 +#include <linux/netfilter_ipv4/ip_tables.h>
9038 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
9039 +#include <net/sock.h>
9040 +
9041 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
9042 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
9043 +MODULE_LICENSE("GPL");
9044 +
9045 +#if 0
9046 +#define DEBUGP printk
9047 +#else
9048 +#define DEBUGP(format, args...)
9049 +#endif
9050 +
9051 +static struct sock *ipfwsk;
9052 +
9053 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
9054 +                                   unsigned int hooknum,
9055 +                                   const struct net_device *in,
9056 +                                   const struct net_device *out,
9057 +                                   const void *targinfo, void *userinfo)
9058 +{
9059 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9060 +       struct iphdr *ip = (*pskb)->nh.iph;
9061 +       struct sk_buff *outskb;
9062 +       struct netlink_t nlhdr;
9063 +       size_t len=0;
9064 +
9065 +       /* Allocate a socket buffer */
9066 +       if ( MASK(nld->flags, USE_SIZE) )
9067 +               len = nld->size+sizeof(nlhdr);
9068 +       else
9069 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
9070 +
9071 +       outskb=alloc_skb(len, GFP_ATOMIC);
9072 +
9073 +       if (outskb) {
9074 +               nlhdr.len=len;
9075 +               
9076 +               if ( MASK(nld->flags, USE_MARK) )
9077 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
9078 +               else
9079 +                       nlhdr.mark=(*pskb)->nfmark;
9080 +               
9081 +               if ( in && in->name ) {
9082 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
9083 +               }else if ( out && out->name ){
9084 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
9085 +               }
9086 +
9087 +               skb_put(outskb, len);
9088 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
9089 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
9090 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
9091 +       }else{
9092 +               if (net_ratelimit())
9093 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
9094 +       }
9095 +
9096 +       if ( MASK(nld->flags, USE_DROP) )
9097 +               return NF_DROP;
9098 +
9099 +       return IPT_CONTINUE;
9100 +}
9101 +
9102 +static int ipt_netlink_checkentry(const char *tablename,
9103 +                              const struct ipt_entry *e,
9104 +                              void *targinfo,
9105 +                              unsigned int targinfosize,
9106 +                              unsigned int hookmask)
9107 +{
9108 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
9109 +
9110 +       return 1;
9111 +}
9112 +
9113 +static struct ipt_target ipt_netlink_reg = { 
9114 +       {NULL, NULL},
9115 +       "NETLINK",
9116 +       ipt_netlink_target,
9117 +       ipt_netlink_checkentry,
9118 +       NULL,
9119 +       THIS_MODULE
9120 +};
9121 +
9122 +static int __init init(void)
9123 +{
9124 +       DEBUGP("ipt_NETLINK: init module\n");   
9125 +
9126 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
9127 +               return -EINVAL;
9128 +       }
9129 +
9130 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
9131 +               return -EINVAL;
9132 +       }
9133 +
9134 +       return 0;
9135 +}
9136 +
9137 +static void __exit fini(void)
9138 +{
9139 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
9140 +       ipt_unregister_target(&ipt_netlink_reg);
9141 +       if(ipfwsk->sk_socket) sock_release(ipfwsk->sk_socket);
9142 +}
9143 +
9144 +module_init(init);
9145 +module_exit(fini);
9146 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c
9147 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_POOL.c   1970-01-01 01:00:00.000000000 +0100
9148 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_POOL.c       2004-04-30 09:10:40.000000000 +0200
9149 @@ -0,0 +1,116 @@
9150 +/* ipt_POOL.c - netfilter target to manipulate IP pools
9151 + *
9152 + * This target can be used almost everywhere. It acts on some specified
9153 + * IP pool, adding or deleting some IP address in the pool. The address
9154 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
9155 + * of the packet under inspection.
9156 + *
9157 + * The target normally returns IPT_CONTINUE.
9158 + */
9159 +
9160 +#include <linux/types.h>
9161 +#include <linux/ip.h>
9162 +#include <linux/timer.h>
9163 +#include <linux/module.h>
9164 +#include <linux/netfilter.h>
9165 +#include <linux/netdevice.h>
9166 +#include <linux/if.h>
9167 +#include <linux/inetdevice.h>
9168 +#include <net/protocol.h>
9169 +#include <net/checksum.h>
9170 +#include <linux/netfilter_ipv4.h>
9171 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
9172 +#include <linux/netfilter_ipv4/ipt_pool.h>
9173 +
9174 +#if 0
9175 +#define DEBUGP printk
9176 +#else
9177 +#define DEBUGP(format, args...)
9178 +#endif
9179 +
9180 +/*** NOTE NOTE NOTE NOTE ***
9181 +**
9182 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
9183 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
9184 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
9185 +** is modified for the source IP address of the packet under inspection.
9186 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
9187 +**
9188 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
9189 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
9190 +**
9191 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
9192 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
9193 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
9194 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
9195 +*/
9196 +
9197 +static int
9198 +do_check(const char *tablename,
9199 +              const struct ipt_entry *e,
9200 +              void *targinfo,
9201 +              unsigned int targinfosize,
9202 +              unsigned int hook_mask)
9203 +{
9204 +       const struct ipt_pool_info *ipi = targinfo;
9205 +
9206 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
9207 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
9208 +               return 0;
9209 +       }
9210 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
9211 +       return 1;
9212 +}
9213 +
9214 +static unsigned int
9215 +do_target(struct sk_buff **pskb,
9216 +               unsigned int hooknum,
9217 +               const struct net_device *in,
9218 +               const struct net_device *out,
9219 +               const void *targinfo,
9220 +               void *userinfo)
9221 +{
9222 +       const struct ipt_pool_info *ipi = targinfo;
9223 +       int modified;
9224 +       unsigned int verdict = IPT_CONTINUE;
9225 +
9226 +       if (ipi->src != IP_POOL_NONE) {
9227 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
9228 +                                       ipi->flags & IPT_POOL_DEL_SRC);
9229 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
9230 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
9231 +                               verdict = NF_ACCEPT;
9232 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
9233 +                               verdict = NF_DROP;
9234 +               }
9235 +       }
9236 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
9237 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
9238 +                                       ipi->flags & IPT_POOL_DEL_DST);
9239 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
9240 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
9241 +                               verdict = NF_ACCEPT;
9242 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
9243 +                               verdict = NF_DROP;
9244 +               }
9245 +       }
9246 +       return verdict;
9247 +}
9248 +
9249 +static struct ipt_target pool_reg
9250 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
9251 +
9252 +static int __init init(void)
9253 +{
9254 +       DEBUGP("init ipt_POOL\n");
9255 +       return ipt_register_target(&pool_reg);
9256 +}
9257 +
9258 +static void __exit fini(void)
9259 +{
9260 +       DEBUGP("fini ipt_POOL\n");
9261 +       ipt_unregister_target(&pool_reg);
9262 +}
9263 +
9264 +module_init(init);
9265 +module_exit(fini);
9266 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c
9267 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TARPIT.c 1970-01-01 01:00:00.000000000 +0100
9268 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TARPIT.c     2004-04-30 09:11:46.000000000 +0200
9269 @@ -0,0 +1,289 @@
9270 +/* 
9271 + * Kernel module to capture and hold incoming TCP connections using 
9272 + * no local per-connection resources.
9273 + * 
9274 + * Based on ipt_REJECT.c and offering functionality similar to 
9275 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
9276 + * 
9277 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
9278 + * 
9279 + * This program is free software; you can redistribute it and/or modify
9280 + * it under the terms of the GNU General Public License as published by
9281 + * the Free Software Foundation; either version 2 of the License, or
9282 + * (at your option) any later version.
9283 + *
9284 + * This program is distributed in the hope that it will be useful,
9285 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9286 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9287 + * GNU General Public License for more details.
9288 + *
9289 + * You should have received a copy of the GNU General Public License
9290 + * along with this program; if not, write to the Free Software
9291 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
9292 + * 
9293 + * Goal:
9294 + * - Allow incoming TCP connections to be established.
9295 + * - Passing data should result in the connection being switched to the 
9296 + *   persist state (0 byte window), in which the remote side stops sending 
9297 + *   data and asks to continue every 60 seconds.
9298 + * - Attempts to shut down the connection should be ignored completely, so 
9299 + *   the remote side ends up having to time it out.
9300 + *
9301 + * This means:
9302 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
9303 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
9304 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
9305 + */
9306 +
9307 +#include <linux/config.h>
9308 +#include <linux/module.h>
9309 +#include <linux/skbuff.h>
9310 +#include <linux/ip.h>
9311 +#include <net/ip.h>
9312 +#include <net/tcp.h>
9313 +#include <net/icmp.h>
9314 +struct in_device;
9315 +#include <net/route.h>
9316 +#include <linux/random.h>
9317 +#include <linux/netfilter_ipv4/ip_tables.h>
9318 +
9319 +#if 0
9320 +#define DEBUGP printk
9321 +#else
9322 +#define DEBUGP(format, args...)
9323 +#endif
9324 +
9325 +MODULE_LICENSE("GPL");
9326 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
9327 +
9328 +/* Stolen from ip_finish_output2 */
9329 +static int ip_direct_send(struct sk_buff *skb)
9330 +{
9331 +       struct dst_entry *dst = skb->dst;
9332 +       struct hh_cache *hh = dst->hh;
9333 +
9334 +       if (hh) {    
9335 +               read_lock_bh(&hh->hh_lock);
9336 +               memcpy(skb->data - 16, hh->hh_data, 16);
9337 +                read_unlock_bh(&hh->hh_lock);
9338 +                skb_push(skb, hh->hh_len);
9339 +                return hh->hh_output(skb);
9340 +        } else if (dst->neighbour)
9341 +                return dst->neighbour->output(skb);
9342 +
9343 +       if (net_ratelimit())
9344 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
9345 +        kfree_skb(skb);
9346 +        return -EINVAL;
9347 +}
9348 +
9349 +
9350 +/* Send reply */
9351 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
9352 +{
9353 +       struct sk_buff *nskb;
9354 +       struct rtable *nrt;
9355 +       struct tcphdr *otcph, *ntcph;
9356 +       unsigned int otcplen;
9357 +       u_int16_t tmp;
9358 +       struct flowi fl = {};
9359 +
9360 +       /* A truncated TCP header isn't going to be useful */
9361 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
9362 +               return;
9363 +
9364 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
9365 +                                  + oskb->nh.iph->ihl);
9366 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
9367 +
9368 +       /* No replies for RST or FIN */
9369 +       if (otcph->rst || otcph->fin)
9370 +               return;
9371 +
9372 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
9373 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
9374 +               return;
9375 +
9376 +       /* Check checksum. */
9377 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
9378 +                        oskb->nh.iph->daddr,
9379 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
9380 +               return;
9381 +
9382 +       /* Copy skb (even if skb is about to be dropped, we can't just
9383 +           clone it because there may be other things, such as tcpdump,
9384 +           interested in it) */
9385 +       nskb = skb_copy(oskb, GFP_ATOMIC);
9386 +       if (!nskb)
9387 +               return;
9388 +
9389 +       /* This packet will not be the same as the other: clear nf fields */
9390 +       nf_conntrack_put(nskb->nfct);
9391 +       nskb->nfct = NULL;
9392 +       nskb->nfcache = 0;
9393 +#ifdef CONFIG_NETFILTER_DEBUG
9394 +       nskb->nf_debug = 0;
9395 +#endif
9396 +
9397 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
9398 +
9399 +       /* Truncate to length (no data) */
9400 +       ntcph->doff = sizeof(struct tcphdr)/4;
9401 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
9402 +       nskb->nh.iph->tot_len = htons(nskb->len);
9403 +
9404 +       /* Swap source and dest */
9405 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
9406 +       tmp = ntcph->source;
9407 +       ntcph->source = ntcph->dest;
9408 +       ntcph->dest = tmp;
9409 +
9410 +       /* Use supplied sequence number or make a new one */
9411 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
9412 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
9413 +                                                       nskb->nh.iph->daddr, 
9414 +                                                       ntcph->source, 
9415 +                                                       ntcph->dest));
9416 +
9417 +       /* Our SYN-ACKs must have a >0 window */
9418 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
9419 +
9420 +       ntcph->urg_ptr = 0;
9421 +
9422 +       /* Reset flags */
9423 +       ((u_int8_t *)ntcph)[13] = 0;
9424 +
9425 +       if (otcph->syn && otcph->ack) {
9426 +               ntcph->rst = 1;
9427 +               ntcph->ack_seq = 0;
9428 +       } else {
9429 +               ntcph->syn = otcph->syn;
9430 +               ntcph->ack = 1;
9431 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
9432 +       }
9433 +
9434 +       /* Adjust TCP checksum */
9435 +       ntcph->check = 0;
9436 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
9437 +                                  nskb->nh.iph->saddr,
9438 +                                  nskb->nh.iph->daddr,
9439 +                                  csum_partial((char *)ntcph,
9440 +                                               sizeof(struct tcphdr), 0));
9441 +
9442 +       /* Adjust IP TTL */
9443 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
9444 +
9445 +       /* Set DF, id = 0 */
9446 +       nskb->nh.iph->frag_off = htons(IP_DF);
9447 +       nskb->nh.iph->id = 0;
9448 +
9449 +       /* Adjust IP checksum */
9450 +       nskb->nh.iph->check = 0;
9451 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
9452 +                                          nskb->nh.iph->ihl);
9453 +
9454 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
9455 +       fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
9456 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
9457 +       fl.oif = 0;
9458 +       if (ip_route_output_key(&nrt, &fl) != 0)
9459 +               goto free_nskb;
9460 +
9461 +       dst_release(nskb->dst);
9462 +       nskb->dst = &nrt->u.dst;
9463 +
9464 +       /* "Never happens" */
9465 +       if (nskb->len > dst_pmtu(nskb->dst))
9466 +               goto free_nskb;
9467 +
9468 +       ip_direct_send (nskb);
9469 +
9470 +       return;
9471 +
9472 + free_nskb:
9473 +       kfree_skb(nskb);
9474 +}
9475 +
9476 +
9477 +static unsigned int tarpit(struct sk_buff **pskb,
9478 +                          const struct net_device *in,
9479 +                          const struct net_device *out,
9480 +                          unsigned int hooknum,
9481 +                          const void *targinfo,
9482 +                          void *userinfo)
9483 +{
9484 +       struct sk_buff *skb = *pskb;
9485 +       struct rtable *rt = (struct rtable*)skb->dst;
9486 +
9487 +       /* Do we have an input route cache entry? */
9488 +       if (!rt)
9489 +               return NF_DROP;
9490 +
9491 +        /* No replies to physical multicast/broadcast */
9492 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
9493 +               return NF_DROP;
9494 +
9495 +        /* Now check at the protocol level */
9496 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
9497 +                return NF_DROP;
9498 +
9499 +       /* Our naive response construction doesn't deal with IP
9500 +           options, and probably shouldn't try. */
9501 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
9502 +               return NF_DROP;
9503 +
9504 +        /* We aren't interested in fragments */
9505 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
9506 +                return NF_DROP;
9507 +
9508 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
9509 +
9510 +       return NF_DROP;
9511 +}
9512 +
9513 +
9514 +static int check(const char *tablename,
9515 +                const struct ipt_entry *e,
9516 +                void *targinfo,
9517 +                unsigned int targinfosize,
9518 +                unsigned int hook_mask)
9519 +{
9520 +       /* Only allow these for input/forward packet filtering. */
9521 +       if (strcmp(tablename, "filter") != 0) {
9522 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
9523 +               return 0;
9524 +       }
9525 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
9526 +                           | (1 << NF_IP_FORWARD))) != 0) {
9527 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
9528 +               return 0;
9529 +       }
9530 +
9531 +       /* Must specify that it's a TCP packet */
9532 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
9533 +               DEBUGP("TARPIT: not valid for non-tcp\n");
9534 +               return 0;
9535 +       }
9536 +
9537 +       return 1;
9538 +}
9539 +
9540 +static struct ipt_target ipt_tarpit_reg = { 
9541 +       .name = "TARPIT",
9542 +       .target = tarpit,
9543 +       .checkentry = check,
9544 +       .me = THIS_MODULE
9545 +};
9546 +
9547 +static int __init init(void)
9548 +{
9549 +       return ipt_register_target(&ipt_tarpit_reg);
9550 +}
9551 +
9552 +static void __exit fini(void)
9553 +{
9554 +       ipt_unregister_target(&ipt_tarpit_reg);
9555 +}
9556 +
9557 +module_init(init);
9558 +module_exit(fini);
9559 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c
9560 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TRACE.c  1970-01-01 01:00:00.000000000 +0100
9561 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TRACE.c      2004-04-30 09:11:53.000000000 +0200
9562 @@ -0,0 +1,64 @@
9563 +/* This is a module which is used for setting 
9564 + * the NFC_TRACE flag in the nfcache field of an skb. 
9565 + */
9566 +#include <linux/module.h>
9567 +#include <linux/skbuff.h>
9568 +
9569 +#include <linux/netfilter_ipv4/ip_tables.h>
9570 +
9571 +static unsigned int
9572 +target(struct sk_buff **pskb,
9573 +       const struct net_device *in,
9574 +       const struct net_device *out,
9575 +       unsigned int hooknum,
9576 +       const void *targinfo,
9577 +       void *userinfo)
9578 +{
9579 +       (*pskb)->nfcache |= NFC_TRACE;
9580 +       return IPT_CONTINUE;
9581 +}
9582 +
9583 +static int
9584 +checkentry(const char *tablename,
9585 +          const struct ipt_entry *e,
9586 +           void *targinfo,
9587 +           unsigned int targinfosize,
9588 +           unsigned int hook_mask)
9589 +{
9590 +       if (targinfosize != 0) {
9591 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
9592 +                      targinfosize);
9593 +               return 0;
9594 +       }
9595 +
9596 +       if (strcmp(tablename, "raw") != 0) {
9597 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
9598 +               return 0;
9599 +       }
9600 +
9601 +       return 1;
9602 +}
9603 +
9604 +static struct ipt_target ipt_trace_reg = { 
9605 +       .name = "TRACE", 
9606 +       .target = target, 
9607 +       .checkentry = checkentry, 
9608 +       .me = THIS_MODULE
9609 +};
9610 +
9611 +static int __init init(void)
9612 +{
9613 +       if (ipt_register_target(&ipt_trace_reg))
9614 +               return -EINVAL;
9615 +
9616 +       return 0;
9617 +}
9618 +
9619 +static void __exit fini(void)
9620 +{
9621 +       ipt_unregister_target(&ipt_trace_reg);
9622 +}
9623 +
9624 +module_init(init);
9625 +module_exit(fini);
9626 +MODULE_LICENSE("GPL");
9627 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c
9628 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_TTL.c    1970-01-01 01:00:00.000000000 +0100
9629 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_TTL.c        2004-04-30 09:10:15.000000000 +0200
9630 @@ -0,0 +1,120 @@
9631 +/* TTL modification target for IP tables
9632 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
9633 + *
9634 + * Version: $Revision$
9635 + *
9636 + * This software is distributed under the terms of GNU GPL
9637 + */
9638 +
9639 +#include <linux/module.h>
9640 +#include <linux/skbuff.h>
9641 +#include <linux/ip.h>
9642 +#include <net/checksum.h>
9643 +
9644 +#include <linux/netfilter_ipv4/ip_tables.h>
9645 +#include <linux/netfilter_ipv4/ipt_TTL.h>
9646 +
9647 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
9648 +MODULE_DESCRIPTION("IP tables TTL modification module");
9649 +MODULE_LICENSE("GPL");
9650 +
9651 +static unsigned int 
9652 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 
9653 +               const struct net_device *out, unsigned int hooknum, 
9654 +               const void *targinfo, void *userinfo)
9655 +{
9656 +       struct iphdr *iph;
9657 +       const struct ipt_TTL_info *info = targinfo;
9658 +       u_int16_t diffs[2];
9659 +       int new_ttl;
9660 +
9661 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
9662 +               return NF_DROP;
9663 +
9664 +       iph = (*pskb)->nh.iph;
9665 +                        
9666 +       switch (info->mode) {
9667 +               case IPT_TTL_SET:
9668 +                       new_ttl = info->ttl;
9669 +                       break;
9670 +               case IPT_TTL_INC:
9671 +                       new_ttl = iph->ttl + info->ttl;
9672 +                       if (new_ttl > 255)
9673 +                               new_ttl = 255;
9674 +                       break;
9675 +               case IPT_TTL_DEC:
9676 +                       new_ttl = iph->ttl + info->ttl;
9677 +                       if (new_ttl < 0)
9678 +                               new_ttl = 0;
9679 +                       break;
9680 +               default:
9681 +                       new_ttl = iph->ttl;
9682 +                       break;
9683 +       }
9684 +
9685 +       if (new_ttl != iph->ttl) {
9686 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
9687 +               iph->ttl = new_ttl;
9688 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
9689 +               iph->check = csum_fold(csum_partial((char *)diffs,
9690 +                                                   sizeof(diffs),
9691 +                                                   iph->check^0xFFFF));
9692 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
9693 +       }
9694 +
9695 +       return IPT_CONTINUE;
9696 +}
9697 +
9698 +static int ipt_ttl_checkentry(const char *tablename,
9699 +               const struct ipt_entry *e,
9700 +               void *targinfo,
9701 +               unsigned int targinfosize,
9702 +               unsigned int hook_mask)
9703 +{
9704 +       struct ipt_TTL_info *info = targinfo;
9705 +
9706 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
9707 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
9708 +                               targinfosize,
9709 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
9710 +               return 0;       
9711 +       }       
9712 +
9713 +       if (strcmp(tablename, "mangle")) {
9714 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9715 +               return 0;
9716 +       }
9717 +
9718 +       if (info->mode > IPT_TTL_MAXMODE) {
9719 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
9720 +                       info->mode);
9721 +               return 0;
9722 +       }
9723 +
9724 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
9725 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
9726 +               return 0;
9727 +       }
9728 +       
9729 +       return 1;
9730 +}
9731 +
9732 +static struct ipt_target ipt_TTL = { 
9733 +       .name = "TTL",
9734 +       .target = ipt_ttl_target, 
9735 +       .checkentry = ipt_ttl_checkentry, 
9736 +       .me = THIS_MODULE 
9737 +};
9738 +
9739 +static int __init init(void)
9740 +{
9741 +       return ipt_register_target(&ipt_TTL);
9742 +}
9743 +
9744 +static void __exit fini(void)
9745 +{
9746 +       ipt_unregister_target(&ipt_TTL);
9747 +}
9748 +
9749 +module_init(init);
9750 +module_exit(fini);
9751 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c
9752 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_XOR.c    1970-01-01 01:00:00.000000000 +0100
9753 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_XOR.c        2004-04-30 09:11:56.000000000 +0200
9754 @@ -0,0 +1,117 @@
9755 +/* XOR target for IP tables
9756 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
9757 + * Based on ipt_TTL.c
9758 + *
9759 + * Version 1.0
9760 + *
9761 + * This software is distributed under the terms of GNU GPL
9762 + */
9763 +
9764 +#include <linux/module.h>
9765 +#include <linux/skbuff.h>
9766 +#include <linux/ip.h>
9767 +#include <linux/tcp.h>
9768 +#include <linux/udp.h>
9769 +
9770 +#include <linux/netfilter_ipv4/ip_tables.h>
9771 +#include <linux/netfilter_ipv4/ipt_XOR.h>
9772 +
9773 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
9774 +MODULE_DESCRIPTION("IP tables XOR module");
9775 +MODULE_LICENSE("GPL");
9776 +
9777 +static unsigned int 
9778 +ipt_xor_target(struct sk_buff **pskb, 
9779 +               const struct net_device *in, const struct net_device *out, 
9780 +               unsigned int hooknum, const void *targinfo, void *userinfo)
9781 +{
9782 +       struct ipt_XOR_info *info = (void *) targinfo;
9783 +       struct iphdr *iph;
9784 +       struct tcphdr *tcph;
9785 +       struct udphdr *udph;
9786 +       int i, j, k;
9787 +
9788 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
9789 +               return NF_DROP;
9790 +
9791 +       iph = (*pskb)->nh.iph;
9792 +  
9793 +       if (iph->protocol == IPPROTO_TCP) {
9794 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
9795 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
9796 +                       for (k=0; k<=info->block_size; k++) {
9797 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
9798 +                                               info->key[j];
9799 +                               i++;
9800 +                       }
9801 +                       j++;
9802 +                       if (info->key[j] == 0x00)
9803 +                               j = 0;
9804 +               }
9805 +       } else if (iph->protocol == IPPROTO_UDP) {
9806 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
9807 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
9808 +                       for (k=0; k<=info->block_size; k++) {
9809 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
9810 +                                               info->key[j];
9811 +                               i++;
9812 +                       }
9813 +                       j++;
9814 +                       if (info->key[j] == 0x00)
9815 +                               j = 0;
9816 +               }
9817 +       }
9818 +  
9819 +       return IPT_CONTINUE;
9820 +}
9821 +
9822 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
9823 +               void *targinfo, unsigned int targinfosize, 
9824 +               unsigned int hook_mask)
9825 +{
9826 +       struct ipt_XOR_info *info = targinfo;
9827 +
9828 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
9829 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
9830 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
9831 +               return 0;
9832 +       }       
9833 +
9834 +       if (strcmp(tablename, "mangle")) {
9835 +               printk(KERN_WARNING "XOR: can only be called from"
9836 +                               "\"mangle\" table, not \"%s\"\n", tablename);
9837 +               return 0; 
9838 +       }
9839 +
9840 +       if (!strcmp(info->key, "")) {
9841 +               printk(KERN_WARNING "XOR: You must specify a key");
9842 +               return 0;
9843 +       }
9844 +
9845 +       if (info->block_size == 0) {
9846 +               printk(KERN_WARNING "XOR: You must specify a block-size");
9847 +               return 0;
9848 +       }
9849 +
9850 +       return 1;
9851 +}
9852 +
9853 +static struct ipt_target ipt_XOR = { 
9854 +       .name = "XOR",
9855 +       .target = ipt_xor_target, 
9856 +       .checkentry = ipt_xor_checkentry,
9857 +       .me = THIS_MODULE,
9858 +};
9859 +
9860 +static int __init init(void)
9861 +{
9862 +       return ipt_register_target(&ipt_XOR);
9863 +}
9864 +
9865 +static void __exit fini(void)
9866 +{
9867 +       ipt_unregister_target(&ipt_XOR);
9868 +}
9869 +
9870 +module_init(init);
9871 +module_exit(fini);
9872 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c
9873 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_addrtype.c       1970-01-01 01:00:00.000000000 +0100
9874 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_addrtype.c   2004-04-30 09:11:57.000000000 +0200
9875 @@ -0,0 +1,68 @@
9876 +/*
9877 + *  iptables module to match inet_addr_type() of an ip.
9878 + */
9879 +
9880 +#include <linux/module.h>
9881 +#include <linux/skbuff.h>
9882 +#include <linux/netdevice.h>
9883 +#include <net/route.h>
9884 +
9885 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
9886 +#include <linux/netfilter_ipv4/ip_tables.h>
9887 +
9888 +MODULE_LICENSE("GPL");
9889 +
9890 +static inline int match_type(u_int32_t addr, u_int16_t mask)
9891 +{
9892 +       return !!(mask & (1 << inet_addr_type(addr)));
9893 +}
9894 +
9895 +static int match(const struct sk_buff *skb, const struct net_device *in,
9896 +                const struct net_device *out, const void *matchinfo,
9897 +                int offset, int *hotdrop)
9898 +{
9899 +       const struct ipt_addrtype_info *info = matchinfo;
9900 +       const struct iphdr *iph = skb->nh.iph;
9901 +       int ret = 1;
9902 +
9903 +       if (info->source)
9904 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
9905 +       if (info->dest)
9906 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
9907 +       
9908 +       return ret;
9909 +}
9910 +
9911 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
9912 +                     void *matchinfo, unsigned int matchsize,
9913 +                     unsigned int hook_mask)
9914 +{
9915 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
9916 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
9917 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
9918 +               return 0;
9919 +       }
9920 +
9921 +       return 1;
9922 +}
9923 +
9924 +static struct ipt_match addrtype_match = { 
9925 +       .name = "addrtype",
9926 +       .match = match,
9927 +       .checkentry = checkentry,
9928 +       .me = THIS_MODULE
9929 +};
9930 +
9931 +static int __init init(void)
9932 +{
9933 +       return ipt_register_match(&addrtype_match);
9934 +}
9935 +
9936 +static void __exit fini(void)
9937 +{
9938 +       ipt_unregister_match(&addrtype_match);
9939 +
9940 +}
9941 +
9942 +module_init(init);
9943 +module_exit(fini);
9944 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c
9945 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connlimit.c      1970-01-01 01:00:00.000000000 +0100
9946 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connlimit.c  2004-04-30 09:10:17.000000000 +0200
9947 @@ -0,0 +1,230 @@
9948 +/*
9949 + * netfilter module to limit the number of parallel tcp
9950 + * connections per IP address.
9951 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
9952 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
9953 + *             only ignore TIME_WAIT or gone connections
9954 + *
9955 + * based on ...
9956 + *
9957 + * Kernel module to match connection tracking information.
9958 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
9959 + */
9960 +#include <linux/module.h>
9961 +#include <linux/skbuff.h>
9962 +#include <linux/list.h>
9963 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9964 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
9965 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
9966 +#include <linux/netfilter_ipv4/ip_tables.h>
9967 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
9968 +
9969 +#define DEBUG 0
9970 +
9971 +MODULE_LICENSE("GPL");
9972 +
9973 +/* we'll save the tuples of all connections we care about */
9974 +struct ipt_connlimit_conn
9975 +{
9976 +        struct list_head list;
9977 +       struct ip_conntrack_tuple tuple;
9978 +};
9979 +
9980 +struct ipt_connlimit_data {
9981 +       spinlock_t lock;
9982 +       struct list_head iphash[256];
9983 +};
9984 +
9985 +static int ipt_iphash(u_int32_t addr)
9986 +{
9987 +       int hash;
9988 +
9989 +       hash  =  addr        & 0xff;
9990 +       hash ^= (addr >>  8) & 0xff;
9991 +       hash ^= (addr >> 16) & 0xff;
9992 +       hash ^= (addr >> 24) & 0xff;
9993 +       return hash;
9994 +}
9995 +
9996 +static int count_them(struct ipt_connlimit_data *data,
9997 +                     u_int32_t addr, u_int32_t mask,
9998 +                     struct ip_conntrack *ct)
9999 +{
10000 +#if DEBUG
10001 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
10002 +                                    "fin_wait", "time_wait", "close", "close_wait",
10003 +                                    "last_ack", "listen" };
10004 +#endif
10005 +       int addit = 1, matches = 0;
10006 +       struct ip_conntrack_tuple tuple;
10007 +       struct ip_conntrack_tuple_hash *found;
10008 +       struct ipt_connlimit_conn *conn;
10009 +       struct list_head *hash,*lh;
10010 +
10011 +       spin_lock(&data->lock);
10012 +       tuple = ct->tuplehash[0].tuple;
10013 +       hash = &data->iphash[ipt_iphash(addr & mask)];
10014 +
10015 +       /* check the saved connections */
10016 +       for (lh = hash->next; lh != hash; lh = lh->next) {
10017 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
10018 +               found = ip_conntrack_find_get(&conn->tuple,ct);
10019 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
10020 +                   found != NULL &&
10021 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
10022 +                       /* Just to be sure we have it only once in the list.
10023 +                          We should'nt see tuples twice unless someone hooks this
10024 +                          into a table without "-p tcp --syn" */
10025 +                       addit = 0;
10026 +               }
10027 +#if DEBUG
10028 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
10029 +                      ipt_iphash(addr & mask),
10030 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
10031 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
10032 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
10033 +#endif
10034 +               if (NULL == found) {
10035 +                       /* this one is gone */
10036 +                       lh = lh->prev;
10037 +                       list_del(lh->next);
10038 +                       kfree(conn);
10039 +                       continue;
10040 +               }
10041 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
10042 +                       /* we don't care about connections which are
10043 +                          closed already -> ditch it */
10044 +                       lh = lh->prev;
10045 +                       list_del(lh->next);
10046 +                       kfree(conn);
10047 +                       nf_conntrack_put(&found->ctrack->infos[0]);
10048 +                       continue;
10049 +               }
10050 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
10051 +                       /* same source IP address -> be counted! */
10052 +                       matches++;
10053 +               }
10054 +               nf_conntrack_put(&found->ctrack->infos[0]);
10055 +       }
10056 +       if (addit) {
10057 +               /* save the new connection in our list */
10058 +#if DEBUG
10059 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
10060 +                      ipt_iphash(addr & mask),
10061 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
10062 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
10063 +#endif
10064 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
10065 +               if (NULL == conn)
10066 +                       return -1;
10067 +               memset(conn,0,sizeof(*conn));
10068 +               INIT_LIST_HEAD(&conn->list);
10069 +               conn->tuple = tuple;
10070 +               list_add(&conn->list,hash);
10071 +               matches++;
10072 +       }
10073 +       spin_unlock(&data->lock);
10074 +       return matches;
10075 +}
10076 +
10077 +static int
10078 +match(const struct sk_buff *skb,
10079 +      const struct net_device *in,
10080 +      const struct net_device *out,
10081 +      const void *matchinfo,
10082 +      int offset,
10083 +      int *hotdrop)
10084 +{
10085 +       const struct ipt_connlimit_info *info = matchinfo;
10086 +       int connections, match;
10087 +       struct ip_conntrack *ct;
10088 +       enum ip_conntrack_info ctinfo;
10089 +
10090 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10091 +       if (NULL == ct) {
10092 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
10093 +               *hotdrop = 1;
10094 +               return 0;
10095 +       }
10096 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
10097 +       if (-1 == connections) {
10098 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
10099 +               *hotdrop = 1; /* let's free some memory :-) */
10100 +               return 0;
10101 +       }
10102 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
10103 +#if DEBUG
10104 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
10105 +              "connections=%d limit=%d match=%s\n",
10106 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
10107 +              connections, info->limit, match ? "yes" : "no");
10108 +#endif
10109 +
10110 +       return match;
10111 +}
10112 +
10113 +static int check(const char *tablename,
10114 +                const struct ipt_ip *ip,
10115 +                void *matchinfo,
10116 +                unsigned int matchsize,
10117 +                unsigned int hook_mask)
10118 +{
10119 +       struct ipt_connlimit_info *info = matchinfo;
10120 +       int i;
10121 +
10122 +       /* verify size */
10123 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
10124 +               return 0;
10125 +
10126 +       /* refuse anything but tcp */
10127 +       if (ip->proto != IPPROTO_TCP)
10128 +               return 0;
10129 +
10130 +       /* init private data */
10131 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
10132 +       spin_lock_init(&(info->data->lock));
10133 +       for (i = 0; i < 256; i++)
10134 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
10135 +       
10136 +       return 1;
10137 +}
10138 +
10139 +static void destroy(void *matchinfo, unsigned int matchinfosize)
10140 +{
10141 +       struct ipt_connlimit_info *info = matchinfo;
10142 +       struct ipt_connlimit_conn *conn;
10143 +       struct list_head *hash;
10144 +       int i;
10145 +
10146 +       /* cleanup */
10147 +       for (i = 0; i < 256; i++) {
10148 +               hash = &(info->data->iphash[i]);
10149 +               while (hash != hash->next) {
10150 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
10151 +                       list_del(hash->next);
10152 +                       kfree(conn);
10153 +               }
10154 +       }
10155 +       kfree(info->data);
10156 +}
10157 +
10158 +static struct ipt_match connlimit_match = { 
10159 +       .name = "connlimit",
10160 +       .match = &match,
10161 +       .checkentry = &check,
10162 +       .destroy = &destroy,
10163 +       .me = THIS_MODULE
10164 +};
10165 +
10166 +static int __init init(void)
10167 +{
10168 +       return ipt_register_match(&connlimit_match);
10169 +}
10170 +
10171 +static void __exit fini(void)
10172 +{
10173 +       ipt_unregister_match(&connlimit_match);
10174 +}
10175 +
10176 +module_init(init);
10177 +module_exit(fini);
10178 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c
10179 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_connmark.c       1970-01-01 01:00:00.000000000 +0100
10180 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_connmark.c   2004-04-30 09:11:35.000000000 +0200
10181 @@ -0,0 +1,81 @@
10182 +/* This kernel module matches connection mark values set by the
10183 + * CONNMARK target
10184 + *
10185 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
10186 + * by Henrik Nordstrom <hno@marasystems.com>
10187 + *
10188 + * This program is free software; you can redistribute it and/or modify
10189 + * it under the terms of the GNU General Public License as published by
10190 + * the Free Software Foundation; either version 2 of the License, or
10191 + * (at your option) any later version.
10192 + *
10193 + * This program is distributed in the hope that it will be useful,
10194 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10195 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10196 + * GNU General Public License for more details.
10197 + *
10198 + * You should have received a copy of the GNU General Public License
10199 + * along with this program; if not, write to the Free Software
10200 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
10201 + */
10202 +
10203 +#include <linux/module.h>
10204 +#include <linux/skbuff.h>
10205 +
10206 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
10207 +MODULE_DESCRIPTION("IP tables connmark match module");
10208 +MODULE_LICENSE("GPL");
10209 +
10210 +#include <linux/netfilter_ipv4/ip_tables.h>
10211 +#include <linux/netfilter_ipv4/ipt_connmark.h>
10212 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10213 +
10214 +static int
10215 +match(const struct sk_buff *skb,
10216 +      const struct net_device *in,
10217 +      const struct net_device *out,
10218 +      const void *matchinfo,
10219 +      int offset,
10220 +      int *hotdrop)
10221 +{
10222 +       const struct ipt_connmark_info *info = matchinfo;
10223 +       enum ip_conntrack_info ctinfo;
10224 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
10225 +       if (!ct)
10226 +               return 0;
10227 +
10228 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
10229 +}
10230 +
10231 +static int
10232 +checkentry(const char *tablename,
10233 +          const struct ipt_ip *ip,
10234 +          void *matchinfo,
10235 +          unsigned int matchsize,
10236 +          unsigned int hook_mask)
10237 +{
10238 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
10239 +               return 0;
10240 +
10241 +       return 1;
10242 +}
10243 +
10244 +static struct ipt_match connmark_match = {
10245 +       .name = "connmark",
10246 +       .match = &match,
10247 +       .checkentry = &checkentry,
10248 +       .me = THIS_MODULE
10249 +};
10250 +
10251 +static int __init init(void)
10252 +{
10253 +       return ipt_register_match(&connmark_match);
10254 +}
10255 +
10256 +static void __exit fini(void)
10257 +{
10258 +       ipt_unregister_match(&connmark_match);
10259 +}
10260 +
10261 +module_init(init);
10262 +module_exit(fini);
10263 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c
10264 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c       1970-01-01 01:00:00.000000000 +0100
10265 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_dstlimit.c   2004-04-30 09:10:21.000000000 +0200
10266 @@ -0,0 +1,690 @@
10267 +/* iptables match extension to limit the number of packets per second
10268 + * seperately for each destination.
10269 + *
10270 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
10271 + *
10272 + * $Id$
10273 + *
10274 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
10275 + *
10276 + * based on ipt_limit.c by:
10277 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
10278 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
10279 + * Rusty Russell       <rusty@rustcorp.com.au>
10280 + *
10281 + * The general idea is to create a hash table for every dstip and have a
10282 + * seperate limit counter per tuple.  This way you can do something like 'limit
10283 + * the number of syn packets for each of my internal addresses.
10284 + *
10285 + * Ideally this would just be implemented as a general 'hash' match, which would
10286 + * allow us to attach any iptables target to it's hash buckets.  But this is
10287 + * not possible in the current iptables architecture.  As always, pkttables for
10288 + * 2.7.x will help ;)
10289 + */
10290 +#include <linux/module.h>
10291 +#include <linux/skbuff.h>
10292 +#include <linux/spinlock.h>
10293 +#include <linux/random.h>
10294 +#include <linux/jhash.h>
10295 +#include <linux/slab.h>
10296 +#include <linux/vmalloc.h>
10297 +#include <linux/tcp.h>
10298 +#include <linux/udp.h>
10299 +#include <linux/proc_fs.h>
10300 +#include <linux/seq_file.h>
10301 +
10302 +#define ASSERT_READ_LOCK(x) 
10303 +#define ASSERT_WRITE_LOCK(x) 
10304 +#include <linux/netfilter_ipv4/lockhelp.h>
10305 +#include <linux/netfilter_ipv4/listhelp.h>
10306 +
10307 +#include <linux/netfilter_ipv4/ip_tables.h>
10308 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
10309 +
10310 +/* FIXME: this is just for IP_NF_ASSERRT */
10311 +#include <linux/netfilter_ipv4/ip_conntrack.h>
10312 +
10313 +#define MS2JIFFIES(x) ((x*HZ)/1000)
10314 +
10315 +MODULE_LICENSE("GPL");
10316 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
10317 +MODULE_DESCRIPTION("iptables match for limiting per destination");
10318 +
10319 +/* need to declare this at the top */
10320 +static struct proc_dir_entry *dstlimit_procdir;
10321 +static struct file_operations dl_file_ops;
10322 +
10323 +/* hash table crap */
10324 +
10325 +struct dsthash_dst {
10326 +       u_int32_t src_ip;
10327 +       u_int32_t dst_ip;
10328 +       u_int16_t port;
10329 +};
10330 +
10331 +struct dsthash_ent {
10332 +       /* static / read-only parts in the beginning */
10333 +       struct list_head list;
10334 +       struct dsthash_dst dst;
10335 +
10336 +       /* modified structure members in the end */
10337 +       unsigned long expires;          /* precalculated expiry time */
10338 +       struct {
10339 +               unsigned long prev;     /* last modification */
10340 +               u_int32_t credit;
10341 +               u_int32_t credit_cap, cost;
10342 +       } rateinfo;
10343 +};
10344 +
10345 +struct ipt_dstlimit_htable {
10346 +       struct list_head list;          /* global list of all htables */
10347 +       atomic_t use;
10348 +
10349 +       struct dstlimit_cfg cfg;        /* config */
10350 +
10351 +       /* used internally */
10352 +       spinlock_t lock;                /* lock for list_head */
10353 +       u_int32_t rnd;                  /* random seed for hash */
10354 +       struct timer_list timer;        /* timer for gc */
10355 +       atomic_t count;                 /* number entries in table */
10356 +
10357 +       /* seq_file stuff */
10358 +       struct proc_dir_entry *pde;
10359 +
10360 +       struct list_head hash[0];       /* hashtable itself */
10361 +};
10362 +
10363 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
10364 +static LIST_HEAD(dstlimit_htables);
10365 +static kmem_cache_t *dstlimit_cachep;
10366 +
10367 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
10368 +{
10369 +       return (ent->dst.dst_ip == b->dst_ip 
10370 +               && ent->dst.port == b->port
10371 +               && ent->dst.src_ip == b->src_ip);
10372 +}
10373 +
10374 +static inline u_int32_t
10375 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
10376 +{
10377 +       return (jhash_3words(dst->dst_ip, dst->port, 
10378 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
10379 +}
10380 +
10381 +static inline struct dsthash_ent *
10382 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
10383 +{
10384 +       struct dsthash_ent *ent;
10385 +       u_int32_t hash = hash_dst(ht, dst);
10386 +       MUST_BE_LOCKED(&ht->lock);
10387 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
10388 +       return ent;
10389 +}
10390 +
10391 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
10392 +static struct dsthash_ent *
10393 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
10394 +{
10395 +       struct dsthash_ent *ent;
10396 +
10397 +       /* initialize hash with random val at the time we allocate
10398 +        * the first hashtable entry */
10399 +       if (!ht->rnd)
10400 +               get_random_bytes(&ht->rnd, 4);
10401 +
10402 +       if (ht->cfg.max &&
10403 +           atomic_read(&ht->count) >= ht->cfg.max) {
10404 +               /* FIXME: do something. question is what.. */
10405 +               if (net_ratelimit())
10406 +                       printk(KERN_WARNING 
10407 +                               "ipt_dstlimit: max count of %u reached\n", 
10408 +                               ht->cfg.max);
10409 +               return NULL;
10410 +       }
10411 +
10412 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
10413 +       if (!ent) {
10414 +               if (net_ratelimit())
10415 +                       printk(KERN_ERR 
10416 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
10417 +               return NULL;
10418 +       }
10419 +
10420 +       atomic_inc(&ht->count);
10421 +
10422 +       ent->dst.dst_ip = dst->dst_ip;
10423 +       ent->dst.port = dst->port;
10424 +       ent->dst.src_ip = dst->src_ip;
10425 +
10426 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
10427 +
10428 +       return ent;
10429 +}
10430 +
10431 +static inline void 
10432 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
10433 +{
10434 +       MUST_BE_LOCKED(&ht->lock);
10435 +
10436 +       list_del(&ent->list);
10437 +       kmem_cache_free(dstlimit_cachep, ent);
10438 +       atomic_dec(&ht->count);
10439 +}
10440 +static void htable_gc(unsigned long htlong);
10441 +
10442 +static int htable_create(struct ipt_dstlimit_info *minfo)
10443 +{
10444 +       int i;
10445 +       unsigned int size;
10446 +       struct ipt_dstlimit_htable *hinfo;
10447 +
10448 +       if (minfo->cfg.size)
10449 +               size = minfo->cfg.size;
10450 +       else {
10451 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
10452 +                        / sizeof(struct list_head));
10453 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
10454 +                       size = 8192;
10455 +               if (size < 16)
10456 +                       size = 16;
10457 +       }
10458 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
10459 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
10460 +                       + (sizeof(struct list_head) * size));
10461 +       if (!hinfo) {
10462 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
10463 +               return -1;
10464 +       }
10465 +       minfo->hinfo = hinfo;
10466 +
10467 +       /* copy match config into hashtable config */
10468 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
10469 +       hinfo->cfg.size = size;
10470 +       if (!hinfo->cfg.max)
10471 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
10472 +       else if (hinfo->cfg.max < hinfo->cfg.size)
10473 +               hinfo->cfg.max = hinfo->cfg.size;
10474 +
10475 +       for (i = 0; i < hinfo->cfg.size; i++)
10476 +               INIT_LIST_HEAD(&hinfo->hash[i]);
10477 +
10478 +       atomic_set(&hinfo->count, 0);
10479 +       atomic_set(&hinfo->use, 1);
10480 +       hinfo->rnd = 0;
10481 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
10482 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
10483 +       if (!hinfo->pde) {
10484 +               vfree(hinfo);
10485 +               return -1;
10486 +       }
10487 +       hinfo->pde->proc_fops = &dl_file_ops;
10488 +       hinfo->pde->data = hinfo;
10489 +
10490 +       init_timer(&hinfo->timer);
10491 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
10492 +       hinfo->timer.data = (unsigned long )hinfo;
10493 +       hinfo->timer.function = htable_gc;
10494 +       add_timer(&hinfo->timer);
10495 +
10496 +       WRITE_LOCK(&dstlimit_lock);
10497 +       list_add(&hinfo->list, &dstlimit_htables);
10498 +       WRITE_UNLOCK(&dstlimit_lock);
10499 +
10500 +       return 0;
10501 +}
10502 +
10503 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
10504 +{
10505 +       return 1;
10506 +}
10507 +
10508 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
10509 +{
10510 +       return (jiffies >= he->expires);
10511 +}
10512 +
10513 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
10514 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
10515 +                                             struct dsthash_ent *he))
10516 +{
10517 +       int i;
10518 +
10519 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
10520 +
10521 +       /* lock hash table and iterate over it */
10522 +       LOCK_BH(&ht->lock);
10523 +       for (i = 0; i < ht->cfg.size; i++) {
10524 +               struct dsthash_ent *dh, *n;
10525 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
10526 +                       if ((*select)(ht, dh))
10527 +                               __dsthash_free(ht, dh);
10528 +               }
10529 +       }
10530 +       UNLOCK_BH(&ht->lock);
10531 +}
10532 +
10533 +/* hash table garbage collector, run by timer */
10534 +static void htable_gc(unsigned long htlong)
10535 +{
10536 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
10537 +
10538 +       htable_selective_cleanup(ht, select_gc);
10539 +
10540 +       /* re-add the timer accordingly */
10541 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
10542 +       add_timer(&ht->timer);
10543 +}
10544 +
10545 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
10546 +{
10547 +       /* remove timer, if it is pending */
10548 +       if (timer_pending(&hinfo->timer))
10549 +               del_timer(&hinfo->timer);
10550 +
10551 +       /* remove proc entry */
10552 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
10553 +
10554 +       htable_selective_cleanup(hinfo, select_all);
10555 +       vfree(hinfo);
10556 +}
10557 +
10558 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
10559 +{
10560 +       struct ipt_dstlimit_htable *hinfo;
10561 +
10562 +       READ_LOCK(&dstlimit_lock);
10563 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
10564 +               if (!strcmp(name, hinfo->pde->name)) {
10565 +                       atomic_inc(&hinfo->use);
10566 +                       READ_UNLOCK(&dstlimit_lock);
10567 +                       return hinfo;
10568 +               }
10569 +       }
10570 +       READ_UNLOCK(&dstlimit_lock);
10571 +
10572 +       return NULL;
10573 +}
10574 +
10575 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
10576 +{
10577 +       if (atomic_dec_and_test(&hinfo->use)) {
10578 +               WRITE_LOCK(&dstlimit_lock);
10579 +               list_del(&hinfo->list);
10580 +               WRITE_UNLOCK(&dstlimit_lock);
10581 +               htable_destroy(hinfo);
10582 +       }
10583 +}
10584 +
10585 +
10586 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
10587 + * see net/sched/sch_tbf.c in the linux source tree
10588 + */
10589 +
10590 +/* Rusty: This is my (non-mathematically-inclined) understanding of
10591 +   this algorithm.  The `average rate' in jiffies becomes your initial
10592 +   amount of credit `credit' and the most credit you can ever have
10593 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
10594 +   test, `cost'.
10595 +
10596 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
10597 +   If you get credit balance more than this, the extra credit is
10598 +   discarded.  Every time the match passes, you lose `cost' credits;
10599 +   if you don't have that many, the test fails.
10600 +
10601 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
10602 +
10603 +   To get the maximum range, we multiply by this factor (ie. you get N
10604 +   credits per jiffy).  We want to allow a rate as low as 1 per day
10605 +   (slowest userspace tool allows), which means
10606 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
10607 +*/
10608 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
10609 +
10610 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
10611 + * us the power of 2 below the theoretical max, so GCC simply does a
10612 + * shift. */
10613 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
10614 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
10615 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
10616 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
10617 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
10618 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
10619 +
10620 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
10621 +
10622 +/* Precision saver. */
10623 +static inline u_int32_t
10624 +user2credits(u_int32_t user)
10625 +{
10626 +       /* If multiplying would overflow... */
10627 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
10628 +               /* Divide first. */
10629 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
10630 +
10631 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
10632 +}
10633 +
10634 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
10635 +{
10636 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
10637 +                                       * CREDITS_PER_JIFFY;
10638 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
10639 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
10640 +}
10641 +
10642 +static int
10643 +dstlimit_match(const struct sk_buff *skb,
10644 +               const struct net_device *in,
10645 +               const struct net_device *out,
10646 +               const void *matchinfo,
10647 +               int offset,
10648 +               int *hotdrop)
10649 +{
10650 +       struct ipt_dstlimit_info *r = 
10651 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
10652 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
10653 +       unsigned long now = jiffies;
10654 +       struct dsthash_ent *dh;
10655 +       struct dsthash_dst dst;
10656 +
10657 +       memset(&dst, 0, sizeof(dst));
10658 +
10659 +       /* dest ip is always in hash */
10660 +       dst.dst_ip = skb->nh.iph->daddr;
10661 +
10662 +       /* source ip only if respective hashmode, otherwise set to
10663 +        * zero */
10664 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
10665 +               dst.src_ip = skb->nh.iph->saddr;
10666 +
10667 +       /* dest port only if respective mode */
10668 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
10669 +               u16 ports[2];
10670 +
10671 +               /* Must not be a fragment. */
10672 +               if (offset)
10673 +                       return 0;
10674 +
10675 +               /* Must be big enough to read ports (both UDP and TCP have
10676 +                  them at the start). */
10677 +               if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
10678 +                       /* We've been asked to examine this packet, and we
10679 +                          can't.  Hence, no choice but to drop. */
10680 +                       *hotdrop = 1;
10681 +                       return 0;
10682 +               }
10683 +
10684 +               switch (skb->nh.iph->protocol) {
10685 +                       struct tcphdr *th;
10686 +                       struct udphdr *uh;
10687 +               case IPPROTO_TCP:
10688 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
10689 +                       dst.port = th->dest;
10690 +                       break;
10691 +               case IPPROTO_UDP:
10692 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
10693 +                       dst.port = uh->dest;
10694 +                       break;
10695 +               default:
10696 +                       break;
10697 +               }
10698 +       } 
10699 +
10700 +       LOCK_BH(&hinfo->lock);
10701 +       dh = __dsthash_find(hinfo, &dst);
10702 +       if (!dh) {
10703 +               dh = __dsthash_alloc_init(hinfo, &dst);
10704 +
10705 +               if (!dh) {
10706 +                       /* enomem... don't match == DROP */
10707 +                       if (net_ratelimit())
10708 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
10709 +                       UNLOCK_BH(&hinfo->lock);
10710 +                       return 0;
10711 +               }
10712 +
10713 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
10714 +
10715 +               dh->rateinfo.prev = jiffies;
10716 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
10717 +                                                       hinfo->cfg.burst);
10718 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
10719 +                                                       hinfo->cfg.burst);
10720 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
10721 +
10722 +               UNLOCK_BH(&hinfo->lock);
10723 +               return 1;
10724 +       }
10725 +
10726 +       /* update expiration timeout */
10727 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
10728 +
10729 +       rateinfo_recalc(dh, now);
10730 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
10731 +               /* We're underlimit. */
10732 +               dh->rateinfo.credit -= dh->rateinfo.cost;
10733 +               UNLOCK_BH(&hinfo->lock);
10734 +               return 1;
10735 +       }
10736 +
10737 +               UNLOCK_BH(&hinfo->lock);
10738 +
10739 +       /* default case: we're overlimit, thus don't match */
10740 +       return 0;
10741 +}
10742 +
10743 +static int
10744 +dstlimit_checkentry(const char *tablename,
10745 +                    const struct ipt_ip *ip,
10746 +                    void *matchinfo,
10747 +                    unsigned int matchsize,
10748 +                    unsigned int hook_mask)
10749 +{
10750 +       struct ipt_dstlimit_info *r = matchinfo;
10751 +
10752 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
10753 +               return 0;
10754 +
10755 +       /* Check for overflow. */
10756 +       if (r->cfg.burst == 0
10757 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
10758 +                                       user2credits(r->cfg.avg)) {
10759 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
10760 +                      r->cfg.avg, r->cfg.burst);
10761 +               return 0;
10762 +       }
10763 +
10764 +       if (r->cfg.mode == 0 
10765 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
10766 +                         |IPT_DSTLIMIT_HASH_DIP
10767 +                         |IPT_DSTLIMIT_HASH_SIP))
10768 +               return 0;
10769 +
10770 +       if (!r->cfg.gc_interval)
10771 +               return 0;
10772 +       
10773 +       if (!r->cfg.expire)
10774 +               return 0;
10775 +
10776 +       r->hinfo = htable_find_get(r->name);
10777 +       if (!r->hinfo && (htable_create(r) != 0)) {
10778 +               return 0;
10779 +       }
10780 +
10781 +       /* Ugly hack: For SMP, we only want to use one set */
10782 +       r->u.master = r;
10783 +
10784 +       return 1;
10785 +}
10786 +
10787 +static void
10788 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
10789 +{
10790 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
10791 +
10792 +       htable_put(r->hinfo);
10793 +}
10794 +
10795 +static struct ipt_match ipt_dstlimit = { 
10796 +       .list = { .prev = NULL, .next = NULL }, 
10797 +       .name = "dstlimit", 
10798 +       .match = dstlimit_match, 
10799 +       .checkentry = dstlimit_checkentry, 
10800 +       .destroy = dstlimit_destroy,
10801 +       .me = THIS_MODULE 
10802 +};
10803 +
10804 +/* PROC stuff */
10805 +
10806 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
10807 +{
10808 +       struct proc_dir_entry *pde = s->private;
10809 +       struct ipt_dstlimit_htable *htable = pde->data;
10810 +       unsigned int *bucket;
10811 +
10812 +       LOCK_BH(&htable->lock);
10813 +       if (*pos >= htable->cfg.size)
10814 +               return NULL;
10815 +
10816 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
10817 +       if (!bucket)
10818 +               return ERR_PTR(-ENOMEM);
10819 +
10820 +       *bucket = *pos;
10821 +       return bucket;
10822 +}
10823 +
10824 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
10825 +{
10826 +       struct proc_dir_entry *pde = s->private;
10827 +       struct ipt_dstlimit_htable *htable = pde->data;
10828 +       unsigned int *bucket = (unsigned int *)v;
10829 +
10830 +       *pos = ++(*bucket);
10831 +       if (*pos >= htable->cfg.size) {
10832 +               kfree(v);
10833 +               return NULL;
10834 +       }
10835 +       return bucket;
10836 +}
10837 +
10838 +static void dl_seq_stop(struct seq_file *s, void *v)
10839 +{
10840 +       struct proc_dir_entry *pde = s->private;
10841 +       struct ipt_dstlimit_htable *htable = pde->data;
10842 +       unsigned int *bucket = (unsigned int *)v;
10843 +
10844 +       kfree(bucket);
10845 +
10846 +       UNLOCK_BH(&htable->lock);
10847 +}
10848 +
10849 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
10850 +{
10851 +       /* recalculate to show accurate numbers */
10852 +       rateinfo_recalc(ent, jiffies);
10853 +
10854 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
10855 +                       (ent->expires - jiffies)/HZ,
10856 +                       NIPQUAD(ent->dst.src_ip),
10857 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
10858 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
10859 +                       ent->rateinfo.cost);
10860 +}
10861 +
10862 +static int dl_seq_show(struct seq_file *s, void *v)
10863 +{
10864 +       struct proc_dir_entry *pde = s->private;
10865 +       struct ipt_dstlimit_htable *htable = pde->data;
10866 +       unsigned int *bucket = (unsigned int *)v;
10867 +
10868 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
10869 +                     struct dsthash_ent *, s)) {
10870 +               /* buffer was filled and unable to print that tuple */
10871 +               return 1;
10872 +       }
10873 +       return 0;
10874 +}
10875 +
10876 +static struct seq_operations dl_seq_ops = {
10877 +       .start = dl_seq_start,
10878 +       .next  = dl_seq_next,
10879 +       .stop  = dl_seq_stop,
10880 +       .show  = dl_seq_show
10881 +};
10882 +
10883 +static int dl_proc_open(struct inode *inode, struct file *file)
10884 +{
10885 +       int ret = seq_open(file, &dl_seq_ops);
10886 +
10887 +       if (!ret) {
10888 +               struct seq_file *sf = file->private_data;
10889 +               sf->private = PDE(inode);
10890 +       }
10891 +       return ret;
10892 +}
10893 +
10894 +static struct file_operations dl_file_ops = {
10895 +       .owner   = THIS_MODULE,
10896 +       .open    = dl_proc_open,
10897 +       .read    = seq_read,
10898 +       .llseek  = seq_lseek,
10899 +       .release = seq_release
10900 +};
10901 +
10902 +static int init_or_fini(int fini)
10903 +{
10904 +       int ret = 0;
10905 +
10906 +       if (fini)
10907 +               goto cleanup;
10908 +
10909 +       if (ipt_register_match(&ipt_dstlimit)) {
10910 +               ret = -EINVAL;
10911 +               goto cleanup_nothing;
10912 +       }
10913 +
10914 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
10915 +        * quite small ? */
10916 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
10917 +                                           sizeof(struct dsthash_ent), 0,
10918 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
10919 +       if (!dstlimit_cachep) {
10920 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
10921 +               ret = -ENOMEM;
10922 +               goto cleanup_unreg_match;
10923 +       }
10924 +
10925 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
10926 +       if (!dstlimit_procdir) {
10927 +               printk(KERN_ERR "Unable to create proc dir entry\n");
10928 +               ret = -ENOMEM;
10929 +               goto cleanup_free_slab;
10930 +       }
10931 +
10932 +       return ret;
10933 +
10934 +cleanup:
10935 +       remove_proc_entry("ipt_dstlimit", proc_net);
10936 +cleanup_free_slab:
10937 +       kmem_cache_destroy(dstlimit_cachep);
10938 +cleanup_unreg_match:
10939 +       ipt_unregister_match(&ipt_dstlimit);
10940 +cleanup_nothing:
10941 +       return ret;
10942 +       
10943 +}
10944 +
10945 +static int __init init(void)
10946 +{
10947 +       return init_or_fini(0);
10948 +}
10949 +
10950 +static void __exit fini(void)
10951 +{
10952 +       init_or_fini(1);
10953 +}
10954 +
10955 +module_init(init);
10956 +module_exit(fini);
10957 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_fuzzy.c
10958 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c  1970-01-01 01:00:00.000000000 +0100
10959 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_fuzzy.c      2004-04-30 09:10:22.000000000 +0200
10960 @@ -0,0 +1,185 @@
10961 +/*
10962 + *  This module implements a simple TSK FLC 
10963 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
10964 + * to limit , in an adaptive and flexible way , the packet rate crossing 
10965 + * a given stream . It serves as an initial and very simple (but effective)
10966 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
10967 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
10968 + * into our code in a precise , adaptive and efficient manner. 
10969 + *  The goal is very similar to that of "limit" match , but using techniques of
10970 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
10971 + * avoiding over and undershoots - and stuff like that .
10972 + *
10973 + *
10974 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
10975 + * 2002-08-17  : Changed to eliminate floating point operations .
10976 + * 2002-08-23  : Coding style changes .
10977 +*/
10978 +
10979 +#include <linux/module.h>
10980 +#include <linux/skbuff.h>
10981 +#include <linux/ip.h>
10982 +#include <linux/random.h>
10983 +#include <net/tcp.h>
10984 +#include <linux/spinlock.h>
10985 +#include <linux/netfilter_ipv4/ip_tables.h>
10986 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
10987 +
10988 +/*
10989 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
10990 + Expressed in percentage
10991 +*/
10992 +
10993 +#define PAR_LOW                1/100
10994 +#define PAR_HIGH       1
10995 +
10996 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
10997 +
10998 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
10999 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
11000 +MODULE_LICENSE("GPL");
11001 +
11002 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11003 +{
11004 +       if (tx >= maxi)
11005 +               return 100;
11006 +
11007 +       if (tx <= mini)
11008 +               return 0;
11009 +
11010 +       return ( (100*(tx-mini)) / (maxi-mini) );
11011 +}
11012 +
11013 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
11014 +{
11015 +       if (tx <= mini)
11016 +               return 100;
11017 +
11018 +       if (tx >= maxi)
11019 +               return 0;
11020 +
11021 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
11022 +}
11023 +
11024 +static int
11025 +ipt_fuzzy_match(const struct sk_buff *pskb,
11026 +              const struct net_device *in,
11027 +              const struct net_device *out,
11028 +              const void *matchinfo,
11029 +              int offset,
11030 +              int *hotdrop)
11031 +{
11032 +       /* From userspace */
11033 +       
11034 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
11035 +
11036 +       u_int8_t random_number;
11037 +       unsigned long amount;
11038 +       u_int8_t howhigh, howlow;
11039 +       
11040 +
11041 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
11042 +
11043 +       info->bytes_total += pskb->len;
11044 +       info->packets_total++;
11045 +
11046 +       info->present_time = jiffies;
11047 +       
11048 +       if (info->present_time >= info->previous_time)
11049 +               amount = info->present_time - info->previous_time;
11050 +       else { 
11051 +               /* There was a transition : I choose to re-sample 
11052 +                  and keep the old acceptance rate...
11053 +               */
11054 +
11055 +               amount = 0;
11056 +               info->previous_time = info->present_time;
11057 +               info->bytes_total = info->packets_total = 0;
11058 +       };
11059 +       
11060 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
11061 +       {
11062 +
11063 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
11064 +                                       / amount );
11065 +
11066 +               info->previous_time = info->present_time;
11067 +               info->bytes_total = info->packets_total = 0;
11068 +
11069 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
11070 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
11071 +
11072 +               info->acceptance_rate = (u_int8_t) \
11073 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
11074 +
11075 +               /* In fact , the above defuzzification would require a denominator
11076 +                  proportional to (howhigh+howlow) but , in this particular case ,
11077 +                  that expression is constant .
11078 +                  An imediate consequence is that it isn't necessary to call 
11079 +                  both mf_high and mf_low - but to keep things understandable ,
11080 +                  I did so .  */ 
11081 +
11082 +       }
11083 +       
11084 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
11085 +
11086 +
11087 +       if ( info->acceptance_rate < 100 )
11088 +       {                
11089 +               get_random_bytes((void *)(&random_number), 1);
11090 +
11091 +               /*  If within the acceptance , it can pass => don't match */
11092 +               if (random_number <= (255 * info->acceptance_rate) / 100)
11093 +                       return 0;
11094 +               else
11095 +                       return 1; /* It can't pass ( It matches ) */
11096 +       } ;
11097 +
11098 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
11099 +       
11100 +}
11101 +
11102 +static int
11103 +ipt_fuzzy_checkentry(const char *tablename,
11104 +                  const struct ipt_ip *e,
11105 +                  void *matchinfo,
11106 +                  unsigned int matchsize,
11107 +                  unsigned int hook_mask)
11108 +{
11109 +       
11110 +       const struct ipt_fuzzy_info *info = matchinfo;
11111 +
11112 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
11113 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
11114 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
11115 +               return 0;
11116 +       }
11117 +
11118 +       if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
11119 +           || (info->minimum_rate >= info->maximum_rate )) {
11120 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
11121 +               return 0;
11122 +       }
11123 +
11124 +       return 1;
11125 +}
11126 +
11127 +static struct ipt_match ipt_fuzzy_reg = { 
11128 +       .name = "fuzzy",
11129 +       .match = ipt_fuzzy_match,
11130 +       .checkentry = ipt_fuzzy_checkentry,
11131 +       .me = THIS_MODULE
11132 +};
11133 +
11134 +static int __init init(void)
11135 +{
11136 +       return ipt_register_match(&ipt_fuzzy_reg);
11137 +}
11138 +
11139 +static void __exit fini(void)
11140 +{
11141 +       ipt_unregister_match(&ipt_fuzzy_reg);
11142 +}
11143 +
11144 +module_init(init);
11145 +module_exit(fini);
11146 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c
11147 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_helper.c 2004-04-28 03:36:22.000000000 +0200
11148 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_helper.c     2004-04-30 09:12:49.000000000 +0200
11149 @@ -41,17 +41,17 @@
11150         struct ip_conntrack_expect *exp;
11151         struct ip_conntrack *ct;
11152         enum ip_conntrack_info ctinfo;
11153 -       int ret = 0;
11154 +       int ret = info->invert;
11155         
11156         ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
11157         if (!ct) {
11158                 DEBUGP("ipt_helper: Eek! invalid conntrack?\n");
11159 -               return 0;
11160 +               return ret;
11161         }
11162  
11163         if (!ct->master) {
11164                 DEBUGP("ipt_helper: conntrack %p has no master\n", ct);
11165 -               return 0;
11166 +               return ret;
11167         }
11168  
11169         exp = ct->master;
11170 @@ -71,8 +71,11 @@
11171         DEBUGP("master's name = %s , info->name = %s\n", 
11172                 exp->expectant->helper->name, info->name);
11173  
11174 -       ret = !strncmp(exp->expectant->helper->name, info->name, 
11175 -                      strlen(exp->expectant->helper->name)) ^ info->invert;
11176 +       if (info->name[0] == '\0')
11177 +               ret ^= 1;
11178 +       else
11179 +               ret ^= !strncmp(exp->expectant->helper->name, info->name, 
11180 +                               strlen(exp->expectant->helper->name));
11181  out_unlock:
11182         READ_UNLOCK(&ip_conntrack_lock);
11183         return ret;
11184 @@ -92,10 +95,6 @@
11185         if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info)))
11186                 return 0;
11187  
11188 -       /* verify that we actually should match anything */
11189 -       if ( strlen(info->name) == 0 )
11190 -               return 0;
11191 -       
11192         return 1;
11193  }
11194  
11195 @@ -108,7 +107,6 @@
11196  
11197  static int __init init(void)
11198  {
11199 -       need_ip_conntrack();
11200         return ipt_register_match(&helper_match);
11201  }
11202  
11203 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_ipv4options.c
11204 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c    1970-01-01 01:00:00.000000000 +0100
11205 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_ipv4options.c        2004-04-30 09:10:27.000000000 +0200
11206 @@ -0,0 +1,172 @@
11207 +/*
11208 +  This is a module which is used to match ipv4 options.
11209 +  This file is distributed under the terms of the GNU General Public
11210 +  License (GPL). Copies of the GPL can be obtained from:
11211 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
11212 +
11213 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
11214 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
11215 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
11216 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
11217 +  19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
11218 +*/
11219 +
11220 +#include <linux/module.h>
11221 +#include <linux/skbuff.h>
11222 +#include <net/ip.h>
11223 +
11224 +#include <linux/netfilter_ipv4/ip_tables.h>
11225 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
11226 +
11227 +MODULE_LICENSE("GPL");
11228 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
11229 +
11230 +static int
11231 +match(const struct sk_buff *skb,
11232 +      const struct net_device *in,
11233 +      const struct net_device *out,
11234 +      const void *matchinfo,
11235 +      int offset,
11236 +      int *hotdrop)
11237 +{
11238 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
11239 +       const struct iphdr *iph = skb->nh.iph;
11240 +       const struct ip_options *opt;
11241 +
11242 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
11243 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
11244 +
11245 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
11246 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
11247 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
11248 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
11249 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
11250 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
11251 +                       return 0;
11252 +               return 1;
11253 +       }
11254 +       else {
11255 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
11256 +                       /* there are options, and we don't need to care which one */
11257 +                       return 1;
11258 +               else {
11259 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
11260 +                               /* there are options but we don't want any ! */
11261 +                               return 0;
11262 +               }
11263 +       }
11264 +
11265 +       opt = &(IPCB(skb)->opt);
11266 +
11267 +       /* source routing */
11268 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
11269 +               if (!((opt->srr) & (opt->is_strictroute)))
11270 +                       return 0;
11271 +       }
11272 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
11273 +               if (!((opt->srr) & (!opt->is_strictroute)))
11274 +                       return 0;
11275 +       }
11276 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
11277 +               if (opt->srr)
11278 +                       return 0;
11279 +       }
11280 +       /* record route */
11281 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
11282 +               if (!opt->rr)
11283 +                       return 0;
11284 +       }
11285 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
11286 +               if (opt->rr)
11287 +                       return 0;
11288 +       }
11289 +       /* timestamp */
11290 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
11291 +               if (!opt->ts)
11292 +                       return 0;
11293 +       }
11294 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
11295 +               if (opt->ts)
11296 +                       return 0;
11297 +       }
11298 +       /* router-alert option  */
11299 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
11300 +               if (!opt->router_alert)
11301 +                       return 0;
11302 +       }
11303 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
11304 +               if (opt->router_alert)
11305 +                       return 0;
11306 +       }
11307 +
11308 +       /* we match ! */
11309 +       return 1;
11310 +}
11311 +
11312 +static int
11313 +checkentry(const char *tablename,
11314 +          const struct ipt_ip *ip,
11315 +          void *matchinfo,
11316 +          unsigned int matchsize,
11317 +          unsigned int hook_mask)
11318 +{
11319 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
11320 +       /* Check the size */
11321 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
11322 +               return 0;
11323 +       /* Now check the coherence of the data ... */
11324 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
11325 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
11326 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
11327 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
11328 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
11329 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
11330 +               return 0; /* opposites */
11331 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
11332 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
11333 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
11334 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
11335 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
11336 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
11337 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
11338 +               return 0; /* opposites */
11339 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
11340 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
11341 +               return 0; /* cannot match in the same time loose and strict source routing */
11342 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
11343 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
11344 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
11345 +               return 0; /* opposites */
11346 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
11347 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
11348 +               return 0; /* opposites */
11349 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
11350 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
11351 +               return 0; /* opposites */
11352 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
11353 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
11354 +               return 0; /* opposites */
11355 +
11356 +       /* everything looks ok. */
11357 +       return 1;
11358 +}
11359 +
11360 +static struct ipt_match ipv4options_match = { 
11361 +       .name = "ipv4options",
11362 +       .match = match,
11363 +       .checkentry = checkentry,
11364 +       .me = THIS_MODULE
11365 +};
11366 +
11367 +static int __init init(void)
11368 +{
11369 +       return ipt_register_match(&ipv4options_match);
11370 +}
11371 +
11372 +static void __exit fini(void)
11373 +{
11374 +       ipt_unregister_match(&ipv4options_match);
11375 +}
11376 +
11377 +module_init(init);
11378 +module_exit(fini);
11379 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_mport.c
11380 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_mport.c  1970-01-01 01:00:00.000000000 +0100
11381 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_mport.c      2004-04-30 09:10:30.000000000 +0200
11382 @@ -0,0 +1,116 @@
11383 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
11384 +   the same place so we can treat them as equal. */
11385 +#include <linux/module.h>
11386 +#include <linux/types.h>
11387 +#include <linux/udp.h>
11388 +#include <linux/skbuff.h>
11389 +
11390 +#include <linux/netfilter_ipv4/ipt_mport.h>
11391 +#include <linux/netfilter_ipv4/ip_tables.h>
11392 +
11393 +MODULE_LICENSE("GPL");
11394 +
11395 +#if 0
11396 +#define duprintf(format, args...) printk(format , ## args)
11397 +#else
11398 +#define duprintf(format, args...)
11399 +#endif
11400 +
11401 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
11402 +static inline int
11403 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
11404 +{
11405 +       unsigned int i;
11406 +        unsigned int m;
11407 +        u_int16_t pflags = minfo->pflags;
11408 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
11409 +                u_int16_t s, e;
11410 +
11411 +                if (pflags & m
11412 +                    && minfo->ports[i] == 65535)
11413 +                        return 0;
11414 +
11415 +                s = minfo->ports[i];
11416 +
11417 +                if (pflags & m) {
11418 +                        e = minfo->ports[++i];
11419 +                        m <<= 1;
11420 +                } else
11421 +                        e = s;
11422 +
11423 +                if (minfo->flags & IPT_MPORT_SOURCE
11424 +                    && src >= s && src <= e)
11425 +                        return 1;
11426 +
11427 +               if (minfo->flags & IPT_MPORT_DESTINATION
11428 +                   && dst >= s && dst <= e)
11429 +                       return 1;
11430 +       }
11431 +
11432 +       return 0;
11433 +}
11434 +
11435 +static int
11436 +match(const struct sk_buff *skb,
11437 +      const struct net_device *in,
11438 +      const struct net_device *out,
11439 +      const void *matchinfo,
11440 +      int offset,
11441 +      int *hotdrop)
11442 +{
11443 +       u16 ports[2];
11444 +       const struct ipt_mport *minfo = matchinfo;
11445 +
11446 +       if (offset)
11447 +               return 0;
11448 +
11449 +       /* Must be big enough to read ports (both UDP and TCP have
11450 +           them at the start). */
11451 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
11452 +               /* We've been asked to examine this packet, and we
11453 +                  can't.  Hence, no choice but to drop. */
11454 +                       duprintf("ipt_multiport:"
11455 +                                " Dropping evil offset=0 tinygram.\n");
11456 +                       *hotdrop = 1;
11457 +                       return 0;
11458 +       }
11459 +
11460 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
11461 +}
11462 +
11463 +/* Called when user tries to insert an entry of this type. */
11464 +static int
11465 +checkentry(const char *tablename,
11466 +          const struct ipt_ip *ip,
11467 +          void *matchinfo,
11468 +          unsigned int matchsize,
11469 +          unsigned int hook_mask)
11470 +{
11471 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
11472 +               return 0;
11473 +
11474 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
11475 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
11476 +               && !(ip->invflags & IPT_INV_PROTO)
11477 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
11478 +}
11479 +
11480 +static struct ipt_match mport_match = { 
11481 +       .name = "mport",
11482 +       .match = &match,
11483 +       .checkentry = &checkentry,
11484 +       .me = THIS_MODULE
11485 +};
11486 +
11487 +static int __init init(void)
11488 +{
11489 +       return ipt_register_match(&mport_match);
11490 +}
11491 +
11492 +static void __exit fini(void)
11493 +{
11494 +       ipt_unregister_match(&mport_match);
11495 +}
11496 +
11497 +module_init(init);
11498 +module_exit(fini);
11499 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_nth.c
11500 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_nth.c    1970-01-01 01:00:00.000000000 +0100
11501 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_nth.c        2004-04-30 09:10:36.000000000 +0200
11502 @@ -0,0 +1,166 @@
11503 +/*
11504 +  This is a module which is used for match support for every Nth packet
11505 +  This file is distributed under the terms of the GNU General Public
11506 +  License (GPL). Copies of the GPL can be obtained from:
11507 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
11508 +
11509 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
11510 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
11511 +        * added support for multiple counters
11512 +        * added support for matching on individual packets
11513 +          in the counter cycle
11514 +  2004-02-19 Harald Welte <laforge@netfilter.org>
11515 +       * port to 2.6.x
11516 +
11517 +*/
11518 +
11519 +#include <linux/module.h>
11520 +#include <linux/skbuff.h>
11521 +#include <linux/ip.h>
11522 +#include <net/tcp.h>
11523 +#include <linux/spinlock.h>
11524 +#include <linux/netfilter_ipv4/ip_tables.h>
11525 +#include <linux/netfilter_ipv4/ipt_nth.h>
11526 +
11527 +MODULE_LICENSE("GPL");
11528 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
11529 +
11530 +/*
11531 + * State information.
11532 + */
11533 +struct state {
11534 +       spinlock_t lock;
11535 +       u_int16_t number;
11536 +};
11537 +
11538 +static struct state states[IPT_NTH_NUM_COUNTERS];
11539 +
11540 +static int
11541 +ipt_nth_match(const struct sk_buff *pskb,
11542 +             const struct net_device *in,
11543 +             const struct net_device *out,
11544 +             const void *matchinfo,
11545 +             int offset,
11546 +             int *hotdrop)
11547 +{
11548 +       /* Parameters from userspace */
11549 +       const struct ipt_nth_info *info = matchinfo;
11550 +        unsigned counter = info->counter;
11551 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
11552 +       {
11553 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
11554 +               return 0;
11555 +        };
11556 +
11557 +        spin_lock(&states[counter].lock);
11558 +
11559 +        /* Are we matching every nth packet?*/
11560 +        if (info->packet == 0xFF)
11561 +        {
11562 +               /* We're matching every nth packet and only every nth packet*/
11563 +               /* Do we match or invert match? */
11564 +               if (info->not == 0)
11565 +               {
11566 +                       if (states[counter].number == 0)
11567 +                       {
11568 +                               ++states[counter].number;
11569 +                               goto match;
11570 +                       }
11571 +                       if (states[counter].number >= info->every)
11572 +                               states[counter].number = 0; /* reset the counter */
11573 +                       else
11574 +                               ++states[counter].number;
11575 +                       goto dontmatch;
11576 +               }
11577 +               else
11578 +               {
11579 +                       if (states[counter].number == 0)
11580 +                       {
11581 +                               ++states[counter].number;
11582 +                               goto dontmatch;
11583 +                       }
11584 +                       if (states[counter].number >= info->every)
11585 +                               states[counter].number = 0;
11586 +                       else
11587 +                               ++states[counter].number;
11588 +                       goto match;
11589 +               }
11590 +        }
11591 +        else
11592 +        {
11593 +               /* We're using the --packet, so there must be a rule for every value */
11594 +               if (states[counter].number == info->packet)
11595 +               {
11596 +                       /* only increment the counter when a match happens */
11597 +                       if (states[counter].number >= info->every)
11598 +                               states[counter].number = 0; /* reset the counter */
11599 +                       else
11600 +                               ++states[counter].number;
11601 +                       goto match;
11602 +               }
11603 +               else
11604 +                       goto dontmatch;
11605 +       }
11606 +
11607 + dontmatch:
11608 +       /* don't match */
11609 +       spin_unlock(&states[counter].lock);
11610 +       return 0;
11611 +
11612 + match:
11613 +       spin_unlock(&states[counter].lock);
11614 +       return 1;
11615 +}
11616 +
11617 +static int
11618 +ipt_nth_checkentry(const char *tablename,
11619 +                  const struct ipt_ip *e,
11620 +                  void *matchinfo,
11621 +                  unsigned int matchsize,
11622 +                  unsigned int hook_mask)
11623 +{
11624 +       /* Parameters from userspace */
11625 +       const struct ipt_nth_info *info = matchinfo;
11626 +        unsigned counter = info->counter;
11627 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
11628 +       {
11629 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
11630 +                       return 0;
11631 +               };
11632 +
11633 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
11634 +               printk("nth: matchsize %u != %u\n", matchsize,
11635 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
11636 +               return 0;
11637 +       }
11638 +
11639 +       states[counter].number = info->startat;
11640 +
11641 +       return 1;
11642 +}
11643 +
11644 +static struct ipt_match ipt_nth_reg = { 
11645 +       .name = "nth",
11646 +       .match = ipt_nth_match,
11647 +       .checkentry = ipt_nth_checkentry,
11648 +       .me = THIS_MODULE
11649 +};
11650 +
11651 +static int __init init(void)
11652 +{
11653 +       unsigned counter;
11654 +
11655 +       memset(&states, 0, sizeof(states));
11656 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
11657 +               spin_lock_init(&(states[counter].lock));
11658 +
11659 +       return ipt_register_match(&ipt_nth_reg);
11660 +}
11661 +
11662 +static void __exit fini(void)
11663 +{
11664 +       ipt_unregister_match(&ipt_nth_reg);
11665 +}
11666 +
11667 +module_init(init);
11668 +module_exit(fini);
11669 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_osf.c
11670 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_osf.c    1970-01-01 01:00:00.000000000 +0100
11671 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_osf.c        2004-04-30 09:10:38.000000000 +0200
11672 @@ -0,0 +1,865 @@
11673 +/*
11674 + * ipt_osf.c
11675 + *
11676 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
11677 + *
11678 + *
11679 + * This program is free software; you can redistribute it and/or modify
11680 + * it under the terms of the GNU General Public License as published by
11681 + * the Free Software Foundation; either version 2 of the License, or
11682 + * (at your option) any later version.
11683 + *
11684 + * This program is distributed in the hope that it will be useful,
11685 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11686 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11687 + * GNU General Public License for more details.
11688 + *
11689 + * You should have received a copy of the GNU General Public License
11690 + * along with this program; if not, write to the Free Software
11691 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11692 + */
11693 +
11694 +/*
11695 + * OS fingerprint matching module.
11696 + * It simply compares various parameters from SYN packet with
11697 + * some hardcoded ones.
11698 + *
11699 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
11700 + * for his p0f.
11701 + */
11702 +
11703 +#include <linux/config.h>
11704 +#include <linux/kernel.h>
11705 +#include <linux/types.h>
11706 +#include <linux/string.h>
11707 +#include <linux/smp.h>
11708 +#include <linux/module.h>
11709 +#include <linux/skbuff.h>
11710 +#include <linux/file.h>
11711 +#include <linux/ip.h>
11712 +#include <linux/proc_fs.h>
11713 +#include <linux/fs.h>
11714 +#include <linux/slab.h>
11715 +#include <linux/spinlock.h>
11716 +#include <linux/ctype.h>
11717 +#include <linux/list.h>
11718 +#include <linux/if.h>
11719 +
11720 +#include <net/sock.h>
11721 +#include <net/ip.h>
11722 +
11723 +#include <linux/netfilter_ipv4/ip_tables.h>
11724 +
11725 +#include <linux/netfilter_ipv4/ipt_osf.h>
11726 +
11727 +#define OSF_DEBUG
11728 +
11729 +#ifdef OSF_DEBUG
11730 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
11731 +#define loga(x...)             printk(x)
11732 +#else
11733 +#define log(x...)              do {} while(0)
11734 +#define loga(x...)             do {} while(0)
11735 +#endif
11736 +
11737 +#define FMATCH_WRONG           0
11738 +#define FMATCH_OK              1
11739 +#define FMATCH_OPT_WRONG       2
11740 +
11741 +#define OPTDEL                 ','
11742 +#define OSFPDEL                ':'
11743 +#define MAXOPTSTRLEN           128
11744 +#define OSFFLUSH               "FLUSH"
11745 +
11746 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
11747 +static spinlock_t ipt_osf_netlink_lock = SPIN_LOCK_UNLOCKED;
11748 +static struct list_head        finger_list;    
11749 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
11750 +                     const void *, int, 
11751 +                     const void *, u_int16_t, 
11752 +                     int *);
11753 +static int checkentry(const char *, const struct ipt_ip *, void *,
11754 +                          unsigned int, unsigned int);
11755 +
11756 +static unsigned long seq, ipt_osf_groups = 1;
11757 +static struct sock *nts;
11758 +
11759 +static struct ipt_match osf_match = 
11760 +{ 
11761 +       { NULL, NULL }, 
11762 +       "osf", 
11763 +       &match, 
11764 +       &checkentry, 
11765 +       NULL, 
11766 +       THIS_MODULE 
11767 +};
11768 +
11769 +static void ipt_osf_nlsend(struct osf_finger *f, const struct sk_buff *sk)
11770 +{
11771 +       unsigned int size;
11772 +       struct sk_buff *skb;
11773 +       struct ipt_osf_nlmsg *data;
11774 +       struct nlmsghdr *nlh;
11775 +
11776 +       size = NLMSG_SPACE(sizeof(struct ipt_osf_nlmsg));
11777 +
11778 +       skb = alloc_skb(size, GFP_ATOMIC);
11779 +       if (!skb)
11780 +       {
11781 +               log("skb_alloc() failed.\n");
11782 +               return;
11783 +       }
11784 +       
11785 +       nlh = NLMSG_PUT(skb, 0, seq++, NLMSG_DONE, size - sizeof(*nlh));
11786 +       
11787 +       data = (struct ipt_osf_nlmsg *)NLMSG_DATA(nlh);
11788 +
11789 +       memcpy(&data->f, f, sizeof(struct osf_finger));
11790 +       memcpy(&data->ip, sk->nh.iph, sizeof(struct iphdr));
11791 +       memcpy(&data->tcp, (struct tcphdr *)((u_int32_t *)sk->nh.iph + sk->nh.iph->ihl), sizeof(struct tcphdr));
11792 +
11793 +       NETLINK_CB(skb).dst_groups = ipt_osf_groups;
11794 +       netlink_broadcast(nts, skb, 0, ipt_osf_groups, GFP_ATOMIC);
11795 +
11796 +nlmsg_failure:
11797 +       return;
11798 +}
11799 +
11800 +static inline int smart_dec(const struct sk_buff *skb, unsigned long flags, unsigned char f_ttl)
11801 +{
11802 +       struct iphdr *ip = skb->nh.iph;
11803 +
11804 +       if (flags & IPT_OSF_SMART)
11805 +       {
11806 +               struct in_device *in_dev = in_dev_get(skb->dev);
11807 +
11808 +               for_ifa(in_dev)
11809 +               {
11810 +                       if (inet_ifa_match(ip->saddr, ifa))
11811 +                       {
11812 +                               in_dev_put(in_dev);
11813 +                               return (ip->ttl == f_ttl);
11814 +                       }
11815 +               }
11816 +               endfor_ifa(in_dev);
11817 +               
11818 +               in_dev_put(in_dev);
11819 +               return (ip->ttl <= f_ttl);
11820 +       }
11821 +       else
11822 +               return (ip->ttl == f_ttl);
11823 +}
11824 +
11825 +static int
11826 +match(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out,
11827 +      const void *matchinfo, int offset,
11828 +      const void *hdr, u_int16_t datalen,
11829 +      int *hotdrop)
11830 +{
11831 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
11832 +       struct iphdr *ip = skb->nh.iph;
11833 +       struct tcphdr *tcp;
11834 +       int fmatch = FMATCH_WRONG, fcount = 0;
11835 +       unsigned long totlen, optsize = 0, window;
11836 +       unsigned char df, *optp = NULL, *_optp = NULL;
11837 +       char check_WSS = 0;
11838 +       struct list_head *ent;
11839 +       struct osf_finger *f;
11840 +
11841 +       if (!ip || !info)
11842 +               return 0;
11843 +                               
11844 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
11845 +
11846 +       if (!tcp->syn)
11847 +               return 0;
11848 +       
11849 +       totlen = ntohs(ip->tot_len);
11850 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
11851 +       window = ntohs(tcp->window);
11852 +       
11853 +       if (tcp->doff*4 > sizeof(struct tcphdr))
11854 +       {
11855 +               _optp = optp = (char *)(tcp+1);
11856 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
11857 +       }
11858 +
11859 +       
11860 +       /* Actually we can create hash/table of all genres and search
11861 +        * only in appropriate part, but here is initial variant,
11862 +        * so will use slow path.
11863 +        */
11864 +       read_lock(&osf_lock);
11865 +       list_for_each(ent, &finger_list)
11866 +       {
11867 +               f = list_entry(ent, struct osf_finger, flist);
11868 +       
11869 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
11870 +                       continue;
11871 +
11872 +               optp = _optp;
11873 +               fmatch = FMATCH_WRONG;
11874 +
11875 +               if (totlen == f->ss && df == f->df && 
11876 +                       smart_dec(skb, info->flags, f->ttl))
11877 +               {
11878 +                       unsigned long foptsize;
11879 +                       int optnum;
11880 +                       unsigned short mss = 0;
11881 +
11882 +                       check_WSS = 0;
11883 +
11884 +                       switch (f->wss.wc)
11885 +                       {
11886 +                               case 0:   check_WSS = 0; break;
11887 +                               case 'S': check_WSS = 1; break;
11888 +                               case 'T': check_WSS = 2; break;
11889 +                               case '%': check_WSS = 3; break;
11890 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
11891 +                                                        f->wss.wc, f->genre, f->details);
11892 +                                        check_WSS = 4;
11893 +                                        break;
11894 +                       }
11895 +                       if (check_WSS == 4)
11896 +                               continue;
11897 +
11898 +                       /* Check options */
11899 +
11900 +                       foptsize = 0;
11901 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
11902 +                               foptsize += f->opt[optnum].length;
11903 +
11904 +                               
11905 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
11906 +                               continue;
11907 +
11908 +                       if (!optp)
11909 +                       {
11910 +                               fmatch = FMATCH_OK;
11911 +                               loga("\tYEP : matching without options.\n");
11912 +                               if ((info->flags & IPT_OSF_LOG) && 
11913 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
11914 +                                       break;
11915 +                               else
11916 +                                       continue;
11917 +                       }
11918 +                       
11919 +
11920 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
11921 +                       {
11922 +                               if (f->opt[optnum].kind == (*optp)) 
11923 +                               {
11924 +                                       unsigned char len = f->opt[optnum].length;
11925 +                                       unsigned char *optend = optp + len;
11926 +                                       int loop_cont = 0;
11927 +
11928 +                                       fmatch = FMATCH_OK;
11929 +
11930 +
11931 +                                       switch (*optp)
11932 +                                       {
11933 +                                               case OSFOPT_MSS:
11934 +                                                       mss = ntohs(*(unsigned short *)(optp+2));
11935 +                                                       break;
11936 +                                               case OSFOPT_TS:
11937 +                                                       loop_cont = 1;
11938 +                                                       break;
11939 +                                       }
11940 +                                       
11941 +                                       if (loop_cont)
11942 +                                       {
11943 +                                               optp = optend;
11944 +                                               continue;
11945 +                                       }
11946 +                                       
11947 +                                       if (len != 1)
11948 +                                       {
11949 +                                               /* Skip kind and length fields*/
11950 +                                               optp += 2; 
11951 +
11952 +                                               if (f->opt[optnum].wc.val != 0)
11953 +                                               {
11954 +                                                       unsigned long tmp = 0;
11955 +                                                       
11956 +                                                       /* Hmmm... It looks a bit ugly. :) */
11957 +                                                       memcpy(&tmp, optp, 
11958 +                                                               (len > sizeof(unsigned long)?
11959 +                                                                       sizeof(unsigned long):len));
11960 +                                                       /* 2 + 2: optlen(2 bytes) + 
11961 +                                                        *      kind(1 byte) + length(1 byte) */
11962 +                                                       if (len == 4) 
11963 +                                                               tmp = ntohs(tmp);
11964 +                                                       else
11965 +                                                               tmp = ntohl(tmp);
11966 +
11967 +                                                       if (f->opt[optnum].wc.wc == '%')
11968 +                                                       {
11969 +                                                               if ((tmp % f->opt[optnum].wc.val) != 0)
11970 +                                                                       fmatch = FMATCH_OPT_WRONG;
11971 +                                                       }
11972 +                                                       else if (tmp != f->opt[optnum].wc.val)
11973 +                                                               fmatch = FMATCH_OPT_WRONG;
11974 +                                               }
11975 +                                       }
11976 +
11977 +                                       optp = optend;
11978 +                               }
11979 +                               else
11980 +                                       fmatch = FMATCH_OPT_WRONG;
11981 +
11982 +                               if (fmatch != FMATCH_OK)
11983 +                                       break;
11984 +                       }
11985 +
11986 +                       if (fmatch != FMATCH_OPT_WRONG)
11987 +                       {
11988 +                               fmatch = FMATCH_WRONG;
11989 +
11990 +                               switch (check_WSS)
11991 +                               {
11992 +                                       case 0:
11993 +                                               if (f->wss.val == 0 || window == f->wss.val)
11994 +                                                       fmatch = FMATCH_OK;
11995 +                                               break;
11996 +                                       case 1: /* MSS */
11997 +/* Lurked in OpenBSD */
11998 +#define SMART_MSS      1460
11999 +                                               if (window == f->wss.val*mss || 
12000 +                                                       window == f->wss.val*SMART_MSS)
12001 +                                                       fmatch = FMATCH_OK;
12002 +                                               break;
12003 +                                       case 2: /* MTU */
12004 +                                               if (window == f->wss.val*(mss+40) ||
12005 +                                                       window == f->wss.val*(SMART_MSS+40))
12006 +                                                       fmatch = FMATCH_OK;
12007 +                                               break;
12008 +                                       case 3: /* MOD */
12009 +                                               if ((window % f->wss.val) == 0)
12010 +                                                       fmatch = FMATCH_OK;
12011 +                                               break;
12012 +                               }
12013 +                       }
12014 +                                       
12015 +
12016 +                       if (fmatch == FMATCH_OK)
12017 +                       {
12018 +                               fcount++;
12019 +                               log("%s [%s:%s:%s] : %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u hops=%d\n", 
12020 +                                       f->genre, f->version,
12021 +                                       f->subtype, f->details,
12022 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
12023 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest),
12024 +                                       f->ttl - ip->ttl);
12025 +                               if (info->flags & IPT_OSF_NETLINK)
12026 +                               {
12027 +                                       spin_lock_bh(&ipt_osf_netlink_lock);
12028 +                                       ipt_osf_nlsend(f, skb);
12029 +                                       spin_unlock_bh(&ipt_osf_netlink_lock);
12030 +                               }
12031 +                               if ((info->flags & IPT_OSF_LOG) && 
12032 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
12033 +                                       break;
12034 +                       }
12035 +               }
12036 +       }
12037 +       if (!fcount && (info->flags & (IPT_OSF_LOG | IPT_OSF_NETLINK)))
12038 +       {
12039 +               unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
12040 +               unsigned int i, optsize;
12041 +               struct osf_finger fg;
12042 +
12043 +               memset(&fg, 0, sizeof(fg));
12044 +
12045 +               if ((info->flags & IPT_OSF_LOG))
12046 +                       log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
12047 +               if (optp)
12048 +               {
12049 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
12050 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
12051 +                                         opt, optsize) < 0)
12052 +                       {
12053 +                               if (info->flags & IPT_OSF_LOG)
12054 +                                       loga("TRUNCATED");
12055 +                               if (info->flags & IPT_OSF_NETLINK)
12056 +                                       strcpy(fg.details, "TRUNCATED");
12057 +                       }
12058 +                       else
12059 +                       {
12060 +                               for (i = 0; i < optsize; i++)
12061 +                               {
12062 +                                       if (info->flags & IPT_OSF_LOG)
12063 +                                               loga("%02X", opt[i]);
12064 +                               }
12065 +                               if (info->flags & IPT_OSF_NETLINK)
12066 +                                       memcpy(fg.details, opt, MAXDETLEN);
12067 +                       }
12068 +               }
12069 +               if ((info->flags & IPT_OSF_LOG))
12070 +                       loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
12071 +                               NIPQUAD(ip->saddr), ntohs(tcp->source),
12072 +                               NIPQUAD(ip->daddr), ntohs(tcp->dest));
12073 +               
12074 +               if (info->flags & IPT_OSF_NETLINK)
12075 +               {
12076 +                       fg.wss.val      = window;
12077 +                       fg.ttl          = ip->ttl;
12078 +                       fg.df           = df;
12079 +                       fg.ss           = totlen;
12080 +                       strncpy(fg.genre, "Unknown", MAXGENRELEN);
12081 +
12082 +                       spin_lock_bh(&ipt_osf_netlink_lock);
12083 +                       ipt_osf_nlsend(&fg, skb);
12084 +                       spin_unlock_bh(&ipt_osf_netlink_lock);
12085 +               }
12086 +       }
12087 +
12088 +       read_unlock(&osf_lock);
12089 +
12090 +       return (fmatch == FMATCH_OK)?1:0;
12091 +}
12092 +
12093 +static int
12094 +checkentry(const char *tablename,
12095 +           const struct ipt_ip *ip,
12096 +           void *matchinfo,
12097 +           unsigned int matchsize,
12098 +           unsigned int hook_mask)
12099 +{
12100 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
12101 +               return 0;
12102 +       if (ip->proto != IPPROTO_TCP)
12103 +              return 0;
12104 +
12105 +       return 1;
12106 +}
12107 +
12108 +static char * osf_strchr(char *ptr, char c)
12109 +{
12110 +       char *tmp;
12111 +
12112 +       tmp = strchr(ptr, c);
12113 +
12114 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
12115 +               tmp++;
12116 +
12117 +       return tmp;
12118 +}
12119 +
12120 +static struct osf_finger * finger_alloc(void)
12121 +{
12122 +       struct osf_finger *f;
12123 +
12124 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
12125 +       if (f)
12126 +               memset(f, 0, sizeof(struct osf_finger));
12127 +       
12128 +       return f;
12129 +}
12130 +
12131 +static void finger_free(struct osf_finger *f)
12132 +{
12133 +       memset(f, 0, sizeof(struct osf_finger));
12134 +       kfree(f);
12135 +}
12136 +
12137 +
12138 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
12139 +{
12140 +       int i, op;
12141 +       char *ptr, wc;
12142 +       unsigned long val;
12143 +
12144 +       ptr = &obuf[0];
12145 +       i = 0;
12146 +       while (ptr != NULL && i < olen)
12147 +       {
12148 +               val = 0;
12149 +               op = 0;
12150 +               wc = 0;
12151 +               switch (obuf[i])
12152 +               {
12153 +                       case 'N': 
12154 +                               op = OSFOPT_NOP;
12155 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
12156 +                               if (ptr)
12157 +                               {
12158 +                                       *ptr = '\0';
12159 +                                       ptr++;
12160 +                                       i += (int)(ptr-&obuf[i]);
12161 +
12162 +                               }
12163 +                               else
12164 +                                       i++;
12165 +                               break;
12166 +                       case 'S': 
12167 +                               op = OSFOPT_SACKP;
12168 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
12169 +                               if (ptr)
12170 +                               {
12171 +                                       *ptr = '\0';
12172 +                                       ptr++;
12173 +                                       i += (int)(ptr-&obuf[i]);
12174 +
12175 +                               }
12176 +                               else
12177 +                                       i++;
12178 +                               break;
12179 +                       case 'T': 
12180 +                               op = OSFOPT_TS;
12181 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
12182 +                               if (ptr)
12183 +                               {
12184 +                                       *ptr = '\0';
12185 +                                       ptr++;
12186 +                                       i += (int)(ptr-&obuf[i]);
12187 +
12188 +                               }
12189 +                               else
12190 +                                       i++;
12191 +                               break;
12192 +                       case 'W': 
12193 +                               op = OSFOPT_WSO;
12194 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
12195 +                               if (ptr)
12196 +                               {
12197 +                                       switch (obuf[i+1])
12198 +                                       {
12199 +                                               case '%':       wc = '%'; break;
12200 +                                               case 'S':       wc = 'S'; break;
12201 +                                               case 'T':       wc = 'T'; break;
12202 +                                               default:        wc = 0; break;
12203 +                                       }
12204 +                                       
12205 +                                       *ptr = '\0';
12206 +                                       ptr++;
12207 +                                       if (wc)
12208 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
12209 +                                       else
12210 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
12211 +                                       i += (int)(ptr-&obuf[i]);
12212 +
12213 +                               }
12214 +                               else
12215 +                                       i++;
12216 +                               break;
12217 +                       case 'M': 
12218 +                               op = OSFOPT_MSS;
12219 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
12220 +                               if (ptr)
12221 +                               {
12222 +                                       if (obuf[i+1] == '%')
12223 +                                               wc = '%';
12224 +                                       *ptr = '\0';
12225 +                                       ptr++;
12226 +                                       if (wc)
12227 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
12228 +                                       else
12229 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
12230 +                                       i += (int)(ptr-&obuf[i]);
12231 +
12232 +                               }
12233 +                               else
12234 +                                       i++;
12235 +                               break;
12236 +                       case 'E': 
12237 +                               op = OSFOPT_EOL;
12238 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
12239 +                               if (ptr)
12240 +                               {
12241 +                                       *ptr = '\0';
12242 +                                       ptr++;
12243 +                                       i += (int)(ptr-&obuf[i]);
12244 +
12245 +                               }
12246 +                               else
12247 +                                       i++;
12248 +                               break;
12249 +                       default:
12250 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
12251 +                               if (ptr)
12252 +                               {
12253 +                                       ptr++;
12254 +                                       i += (int)(ptr-&obuf[i]);
12255 +
12256 +                               }
12257 +                               else
12258 +                                       i++;
12259 +                               break;
12260 +               }
12261 +
12262 +               opt[*optnum].kind       = IANA_opts[op].kind;
12263 +               opt[*optnum].length     = IANA_opts[op].length;
12264 +               opt[*optnum].wc.wc      = wc;
12265 +               opt[*optnum].wc.val     = val;
12266 +
12267 +               (*optnum)++;
12268 +       }
12269 +}
12270 +
12271 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
12272 +{
12273 +       struct list_head *ent;
12274 +       struct osf_finger *f = NULL;
12275 +       int i;
12276 +       
12277 +       *eof = 1;
12278 +       count = 0;
12279 +
12280 +       read_lock_bh(&osf_lock);
12281 +       list_for_each(ent, &finger_list)
12282 +       {
12283 +               f = list_entry(ent, struct osf_finger, flist);
12284 +
12285 +               log("%s [%s]", f->genre, f->details);
12286 +               
12287 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
12288 +                                       f->genre, f->version,
12289 +                                       f->subtype, f->details);
12290 +               
12291 +               if (f->opt_num)
12292 +               {
12293 +                       loga(" OPT: ");
12294 +                       //count += sprintf(buf+count, " OPT: ");
12295 +                       for (i=0; i<f->opt_num; ++i)
12296 +                       {
12297 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
12298 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
12299 +                               loga("%d.%c%lu; ", 
12300 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
12301 +                       }
12302 +               }
12303 +               loga("\n");
12304 +               count += sprintf(buf+count, "\n");
12305 +       }
12306 +       read_unlock_bh(&osf_lock);
12307 +
12308 +       return count;
12309 +}
12310 +
12311 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
12312 +{
12313 +       int cnt;
12314 +       unsigned long i;
12315 +       char obuf[MAXOPTSTRLEN];
12316 +       struct osf_finger *finger;
12317 +       struct list_head *ent, *n;
12318 +
12319 +       char *pbeg, *pend;
12320 +
12321 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
12322 +       {
12323 +               int i = 0;
12324 +               write_lock_bh(&osf_lock);
12325 +               list_for_each_safe(ent, n, &finger_list)
12326 +               {
12327 +                       i++;
12328 +                       finger = list_entry(ent, struct osf_finger, flist);
12329 +                       list_del(&finger->flist);
12330 +                       finger_free(finger);
12331 +               }
12332 +               write_unlock_bh(&osf_lock);
12333 +       
12334 +               log("Flushed %d entries.\n", i);
12335 +               
12336 +               return count;
12337 +       }
12338 +
12339 +       
12340 +       cnt = 0;
12341 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
12342 +               if (buffer[i] == ':')
12343 +                       cnt++;
12344 +
12345 +       if (cnt != 8 || i != count)
12346 +       {
12347 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
12348 +                       cnt, i, count);
12349 +               return count;
12350 +       }
12351 +
12352 +       memset(obuf, 0, sizeof(obuf));
12353 +       
12354 +       finger = finger_alloc();
12355 +       if (!finger)
12356 +       {
12357 +               log("Failed to allocate new fingerprint entry.\n");
12358 +               return -ENOMEM;
12359 +       }
12360 +
12361 +       pbeg = (char *)buffer;
12362 +       pend = osf_strchr(pbeg, OSFPDEL);
12363 +       if (pend)
12364 +       {
12365 +               *pend = '\0';
12366 +               if (pbeg[0] == 'S')
12367 +               {
12368 +                       finger->wss.wc = 'S';
12369 +                       if (pbeg[1] == '%')
12370 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
12371 +                       else if (pbeg[1] == '*')
12372 +                               finger->wss.val = 0;
12373 +                       else 
12374 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
12375 +               }
12376 +               else if (pbeg[0] == 'T')
12377 +               {
12378 +                       finger->wss.wc = 'T';
12379 +                       if (pbeg[1] == '%')
12380 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
12381 +                       else if (pbeg[1] == '*')
12382 +                               finger->wss.val = 0;
12383 +                       else 
12384 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
12385 +               }
12386 +               else if (pbeg[0] == '%')
12387 +               {
12388 +                       finger->wss.wc = '%';
12389 +                       finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
12390 +               }
12391 +               else if (isdigit(pbeg[0]))
12392 +               {
12393 +                       finger->wss.wc = 0;
12394 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
12395 +               }
12396 +
12397 +               pbeg = pend+1;
12398 +       }
12399 +       pend = osf_strchr(pbeg, OSFPDEL);
12400 +       if (pend)
12401 +       {
12402 +               *pend = '\0';
12403 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
12404 +               pbeg = pend+1;
12405 +       }
12406 +       pend = osf_strchr(pbeg, OSFPDEL);
12407 +       if (pend)
12408 +       {
12409 +               *pend = '\0';
12410 +               finger->df = simple_strtoul(pbeg, NULL, 10);
12411 +               pbeg = pend+1;
12412 +       }
12413 +       pend = osf_strchr(pbeg, OSFPDEL);
12414 +       if (pend)
12415 +       {
12416 +               *pend = '\0';
12417 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
12418 +               pbeg = pend+1;
12419 +       }
12420 +
12421 +       pend = osf_strchr(pbeg, OSFPDEL);
12422 +       if (pend)
12423 +       {
12424 +               *pend = '\0';
12425 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
12426 +               pbeg = pend+1;
12427 +       }
12428 +
12429 +       pend = osf_strchr(pbeg, OSFPDEL);
12430 +       if (pend)
12431 +       {
12432 +               *pend = '\0';
12433 +               if (pbeg[0] == '@' || pbeg[0] == '*')
12434 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
12435 +               else
12436 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
12437 +               pbeg = pend+1;
12438 +       }
12439 +       
12440 +       pend = osf_strchr(pbeg, OSFPDEL);
12441 +       if (pend)
12442 +       {
12443 +               *pend = '\0';
12444 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
12445 +               pbeg = pend+1;
12446 +       }
12447 +       
12448 +       pend = osf_strchr(pbeg, OSFPDEL);
12449 +       if (pend)
12450 +       {
12451 +               *pend = '\0';
12452 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
12453 +               pbeg = pend+1;
12454 +       }
12455 +
12456 +       cnt = snprintf(finger->details, 
12457 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
12458 +                       "%s", pbeg);
12459 +       
12460 +       log("%s - %s[%s] : %s\n", 
12461 +               finger->genre, finger->version,
12462 +               finger->subtype, finger->details);
12463 +       
12464 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
12465 +       
12466 +
12467 +       write_lock_bh(&osf_lock);
12468 +       list_add_tail(&finger->flist, &finger_list);
12469 +       write_unlock_bh(&osf_lock);
12470 +
12471 +       return count;
12472 +}
12473 +
12474 +static int __init osf_init(void)
12475 +{
12476 +       int err;
12477 +       struct proc_dir_entry *p;
12478 +
12479 +       log("Startng OS fingerprint matching module.\n");
12480 +
12481 +       INIT_LIST_HEAD(&finger_list);
12482 +       
12483 +       err = ipt_register_match(&osf_match);
12484 +       if (err)
12485 +       {
12486 +               log("Failed to register OS fingerprint matching module.\n");
12487 +               return -ENXIO;
12488 +       }
12489 +
12490 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
12491 +       if (!p)
12492 +       {
12493 +               ipt_unregister_match(&osf_match);
12494 +               return -ENXIO;
12495 +       }
12496 +
12497 +       p->write_proc = osf_proc_write;
12498 +       p->read_proc  = osf_proc_read;
12499 +       
12500 +       nts = netlink_kernel_create(NETLINK_NFLOG, NULL);
12501 +       if (!nts)
12502 +       {
12503 +               log("netlink_kernel_create() failed\n");
12504 +               remove_proc_entry("sys/net/ipv4/osf", NULL);
12505 +               ipt_unregister_match(&osf_match);
12506 +               return -ENOMEM;
12507 +       }
12508 +
12509 +       return 0;
12510 +}
12511 +
12512 +static void __exit osf_fini(void)
12513 +{
12514 +       struct list_head *ent, *n;
12515 +       struct osf_finger *f;
12516 +       
12517 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
12518 +       ipt_unregister_match(&osf_match);
12519 +       if (nts && nts->sk_socket)
12520 +               sock_release(nts->sk_socket);
12521 +
12522 +       list_for_each_safe(ent, n, &finger_list)
12523 +       {
12524 +               f = list_entry(ent, struct osf_finger, flist);
12525 +               list_del(&f->flist);
12526 +               finger_free(f);
12527 +       }
12528 +       
12529 +       log("OS fingerprint matching module finished.\n");
12530 +}
12531 +
12532 +module_init(osf_init);
12533 +module_exit(osf_fini);
12534 +
12535 +MODULE_LICENSE("GPL");
12536 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
12537 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
12538 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c
12539 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_owner.c  2004-04-28 03:36:37.000000000 +0200
12540 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_owner.c      2004-04-30 09:13:14.000000000 +0200
12541 @@ -6,12 +6,19 @@
12542   * This program is free software; you can redistribute it and/or modify
12543   * it under the terms of the GNU General Public License version 2 as
12544   * published by the Free Software Foundation.
12545 + *
12546 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
12547   */
12548  
12549  #include <linux/module.h>
12550  #include <linux/skbuff.h>
12551  #include <linux/file.h>
12552 +#include <linux/ip.h>
12553 +#include <linux/tcp.h>
12554 +#include <linux/udp.h>
12555  #include <net/sock.h>
12556 +#include <net/tcp.h>
12557 +#include <net/udp.h>
12558  
12559  #include <linux/netfilter_ipv4/ipt_owner.h>
12560  #include <linux/netfilter_ipv4/ip_tables.h>
12561 @@ -21,7 +28,7 @@
12562  MODULE_DESCRIPTION("iptables owner match");
12563  
12564  static int
12565 -match_comm(const struct sk_buff *skb, const char *comm)
12566 +match_comm(const struct sock *sk, const char *comm)
12567  {
12568         struct task_struct *g, *p;
12569         struct files_struct *files;
12570 @@ -38,7 +45,7 @@
12571                         spin_lock(&files->file_lock);
12572                         for (i=0; i < files->max_fds; i++) {
12573                                 if (fcheck_files(files, i) ==
12574 -                                   skb->sk->sk_socket->file) {
12575 +                                   sk->sk_socket->file) {
12576                                         spin_unlock(&files->file_lock);
12577                                         task_unlock(p);
12578                                         read_unlock(&tasklist_lock);
12579 @@ -54,7 +61,7 @@
12580  }
12581  
12582  static int
12583 -match_pid(const struct sk_buff *skb, pid_t pid)
12584 +match_pid(const struct sock *sk, pid_t pid)
12585  {
12586         struct task_struct *p;
12587         struct files_struct *files;
12588 @@ -70,7 +77,7 @@
12589                 spin_lock(&files->file_lock);
12590                 for (i=0; i < files->max_fds; i++) {
12591                         if (fcheck_files(files, i) ==
12592 -                           skb->sk->sk_socket->file) {
12593 +                           sk->sk_socket->file) {
12594                                 spin_unlock(&files->file_lock);
12595                                 task_unlock(p);
12596                                 read_unlock(&tasklist_lock);
12597 @@ -86,10 +93,10 @@
12598  }
12599  
12600  static int
12601 -match_sid(const struct sk_buff *skb, pid_t sid)
12602 +match_sid(const struct sock *sk, pid_t sid)
12603  {
12604         struct task_struct *g, *p;
12605 -       struct file *file = skb->sk->sk_socket->file;
12606 +       struct file *file = sk->sk_socket->file;
12607         int i, found=0;
12608  
12609         read_lock(&tasklist_lock);
12610 @@ -129,41 +136,71 @@
12611        int *hotdrop)
12612  {
12613         const struct ipt_owner_info *info = matchinfo;
12614 +       struct iphdr *iph = skb->nh.iph;
12615 +       struct sock *sk = NULL;
12616 +       int ret = 0;
12617 +
12618 +       if (out) {
12619 +               sk = skb->sk;
12620 +       } else {
12621 +               if (iph->protocol == IPPROTO_TCP) {
12622 +                       struct tcphdr *tcph =
12623 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
12624 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
12625 +                                          iph->daddr, tcph->dest,
12626 +                                          skb->dev->ifindex);
12627 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
12628 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
12629 +                               return ret;
12630 +                       }
12631 +               } else if (iph->protocol == IPPROTO_UDP) {
12632 +                       struct udphdr *udph =
12633 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
12634 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
12635 +                                          udph->dest, skb->dev->ifindex);
12636 +               }
12637 +       }
12638  
12639 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
12640 -               return 0;
12641 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
12642 +               goto out;
12643  
12644         if(info->match & IPT_OWNER_UID) {
12645 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
12646 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
12647                     !!(info->invert & IPT_OWNER_UID))
12648 -                       return 0;
12649 +                       goto out;
12650         }
12651  
12652         if(info->match & IPT_OWNER_GID) {
12653 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
12654 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
12655                     !!(info->invert & IPT_OWNER_GID))
12656 -                       return 0;
12657 +                       goto out;
12658         }
12659  
12660         if(info->match & IPT_OWNER_PID) {
12661 -               if (!match_pid(skb, info->pid) ^
12662 +               if (!match_pid(sk, info->pid) ^
12663                     !!(info->invert & IPT_OWNER_PID))
12664 -                       return 0;
12665 +                       goto out;
12666         }
12667  
12668         if(info->match & IPT_OWNER_SID) {
12669 -               if (!match_sid(skb, info->sid) ^
12670 +               if (!match_sid(sk, info->sid) ^
12671                     !!(info->invert & IPT_OWNER_SID))
12672 -                       return 0;
12673 +                       goto out;
12674         }
12675  
12676         if(info->match & IPT_OWNER_COMM) {
12677 -               if (!match_comm(skb, info->comm) ^
12678 +               if (!match_comm(sk, info->comm) ^
12679                     !!(info->invert & IPT_OWNER_COMM))
12680 -                       return 0;
12681 +                       goto out;
12682         }
12683  
12684 -       return 1;
12685 +       ret = 1;
12686 +
12687 +out:
12688 +       if (in && sk)
12689 +               sock_put(sk);
12690 +
12691 +       return ret;
12692  }
12693  
12694  static int
12695 @@ -173,11 +210,19 @@
12696             unsigned int matchsize,
12697             unsigned int hook_mask)
12698  {
12699 -        if (hook_mask
12700 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
12701 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
12702 -                return 0;
12703 -        }
12704 +       if (hook_mask
12705 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
12706 +           (1 << NF_IP_LOCAL_IN))) {
12707 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
12708 +                      "or POST_ROUTING.\n");
12709 +               return 0;
12710 +       }
12711 +
12712 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
12713 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
12714 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
12715 +               return 0;
12716 +       }
12717  
12718         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
12719                 printk("Matchsize %u != %Zu\n", matchsize,
12720 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c
12721 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_policy.c 1970-01-01 01:00:00.000000000 +0100
12722 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_policy.c     2004-04-30 09:13:22.000000000 +0200
12723 @@ -0,0 +1,176 @@
12724 +/* IP tables module for matching IPsec policy
12725 + *
12726 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
12727 + *
12728 + * This program is free software; you can redistribute it and/or modify
12729 + * it under the terms of the GNU General Public License version 2 as
12730 + * published by the Free Software Foundation.
12731 + */
12732 +
12733 +#include <linux/kernel.h>
12734 +#include <linux/config.h>
12735 +#include <linux/module.h>
12736 +#include <linux/skbuff.h>
12737 +#include <linux/init.h>
12738 +#include <net/xfrm.h>
12739 +
12740 +#include <linux/netfilter_ipv4.h>
12741 +#include <linux/netfilter_ipv4/ipt_policy.h>
12742 +#include <linux/netfilter_ipv4/ip_tables.h>
12743 +
12744 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
12745 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
12746 +MODULE_LICENSE("GPL");
12747 +
12748 +
12749 +static inline int
12750 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
12751 +{
12752 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
12753 +
12754 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
12755 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
12756 +           MISMATCH(proto, x->id.proto) ||
12757 +           MISMATCH(mode, x->props.mode) ||
12758 +           MISMATCH(spi, x->id.spi) ||
12759 +           MISMATCH(reqid, x->props.reqid))
12760 +               return 0;
12761 +       return 1;
12762 +}
12763 +
12764 +static int
12765 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
12766 +{
12767 +       const struct ipt_policy_elem *e;
12768 +       struct sec_path *sp = skb->sp;
12769 +       int strict = info->flags & POLICY_MATCH_STRICT;
12770 +       int i, pos;
12771 +
12772 +       if (sp == NULL)
12773 +               return -1;
12774 +       if (strict && info->len != sp->len)
12775 +               return 0;
12776 +
12777 +       for (i = sp->len - 1; i >= 0; i--) {
12778 +               pos = strict ? i - sp->len + 1 : 0;
12779 +               if (pos >= info->len)
12780 +                       return 0;
12781 +               e = &info->pol[pos];
12782 +
12783 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
12784 +                       if (!strict)
12785 +                               return 1;
12786 +               } else if (strict)
12787 +                       return 0;
12788 +       }
12789 +
12790 +       return strict ? 1 : 0;
12791 +}
12792 +
12793 +static int
12794 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
12795 +{
12796 +       const struct ipt_policy_elem *e;
12797 +       struct dst_entry *dst = skb->dst;
12798 +       int strict = info->flags & POLICY_MATCH_STRICT;
12799 +       int i, pos;
12800 +
12801 +       if (dst->xfrm == NULL)
12802 +               return -1;
12803 +
12804 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
12805 +               pos = strict ? i : 0;
12806 +               if (pos >= info->len)
12807 +                       return 0;
12808 +               e = &info->pol[pos];
12809 +
12810 +               if (match_xfrm_state(dst->xfrm, e)) {
12811 +                       if (!strict)
12812 +                               return 1;
12813 +               } else if (strict)
12814 +                       return 0;
12815 +       }
12816 +
12817 +       return strict ? 1 : 0;
12818 +}
12819 +
12820 +static int match(const struct sk_buff *skb,
12821 +                 const struct net_device *in,
12822 +                 const struct net_device *out,
12823 +                 const void *matchinfo, int offset, int *hotdrop)
12824 +{
12825 +       const struct ipt_policy_info *info = matchinfo;
12826 +       int ret;
12827 +
12828 +       if (info->flags & POLICY_MATCH_IN)
12829 +               ret = match_policy_in(skb, info);
12830 +       else
12831 +               ret = match_policy_out(skb, info);
12832 +
12833 +       if (ret < 0) {
12834 +               if (info->flags & POLICY_MATCH_NONE)
12835 +                       ret = 1;
12836 +               else
12837 +                       ret = 0;
12838 +       } else if (info->flags & POLICY_MATCH_NONE)
12839 +               ret = 0;
12840 +
12841 +       return ret;
12842 +}
12843 +
12844 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
12845 +                      void *matchinfo, unsigned int matchsize,
12846 +                      unsigned int hook_mask)
12847 +{
12848 +       struct ipt_policy_info *info = matchinfo;
12849 +
12850 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
12851 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
12852 +                      matchsize, IPT_ALIGN(sizeof(*info)));
12853 +               return 0;
12854 +       }
12855 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
12856 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
12857 +                               "outgoing policy selected\n");
12858 +               return 0;
12859 +       }
12860 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
12861 +           && info->flags & POLICY_MATCH_OUT) {
12862 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
12863 +                               "PRE_ROUTING and INPUT\n");
12864 +               return 0;
12865 +       }
12866 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
12867 +           && info->flags & POLICY_MATCH_IN) {
12868 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
12869 +                               "POST_ROUTING and OUTPUT\n");
12870 +               return 0;
12871 +       }
12872 +       if (info->len > POLICY_MAX_ELEM) {
12873 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
12874 +               return 0;
12875 +       }
12876 +
12877 +       return 1;
12878 +}
12879 +
12880 +static struct ipt_match policy_match =
12881 +{
12882 +       .name           = "policy",
12883 +       .match          = match,
12884 +       .checkentry     = checkentry,
12885 +       .me             = THIS_MODULE,
12886 +};
12887 +
12888 +static int __init init(void)
12889 +{
12890 +       return ipt_register_match(&policy_match);
12891 +}
12892 +
12893 +static void __exit fini(void)
12894 +{
12895 +       ipt_unregister_match(&policy_match);
12896 +}
12897 +
12898 +module_init(init);
12899 +module_exit(fini);
12900 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_pool.c
12901 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_pool.c   1970-01-01 01:00:00.000000000 +0100
12902 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_pool.c       2004-04-30 09:10:40.000000000 +0200
12903 @@ -0,0 +1,71 @@
12904 +/* Kernel module to match an IP address pool. */
12905 +
12906 +#include <linux/module.h>
12907 +#include <linux/ip.h>
12908 +#include <linux/skbuff.h>
12909 +
12910 +#include <linux/netfilter_ipv4/ip_tables.h>
12911 +#include <linux/netfilter_ipv4/ip_pool.h>
12912 +#include <linux/netfilter_ipv4/ipt_pool.h>
12913 +
12914 +static inline int match_pool(
12915 +       ip_pool_t index,
12916 +       __u32 addr,
12917 +       int inv
12918 +) {
12919 +       if (ip_pool_match(index, ntohl(addr)))
12920 +               inv = !inv;
12921 +       return inv;
12922 +}
12923 +
12924 +static int match(
12925 +       const struct sk_buff *skb,
12926 +       const struct net_device *in,
12927 +       const struct net_device *out,
12928 +       const void *matchinfo,
12929 +       int offset,
12930 +       const void *hdr,
12931 +       u_int16_t datalen,
12932 +       int *hotdrop
12933 +) {
12934 +       const struct ipt_pool_info *info = matchinfo;
12935 +       const struct iphdr *iph = skb->nh.iph;
12936 +
12937 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
12938 +                                               info->flags&IPT_POOL_INV_SRC))
12939 +               return 0;
12940 +
12941 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
12942 +                                               info->flags&IPT_POOL_INV_DST))
12943 +               return 0;
12944 +
12945 +       return 1;
12946 +}
12947 +
12948 +static int checkentry(
12949 +       const char *tablename,
12950 +       const struct ipt_ip *ip,
12951 +       void *matchinfo,
12952 +       unsigned int matchsize,
12953 +       unsigned int hook_mask
12954 +) {
12955 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
12956 +               return 0;
12957 +       return 1;
12958 +}
12959 +
12960 +static struct ipt_match pool_match
12961 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
12962 +
12963 +static int __init init(void)
12964 +{
12965 +       return ipt_register_match(&pool_match);
12966 +}
12967 +
12968 +static void __exit fini(void)
12969 +{
12970 +       ipt_unregister_match(&pool_match);
12971 +}
12972 +
12973 +module_init(init);
12974 +module_exit(fini);
12975 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_psd.c
12976 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_psd.c    1970-01-01 01:00:00.000000000 +0100
12977 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_psd.c        2004-04-30 09:10:44.000000000 +0200
12978 @@ -0,0 +1,361 @@
12979 +/*
12980 +  This is a module which is used for PSD (portscan detection)
12981 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
12982 +  and LOG target module.
12983 +
12984 +  Copyright (C) 2000,2001 astaro AG
12985 +
12986 +  This file is distributed under the terms of the GNU General Public
12987 +  License (GPL). Copies of the GPL can be obtained from:
12988 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
12989 +
12990 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
12991 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
12992 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
12993 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
12994 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
12995 +*/
12996 +
12997 +#include <linux/module.h>
12998 +#include <linux/skbuff.h>
12999 +#include <linux/ip.h>
13000 +#include <net/tcp.h>
13001 +#include <linux/spinlock.h>
13002 +#include <linux/netfilter_ipv4/ip_tables.h>
13003 +#include <linux/netfilter_ipv4/ipt_psd.h>
13004 +
13005 +#if 0
13006 +#define DEBUGP printk
13007 +#else
13008 +#define DEBUGP(format, args...)
13009 +#endif
13010 +
13011 +MODULE_LICENSE("GPL");
13012 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
13013 +
13014 +#define HF_DADDR_CHANGING   0x01
13015 +#define HF_SPORT_CHANGING   0x02
13016 +#define HF_TOS_CHANGING            0x04
13017 +#define HF_TTL_CHANGING            0x08
13018 +            
13019 +/*
13020 + * Information we keep per each target port
13021 + */
13022 +struct port {
13023 +       u_int16_t number;      /* port number */ 
13024 +       u_int8_t proto;        /* protocol number */
13025 +       u_int8_t and_flags;    /* tcp ANDed flags */
13026 +       u_int8_t or_flags;     /* tcp ORed flags */
13027 +};
13028 +
13029 +/*
13030 + * Information we keep per each source address.
13031 + */
13032 +struct host {
13033 +       struct host *next;              /* Next entry with the same hash */
13034 +       clock_t timestamp;              /* Last update time */
13035 +       struct in_addr src_addr;        /* Source address */
13036 +       struct in_addr dest_addr;       /* Destination address */
13037 +       unsigned short src_port;        /* Source port */
13038 +       int count;                      /* Number of ports in the list */
13039 +       int weight;                     /* Total weight of ports in the list */
13040 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
13041 +       unsigned char tos;              /* TOS */
13042 +       unsigned char ttl;              /* TTL */
13043 +       unsigned char flags;            /* HF_ flags bitmask */
13044 +};
13045 +
13046 +/*
13047 + * State information.
13048 + */
13049 +static struct {
13050 +       spinlock_t lock;
13051 +       struct host list[LIST_SIZE];    /* List of source addresses */
13052 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
13053 +       int index;                      /* Oldest entry to be replaced */
13054 +} state;
13055 +
13056 +/*
13057 + * Convert an IP address into a hash table index.
13058 + */
13059 +static inline int hashfunc(struct in_addr addr)
13060 +{
13061 +       unsigned int value;
13062 +       int hash;
13063 +
13064 +       value = addr.s_addr;
13065 +       hash = 0;
13066 +       do {
13067 +               hash ^= value;
13068 +       } while ((value >>= HASH_LOG));
13069 +
13070 +       return hash & (HASH_SIZE - 1);
13071 +}
13072 +
13073 +static int
13074 +ipt_psd_match(const struct sk_buff *pskb,
13075 +             const struct net_device *in,
13076 +             const struct net_device *out,
13077 +             const void *matchinfo,
13078 +             int offset,
13079 +             const void *hdr,
13080 +             u_int16_t datalen,
13081 +             int *hotdrop)
13082 +{
13083 +       struct iphdr *ip_hdr;
13084 +       struct tcphdr *tcp_hdr;
13085 +       struct in_addr addr;
13086 +       u_int16_t src_port,dest_port;
13087 +       u_int8_t tcp_flags, proto;
13088 +       clock_t now;
13089 +       struct host *curr, *last, **head;
13090 +       int hash, index, count;
13091 +
13092 +       /* Parameters from userspace */
13093 +       const struct ipt_psd_info *psdinfo = matchinfo;
13094 +
13095 +       /* IP header */
13096 +       ip_hdr = pskb->nh.iph;
13097 +
13098 +       /* Sanity check */
13099 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
13100 +               DEBUGP("PSD: sanity check failed\n");
13101 +               return 0;
13102 +       }
13103 +
13104 +       /* TCP or UDP ? */
13105 +       proto = ip_hdr->protocol;
13106 +
13107 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
13108 +               DEBUGP("PSD: protocol not supported\n");
13109 +               return 0;
13110 +       }
13111 +
13112 +       /* Get the source address, source & destination ports, and TCP flags */
13113 +
13114 +       addr.s_addr = ip_hdr->saddr;
13115 +
13116 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
13117 +
13118 +       /* Yep, it´s dirty */
13119 +       src_port = tcp_hdr->source;
13120 +       dest_port = tcp_hdr->dest;
13121 +
13122 +       if (proto == IPPROTO_TCP) {
13123 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
13124 +       }
13125 +       else {
13126 +               tcp_flags = 0x00;
13127 +       }
13128 +
13129 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
13130 +        * them spoof us. [DHCP needs this feature - HW] */
13131 +       if (!addr.s_addr) {
13132 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
13133 +               return 0;
13134 +       }
13135 +
13136 +       /* Use jiffies here not to depend on someone setting the time while we're
13137 +        * running; we need to be careful with possible return value overflows. */
13138 +       now = jiffies;
13139 +
13140 +       spin_lock(&state.lock);
13141 +
13142 +       /* Do we know this source address already? */
13143 +       count = 0;
13144 +       last = NULL;
13145 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
13146 +               do {
13147 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
13148 +                       count++;
13149 +                       if (curr->next) last = curr;
13150 +               } while ((curr = curr->next));
13151 +
13152 +       if (curr) {
13153 +
13154 +               /* We know this address, and the entry isn't too old. Update it. */
13155 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
13156 +                   time_after_eq(now, curr->timestamp)) {
13157 +
13158 +                       /* Just update the appropriate list entry if we've seen this port already */
13159 +                       for (index = 0; index < curr->count; index++) {
13160 +                               if (curr->ports[index].number == dest_port) {
13161 +                                       curr->ports[index].proto = proto;
13162 +                                       curr->ports[index].and_flags &= tcp_flags;
13163 +                                       curr->ports[index].or_flags |= tcp_flags;
13164 +                                       goto out_no_match;
13165 +                               }
13166 +                       }
13167 +
13168 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
13169 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
13170 +                               goto out_no_match;
13171 +
13172 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
13173 +                       curr->timestamp = now;
13174 +
13175 +                       /* Logged this scan already? Then drop the packet. */
13176 +                       if (curr->weight >= psdinfo->weight_threshold)
13177 +                               goto out_match;
13178 +
13179 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
13180 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
13181 +                               curr->flags |= HF_DADDR_CHANGING;
13182 +                       if (curr->src_port != src_port)
13183 +                               curr->flags |= HF_SPORT_CHANGING;
13184 +                       if (curr->tos != ip_hdr->tos)
13185 +                               curr->flags |= HF_TOS_CHANGING;
13186 +                       if (curr->ttl != ip_hdr->ttl)
13187 +                               curr->flags |= HF_TTL_CHANGING;
13188 +
13189 +                       /* Update the total weight */
13190 +                       curr->weight += (ntohs(dest_port) < 1024) ?
13191 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
13192 +
13193 +                       /* Got enough destination ports to decide that this is a scan? */
13194 +                       /* Then log it and drop the packet. */
13195 +                       if (curr->weight >= psdinfo->weight_threshold)
13196 +                               goto out_match;
13197 +
13198 +                       /* Remember the new port */
13199 +                       if (curr->count < SCAN_MAX_COUNT) {
13200 +                               curr->ports[curr->count].number = dest_port;
13201 +                               curr->ports[curr->count].proto = proto;
13202 +                               curr->ports[curr->count].and_flags = tcp_flags;
13203 +                               curr->ports[curr->count].or_flags = tcp_flags;
13204 +                               curr->count++;
13205 +                       }
13206 +
13207 +                       goto out_no_match;
13208 +               }
13209 +
13210 +               /* We know this address, but the entry is outdated. Mark it unused, and
13211 +                * remove from the hash table. We'll allocate a new entry instead since
13212 +                * this one might get re-used too soon. */
13213 +               curr->src_addr.s_addr = 0;
13214 +               if (last)
13215 +                       last->next = last->next->next;
13216 +               else if (*head)
13217 +                       *head = (*head)->next;
13218 +               last = NULL;
13219 +       }
13220 +
13221 +       /* We don't need an ACK from a new source address */
13222 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
13223 +               goto out_no_match;
13224 +
13225 +       /* Got too many source addresses with the same hash value? Then remove the
13226 +        * oldest one from the hash table, so that they can't take too much of our
13227 +        * CPU time even with carefully chosen spoofed IP addresses. */
13228 +       if (count >= HASH_MAX && last) last->next = NULL;
13229 +
13230 +       /* We're going to re-use the oldest list entry, so remove it from the hash
13231 +        * table first (if it is really already in use, and isn't removed from the
13232 +        * hash table already because of the HASH_MAX check above). */
13233 +
13234 +       /* First, find it */
13235 +       if (state.list[state.index].src_addr.s_addr)
13236 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
13237 +       else
13238 +               head = &last;
13239 +       last = NULL;
13240 +       if ((curr = *head))
13241 +       do {
13242 +               if (curr == &state.list[state.index]) break;
13243 +               last = curr;
13244 +       } while ((curr = curr->next));
13245 +
13246 +       /* Then, remove it */
13247 +       if (curr) {
13248 +               if (last)
13249 +                       last->next = last->next->next;
13250 +               else if (*head)
13251 +                       *head = (*head)->next;
13252 +       }
13253 +
13254 +       /* Get our list entry */
13255 +       curr = &state.list[state.index++];
13256 +       if (state.index >= LIST_SIZE) state.index = 0;
13257 +
13258 +       /* Link it into the hash table */
13259 +       head = &state.hash[hash];
13260 +       curr->next = *head;
13261 +       *head = curr;
13262 +
13263 +       /* And fill in the fields */
13264 +       curr->timestamp = now;
13265 +       curr->src_addr = addr;
13266 +       curr->dest_addr.s_addr = ip_hdr->daddr;
13267 +       curr->src_port = src_port;
13268 +       curr->count = 1;
13269 +       curr->weight = (ntohs(dest_port) < 1024) ?
13270 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
13271 +       curr->ports[0].number = dest_port;
13272 +       curr->ports[0].proto = proto;
13273 +       curr->ports[0].and_flags = tcp_flags;
13274 +       curr->ports[0].or_flags = tcp_flags;
13275 +       curr->tos = ip_hdr->tos;
13276 +       curr->ttl = ip_hdr->ttl;
13277 +
13278 +out_no_match:
13279 +       spin_unlock(&state.lock);
13280 +       return 0;
13281 +
13282 +out_match:
13283 +       spin_unlock(&state.lock);
13284 +       return 1;
13285 +}
13286 +
13287 +static int ipt_psd_checkentry(const char *tablename,
13288 +                             const struct ipt_ip *e,
13289 +                             void *matchinfo,
13290 +                             unsigned int matchsize,
13291 +                             unsigned int hook_mask)
13292 +{
13293 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
13294 +
13295 +       /* we accept TCP only */
13296 +/*     if (e->ip.proto != IPPROTO_TCP) { */
13297 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
13298 +/*             return 0; */
13299 +/*     } */
13300 +
13301 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
13302 +               DEBUGP("PSD: matchsize %u != %u\n",
13303 +                      matchsize,
13304 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
13305 +               return 0;
13306 +       }
13307 +
13308 +       return 1;
13309 +}
13310 +
13311 +static struct ipt_match ipt_psd_reg = { 
13312 +       {NULL, NULL},
13313 +       "psd",
13314 +       ipt_psd_match,
13315 +       ipt_psd_checkentry,
13316 +       NULL,
13317 +       THIS_MODULE };
13318 +
13319 +static int __init init(void)
13320 +{
13321 +       if (ipt_register_match(&ipt_psd_reg))
13322 +               return -EINVAL;
13323 +
13324 +       memset(&state, 0, sizeof(state));
13325 +
13326 +       spin_lock_init(&(state.lock));
13327 +
13328 +       printk("netfilter PSD loaded - (c) astaro AG\n");
13329 +       return 0;
13330 +}
13331 +
13332 +static void __exit fini(void)
13333 +{
13334 +       ipt_unregister_match(&ipt_psd_reg);
13335 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
13336 +}
13337 +
13338 +module_init(init);
13339 +module_exit(fini);
13340 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_quota.c
13341 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_quota.c  1970-01-01 01:00:00.000000000 +0100
13342 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_quota.c      2004-04-30 09:10:45.000000000 +0200
13343 @@ -0,0 +1,91 @@
13344 +/* 
13345 + * netfilter module to enforce network quotas
13346 + *
13347 + * Sam Johnston <samj@samj.net>
13348 + */
13349 +#include <linux/module.h>
13350 +#include <linux/skbuff.h>
13351 +#include <linux/spinlock.h>
13352 +#include <linux/interrupt.h>
13353 +
13354 +#include <linux/netfilter_ipv4/ip_tables.h>
13355 +#include <linux/netfilter_ipv4/ipt_quota.h>
13356 +
13357 +MODULE_LICENSE("GPL");
13358 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
13359 +
13360 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
13361 +
13362 +static int
13363 +match(const struct sk_buff *skb,
13364 +      const struct net_device *in,
13365 +      const struct net_device *out,
13366 +      const void *matchinfo,
13367 +      int offset, int *hotdrop)
13368 +{
13369 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
13370 +       unsigned int datalen;
13371 +
13372 +       if (skb->len < sizeof(struct iphdr))
13373 +               return NF_ACCEPT;
13374 +       
13375 +       datalen = skb->len - skb->nh.iph->ihl*4;
13376 +
13377 +        spin_lock_bh(&quota_lock);
13378 +
13379 +        if (q->quota >= datalen) {
13380 +                /* we can afford this one */
13381 +                q->quota -= datalen;
13382 +                spin_unlock_bh(&quota_lock);
13383 +
13384 +#ifdef DEBUG_IPT_QUOTA
13385 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
13386 +#endif
13387 +                return 1;
13388 +        }
13389 +
13390 +        /* so we do not allow even small packets from now on */
13391 +        q->quota = 0;
13392 +
13393 +#ifdef DEBUG_IPT_QUOTA
13394 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
13395 +#endif
13396 +
13397 +        spin_unlock_bh(&quota_lock);
13398 +        return 0;
13399 +}
13400 +
13401 +static int
13402 +checkentry(const char *tablename,
13403 +           const struct ipt_ip *ip,
13404 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
13405 +{
13406 +        /* TODO: spinlocks? sanity checks? */
13407 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
13408 +                return 0;
13409 +
13410 +        return 1;
13411 +}
13412 +
13413 +static struct ipt_match quota_match = {
13414 +       .name = "quota",
13415 +       .match = match,
13416 +       .checkentry = checkentry,
13417 +       .me = THIS_MODULE
13418 +};
13419 +
13420 +static int __init
13421 +init(void)
13422 +{
13423 +        return ipt_register_match(&quota_match);
13424 +}
13425 +
13426 +static void __exit
13427 +fini(void)
13428 +{
13429 +        ipt_unregister_match(&quota_match);
13430 +}
13431 +
13432 +module_init(init);
13433 +module_exit(fini);
13434 +
13435 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_random.c
13436 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
13437 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_random.c     2004-04-30 09:10:46.000000000 +0200
13438 @@ -0,0 +1,96 @@
13439 +/*
13440 +  This is a module which is used for a "random" match support.
13441 +  This file is distributed under the terms of the GNU General Public
13442 +  License (GPL). Copies of the GPL can be obtained from:
13443 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
13444 +
13445 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
13446 +*/
13447 +
13448 +#include <linux/module.h>
13449 +#include <linux/skbuff.h>
13450 +#include <linux/ip.h>
13451 +#include <linux/random.h>
13452 +#include <net/tcp.h>
13453 +#include <linux/spinlock.h>
13454 +#include <linux/netfilter_ipv4/ip_tables.h>
13455 +#include <linux/netfilter_ipv4/ipt_random.h>
13456 +
13457 +MODULE_LICENSE("GPL");
13458 +
13459 +static int
13460 +ipt_rand_match(const struct sk_buff *pskb,
13461 +              const struct net_device *in,
13462 +              const struct net_device *out,
13463 +              const void *matchinfo,
13464 +              int offset,
13465 +              const void *hdr,
13466 +              u_int16_t datalen,
13467 +              int *hotdrop)
13468 +{
13469 +       /* Parameters from userspace */
13470 +       const struct ipt_rand_info *info = matchinfo;
13471 +       u_int8_t random_number;
13472 +
13473 +       /* get 1 random number from the kernel random number generation routine */
13474 +       get_random_bytes((void *)(&random_number), 1);
13475 +
13476 +       /* Do we match ? */
13477 +       if (random_number <= info->average)
13478 +               return 1;
13479 +       else
13480 +               return 0;
13481 +}
13482 +
13483 +static int
13484 +ipt_rand_checkentry(const char *tablename,
13485 +                  const struct ipt_ip *e,
13486 +                  void *matchinfo,
13487 +                  unsigned int matchsize,
13488 +                  unsigned int hook_mask)
13489 +{
13490 +       /* Parameters from userspace */
13491 +       const struct ipt_rand_info *info = matchinfo;
13492 +
13493 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
13494 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
13495 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
13496 +               return 0;
13497 +       }
13498 +
13499 +       /* must be  1 <= average % <= 99 */
13500 +       /* 1  x 2.55 = 2   */
13501 +       /* 99 x 2.55 = 252 */
13502 +       if ((info->average < 2) || (info->average > 252)) {
13503 +               printk("ipt_random:  invalid average %u\n", info->average);
13504 +               return 0;
13505 +       }
13506 +
13507 +       return 1;
13508 +}
13509 +
13510 +static struct ipt_match ipt_rand_reg = { 
13511 +       {NULL, NULL},
13512 +       "random",
13513 +       ipt_rand_match,
13514 +       ipt_rand_checkentry,
13515 +       NULL,
13516 +       THIS_MODULE };
13517 +
13518 +static int __init init(void)
13519 +{
13520 +       if (ipt_register_match(&ipt_rand_reg))
13521 +               return -EINVAL;
13522 +
13523 +       printk("ipt_random match loaded\n");
13524 +       return 0;
13525 +}
13526 +
13527 +static void __exit fini(void)
13528 +{
13529 +       ipt_unregister_match(&ipt_rand_reg);
13530 +       printk("ipt_random match unloaded\n");
13531 +}
13532 +
13533 +module_init(init);
13534 +module_exit(fini);
13535 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_realm.c
13536 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_realm.c  1970-01-01 01:00:00.000000000 +0100
13537 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_realm.c      2004-04-30 09:10:50.000000000 +0200
13538 @@ -0,0 +1,78 @@
13539 +/* IP tables module for matching the routing realm
13540 + *
13541 + * $Id$
13542 + *
13543 + * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
13544 + *
13545 + * This program is free software; you can redistribute it and/or modify
13546 + * it under the terms of the GNU General Public License version 2 as
13547 + * published by the Free Software Foundation.
13548 + */
13549 +
13550 +#include <linux/module.h>
13551 +#include <linux/skbuff.h>
13552 +#include <linux/netdevice.h>
13553 +#include <net/route.h>
13554 +
13555 +#include <linux/netfilter_ipv4/ipt_realm.h>
13556 +#include <linux/netfilter_ipv4/ip_tables.h>
13557 +
13558 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
13559 +MODULE_LICENSE("GPL");
13560 +
13561 +static int
13562 +match(const struct sk_buff *skb,
13563 +      const struct net_device *in,
13564 +      const struct net_device *out,
13565 +      const void *matchinfo,
13566 +      int offset,
13567 +      int *hotdrop)
13568 +{
13569 +       const struct ipt_realm_info *info = matchinfo;
13570 +       struct dst_entry *dst = skb->dst;
13571 +    
13572 +       if (!dst)
13573 +               return 0;
13574 +
13575 +       return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
13576 +}
13577 +
13578 +static int check(const char *tablename,
13579 +                 const struct ipt_ip *ip,
13580 +                 void *matchinfo,
13581 +                 unsigned int matchsize,
13582 +                 unsigned int hook_mask)
13583 +{
13584 +       if (hook_mask
13585 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
13586 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
13587 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
13588 +                      "LOCAL_IN or FORWARD.\n");
13589 +               return 0;
13590 +       }
13591 +
13592 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
13593 +               return 0;
13594 +
13595 +       return 1;
13596 +}
13597 +
13598 +static struct ipt_match realm_match = {
13599 +       .name = "realm",
13600 +       .match = match, 
13601 +       .checkentry = check,
13602 +       .me = THIS_MODULE
13603 +};
13604 +
13605 +static int __init init(void)
13606 +{
13607 +       return ipt_register_match(&realm_match);
13608 +}
13609 +
13610 +static void __exit fini(void)
13611 +{
13612 +       ipt_unregister_match(&realm_match);
13613 +}
13614 +
13615 +module_init(init);
13616 +module_exit(fini);
13617 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_sctp.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_sctp.c
13618 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_sctp.c   1970-01-01 01:00:00.000000000 +0100
13619 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_sctp.c       2004-04-30 09:10:52.000000000 +0200
13620 @@ -0,0 +1,199 @@
13621 +#include <linux/module.h>
13622 +#include <linux/skbuff.h>
13623 +#include <net/ip.h>
13624 +#include <linux/sctp.h>
13625 +
13626 +#include <linux/netfilter_ipv4/ip_tables.h>
13627 +#include <linux/netfilter_ipv4/ipt_sctp.h>
13628 +
13629 +#if 0
13630 +#define duprintf(format, args...) printk(format , ## args)
13631 +#else
13632 +#define duprintf(format, args...)
13633 +#endif
13634 +
13635 +#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
13636 +                                             || (!!((invflag) & (option)) ^ (cond)))
13637 +
13638 +static int
13639 +match_flags(const struct ipt_sctp_flag_info *flag_info,
13640 +           const int flag_count,
13641 +           u_int8_t chunktype,
13642 +           u_int8_t chunkflags)
13643 +{
13644 +       int i;
13645 +
13646 +       for (i = 0; i < flag_count; i++) {
13647 +               if (flag_info[i].chunktype == chunktype) {
13648 +                       return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
13649 +               }
13650 +       }
13651 +
13652 +       return 1;
13653 +}
13654 +
13655 +static int
13656 +match_packet(const struct sk_buff *skb,
13657 +            const u_int32_t *chunkmap,
13658 +            int chunk_match_type,
13659 +            const struct ipt_sctp_flag_info *flag_info,
13660 +            const int flag_count,
13661 +            int *hotdrop)
13662 +{
13663 +       int offset;
13664 +       u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
13665 +       sctp_chunkhdr_t sch;
13666 +
13667 +       int i = 0;
13668 +
13669 +       if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
13670 +               SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
13671 +       }
13672 +
13673 +       offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t);
13674 +       do {
13675 +               if (skb_copy_bits(skb, offset, &sch, sizeof(sch)) < 0) {
13676 +                       duprintf("Dropping invalid SCTP packet.\n");
13677 +                       *hotdrop = 1;
13678 +                       return 0;
13679 +               }
13680 +
13681 +               duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", 
13682 +                               ++i, offset, sch.type, htons(sch.length), sch.flags);
13683 +
13684 +               offset += (htons(sch.length) + 3) & ~3;
13685 +
13686 +               duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
13687 +
13688 +               if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch.type)) {
13689 +                       switch (chunk_match_type) {
13690 +                       case SCTP_CHUNK_MATCH_ANY:
13691 +                               if (match_flags(flag_info, flag_count, 
13692 +                                       sch.type, sch.flags)) {
13693 +                                       return 1;
13694 +                               }
13695 +                               break;
13696 +
13697 +                       case SCTP_CHUNK_MATCH_ALL:
13698 +                               if (match_flags(flag_info, flag_count, 
13699 +                                       sch.type, sch.flags)) {
13700 +                                       SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch.type);
13701 +                               }
13702 +                               break;
13703 +
13704 +                       case SCTP_CHUNK_MATCH_ONLY:
13705 +                               if (!match_flags(flag_info, flag_count, 
13706 +                                       sch.type, sch.flags)) {
13707 +                                       return 0;
13708 +                               }
13709 +                               break;
13710 +                       }
13711 +               } else {
13712 +                       switch (chunk_match_type) {
13713 +                       case SCTP_CHUNK_MATCH_ONLY:
13714 +                               return 0;
13715 +                       }
13716 +               }
13717 +       } while (offset < skb->len);
13718 +
13719 +       switch (chunk_match_type) {
13720 +       case SCTP_CHUNK_MATCH_ALL:
13721 +               return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
13722 +       case SCTP_CHUNK_MATCH_ANY:
13723 +               return 0;
13724 +       case SCTP_CHUNK_MATCH_ONLY:
13725 +               return 1;
13726 +       }
13727 +
13728 +       /* This will never be reached, but required to stop compiler whine */
13729 +       return 0;
13730 +}
13731 +
13732 +static int
13733 +match(const struct sk_buff *skb,
13734 +      const struct net_device *in,
13735 +      const struct net_device *out,
13736 +      const void *matchinfo,
13737 +      int offset,
13738 +      int *hotdrop)
13739 +{
13740 +       const struct ipt_sctp_info *info;
13741 +       sctp_sctphdr_t sh;
13742 +
13743 +       info = (const struct ipt_sctp_info *)matchinfo;
13744 +
13745 +       if (offset) {
13746 +               duprintf("Dropping non-first fragment.. FIXME\n");
13747 +               return 0;
13748 +       }
13749 +       
13750 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &sh, sizeof(sh)) < 0) {
13751 +               duprintf("Dropping evil TCP offset=0 tinygram.\n");
13752 +               *hotdrop = 1;
13753 +               return 0;
13754 +               }
13755 +       duprintf("spt: %d\tdpt: %d\n", ntohs(sh.source), ntohs(sh.dest));
13756 +
13757 +       return  SCCHECK(((ntohs(sh.source) >= info->spts[0]) 
13758 +                       && (ntohs(sh.source) <= info->spts[1])), 
13759 +                       IPT_SCTP_SRC_PORTS, info->flags, info->invflags)
13760 +               && SCCHECK(((ntohs(sh.dest) >= info->dpts[0]) 
13761 +                       && (ntohs(sh.dest) <= info->dpts[1])), 
13762 +                       IPT_SCTP_DEST_PORTS, info->flags, info->invflags)
13763 +               && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type,
13764 +                                       info->flag_info, info->flag_count, 
13765 +                                       hotdrop),
13766 +                          IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
13767 +}
13768 +
13769 +static int
13770 +checkentry(const char *tablename,
13771 +          const struct ipt_ip *ip,
13772 +          void *matchinfo,
13773 +          unsigned int matchsize,
13774 +          unsigned int hook_mask)
13775 +{
13776 +       const struct ipt_sctp_info *info;
13777 +
13778 +       info = (const struct ipt_sctp_info *)matchinfo;
13779 +
13780 +       return ip->proto == IPPROTO_SCTP
13781 +               && !(ip->invflags & IPT_INV_PROTO)
13782 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info))
13783 +               && !(info->flags & ~IPT_SCTP_VALID_FLAGS)
13784 +               && !(info->invflags & ~IPT_SCTP_VALID_FLAGS)
13785 +               && !(info->invflags & ~info->flags)
13786 +               && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || 
13787 +                       (info->chunk_match_type &
13788 +                               (SCTP_CHUNK_MATCH_ALL 
13789 +                               | SCTP_CHUNK_MATCH_ANY
13790 +                               | SCTP_CHUNK_MATCH_ONLY)));
13791 +}
13792 +
13793 +static struct ipt_match sctp_match = 
13794 +{ 
13795 +       .list = { NULL, NULL},
13796 +       .name = "sctp",
13797 +       .match = &match,
13798 +       .checkentry = &checkentry,
13799 +       .destroy = NULL,
13800 +       .me = THIS_MODULE
13801 +};
13802 +
13803 +static int __init init(void)
13804 +{
13805 +       return ipt_register_match(&sctp_match);
13806 +}
13807 +
13808 +static void __exit fini(void)
13809 +{
13810 +       ipt_unregister_match(&sctp_match);
13811 +}
13812 +
13813 +module_init(init);
13814 +module_exit(fini);
13815 +
13816 +MODULE_LICENSE("GPL");
13817 +MODULE_AUTHOR("Kiran Kumar Immidi");
13818 +MODULE_DESCRIPTION("Match for SCTP protocol packets");
13819 +
13820 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c
13821 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_string.c 1970-01-01 01:00:00.000000000 +0100
13822 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_string.c     2004-04-30 09:14:35.000000000 +0200
13823 @@ -0,0 +1,183 @@
13824 +/* Kernel module to match a string into a packet.
13825 + *
13826 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
13827 + * 
13828 + * ChangeLog
13829 + *     24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
13830 + *             Initial 2.6 port
13831 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
13832 + *             Fixed SMP re-entrancy problem using per-cpu data areas
13833 + *             for the skip/shift tables.
13834 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
13835 + *             Fixed kernel panic, due to overrunning boyer moore string
13836 + *             tables. Also slightly tweaked heuristic for deciding what
13837 + *             search algo to use.
13838 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
13839 + *             Implemented Boyer Moore Sublinear search algorithm
13840 + *             alongside the existing linear search based on memcmp().
13841 + *             Also a quick check to decide which method to use on a per
13842 + *             packet basis.
13843 + */
13844 +
13845 +#include <linux/smp.h>
13846 +#include <linux/percpu.h>
13847 +#include <linux/module.h>
13848 +#include <linux/skbuff.h>
13849 +#include <linux/file.h>
13850 +#include <net/sock.h>
13851 +
13852 +#include <linux/netfilter_ipv4/ip_tables.h>
13853 +#include <linux/netfilter_ipv4/ipt_string.h>
13854 +
13855 +MODULE_LICENSE("GPL");
13856 +
13857 +struct string_per_cpu {
13858 +       int skip[BM_MAX_HLEN];
13859 +       int shift[BM_MAX_HLEN];
13860 +       int len[BM_MAX_HLEN];
13861 +};
13862 +
13863 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
13864 +
13865 +
13866 +/* Boyer Moore Sublinear string search - VERY FAST */
13867 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
13868 +{
13869 +       int M1, right_end, sk, sh;  
13870 +       int ended, j, i;
13871 +
13872 +       int *skip, *shift, *len;
13873 +       
13874 +       /* use data suitable for this CPU */
13875 +       shift=__get_cpu_var(bm_string_data).shift;
13876 +       skip=__get_cpu_var(bm_string_data).skip;
13877 +       len=__get_cpu_var(bm_string_data).len;
13878 +       
13879 +       /* Setup skip/shift tables */
13880 +       M1 = right_end = needle_len-1;
13881 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
13882 +       for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
13883 +
13884 +       for (i = 1; i < needle_len; i++) {   
13885 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
13886 +               len[i] = j;  
13887 +       }  
13888 +
13889 +       shift[0] = 1;  
13890 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
13891 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
13892 +       ended = 0;  
13893 +       
13894 +       for (i = 0; i < needle_len; i++) {  
13895 +               if (len[i] == M1 - i) ended = i;  
13896 +               if (ended) shift[i] = ended;  
13897 +       }  
13898 +
13899 +       /* Do the search*/  
13900 +       while (right_end < haystack_len)
13901 +       {
13902 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
13903 +               if (i == needle_len) {
13904 +                       return haystack+(right_end - M1);
13905 +               }
13906 +               
13907 +               sk = skip[(int)haystack[right_end - i]];  
13908 +               sh = shift[i];
13909 +               right_end = max(right_end - i + sk, right_end + sh);  
13910 +       }
13911 +
13912 +       return NULL;
13913 +}  
13914 +
13915 +/* Linear string search based on memcmp() */
13916 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
13917 +{
13918 +       char *k = haystack + (haystack_len-needle_len);
13919 +       char *t = haystack;
13920 +       
13921 +       while ( t <= k ) {
13922 +               if (memcmp(t, needle, needle_len) == 0)
13923 +                       return t;
13924 +               t++;
13925 +       }
13926 +
13927 +       return NULL;
13928 +}
13929 +
13930 +static int
13931 +match(const struct sk_buff *skb,
13932 +      const struct net_device *in,
13933 +      const struct net_device *out,
13934 +      const void *matchinfo,
13935 +      int offset,
13936 +      int *hotdrop)
13937 +{
13938 +       const struct ipt_string_info *info = matchinfo;
13939 +       struct iphdr *ip = skb->nh.iph;
13940 +       int hlen, nlen;
13941 +       char *needle, *haystack;
13942 +       proc_ipt_search search=search_linear;
13943 +
13944 +       if ( !ip ) return 0;
13945 +
13946 +       /* get lenghts, and validate them */
13947 +       nlen=info->len;
13948 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
13949 +       if ( nlen > hlen ) return 0;
13950 +
13951 +       needle=(char *)&info->string;
13952 +       haystack=(char *)ip+(ip->ihl*4);
13953 +
13954 +       /* The sublinear search comes in to its own
13955 +        * on the larger packets */
13956 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
13957 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
13958 +               if ( hlen < BM_MAX_HLEN ) {
13959 +                       search=search_sublinear;
13960 +               }else{
13961 +                       if (net_ratelimit())
13962 +                               printk(KERN_INFO "ipt_string: Packet too big "
13963 +                                       "to attempt sublinear string search "
13964 +                                       "(%d bytes)\n", hlen );
13965 +               }
13966 +       }
13967 +       
13968 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
13969 +}
13970 +
13971 +static int
13972 +checkentry(const char *tablename,
13973 +           const struct ipt_ip *ip,
13974 +           void *matchinfo,
13975 +           unsigned int matchsize,
13976 +           unsigned int hook_mask)
13977 +{
13978 +
13979 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
13980 +               return 0;
13981 +
13982 +       return 1;
13983 +}
13984 +
13985 +static struct ipt_match string_match = {
13986 +    .name = "string",
13987 +    .match = &match,
13988 +    .checkentry = &checkentry,
13989 +    .me = THIS_MODULE
13990 +};
13991 +
13992 +
13993 +static int __init init(void)
13994 +{
13995 +       return ipt_register_match(&string_match);
13996 +}
13997 +
13998 +static void __exit fini(void)
13999 +{
14000 +       ipt_unregister_match(&string_match);
14001 +}
14002 +
14003 +module_init(init);
14004 +module_exit(fini);
14005 +
14006 +
14007 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_time.c
14008 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_time.c   1970-01-01 01:00:00.000000000 +0100
14009 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_time.c       2004-04-30 09:10:54.000000000 +0200
14010 @@ -0,0 +1,185 @@
14011 +/*
14012 +  This is a module which is used for time matching
14013 +  It is using some modified code from dietlibc (localtime() function)
14014 +  that you can find at http://www.fefe.de/dietlibc/
14015 +  This file is distributed under the terms of the GNU General Public
14016 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
14017 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
14018 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
14019 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
14020 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
14021 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
14022 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
14023 +*/
14024 +
14025 +#include <linux/module.h>
14026 +#include <linux/skbuff.h>
14027 +#include <linux/netfilter_ipv4/ip_tables.h>
14028 +#include <linux/netfilter_ipv4/ipt_time.h>
14029 +#include <linux/time.h>
14030 +
14031 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
14032 +MODULE_DESCRIPTION("Match arrival timestamp");
14033 +MODULE_LICENSE("GPL");
14034 +
14035 +struct tm
14036 +{
14037 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
14038 +       int tm_min;                   /* Minutes.     [0-59] */
14039 +       int tm_hour;                  /* Hours.       [0-23] */
14040 +       int tm_mday;                  /* Day.         [1-31] */
14041 +       int tm_mon;                   /* Month.       [0-11] */
14042 +       int tm_year;                  /* Year - 1900.  */
14043 +       int tm_wday;                  /* Day of week. [0-6] */
14044 +       int tm_yday;                  /* Days in year.[0-365] */
14045 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
14046 +
14047 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
14048 +       const char *tm_zone;          /* we don't care, we count from GMT */
14049 +};
14050 +
14051 +void
14052 +localtime(const time_t *timepr, struct tm *r);
14053 +
14054 +static int
14055 +match(const struct sk_buff *skb,
14056 +      const struct net_device *in,
14057 +      const struct net_device *out,
14058 +      const void *matchinfo,
14059 +      int offset,
14060 +      const void *hdr,
14061 +      u_int16_t datalen,
14062 +      int *hotdrop)
14063 +{
14064 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
14065 +       struct tm currenttime;                          /* time human readable */
14066 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
14067 +       u_int16_t packet_time;
14068 +       struct timeval kerneltimeval;
14069 +       time_t packet_local_time;
14070 +
14071 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
14072 +       if (info->kerneltime)
14073 +       {
14074 +               do_gettimeofday(&kerneltimeval);
14075 +               packet_local_time = kerneltimeval.tv_sec;
14076 +       }
14077 +       else
14078 +               packet_local_time = skb->stamp.tv_sec;
14079 +
14080 +       /* Transform the timestamp of the packet, in a human readable form */
14081 +       localtime(&packet_local_time, &currenttime);
14082 +
14083 +       /* check if we match this timestamp, we start by the days... */
14084 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
14085 +               return 0; /* the day doesn't match */
14086 +
14087 +       /* ... check the time now */
14088 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
14089 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
14090 +               return 0;
14091 +
14092 +       /* here we match ! */
14093 +       return 1;
14094 +}
14095 +
14096 +static int
14097 +checkentry(const char *tablename,
14098 +           const struct ipt_ip *ip,
14099 +           void *matchinfo,
14100 +           unsigned int matchsize,
14101 +           unsigned int hook_mask)
14102 +{
14103 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
14104 +
14105 +       /* First, check that we are in the correct hook */
14106 +       /* PRE_ROUTING, LOCAL_IN or FROWARD */
14107 +       if (hook_mask
14108 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
14109 +       {
14110 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
14111 +               return 0;
14112 +       }
14113 +       /* we use the kerneltime if we are in forward or output */
14114 +       info->kerneltime = 1;
14115 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
14116 +               /* if not, we use the skb time */
14117 +               info->kerneltime = 0;
14118 +
14119 +       /* Check the size */
14120 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
14121 +               return 0;
14122 +       /* Now check the coherence of the data ... */
14123 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
14124 +           (info->time_stop  > 1439))
14125 +       {
14126 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
14127 +               return 0;
14128 +       }
14129 +
14130 +       return 1;
14131 +}
14132 +
14133 +static struct ipt_match time_match
14134 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
14135 +
14136 +static int __init init(void)
14137 +{
14138 +       printk("ipt_time loading\n");
14139 +       return ipt_register_match(&time_match);
14140 +}
14141 +
14142 +static void __exit fini(void)
14143 +{
14144 +       ipt_unregister_match(&time_match);
14145 +       printk("ipt_time unloaded\n");
14146 +}
14147 +
14148 +module_init(init);
14149 +module_exit(fini);
14150 +
14151 +
14152 +/* The part below is borowed and modified from dietlibc */
14153 +
14154 +/* seconds per day */
14155 +#define SPD 24*60*60
14156 +
14157 +void
14158 +localtime(const time_t *timepr, struct tm *r) {
14159 +       time_t i;
14160 +       time_t timep;
14161 +       extern struct timezone sys_tz;
14162 +       const unsigned int __spm[12] =
14163 +               { 0,
14164 +                 (31),
14165 +                 (31+28),
14166 +                 (31+28+31),
14167 +                 (31+28+31+30),
14168 +                 (31+28+31+30+31),
14169 +                 (31+28+31+30+31+30),
14170 +                 (31+28+31+30+31+30+31),
14171 +                 (31+28+31+30+31+30+31+31),
14172 +                 (31+28+31+30+31+30+31+31+30),
14173 +                 (31+28+31+30+31+30+31+31+30+31),
14174 +                 (31+28+31+30+31+30+31+31+30+31+30),
14175 +               };
14176 +       register time_t work;
14177 +
14178 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
14179 +       work=timep%(SPD);
14180 +       r->tm_sec=work%60; work/=60;
14181 +       r->tm_min=work%60; r->tm_hour=work/60;
14182 +       work=timep/(SPD);
14183 +       r->tm_wday=(4+work)%7;
14184 +       for (i=1970; ; ++i) {
14185 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
14186 +               if (work>k)
14187 +                       work-=k;
14188 +               else
14189 +                       break;
14190 +       }
14191 +       r->tm_year=i-1900;
14192 +       for (i=11; i && __spm[i]>work; --i) ;
14193 +       r->tm_mon=i;
14194 +       r->tm_mday=work-__spm[i]+1;
14195 +}
14196 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_u32.c
14197 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_u32.c    1970-01-01 01:00:00.000000000 +0100
14198 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_u32.c        2004-04-30 09:10:55.000000000 +0200
14199 @@ -0,0 +1,211 @@
14200 +/* Kernel module to match u32 packet content. */
14201 +
14202 +/* 
14203 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
14204 +have specified values.  The specification of what to extract is general 
14205 +enough to find data at given offsets from tcp headers or payloads.
14206 +
14207 + --u32 tests
14208 + The argument amounts to a program in a small language described below.
14209 + tests := location = value |  tests && location = value
14210 + value := range | value , range
14211 + range := number | number : number
14212 +  a single number, n, is interpreted the same as n:n
14213 +  n:m is interpreted as the range of numbers >=n and <=m
14214 + location := number | location operator number
14215 + operator := & | << | >> | @
14216 +
14217 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
14218 + membership operator and the value syntax describes a set.  The @ operator
14219 + is what allows moving to the next header and is described further below.
14220 +
14221 + *** Until I can find out how to avoid it, there are some artificial limits
14222 + on the size of the tests:
14223 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
14224 + - no more than 10 ranges (and 9 commas) per value
14225 + - no more than 10 numbers (and 9 operators) per location
14226 +
14227 + To describe the meaning of location, imagine the following machine that
14228 + interprets it.  There are three registers:
14229 +  A is of type char*, initially the address of the IP header
14230 +  B and C are unsigned 32 bit integers, initially zero
14231 +
14232 +  The instructions are:
14233 +   number      B = number;
14234 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
14235 +   &number     C = C&number
14236 +   <<number    C = C<<number
14237 +   >>number    C = C>>number
14238 +   @number     A = A+C; then do the instruction number
14239 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
14240 +  Otherwise the result of the computation is the final value of C.
14241 +
14242 + Whitespace is allowed but not required in the tests.
14243 + However the characters that do occur there are likely to require
14244 + shell quoting, so it's a good idea to enclose the arguments in quotes.
14245 +
14246 +Example:
14247 + match IP packets with total length >= 256
14248 + The IP header contains a total length field in bytes 2-3.
14249 + --u32 "0&0xFFFF=0x100:0xFFFF" 
14250 + read bytes 0-3
14251 + AND that with FFFF (giving bytes 2-3),
14252 + and test whether that's in the range [0x100:0xFFFF]
14253 +
14254 +Example: (more realistic, hence more complicated)
14255 + match icmp packets with icmp type 0
14256 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
14257 + --u32 "6&0xFF=1 && ...
14258 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
14259 + Next test that it's not a fragment.
14260 +  (If so it might be part of such a packet but we can't always tell.)
14261 +  n.b. This test is generally needed if you want to match anything
14262 +  beyond the IP header.
14263 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
14264 + packet (not a fragment).  Alternatively, you can allow first fragments
14265 + by only testing the last 5 bits of byte 6.
14266 + ... 4&0x3FFF=0 && ...
14267 + Last test: the first byte past the IP header (the type) is 0
14268 + This is where we have to use the @syntax.  The length of the IP header
14269 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
14270 + IP header itself.
14271 + ... 0>>22&0x3C@0>>24=0"
14272 + The first 0 means read bytes 0-3,
14273 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
14274 +   the first byte, so only 22 bits is four times that plus a few more bits.
14275 + &3C then eliminates the two extra bits on the right and the first four 
14276 + bits of the first byte.
14277 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
14278 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
14279 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
14280 + @ means to use this number as a new offset into the packet, and read
14281 + four bytes starting from there.  This is the first 4 bytes of the icmp
14282 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
14283 + the value 24 to the right to throw out all but the first byte and compare
14284 + the result with 0.
14285 +
14286 +Example: 
14287 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
14288 + First we test that the packet is a tcp packet (similar to icmp).
14289 + --u32 "6&0xFF=6 && ...
14290 + Next, test that it's not a fragment (same as above).
14291 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
14292 + 0>>22&3C as above computes the number of bytes in the IP header.
14293 + @ makes this the new offset into the packet, which is the start of the
14294 + tcp header.  The length of the tcp header (again in 32 bit words) is
14295 + the left half of byte 12 of the tcp header.  The 12>>26&3C
14296 + computes this length in bytes (similar to the IP header before).
14297 + @ makes this the new offset, which is the start of the tcp payload.
14298 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
14299 + result is any of 1, 2, 5 or 8
14300 +*/
14301 +
14302 +#include <linux/module.h>
14303 +#include <linux/skbuff.h>
14304 +
14305 +#include <linux/netfilter_ipv4/ipt_u32.h>
14306 +#include <linux/netfilter_ipv4/ip_tables.h>
14307 +
14308 +/* #include <asm-i386/timex.h> for timing */
14309 +
14310 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
14311 +MODULE_DESCRIPTION("IP tables u32 matching module");
14312 +MODULE_LICENSE("GPL");
14313 +
14314 +static int
14315 +match(const struct sk_buff *skb,
14316 +      const struct net_device *in,
14317 +      const struct net_device *out,
14318 +      const void *matchinfo,
14319 +      int offset,
14320 +      const void *hdr,
14321 +      u_int16_t datalen,
14322 +      int *hotdrop)
14323 +{
14324 +       const struct ipt_u32 *data = matchinfo;
14325 +       int testind, i;
14326 +       unsigned char* origbase = (char*)skb->nh.iph;
14327 +       unsigned char* base = origbase;
14328 +       unsigned char* head = skb->head;
14329 +       unsigned char* end = skb->end;
14330 +       int nnums, nvals;
14331 +       u_int32_t pos, val;
14332 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
14333 +          cycles1 = get_cycles(); */
14334 +
14335 +       for (testind=0; testind < data->ntests; testind++) {
14336 +               base = origbase; /* reset for each test */
14337 +               pos = data->tests[testind].location[0].number;
14338 +               if (base+pos+3 > end || base+pos < head) 
14339 +                       return 0;
14340 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
14341 +                       (base[pos+2]<<8) + base[pos+3];
14342 +               nnums = data->tests[testind].nnums;
14343 +               for (i=1; i < nnums; i++) {
14344 +                       u_int32_t number = data->tests[testind].location[i].number;
14345 +                       switch (data->tests[testind].location[i].nextop) {
14346 +                       case IPT_U32_AND: 
14347 +                               val = val & number; 
14348 +                               break;
14349 +                       case IPT_U32_LEFTSH: 
14350 +                               val = val << number;
14351 +                               break;
14352 +                       case IPT_U32_RIGHTSH: 
14353 +                               val = val >> number; 
14354 +                               break;
14355 +                       case IPT_U32_AT:
14356 +                               base = base + val;
14357 +                               pos = number;
14358 +                               if (base+pos+3 > end || base+pos < head) 
14359 +                                       return 0;
14360 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
14361 +                                       (base[pos+2]<<8) + base[pos+3];
14362 +                               break;
14363 +                       }
14364 +               }
14365 +               nvals = data->tests[testind].nvalues;
14366 +               for (i=0; i < nvals; i++) {
14367 +                       if ((data->tests[testind].value[i].min <= val) &&
14368 +                           (val <= data->tests[testind].value[i].max)) {
14369 +                               break;
14370 +                       }
14371 +               }
14372 +               if (i >= data->tests[testind].nvalues) {
14373 +                       /* cycles2 = get_cycles(); 
14374 +                          printk("failed %d in %d cycles\n", testind, 
14375 +                                 cycles2-cycles1); */
14376 +                       return 0;
14377 +               }
14378 +       }
14379 +       /* cycles2 = get_cycles();
14380 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
14381 +       return 1;
14382 +}
14383 +
14384 +static int
14385 +checkentry(const char *tablename,
14386 +           const struct ipt_ip *ip,
14387 +           void *matchinfo,
14388 +           unsigned int matchsize,
14389 +           unsigned int hook_mask)
14390 +{
14391 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
14392 +               return 0;
14393 +       return 1;
14394 +}
14395 +
14396 +static struct ipt_match u32_match
14397 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
14398 +
14399 +static int __init init(void)
14400 +{
14401 +       return ipt_register_match(&u32_match);
14402 +}
14403 +
14404 +static void __exit fini(void)
14405 +{
14406 +       ipt_unregister_match(&u32_match);
14407 +}
14408 +
14409 +module_init(init);
14410 +module_exit(fini);
14411 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c
14412 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/ipt_unclean.c        1970-01-01 01:00:00.000000000 +0100
14413 +++ linux-2.6.6-rc3/net/ipv4/netfilter/ipt_unclean.c    2004-04-30 09:14:28.000000000 +0200
14414 @@ -0,0 +1,604 @@
14415 +/* Kernel module to match suspect packets. */
14416 +#include <linux/module.h>
14417 +#include <linux/skbuff.h>
14418 +#include <linux/ip.h>
14419 +#include <linux/udp.h>
14420 +#include <linux/tcp.h>
14421 +#include <linux/icmp.h>
14422 +#include <net/checksum.h>
14423 +
14424 +#include <linux/netfilter_ipv4/ip_tables.h>
14425 +
14426 +#define limpk(format, args...)                                          \
14427 +do {                                                                    \
14428 +       if (net_ratelimit())                                             \
14429 +               printk("ipt_unclean: %s" format,                         \
14430 +                      embedded ? "(embedded packet) " : "" , ## args);  \
14431 +} while(0)
14432 +
14433 +enum icmp_error_status
14434 +{
14435 +       ICMP_MAY_BE_ERROR,
14436 +       ICMP_IS_ERROR,
14437 +       ICMP_NOT_ERROR
14438 +};
14439 +
14440 +struct icmp_info
14441 +{
14442 +       size_t min_len, max_len;
14443 +       enum icmp_error_status err;
14444 +       u_int8_t min_code, max_code;
14445 +};
14446 +
14447 +static int
14448 +check_ip(struct iphdr *iph, size_t length, int embedded);
14449 +
14450 +/* ICMP-specific checks. */
14451 +static int
14452 +check_icmp(const struct icmphdr *icmph,
14453 +          u_int16_t datalen,
14454 +          unsigned int offset,
14455 +          int more_frags,
14456 +          int embedded)
14457 +{
14458 +       static struct icmp_info info[]
14459 +               = { [ICMP_ECHOREPLY]
14460 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
14461 +                   [ICMP_DEST_UNREACH]
14462 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
14463 +                   [ICMP_SOURCE_QUENCH]
14464 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
14465 +                   [ICMP_REDIRECT]
14466 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
14467 +                   [ICMP_ECHO]
14468 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0  },
14469 +                   /* Router advertisement. */
14470 +                   [9]
14471 +                   = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
14472 +                   /* Router solicitation. */
14473 +                   [10]
14474 +                   = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
14475 +                   [ICMP_TIME_EXCEEDED]
14476 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1  },
14477 +                   [ICMP_PARAMETERPROB]
14478 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
14479 +                   [ICMP_TIMESTAMP]
14480 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
14481 +                   [ICMP_TIMESTAMPREPLY]
14482 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
14483 +                   [ICMP_INFO_REQUEST]
14484 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
14485 +                   [ICMP_INFO_REPLY]
14486 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
14487 +                   [ICMP_ADDRESS]
14488 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
14489 +                   [ICMP_ADDRESSREPLY]
14490 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
14491 +
14492 +       /* Can't do anything if it's a fragment. */
14493 +       if (offset)
14494 +               return 1;
14495 +
14496 +       /* Must cover type and code. */
14497 +       if (datalen < 2) {
14498 +               limpk("ICMP len=%u too short\n", datalen);
14499 +               return 0;
14500 +       }
14501 +
14502 +       /* If not embedded. */
14503 +       if (!embedded) {
14504 +               /* Bad checksum?  Don't print, just ignore. */
14505 +               if (!more_frags
14506 +                   && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
14507 +                       return 0;
14508 +
14509 +               /* CHECK: Truncated ICMP (even if first fragment). */
14510 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14511 +                   && info[icmph->type].min_len != 0
14512 +                   && datalen < info[icmph->type].min_len) {
14513 +                       limpk("ICMP type %u len %u too short\n",
14514 +                             icmph->type, datalen);
14515 +                       return 0;
14516 +               }
14517 +
14518 +               /* CHECK: Check within known error ICMPs. */
14519 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14520 +                   && info[icmph->type].err == ICMP_IS_ERROR) {
14521 +                       /* CHECK: Embedded packet must be at least
14522 +                          length of iph + 8 bytes. */
14523 +                       struct iphdr *inner = (void *)icmph + 8;
14524 +
14525 +                       /* datalen > 8 since all ICMP_IS_ERROR types
14526 +                           have min length > 8 */
14527 +                       if (datalen - 8 < sizeof(struct iphdr)) {
14528 +                               limpk("ICMP error internal way too short\n");
14529 +                               return 0;
14530 +                       }
14531 +                       if (datalen - 8 < inner->ihl*4 + 8) {
14532 +                               limpk("ICMP error internal too short\n");
14533 +                               return 0;
14534 +                       }
14535 +                       if (!check_ip(inner, datalen - 8, 1))
14536 +                               return 0;
14537 +               }
14538 +       } else {
14539 +               /* CHECK: Can't embed ICMP unless known non-error. */
14540 +               if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
14541 +                   || info[icmph->type].err != ICMP_NOT_ERROR) {
14542 +                       limpk("ICMP type %u not embeddable\n",
14543 +                             icmph->type);
14544 +                       return 0;
14545 +               }
14546 +       }
14547 +
14548 +       /* CHECK: Invalid ICMP codes. */
14549 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14550 +           && (icmph->code < info[icmph->type].min_code
14551 +               || icmph->code > info[icmph->type].max_code)) {
14552 +               limpk("ICMP type=%u code=%u\n",
14553 +                     icmph->type, icmph->code);
14554 +               return 0;
14555 +       }
14556 +
14557 +       /* CHECK: Above maximum length. */
14558 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
14559 +           && info[icmph->type].max_len != 0
14560 +           && datalen > info[icmph->type].max_len) {
14561 +               limpk("ICMP type=%u too long: %u bytes\n",
14562 +                     icmph->type, datalen);
14563 +               return 0;
14564 +       }
14565 +
14566 +       switch (icmph->type) {
14567 +       case ICMP_PARAMETERPROB: {
14568 +               /* CHECK: Problem param must be within error packet's
14569 +                * IP header. */
14570 +               struct iphdr *iph = (void *)icmph + 8;
14571 +               u_int32_t arg = ntohl(icmph->un.gateway);
14572 +
14573 +               if (icmph->code == 0) {
14574 +                       /* Code 0 means that upper 8 bits is pointer
14575 +                           to problem. */
14576 +                       if ((arg >> 24) >= iph->ihl*4) {
14577 +                               limpk("ICMP PARAMETERPROB ptr = %u\n",
14578 +                                     ntohl(icmph->un.gateway) >> 24);
14579 +                               return 0;
14580 +                       }
14581 +                       arg &= 0x00FFFFFF;
14582 +               }
14583 +
14584 +               /* CHECK: Rest must be zero. */
14585 +               if (arg) {
14586 +                       limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
14587 +                             arg);
14588 +                       return 0;
14589 +               }
14590 +               break;
14591 +       }
14592 +
14593 +       case ICMP_TIME_EXCEEDED:
14594 +       case ICMP_SOURCE_QUENCH:
14595 +               /* CHECK: Unused must be zero. */
14596 +               if (icmph->un.gateway != 0) {
14597 +                       limpk("ICMP type=%u unused = %u\n",
14598 +                             icmph->type, ntohl(icmph->un.gateway));
14599 +                       return 0;
14600 +               }
14601 +               break;
14602 +       }
14603 +
14604 +       return 1;
14605 +}
14606 +
14607 +/* UDP-specific checks. */
14608 +static int
14609 +check_udp(const struct iphdr *iph,
14610 +         const struct udphdr *udph,
14611 +         u_int16_t datalen,
14612 +         unsigned int offset,
14613 +         int more_frags,
14614 +         int embedded)
14615 +{
14616 +       /* Can't do anything if it's a fragment. */
14617 +       if (offset)
14618 +               return 1;
14619 +
14620 +       /* CHECK: Must cover UDP header. */
14621 +       if (datalen < sizeof(struct udphdr)) {
14622 +               limpk("UDP len=%u too short\n", datalen);
14623 +               return 0;
14624 +       }
14625 +
14626 +       /* Bad checksum?  Don't print, just say it's unclean. */
14627 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
14628 +       if (!more_frags && !embedded && udph->check
14629 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
14630 +                                csum_partial((char *)udph, datalen, 0)) != 0)
14631 +               return 0;
14632 +
14633 +       /* CHECK: Destination port can't be zero. */
14634 +       if (!udph->dest) {
14635 +               limpk("UDP zero destination port\n");
14636 +               return 0;
14637 +       }
14638 +
14639 +       if (!more_frags) {
14640 +               if (!embedded) {
14641 +                       /* CHECK: UDP length must match. */
14642 +                       if (ntohs(udph->len) != datalen) {
14643 +                               limpk("UDP len too short %u vs %u\n",
14644 +                                     ntohs(udph->len), datalen);
14645 +                               return 0;
14646 +                       }
14647 +               } else {
14648 +                       /* CHECK: UDP length be >= this truncated pkt. */
14649 +                       if (ntohs(udph->len) < datalen) {
14650 +                               limpk("UDP len too long %u vs %u\n",
14651 +                                     ntohs(udph->len), datalen);
14652 +                               return 0;
14653 +                       }
14654 +               }
14655 +       } else {
14656 +               /* CHECK: UDP length must be > this frag's length. */
14657 +               if (ntohs(udph->len) <= datalen) {
14658 +                       limpk("UDP fragment len too short %u vs %u\n",
14659 +                             ntohs(udph->len), datalen);
14660 +                       return 0;
14661 +               }
14662 +       }
14663 +
14664 +       return 1;
14665 +}
14666 +
14667 +#define        TH_FIN  0x01
14668 +#define        TH_SYN  0x02
14669 +#define        TH_RST  0x04
14670 +#define        TH_PUSH 0x08
14671 +#define        TH_ACK  0x10
14672 +#define        TH_URG  0x20
14673 +#define        TH_ECE  0x40
14674 +#define        TH_CWR  0x80
14675 +
14676 +/* table of valid flag combinations - ECE and CWR are always valid */
14677 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
14678 +{
14679 +       [TH_SYN]                        = 1,
14680 +       [TH_SYN|TH_ACK]                 = 1,
14681 +       [TH_RST]                        = 1,
14682 +       [TH_RST|TH_ACK]                 = 1,
14683 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
14684 +       [TH_FIN|TH_ACK]                 = 1,
14685 +       [TH_ACK]                        = 1,
14686 +       [TH_ACK|TH_PUSH]                = 1,
14687 +       [TH_ACK|TH_URG]                 = 1,
14688 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
14689 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
14690 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
14691 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
14692 +};
14693 +
14694 +/* TCP-specific checks. */
14695 +static int
14696 +check_tcp(const struct iphdr *iph,
14697 +         const struct tcphdr *tcph,
14698 +         u_int16_t datalen,
14699 +         unsigned int offset,
14700 +         int more_frags,
14701 +         int embedded)
14702 +{
14703 +       u_int8_t *opt = (u_int8_t *)tcph;
14704 +       u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
14705 +       u_int8_t tcpflags;
14706 +       int end_of_options = 0;
14707 +       size_t i;
14708 +
14709 +       /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
14710 +       /* In fact, this is caught below (offset < 516). */
14711 +
14712 +       /* Can't do anything if it's a fragment. */
14713 +       if (offset)
14714 +               return 1;
14715 +
14716 +       /* CHECK: Smaller than minimal TCP hdr. */
14717 +       if (datalen < sizeof(struct tcphdr)) {
14718 +               if (!embedded) {
14719 +                       limpk("Packet length %u < TCP header.\n", datalen);
14720 +                       return 0;
14721 +               }
14722 +               /* Must have ports available (datalen >= 8), from
14723 +                   check_icmp which set embedded = 1 */
14724 +               /* CHECK: TCP ports inside ICMP error */
14725 +               if (!tcph->source || !tcph->dest) {
14726 +                       limpk("Zero TCP ports %u/%u.\n",
14727 +                             htons(tcph->source), htons(tcph->dest));
14728 +                       return 0;
14729 +               }
14730 +               return 1;
14731 +       }
14732 +
14733 +       /* CHECK: Smaller than actual TCP hdr. */
14734 +       if (datalen < tcph->doff * 4) {
14735 +               if (!embedded) {
14736 +                       limpk("Packet length %u < actual TCP header.\n",
14737 +                             datalen);
14738 +                       return 0;
14739 +               } else
14740 +                       return 1;
14741 +       }
14742 +
14743 +       /* Bad checksum?  Don't print, just say it's unclean. */
14744 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
14745 +       if (!more_frags && !embedded
14746 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
14747 +                                csum_partial((char *)tcph, datalen, 0)) != 0)
14748 +               return 0;
14749 +
14750 +       /* CHECK: TCP ports non-zero */
14751 +       if (!tcph->source || !tcph->dest) {
14752 +               limpk("Zero TCP ports %u/%u.\n",
14753 +                     htons(tcph->source), htons(tcph->dest));
14754 +               return 0;
14755 +       }
14756 +
14757 +       /* CHECK: TCP reserved bits zero. */
14758 +       if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
14759 +               limpk("TCP reserved bits not zero\n");
14760 +               return 0;
14761 +       }
14762 +
14763 +       /* CHECK: TCP flags. */
14764 +       tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
14765 +       if (!tcp_valid_flags[tcpflags]) {
14766 +               limpk("TCP flags bad: %u\n", tcpflags);
14767 +               return 0;
14768 +       }
14769 +
14770 +       for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
14771 +               switch (opt[i]) {
14772 +               case 0:
14773 +                       end_of_options = 1;
14774 +                       i++;
14775 +                       break;
14776 +               case 1:
14777 +                       i++;
14778 +                       break;
14779 +               default:
14780 +                       /* CHECK: options after EOO. */
14781 +                       if (end_of_options) {
14782 +                               limpk("TCP option %u after end\n",
14783 +                                     opt[i]);
14784 +                               return 0;
14785 +                       }
14786 +                       /* CHECK: options at tail. */
14787 +                       else if (i+1 >= tcph->doff * 4) {
14788 +                               limpk("TCP option %u at tail\n",
14789 +                                     opt[i]);
14790 +                               return 0;
14791 +                       }
14792 +                       /* CHECK: zero-length options. */
14793 +                       else if (opt[i+1] == 0) {
14794 +                               limpk("TCP option %u 0 len\n",
14795 +                                     opt[i]);
14796 +                               return 0;
14797 +                       }
14798 +                       /* CHECK: oversize options. */
14799 +                       else if (&opt[i] + opt[i+1] > endhdr) {
14800 +                               limpk("TCP option %u at %Zu too long\n",
14801 +                                     (unsigned int) opt[i], i);
14802 +                               return 0;
14803 +                       }
14804 +                       /* Move to next option */
14805 +                       i += opt[i+1];
14806 +               }
14807 +       }
14808 +
14809 +       return 1;
14810 +}
14811 +
14812 +/* Returns 1 if ok */
14813 +/* Standard IP checks. */
14814 +static int
14815 +check_ip(struct iphdr *iph, size_t length, int embedded)
14816 +{
14817 +       u_int8_t *opt = (u_int8_t *)iph;
14818 +       u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
14819 +       int end_of_options = 0;
14820 +       void *protoh;
14821 +       size_t datalen;
14822 +       unsigned int i;
14823 +       unsigned int offset;
14824 +
14825 +       /* Should only happen for local outgoing raw-socket packets. */
14826 +       /* CHECK: length >= ip header. */
14827 +       if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
14828 +               limpk("Packet length %Zu < IP header.\n", length);
14829 +               return 0;
14830 +       }
14831 +
14832 +       offset = ntohs(iph->frag_off) & IP_OFFSET;
14833 +       protoh = (void *)iph + iph->ihl * 4;
14834 +       datalen = length - iph->ihl * 4;
14835 +
14836 +       /* CHECK: Embedded fragment. */
14837 +       if (embedded && offset) {
14838 +               limpk("Embedded fragment.\n");
14839 +               return 0;
14840 +       }
14841 +
14842 +       for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
14843 +               switch (opt[i]) {
14844 +               case 0:
14845 +                       end_of_options = 1;
14846 +                       i++;
14847 +                       break;
14848 +               case 1:
14849 +                       i++;
14850 +                       break;
14851 +               default:
14852 +                       /* CHECK: options after EOO. */
14853 +                       if (end_of_options) {
14854 +                               limpk("IP option %u after end\n",
14855 +                                     opt[i]);
14856 +                               return 0;
14857 +                       }
14858 +                       /* CHECK: options at tail. */
14859 +                       else if (i+1 >= iph->ihl * 4) {
14860 +                               limpk("IP option %u at tail\n",
14861 +                                     opt[i]);
14862 +                               return 0;
14863 +                       }
14864 +                       /* CHECK: zero-length or one-length options. */
14865 +                       else if (opt[i+1] < 2) {
14866 +                               limpk("IP option %u %u len\n",
14867 +                                     opt[i], opt[i+1]);
14868 +                               return 0;
14869 +                       }
14870 +                       /* CHECK: oversize options. */
14871 +                       else if (&opt[i] + opt[i+1] > endhdr) {
14872 +                               limpk("IP option %u at %u too long\n",
14873 +                                     opt[i], i);
14874 +                               return 0;
14875 +                       }
14876 +                       /* Move to next option */
14877 +                       i += opt[i+1];
14878 +               }
14879 +       }
14880 +
14881 +       /* Fragment checks. */
14882 +
14883 +       /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
14884 +       if ((ntohs(iph->frag_off) & IP_MF)
14885 +           && (ntohs(iph->tot_len) % 8) != 0) {
14886 +               limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
14887 +               return 0;
14888 +       }
14889 +
14890 +       /* CHECK: Oversize fragment a-la Ping of Death. */
14891 +       if (offset * 8 + datalen > 65535) {
14892 +               limpk("Oversize fragment to %u.\n", offset * 8);
14893 +               return 0;
14894 +       }
14895 +
14896 +       /* CHECK: DF set and offset or MF set. */
14897 +       if ((ntohs(iph->frag_off) & IP_DF)
14898 +           && (offset || (ntohs(iph->frag_off) & IP_MF))) {
14899 +               limpk("DF set and offset=%u, MF=%u.\n",
14900 +                     offset, ntohs(iph->frag_off) & IP_MF);
14901 +               return 0;
14902 +       }
14903 +
14904 +       /* CHECK: Zero-sized fragments. */
14905 +       if ((offset || (ntohs(iph->frag_off) & IP_MF))
14906 +           && datalen == 0) {
14907 +               limpk("Zero size fragment offset=%u\n", offset);
14908 +               return 0;
14909 +       }
14910 +
14911 +       /* Note: we can have even middle fragments smaller than this:
14912 +          consider a large packet passing through a 600MTU then
14913 +          576MTU link: this gives a fragment of 24 data bytes.  But
14914 +          everyone packs fragments largest first, hence a fragment
14915 +          can't START before 576 - MAX_IP_HEADER_LEN. */
14916 +
14917 +       /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
14918 +          down to 128 (576 taken from RFC 791: All hosts must be
14919 +          prepared to accept datagrams of up to 576 octets).  Use 128
14920 +          here. */
14921 +#define MIN_LIKELY_MTU 128
14922 +       /* CHECK: Min size of first frag = 128. */
14923 +       if ((ntohs(iph->frag_off) & IP_MF)
14924 +           && offset == 0
14925 +           && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
14926 +               limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
14927 +                     MIN_LIKELY_MTU);
14928 +               return 0;
14929 +       }
14930 +
14931 +       /* CHECK: Min offset of frag = 128 - IP hdr len. */
14932 +       if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
14933 +               limpk("Fragment starts at %u < %u\n", offset * 8,
14934 +                     MIN_LIKELY_MTU - iph->ihl * 4);
14935 +               return 0;
14936 +       }
14937 +
14938 +       /* CHECK: Protocol specification non-zero. */
14939 +       if (iph->protocol == 0) {
14940 +               limpk("Zero protocol\n");
14941 +               return 0;
14942 +       }
14943 +
14944 +       /* CHECK: Do not use what is unused.
14945 +        * First bit of fragmentation flags should be unused.
14946 +        * May be used by OS fingerprinting tools.
14947 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
14948 +        */
14949 +       if (ntohs(iph->frag_off)>>15) {
14950 +               limpk("IP unused bit set\n");
14951 +               return 0;
14952 +       }
14953 +
14954 +       /* Per-protocol checks. */
14955 +       switch (iph->protocol) {
14956 +       case IPPROTO_ICMP:
14957 +               return check_icmp(protoh, datalen, offset,
14958 +                                 (ntohs(iph->frag_off) & IP_MF),
14959 +                                 embedded);
14960 +
14961 +       case IPPROTO_UDP:
14962 +               return check_udp(iph, protoh, datalen, offset,
14963 +                                (ntohs(iph->frag_off) & IP_MF),
14964 +                                embedded);
14965 +
14966 +       case IPPROTO_TCP:
14967 +               return check_tcp(iph, protoh, datalen, offset,
14968 +                                (ntohs(iph->frag_off) & IP_MF),
14969 +                                embedded);
14970 +       default:
14971 +               /* Ignorance is bliss. */
14972 +               return 1;
14973 +       }
14974 +}
14975 +
14976 +static int
14977 +match(const struct sk_buff *skb,
14978 +      const struct net_device *in,
14979 +      const struct net_device *out,
14980 +      const void *matchinfo,
14981 +      int offset,
14982 +      const void *hdr,
14983 +      u_int16_t datalen,
14984 +      int *hotdrop)
14985 +{
14986 +       return !check_ip(skb->nh.iph, skb->len, 0);
14987 +}
14988 +
14989 +/* Called when user tries to insert an entry of this type. */
14990 +static int
14991 +checkentry(const char *tablename,
14992 +          const struct ipt_ip *ip,
14993 +          void *matchinfo,
14994 +          unsigned int matchsize,
14995 +          unsigned int hook_mask)
14996 +{
14997 +       if (matchsize != IPT_ALIGN(0))
14998 +               return 0;
14999 +
15000 +       return 1;
15001 +}
15002 +
15003 +static struct ipt_match unclean_match
15004 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
15005 +
15006 +static int __init init(void)
15007 +{
15008 +       return ipt_register_match(&unclean_match);
15009 +}
15010 +
15011 +static void __exit fini(void)
15012 +{
15013 +       ipt_unregister_match(&unclean_match);
15014 +}
15015 +
15016 +module_init(init);
15017 +module_exit(fini);
15018 +MODULE_LICENSE("GPL");
15019 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c
15020 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_filter.c     2004-04-28 03:35:43.000000000 +0200
15021 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_filter.c 2004-04-30 09:11:53.000000000 +0200
15022 @@ -59,7 +59,7 @@
15023                 0,
15024                 sizeof(struct ipt_entry),
15025                 sizeof(struct ipt_standard),
15026 -               0, { 0, 0 }, { } },
15027 +               0, NULL, 0, { 0, 0 }, { } },
15028               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15029                 -NF_ACCEPT - 1 } },
15030             /* FORWARD */
15031 @@ -67,7 +67,7 @@
15032                 0,
15033                 sizeof(struct ipt_entry),
15034                 sizeof(struct ipt_standard),
15035 -               0, { 0, 0 }, { } },
15036 +               0, NULL, 0, { 0, 0 }, { } },
15037               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15038                 -NF_ACCEPT - 1 } },
15039             /* LOCAL_OUT */
15040 @@ -75,7 +75,7 @@
15041                 0,
15042                 sizeof(struct ipt_entry),
15043                 sizeof(struct ipt_standard),
15044 -               0, { 0, 0 }, { } },
15045 +               0, NULL, 0, { 0, 0 }, { } },
15046               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15047                 -NF_ACCEPT - 1 } }
15048      },
15049 @@ -84,7 +84,7 @@
15050         0,
15051         sizeof(struct ipt_entry),
15052         sizeof(struct ipt_error),
15053 -       0, { 0, 0 }, { } },
15054 +       0, NULL, 0, { 0, 0 }, { } },
15055        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15056           { } },
15057         "ERROR"
15058 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c
15059 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_mangle.c     2004-04-28 03:36:34.000000000 +0200
15060 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_mangle.c 2004-04-30 09:11:53.000000000 +0200
15061 @@ -74,7 +74,7 @@
15062                 0,
15063                 sizeof(struct ipt_entry),
15064                 sizeof(struct ipt_standard),
15065 -               0, { 0, 0 }, { } },
15066 +               0, NULL, 0, { 0, 0 }, { } },
15067               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15068                 -NF_ACCEPT - 1 } },
15069             /* LOCAL_IN */
15070 @@ -82,7 +82,7 @@
15071                 0,
15072                 sizeof(struct ipt_entry),
15073                 sizeof(struct ipt_standard),
15074 -               0, { 0, 0 }, { } },
15075 +               0, NULL, 0, { 0, 0 }, { } },
15076               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15077                 -NF_ACCEPT - 1 } },
15078             /* FORWARD */
15079 @@ -90,7 +90,7 @@
15080                 0,
15081                 sizeof(struct ipt_entry),
15082                 sizeof(struct ipt_standard),
15083 -               0, { 0, 0 }, { } },
15084 +               0, NULL, 0, { 0, 0 }, { } },
15085               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15086                 -NF_ACCEPT - 1 } },
15087             /* LOCAL_OUT */
15088 @@ -98,7 +98,7 @@
15089                 0,
15090                 sizeof(struct ipt_entry),
15091                 sizeof(struct ipt_standard),
15092 -               0, { 0, 0 }, { } },
15093 +               0, NULL, 0, { 0, 0 }, { } },
15094               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15095                 -NF_ACCEPT - 1 } },
15096             /* POST_ROUTING */
15097 @@ -106,7 +106,7 @@
15098                 0,
15099                 sizeof(struct ipt_entry),
15100                 sizeof(struct ipt_standard),
15101 -               0, { 0, 0 }, { } },
15102 +               0, NULL, 0, { 0, 0 }, { } },
15103               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15104                 -NF_ACCEPT - 1 } },
15105      },
15106 @@ -115,7 +115,7 @@
15107         0,
15108         sizeof(struct ipt_entry),
15109         sizeof(struct ipt_error),
15110 -       0, { 0, 0 }, { } },
15111 +       0, NULL, 0, { 0, 0 }, { } },
15112        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15113           { } },
15114         "ERROR"
15115 diff -Nur linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c
15116 --- linux-2.6.6-rc3.org/net/ipv4/netfilter/iptable_raw.c        2004-04-28 03:36:36.000000000 +0200
15117 +++ linux-2.6.6-rc3/net/ipv4/netfilter/iptable_raw.c    2004-04-30 09:11:53.000000000 +0200
15118 @@ -46,7 +46,7 @@
15119                 0,
15120                 sizeof(struct ipt_entry),
15121                 sizeof(struct ipt_standard),
15122 -               0, { 0, 0 }, { } },
15123 +               0, NULL, 0, { 0, 0 }, { } },
15124               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15125                 -NF_ACCEPT - 1 } },
15126             /* LOCAL_OUT */
15127 @@ -54,7 +54,7 @@
15128                 0,
15129                 sizeof(struct ipt_entry),
15130                 sizeof(struct ipt_standard),
15131 -               0, { 0, 0 }, { } },
15132 +               0, NULL, 0, { 0, 0 }, { } },
15133               { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
15134                 -NF_ACCEPT - 1 } }
15135      },
15136 @@ -63,7 +63,7 @@
15137         0,
15138         sizeof(struct ipt_entry),
15139         sizeof(struct ipt_error),
15140 -       0, { 0, 0 }, { } },
15141 +       0, NULL, 0, { 0, 0 }, { } },
15142        { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
15143           { } },
15144         "ERROR"
15145 diff -Nur linux-2.6.6-rc3.org/net/ipv4/raw.c linux-2.6.6-rc3/net/ipv4/raw.c
15146 --- linux-2.6.6-rc3.org/net/ipv4/raw.c  2004-04-28 03:35:49.000000000 +0200
15147 +++ linux-2.6.6-rc3/net/ipv4/raw.c      2004-04-30 09:12:42.000000000 +0200
15148 @@ -249,6 +249,7 @@
15149                 kfree_skb(skb);
15150                 return NET_RX_DROP;
15151         }
15152 +       nf_reset(skb);
15153  
15154         skb_push(skb, skb->data - skb->nh.raw);
15155  
15156 @@ -307,7 +308,7 @@
15157         }
15158  
15159         err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
15160 -                     dst_output);
15161 +                     ip_dst_output);
15162         if (err > 0)
15163                 err = inet->recverr ? net_xmit_errno(err) : 0;
15164         if (err)
15165 diff -Nur linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c
15166 --- linux-2.6.6-rc3.org/net/ipv4/tcp_ipv4.c     2004-04-28 03:35:40.000000000 +0200
15167 +++ linux-2.6.6-rc3/net/ipv4/tcp_ipv4.c 2004-04-30 09:13:14.000000000 +0200
15168 @@ -1785,6 +1785,7 @@
15169  
15170         if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
15171                 goto discard_and_relse;
15172 +       nf_reset(skb);
15173  
15174         if (sk_filter(sk, skb, 0))
15175                 goto discard_and_relse;
15176 @@ -2670,6 +2671,7 @@
15177  EXPORT_SYMBOL(tcp_v4_connect);
15178  EXPORT_SYMBOL(tcp_v4_do_rcv);
15179  EXPORT_SYMBOL(tcp_v4_lookup_listener);
15180 +EXPORT_SYMBOL(tcp_v4_lookup);
15181  EXPORT_SYMBOL(tcp_v4_rebuild_header);
15182  EXPORT_SYMBOL(tcp_v4_remember_stamp);
15183  EXPORT_SYMBOL(tcp_v4_send_check);
15184 diff -Nur linux-2.6.6-rc3.org/net/ipv4/udp.c linux-2.6.6-rc3/net/ipv4/udp.c
15185 --- linux-2.6.6-rc3.org/net/ipv4/udp.c  2004-04-28 03:35:19.000000000 +0200
15186 +++ linux-2.6.6-rc3/net/ipv4/udp.c      2004-04-30 09:13:14.000000000 +0200
15187 @@ -1045,6 +1045,7 @@
15188                 kfree_skb(skb);
15189                 return -1;
15190         }
15191 +       nf_reset(skb);
15192  
15193         if (up->encap_type) {
15194                 /*
15195 @@ -1210,6 +1211,7 @@
15196  
15197         if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
15198                 goto drop;
15199 +       nf_reset(skb);
15200  
15201         /* No socket. Drop packet silently, if checksum is wrong */
15202         if (udp_checksum_complete(skb))
15203 @@ -1558,6 +1560,7 @@
15204  EXPORT_SYMBOL(udp_port_rover);
15205  EXPORT_SYMBOL(udp_prot);
15206  EXPORT_SYMBOL(udp_sendmsg);
15207 +EXPORT_SYMBOL(udp_v4_lookup);
15208  
15209  #ifdef CONFIG_PROC_FS
15210  EXPORT_SYMBOL(udp_proc_register);
15211 diff -Nur linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c
15212 --- linux-2.6.6-rc3.org/net/ipv4/xfrm4_tunnel.c 2004-04-28 03:35:08.000000000 +0200
15213 +++ linux-2.6.6-rc3/net/ipv4/xfrm4_tunnel.c     2004-04-30 09:12:40.000000000 +0200
15214 @@ -76,6 +76,7 @@
15215                 err = -EHOSTUNREACH;
15216                 goto error_nolock;
15217         }
15218 +       IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
15219         return NET_XMIT_BYPASS;
15220  
15221  error_nolock:
15222 @@ -170,6 +171,7 @@
15223         .handler        =       ipip_rcv,
15224         .err_handler    =       ipip_err,
15225         .no_policy      =       1,
15226 +       .xfrm_prot      =       1,
15227  };
15228  
15229  static int __init ipip_init(void)
15230 diff -Nur linux-2.6.6-rc3.org/net/ipv6/ip6_tunnel.c linux-2.6.6-rc3/net/ipv6/ip6_tunnel.c
15231 --- linux-2.6.6-rc3.org/net/ipv6/ip6_tunnel.c   2004-04-28 03:35:06.000000000 +0200
15232 +++ linux-2.6.6-rc3/net/ipv6/ip6_tunnel.c       2004-04-30 09:09:38.000000000 +0200
15233 @@ -715,13 +715,7 @@
15234         ipv6h->nexthdr = proto;
15235         ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
15236         ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
15237 -#ifdef CONFIG_NETFILTER
15238 -       nf_conntrack_put(skb->nfct);
15239 -       skb->nfct = NULL;
15240 -#ifdef CONFIG_NETFILTER_DEBUG
15241 -       skb->nf_debug = 0;
15242 -#endif
15243 -#endif
15244 +       nf_reset(skb);
15245         pkt_len = skb->len;
15246         err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, 
15247                       skb->dst->dev, dst_output);
15248 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig
15249 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Kconfig      2004-04-28 03:36:33.000000000 +0200
15250 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Kconfig  2004-04-30 09:15:25.000000000 +0200
15251 @@ -230,5 +230,53 @@
15252           <file:Documentation/modules.txt>.  If unsure, say `N'.
15253           help
15254  
15255 +config IP6_NF_TARGET_HL
15256 +       tristate  'HL target support'
15257 +       depends on IP6_NF_MANGLE
15258 +         help
15259 +
15260 +config IP6_NF_TARGET_REJECT
15261 +       tristate  'REJECT target support'
15262 +       depends on IP6_NF_FILTER
15263 +         help
15264 +
15265 +config IP6_NF_MATCH_FUZZY
15266 +       tristate  'Fuzzy match support'
15267 +       depends on IP6_NF_FILTER
15268 +         help
15269 +
15270 +config IP6_NF_MATCH_NTH
15271 +       tristate  'Nth match support'
15272 +       depends on IP6_NF_IPTABLES
15273 +         help
15274 +
15275 +config IP6_NF_MATCH_RANDOM
15276 +       tristate  'Random match support'
15277 +       depends on IP6_NF_IPTABLES
15278 +         help
15279 +
15280 +config IP6_NF_TARGET_TRACE
15281 +       tristate  'TRACE target support'
15282 +       depends on IP6_NF_RAW
15283 +       help
15284 +         The TRACE target allows packets to be traced as those
15285 +         matches any subsequent rule in any table/rule. The matched
15286 +         rule and the packet is logged with the prefix
15287 +       
15288 +         TRACE: tablename/chainname/rulenum  
15289 +       
15290 +         If you want to compile it as a module, say M here and read
15291 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
15292 +         help
15293 +
15294 +config IP6_NF_MATCH_POLICY
15295 +       tristate "IPsec policy match support"
15296 +       depends on IP6_NF_IPTABLES && XFRM
15297 +       help
15298 +         Policy matching allows you to match packets based on the
15299 +         IPsec policy that was used during decapsulation/will
15300 +         be used during encapsulation.
15301 +
15302 +         To compile it as a module, choose M here.  If unsure, say N.
15303  endmenu
15304  
15305 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.6-rc3/net/ipv6/netfilter/Makefile
15306 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/Makefile     2004-04-28 03:36:01.000000000 +0200
15307 +++ linux-2.6.6-rc3/net/ipv6/netfilter/Makefile 2004-04-30 09:13:22.000000000 +0200
15308 @@ -8,6 +8,7 @@
15309  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
15310  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
15311  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
15312 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
15313  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
15314  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
15315  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
15316 @@ -19,7 +20,15 @@
15317  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
15318  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
15319  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
15320 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
15321  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
15322  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
15323 +
15324 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
15325 +
15326 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
15327 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
15328  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
15329 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
15330  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
15331 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
15332 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c
15333 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6_tables.c 2004-04-28 03:36:34.000000000 +0200
15334 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6_tables.c     2004-04-30 09:11:53.000000000 +0200
15335 @@ -38,6 +38,14 @@
15336  #define IPV6_HDR_LEN   (sizeof(struct ipv6hdr))
15337  #define IPV6_OPTHDR_LEN        (sizeof(struct ipv6_opt_hdr))
15338  
15339 +static const char *hook6names[] = { 
15340 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
15341 +       [NF_IP6_LOCAL_IN] "INPUT",
15342 +       [NF_IP6_FORWARD] "FORWARD",
15343 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
15344 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
15345 +};
15346 +
15347  /*#define DEBUG_IP_FIREWALL*/
15348  /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
15349  /*#define DEBUG_IP_FIREWALL_USER*/
15350 @@ -408,6 +416,12 @@
15351  
15352                         t = ip6t_get_target(e);
15353                         IP_NF_ASSERT(t->u.kernel.target);
15354 +
15355 +                       /* The packet traced and the rule isn't an unconditional return/END. */
15356 +                       if (((*pskb)->nfcache & NFC_TRACE) && e->rulenum) {
15357 +                               nf_log_packet(PF_INET6, hook, *pskb, in, out, "TRACE: %s/%s/%u ",
15358 +                                             table->name, e->chainname, e->rulenum);
15359 +                       }
15360                         /* Standard target? */
15361                         if (!t->u.kernel.target->target) {
15362                                 int v;
15363 @@ -561,6 +575,29 @@
15364         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
15365  }
15366  
15367 +static inline int
15368 +find_error_target(struct ip6t_entry *s, 
15369 +                 struct ip6t_entry *e,
15370 +                 char **chainname)
15371 +{
15372 +       struct ip6t_entry_target *t;
15373 +       static struct ip6t_entry *found = NULL;
15374 +
15375 +       if (s == e) {
15376 +               if (!found)
15377 +                       return 0;
15378 +               t = ip6t_get_target(found);
15379 +               if (strcmp(t->u.user.name, 
15380 +                          IP6T_ERROR_TARGET) == 0) {
15381 +                       *chainname = t->data;
15382 +                       return 1;
15383 +               }
15384 +       } else
15385 +               found = s;
15386 +       
15387 +       return 0;
15388 +}
15389 +
15390  /* All zeroes == unconditional rule. */
15391  static inline int
15392  unconditional(const struct ip6t_ip6 *ipv6)
15393 @@ -580,6 +617,8 @@
15394  mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
15395  {
15396         unsigned int hook;
15397 +       char *chainname = NULL;
15398 +       u_int32_t rulenum;
15399  
15400         /* No recursion; use packet counter to save back ptrs (reset
15401            to 0 as we leave), and comefrom to save source hook bitmask */
15402 @@ -593,6 +632,8 @@
15403  
15404                 /* Set initial back pointer. */
15405                 e->counters.pcnt = pos;
15406 +               rulenum = 1;
15407 +               chainname = (char *) hook6names[hook];
15408  
15409                 for (;;) {
15410                         struct ip6t_standard_target *t
15411 @@ -605,6 +646,8 @@
15412                         }
15413                         e->comefrom
15414                                 |= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
15415 +                       e->rulenum = rulenum++;
15416 +                       e->chainname = chainname;
15417  
15418                         /* Unconditional return/END. */
15419                         if (e->target_offset == sizeof(struct ip6t_entry)
15420 @@ -614,6 +657,10 @@
15421                             && unconditional(&e->ipv6)) {
15422                                 unsigned int oldpos, size;
15423  
15424 +                               /* Set unconditional rulenum to zero. */
15425 +                               e->rulenum = 0;
15426 +                               e->counters.bcnt = 0;
15427 +
15428                                 /* Return: backtrack through the last
15429                                    big jump. */
15430                                 do {
15431 @@ -639,6 +686,11 @@
15432                                                 (newinfo->entries + pos);
15433                                 } while (oldpos == pos + e->next_offset);
15434  
15435 +                               /* Restore chainname, rulenum. */
15436 +                               chainname = e->chainname;
15437 +                               rulenum = e->counters.bcnt;
15438 +                               e->counters.bcnt = 0;
15439 +
15440                                 /* Move along one */
15441                                 size = e->next_offset;
15442                                 e = (struct ip6t_entry *)
15443 @@ -654,6 +706,17 @@
15444                                         /* This a jump; chase it. */
15445                                         duprintf("Jump rule %u -> %u\n",
15446                                                  pos, newpos);
15447 +                                       e->counters.bcnt = rulenum++;
15448 +                                       rulenum = 1;
15449 +                                       e = (struct ip6t_entry *)
15450 +                                               (newinfo->entries + newpos);
15451 +                                       if (IP6T_ENTRY_ITERATE(newinfo->entries,
15452 +                                                              newinfo->size,
15453 +                                                              find_error_target,
15454 +                                                              e, &chainname) == 0) {
15455 +                                               printk("ip6_tables: table screwed up!\n");
15456 +                                               return 0;
15457 +                                       }
15458                                 } else {
15459                                         /* ... this is a fallthru */
15460                                         newpos = pos + e->next_offset;
15461 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_HL.c
15462 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_HL.c    1970-01-01 01:00:00.000000000 +0100
15463 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_HL.c        2004-04-30 09:10:04.000000000 +0200
15464 @@ -0,0 +1,105 @@
15465 +/* 
15466 + * Hop Limit modification target for ip6tables
15467 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
15468 + * Based on HW's TTL module
15469 + *
15470 + * This software is distributed under the terms of GNU GPL
15471 + */
15472 +
15473 +#include <linux/module.h>
15474 +#include <linux/skbuff.h>
15475 +#include <linux/ip.h>
15476 +
15477 +#include <linux/netfilter_ipv6/ip6_tables.h>
15478 +#include <linux/netfilter_ipv6/ip6t_HL.h>
15479 +
15480 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
15481 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
15482 +MODULE_LICENSE("GPL");
15483 +
15484 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
15485 +               const struct net_device *in, const struct net_device *out,
15486 +               const void *targinfo, void *userinfo)
15487 +{
15488 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
15489 +       const struct ip6t_HL_info *info = targinfo;
15490 +       u_int16_t diffs[2];
15491 +       int new_hl;
15492 +                        
15493 +       switch (info->mode) {
15494 +               case IP6T_HL_SET:
15495 +                       new_hl = info->hop_limit;
15496 +                       break;
15497 +               case IP6T_HL_INC:
15498 +                       new_hl = ip6h->hop_limit + info->hop_limit;
15499 +                       if (new_hl > 255)
15500 +                               new_hl = 255;
15501 +                       break;
15502 +               case IP6T_HL_DEC:
15503 +                       new_hl = ip6h->hop_limit + info->hop_limit;
15504 +                       if (new_hl < 0)
15505 +                               new_hl = 0;
15506 +                       break;
15507 +               default:
15508 +                       new_hl = ip6h->hop_limit;
15509 +                       break;
15510 +       }
15511 +
15512 +       if (new_hl != ip6h->hop_limit) {
15513 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
15514 +               ip6h->hop_limit = new_hl;
15515 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
15516 +       }
15517 +
15518 +       return IP6T_CONTINUE;
15519 +}
15520 +
15521 +static int ip6t_hl_checkentry(const char *tablename,
15522 +               const struct ip6t_entry *e,
15523 +               void *targinfo,
15524 +               unsigned int targinfosize,
15525 +               unsigned int hook_mask)
15526 +{
15527 +       struct ip6t_HL_info *info = targinfo;
15528 +
15529 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
15530 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
15531 +                               targinfosize,
15532 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
15533 +               return 0;       
15534 +       }       
15535 +
15536 +       if (strcmp(tablename, "mangle")) {
15537 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
15538 +               return 0;
15539 +       }
15540 +
15541 +       if (info->mode > IP6T_HL_MAXMODE) {
15542 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
15543 +                       info->mode);
15544 +               return 0;
15545 +       }
15546 +
15547 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
15548 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
15549 +               return 0;
15550 +       }
15551 +       
15552 +       return 1;
15553 +}
15554 +
15555 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
15556 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
15557 +
15558 +static int __init init(void)
15559 +{
15560 +       return ip6t_register_target(&ip6t_HL);
15561 +}
15562 +
15563 +static void __exit fini(void)
15564 +{
15565 +       ip6t_unregister_target(&ip6t_HL);
15566 +}
15567 +
15568 +module_init(init);
15569 +module_exit(fini);
15570 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_REJECT.c
15571 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c        1970-01-01 01:00:00.000000000 +0100
15572 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_REJECT.c    2004-04-30 09:10:13.000000000 +0200
15573 @@ -0,0 +1,458 @@
15574 +/*
15575 + * IP6 tables REJECT target module
15576 + * Linux INET6 implementation
15577 + *
15578 + * Copyright (C)2003 USAGI/WIDE Project
15579 + *
15580 + * Authors:
15581 + *     Yasuyuki Kozakai        <yasuyuki.kozakai@toshiba.co.jp>
15582 + *
15583 + * Based on net/ipv4/netfilter/ipt_REJECT.c
15584 + *
15585 + * This program is free software; you can redistribute it and/or
15586 + * modify it under the terms of the GNU General Public License
15587 + * as published by the Free Software Foundation; either version
15588 + * 2 of the License, or (at your option) any later version.
15589 + */
15590 +
15591 +#include <linux/config.h>
15592 +#include <linux/module.h>
15593 +#include <linux/skbuff.h>
15594 +#include <linux/icmpv6.h>
15595 +#include <net/ipv6.h>
15596 +#include <net/tcp.h>
15597 +#include <net/icmp.h>
15598 +#include <net/ip6_fib.h>
15599 +#include <net/ip6_route.h>
15600 +#include <net/flow.h>
15601 +#include <linux/netfilter_ipv6/ip6_tables.h>
15602 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
15603 +
15604 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
15605 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
15606 +MODULE_LICENSE("GPL");
15607 +
15608 +#if 0
15609 +#define DEBUGP printk
15610 +#else
15611 +#define DEBUGP(format, args...)
15612 +#endif
15613 +
15614 +#if 0
15615 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
15616 +{
15617 +       void (*attach)(struct sk_buff *, struct nf_ct_info *);
15618 +       if (nfct && (attach = ip6_ct_attach) != NULL) {
15619 +               mb();
15620 +               attach(new_skb, nfct);
15621 +       }
15622 +}
15623 +#endif
15624 +
15625 +static int maybe_reroute(struct sk_buff *skb)
15626 +{
15627 +       if (skb->nfcache & NFC_ALTERED){
15628 +               if (ip6_route_me_harder(skb) != 0){
15629 +                       kfree_skb(skb);
15630 +                       return -EINVAL;
15631 +               }
15632 +       }
15633 +
15634 +       return dst_output(skb);
15635 +}
15636 +
15637 +/* Send RST reply */
15638 +static void send_reset(struct sk_buff *oldskb)
15639 +{
15640 +       struct sk_buff *nskb;
15641 +       struct tcphdr otcph, *tcph;
15642 +       unsigned int otcplen, tcphoff, hh_len;
15643 +       int needs_ack;
15644 +       struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
15645 +       struct dst_entry *dst = NULL;
15646 +       u8 proto;
15647 +       struct flowi fl;
15648 +       proto = oip6h->nexthdr;
15649 +       int err;
15650 +
15651 +       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
15652 +           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
15653 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
15654 +               return;
15655 +       }
15656 +
15657 +       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
15658 +                                  &proto, oldskb->len - ((u8*)(oip6h+1)
15659 +                                                         - oldskb->data));
15660 +
15661 +       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
15662 +               DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
15663 +               return;
15664 +       }
15665 +
15666 +       otcplen = oldskb->len - tcphoff;
15667 +
15668 +       /* IP header checks: fragment, too short. */
15669 +       if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
15670 +               DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
15671 +                       proto, otcplen);
15672 +               return;
15673 +       }
15674 +
15675 +       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
15676 +               if (net_ratelimit())
15677 +                       printk("ip6t_REJECT: Can't copy tcp header\n");
15678 +               return;
15679 +       }
15680 +
15681 +       /* No RST for RST. */
15682 +       if (otcph.rst) {
15683 +               DEBUGP("ip6t_REJECT: RST is set\n");
15684 +               return;
15685 +       }
15686 +
15687 +       /* Check checksum. */
15688 +       if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
15689 +                           skb_checksum(oldskb, tcphoff, otcplen, 0))) {
15690 +               DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
15691 +               return;
15692 +       }
15693 +
15694 +       memset(&fl, 0, sizeof(fl));
15695 +       fl.proto = IPPROTO_TCP;
15696 +       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
15697 +       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
15698 +       fl.fl_ip_sport = otcph.dest;
15699 +       fl.fl_ip_dport = otcph.source;
15700 +       err = ip6_dst_lookup(NULL, &dst, &fl);
15701 +       if (err) {
15702 +               if (net_ratelimit())
15703 +                       printk("ip6t_REJECT: can't find dst. err = %d\n", err);
15704 +               return;
15705 +       }
15706 +
15707 +       hh_len = (dst->dev->hard_header_len + 15)&~15;
15708 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
15709 +                        + sizeof(struct tcphdr) + dst->trailer_len,
15710 +                        GFP_ATOMIC);
15711 +
15712 +       if (!nskb) {
15713 +               if (net_ratelimit())
15714 +                       printk("ip6t_REJECT: Can't alloc skb\n");
15715 +               dst_release(dst);
15716 +               return;
15717 +       }
15718 +
15719 +       nskb->dst = dst;
15720 +       dst_hold(dst);
15721 +
15722 +       skb_reserve(nskb, hh_len + dst->header_len);
15723 +
15724 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
15725 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
15726 +       ip6h->version = 6;
15727 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
15728 +       ip6h->nexthdr = IPPROTO_TCP;
15729 +       ip6h->payload_len = htons(sizeof(struct tcphdr));
15730 +       ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
15731 +       ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
15732 +
15733 +       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
15734 +       /* Truncate to length (no data) */
15735 +       tcph->doff = sizeof(struct tcphdr)/4;
15736 +       tcph->source = otcph.dest;
15737 +       tcph->dest = otcph.source;
15738 +
15739 +       if (otcph.ack) {
15740 +               needs_ack = 0;
15741 +               tcph->seq = otcph.ack_seq;
15742 +               tcph->ack_seq = 0;
15743 +       } else {
15744 +               needs_ack = 1;
15745 +               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
15746 +                                     + otcplen - (otcph.doff<<2));
15747 +               tcph->seq = 0;
15748 +       }
15749 +
15750 +       /* Reset flags */
15751 +       ((u_int8_t *)tcph)[13] = 0;
15752 +       tcph->rst = 1;
15753 +       tcph->ack = needs_ack;
15754 +       tcph->window = 0;
15755 +       tcph->urg_ptr = 0;
15756 +       tcph->check = 0;
15757 +
15758 +       /* Adjust TCP checksum */
15759 +       tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
15760 +                                     &nskb->nh.ipv6h->daddr,
15761 +                                     sizeof(struct tcphdr), IPPROTO_TCP,
15762 +                                     csum_partial((char *)tcph,
15763 +                                                  sizeof(struct tcphdr), 0));
15764 +
15765 +#if 0
15766 +       connection_attach(nskb, oldskb->nfct);
15767 +#endif
15768 +
15769 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
15770 +               maybe_reroute);
15771 +
15772 +       dst_release(dst);
15773 +}
15774 +
15775 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
15776 +{
15777 +       struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
15778 +       struct icmp6hdr *icmp6h;
15779 +       struct dst_entry *dst = NULL;
15780 +       struct rt6_info *rt;
15781 +       int tmo;
15782 +       __u32 csum;
15783 +       unsigned int len, datalen, hh_len;
15784 +       int saddr_type, daddr_type;
15785 +       unsigned int ptr, ip6off;
15786 +       u8 proto;
15787 +       struct flowi fl;
15788 +       struct sk_buff *nskb;
15789 +       char *data;
15790 +
15791 +       saddr_type = ipv6_addr_type(&hdr->saddr);
15792 +       daddr_type = ipv6_addr_type(&hdr->daddr);
15793 +
15794 +       if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
15795 +           (!(daddr_type & IPV6_ADDR_UNICAST))) {
15796 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
15797 +               return;
15798 +       }
15799 +
15800 +       ip6off = skb_in->nh.raw - skb_in->data;
15801 +       proto = hdr->nexthdr;
15802 +       ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
15803 +                              skb_in->len - ip6off);
15804 +
15805 +       if ((ptr < 0) || (ptr > skb_in->len)) {
15806 +               ptr = ip6off + sizeof(struct ipv6hdr);
15807 +               proto = hdr->nexthdr;
15808 +       } else if (proto == IPPROTO_ICMPV6) {
15809 +                u8 type;
15810 +
15811 +                if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
15812 +                                                     icmp6_type), &type, 1)) {
15813 +                       DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
15814 +                       return;
15815 +               }
15816 +
15817 +               if (!(type & ICMPV6_INFOMSG_MASK)) {
15818 +                       DEBUGP("ip6t_REJECT: no reply to icmp error\n");
15819 +                       return;
15820 +               }
15821 +        } else if (proto == IPPROTO_UDP) {
15822 +               int plen = skb_in->len - (ptr - ip6off);
15823 +               uint16_t check;
15824 +
15825 +               if (plen < sizeof(struct udphdr)) {
15826 +                       DEBUGP("ip6t_REJECT: too short\n");
15827 +                       return;
15828 +               }
15829 +
15830 +               if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
15831 +                                 &check, 2)) {
15832 +                       if (net_ratelimit())
15833 +                               printk("ip6t_REJECT: can't get copy from skb");
15834 +                       return;
15835 +               }
15836 +
15837 +               if (check &&
15838 +                   csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
15839 +                                   IPPROTO_UDP,
15840 +                                   skb_checksum(skb_in, ptr, plen, 0))) {
15841 +                       DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
15842 +                       return;
15843 +               }
15844 +       }
15845 +
15846 +       memset(&fl, 0, sizeof(fl));
15847 +       fl.proto = IPPROTO_ICMPV6;
15848 +       ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
15849 +       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
15850 +       fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
15851 +       fl.fl_icmp_code = code;
15852 +
15853 +       if (ip6_dst_lookup(NULL, &dst, &fl)) {
15854 +               return;
15855 +       }
15856 +
15857 +       rt = (struct rt6_info *)dst;
15858 +       tmo = 1*HZ;
15859 +
15860 +       if (rt->rt6i_dst.plen < 128)
15861 +               tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
15862 +
15863 +       if (!xrlim_allow(dst, tmo)) {
15864 +               if (net_ratelimit())
15865 +                       printk("ip6t_REJECT: rate limitted\n");
15866 +               goto dst_release_out;
15867 +       }
15868 +
15869 +       len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
15870 +
15871 +       if (len > dst_pmtu(dst))
15872 +               len = dst_pmtu(dst);
15873 +       if (len > IPV6_MIN_MTU)
15874 +               len = IPV6_MIN_MTU;
15875 +
15876 +       datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
15877 +       hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
15878 +
15879 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
15880 +                        GFP_ATOMIC);
15881 +
15882 +       if (!nskb) {
15883 +               if (net_ratelimit())
15884 +                       printk("ip6t_REJECT: can't alloc skb\n");
15885 +               goto dst_release_out;
15886 +       }
15887 +
15888 +       nskb->priority = 0;
15889 +       nskb->dst = dst;
15890 +       dst_hold(dst);
15891 +
15892 +       skb_reserve(nskb, hh_len + dst->header_len);
15893 +
15894 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
15895 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
15896 +       ip6h->version = 6;
15897 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
15898 +       ip6h->nexthdr = IPPROTO_ICMPV6;
15899 +       ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
15900 +       ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
15901 +       ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
15902 +
15903 +       icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
15904 +       icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
15905 +       icmp6h->icmp6_code = code;
15906 +       icmp6h->icmp6_cksum = 0;
15907 +
15908 +       data = skb_put(nskb, datalen);
15909 +
15910 +       csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
15911 +       csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
15912 +       icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
15913 +                                            datalen + sizeof(struct icmp6hdr),
15914 +                                            IPPROTO_ICMPV6, csum);
15915 +
15916 +#if 0
15917 +       connection_attach(nskb, skb_in->nfct);
15918 +#endif
15919 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
15920 +               maybe_reroute);
15921 +
15922 +dst_release_out:
15923 +       dst_release(dst);
15924 +}
15925 +
15926 +static unsigned int reject6_target(struct sk_buff **pskb,
15927 +                          unsigned int hooknum,
15928 +                          const struct net_device *in,
15929 +                          const struct net_device *out,
15930 +                          const void *targinfo,
15931 +                          void *userinfo)
15932 +{
15933 +       const struct ip6t_reject_info *reject = targinfo;
15934 +
15935 +       DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
15936 +       /* WARNING: This code causes reentry within ip6tables.
15937 +          This means that the ip6tables jump stack is now crap.  We
15938 +          must return an absolute verdict. --RR */
15939 +       switch (reject->with) {
15940 +       case IP6T_ICMP6_NO_ROUTE:
15941 +               send_unreach(*pskb, ICMPV6_NOROUTE);
15942 +               break;
15943 +       case IP6T_ICMP6_ADM_PROHIBITED:
15944 +               send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
15945 +               break;
15946 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
15947 +               send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
15948 +               break;
15949 +       case IP6T_ICMP6_ADDR_UNREACH:
15950 +               send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
15951 +               break;
15952 +       case IP6T_ICMP6_PORT_UNREACH:
15953 +               send_unreach(*pskb, ICMPV6_PORT_UNREACH);
15954 +               break;
15955 +       case IP6T_ICMP6_ECHOREPLY:
15956 +               /* Do nothing */
15957 +               break;
15958 +       case IP6T_TCP_RESET:
15959 +               send_reset(*pskb);
15960 +               break;
15961 +       default:
15962 +               if (net_ratelimit())
15963 +                       printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
15964 +               break;
15965 +       }
15966 +
15967 +       return NF_DROP;
15968 +}
15969 +
15970 +static int check(const char *tablename,
15971 +                const struct ip6t_entry *e,
15972 +                void *targinfo,
15973 +                unsigned int targinfosize,
15974 +                unsigned int hook_mask)
15975 +{
15976 +       const struct ip6t_reject_info *rejinfo = targinfo;
15977 +
15978 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
15979 +               DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
15980 +               return 0;
15981 +       }
15982 +
15983 +       /* Only allow these for packet filtering. */
15984 +       if (strcmp(tablename, "filter") != 0) {
15985 +               DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
15986 +               return 0;
15987 +       }
15988 +
15989 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
15990 +                          | (1 << NF_IP6_FORWARD)
15991 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
15992 +               DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
15993 +               return 0;
15994 +       }
15995 +
15996 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
15997 +               printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
15998 +               return 0;
15999 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
16000 +               /* Must specify that it's a TCP packet */
16001 +               if (e->ipv6.proto != IPPROTO_TCP
16002 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
16003 +                       DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
16004 +                       return 0;
16005 +               }
16006 +       }
16007 +
16008 +       return 1;
16009 +}
16010 +
16011 +static struct ip6t_target ip6t_reject_reg = {
16012 +       .name           = "REJECT",
16013 +       .target         = reject6_target,
16014 +       .checkentry     = check,
16015 +       .me             = THIS_MODULE
16016 +};
16017 +
16018 +static int __init init(void)
16019 +{
16020 +       if (ip6t_register_target(&ip6t_reject_reg))
16021 +               return -EINVAL;
16022 +       return 0;
16023 +}
16024 +
16025 +static void __exit fini(void)
16026 +{
16027 +       ip6t_unregister_target(&ip6t_reject_reg);
16028 +}
16029 +
16030 +module_init(init);
16031 +module_exit(fini);
16032 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c
16033 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_TRACE.c 1970-01-01 01:00:00.000000000 +0100
16034 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_TRACE.c     2004-04-30 09:11:53.000000000 +0200
16035 @@ -0,0 +1,65 @@
16036 +/* This is a module which is used for setting
16037 + * the NFC_TRACE flag in the nfcache field of an skb. 
16038 + */
16039 +#include <linux/module.h>
16040 +#include <linux/skbuff.h>
16041 +
16042 +#include <linux/netfilter_ipv6/ip6_tables.h>
16043 +
16044 +MODULE_LICENSE("GPL");
16045 +
16046 +static unsigned int
16047 +target(struct sk_buff **pskb,
16048 +       unsigned int hooknum,
16049 +       const struct net_device *in,
16050 +       const struct net_device *out,
16051 +       const void *targinfo,
16052 +       void *userinfo)
16053 +{
16054 +       (*pskb)->nfcache |= NFC_TRACE;
16055 +       return IP6T_CONTINUE;
16056 +}
16057 +
16058 +static int 
16059 +checkentry(const char *tablename,
16060 +                  const struct ip6t_entry *e,
16061 +           void *targinfo,
16062 +           unsigned int targinfosize,
16063 +           unsigned int hook_mask)
16064 +{
16065 +       if (targinfosize != 0) {
16066 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
16067 +                      targinfosize);
16068 +               return 0;
16069 +       }
16070 +
16071 +       if (strcmp(tablename, "raw") != 0) {
16072 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
16073 +               return 0;
16074 +       }
16075 +
16076 +       return 1;
16077 +}
16078 +
16079 +static struct ip6t_target ip6t_trace_reg = { 
16080 +       .name = "TRACE",
16081 +       .target = target, 
16082 +       .checkentry = checkentry, 
16083 +       .me = THIS_MODULE
16084 +};
16085 +
16086 +static int __init init(void)
16087 +{
16088 +       if (ip6t_register_target(&ip6t_trace_reg))
16089 +               return -EINVAL;
16090 +
16091 +       return 0;
16092 +}
16093 +
16094 +static void __exit fini(void)
16095 +{
16096 +       ip6t_unregister_target(&ip6t_trace_reg);
16097 +}
16098 +
16099 +module_init(init);
16100 +module_exit(fini);
16101 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_fuzzy.c
16102 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
16103 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_fuzzy.c     2004-04-30 09:10:22.000000000 +0200
16104 @@ -0,0 +1,189 @@
16105 +/*
16106 + * This module implements a simple TSK FLC
16107 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
16108 + * to limit , in an adaptive and flexible way , the packet rate crossing
16109 + * a given stream . It serves as an initial and very simple (but effective)
16110 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
16111 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
16112 + * into our code in a precise , adaptive and efficient manner.
16113 + *  The goal is very similar to that of "limit" match , but using techniques of
16114 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
16115 + * avoiding over and undershoots - and stuff like that .
16116 + *
16117 + *
16118 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
16119 + * 2002-08-17  : Changed to eliminate floating point operations .
16120 + * 2002-08-23  : Coding style changes .
16121 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
16122 + */
16123 +
16124 +#include <linux/module.h>
16125 +#include <linux/skbuff.h>
16126 +#include <linux/ipv6.h>
16127 +#include <linux/random.h>
16128 +#include <net/tcp.h>
16129 +#include <linux/spinlock.h>
16130 +#include <linux/netfilter_ipv6/ip6_tables.h>
16131 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
16132 +
16133 +/*
16134 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
16135 + Expressed in percentage
16136 +*/
16137 +
16138 +#define PAR_LOW                1/100
16139 +#define PAR_HIGH       1
16140 +
16141 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
16142 +
16143 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
16144 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
16145 +MODULE_LICENSE("GPL");
16146 +
16147 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
16148 +{
16149 +       if (tx >= maxi) return 100;
16150 +
16151 +       if (tx <= mini) return 0;
16152 +
16153 +       return ((100 * (tx-mini)) / (maxi-mini));
16154 +}
16155 +
16156 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
16157 +{
16158 +       if (tx <= mini) return 100;
16159 +
16160 +       if (tx >= maxi) return 0;
16161 +
16162 +       return ((100 * (maxi - tx)) / (maxi - mini));
16163 +
16164 +}
16165 +
16166 +static int
16167 +ip6t_fuzzy_match(const struct sk_buff *pskb,
16168 +              const struct net_device *in,
16169 +              const struct net_device *out,
16170 +              const void *matchinfo,
16171 +              int offset,
16172 +              const void *hdr,
16173 +              u_int16_t datalen,
16174 +              int *hotdrop)
16175 +{
16176 +       /* From userspace */
16177 +
16178 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
16179 +
16180 +       u_int8_t random_number;
16181 +       unsigned long amount;
16182 +       u_int8_t howhigh, howlow;
16183 +
16184 +
16185 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
16186 +
16187 +       info->bytes_total += pskb->len;
16188 +       info->packets_total++;
16189 +
16190 +       info->present_time = jiffies;
16191 +
16192 +       if (info->present_time >= info->previous_time)
16193 +               amount = info->present_time - info->previous_time;
16194 +       else {
16195 +               /* There was a transition : I choose to re-sample
16196 +                  and keep the old acceptance rate...
16197 +               */
16198 +
16199 +               amount = 0;
16200 +               info->previous_time = info->present_time;
16201 +               info->bytes_total = info->packets_total = 0;
16202 +            };
16203 +
16204 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
16205 +
16206 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
16207 +                                       / amount);
16208 +
16209 +               info->previous_time = info->present_time;
16210 +               info->bytes_total = info->packets_total = 0;
16211 +
16212 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
16213 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
16214 +
16215 +               info->acceptance_rate = (u_int8_t) \
16216 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
16217 +
16218 +       /* In fact, the above defuzzification would require a denominator
16219 +        * proportional to (howhigh+howlow) but, in this particular case,
16220 +        * that expression is constant.
16221 +        * An imediate consequence is that it is not necessary to call
16222 +        * both mf_high and mf_low - but to keep things understandable,
16223 +        * I did so.
16224 +        */
16225 +
16226 +       }
16227 +
16228 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
16229 +
16230 +
16231 +       if (info->acceptance_rate < 100)
16232 +       {
16233 +               get_random_bytes((void *)(&random_number), 1);
16234 +
16235 +               /*  If within the acceptance , it can pass => don't match */
16236 +               if (random_number <= (255 * info->acceptance_rate) / 100)
16237 +                       return 0;
16238 +               else
16239 +                       return 1; /* It can't pass (It matches) */
16240 +       };
16241 +
16242 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
16243 +
16244 +}
16245 +
16246 +static int
16247 +ip6t_fuzzy_checkentry(const char *tablename,
16248 +                  const struct ip6t_ip6 *ip,
16249 +                  void *matchinfo,
16250 +                  unsigned int matchsize,
16251 +                  unsigned int hook_mask)
16252 +{
16253 +
16254 +       const struct ip6t_fuzzy_info *info = matchinfo;
16255 +
16256 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
16257 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
16258 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
16259 +               return 0;
16260 +       }
16261 +
16262 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
16263 +        || (info->minimum_rate >= info->maximum_rate)) {
16264 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
16265 +               return 0;
16266 +       }
16267 +
16268 +       return 1;
16269 +}
16270 +
16271 +static struct ip6t_match ip6t_fuzzy_reg = {
16272 +       {NULL, NULL},
16273 +       "fuzzy",
16274 +       ip6t_fuzzy_match,
16275 +       ip6t_fuzzy_checkentry,
16276 +       NULL,
16277 +       THIS_MODULE };
16278 +
16279 +static int __init init(void)
16280 +{
16281 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
16282 +               return -EINVAL;
16283 +
16284 +       return 0;
16285 +}
16286 +
16287 +static void __exit fini(void)
16288 +{
16289 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
16290 +}
16291 +
16292 +module_init(init);
16293 +module_exit(fini);
16294 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_nth.c
16295 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_nth.c   1970-01-01 01:00:00.000000000 +0100
16296 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_nth.c       2004-04-30 09:10:36.000000000 +0200
16297 @@ -0,0 +1,173 @@
16298 +/*
16299 +  This is a module which is used for match support for every Nth packet
16300 +  This file is distributed under the terms of the GNU General Public
16301 +  License (GPL). Copies of the GPL can be obtained from:
16302 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
16303 +
16304 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
16305 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
16306 +        * added support for multiple counters
16307 +        * added support for matching on individual packets
16308 +          in the counter cycle
16309 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
16310 +
16311 +*/
16312 +
16313 +#include <linux/module.h>
16314 +#include <linux/skbuff.h>
16315 +#include <linux/ip.h>
16316 +#include <net/tcp.h>
16317 +#include <linux/spinlock.h>
16318 +#include <linux/netfilter_ipv6/ip6_tables.h>
16319 +#include <linux/netfilter_ipv6/ip6t_nth.h>
16320 +
16321 +MODULE_LICENSE("GPL");
16322 +
16323 +/*
16324 + * State information.
16325 + */
16326 +struct state {
16327 +       spinlock_t lock;
16328 +       u_int16_t number;
16329 +};
16330 +
16331 +static struct state states[IP6T_NTH_NUM_COUNTERS];
16332 +
16333 +static int
16334 +ip6t_nth_match(const struct sk_buff *pskb,
16335 +             const struct net_device *in,
16336 +             const struct net_device *out,
16337 +             const void *matchinfo,
16338 +             int offset,
16339 +             const void *hdr,
16340 +             u_int16_t datalen,
16341 +             int *hotdrop)
16342 +{
16343 +       /* Parameters from userspace */
16344 +       const struct ip6t_nth_info *info = matchinfo;
16345 +        unsigned counter = info->counter;
16346 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
16347 +       {
16348 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
16349 +               return 0;
16350 +        };
16351 +
16352 +        spin_lock(&states[counter].lock);
16353 +
16354 +        /* Are we matching every nth packet?*/
16355 +        if (info->packet == 0xFF)
16356 +        {
16357 +               /* We're matching every nth packet and only every nth packet*/
16358 +               /* Do we match or invert match? */
16359 +               if (info->not == 0)
16360 +               {
16361 +                       if (states[counter].number == 0)
16362 +                       {
16363 +                               ++states[counter].number;
16364 +                               goto match;
16365 +                       }
16366 +                       if (states[counter].number >= info->every)
16367 +                               states[counter].number = 0; /* reset the counter */
16368 +                       else
16369 +                               ++states[counter].number;
16370 +                       goto dontmatch;
16371 +               }
16372 +               else
16373 +               {
16374 +                       if (states[counter].number == 0)
16375 +                       {
16376 +                               ++states[counter].number;
16377 +                               goto dontmatch;
16378 +                       }
16379 +                       if (states[counter].number >= info->every)
16380 +                               states[counter].number = 0;
16381 +                       else
16382 +                               ++states[counter].number;
16383 +                       goto match;
16384 +               }
16385 +        }
16386 +        else
16387 +        {
16388 +               /* We're using the --packet, so there must be a rule for every value */
16389 +               if (states[counter].number == info->packet)
16390 +               {
16391 +                       /* only increment the counter when a match happens */
16392 +                       if (states[counter].number >= info->every)
16393 +                               states[counter].number = 0; /* reset the counter */
16394 +                       else
16395 +                               ++states[counter].number;
16396 +                       goto match;
16397 +               }
16398 +               else
16399 +                       goto dontmatch;
16400 +       }
16401 +
16402 + dontmatch:
16403 +       /* don't match */
16404 +       spin_unlock(&states[counter].lock);
16405 +       return 0;
16406 +
16407 + match:
16408 +       spin_unlock(&states[counter].lock);
16409 +       return 1;
16410 +}
16411 +
16412 +static int
16413 +ip6t_nth_checkentry(const char *tablename,
16414 +                  const struct ip6t_ip6 *e,
16415 +                  void *matchinfo,
16416 +                  unsigned int matchsize,
16417 +                  unsigned int hook_mask)
16418 +{
16419 +       /* Parameters from userspace */
16420 +       const struct ip6t_nth_info *info = matchinfo;
16421 +        unsigned counter = info->counter;
16422 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
16423 +       {
16424 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
16425 +                       return 0;
16426 +               };
16427 +
16428 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
16429 +               printk("nth: matchsize %u != %u\n", matchsize,
16430 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
16431 +               return 0;
16432 +       }
16433 +
16434 +       states[counter].number = info->startat;
16435 +
16436 +       return 1;
16437 +}
16438 +
16439 +static struct ip6t_match ip6t_nth_reg = { 
16440 +       {NULL, NULL},
16441 +       "nth",
16442 +       ip6t_nth_match,
16443 +       ip6t_nth_checkentry,
16444 +       NULL,
16445 +       THIS_MODULE };
16446 +
16447 +static int __init init(void)
16448 +{
16449 +       unsigned counter;
16450 +        memset(&states, 0, sizeof(states));
16451 +       if (ip6t_register_match(&ip6t_nth_reg))
16452 +               return -EINVAL;
16453 +
16454 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
16455 +       {
16456 +               spin_lock_init(&(states[counter].lock));
16457 +        };
16458 +
16459 +       printk("ip6t_nth match loaded\n");
16460 +       return 0;
16461 +}
16462 +
16463 +static void __exit fini(void)
16464 +{
16465 +       ip6t_unregister_match(&ip6t_nth_reg);
16466 +       printk("ip6t_nth match unloaded\n");
16467 +}
16468 +
16469 +module_init(init);
16470 +module_exit(fini);
16471 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c
16472 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_owner.c 2004-04-28 03:36:30.000000000 +0200
16473 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_owner.c     2004-04-30 09:13:19.000000000 +0200
16474 @@ -21,6 +21,39 @@
16475  MODULE_LICENSE("GPL");
16476  
16477  static int
16478 +match_comm(const struct sk_buff *skb, const char *comm)
16479 +{
16480 +       struct task_struct *p, *g;
16481 +       struct files_struct *files;
16482 +       int i;
16483 +
16484 +       read_lock(&tasklist_lock);
16485 +       do_each_thread(g, p) {
16486 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
16487 +                       continue;
16488 +
16489 +               task_lock(p);
16490 +               files = p->files;
16491 +               if(files) {
16492 +                       read_lock(&files->file_lock);
16493 +                       for (i=0; i < files->max_fds; i++) {
16494 +                               if (fcheck_files(files, i) ==
16495 +                                   skb->sk->sk_socket->file) {
16496 +                                       read_unlock(&files->file_lock);
16497 +                                       task_unlock(p);
16498 +                                       read_unlock(&tasklist_lock);
16499 +                                       return 1;
16500 +                               }
16501 +                       }
16502 +                       read_unlock(&files->file_lock);
16503 +               }
16504 +               task_unlock(p);
16505 +       } while_each_thread(g, p);
16506 +       read_unlock(&tasklist_lock);
16507 +       return 0;
16508 +}
16509 +
16510 +static int
16511  match_pid(const struct sk_buff *skb, pid_t pid)
16512  {
16513         struct task_struct *p;
16514 @@ -125,6 +158,12 @@
16515                         return 0;
16516         }
16517  
16518 +       if(info->match & IP6T_OWNER_COMM) {
16519 +               if (!match_comm(skb, info->comm) ^
16520 +                   !!(info->invert & IP6T_OWNER_COMM))
16521 +                       return 0;
16522 +       }
16523 +
16524         return 1;
16525  }
16526  
16527 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c
16528 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_policy.c        1970-01-01 01:00:00.000000000 +0100
16529 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_policy.c    2004-04-30 09:13:22.000000000 +0200
16530 @@ -0,0 +1,200 @@
16531 +/* IP tables module for matching IPsec policy\r
16532 + *\r
16533 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>\r
16534 + *\r
16535 + * This program is free software; you can redistribute it and/or modify\r
16536 + * it under the terms of the GNU General Public License version 2 as\r
16537 + * published by the Free Software Foundation.\r
16538 + */\r
16539 +\r
16540 +#include <linux/kernel.h>\r
16541 +#include <linux/config.h>\r
16542 +#include <linux/module.h>\r
16543 +#include <linux/skbuff.h>\r
16544 +#include <linux/init.h>\r
16545 +#include <net/xfrm.h>\r
16546 +\r
16547 +#include <linux/netfilter_ipv6.h>\r
16548 +#include <linux/netfilter_ipv6/ip6t_policy.h>\r
16549 +#include <linux/netfilter_ipv6/ip6_tables.h>\r
16550 +\r
16551 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");\r
16552 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");\r
16553 +MODULE_LICENSE("GPL");\r
16554 +\r
16555 +\r
16556 +static inline int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,\r
16557 +                                     struct in6_addr addr2)\r
16558 +{\r
16559 +       int i;\r
16560 +\r
16561 +       for (i = 0; i < 16; i++) {\r
16562 +               if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=\r
16563 +                   (addr2.s6_addr[i] & mask.s6_addr[i]))\r
16564 +                       return 1;\r
16565 +       }\r
16566 +       return 0;\r
16567 +}\r
16568 +\r
16569 +\r
16570 +static inline int\r
16571 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)\r
16572 +{\r
16573 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))\r
16574 +       \r
16575 +       struct in6_addr xfrm_saddr, xfrm_daddr;\r
16576 +       \r
16577 +       if ((e->match.saddr\r
16578 +            && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))\r
16579 +               ^ e->invert.saddr ) ||\r
16580 +           (e->match.daddr\r
16581 +            && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))\r
16582 +               ^ e->invert.daddr ) ||\r
16583 +           MISMATCH(proto, x->id.proto) ||\r
16584 +           MISMATCH(mode, x->props.mode) ||\r
16585 +           MISMATCH(spi, x->id.spi) ||\r
16586 +           MISMATCH(reqid, x->props.reqid))\r
16587 +               return 0;\r
16588 +       return 1;\r
16589 +}\r
16590 +\r
16591 +static int\r
16592 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
16593 +{\r
16594 +       const struct ip6t_policy_elem *e;\r
16595 +       struct sec_path *sp = skb->sp;\r
16596 +       int strict = info->flags & POLICY_MATCH_STRICT;\r
16597 +       int i, pos;\r
16598 +\r
16599 +       if (sp == NULL)\r
16600 +               return -1;\r
16601 +       if (strict && info->len != sp->len)\r
16602 +               return 0;\r
16603 +\r
16604 +       for (i = sp->len - 1; i >= 0; i--) {\r
16605 +               pos = strict ? i - sp->len + 1 : 0;\r
16606 +               if (pos >= info->len)\r
16607 +                       return 0;\r
16608 +               e = &info->pol[pos];\r
16609 +\r
16610 +               if (match_xfrm_state(sp->x[i].xvec, e)) {\r
16611 +                       if (!strict)\r
16612 +                               return 1;\r
16613 +               } else if (strict)\r
16614 +                       return 0;\r
16615 +       }\r
16616 +\r
16617 +       return strict ? 1 : 0;\r
16618 +}\r
16619 +\r
16620 +static int\r
16621 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)\r
16622 +{\r
16623 +       const struct ip6t_policy_elem *e;\r
16624 +       struct dst_entry *dst = skb->dst;\r
16625 +       int strict = info->flags & POLICY_MATCH_STRICT;\r
16626 +       int i, pos;\r
16627 +\r
16628 +       if (dst->xfrm == NULL)\r
16629 +               return -1;\r
16630 +\r
16631 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {\r
16632 +               pos = strict ? i : 0;\r
16633 +               if (pos >= info->len)\r
16634 +                       return 0;\r
16635 +               e = &info->pol[pos];\r
16636 +\r
16637 +               if (match_xfrm_state(dst->xfrm, e)) {\r
16638 +                       if (!strict)\r
16639 +                               return 1;\r
16640 +               } else if (strict)\r
16641 +                       return 0;\r
16642 +       }\r
16643 +\r
16644 +       return strict ? 1 : 0;\r
16645 +}\r
16646 +\r
16647 +static int match(const struct sk_buff *skb,\r
16648 +                 const struct net_device *in,\r
16649 +                 const struct net_device *out,\r
16650 +                 const void *matchinfo,\r
16651 +                int offset,\r
16652 +                const void *hdr,\r
16653 +                u_int16_t datalen,\r
16654 +                int *hotdrop)\r
16655 +{\r
16656 +       const struct ip6t_policy_info *info = matchinfo;\r
16657 +       int ret;\r
16658 +\r
16659 +       if (info->flags & POLICY_MATCH_IN)\r
16660 +               ret = match_policy_in(skb, info);\r
16661 +       else\r
16662 +               ret = match_policy_out(skb, info);\r
16663 +\r
16664 +       if (ret < 0) {\r
16665 +               if (info->flags & POLICY_MATCH_NONE)\r
16666 +                       ret = 1;\r
16667 +               else\r
16668 +                       ret = 0;\r
16669 +       } else if (info->flags & POLICY_MATCH_NONE)\r
16670 +               ret = 0;\r
16671 +\r
16672 +       return ret;\r
16673 +}\r
16674 +\r
16675 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,\r
16676 +                      void *matchinfo, unsigned int matchsize,\r
16677 +                      unsigned int hook_mask)\r
16678 +{\r
16679 +       struct ip6t_policy_info *info = matchinfo;\r
16680 +\r
16681 +       if (matchsize != IP6T_ALIGN(sizeof(*info))) {\r
16682 +               printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",\r
16683 +                      matchsize, IP6T_ALIGN(sizeof(*info)));\r
16684 +               return 0;\r
16685 +       }\r
16686 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {\r
16687 +               printk(KERN_ERR "ip6t_policy: neither incoming nor "\r
16688 +                               "outgoing policy selected\n");\r
16689 +               return 0;\r
16690 +       }\r
16691 +       if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)\r
16692 +           && info->flags & POLICY_MATCH_OUT) {\r
16693 +               printk(KERN_ERR "ip6t_policy: output policy not valid in "\r
16694 +                               "PRE_ROUTING and INPUT\n");\r
16695 +               return 0;\r
16696 +       }\r
16697 +       if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)\r
16698 +           && info->flags & POLICY_MATCH_IN) {\r
16699 +               printk(KERN_ERR "ip6t_policy: input policy not valid in "\r
16700 +                               "POST_ROUTING and OUTPUT\n");\r
16701 +               return 0;\r
16702 +       }\r
16703 +       if (info->len > POLICY_MAX_ELEM) {\r
16704 +               printk(KERN_ERR "ip6t_policy: too many policy elements\n");\r
16705 +               return 0;\r
16706 +       }\r
16707 +\r
16708 +       return 1;\r
16709 +}\r
16710 +\r
16711 +static struct ip6t_match policy_match =\r
16712 +{\r
16713 +       .name           = "policy",\r
16714 +       .match          = match,\r
16715 +       .checkentry     = checkentry,\r
16716 +       .me             = THIS_MODULE,\r
16717 +};\r
16718 +\r
16719 +static int __init init(void)\r
16720 +{\r
16721 +       return ip6t_register_match(&policy_match);\r
16722 +}\r
16723 +\r
16724 +static void __exit fini(void)\r
16725 +{\r
16726 +       ip6t_unregister_match(&policy_match);\r
16727 +}\r
16728 +\r
16729 +module_init(init);\r
16730 +module_exit(fini);\r
16731 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_random.c
16732 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6t_random.c        1970-01-01 01:00:00.000000000 +0100
16733 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6t_random.c    2004-04-30 09:10:46.000000000 +0200
16734 @@ -0,0 +1,97 @@
16735 +/*
16736 +  This is a module which is used for a "random" match support.
16737 +  This file is distributed under the terms of the GNU General Public
16738 +  License (GPL). Copies of the GPL can be obtained from:
16739 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
16740 +
16741 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
16742 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
16743 +*/
16744 +
16745 +#include <linux/module.h>
16746 +#include <linux/skbuff.h>
16747 +#include <linux/ip.h>
16748 +#include <linux/random.h>
16749 +#include <net/tcp.h>
16750 +#include <linux/spinlock.h>
16751 +#include <linux/netfilter_ipv6/ip6_tables.h>
16752 +#include <linux/netfilter_ipv6/ip6t_random.h>
16753 +
16754 +MODULE_LICENSE("GPL");
16755 +
16756 +static int
16757 +ip6t_rand_match(const struct sk_buff *pskb,
16758 +              const struct net_device *in,
16759 +              const struct net_device *out,
16760 +              const void *matchinfo,
16761 +              int offset,
16762 +              const void *hdr,
16763 +              u_int16_t datalen,
16764 +              int *hotdrop)
16765 +{
16766 +       /* Parameters from userspace */
16767 +       const struct ip6t_rand_info *info = matchinfo;
16768 +       u_int8_t random_number;
16769 +
16770 +       /* get 1 random number from the kernel random number generation routine */
16771 +       get_random_bytes((void *)(&random_number), 1);
16772 +
16773 +       /* Do we match ? */
16774 +       if (random_number <= info->average)
16775 +               return 1;
16776 +       else
16777 +               return 0;
16778 +}
16779 +
16780 +static int
16781 +ip6t_rand_checkentry(const char *tablename,
16782 +                  const struct ip6t_ip6 *e,
16783 +                  void *matchinfo,
16784 +                  unsigned int matchsize,
16785 +                  unsigned int hook_mask)
16786 +{
16787 +       /* Parameters from userspace */
16788 +       const struct ip6t_rand_info *info = matchinfo;
16789 +
16790 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
16791 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
16792 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
16793 +               return 0;
16794 +       }
16795 +
16796 +       /* must be  1 <= average % <= 99 */
16797 +       /* 1  x 2.55 = 2   */
16798 +       /* 99 x 2.55 = 252 */
16799 +       if ((info->average < 2) || (info->average > 252)) {
16800 +               printk("ip6t_random:  invalid average %u\n", info->average);
16801 +               return 0;
16802 +       }
16803 +
16804 +       return 1;
16805 +}
16806 +
16807 +static struct ip6t_match ip6t_rand_reg = { 
16808 +       {NULL, NULL},
16809 +       "random",
16810 +       ip6t_rand_match,
16811 +       ip6t_rand_checkentry,
16812 +       NULL,
16813 +       THIS_MODULE };
16814 +
16815 +static int __init init(void)
16816 +{
16817 +       if (ip6t_register_match(&ip6t_rand_reg))
16818 +               return -EINVAL;
16819 +
16820 +       printk("ip6t_random match loaded\n");
16821 +       return 0;
16822 +}
16823 +
16824 +static void __exit fini(void)
16825 +{
16826 +       ip6t_unregister_match(&ip6t_rand_reg);
16827 +       printk("ip6t_random match unloaded\n");
16828 +}
16829 +
16830 +module_init(init);
16831 +module_exit(fini);
16832 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c
16833 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_filter.c    2004-04-28 03:35:07.000000000 +0200
16834 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_filter.c        2004-04-30 09:11:53.000000000 +0200
16835 @@ -58,7 +58,7 @@
16836                 0,
16837                 sizeof(struct ip6t_entry),
16838                 sizeof(struct ip6t_standard),
16839 -               0, { 0, 0 }, { } },
16840 +               0, NULL, 0, { 0, 0 }, { } },
16841               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16842                 -NF_ACCEPT - 1 } },
16843             /* FORWARD */
16844 @@ -66,7 +66,7 @@
16845                 0,
16846                 sizeof(struct ip6t_entry),
16847                 sizeof(struct ip6t_standard),
16848 -               0, { 0, 0 }, { } },
16849 +               0, NULL, 0, { 0, 0 }, { } },
16850               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16851                 -NF_ACCEPT - 1 } },
16852             /* LOCAL_OUT */
16853 @@ -74,7 +74,7 @@
16854                 0,
16855                 sizeof(struct ip6t_entry),
16856                 sizeof(struct ip6t_standard),
16857 -               0, { 0, 0 }, { } },
16858 +               0, NULL, 0, { 0, 0 }, { } },
16859               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16860                 -NF_ACCEPT - 1 } }
16861      },
16862 @@ -83,7 +83,7 @@
16863         0,
16864         sizeof(struct ip6t_entry),
16865         sizeof(struct ip6t_error),
16866 -       0, { 0, 0 }, { } },
16867 +       0, NULL, 0, { 0, 0 }, { } },
16868        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
16869           { } },
16870         "ERROR"
16871 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c
16872 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_mangle.c    2004-04-28 03:35:43.000000000 +0200
16873 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_mangle.c        2004-04-30 09:11:53.000000000 +0200
16874 @@ -73,7 +73,7 @@
16875                 0,
16876                 sizeof(struct ip6t_entry),
16877                 sizeof(struct ip6t_standard),
16878 -               0, { 0, 0 }, { } },
16879 +               0, NULL, 0, { 0, 0 }, { } },
16880               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16881                 -NF_ACCEPT - 1 } },
16882             /* LOCAL_IN */
16883 @@ -81,7 +81,7 @@
16884                 0,
16885                 sizeof(struct ip6t_entry),
16886                 sizeof(struct ip6t_standard),
16887 -               0, { 0, 0 }, { } },
16888 +               0, NULL, 0, { 0, 0 }, { } },
16889               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16890                 -NF_ACCEPT - 1 } },
16891             /* FORWARD */
16892 @@ -89,7 +89,7 @@
16893                 0,
16894                 sizeof(struct ip6t_entry),
16895                 sizeof(struct ip6t_standard),
16896 -               0, { 0, 0 }, { } },
16897 +               0, NULL, 0, { 0, 0 }, { } },
16898               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16899                 -NF_ACCEPT - 1 } },
16900             /* LOCAL_OUT */
16901 @@ -97,7 +97,7 @@
16902                 0,
16903                 sizeof(struct ip6t_entry),
16904                 sizeof(struct ip6t_standard),
16905 -               0, { 0, 0 }, { } },
16906 +               0, NULL, 0, { 0, 0 }, { } },
16907               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16908                 -NF_ACCEPT - 1 } },
16909             /* POST_ROUTING */
16910 @@ -105,7 +105,7 @@
16911                 0,
16912                 sizeof(struct ip6t_entry),
16913                 sizeof(struct ip6t_standard),
16914 -               0, { 0, 0 }, { } },
16915 +               0, NULL, 0, { 0, 0 }, { } },
16916               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16917                 -NF_ACCEPT - 1 } }
16918      },
16919 @@ -114,7 +114,7 @@
16920         0,
16921         sizeof(struct ip6t_entry),
16922         sizeof(struct ip6t_error),
16923 -       0, { 0, 0 }, { } },
16924 +       0, NULL, 0, { 0, 0 }, { } },
16925        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
16926           { } },
16927         "ERROR"
16928 diff -Nur linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c
16929 --- linux-2.6.6-rc3.org/net/ipv6/netfilter/ip6table_raw.c       2004-04-28 03:36:19.000000000 +0200
16930 +++ linux-2.6.6-rc3/net/ipv6/netfilter/ip6table_raw.c   2004-04-30 09:11:53.000000000 +0200
16931 @@ -52,7 +52,7 @@
16932                 0,
16933                 sizeof(struct ip6t_entry),
16934                 sizeof(struct ip6t_standard),
16935 -               0, { 0, 0 }, { } },
16936 +               0, NULL, 0, { 0, 0 }, { } },
16937               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16938                 -NF_ACCEPT - 1 } },
16939             /* LOCAL_OUT */
16940 @@ -60,7 +60,7 @@
16941                 0,
16942                 sizeof(struct ip6t_entry),
16943                 sizeof(struct ip6t_standard),
16944 -               0, { 0, 0 }, { } },
16945 +               0, NULL, 0, { 0, 0 }, { } },
16946               { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
16947                 -NF_ACCEPT - 1 } },
16948      },
16949 @@ -69,7 +69,7 @@
16950         0,
16951         sizeof(struct ip6t_entry),
16952         sizeof(struct ip6t_error),
16953 -       0, { 0, 0 }, { } },
16954 +       0, NULL, 0, { 0, 0 }, { } },
16955        { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
16956           { } },
16957         "ERROR"
16958 diff -Nur linux-2.6.6-rc3.org/net/ipv6/sit.c linux-2.6.6-rc3/net/ipv6/sit.c
16959 --- linux-2.6.6-rc3.org/net/ipv6/sit.c  2004-04-28 03:36:36.000000000 +0200
16960 +++ linux-2.6.6-rc3/net/ipv6/sit.c      2004-04-30 09:09:38.000000000 +0200
16961 @@ -388,13 +388,7 @@
16962                 skb->dev = tunnel->dev;
16963                 dst_release(skb->dst);
16964                 skb->dst = NULL;
16965 -#ifdef CONFIG_NETFILTER
16966 -               nf_conntrack_put(skb->nfct);
16967 -               skb->nfct = NULL;
16968 -#ifdef CONFIG_NETFILTER_DEBUG
16969 -               skb->nf_debug = 0;
16970 -#endif
16971 -#endif
16972 +               nf_reset(skb);
16973                 ipip6_ecn_decapsulate(iph, skb);
16974                 netif_rx(skb);
16975                 read_unlock(&ipip6_lock);
16976 @@ -580,13 +574,7 @@
16977         if ((iph->ttl = tiph->ttl) == 0)
16978                 iph->ttl        =       iph6->hop_limit;
16979  
16980 -#ifdef CONFIG_NETFILTER
16981 -       nf_conntrack_put(skb->nfct);
16982 -       skb->nfct = NULL;
16983 -#ifdef CONFIG_NETFILTER_DEBUG
16984 -       skb->nf_debug = 0;
16985 -#endif
16986 -#endif
16987 +       nf_reset(skb);
16988  
16989         IPTUNNEL_XMIT();
16990         tunnel->recursion--;
16991 diff -Nur linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c linux-2.6.6-rc3/net/xfrm/xfrm_input.c
16992 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_input.c   2004-04-28 03:35:05.000000000 +0200
16993 +++ linux-2.6.6-rc3/net/xfrm/xfrm_input.c       2004-04-30 09:12:40.000000000 +0200
16994 @@ -29,6 +29,9 @@
16995         if (!sp)
16996                 return NULL;
16997  
16998 +#ifdef CONFIG_NETFILTER
16999 +       sp->decap_done = 0;
17000 +#endif
17001         sp->len = 0;
17002         if (src) {
17003                 int i;
17004 diff -Nur linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c linux-2.6.6-rc3/net/xfrm/xfrm_policy.c
17005 --- linux-2.6.6-rc3.org/net/xfrm/xfrm_policy.c  2004-04-28 03:35:48.000000000 +0200
17006 +++ linux-2.6.6-rc3/net/xfrm/xfrm_policy.c      2004-04-30 09:12:42.000000000 +0200
17007 @@ -21,6 +21,7 @@
17008  #include <linux/workqueue.h>
17009  #include <linux/notifier.h>
17010  #include <linux/netdevice.h>
17011 +#include <linux/netfilter.h>
17012  #include <net/xfrm.h>
17013  #include <net/ip.h>
17014  
17015 @@ -908,6 +909,7 @@
17016  
17017         if (_decode_session(skb, &fl, family) < 0)
17018                 return 0;
17019 +       nf_nat_decode_session(skb, &fl, family);
17020  
17021         /* First, check used SA against their selectors. */
17022         if (skb->sp) {
This page took 1.646715 seconds and 3 git commands to generate.